diff --git a/.travis.yml b/.travis.yml index f465ba4228174..36329ab91143c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -171,8 +171,6 @@ matrix: if: branch = auto - env: IMAGE=x86_64-gnu-distcheck if: branch = auto - - env: IMAGE=x86_64-gnu-incremental - if: branch = auto - stage: publish toolstate if: branch = master AND type = push diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index da57881202d17..9cc18464fea09 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -140,48 +140,58 @@ pub fn std_cargo(build: &Builder, compiler: &Compiler, target: Interned, cargo: &mut Command) { - let mut features = build.std_features(); - if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } - // When doing a local rebuild we tell cargo that we're stage1 rather than - // stage0. This works fine if the local rust and being-built rust have the - // same view of what the default allocator is, but fails otherwise. Since - // we don't have a way to express an allocator preference yet, work - // around the issue in the case of a local rebuild with jemalloc disabled. - if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { - features.push_str(" force_alloc_system"); - } + if build.no_std(target) == Some(true) { + // for no-std targets we only compile a few no_std crates + cargo.arg("--features").arg("c mem") + .args(&["-p", "alloc"]) + .args(&["-p", "compiler_builtins"]) + .args(&["-p", "std_unicode"]) + .arg("--manifest-path") + .arg(build.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); + } else { + let mut features = build.std_features(); + + // When doing a local rebuild we tell cargo that we're stage1 rather than + // stage0. This works fine if the local rust and being-built rust have the + // same view of what the default allocator is, but fails otherwise. Since + // we don't have a way to express an allocator preference yet, work + // around the issue in the case of a local rebuild with jemalloc disabled. + if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { + features.push_str(" force_alloc_system"); + } - if compiler.stage != 0 && build.config.sanitizers { - // This variable is used by the sanitizer runtime crates, e.g. - // rustc_lsan, to build the sanitizer runtime from C code - // When this variable is missing, those crates won't compile the C code, - // so we don't set this variable during stage0 where llvm-config is - // missing - // We also only build the runtimes when --enable-sanitizers (or its - // config.toml equivalent) is used - let llvm_config = build.ensure(native::Llvm { - target: build.config.build, - emscripten: false, - }); - cargo.env("LLVM_CONFIG", llvm_config); - } + if compiler.stage != 0 && build.config.sanitizers { + // This variable is used by the sanitizer runtime crates, e.g. + // rustc_lsan, to build the sanitizer runtime from C code + // When this variable is missing, those crates won't compile the C code, + // so we don't set this variable during stage0 where llvm-config is + // missing + // We also only build the runtimes when --enable-sanitizers (or its + // config.toml equivalent) is used + let llvm_config = build.ensure(native::Llvm { + target: build.config.build, + emscripten: false, + }); + cargo.env("LLVM_CONFIG", llvm_config); + } - cargo.arg("--features").arg(features) - .arg("--manifest-path") - .arg(build.src.join("src/libstd/Cargo.toml")); + cargo.arg("--features").arg(features) + .arg("--manifest-path") + .arg(build.src.join("src/libstd/Cargo.toml")); - if let Some(target) = build.config.target_config.get(&target) { - if let Some(ref jemalloc) = target.jemalloc { - cargo.env("JEMALLOC_OVERRIDE", jemalloc); + if let Some(target) = build.config.target_config.get(&target) { + if let Some(ref jemalloc) = target.jemalloc { + cargo.env("JEMALLOC_OVERRIDE", jemalloc); + } } - } - if target.contains("musl") { - if let Some(p) = build.musl_root(target) { - cargo.env("MUSL_ROOT", p); + if target.contains("musl") { + if let Some(p) = build.musl_root(target) { + cargo.env("MUSL_ROOT", p); + } } } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 76672df5c570d..863abd14935a8 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -161,6 +161,7 @@ pub struct Target { pub crt_static: Option, pub musl_root: Option, pub qemu_rootfs: Option, + pub no_std: bool, } /// Structure of the `config.toml` file that configuration is read from. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c9be17ff1ad2d..e1f5d34bf6723 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -642,7 +642,12 @@ impl Step for Std { if build.hosts.iter().any(|t| t == target) { builder.ensure(compile::Rustc { compiler, target }); } else { - builder.ensure(compile::Test { compiler, target }); + if build.no_std(target) == Some(true) { + // the `test` doesn't compile for no-std targets + builder.ensure(compile::Std { compiler, target }); + } else { + builder.ensure(compile::Test { compiler, target }); + } } let image = tmpdir(build).join(format!("{}-{}-image", name, target)); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index f07c3e707574b..4237ded2215c2 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -698,6 +698,7 @@ impl Step for Rustc { t!(symlink_dir_force(&builder.config, &out, &out_dir)); let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc"); + cargo.env("RUSTDOCFLAGS", "--document-private-items"); compile::rustc_cargo(build, &mut cargo); // Only include compiler crates, no dependencies of those, such as `libc`. diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2eeb2691eaee4..ea4368c0323fb 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -750,6 +750,12 @@ impl Build { .map(|p| &**p) } + /// Returns true if this is a no-std `target`, if defined + fn no_std(&self, target: Interned) -> Option { + self.config.target_config.get(&target) + .map(|t| t.no_std) + } + /// Returns whether the target will be tested using the `remote-test-client` /// and `remote-test-server` binaries. fn remote_tested(&self, target: Interned) -> bool { diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 5184cca653c4b..1b1cec5f18c07 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -169,6 +169,19 @@ pub fn check(build: &mut Build) { panic!("the iOS target is only supported on macOS"); } + if target.contains("-none-") { + if build.no_std(*target).is_none() { + let target = build.config.target_config.entry(target.clone()) + .or_insert(Default::default()); + + target.no_std = true; + } + + if build.no_std(*target) == Some(false) { + panic!("All the *-none-* targets are no-std targets") + } + } + // Make sure musl-root is valid if target.contains("musl") { // If this is a native target (host is also musl) and no musl-root is given, diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index 1b6ee44d87afc..00366301aa17a 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -20,7 +20,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ bzip2 \ patch \ libssl-dev \ - pkg-config + pkg-config \ + gcc-arm-none-eabi \ + libnewlib-arm-none-eabi WORKDIR /build @@ -86,6 +88,10 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu ENV TARGETS=$TARGETS,x86_64-unknown-redox +ENV TARGETS=$TARGETS,thumbv6m-none-eabi +ENV TARGETS=$TARGETS,thumbv7m-none-eabi +ENV TARGETS=$TARGETS,thumbv7em-none-eabi +ENV TARGETS=$TARGETS,thumbv7em-none-eabihf # FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271 # get fixed and cc update diff --git a/src/ci/docker/x86_64-gnu-incremental/Dockerfile b/src/ci/docker/x86_64-gnu-incremental/Dockerfile deleted file mode 100644 index 7304ed6015cc9..0000000000000 --- a/src/ci/docker/x86_64-gnu-incremental/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - file \ - curl \ - ca-certificates \ - python2.7 \ - git \ - cmake \ - sudo \ - gdb \ - xz-utils - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu -ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache -ENV RUST_CHECK_TARGET check -ENV CARGO_INCREMENTAL 0 diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 02008310b8161..4b883b5bce79b 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1594,40 +1594,69 @@ impl SpecFromElem for u8 { } } -macro_rules! impl_spec_from_elem { +impl SpecFromElem for T { + #[inline] + fn from_elem(elem: T, n: usize) -> Vec { + if elem.is_zero() { + return Vec { + buf: RawVec::with_capacity_zeroed(n), + len: n, + } + } + let mut v = Vec::with_capacity(n); + v.extend_with(n, ExtendElement(elem)); + v + } +} + +unsafe trait IsZero { + /// Whether this value is zero + fn is_zero(&self) -> bool; +} + +macro_rules! impl_is_zero { ($t: ty, $is_zero: expr) => { - impl SpecFromElem for $t { + unsafe impl IsZero for $t { #[inline] - fn from_elem(elem: $t, n: usize) -> Vec<$t> { - if $is_zero(elem) { - return Vec { - buf: RawVec::with_capacity_zeroed(n), - len: n, - } - } - let mut v = Vec::with_capacity(n); - v.extend_with(n, ExtendElement(elem)); - v + fn is_zero(&self) -> bool { + $is_zero(*self) } } - }; + } } -impl_spec_from_elem!(i8, |x| x == 0); -impl_spec_from_elem!(i16, |x| x == 0); -impl_spec_from_elem!(i32, |x| x == 0); -impl_spec_from_elem!(i64, |x| x == 0); -impl_spec_from_elem!(i128, |x| x == 0); -impl_spec_from_elem!(isize, |x| x == 0); +impl_is_zero!(i8, |x| x == 0); +impl_is_zero!(i16, |x| x == 0); +impl_is_zero!(i32, |x| x == 0); +impl_is_zero!(i64, |x| x == 0); +impl_is_zero!(i128, |x| x == 0); +impl_is_zero!(isize, |x| x == 0); + +impl_is_zero!(u16, |x| x == 0); +impl_is_zero!(u32, |x| x == 0); +impl_is_zero!(u64, |x| x == 0); +impl_is_zero!(u128, |x| x == 0); +impl_is_zero!(usize, |x| x == 0); + +impl_is_zero!(char, |x| x == '\0'); + +impl_is_zero!(f32, |x: f32| x.to_bits() == 0); +impl_is_zero!(f64, |x: f64| x.to_bits() == 0); -impl_spec_from_elem!(u16, |x| x == 0); -impl_spec_from_elem!(u32, |x| x == 0); -impl_spec_from_elem!(u64, |x| x == 0); -impl_spec_from_elem!(u128, |x| x == 0); -impl_spec_from_elem!(usize, |x| x == 0); +unsafe impl IsZero for *const T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +unsafe impl IsZero for *mut T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} -impl_spec_from_elem!(f32, |x: f32| x.to_bits() == 0); -impl_spec_from_elem!(f64, |x: f64| x.to_bits() == 0); //////////////////////////////////////////////////////////////////////////////// // Common trait implementations for Vec diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index d934706be67d9..d336934ec7214 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -952,6 +952,7 @@ macro_rules! atomic_int { $stable_nand:meta, $s_int_type:expr, $int_ref:expr, $extra_feature:expr, + $min_fn:ident, $max_fn:ident, $int_type:ident $atomic_type:ident $atomic_init:ident) => { /// An integer type which can be safely shared between threads. /// @@ -1421,6 +1422,128 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110); unsafe { atomic_xor(self.v.get(), val, order) } } } + + doc_comment! { + concat!("Fetches the value, and applies a function to it that returns an optional +new value. Returns a `Result` (`Ok(_)` if the function returned `Some(_)`, else `Err(_)`) of the +previous value. + +Note: This may call the function multiple times if the value has been changed from other threads in +the meantime, as long as the function returns `Some(_)`, but the function will have been applied +but once to the stored value. + +# Examples + +```rust +#![feature(no_more_cas)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let x = ", stringify!($atomic_type), "::new(7); +assert_eq!(x.fetch_update(|_| None, Ordering::SeqCst, Ordering::SeqCst), Err(7)); +assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(7)); +assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(8)); +assert_eq!(x.load(Ordering::SeqCst), 9); +```"), + #[inline] + #[unstable(feature = "no_more_cas", + reason = "no more CAS loops in user code", + issue = "48655")] + pub fn fetch_update(&self, + mut f: F, + fetch_order: Ordering, + set_order: Ordering) -> Result<$int_type, $int_type> + where F: FnMut($int_type) -> Option<$int_type> { + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev + } + } + Err(prev) + } + } + + doc_comment! { + concat!("Maximum with the current value. + +Finds the maximum of the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +#![feature(atomic_min_max)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(23); +assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23); +assert_eq!(foo.load(Ordering::SeqCst), 42); +``` + +If you want to obtain the maximum value in one step, you can use the following: + +``` +#![feature(atomic_min_max)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(23); +let bar = 42; +let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar); +assert!(max_foo == 42); +```"), + #[inline] + #[unstable(feature = "atomic_min_max", + reason = "easier and faster min/max than writing manual CAS loop", + issue = "48655")] + pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { $max_fn(self.v.get(), val, order) } + } + } + + doc_comment! { + concat!("Minimum with the current value. + +Finds the minimum of the current value and the argument `val`, and +sets the new value to the result. + +Returns the previous value. + +# Examples + +``` +#![feature(atomic_min_max)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(23); +assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23); +assert_eq!(foo.load(Ordering::Relaxed), 23); +assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23); +assert_eq!(foo.load(Ordering::Relaxed), 22); +``` + +If you want to obtain the minimum value in one step, you can use the following: + +``` +#![feature(atomic_min_max)] +", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering}; + +let foo = ", stringify!($atomic_type), "::new(23); +let bar = 12; +let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar); +assert_eq!(min_foo, 12); +```"), + #[inline] + #[unstable(feature = "atomic_min_max", + reason = "easier and faster min/max than writing manual CAS loop", + issue = "48655")] + pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { + unsafe { $min_fn(self.v.get(), val, order) } + } + } + } } } @@ -1435,6 +1558,7 @@ atomic_int! { unstable(feature = "atomic_nand", issue = "13226"), "i8", "../../../std/primitive.i8.html", "#![feature(integer_atomics)]\n\n", + atomic_min, atomic_max, i8 AtomicI8 ATOMIC_I8_INIT } #[cfg(target_has_atomic = "8")] @@ -1447,6 +1571,7 @@ atomic_int! { unstable(feature = "atomic_nand", issue = "13226"), "u8", "../../../std/primitive.u8.html", "#![feature(integer_atomics)]\n\n", + atomic_umin, atomic_umax, u8 AtomicU8 ATOMIC_U8_INIT } #[cfg(target_has_atomic = "16")] @@ -1459,6 +1584,7 @@ atomic_int! { unstable(feature = "atomic_nand", issue = "13226"), "i16", "../../../std/primitive.i16.html", "#![feature(integer_atomics)]\n\n", + atomic_min, atomic_max, i16 AtomicI16 ATOMIC_I16_INIT } #[cfg(target_has_atomic = "16")] @@ -1471,6 +1597,7 @@ atomic_int! { unstable(feature = "atomic_nand", issue = "13226"), "u16", "../../../std/primitive.u16.html", "#![feature(integer_atomics)]\n\n", + atomic_umin, atomic_umax, u16 AtomicU16 ATOMIC_U16_INIT } #[cfg(target_has_atomic = "32")] @@ -1483,6 +1610,7 @@ atomic_int! { unstable(feature = "atomic_nand", issue = "13226"), "i32", "../../../std/primitive.i32.html", "#![feature(integer_atomics)]\n\n", + atomic_min, atomic_max, i32 AtomicI32 ATOMIC_I32_INIT } #[cfg(target_has_atomic = "32")] @@ -1495,6 +1623,7 @@ atomic_int! { unstable(feature = "atomic_nand", issue = "13226"), "u32", "../../../std/primitive.u32.html", "#![feature(integer_atomics)]\n\n", + atomic_umin, atomic_umax, u32 AtomicU32 ATOMIC_U32_INIT } #[cfg(target_has_atomic = "64")] @@ -1507,6 +1636,7 @@ atomic_int! { unstable(feature = "atomic_nand", issue = "13226"), "i64", "../../../std/primitive.i64.html", "#![feature(integer_atomics)]\n\n", + atomic_min, atomic_max, i64 AtomicI64 ATOMIC_I64_INIT } #[cfg(target_has_atomic = "64")] @@ -1519,6 +1649,7 @@ atomic_int! { unstable(feature = "atomic_nand", issue = "13226"), "u64", "../../../std/primitive.u64.html", "#![feature(integer_atomics)]\n\n", + atomic_umin, atomic_umax, u64 AtomicU64 ATOMIC_U64_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1531,6 +1662,7 @@ atomic_int!{ unstable(feature = "atomic_nand", issue = "13226"), "isize", "../../../std/primitive.isize.html", "", + atomic_min, atomic_max, isize AtomicIsize ATOMIC_ISIZE_INIT } #[cfg(target_has_atomic = "ptr")] @@ -1543,6 +1675,7 @@ atomic_int!{ unstable(feature = "atomic_nand", issue = "13226"), "usize", "../../../std/primitive.usize.html", "", + atomic_umin, atomic_umax, usize AtomicUsize ATOMIC_USIZE_INIT } @@ -1720,6 +1853,58 @@ unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { } } +/// returns the max value (signed comparison) +#[inline] +unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_max_acq(dst, val), + Release => intrinsics::atomic_max_rel(dst, val), + AcqRel => intrinsics::atomic_max_acqrel(dst, val), + Relaxed => intrinsics::atomic_max_relaxed(dst, val), + SeqCst => intrinsics::atomic_max(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + +/// returns the min value (signed comparison) +#[inline] +unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_min_acq(dst, val), + Release => intrinsics::atomic_min_rel(dst, val), + AcqRel => intrinsics::atomic_min_acqrel(dst, val), + Relaxed => intrinsics::atomic_min_relaxed(dst, val), + SeqCst => intrinsics::atomic_min(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + +/// returns the max value (signed comparison) +#[inline] +unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_umax_acq(dst, val), + Release => intrinsics::atomic_umax_rel(dst, val), + AcqRel => intrinsics::atomic_umax_acqrel(dst, val), + Relaxed => intrinsics::atomic_umax_relaxed(dst, val), + SeqCst => intrinsics::atomic_umax(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + +/// returns the min value (signed comparison) +#[inline] +unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { + match order { + Acquire => intrinsics::atomic_umin_acq(dst, val), + Release => intrinsics::atomic_umin_rel(dst, val), + AcqRel => intrinsics::atomic_umin_acqrel(dst, val), + Relaxed => intrinsics::atomic_umin_relaxed(dst, val), + SeqCst => intrinsics::atomic_umin(dst, val), + __Nonexhaustive => panic!("invalid memory ordering"), + } +} + /// An atomic fence. /// /// Depending on the specified order, a fence prevents the compiler and CPU from diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 42cda6a05a1a7..d1f3736556c5d 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -589,6 +589,7 @@ define_dep_nodes!( <'tcx> [input] CrateDisambiguator(CrateNum), [input] CrateHash(CrateNum), [input] OriginalCrateName(CrateNum), + [input] ExtraFileName(CrateNum), [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId }, [] AllTraitImplementations(CrateNum), diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index c74ae2343b866..2662e70999196 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -2058,6 +2058,33 @@ where 'x: 'y ``` "##, +E0910: r##" +This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed +on something other than a struct or enum. + +Examples of erroneous code: + +```compile_fail,E0910 +# #![feature(non_exhaustive)] + +#[non_exhaustive] +trait Foo { } +``` +"##, + +E0911: r##" +This error indicates that a `#[non_exhaustive]` attribute had a value. The +`#[non_exhaustive]` should be empty. + +Examples of erroneous code: + +```compile_fail,E0911 +# #![feature(non_exhaustive)] + +#[non_exhaustive(anything)] +struct Foo; +``` +"##, } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 316ed07ca05d9..956cd17f38f21 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -66,6 +66,8 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { for attr in &item.attrs { if attr.check_name("inline") { self.check_inline(attr, &item.span, target) + } else if attr.check_name("non_exhaustive") { + self.check_non_exhaustive(attr, item, target) } else if attr.check_name("wasm_import_module") { has_wasm_import_module = true; if attr.value_str().is_none() { @@ -113,6 +115,31 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { } } + /// Check if the `#[non_exhaustive]` attribute on an `item` is valid. + fn check_non_exhaustive(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) { + match target { + Target::Struct | Target::Enum => { /* Valid */ }, + _ => { + struct_span_err!(self.tcx.sess, + attr.span, + E0910, + "attribute can only be applied to a struct or enum") + .span_label(item.span, "not a struct or enum") + .emit(); + return; + } + } + + if attr.meta_item_list().is_some() || attr.value_str().is_some() { + struct_span_err!(self.tcx.sess, + attr.span, + E0911, + "attribute should be empty") + .span_label(item.span, "not empty") + .emit(); + } + } + /// Check if the `#[repr]` attributes on `item` are valid. fn check_repr(&self, item: &hir::Item, target: Target) { // Extract the names of all repr hints, e.g., [foo, bar, align] for: diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index c7396b34c4689..7e1b7c08c3dad 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -353,8 +353,8 @@ pub struct ScopeTree { /// the result of `g()` occurs after the yield (and therefore /// doesn't). If we want to infer that, we can look at the /// postorder traversal: - /// ``` - /// `foo` `f` Call#1 `y` Yield `bar` `g` Call#3 Call#2 Call#0 + /// ```plain,ignore + /// `foo` `f` Call#1 `y` Yield `bar` `g` Call#3 Call#2 Call#0 /// ``` /// /// In which we can easily see that `Call#1` occurs before the yield, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index bbd428611874a..b1649686323f8 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -362,7 +362,9 @@ enum EvaluationResult { /// When checking `foo`, we have to prove `T: Trait`. This basically /// translates into this: /// + /// ```plain,ignore /// (T: Trait + Sized →_\impl T: Trait), T: Trait ⊢ T: Trait + /// ``` /// /// When we try to prove it, we first go the first option, which /// recurses. This shows us that the impl is "useless" - it won't diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index bb9467305e335..a08cd57b1f7e2 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -466,6 +466,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::original_crate_name<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::extra_filename<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up the extra filename for a crate") + } +} + impl<'tcx> QueryDescription<'tcx> for queries::implementations_of_trait<'tcx> { fn describe(_tcx: TyCtxt, _: (CrateNum, DefId)) -> String { format!("looking up implementations of a trait in a crate") diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 2bfb687032923..8651619705b42 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -328,6 +328,7 @@ define_maps! { <'tcx> [] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator, [] fn crate_hash: CrateHash(CrateNum) -> Svh, [] fn original_crate_name: OriginalCrateName(CrateNum) -> Symbol, + [] fn extra_filename: ExtraFileName(CrateNum) -> String, [] fn implementations_of_trait: implementations_of_trait_node((CrateNum, DefId)) -> Lrc>, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 50a19526ba8c4..fa69eb8e5bc66 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -881,6 +881,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); } DepKind::CrateHash => { force!(crate_hash, krate!()); } DepKind::OriginalCrateName => { force!(original_crate_name, krate!()); } + DepKind::ExtraFileName => { force!(extra_filename, krate!()); } DepKind::AllTraitImplementations => { force!(all_trait_implementations, krate!()); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 13ebb5f61660f..86f495c5fac3a 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -262,6 +262,7 @@ impl<'a> CrateLoader<'a> { ident: Symbol, name: Symbol, hash: Option<&Svh>, + extra_filename: Option<&str>, span: Span, path_kind: PathKind, mut dep_kind: DepKind) @@ -277,6 +278,7 @@ impl<'a> CrateLoader<'a> { ident, crate_name: name, hash: hash.map(|a| &*a), + extra_filename: extra_filename, filesearch: self.sess.target_filesearch(path_kind), target: &self.sess.target.target, triple: &self.sess.opts.target_triple, @@ -409,7 +411,8 @@ impl<'a> CrateLoader<'a> { ::std::iter::once(krate).chain(crate_root.crate_deps .decode(metadata) .map(|dep| { - debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); + info!("resolving dep crate {} hash: `{}` extra filename: `{}`", dep.name, dep.hash, + dep.extra_filename); if dep.kind == DepKind::UnexportedMacrosOnly { return krate; } @@ -418,7 +421,8 @@ impl<'a> CrateLoader<'a> { _ => dep.kind, }; let (local_cnum, ..) = self.resolve_crate( - root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind, + root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span, + PathKind::Dependency, dep_kind, ); local_cnum })).collect() @@ -437,6 +441,7 @@ impl<'a> CrateLoader<'a> { ident: orig_name, crate_name: rename, hash: None, + extra_filename: None, filesearch: self.sess.host_filesearch(PathKind::Crate), target: &self.sess.host, triple: &host_triple, @@ -664,7 +669,7 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Implicit; let (cnum, data) = - self.resolve_crate(&None, name, name, None, DUMMY_SP, PathKind::Crate, dep_kind); + self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. @@ -771,7 +776,7 @@ impl<'a> CrateLoader<'a> { let symbol = Symbol::intern(name); let dep_kind = DepKind::Explicit; let (_, data) = - self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime @@ -794,7 +799,7 @@ impl<'a> CrateLoader<'a> { let symbol = Symbol::intern("profiler_builtins"); let dep_kind = DepKind::Implicit; let (_, data) = - self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a profiler runtime @@ -909,6 +914,7 @@ impl<'a> CrateLoader<'a> { name, name, None, + None, DUMMY_SP, PathKind::Crate, DepKind::Implicit); @@ -1059,7 +1065,8 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { }; let (cnum, ..) = self.resolve_crate( - &None, item.ident.name, orig_name, None, item.span, PathKind::Crate, dep_kind, + &None, item.ident.name, orig_name, None, None, + item.span, PathKind::Crate, dep_kind, ); let def_id = definitions.opt_local_def_id(item.id).unwrap(); @@ -1074,6 +1081,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum { - self.resolve_crate(&None, name, name, None, span, PathKind::Crate, DepKind::Explicit).0 + self.resolve_crate(&None, name, name, None, None, span, PathKind::Crate, + DepKind::Explicit).0 } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 5fd8ebaa9b4a6..f63edf07fa8ba 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -213,6 +213,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, crate_hash => { cdata.hash() } original_crate_name => { cdata.name() } + extra_filename => { cdata.root.extra_filename.clone() } + + implementations_of_trait => { let mut result = vec![]; let filter = Some(other); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 39de1ec852ec4..0da6fc5b9eda1 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -462,6 +462,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let has_global_allocator = tcx.sess.has_global_allocator.get(); let root = self.lazy(&CrateRoot { name: tcx.crate_name(LOCAL_CRATE), + extra_filename: tcx.sess.opts.cg.extra_filename.clone(), triple: tcx.sess.opts.target_triple.clone(), hash: link_meta.crate_hash, disambiguator: tcx.sess.local_crate_disambiguator(), @@ -1357,6 +1358,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { name: self.tcx.original_crate_name(cnum), hash: self.tcx.crate_hash(cnum), kind: self.tcx.dep_kind(cnum), + extra_filename: self.tcx.extra_filename(cnum), }; (cnum, dep) }) diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 41e10b4755d01..f553c55ae56fa 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -83,7 +83,10 @@ //! 1. Does the filename match an rlib/dylib pattern? That is to say, does the //! filename have the right prefix/suffix? //! 2. Does the filename have the right prefix for the crate name being queried? -//! This is filtering for files like `libfoo*.rlib` and such. +//! This is filtering for files like `libfoo*.rlib` and such. If the crate +//! we're looking for was originally compiled with -C extra-filename, the +//! extra filename will be included in this prefix to reduce reading +//! metadata from crates that would otherwise share our prefix. //! 3. Is the file an actual rust library? This is done by loading the metadata //! from the library and making sure it's actually there. //! 4. Does the name in the metadata agree with the name of the library? @@ -236,6 +239,7 @@ use syntax_pos::Span; use rustc_back::target::{Target, TargetTriple}; use std::cmp; +use std::collections::HashSet; use std::fmt; use std::fs; use std::io::{self, Read}; @@ -256,6 +260,7 @@ pub struct Context<'a> { pub ident: Symbol, pub crate_name: Symbol, pub hash: Option<&'a Svh>, + pub extra_filename: Option<&'a str>, // points to either self.sess.target.target or self.sess.host, must match triple pub target: &'a Target, pub triple: &'a TargetTriple, @@ -303,7 +308,12 @@ impl CratePaths { impl<'a> Context<'a> { pub fn maybe_load_library_crate(&mut self) -> Option { - self.find_library_crate() + let mut seen_paths = HashSet::new(); + match self.extra_filename { + Some(s) => self.find_library_crate(s, &mut seen_paths) + .or_else(|| self.find_library_crate("", &mut seen_paths)), + None => self.find_library_crate("", &mut seen_paths) + } } pub fn report_errs(&mut self) -> ! { @@ -419,7 +429,10 @@ impl<'a> Context<'a> { unreachable!(); } - fn find_library_crate(&mut self) -> Option { + fn find_library_crate(&mut self, + extra_prefix: &str, + seen_paths: &mut HashSet) + -> Option { // If an SVH is specified, then this is a transitive dependency that // must be loaded via -L plus some filtering. if self.hash.is_none() { @@ -434,9 +447,9 @@ impl<'a> Context<'a> { let staticpair = self.staticlibname(); // want: crate_name.dir_part() + prefix + crate_name.file_part + "-" - let dylib_prefix = format!("{}{}", dypair.0, self.crate_name); - let rlib_prefix = format!("lib{}", self.crate_name); - let staticlib_prefix = format!("{}{}", staticpair.0, self.crate_name); + let dylib_prefix = format!("{}{}{}", dypair.0, self.crate_name, extra_prefix); + let rlib_prefix = format!("lib{}{}", self.crate_name, extra_prefix); + let staticlib_prefix = format!("{}{}{}", staticpair.0, self.crate_name, extra_prefix); let mut candidates = FxHashMap(); let mut staticlibs = vec![]; @@ -476,6 +489,7 @@ impl<'a> Context<'a> { } return FileDoesntMatch; }; + info!("lib candidate: {}", path.display()); let hash_str = hash.to_string(); @@ -484,6 +498,10 @@ impl<'a> Context<'a> { let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot; fs::canonicalize(path) .map(|p| { + if seen_paths.contains(&p) { + return FileDoesntMatch + }; + seen_paths.insert(p.clone()); match found_kind { CrateFlavor::Rlib => { rlibs.insert(p, kind); } CrateFlavor::Rmeta => { rmetas.insert(p, kind); } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d04a4001c5023..a7ee0e7e9a961 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -188,6 +188,7 @@ pub enum LazyState { pub struct CrateRoot { pub name: Symbol, pub triple: TargetTriple, + pub extra_filename: String, pub hash: hir::svh::Svh, pub disambiguator: CrateDisambiguator, pub panic_strategy: PanicStrategy, @@ -216,12 +217,14 @@ pub struct CrateDep { pub name: ast::Name, pub hash: hir::svh::Svh, pub kind: DepKind, + pub extra_filename: String, } impl_stable_hash_for!(struct CrateDep { name, hash, - kind + kind, + extra_filename }); #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 97dcf081f8c8d..3a97d2767444b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -427,14 +427,14 @@ fn generate_fn_name_span(cm: &CodeMap, span: Span) -> Option { /// a new local type parameter. /// /// For instance: -/// ``` +/// ```rust,ignore (pseudo-Rust) /// // Given span /// fn my_function(param: T) -/// ^ Original span +/// // ^ Original span /// /// // Result /// fn my_function(param: T) -/// ^^^^^^^^^^^ Generated span with snippet `my_function` +/// // ^^^^^^^^^^^ Generated span with snippet `my_function` /// ``` /// /// Attention: The method used is very fragile since it essentially duplicates the work of the diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 6ba3ad879b7d5..4ffc71ba4703e 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -694,7 +694,7 @@ fn link_natively(sess: &Session, loop { i += 1; prog = time(sess, "running linker", || { - exec_linker(sess, &mut cmd, tmpdir) + exec_linker(sess, &mut cmd, out_filename, tmpdir) }); let output = match prog { Ok(ref output) => output, @@ -822,7 +822,7 @@ fn link_natively(sess: &Session, } } -fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path) +fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: &Path) -> io::Result { // When attempting to spawn the linker we run a risk of blowing out the @@ -836,7 +836,11 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path) // there instead of looking at the command line. if !cmd.very_likely_to_exceed_some_spawn_limit() { match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() { - Ok(child) => return child.wait_with_output(), + Ok(child) => { + let output = child.wait_with_output(); + flush_linked_file(&output, out_filename)?; + return output; + } Err(ref e) if command_line_too_big(e) => { info!("command line to linker was too big: {}", e); } @@ -870,7 +874,37 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path) fs::write(&file, &bytes)?; cmd2.arg(format!("@{}", file.display())); info!("invoking linker {:?}", cmd2); - return cmd2.output(); + let output = cmd2.output(); + flush_linked_file(&output, out_filename)?; + return output; + + #[cfg(unix)] + fn flush_linked_file(_: &io::Result, _: &Path) -> io::Result<()> { + Ok(()) + } + + #[cfg(windows)] + fn flush_linked_file(command_output: &io::Result, out_filename: &Path) + -> io::Result<()> + { + // On Windows, under high I/O load, output buffers are sometimes not flushed, + // even long after process exit, causing nasty, non-reproducible output bugs. + // + // File::sync_all() calls FlushFileBuffers() down the line, which solves the problem. + // + // А full writeup of the original Chrome bug can be found at + // randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/amp + + if let &Ok(ref out) = command_output { + if out.status.success() { + if let Ok(of) = fs::OpenOptions::new().write(true).open(out_filename) { + of.sync_all()?; + } + } + } + + Ok(()) + } #[cfg(unix)] fn command_line_too_big(err: &io::Error) -> bool { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 9ed4ab45a1ba7..b5e862fac958a 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1164,10 +1164,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// constraint that `'z <= 'a`. Given this setup, let's clarify the /// parameters in (roughly) terms of the example: /// + /// ```plain,ignore (pseudo-Rust) /// A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T` /// borrow_region ^~ ref_region ^~ /// borrow_kind ^~ ref_kind ^~ /// ref_cmt ^ + /// ``` /// /// Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc). /// diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 1eed1bf4b71fb..faf3ccb1133ad 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -42,21 +42,21 @@ use syntax_pos::Span; /// /// Example: /// -/// ``` +/// ```rust,ignore (pseudo-Rust) /// impl Trait for Bar { ... } -/// ^ T does not appear in `Foo` or `Bar`, error! +/// // ^ T does not appear in `Foo` or `Bar`, error! /// /// impl Trait> for Bar { ... } -/// ^ T appears in `Foo`, ok. +/// // ^ T appears in `Foo`, ok. /// /// impl Trait for Bar where Bar: Iterator { ... } -/// ^ T is bound to `::Item`, ok. +/// // ^ T is bound to `::Item`, ok. /// /// impl<'a> Trait for Bar { } -/// ^ 'a is unused, but for back-compat we allow it +/// // ^ 'a is unused, but for back-compat we allow it /// /// impl<'a> Trait for Bar { type X = &'a i32; } -/// ^ 'a is unused and appears in assoc type, error +/// // ^ 'a is unused and appears in assoc type, error /// ``` pub fn impl_wf_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // We will tag this as part of the WF check -- logically, it is, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1cf62a8bf33f2..0f039895dee77 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -193,7 +193,7 @@ declare_features! ( (active, rustc_attrs, "1.0.0", Some(29642), None), // Allows the use of non lexical lifetimes; RFC 2094 - (active, nll, "1.0.0", Some(43234), None), + (active, nll, "1.0.0", Some(43234), Some(Edition::Edition2018)), // Allows the use of #[allow_internal_unstable]. This is an // attribute on macro_rules! and can't use the attribute handling @@ -388,7 +388,7 @@ declare_features! ( (active, dyn_trait, "1.22.0", Some(44662), Some(Edition::Edition2018)), // `crate` as visibility modifier, synonymous to `pub(crate)` - (active, crate_visibility_modifier, "1.23.0", Some(45388), None), + (active, crate_visibility_modifier, "1.23.0", Some(45388), Some(Edition::Edition2018)), // extern types (active, extern_types, "1.23.0", Some(43467), None), @@ -397,10 +397,10 @@ declare_features! ( (active, arbitrary_self_types, "1.23.0", Some(44874), None), // `crate` in paths - (active, crate_in_paths, "1.23.0", Some(45477), None), + (active, crate_in_paths, "1.23.0", Some(45477), Some(Edition::Edition2018)), // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`) - (active, in_band_lifetimes, "1.23.0", Some(44524), None), + (active, in_band_lifetimes, "1.23.0", Some(44524), Some(Edition::Edition2018)), // generic associated types (RFC 1598) (active, generic_associated_types, "1.23.0", Some(44265), None), @@ -409,10 +409,10 @@ declare_features! ( (active, extern_absolute_paths, "1.24.0", Some(44660), None), // `foo.rs` as an alternative to `foo/mod.rs` - (active, non_modrs_mods, "1.24.0", Some(44660), None), + (active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)), // Termination trait in tests (RFC 1937) - (active, termination_trait_test, "1.24.0", Some(48854), None), + (active, termination_trait_test, "1.24.0", Some(48854), Some(Edition::Edition2018)), // Allows use of the :lifetime macro fragment specifier (active, macro_lifetime_matcher, "1.24.0", Some(46895), None), diff --git a/src/rustc/compiler_builtins_shim/Cargo.toml b/src/rustc/compiler_builtins_shim/Cargo.toml index 608e5f5f36d02..7d8423ca84eb4 100644 --- a/src/rustc/compiler_builtins_shim/Cargo.toml +++ b/src/rustc/compiler_builtins_shim/Cargo.toml @@ -35,5 +35,6 @@ cc = "1.0.1" [features] c = [] default = ["c", "rustbuild", "compiler-builtins"] +mem = [] rustbuild = [] compiler-builtins = [] diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs new file mode 100644 index 0000000000000..e48d989c01d61 --- /dev/null +++ b/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs @@ -0,0 +1,28 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(non_exhaustive)] + +#[non_exhaustive(anything)] +//~^ ERROR attribute should be empty [E0911] +struct Foo; + +#[non_exhaustive] +//~^ ERROR attribute can only be applied to a struct or enum [E0910] +trait Bar { } + +#[non_exhaustive] +//~^ ERROR attribute can only be applied to a struct or enum [E0910] +union Baz { + f1: u16, + f2: u16 +} + +fn main() { } diff --git a/src/test/run-make-fulldeps/resolve-rename/Makefile b/src/test/run-make-fulldeps/resolve-rename/Makefile new file mode 100644 index 0000000000000..4b0c36d01b7a8 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) -C extra-filename=-hash foo.rs + $(RUSTC) bar.rs + mv $(TMPDIR)/libfoo-hash.rlib $(TMPDIR)/libfoo-another-hash.rlib + $(RUSTC) baz.rs diff --git a/src/test/run-make-fulldeps/resolve-rename/bar.rs b/src/test/run-make-fulldeps/resolve-rename/bar.rs new file mode 100644 index 0000000000000..1552b45f2fc16 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/bar.rs @@ -0,0 +1,15 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +extern crate foo; + +pub fn bar() { foo::foo() } diff --git a/src/test/run-make-fulldeps/resolve-rename/baz.rs b/src/test/run-make-fulldeps/resolve-rename/baz.rs new file mode 100644 index 0000000000000..27d801490e425 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/baz.rs @@ -0,0 +1,15 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +extern crate bar; + +pub fn baz() { bar::bar() } diff --git a/src/test/run-make-fulldeps/resolve-rename/foo.rs b/src/test/run-make-fulldeps/resolve-rename/foo.rs new file mode 100644 index 0000000000000..830c289b65f11 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/foo.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +pub fn foo() {}