From: kennytm Date: Wed, 9 May 2018 09:23:31 +0000 (+0800) Subject: Rollup merge of #50525 - nnethercote:lit_token, r=michaelwoerister X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=0fa08507efe4187a8056691ceb550e9da1171863;hp=65ea0ff29d32ca4fea30477f7fb1a1d43342dc26;p=rust.git Rollup merge of #50525 - nnethercote:lit_token, r=michaelwoerister Optimize string handling in lit_token(). In the common case, the string value in a string literal Token is the same as the string value in a string literal LitKind. (The exception is when escapes or \r are involved.) This patch takes advantage of that to avoid calling str_lit() and re-interning the string in that case. This speeds up incremental builds for a few of the rustc-benchmarks, the best by 3%. Benchmarks that got a speedup of 1% or more: ``` coercions avg: -1.1% min: -3.5% max: 0.4% regex-check avg: -1.2% min: -1.5% max: -0.6% futures-check avg: -0.9% min: -1.4% max: -0.3% futures avg: -0.8% min: -1.3% max: -0.3% futures-opt avg: -0.7% min: -1.2% max: -0.1% regex avg: -0.5% min: -1.2% max: -0.1% regex-opt avg: -0.5% min: -1.1% max: -0.1% hyper-check avg: -0.7% min: -1.0% max: -0.3% ``` --- diff --git a/.mailmap b/.mailmap index 3ff9e94ee54..8f4287a4385 100644 --- a/.mailmap +++ b/.mailmap @@ -51,6 +51,7 @@ Carol Willing Chris C Cerami Chris C Cerami Chris Pressey Chris Thorn Chris Thorn +Chris Vittal Christopher Vittal Clark Gaebel Clinton Ryan Corey Richardson Elaine "See More" Nemo diff --git a/src/Cargo.lock b/src/Cargo.lock index a2767bd290d..21c35458398 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -305,11 +305,11 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.195" +version = "0.0.197" dependencies = [ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", - "clippy_lints 0.0.195", + "clippy_lints 0.0.197", "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -325,8 +325,9 @@ version = "0.2.0" [[package]] name = "clippy_lints" -version = "0.0.195" +version = "0.0.197" dependencies = [ + "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1630,7 +1631,7 @@ version = "0.127.0" dependencies = [ "cargo 0.28.0", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy_lints 0.0.195", + "clippy_lints 0.0.197", "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1641,7 +1642,7 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1656,7 +1657,7 @@ dependencies = [ [[package]] name = "rls-analysis" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3144,7 +3145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum rls-analysis 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b339561571efd8d2d4ae1b16eb27f760cad46907d49e9726242844dbbde14e79" +"checksum rls-analysis 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a41488cf5dc99d6ce383319d2978756567b70d4ed0539eb0d9ce07763e732e46" "checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2" "checksum rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bea04462e94b5512a78499837eecb7db182ff082144cd1b4bc32ef5d43de6510" "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea" diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 9ff681ac680..98c353eb6ec 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -64,6 +64,10 @@ The script accepts commands, flags, and arguments to determine what to do: # execute tests in the standard library in stage0 ./x.py test --stage 0 src/libstd + # execute tests in the core and standard library in stage0, + # without running doc tests (thus avoid depending on building the compiler) + ./x.py test --stage 0 --no-doc src/libcore src/libstd + # execute all doc tests ./x.py test src/doc ``` diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 43387e28565..9c35cb7f506 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -25,7 +25,7 @@ use install; use dist; use util::{exe, libdir, add_lib_path}; -use {Build, Mode}; +use {Build, Mode, DocTests}; use cache::{INTERNER, Interned, Cache}; use check; use test; @@ -591,6 +591,8 @@ pub fn cargo(&self, format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args)); } + let want_rustdoc = self.doc_tests != DocTests::No; + // Customize the compiler we're running. Specify the compiler to cargo // as our shim and then pass it some various options used to configure // how the actual compiler itself is called. @@ -607,7 +609,7 @@ pub fn cargo(&self, .env("RUSTC_LIBDIR", self.rustc_libdir(compiler)) .env("RUSTC_RPATH", self.config.rust_rpath.to_string()) .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) - .env("RUSTDOC_REAL", if cmd == "doc" || cmd == "test" { + .env("RUSTDOC_REAL", if cmd == "doc" || (cmd == "test" && want_rustdoc) { self.rustdoc(compiler.host) } else { PathBuf::from("/path/to/nowhere/rustdoc/not/required") @@ -624,7 +626,7 @@ pub fn cargo(&self, if let Some(ref error_format) = self.config.rustc_error_format { cargo.env("RUSTC_ERROR_FORMAT", error_format); } - if cmd != "build" && cmd != "check" { + if cmd != "build" && cmd != "check" && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.config.build))); } @@ -1407,4 +1409,39 @@ fn build_with_target_flag() { }, ]); } + + #[test] + fn test_with_no_doc_stage0() { + let mut config = configure(&[], &[]); + config.stage = Some(0); + config.cmd = Subcommand::Test { + paths: vec!["src/libstd".into()], + test_args: vec![], + rustc_args: vec![], + fail_fast: true, + doc_tests: DocTests::No, + }; + + let build = Build::new(config); + let mut builder = Builder::new(&build); + + let host = INTERNER.intern_str("A"); + + builder.run_step_descriptions( + &[StepDescription::from::()], + &["src/libstd".into()], + ); + + // Ensure we don't build any compiler artifacts. + assert!(builder.cache.all::().is_empty()); + assert_eq!(first(builder.cache.all::()), &[ + test::Crate { + compiler: Compiler { host, stage: 0 }, + target: host, + mode: Mode::Libstd, + test_kind: test::TestKind::Test, + krate: INTERNER.intern_str("std"), + }, + ]); + } } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 3eb9dca2aa8..5315a3028ff 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -19,7 +19,7 @@ use getopts::Options; -use Build; +use {Build, DocTests}; use config::Config; use metadata; use builder::Builder; @@ -62,7 +62,7 @@ pub enum Subcommand { test_args: Vec, rustc_args: Vec, fail_fast: bool, - doc_tests: bool, + doc_tests: DocTests, }, Bench { paths: Vec, @@ -171,7 +171,8 @@ pub fn parse(args: &[String]) -> Flags { "extra options to pass the compiler when running tests", "ARGS", ); - opts.optflag("", "doc", "run doc tests"); + opts.optflag("", "no-doc", "do not run doc tests"); + opts.optflag("", "doc", "only run doc tests"); }, "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); }, "clean" => { opts.optflag("", "all", "clean all build artifacts"); }, @@ -324,7 +325,13 @@ pub fn parse(args: &[String]) -> Flags { test_args: matches.opt_strs("test-args"), rustc_args: matches.opt_strs("rustc-args"), fail_fast: !matches.opt_present("no-fail-fast"), - doc_tests: matches.opt_present("doc"), + doc_tests: if matches.opt_present("doc") { + DocTests::Only + } else if matches.opt_present("no-doc") { + DocTests::No + } else { + DocTests::Yes + } } } "bench" => { @@ -411,10 +418,10 @@ pub fn fail_fast(&self) -> bool { } } - pub fn doc_tests(&self) -> bool { + pub fn doc_tests(&self) -> DocTests { match *self { Subcommand::Test { doc_tests, .. } => doc_tests, - _ => false, + _ => DocTests::Yes, } } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 0a7f0e5ff4e..e53fef06786 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -210,6 +210,16 @@ pub struct Compiler { host: Interned, } +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +pub enum DocTests { + // Default, run normal tests and doc tests. + Yes, + // Do not run any doc tests. + No, + // Only run doc tests. + Only, +} + /// Global configuration for the build system. /// /// This structure transitively contains all configuration for the build system. @@ -233,7 +243,7 @@ pub struct Build { rustfmt_info: channel::GitInfo, local_rebuild: bool, fail_fast: bool, - doc_tests: bool, + doc_tests: DocTests, verbosity: usize, // Targets for which to build. @@ -294,7 +304,7 @@ fn local_path(&self, build: &Build) -> PathBuf { /// /// These entries currently correspond to the various output directories of the /// build system, with each mod generating output in a different directory. -#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum Mode { /// Build the standard library, placing output in the "stageN-std" directory. Libstd, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e8c40dfdb0a..650e09feb0e 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -32,13 +32,13 @@ use native; use tool::{self, Tool}; use util::{self, dylib_path, dylib_path_var}; -use Mode; +use {Mode, DocTests}; use toolstate::ToolState; const ADB_TEST_DIR: &str = "/data/tmp/work"; /// The two modes of the test runner; tests or benchmarks. -#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)] pub enum TestKind { /// Run `cargo test` Test, @@ -313,6 +313,9 @@ fn run(self, builder: &Builder) { // Don't build tests dynamically, just a pain to work with cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); + let dir = testdir(builder, compiler.host); + t!(fs::create_dir_all(&dir)); + cargo.env("RUSTFMT_TEST_DIR", dir); builder.add_rustc_lib_path(compiler, &mut cargo); @@ -832,7 +835,7 @@ fn run(self, builder: &Builder) { host: true }); -default_test!(RunMake { +host_test!(RunMake { path: "src/test/run-make", mode: "run-make", suite: "run-make" @@ -1019,7 +1022,7 @@ fn run(self, builder: &Builder) { // Only pass correct values for these flags for the `run-make` suite as it // requires that a C++ compiler was configured which isn't always the case. - if !builder.config.dry_run && suite == "run-make-fulldeps" { + if !builder.config.dry_run && mode == "run-make" { let llvm_components = output(Command::new(&llvm_config).arg("--components")); let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags")); cmd.arg("--cc").arg(builder.cc(target)) @@ -1032,13 +1035,13 @@ fn run(self, builder: &Builder) { } } } - if suite == "run-make-fulldeps" && !builder.config.llvm_enabled { + if mode == "run-make" && !builder.config.llvm_enabled { builder.info( &format!("Ignoring run-make test suite as they generally don't work without LLVM")); return; } - if suite != "run-make-fulldeps" { + if mode != "run-make" { cmd.arg("--cc").arg("") .arg("--cxx").arg("") .arg("--cflags").arg("") @@ -1407,13 +1410,13 @@ fn run(self, builder: &Builder) { } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Crate { - compiler: Compiler, - target: Interned, - mode: Mode, - test_kind: TestKind, - krate: Interned, + pub compiler: Compiler, + pub target: Interned, + pub mode: Mode, + pub test_kind: TestKind, + pub krate: Interned, } impl Step for Crate { @@ -1519,8 +1522,14 @@ fn run(self, builder: &Builder) { if test_kind.subcommand() == "test" && !builder.fail_fast { cargo.arg("--no-fail-fast"); } - if builder.doc_tests { - cargo.arg("--doc"); + match builder.doc_tests { + DocTests::Only => { + cargo.arg("--doc"); + } + DocTests::No => { + cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]); + } + DocTests::Yes => {} } cargo.arg("-p").arg(krate); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 6c29bd84fe4..220af6bd6e4 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -10,6 +10,7 @@ use std::fs; use std::env; +use std::iter; use std::path::PathBuf; use std::process::{Command, exit}; @@ -593,7 +594,7 @@ pub fn tool_cmd(&self, tool: Tool) -> Command { /// right location to run `compiler`. fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) { let host = &compiler.host; - let mut paths: Vec = vec![ + let mut lib_paths: Vec = vec![ PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)), self.cargo_out(compiler, Mode::Tool, *host).join("deps"), ]; @@ -610,11 +611,46 @@ fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) { } for path in env::split_paths(v) { if !curpaths.contains(&path) { - paths.push(path); + lib_paths.push(path); } } } } - add_lib_path(paths, cmd); + + // Add the llvm/bin directory to PATH since it contains lots of + // useful, platform-independent tools + if let Some(llvm_bin_path) = self.llvm_bin_path() { + if host.contains("windows") { + // On Windows, PATH and the dynamic library path are the same, + // so we just add the LLVM bin path to lib_path + lib_paths.push(llvm_bin_path); + } else { + let old_path = env::var_os("PATH").unwrap_or_default(); + let new_path = env::join_paths(iter::once(llvm_bin_path) + .chain(env::split_paths(&old_path))) + .expect("Could not add LLVM bin path to PATH"); + cmd.env("PATH", new_path); + } + } + + add_lib_path(lib_paths, cmd); + } + + fn llvm_bin_path(&self) -> Option { + if self.config.llvm_enabled && !self.config.dry_run { + let llvm_config = self.ensure(native::Llvm { + target: self.config.build, + emscripten: false, + }); + + // Add the llvm/bin directory to PATH since it contains lots of + // useful, platform-independent tools + let llvm_bin_path = llvm_config.parent() + .expect("Expected llvm-config to be contained in directory"); + assert!(llvm_bin_path.is_dir()); + Some(llvm_bin_path.to_path_buf()) + } else { + None + } } } diff --git a/src/doc/book b/src/doc/book index 6237a75790c..f51127530d4 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 6237a75790cd2e0ca22961b55f64a83319e73464 +Subproject commit f51127530d46b9acbf4747c859da185e771cfcf3 diff --git a/src/doc/nomicon b/src/doc/nomicon index 3c56329d1bd..748a5e6742d 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 3c56329d1bd9038e5341f1962bcd8d043312a712 +Subproject commit 748a5e6742db4a21c4c630a58087f818828e8a0a diff --git a/src/doc/reference b/src/doc/reference index 76296346e97..134f419ee62 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 76296346e97c3702974d3398fdb94af9e10111a2 +Subproject commit 134f419ee62714590b04712fe6072253bc2a7822 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index d5ec87eabe5..eebda16e4b4 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit d5ec87eabe5733cc2348c7dada89fc67c086f391 +Subproject commit eebda16e4b45f2eed4310cf7b9872cc752278163 diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md index e7ec6af8be1..ef76295f04d 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -239,3 +239,44 @@ error: invalid `crate_type` value | ^^^^^^^^^^^^^^^^^^^^ | ``` + +## incoherent-fundamental-impls + +This lint detects potentially-conflicting impls that were erroneously allowed. Some +example code that triggers this lint: + +```rust,ignore +pub trait Trait1 { + type Output; +} + +pub trait Trait2 {} + +pub struct A; + +impl Trait1 for T where T: Trait2 { + type Output = (); +} + +impl Trait1> for A { + type Output = i32; +} +``` + +This will produce: + +```text +error: conflicting implementations of trait `Trait1>` for type `A`: (E0119) + --> src/main.rs:13:1 + | +9 | impl Trait1 for T where T: Trait2 { + | --------------------------------------------- first implementation here +... +13 | impl Trait1> for A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A` + | + = note: #[deny(incoherent_fundamental_impls)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #46205 + = note: downstream crates may implement trait `Trait2>` for type `A` +``` diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index 1171f75caa1..b49708ff6ad 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -117,47 +117,6 @@ warning: found struct without foreign-function-safe representation annotation in | ``` -## incoherent-fundamental-impls - -This lint detects potentially-conflicting impls that were erroneously allowed. Some -example code that triggers this lint: - -```rust -pub trait Trait1 { - type Output; -} - -pub trait Trait2 {} - -pub struct A; - -impl Trait1 for T where T: Trait2 { - type Output = (); -} - -impl Trait1> for A { - type Output = i32; -} -``` - -This will produce: - -```text -warning: conflicting implementations of trait `Trait1>` for type `A`: (E0119) - --> src/main.rs:13:1 - | -9 | impl Trait1 for T where T: Trait2 { - | --------------------------------------------- first implementation here -... -13 | impl Trait1> for A { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A` - | - = note: #[warn(incoherent_fundamental_impls)] on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #46205 - = note: downstream crates may implement trait `Trait2>` for type `A` -``` - ## late-bound-lifetime-arguments This lint detects detects generic lifetime arguments in path segments with diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index 668b61c51d8..fcadcb544c4 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -157,7 +157,7 @@ use core::ops::{Deref, DerefMut}; use core::iter::{FromIterator, FusedIterator}; -use core::mem::{swap, size_of}; +use core::mem::{swap, size_of, ManuallyDrop}; use core::ptr; use core::fmt; @@ -864,8 +864,7 @@ fn better_to_rebuild(len1: usize, len2: usize) -> bool { /// position with the value that was originally removed. struct Hole<'a, T: 'a> { data: &'a mut [T], - /// `elt` is always `Some` from new until drop. - elt: Option, + elt: ManuallyDrop, pos: usize, } @@ -879,7 +878,7 @@ unsafe fn new(data: &'a mut [T], pos: usize) -> Self { let elt = ptr::read(&data[pos]); Hole { data, - elt: Some(elt), + elt: ManuallyDrop::new(elt), pos, } } @@ -892,7 +891,7 @@ fn pos(&self) -> usize { /// Returns a reference to the element removed. #[inline] fn element(&self) -> &T { - self.elt.as_ref().unwrap() + &self.elt } /// Returns a reference to the element at `index`. @@ -925,7 +924,7 @@ fn drop(&mut self) { // fill the hole again unsafe { let pos = self.pos; - ptr::write(self.data.get_unchecked_mut(pos), self.elt.take().unwrap()); + ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1); } } } diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 1b4f86dcfac..a1567344235 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -62,7 +62,7 @@ use core::hash::{Hash, Hasher}; use core::iter::FusedIterator; use core::marker::{Unpin, Unsize}; -use core::mem::{self, Pin}; +use core::mem::{self, PinMut}; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; use core::ptr::{self, NonNull, Unique}; use core::convert::From; @@ -771,8 +771,8 @@ pub fn new(data: T) -> PinBox { #[unstable(feature = "pin", issue = "49150")] impl PinBox { /// Get a pinned reference to the data in this PinBox. - pub fn as_pin<'a>(&'a mut self) -> Pin<'a, T> { - unsafe { Pin::new_unchecked(&mut *self.inner) } + pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> { + unsafe { PinMut::new_unchecked(&mut *self.inner) } } /// Get a mutable reference to the data inside this PinBox. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 04dd42583d4..54f35d17974 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -50,6 +50,15 @@ // Since libcore defines many fundamental lang items, all tests live in a // separate crate, libcoretest, to avoid bizarre issues. +// +// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do +// this, both the generated test artifact and the linked libtest (which +// transitively includes libcore) will both define the same set of lang items, +// and this will cause the E0152 "duplicate lang item found" error. See +// discussion in #50466 for details. +// +// This cfg won't affect doc tests. +#![cfg(not(test))] #![stable(feature = "core", since = "1.6.0")] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index c074adfd570..db5f50a99ca 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -595,15 +595,15 @@ unsafe impl Freeze for *mut T {} unsafe impl<'a, T: ?Sized> Freeze for &'a T {} unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} -/// Types which can be moved out of a `Pin`. +/// Types which can be moved out of a `PinMut`. /// -/// The `Unpin` trait is used to control the behavior of the [`Pin`] type. If a +/// The `Unpin` trait is used to control the behavior of the [`PinMut`] type. If a /// type implements `Unpin`, it is safe to move a value of that type out of the -/// `Pin` pointer. +/// `PinMut` pointer. /// /// This trait is automatically implemented for almost every type. /// -/// [`Pin`]: ../mem/struct.Pin.html +/// [`PinMut`]: ../mem/struct.PinMut.html #[unstable(feature = "pin", issue = "49150")] pub unsafe auto trait Unpin {} diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 10efab82ddf..6cbe26afae9 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1101,53 +1101,56 @@ fn hash(&self, state: &mut H) { /// value implements the `Unpin` trait. #[unstable(feature = "pin", issue = "49150")] #[fundamental] -pub struct Pin<'a, T: ?Sized + 'a> { +pub struct PinMut<'a, T: ?Sized + 'a> { inner: &'a mut T, } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unpin> Pin<'a, T> { - /// Construct a new `Pin` around a reference to some data of a type that +impl<'a, T: ?Sized + Unpin> PinMut<'a, T> { + /// Construct a new `PinMut` around a reference to some data of a type that /// implements `Unpin`. #[unstable(feature = "pin", issue = "49150")] - pub fn new(reference: &'a mut T) -> Pin<'a, T> { - Pin { inner: reference } + pub fn new(reference: &'a mut T) -> PinMut<'a, T> { + PinMut { inner: reference } } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Pin<'a, T> { - /// Construct a new `Pin` around a reference to some data of a type that +impl<'a, T: ?Sized> PinMut<'a, T> { + /// Construct a new `PinMut` around a reference to some data of a type that /// may or may not implement `Unpin`. /// /// This constructor is unsafe because we do not know what will happen with /// that data after the reference ends. If you cannot guarantee that the /// data will never move again, calling this constructor is invalid. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn new_unchecked(reference: &'a mut T) -> Pin<'a, T> { - Pin { inner: reference } + pub unsafe fn new_unchecked(reference: &'a mut T) -> PinMut<'a, T> { + PinMut { inner: reference } } - /// Borrow a Pin for a shorter lifetime than it already has. + /// Reborrow a `PinMut` for a shorter lifetime. + /// + /// For example, `PinMut::get_mut(x.reborrow())` (unsafely) returns a + /// short-lived mutable reference reborrowing from `x`. #[unstable(feature = "pin", issue = "49150")] - pub fn borrow<'b>(this: &'b mut Pin<'a, T>) -> Pin<'b, T> { - Pin { inner: this.inner } + pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> { + PinMut { inner: self.inner } } - /// Get a mutable reference to the data inside of this `Pin`. + /// Get a mutable reference to the data inside of this `PinMut`. /// /// This function is unsafe. You must guarantee that you will never move /// the data out of the mutable reference you receive when you call this /// function. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T { + pub unsafe fn get_mut(this: PinMut<'a, T>) -> &'a mut T { this.inner } /// Construct a new pin by mapping the interior value. /// - /// For example, if you wanted to get a `Pin` of a field of something, you + /// For example, if you wanted to get a `PinMut` of a field of something, you /// could use this to get access to that field in one line of code. /// /// This function is unsafe. You must guarantee that the data you return @@ -1155,15 +1158,15 @@ pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T { /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn map<'b, U, F>(this: &'b mut Pin<'a, T>, f: F) -> Pin<'b, U> where + pub unsafe fn map(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where F: FnOnce(&mut T) -> &mut U { - Pin { inner: f(this.inner) } + PinMut { inner: f(this.inner) } } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Deref for Pin<'a, T> { +impl<'a, T: ?Sized> Deref for PinMut<'a, T> { type Target = T; fn deref(&self) -> &T { @@ -1172,35 +1175,35 @@ fn deref(&self) -> &T { } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unpin> DerefMut for Pin<'a, T> { +impl<'a, T: ?Sized + Unpin> DerefMut for PinMut<'a, T> { fn deref_mut(&mut self) -> &mut T { self.inner } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for Pin<'a, T> { +impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for PinMut<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: fmt::Display + ?Sized> fmt::Display for Pin<'a, T> { +impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&**self, f) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> fmt::Pointer for Pin<'a, T> { +impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&(&*self.inner as *const T), f) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Pin<'a, T> {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for PinMut<'a, T> {} #[unstable(feature = "pin", issue = "49150")] -unsafe impl<'a, T: ?Sized> Unpin for Pin<'a, T> {} +unsafe impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {} diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs index 469404f7f6b..7b62e7b0620 100644 --- a/src/libcore/slice/memchr.rs +++ b/src/libcore/slice/memchr.rs @@ -135,85 +135,3 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option { // find the byte before the point the body loop stopped text[..offset].iter().rposition(|elt| *elt == x) } - -// test fallback implementations on all platforms -#[test] -fn matches_one() { - assert_eq!(Some(0), memchr(b'a', b"a")); -} - -#[test] -fn matches_begin() { - assert_eq!(Some(0), memchr(b'a', b"aaaa")); -} - -#[test] -fn matches_end() { - assert_eq!(Some(4), memchr(b'z', b"aaaaz")); -} - -#[test] -fn matches_nul() { - assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00")); -} - -#[test] -fn matches_past_nul() { - assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z")); -} - -#[test] -fn no_match_empty() { - assert_eq!(None, memchr(b'a', b"")); -} - -#[test] -fn no_match() { - assert_eq!(None, memchr(b'a', b"xyz")); -} - -#[test] -fn matches_one_reversed() { - assert_eq!(Some(0), memrchr(b'a', b"a")); -} - -#[test] -fn matches_begin_reversed() { - assert_eq!(Some(3), memrchr(b'a', b"aaaa")); -} - -#[test] -fn matches_end_reversed() { - assert_eq!(Some(0), memrchr(b'z', b"zaaaa")); -} - -#[test] -fn matches_nul_reversed() { - assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00")); -} - -#[test] -fn matches_past_nul_reversed() { - assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa")); -} - -#[test] -fn no_match_empty_reversed() { - assert_eq!(None, memrchr(b'a', b"")); -} - -#[test] -fn no_match_reversed() { - assert_eq!(None, memrchr(b'a', b"xyz")); -} - -#[test] -fn each_alignment_reversed() { - let mut data = [1u8; 64]; - let needle = 2; - let pos = 40; - data[pos] = needle; - for start in 0..16 { - assert_eq!(Some(pos - start), memrchr(needle, &data[start..])); - } -} diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index f6750c590b3..5e98e40e0d5 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -46,6 +46,7 @@ #![feature(reverse_bits)] #![feature(inclusive_range_methods)] #![feature(iterator_find_map)] +#![feature(slice_internals)] extern crate core; extern crate test; @@ -74,4 +75,5 @@ mod slice; mod str; mod str_lossy; +mod time; mod tuple; diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs index ca6906f7310..257f6ea20d4 100644 --- a/src/libcore/tests/num/uint_macros.rs +++ b/src/libcore/tests/num/uint_macros.rs @@ -98,6 +98,7 @@ fn test_swap_bytes() { } #[test] + #[cfg(not(stage0))] fn test_reverse_bits() { assert_eq!(A.reverse_bits().reverse_bits(), A); assert_eq!(B.reverse_bits().reverse_bits(), B); diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 53fdfa06827..c81e5e97cbb 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -550,3 +550,89 @@ fn sort_unstable() { v.sort_unstable(); assert!(v == [0xDEADBEEF]); } + +pub mod memchr { + use core::slice::memchr::{memchr, memrchr}; + + // test fallback implementations on all platforms + #[test] + fn matches_one() { + assert_eq!(Some(0), memchr(b'a', b"a")); + } + + #[test] + fn matches_begin() { + assert_eq!(Some(0), memchr(b'a', b"aaaa")); + } + + #[test] + fn matches_end() { + assert_eq!(Some(4), memchr(b'z', b"aaaaz")); + } + + #[test] + fn matches_nul() { + assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00")); + } + + #[test] + fn matches_past_nul() { + assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z")); + } + + #[test] + fn no_match_empty() { + assert_eq!(None, memchr(b'a', b"")); + } + + #[test] + fn no_match() { + assert_eq!(None, memchr(b'a', b"xyz")); + } + + #[test] + fn matches_one_reversed() { + assert_eq!(Some(0), memrchr(b'a', b"a")); + } + + #[test] + fn matches_begin_reversed() { + assert_eq!(Some(3), memrchr(b'a', b"aaaa")); + } + + #[test] + fn matches_end_reversed() { + assert_eq!(Some(0), memrchr(b'z', b"zaaaa")); + } + + #[test] + fn matches_nul_reversed() { + assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00")); + } + + #[test] + fn matches_past_nul_reversed() { + assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa")); + } + + #[test] + fn no_match_empty_reversed() { + assert_eq!(None, memrchr(b'a', b"")); + } + + #[test] + fn no_match_reversed() { + assert_eq!(None, memrchr(b'a', b"xyz")); + } + + #[test] + fn each_alignment_reversed() { + let mut data = [1u8; 64]; + let needle = 2; + let pos = 40; + data[pos] = needle; + for start in 0..16 { + assert_eq!(Some(pos - start), memrchr(needle, &data[start..])); + } + } +} diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs new file mode 100644 index 00000000000..042c523f25f --- /dev/null +++ b/src/libcore/tests/time.rs @@ -0,0 +1,124 @@ +// Copyright 2018 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. + +use core::time::Duration; + +#[test] +fn creation() { + assert!(Duration::from_secs(1) != Duration::from_secs(0)); + assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), + Duration::from_secs(3)); + assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), + Duration::new(4, 10 * 1_000_000)); + assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); +} + +#[test] +fn secs() { + assert_eq!(Duration::new(0, 0).as_secs(), 0); + assert_eq!(Duration::from_secs(1).as_secs(), 1); + assert_eq!(Duration::from_millis(999).as_secs(), 0); + assert_eq!(Duration::from_millis(1001).as_secs(), 1); +} + +#[test] +fn nanos() { + assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); + assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); + assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); + assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); + assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); + assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); +} + +#[test] +fn add() { + assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), + Duration::new(1, 1)); +} + +#[test] +fn checked_add() { + assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), + Some(Duration::new(0, 1))); + assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), + Some(Duration::new(1, 1))); + assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::core::u64::MAX, 0)), None); +} + +#[test] +fn sub() { + assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), + Duration::new(0, 1)); + assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), + Duration::new(0, 999_999_999)); +} + +#[test] +fn checked_sub() { + let zero = Duration::new(0, 0); + let one_nano = Duration::new(0, 1); + let one_sec = Duration::new(1, 0); + assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); + assert_eq!(one_sec.checked_sub(one_nano), + Some(Duration::new(0, 999_999_999))); + assert_eq!(zero.checked_sub(one_nano), None); + assert_eq!(zero.checked_sub(one_sec), None); +} + +#[test] +#[should_panic] +fn sub_bad1() { + let _ = Duration::new(0, 0) - Duration::new(0, 1); +} + +#[test] +#[should_panic] +fn sub_bad2() { + let _ = Duration::new(0, 0) - Duration::new(1, 0); +} + +#[test] +fn mul() { + assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); + assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); + assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); + assert_eq!(Duration::new(0, 500_000_001) * 4000, + Duration::new(2000, 4000)); +} + +#[test] +fn checked_mul() { + assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); + assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); + assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); + assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), + Some(Duration::new(2000, 4000))); + assert_eq!(Duration::new(::core::u64::MAX - 1, 0).checked_mul(2), None); +} + +#[test] +fn div() { + assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); + assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); + assert_eq!(Duration::new(99, 999_999_000) / 100, + Duration::new(0, 999_999_990)); +} + +#[test] +fn checked_div() { + assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); + assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); + assert_eq!(Duration::new(2, 0).checked_div(0), None); +} diff --git a/src/libcore/time.rs b/src/libcore/time.rs index e22fe450bb1..8e8b1691c65 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -481,119 +481,3 @@ fn sum>(iter: I) -> Duration { iter.fold(Duration::new(0, 0), |a, b| a + *b) } } - -#[cfg(test)] -mod tests { - use super::Duration; - - #[test] - fn creation() { - assert!(Duration::from_secs(1) != Duration::from_secs(0)); - assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), - Duration::from_secs(3)); - assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), - Duration::new(4, 10 * 1_000_000)); - assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); - } - - #[test] - fn secs() { - assert_eq!(Duration::new(0, 0).as_secs(), 0); - assert_eq!(Duration::from_secs(1).as_secs(), 1); - assert_eq!(Duration::from_millis(999).as_secs(), 0); - assert_eq!(Duration::from_millis(1001).as_secs(), 1); - } - - #[test] - fn nanos() { - assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); - assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); - assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); - assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); - assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); - assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); - } - - #[test] - fn add() { - assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), - Duration::new(1, 1)); - } - - #[test] - fn checked_add() { - assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), - Some(Duration::new(0, 1))); - assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), - Some(Duration::new(1, 1))); - assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None); - } - - #[test] - fn sub() { - assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), - Duration::new(0, 1)); - assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), - Duration::new(0, 999_999_999)); - } - - #[test] - fn checked_sub() { - let zero = Duration::new(0, 0); - let one_nano = Duration::new(0, 1); - let one_sec = Duration::new(1, 0); - assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); - assert_eq!(one_sec.checked_sub(one_nano), - Some(Duration::new(0, 999_999_999))); - assert_eq!(zero.checked_sub(one_nano), None); - assert_eq!(zero.checked_sub(one_sec), None); - } - - #[test] #[should_panic] - fn sub_bad1() { - Duration::new(0, 0) - Duration::new(0, 1); - } - - #[test] #[should_panic] - fn sub_bad2() { - Duration::new(0, 0) - Duration::new(1, 0); - } - - #[test] - fn mul() { - assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); - assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); - assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); - assert_eq!(Duration::new(0, 500_000_001) * 4000, - Duration::new(2000, 4000)); - } - - #[test] - fn checked_mul() { - assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); - assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); - assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); - assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), - Some(Duration::new(2000, 4000))); - assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None); - } - - #[test] - fn div() { - assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); - assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); - assert_eq!(Duration::new(99, 999_999_000) / 100, - Duration::new(0, 999_999_990)); - } - - #[test] - fn checked_div() { - assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); - assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); - assert_eq!(Duration::new(2, 0).checked_div(0), None); - } -} diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index f51dbc3772f..8451e5987e9 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -74,6 +74,11 @@ #[derive(Clone)] pub struct TokenStream(tokenstream::TokenStream); +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for TokenStream {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for TokenStream {} + /// Error returned from `TokenStream::from_str`. #[stable(feature = "proc_macro_lib", since = "1.15.0")] #[derive(Debug)] @@ -81,6 +86,11 @@ pub struct LexError { _inner: (), } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for LexError {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for LexError {} + impl TokenStream { /// Returns an empty `TokenStream`. #[unstable(feature = "proc_macro", issue = "38356")] @@ -231,6 +241,11 @@ pub fn quote_span(span: Span) -> TokenStream { #[derive(Copy, Clone)] pub struct Span(syntax_pos::Span); +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Span {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Span {} + macro_rules! diagnostic_method { ($name:ident, $level:expr) => ( /// Create a new `Diagnostic` with the given `message` at the span @@ -363,6 +378,11 @@ pub struct LineColumn { pub column: usize } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for LineColumn {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for LineColumn {} + /// The source file of a given `Span`. #[unstable(feature = "proc_macro", issue = "38356")] #[derive(Clone)] @@ -393,7 +413,7 @@ pub fn path(&self) -> &FileName { /// Returns `true` if this source file is a real source file, and not generated by an external /// macro's expansion. - # [unstable(feature = "proc_macro", issue = "38356")] + #[unstable(feature = "proc_macro", issue = "38356")] pub fn is_real(&self) -> bool { // This is a hack until intercrate spans are implemented and we can have real source files // for spans generated in external macros. @@ -450,6 +470,11 @@ pub enum TokenTree { Literal(Literal), } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for TokenTree {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for TokenTree {} + impl TokenTree { /// Returns the span of this token, accessing the `span` method of each of /// the internal tokens. @@ -546,6 +571,11 @@ pub struct Group { span: Span, } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Group {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Group {} + /// Describes how a sequence of token trees is delimited. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "proc_macro", issue = "38356")] @@ -628,6 +658,11 @@ pub struct Op { span: Span, } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Op {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Op {} + /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "proc_macro", issue = "38356")] @@ -694,6 +729,11 @@ pub struct Term { span: Span, } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Term {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Term {} + impl Term { /// Creates a new `Term` with the given `string` as well as the specified /// `span`. @@ -752,6 +792,11 @@ pub struct Literal { span: Span, } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Literal {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Literal {} + macro_rules! suffixed_int_literals { ($($name:ident => $kind:ident,)*) => ($( /// Creates a new suffixed integer literal with the specified value. diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 109edffcde3..398d7d5704c 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -14,7 +14,7 @@ //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. -use errors::DiagnosticBuilder; +use errors::{Applicability, DiagnosticBuilder}; use lint::{LintPass, LateLintPass, LintArray}; use session::Session; use syntax::codemap::Span; @@ -208,7 +208,7 @@ declare_lint! { pub INCOHERENT_FUNDAMENTAL_IMPLS, - Warn, + Deny, "potentially-conflicting impls were erroneously allowed" } @@ -341,15 +341,16 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) { match self { BuiltinLintDiagnostics::Normal => (), BuiltinLintDiagnostics::BareTraitObject(span, is_global) => { - let sugg = match sess.codemap().span_to_snippet(span) { - Ok(ref s) if is_global => format!("dyn ({})", s), - Ok(s) => format!("dyn {}", s), - Err(_) => format!("dyn ") + let (sugg, app) = match sess.codemap().span_to_snippet(span) { + Ok(ref s) if is_global => (format!("dyn ({})", s), + Applicability::MachineApplicable), + Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable), + Err(_) => (format!("dyn "), Applicability::HasPlaceholders) }; - db.span_suggestion(span, "use `dyn`", sugg); + db.span_suggestion_with_applicability(span, "use `dyn`", sugg, app); } BuiltinLintDiagnostics::AbsPathWithModule(span) => { - let sugg = match sess.codemap().span_to_snippet(span) { + let (sugg, app) = match sess.codemap().span_to_snippet(span) { Ok(ref s) => { // FIXME(Manishearth) ideally the emitting code // can tell us whether or not this is global @@ -359,11 +360,11 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) { "::" }; - format!("crate{}{}", opt_colon, s) + (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable) } - Err(_) => format!("crate::") + Err(_) => (format!("crate::"), Applicability::HasPlaceholders) }; - db.span_suggestion(span, "use `crate`", sugg); + db.span_suggestion_with_applicability(span, "use `crate`", sugg, app); } } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 0beda679e69..83dac033f94 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1295,6 +1295,8 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool { "make the current crate share its generic instantiations"), chalk: bool = (false, parse_bool, [TRACKED], "enable the experimental Chalk-based trait solving engine"), + cross_lang_lto: bool = (false, parse_bool, [TRACKED], + "generate build artifacts that are compatible with linker-based LTO."), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index a319b341ebb..02c4b73efa1 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1057,7 +1057,7 @@ enum StructKind { } tcx.intern_layout(LayoutDetails { variants: Variants::Tagged { - discr: tag, + tag, variants: layout_variants, }, fields: FieldPlacement::Arbitrary { @@ -1218,7 +1218,7 @@ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) { }) .collect(); record(adt_kind.into(), adt_packed, match layout.variants { - Variants::Tagged { ref discr, .. } => Some(discr.value.size(self)), + Variants::Tagged { ref tag, .. } => Some(tag.value.size(self)), _ => None }, variant_infos); } @@ -1622,7 +1622,7 @@ fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout { } // Discriminant field for enums (where applicable). - Variants::Tagged { ref discr, .. } | + Variants::Tagged { tag: ref discr, .. } | Variants::NicheFilling { niche: ref discr, .. } => { assert_eq!(i, 0); let layout = LayoutDetails::scalar(tcx, discr.clone()); @@ -1736,10 +1736,10 @@ fn hash_stable(&self, index.hash_stable(hcx, hasher); } Tagged { - ref discr, + ref tag, ref variants, } => { - discr.hash_stable(hcx, hasher); + tag.hash_stable(hcx, hasher); variants.hash_stable(hcx, hasher); } NicheFilling { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index f06062fa4ac..7ae13c803dd 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -46,7 +46,7 @@ use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes}; use syntax_pos::{BytePos, Span, SyntaxContext}; use syntax::symbol::keywords; -use syntax::errors::DiagnosticBuilder; +use syntax::errors::{Applicability, DiagnosticBuilder}; use rustc::hir::{self, PatKind}; use rustc::hir::intravisit::FnKind; @@ -1300,7 +1300,19 @@ fn perform_lint(&self, cx: &LateContext, what: &str, id: ast::NodeId, } else { "pub(crate)" }.to_owned(); - err.span_suggestion(pub_span, "consider restricting its visibility", replacement); + let app = if span.ctxt().outer().expn_info().is_none() { + // even if macros aren't involved the suggestion + // may be incorrect -- the user may have mistakenly + // hidden it behind a private module and this lint is + // a helpful way to catch that. However, we're trying + // not to change the nature of the code with this lint + // so it's marked as machine applicable. + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + err.span_suggestion_with_applicability(pub_span, "consider restricting its visibility", + replacement, app); if exportable { err.help("or consider exporting it for use by other crates"); } @@ -1508,3 +1520,66 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { } } } + +declare_lint! { + pub UNNECESSARY_EXTERN_CRATE, + Allow, + "suggest removing `extern crate` for the 2018 edition" +} + +pub struct ExternCrate(/* depth */ u32); + +impl ExternCrate { + pub fn new() -> Self { + ExternCrate(0) + } +} + +impl LintPass for ExternCrate { + fn get_lints(&self) -> LintArray { + lint_array!(UNNECESSARY_EXTERN_CRATE) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExternCrate { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { + if let hir::ItemExternCrate(ref orig) = it.node { + if it.attrs.iter().any(|a| a.check_name("macro_use")) { + return + } + let mut err = cx.struct_span_lint(UNNECESSARY_EXTERN_CRATE, + it.span, "`extern crate` is unnecessary in the new edition"); + if it.vis == hir::Visibility::Public || self.0 > 1 || orig.is_some() { + let pub_ = if it.vis == hir::Visibility::Public { + "pub " + } else { + "" + }; + + let help = format!("use `{}use`", pub_); + + if let Some(orig) = orig { + err.span_suggestion(it.span, &help, + format!("{}use {} as {}", pub_, orig, it.name)); + } else { + err.span_suggestion(it.span, &help, + format!("{}use {}", pub_, it.name)); + } + } else { + err.span_suggestion(it.span, "remove it", "".into()); + } + + err.emit(); + } + } + + fn check_mod(&mut self, _: &LateContext, _: &hir::Mod, + _: Span, _: ast::NodeId) { + self.0 += 1; + } + + fn check_mod_post(&mut self, _: &LateContext, _: &hir::Mod, + _: Span, _: ast::NodeId) { + self.0 += 1; + } +} diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 4f6d23dce6d..4403e1e3358 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -143,6 +143,7 @@ macro_rules! add_lint_group { TypeLimits, MissingDoc, MissingDebugImplementations, + ExternCrate, ); add_lint_group!(sess, @@ -178,9 +179,10 @@ macro_rules! add_lint_group { UNUSED_PARENS); add_lint_group!(sess, - "rust_2018_idioms", + "rust_2018_migration", BARE_TRAIT_OBJECT, - UNREACHABLE_PUB); + UNREACHABLE_PUB, + UNNECESSARY_EXTERN_CRATE); // Guidelines for creating a future incompatibility lint: // diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 904a3e4c427..9e0dc4d80c8 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -820,8 +820,8 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { bug!("failed to get layout for `{}`: {}", t, e) }); - if let layout::Variants::Tagged { ref variants, ref discr, .. } = layout.variants { - let discr_size = discr.value.size(cx.tcx).bytes(); + if let layout::Variants::Tagged { ref variants, ref tag, .. } = layout.variants { + let discr_size = tag.value.size(cx.tcx).bytes(); debug!("enum `{}` is {} bytes large with layout:\n{:#?}", t, layout.size.bytes(), layout); diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 8df40b62ddd..845c964b986 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -135,12 +135,12 @@ fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span, describe_path: &str if attr.check_name("must_use") { let mut msg = format!("unused {}`{}` which must be used", describe_path, cx.tcx.item_path_str(def_id)); - // check for #[must_use="..."] - if let Some(s) = attr.value_str() { - msg.push_str(": "); - msg.push_str(&s.as_str()); + let mut err = cx.struct_span_lint(UNUSED_MUST_USE, sp, &msg); + // check for #[must_use = "..."] + if let Some(note) = attr.value_str() { + err.note(¬e.as_str()); } - cx.span_lint(UNUSED_MUST_USE, sp, &msg); + err.emit(); return true; } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index bea29b6926a..d8f13242065 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -654,6 +654,9 @@ pub(super) fn eval_rvalue_into_place( if self.type_is_fat_ptr(src.ty) { match (src.value, self.type_is_fat_ptr(dest_ty)) { (Value::ByRef { .. }, _) | + // pointers to extern types + (Value::ByVal(_),_) | + // slices and trait objects to other slices/trait objects (Value::ByValPair(..), true) => { let valty = ValTy { value: src.value, @@ -661,6 +664,7 @@ pub(super) fn eval_rvalue_into_place( }; self.write_value(valty, dest)?; } + // slices and trait objects to thin pointers (dropping the metadata) (Value::ByValPair(data, _), false) => { let valty = ValTy { value: Value::ByVal(data), @@ -668,7 +672,6 @@ pub(super) fn eval_rvalue_into_place( }; self.write_value(valty, dest)?; } - (Value::ByVal(_), _) => bug!("expected fat ptr"), } } else { let src_layout = self.layout_of(src.ty)?; @@ -960,7 +963,7 @@ pub fn write_discriminant_value( layout::Abi::Uninhabited); } } - layout::Variants::Tagged { ref discr, .. } => { + layout::Variants::Tagged { ref tag, .. } => { let discr_val = dest_ty.ty_adt_def().unwrap() .discriminant_for_variant(*self.tcx, variant_index) .val; @@ -968,12 +971,12 @@ pub fn write_discriminant_value( // raw discriminants for enums are isize or bigger during // their computation, but the in-memory tag is the smallest possible // representation - let size = discr.value.size(self.tcx.tcx).bits(); + let size = tag.value.size(self.tcx.tcx).bits(); let amt = 128 - size; let discr_val = (discr_val << amt) >> amt; - let (discr_dest, discr) = self.place_field(dest, mir::Field::new(0), layout)?; - self.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr.ty)?; + let (discr_dest, tag) = self.place_field(dest, mir::Field::new(0), layout)?; + self.write_primval(discr_dest, PrimVal::Bytes(discr_val), tag.ty)?; } layout::Variants::NicheFilling { dataful_variant, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d4b212a15d8..0f931d4374e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3277,9 +3277,8 @@ fn resolve_path(&mut self, let prev_name = path[0].name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() && - // Note: When this feature stabilizes, this should - // be gated on sess.rust_2018() - self.session.features_untracked().extern_absolute_paths { + self.session.features_untracked().extern_absolute_paths && + self.session.rust_2018() { // `::extern_crate::a::b` let crate_id = self.crate_loader.process_path_extern(name, ident.span); let crate_root = diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 17aa510b565..6a5a31a885f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -646,7 +646,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa if module_path.len() == 1 && (module_path[0].name == keywords::CrateRoot.name() || module_path[0].name == keywords::Extern.name()) { let is_extern = module_path[0].name == keywords::Extern.name() || - self.session.features_untracked().extern_absolute_paths; + (self.session.features_untracked().extern_absolute_paths && + self.session.rust_2018()); match directive.subclass { GlobImport { .. } if is_extern => { return Some((directive.span, diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 401a280412a..cf12302d989 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -40,7 +40,7 @@ use rustc::hir; use rustc::hir::def::Def as HirDef; -use rustc::hir::map::{Node, NodeItem}; +use rustc::hir::map::{Node, NodeTraitItem, NodeImplItem}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::cstore::ExternCrate; use rustc::session::config::CrateType::CrateTypeExecutable; @@ -418,34 +418,30 @@ pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> O Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) { Some(Node::NodeItem(item)) => match item.node { hir::ItemImpl(.., ref ty, _) => { - let mut result = String::from("<"); - result.push_str(&self.tcx.hir.node_to_pretty_string(ty.id)); + let mut qualname = String::from("<"); + qualname.push_str(&self.tcx.hir.node_to_pretty_string(ty.id)); let mut trait_id = self.tcx.trait_id_of_impl(impl_id); let mut decl_id = None; + let mut docs = String::new(); + let mut attrs = vec![]; + if let Some(NodeImplItem(item)) = self.tcx.hir.find(id) { + docs = self.docs_for_attrs(&item.attrs); + attrs = item.attrs.to_vec(); + } + if let Some(def_id) = trait_id { - result.push_str(" as "); - result.push_str(&self.tcx.item_path_str(def_id)); + // A method in a trait impl. + qualname.push_str(" as "); + qualname.push_str(&self.tcx.item_path_str(def_id)); self.tcx .associated_items(def_id) .find(|item| item.name == name) .map(|item| decl_id = Some(item.def_id)); - } else { - if let Some(NodeItem(item)) = self.tcx.hir.find(id) { - if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node { - trait_id = self.lookup_ref_id(ty.id); - } - } } - result.push_str(">"); - - ( - result, - trait_id, - decl_id, - self.docs_for_attrs(&item.attrs), - item.attrs.to_vec(), - ) + qualname.push_str(">"); + + (qualname, trait_id, decl_id, docs, attrs) } _ => { span_bug!( @@ -467,25 +463,23 @@ pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> O } }, None => match self.tcx.trait_of_item(self.tcx.hir.local_def_id(id)) { - Some(def_id) => match self.tcx.hir.get_if_local(def_id) { - Some(Node::NodeItem(item)) => ( + Some(def_id) => { + let mut docs = String::new(); + let mut attrs = vec![]; + + if let Some(NodeTraitItem(item)) = self.tcx.hir.find(id) { + docs = self.docs_for_attrs(&item.attrs); + attrs = item.attrs.to_vec(); + } + + ( format!("::{}", self.tcx.item_path_str(def_id)), Some(def_id), None, - self.docs_for_attrs(&item.attrs), - item.attrs.to_vec(), - ), - r => { - span_bug!( - span, - "Could not find container {:?} for \ - method {}, got {:?}", - def_id, - id, - r - ); - } - }, + docs, + attrs, + ) + } None => { debug!("Could not find container for method {} at {:?}", id, span); // This is not necessarily a bug, if there was a compilation error, diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index fd1f779f9ec..7ae4d990c8a 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -716,10 +716,10 @@ pub enum Variants { }, /// General-case enums: for each case there is a struct, and they all have - /// all space reserved for the discriminant, and their first field starts - /// at a non-0 offset, after where the discriminant would go. + /// all space reserved for the tag, and their first field starts + /// at a non-0 offset, after where the tag would go. Tagged { - discr: Scalar, + tag: Scalar, variants: Vec, }, diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 148e3d0025c..b6fae3eaff2 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -293,7 +293,8 @@ fn set_flags(&mut self, sess: &Session, no_builtins: bool) { self.inline_threshold = sess.opts.cg.inline_threshold; self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode; let embed_bitcode = sess.target.target.options.embed_bitcode || - sess.opts.debugging_opts.embed_bitcode; + sess.opts.debugging_opts.embed_bitcode || + sess.opts.debugging_opts.cross_lang_lto; if embed_bitcode { match sess.opts.optimize { config::OptLevel::No | @@ -841,13 +842,18 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, "rustc.embedded.module\0".as_ptr() as *const _, ); llvm::LLVMSetInitializer(llglobal, llconst); - let section = if cgcx.opts.target_triple.triple().contains("-ios") { + + let is_apple = cgcx.opts.target_triple.triple().contains("-ios") || + cgcx.opts.target_triple.triple().contains("-darwin"); + + let section = if is_apple { "__LLVM,__bitcode\0" } else { ".llvmbc\0" }; llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); + llvm::LLVMSetGlobalConstant(llglobal, llvm::True); let llconst = C_bytes_in_context(llcx, &[]); let llglobal = llvm::LLVMAddGlobal( @@ -856,7 +862,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, "rustc.embedded.cmdline\0".as_ptr() as *const _, ); llvm::LLVMSetInitializer(llglobal, llconst); - let section = if cgcx.opts.target_triple.triple().contains("-ios") { + let section = if is_apple { "__LLVM,__cmdline\0" } else { ".llvmcmd\0" @@ -1350,6 +1356,10 @@ fn execute_work_item(cgcx: &CodegenContext, // settings. let needs_lto = needs_lto && mtrans.kind != ModuleKind::Metadata; + // Don't run LTO passes when cross-lang LTO is enabled. The linker + // will do that for us in this case. + let needs_lto = needs_lto && !cgcx.opts.debugging_opts.cross_lang_lto; + if needs_lto { Ok(WorkItemResult::NeedsLTO(mtrans)) } else { diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 2fc6c9d4433..f16fef5ec1e 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1429,8 +1429,8 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let discriminant_type_metadata = match layout.variants { layout::Variants::Single { .. } | layout::Variants::NicheFilling { .. } => None, - layout::Variants::Tagged { ref discr, .. } => { - Some(discriminant_type_metadata(discr.value)) + layout::Variants::Tagged { ref tag, .. } => { + Some(discriminant_type_metadata(tag.value)) } }; diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs index 79859aee64d..d4abd5fa88d 100644 --- a/src/librustc_trans/mir/place.rs +++ b/src/librustc_trans/mir/place.rs @@ -273,8 +273,8 @@ pub fn trans_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Value let lldiscr = discr.load(bx).immediate(); match self.layout.variants { layout::Variants::Single { .. } => bug!(), - layout::Variants::Tagged { ref discr, .. } => { - let signed = match discr.value { + layout::Variants::Tagged { ref tag, .. } => { + let signed = match tag.value { layout::Int(_, signed) => signed, _ => false }; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 23e0c2625ee..a8f4848bf89 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -38,7 +38,7 @@ /// /// The returned value is `None` if the definition could not be inlined, /// and `Some` of a vector of items if it was successfully expanded. -pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name) +pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHashSet) -> Option> { if def == Def::Err { return None } let did = def.def_id(); @@ -87,7 +87,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name) Def::StructCtor(..) => return Some(Vec::new()), Def::Mod(did) => { record_extern_fqn(cx, did, clean::TypeKind::Module); - clean::ModuleItem(build_module(cx, did)) + clean::ModuleItem(build_module(cx, did, visited)) } Def::Static(did, mtbl) => { record_extern_fqn(cx, did, clean::TypeKind::Static); @@ -385,24 +385,24 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { }); } -fn build_module(cx: &DocContext, did: DefId) -> clean::Module { +fn build_module(cx: &DocContext, did: DefId, visited: &mut FxHashSet) -> clean::Module { let mut items = Vec::new(); - fill_in(cx, did, &mut items); + fill_in(cx, did, &mut items, visited); return clean::Module { items, is_crate: false, }; - fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec) { + fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec, + visited: &mut FxHashSet) { // If we're re-exporting a re-export it may actually re-export something in // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. - let mut visited = FxHashSet(); for &item in cx.tcx.item_children(did).iter() { let def_id = item.def.def_id(); if item.vis == ty::Visibility::Public { - if !visited.insert(def_id) { continue } - if let Some(i) = try_inline(cx, item.def, item.ident.name) { + if did == def_id || !visited.insert(def_id) { continue } + if let Some(i) = try_inline(cx, item.def, item.ident.name, visited) { items.extend(i) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index edbf5f3abd2..fb0bd0e42c5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3686,7 +3686,8 @@ fn clean(&self, cx: &DocContext) -> Vec { } else { let name = self.name; if !denied { - if let Some(items) = inline::try_inline(cx, path.def, name) { + let mut visited = FxHashSet(); + if let Some(items) = inline::try_inline(cx, path.def, name, &mut visited) { return items; } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fc05833e285..d41739ab02c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -330,10 +330,10 @@ // with a rustc without jemalloc. // FIXME(#44236) shouldn't need MSVC logic #![cfg_attr(all(not(target_env = "msvc"), - any(stage0, feature = "force_alloc_system")), + any(all(stage0, not(test)), feature = "force_alloc_system")), feature(global_allocator))] #[cfg(all(not(target_env = "msvc"), - any(stage0, feature = "force_alloc_system")))] + any(all(stage0, not(test)), feature = "force_alloc_system")))] #[global_allocator] static ALLOC: alloc_system::System = alloc_system::System; diff --git a/src/libsyntax/edition.rs b/src/libsyntax/edition.rs index 3fc1c279f5a..7341941c242 100644 --- a/src/libsyntax/edition.rs +++ b/src/libsyntax/edition.rs @@ -50,8 +50,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { impl Edition { pub fn lint_name(&self) -> &'static str { match *self { - Edition::Edition2015 => "edition_2015", - Edition::Edition2018 => "edition_2018", + Edition::Edition2015 => "rust_2015_breakage", + Edition::Edition2018 => "rust_2018_breakage", } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d8db76a95ff..5155408ba63 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -300,7 +300,7 @@ pub fn walk_feature_fields(&self, mut f: F) (active, abi_unadjusted, "1.16.0", None, None), // Procedural macros 2.0. - (active, proc_macro, "1.16.0", Some(38356), None), + (active, proc_macro, "1.16.0", Some(38356), Some(Edition::Edition2018)), // Declarative macros 2.0 (`macro`). (active, decl_macro, "1.17.0", Some(39412), None), @@ -324,7 +324,7 @@ pub fn walk_feature_fields(&self, mut f: F) // Allows the `catch {...}` expression - (active, catch_expr, "1.17.0", Some(31436), None), + (active, catch_expr, "1.17.0", Some(31436), Some(Edition::Edition2018)), // Used to preserve symbols (see llvm.used) (active, used, "1.18.0", Some(40289), None), @@ -1848,6 +1848,14 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) { let mut feature_checker = FeatureChecker::default(); + for &(.., f_edition, set) in ACTIVE_FEATURES.iter() { + if let Some(f_edition) = f_edition { + if f_edition <= crate_edition { + set(&mut features, DUMMY_SP); + } + } + } + for attr in krate_attrs { if !attr.check_name("feature") { continue diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d8228e2b28b..b8ddb063d98 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -656,7 +656,7 @@ fn print_string(&mut self, st: &str, style: ast::StrStyle) -> io::Result<()> { let st = match style { ast::StrStyle::Cooked => { - (format!("\"{}\"", st.escape_default())) + (format!("\"{}\"", st.escape_debug())) } ast::StrStyle::Raw(n) => { (format!("r{delim}\"{string}\"{delim}", diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index 7352c494a42..754f04a26e7 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -42,16 +42,13 @@ pub fn expand_assert<'cx>( tts: if let Some(ts) = custom_msg_args { ts.into() } else { - // `expr_to_string` escapes the string literals with `.escape_default()` - // which escapes all non-ASCII characters with `\u`. - let escaped_expr = escape_format_string(&unescape_printable_unicode( - &pprust::expr_to_string(&cond_expr), - )); - TokenStream::from(TokenTree::Token( DUMMY_SP, token::Literal( - token::Lit::Str_(Name::intern(&format!("assertion failed: {}", escaped_expr))), + token::Lit::Str_(Name::intern(&format!( + "assertion failed: {}", + pprust::expr_to_string(&cond_expr).escape_debug() + ))), None, ), )).into() @@ -71,53 +68,3 @@ pub fn expand_assert<'cx>( ); MacEager::expr(if_expr) } - -/// Escapes a string for use as a formatting string. -fn escape_format_string(s: &str) -> String { - let mut res = String::with_capacity(s.len()); - for c in s.chars() { - res.extend(c.escape_debug()); - match c { - '{' | '}' => res.push(c), - _ => {} - } - } - res -} - -#[test] -fn test_escape_format_string() { - assert!(escape_format_string(r"foo{}\") == r"foo{{}}\\"); -} - -/// Unescapes the escaped unicodes (`\u{...}`) that are printable. -fn unescape_printable_unicode(mut s: &str) -> String { - use std::{char, u32}; - - let mut res = String::with_capacity(s.len()); - - loop { - if let Some(start) = s.find(r"\u{") { - res.push_str(&s[0..start]); - s = &s[start..]; - s.find('}') - .and_then(|end| { - let v = u32::from_str_radix(&s[3..end], 16).ok()?; - let c = char::from_u32(v)?; - // Escape unprintable characters. - res.extend(c.escape_debug()); - s = &s[end + 1..]; - Some(()) - }) - .expect("lexer should have rejected invalid escape sequences"); - } else { - res.push_str(s); - return res; - } - } -} - -#[test] -fn test_unescape_printable_unicode() { - assert!(unescape_printable_unicode(r"\u{2603}\n\u{0}") == r"☃\n\u{0}"); -} diff --git a/src/stdsimd b/src/stdsimd index 1ea18a5cb43..2f86c75a247 160000 --- a/src/stdsimd +++ b/src/stdsimd @@ -1 +1 @@ -Subproject commit 1ea18a5cb431e24aa838b652ac305acc5e394d6b +Subproject commit 2f86c75a2479cf051b92fc98273daaf7f151e7a1 diff --git a/src/test/compile-fail/issue-43355.rs b/src/test/compile-fail/issue-43355.rs index 4db5c84df9a..d793a78799a 100644 --- a/src/test/compile-fail/issue-43355.rs +++ b/src/test/compile-fail/issue-43355.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(incoherent_fundamental_impls)] - pub trait Trait1 { type Output; } diff --git a/src/test/compile-fail/issue-50471.rs b/src/test/compile-fail/issue-50471.rs new file mode 100644 index 00000000000..ce2947144af --- /dev/null +++ b/src/test/compile-fail/issue-50471.rs @@ -0,0 +1,19 @@ +// Copyright 2018 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. + +// compile-pass + +fn main() { + assert!({false}); + + assert!(r"\u{41}" == "A"); + + assert!(r"\u{".is_empty()); +} diff --git a/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-1.rs b/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-1.rs index 14d5d9caa31..fcf4714ba96 100644 --- a/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-1.rs +++ b/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: --edition=2018 -Zunstable-options + #![feature(extern_absolute_paths)] use xcrate::S; //~ ERROR can't find crate for `xcrate` diff --git a/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-2.rs b/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-2.rs index defd103f9e4..c256c5592c2 100644 --- a/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-2.rs +++ b/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: --edition=2018 -Zunstable-options + #![feature(extern_absolute_paths)] fn main() { diff --git a/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-3.rs b/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-3.rs index be1708e2b57..837dc617b3a 100644 --- a/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-3.rs +++ b/src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-3.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: --edition=2018 -Zunstable-options + #![feature(extern_absolute_paths)] use ycrate; //~ ERROR can't find crate for `ycrate` diff --git a/src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs b/src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs index e44465750d1..9b7baa00163 100644 --- a/src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs +++ b/src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs @@ -9,6 +9,7 @@ // except according to those terms. // aux-build:xcrate.rs +// compile-flags: --edition=2018 -Zunstable-options #![feature(crate_in_paths)] #![feature(extern_absolute_paths)] diff --git a/src/test/compile-fail/unused-result.rs b/src/test/compile-fail/unused-result.rs index 0c6c7fc5a0d..363ab6220bd 100644 --- a/src/test/compile-fail/unused-result.rs +++ b/src/test/compile-fail/unused-result.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(unused_results, unused_must_use)] #![allow(dead_code)] +#![deny(unused_results, unused_must_use)] +//~^ NOTE: lint level defined here +//~| NOTE: lint level defined here #[must_use] enum MustUse { Test } @@ -27,7 +29,8 @@ fn foo() -> T { panic!() } fn test() { foo::(); foo::(); //~ ERROR: unused `MustUse` which must be used - foo::(); //~ ERROR: unused `MustUseMsg` which must be used: some message + foo::(); //~ ERROR: unused `MustUseMsg` which must be used + //~^ NOTE: some message } #[allow(unused_results, unused_must_use)] @@ -40,7 +43,8 @@ fn test2() { fn main() { foo::(); //~ ERROR: unused result foo::(); //~ ERROR: unused `MustUse` which must be used - foo::(); //~ ERROR: unused `MustUseMsg` which must be used: some message + foo::(); //~ ERROR: unused `MustUseMsg` which must be used + //~^ NOTE: some message let _ = foo::(); let _ = foo::(); diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile index a132668ec7c..6a67b5862a8 100644 --- a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile @@ -1,9 +1,9 @@ -include ../tools.mk all: extern_absolute_paths.rs extern_in_paths.rs krate2 - $(RUSTC) extern_absolute_paths.rs -Zsave-analysis + $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py - $(RUSTC) extern_in_paths.rs -Zsave-analysis + $(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018 cat $(TMPDIR)/save-analysis/extern_in_paths.json | "$(PYTHON)" validate_json.py krate2: krate2.rs diff --git a/src/test/run-make/cross-lang-lto/Makefile b/src/test/run-make/cross-lang-lto/Makefile new file mode 100644 index 00000000000..98b509cd81f --- /dev/null +++ b/src/test/run-make/cross-lang-lto/Makefile @@ -0,0 +1,53 @@ + +# min-llvm-version 4.0 +# ignore-mingw + +-include ../../run-make-fulldeps/tools.mk + +# This test makes sure that the expected .llvmbc sections for use by +# linker-based LTO are available in object files when compiling with +# -Z cross-lang-lto + +LLVMBC_SECTION_NAME=\\.llvmbc + +ifeq ($(UNAME),Darwin) + LLVMBC_SECTION_NAME=__bitcode +endif + + +OBJDUMP=llvm-objdump +SECTION_HEADERS=$(OBJDUMP) -section-headers + +BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Z cross-lang-lto -Ccodegen-units=1 + +BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Z cross-lang-lto -Ccodegen-units=1 --emit=obj + +all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib + +staticlib: lib.rs + $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a + [ "$$($(SECTION_HEADERS) $(TMPDIR)/liblib.a | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ] + +staticlib-fat-lto: lib.rs + $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat + [ "$$($(SECTION_HEADERS) $(TMPDIR)/liblib-fat-lto.a | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ] + +staticlib-thin-lto: lib.rs + $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin + [ "$$($(SECTION_HEADERS) $(TMPDIR)/liblib-thin-lto.a | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ] + +rlib: lib.rs + $(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib + [ "$$($(SECTION_HEADERS) $(TMPDIR)/liblib.rlib | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ] + +cdylib: lib.rs + $(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o + [ "$$($(SECTION_HEADERS) $(TMPDIR)/cdylib.o | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ] + +rdylib: lib.rs + $(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o + [ "$$($(SECTION_HEADERS) $(TMPDIR)/rdylib.o | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ] + +exe: lib.rs + $(BUILD_EXE) -o $(TMPDIR)/exe.o + [ "$$($(SECTION_HEADERS) $(TMPDIR)/exe.o | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ] diff --git a/src/test/run-make/cross-lang-lto/lib.rs b/src/test/run-make/cross-lang-lto/lib.rs new file mode 100644 index 00000000000..b2a5b946160 --- /dev/null +++ b/src/test/run-make/cross-lang-lto/lib.rs @@ -0,0 +1,14 @@ +// Copyright 2018 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. + +#[no_mangle] +pub extern "C" fn foo() { + println!("abc"); +} diff --git a/src/test/run-make/cross-lang-lto/main.rs b/src/test/run-make/cross-lang-lto/main.rs new file mode 100644 index 00000000000..ccd34c9e4db --- /dev/null +++ b/src/test/run-make/cross-lang-lto/main.rs @@ -0,0 +1,13 @@ +// Copyright 2018 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. + +fn main() { + println!("Hello World"); +} diff --git a/src/test/run-pass/issue-43355.rs b/src/test/run-pass/issue-43355.rs deleted file mode 100644 index 19431a6a429..00000000000 --- a/src/test/run-pass/issue-43355.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 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. - -// Check that the code for issue #43355 can run without an ICE, please remove -// this test when it becomes an hard error. - -pub trait Trait1 { - type Output; -} -pub trait Trait2 {} - -impl Trait1 for T where T: Trait2 { - type Output = (); -} -impl Trait1> for A { - type Output = i32; -} - -pub struct A; - -fn f>>() { - println!("k: {}", ::std::mem::size_of::<>>::Output>()); -} - -pub fn g>>() { - f::(); -} - -fn main() {} diff --git a/src/test/run-pass/rfc-2126-extern-absolute-paths/basic.rs b/src/test/run-pass/rfc-2126-extern-absolute-paths/basic.rs index 0fa125a3e50..bbe066481a8 100644 --- a/src/test/run-pass/rfc-2126-extern-absolute-paths/basic.rs +++ b/src/test/run-pass/rfc-2126-extern-absolute-paths/basic.rs @@ -9,6 +9,7 @@ // except according to those terms. // aux-build:xcrate.rs +// compile-flags: --edition=2018 -Zunstable-options #![feature(extern_absolute_paths)] diff --git a/src/test/run-pass/rfc-2126-extern-absolute-paths/test.rs b/src/test/run-pass/rfc-2126-extern-absolute-paths/test.rs index 796f652d6b5..ead462cf0d2 100644 --- a/src/test/run-pass/rfc-2126-extern-absolute-paths/test.rs +++ b/src/test/run-pass/rfc-2126-extern-absolute-paths/test.rs @@ -12,7 +12,7 @@ // // Regression test for #47075. -// compile-flags: --test +// compile-flags: --test --edition=2018 -Zunstable-options #![feature(extern_absolute_paths)] diff --git a/src/test/rustdoc/auxiliary/mod-stackoverflow.rs b/src/test/rustdoc/auxiliary/mod-stackoverflow.rs new file mode 100644 index 00000000000..f03593dbee6 --- /dev/null +++ b/src/test/rustdoc/auxiliary/mod-stackoverflow.rs @@ -0,0 +1,21 @@ +// Copyright 2018 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. + +// compile-flags: -Cmetadata=aux + +pub mod tree { + pub use tree; +} + +pub mod tree2 { + pub mod prelude { + pub use tree2; + } +} diff --git a/src/test/rustdoc/mod-stackoverflow.rs b/src/test/rustdoc/mod-stackoverflow.rs new file mode 100644 index 00000000000..1e2f6dbe780 --- /dev/null +++ b/src/test/rustdoc/mod-stackoverflow.rs @@ -0,0 +1,16 @@ +// Copyright 2018 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. + +// aux-build:mod-stackoverflow.rs +// ignore-cross-compile + +extern crate mod_stackoverflow; +pub use mod_stackoverflow::tree; +pub use mod_stackoverflow::tree2; diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.rs b/src/test/ui-fulldeps/unnecessary-extern-crate.rs new file mode 100644 index 00000000000..9d678d91578 --- /dev/null +++ b/src/test/ui-fulldeps/unnecessary-extern-crate.rs @@ -0,0 +1,55 @@ +// Copyright 2015 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. + +#![deny(unnecessary_extern_crate)] +#![feature(alloc, test, libc)] + +extern crate alloc; +//~^ ERROR `extern crate` is unnecessary in the new edition +//~| HELP remove +extern crate alloc as x; +//~^ ERROR `extern crate` is unnecessary in the new edition +//~| HELP use `use` + +#[macro_use] +extern crate test; +pub extern crate test as y; +//~^ ERROR `extern crate` is unnecessary in the new edition +//~| HELP use `pub use` +pub extern crate libc; +//~^ ERROR `extern crate` is unnecessary in the new edition +//~| HELP use `pub use` + + +mod foo { + extern crate alloc; + //~^ ERROR `extern crate` is unnecessary in the new edition + //~| HELP use `use` + extern crate alloc as x; + //~^ ERROR `extern crate` is unnecessary in the new edition + //~| HELP use `use` + pub extern crate test; + //~^ ERROR `extern crate` is unnecessary in the new edition + //~| HELP use `pub use` + pub extern crate test as y; + //~^ ERROR `extern crate` is unnecessary in the new edition + //~| HELP use `pub use` + mod bar { + extern crate alloc; + //~^ ERROR `extern crate` is unnecessary in the new edition + //~| HELP use `use` + extern crate alloc as x; + //~^ ERROR `extern crate` is unnecessary in the new edition + //~| HELP use `use` + } +} + + +fn main() {} diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.stderr b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr new file mode 100644 index 00000000000..7718808be58 --- /dev/null +++ b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr @@ -0,0 +1,68 @@ +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:14:1 + | +LL | extern crate alloc; + | ^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: lint level defined here + --> $DIR/unnecessary-extern-crate.rs:11:9 + | +LL | #![deny(unnecessary_extern_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:17:1 + | +LL | extern crate alloc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x` + +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:23:1 + | +LL | pub extern crate test as y; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y` + +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:26:1 + | +LL | pub extern crate libc; + | ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use libc` + +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:32:5 + | +LL | extern crate alloc; + | ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc` + +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:35:5 + | +LL | extern crate alloc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x` + +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:38:5 + | +LL | pub extern crate test; + | ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test` + +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:41:5 + | +LL | pub extern crate test as y; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y` + +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:45:9 + | +LL | extern crate alloc; + | ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc` + +error: `extern crate` is unnecessary in the new edition + --> $DIR/unnecessary-extern-crate.rs:48:9 + | +LL | extern crate alloc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x` + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/const-eval/extern_fat_pointer.rs b/src/test/ui/const-eval/extern_fat_pointer.rs new file mode 100644 index 00000000000..071311430a8 --- /dev/null +++ b/src/test/ui/const-eval/extern_fat_pointer.rs @@ -0,0 +1,23 @@ +// Copyright 2018 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. + +// compile-pass + +#![feature(extern_types)] + +extern { + type Opaque; +} + +const FOO: *const u8 = &42 as *const _ as *const Opaque as *const u8; + +fn main() { + let _foo = FOO; +} diff --git a/src/test/ui/fn_must_use.stderr b/src/test/ui/fn_must_use.stderr index 5026dac0a94..b5bad22f3dc 100644 --- a/src/test/ui/fn_must_use.stderr +++ b/src/test/ui/fn_must_use.stderr @@ -1,4 +1,4 @@ -warning: unused return value of `need_to_use_this_value` which must be used: it's important +warning: unused return value of `need_to_use_this_value` which must be used --> $DIR/fn_must_use.rs:60:5 | LL | need_to_use_this_value(); //~ WARN unused return value @@ -9,6 +9,7 @@ note: lint level defined here | LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ + = note: it's important warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used --> $DIR/fn_must_use.rs:65:5 @@ -16,11 +17,13 @@ warning: unused return value of `MyStruct::need_to_use_this_method_value` which LL | m.need_to_use_this_method_value(); //~ WARN unused return value | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: unused return value of `EvenNature::is_even` which must be used: no side effects +warning: unused return value of `EvenNature::is_even` which must be used --> $DIR/fn_must_use.rs:66:5 | LL | m.is_even(); // trait method! | ^^^^^^^^^^^^ + | + = note: no side effects warning: unused return value of `std::cmp::PartialEq::eq` which must be used --> $DIR/fn_must_use.rs:72:5 diff --git a/src/tools/cargo b/src/tools/cargo index af3f1cd29bc..9e53ac6e652 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit af3f1cd29bc872b932a13083e531255aab233a7e +Subproject commit 9e53ac6e6525da914cb05a85e5e8eff7b5dca81f diff --git a/src/tools/clippy b/src/tools/clippy index 1742229ebb7..e456241f182 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 1742229ebb7843a65c05ee495d8de5366fcc5567 +Subproject commit e456241f18227c7eb8d78a45daa66c756a9b65e7 diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 7ac3f5b5b25..32980a513f6 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -425,6 +425,15 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) { if testfile.is_dir() { return; } + + let comment = if testfile.to_string_lossy().ends_with(".rs") { + "//" + } else { + "#" + }; + + let comment_with_brace = comment.to_string() + "["; + let rdr = BufReader::new(File::open(testfile).unwrap()); for ln in rdr.lines() { // Assume that any directives will be found before the first @@ -434,10 +443,11 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) { let ln = ln.trim(); if ln.starts_with("fn") || ln.starts_with("mod") { return; - } else if ln.starts_with("//[") { + } else if ln.starts_with(&comment_with_brace) { // A comment like `//[foo]` is specific to revision `foo` if let Some(close_brace) = ln.find(']') { - let lncfg = &ln[3..close_brace]; + let open_brace = ln.find('[').unwrap(); + let lncfg = &ln[open_brace + 1 .. close_brace]; let matches = match cfg { Some(s) => s == &lncfg[..], None => false, @@ -446,11 +456,11 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) { it(ln[(close_brace + 1) ..].trim_left()); } } else { - panic!("malformed condition directive: expected `//[foo]`, found `{}`", - ln) + panic!("malformed condition directive: expected `{}foo]`, found `{}`", + comment_with_brace, ln) } - } else if ln.starts_with("//") { - it(ln[2..].trim_left()); + } else if ln.starts_with(comment) { + it(ln[comment.len() ..].trim_left()); } } return; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index e2b446c99dc..e8b140978b5 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -614,7 +614,12 @@ pub fn is_test(file_name: &OsString) -> bool { } pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn { - let early_props = EarlyProps::from_file(config, &testpaths.file); + + let early_props = if config.mode == Mode::RunMake { + EarlyProps::from_file(config, &testpaths.file.join("Makefile")) + } else { + EarlyProps::from_file(config, &testpaths.file) + }; // The `should-fail` annotation doesn't apply to pretty tests, // since we run the pretty printer across all tests by default. diff --git a/src/tools/miri b/src/tools/miri index f48fed70d44..e0e1bd7ff77 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit f48fed70d4447445b586a35c4ae88683542ffc72 +Subproject commit e0e1bd7ff778e5913b566c9e03224faecc0eb486 diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 8e23519f57e..1539c2e2578 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -86,7 +86,7 @@ def update_latest( .format(tool, os, old, new) elif new < old: changed = True - message += '💔 {} on {}: {} → {} (cc {}).\n' \ + message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \ .format(tool, os, old, new, MAINTAINERS.get(tool)) if changed: diff --git a/src/tools/rls b/src/tools/rls index d2f44357fef..d2ade31a52a 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit d2f44357fef6d61f316abc403e0a5d917f2771c6 +Subproject commit d2ade31a52a417257742de72c5936a8a342a34b5 diff --git a/src/tools/rustfmt b/src/tools/rustfmt index b6cd17f28ae..0f8029f251b 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit b6cd17f28ae314f2484ff05d3ce57652d51c5e85 +Subproject commit 0f8029f251b569a010cb5cfc5a8bff8bf3c949ac diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index fa227436640..022ef57503a 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -51,6 +51,7 @@ macro_rules! tidy_error { pub mod deps; pub mod ui_tests; pub mod unstable_book; +pub mod libcoretest; fn filter_dirs(path: &Path) -> bool { let skip = [ diff --git a/src/tools/tidy/src/libcoretest.rs b/src/tools/tidy/src/libcoretest.rs new file mode 100644 index 00000000000..ef8b55186b1 --- /dev/null +++ b/src/tools/tidy/src/libcoretest.rs @@ -0,0 +1,34 @@ +// Copyright 2018 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. + +//! Tidy check to ensure `#[test]` is not used directly inside `libcore`. +//! +//! `#![no_core]` libraries cannot be tested directly due to duplicating lang +//! item. All tests must be written externally in `libcore/tests`. + +use std::path::Path; +use std::fs::read_to_string; + +pub fn check(path: &Path, bad: &mut bool) { + let libcore_path = path.join("libcore"); + super::walk( + &libcore_path, + &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"), + &mut |subpath| { + if t!(read_to_string(subpath)).contains("#[test]") { + tidy_error!( + bad, + "{} contains #[test]; libcore tests must be placed inside `src/libcore/tests/`", + subpath.display() + ); + } + }, + ); +} diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 24974192795..7b86650823a 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -41,6 +41,7 @@ fn main() { features::check(&path, &mut bad, quiet); pal::check(&path, &mut bad); unstable_book::check(&path, &mut bad); + libcoretest::check(&path, &mut bad); if !args.iter().any(|s| *s == "--no-vendor") { deps::check(&path, &mut bad); }