diff --git a/README.md b/README.md index f387b4be6008f..dbb5bf9ce38d6 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Read ["Installing Rust"] from [The Book]. 3. Build and install: ```sh - $ ./x.py build && sudo ./x.py dist --install + $ ./x.py build && sudo ./x.py install ``` > ***Note:*** Install locations can be adjusted by copying the config file @@ -43,7 +43,7 @@ Read ["Installing Rust"] from [The Book]. > adjusting the `prefix` option under `[install]`. Various other options are > also supported, and are documented in the config file. - When complete, `sudo ./x.py dist --install` will place several programs into + When complete, `sudo ./x.py install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the API-documentation tool. This install does not include [Cargo], Rust's package manager, which you may also want to build. @@ -96,7 +96,7 @@ build. 4. Navigate to Rust's source code (or clone it), then build it: ```sh - $ ./x.py build && ./x.py dist --install + $ ./x.py build && ./x.py install ``` #### MSVC diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 95cca96f7fcc0..0eb6c4c82c4dd 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -314,3 +314,9 @@ # Note that this address should not contain a trailing slash as file names will # be appended to it. #upload-addr = "https://example.com/folder" + +# Whether to build a plain source tarball to upload +# We disable that on Windows not to override the one already uploaded on S3 +# as the one built on Windows will contain backslashes in paths causing problems +# on linux +#src-tarball = true diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 511f2c9e80ec7..94189d7eb92fd 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -30,11 +30,11 @@ use {Build, Compiler, Mode}; use channel; use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe}; -fn pkgname(build: &Build, component: &str) -> String { +pub fn pkgname(build: &Build, component: &str) -> String { if component == "cargo" { format!("{}-{}", component, build.cargo_package_vers()) } else if component == "rls" { - format!("{}-{}", component, build.package_vers(&build.release_num("rls"))) + format!("{}-{}", component, build.rls_package_vers()) } else { assert!(component.starts_with("rust")); format!("{}-{}", component, build.rust_package_vers()) @@ -369,38 +369,7 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { t!(fs::remove_dir_all(&image)); } -const CARGO_VENDOR_VERSION: &'static str = "0.1.4"; - -/// Creates the `rust-src` installer component and the plain source tarball -pub fn rust_src(build: &Build) { - if !build.config.rust_dist_src { - return - } - - println!("Dist src"); - - // Make sure that the root folder of tarball has the correct name - let plain_name = format!("rustc-{}-src", build.rust_package_vers()); - let plain_dst_src = tmpdir(build).join(&plain_name); - let _ = fs::remove_dir_all(&plain_dst_src); - t!(fs::create_dir_all(&plain_dst_src)); - - // This is the set of root paths which will become part of the source package - let src_files = [ - "COPYRIGHT", - "LICENSE-APACHE", - "LICENSE-MIT", - "CONTRIBUTING.md", - "README.md", - "RELEASES.md", - "configure", - "x.py", - ]; - let src_dirs = [ - "man", - "src", - ]; - +fn copy_src_dirs(build: &Build, src_dirs: &[&str], dst_dir: &Path) { let filter_fn = move |path: &Path| { let spath = match path.to_str() { Some(path) => path, @@ -429,60 +398,16 @@ pub fn rust_src(build: &Build) { }; // Copy the directories using our filter - for item in &src_dirs { - let dst = &plain_dst_src.join(item); - t!(fs::create_dir(dst)); + for item in src_dirs { + let dst = &dst_dir.join(item); + t!(fs::create_dir_all(dst)); cp_filtered(&build.src.join(item), dst, &filter_fn); } - // Copy the files normally - for item in &src_files { - copy(&build.src.join(item), &plain_dst_src.join(item)); - } - - // If we're building from git sources, we need to vendor a complete distribution. - if build.src_is_git { - // Get cargo-vendor installed, if it isn't already. - let mut has_cargo_vendor = false; - let mut cmd = Command::new(&build.cargo); - for line in output(cmd.arg("install").arg("--list")).lines() { - has_cargo_vendor |= line.starts_with("cargo-vendor "); - } - if !has_cargo_vendor { - let mut cmd = Command::new(&build.cargo); - cmd.arg("install") - .arg("--force") - .arg("--debug") - .arg("--vers").arg(CARGO_VENDOR_VERSION) - .arg("cargo-vendor") - .env("RUSTC", &build.rustc); - build.run(&mut cmd); - } - - // Vendor all Cargo dependencies - let mut cmd = Command::new(&build.cargo); - cmd.arg("vendor") - .current_dir(&plain_dst_src.join("src")); - build.run(&mut cmd); - } - - // Create the version file - write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); - - // Create plain source tarball - let mut tarball = rust_src_location(build); - tarball.set_extension(""); // strip .gz - tarball.set_extension(""); // strip .tar - if let Some(dir) = tarball.parent() { - t!(fs::create_dir_all(dir)); - } - let mut cmd = rust_installer(build); - cmd.arg("tarball") - .arg("--input").arg(&plain_name) - .arg("--output").arg(&tarball) - .arg("--work-dir=.") - .current_dir(tmpdir(build)); - build.run(&mut cmd); +} +/// Creates the `rust-src` installer component +pub fn rust_src(build: &Build) { + println!("Dist src"); let name = pkgname(build, "rust-src"); let image = tmpdir(build).join(format!("{}-image", name)); @@ -516,11 +441,7 @@ pub fn rust_src(build: &Build) { "src/rustc/libc_shim", ]; - for item in &std_src_dirs { - let dst = &dst_src.join(item); - t!(fs::create_dir_all(dst)); - cp_r(&plain_dst_src.join(item), dst); - } + copy_src_dirs(build, &std_src_dirs[..], &dst_src); // Create source tarball in rust-installer format let mut cmd = rust_installer(build); @@ -537,7 +458,86 @@ pub fn rust_src(build: &Build) { build.run(&mut cmd); t!(fs::remove_dir_all(&image)); - t!(fs::remove_dir_all(&plain_dst_src)); +} + +const CARGO_VENDOR_VERSION: &'static str = "0.1.4"; + +/// Creates the plain source tarball +pub fn plain_source_tarball(build: &Build) { + println!("Create plain source tarball"); + + // Make sure that the root folder of tarball has the correct name + let plain_name = format!("{}-src", pkgname(build, "rustc")); + let plain_dst_src = tmpdir(build).join(&plain_name); + let _ = fs::remove_dir_all(&plain_dst_src); + t!(fs::create_dir_all(&plain_dst_src)); + + // This is the set of root paths which will become part of the source package + let src_files = [ + "COPYRIGHT", + "LICENSE-APACHE", + "LICENSE-MIT", + "CONTRIBUTING.md", + "README.md", + "RELEASES.md", + "configure", + "x.py", + ]; + let src_dirs = [ + "man", + "src", + ]; + + copy_src_dirs(build, &src_dirs[..], &plain_dst_src); + + // Copy the files normally + for item in &src_files { + copy(&build.src.join(item), &plain_dst_src.join(item)); + } + + // Create the version file + write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); + + // If we're building from git sources, we need to vendor a complete distribution. + if build.src_is_git { + // Get cargo-vendor installed, if it isn't already. + let mut has_cargo_vendor = false; + let mut cmd = Command::new(&build.cargo); + for line in output(cmd.arg("install").arg("--list")).lines() { + has_cargo_vendor |= line.starts_with("cargo-vendor "); + } + if !has_cargo_vendor { + let mut cmd = Command::new(&build.cargo); + cmd.arg("install") + .arg("--force") + .arg("--debug") + .arg("--vers").arg(CARGO_VENDOR_VERSION) + .arg("cargo-vendor") + .env("RUSTC", &build.rustc); + build.run(&mut cmd); + } + + // Vendor all Cargo dependencies + let mut cmd = Command::new(&build.cargo); + cmd.arg("vendor") + .current_dir(&plain_dst_src.join("src")); + build.run(&mut cmd); + } + + // Create plain source tarball + let mut tarball = rust_src_location(build); + tarball.set_extension(""); // strip .gz + tarball.set_extension(""); // strip .tar + if let Some(dir) = tarball.parent() { + t!(fs::create_dir_all(dir)); + } + let mut cmd = rust_installer(build); + cmd.arg("tarball") + .arg("--input").arg(&plain_name) + .arg("--output").arg(&tarball) + .arg("--work-dir=.") + .current_dir(tmpdir(build)); + build.run(&mut cmd); } fn install(src: &Path, dstdir: &Path, perms: u32) { diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index a1466d68a135a..fe4e18ab622cd 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -69,7 +69,9 @@ pub enum Subcommand { Clean, Dist { paths: Vec, - install: bool, + }, + Install { + paths: Vec, }, } @@ -85,7 +87,8 @@ Subcommands: bench Build and run some benchmarks doc Build documentation clean Clean out build directories - dist Build and/or install distribution artifacts + dist Build distribution artifacts + install Install distribution artifacts To learn more about a subcommand, run `./x.py -h`"); @@ -125,7 +128,8 @@ To learn more about a subcommand, run `./x.py -h`"); || (s == "bench") || (s == "doc") || (s == "clean") - || (s == "dist")); + || (s == "dist") + || (s == "install")); let subcommand = match possible_subcommands.first() { Some(s) => s, None => { @@ -139,7 +143,6 @@ To learn more about a subcommand, run `./x.py -h`"); match subcommand.as_str() { "test" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); }, "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); }, - "dist" => { opts.optflag("", "install", "run installer as well"); }, _ => { }, }; @@ -281,7 +284,11 @@ Arguments: "dist" => { Subcommand::Dist { paths: paths, - install: matches.opt_present("install"), + } + } + "install" => { + Subcommand::Install { + paths: paths, } } _ => { diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index dce0b1670e181..21e21628dc947 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -19,7 +19,7 @@ use std::path::{Path, PathBuf, Component}; use std::process::Command; use Build; -use dist::{sanitize_sh, tmpdir}; +use dist::{pkgname, sanitize_sh, tmpdir}; pub struct Installer<'a> { build: &'a Build, @@ -29,6 +29,13 @@ pub struct Installer<'a> { bindir: PathBuf, libdir: PathBuf, mandir: PathBuf, + empty_dir: PathBuf, +} + +impl<'a> Drop for Installer<'a> { + fn drop(&mut self) { + t!(fs::remove_dir_all(&self.empty_dir)); + } } impl<'a> Installer<'a> { @@ -61,6 +68,10 @@ impl<'a> Installer<'a> { let libdir = add_destdir(&libdir, &destdir); let mandir = add_destdir(&mandir, &destdir); + let empty_dir = build.out.join("tmp/empty_dir"); + + t!(fs::create_dir_all(&empty_dir)); + Installer { build, prefix, @@ -69,52 +80,49 @@ impl<'a> Installer<'a> { bindir, libdir, mandir, + empty_dir, } } - /// Installs everything. - pub fn install(&self, stage: u32, host: &str) { - let empty_dir = self.build.out.join("tmp/empty_dir"); - t!(fs::create_dir_all(&empty_dir)); - - if self.build.config.docs { - self.install_sh("docs", "rust-docs", &self.build.rust_package_vers(), - stage, Some(host), &empty_dir); - } + pub fn install_docs(&self, stage: u32, host: &str) { + self.install_sh("docs", "rust-docs", stage, Some(host)); + } + pub fn install_std(&self, stage: u32) { for target in self.build.config.target.iter() { - self.install_sh("std", "rust-std", &self.build.rust_package_vers(), - stage, Some(target), &empty_dir); + self.install_sh("std", "rust-std", stage, Some(target)); } + } - if self.build.config.extended { - self.install_sh("cargo", "cargo", &self.build.cargo_package_vers(), - stage, Some(host), &empty_dir); - self.install_sh("rls", "rls", &self.build.rls_package_vers(), - stage, Some(host), &empty_dir); - self.install_sh("analysis", "rust-analysis", &self.build.rust_package_vers(), - stage, Some(host), &empty_dir); - self.install_sh("src", "rust-src", &self.build.rust_package_vers(), - stage, None, &empty_dir); - } + pub fn install_cargo(&self, stage: u32, host: &str) { + self.install_sh("cargo", "cargo", stage, Some(host)); + } - self.install_sh("rustc", "rustc", &self.build.rust_package_vers(), - stage, Some(host), &empty_dir); + pub fn install_rls(&self, stage: u32, host: &str) { + self.install_sh("rls", "rls", stage, Some(host)); + } + + pub fn install_analysis(&self, stage: u32, host: &str) { + self.install_sh("analysis", "rust-analysis", stage, Some(host)); + } - t!(fs::remove_dir_all(&empty_dir)); + pub fn install_src(&self, stage: u32) { + self.install_sh("src", "rust-src", stage, None); + } + pub fn install_rustc(&self, stage: u32, host: &str) { + self.install_sh("rustc", "rustc", stage, Some(host)); } - fn install_sh(&self, package: &str, name: &str, version: &str, - stage: u32, host: Option<&str>, empty_dir: &Path) { + fn install_sh(&self, package: &str, name: &str, stage: u32, host: Option<&str>) { println!("Install {} stage{} ({:?})", package, stage, host); let package_name = if let Some(host) = host { - format!("{}-{}-{}", name, version, host) + format!("{}-{}", pkgname(self.build, name), host) } else { - format!("{}-{}", name, version) + pkgname(self.build, name) }; let mut cmd = Command::new("sh"); - cmd.current_dir(empty_dir) + cmd.current_dir(&self.empty_dir) .arg(sanitize_sh(&tmpdir(self.build).join(&package_name).join("install.sh"))) .arg(format!("--prefix={}", sanitize_sh(&self.prefix))) .arg(format!("--sysconfdir={}", sanitize_sh(&self.sysconfdir))) diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index a5df741e2bfc8..47c792a510b1b 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -69,7 +69,7 @@ distcheck: $(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS) $(Q)$(BOOTSTRAP) test distcheck $(BOOTSTRAP_ARGS) install: - $(Q)$(BOOTSTRAP) dist --install $(BOOTSTRAP_ARGS) + $(Q)$(BOOTSTRAP) install $(BOOTSTRAP_ARGS) tidy: $(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS) prepare: diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 57915446e1d1a..8e65fbd40b460 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -492,7 +492,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .host(true) .run(move |s| check::docs(build, &s.compiler())); rules.test("check-distcheck", "distcheck") - .dep(|s| s.name("dist-src")) + .dep(|s| s.name("dist-plain-source-tarball")) .run(move |_| check::distcheck(build)); rules.build("test-helpers", "src/rt/rust_test_helpers.c") @@ -734,6 +734,13 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { dist::mingw(build, s.target) } }); + rules.dist("dist-plain-source-tarball", "src") + .default(build.config.rust_dist_src) + .host(true) + .only_build(true) + .only_host_build(true) + .dep(move |s| tool_rust_installer(build, s)) + .run(move |_| dist::plain_source_tarball(build)); rules.dist("dist-src", "src") .default(true) .host(true) @@ -759,9 +766,6 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(|s| s.name("tool-rls")) .dep(move |s| tool_rust_installer(build, s)) .run(move |s| dist::rls(build, s.stage, s.target)); - rules.dist("install", "path/to/nowhere") - .dep(|s| s.name("default:dist")) - .run(move |s| install::Installer::new(build).install(s.stage, s.target)); rules.dist("dist-cargo", "cargo") .host(true) .only_host_build(true) @@ -789,6 +793,47 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0)) .run(move |_| dist::hash_and_sign(build)); + rules.install("install-docs", "src/doc") + .default(build.config.docs) + .only_host_build(true) + .dep(|s| s.name("dist-docs")) + .run(move |s| install::Installer::new(build).install_docs(s.stage, s.target)); + rules.install("install-std", "src/libstd") + .default(true) + .only_host_build(true) + .dep(|s| s.name("dist-std")) + .run(move |s| install::Installer::new(build).install_std(s.stage)); + rules.install("install-cargo", "cargo") + .default(build.config.extended) + .host(true) + .only_host_build(true) + .dep(|s| s.name("dist-cargo")) + .run(move |s| install::Installer::new(build).install_cargo(s.stage, s.target)); + rules.install("install-rls", "rls") + .default(build.config.extended) + .host(true) + .only_host_build(true) + .dep(|s| s.name("dist-rls")) + .run(move |s| install::Installer::new(build).install_rls(s.stage, s.target)); + rules.install("install-analysis", "analysis") + .default(build.config.extended) + .only_host_build(true) + .dep(|s| s.name("dist-analysis")) + .run(move |s| install::Installer::new(build).install_analysis(s.stage, s.target)); + rules.install("install-src", "src") + .default(build.config.extended) + .host(true) + .only_build(true) + .only_host_build(true) + .dep(|s| s.name("dist-src")) + .run(move |s| install::Installer::new(build).install_src(s.stage)); + rules.install("install-rustc", "src/librustc") + .default(true) + .host(true) + .only_host_build(true) + .dep(|s| s.name("dist-rustc")) + .run(move |s| install::Installer::new(build).install_rustc(s.stage, s.target)); + rules.verify(); return rules; @@ -902,6 +947,7 @@ enum Kind { Bench, Dist, Doc, + Install, } impl<'a> Rule<'a> { @@ -1033,6 +1079,12 @@ impl<'a> Rules<'a> { self.rule(name, path, Kind::Dist) } + /// Same as `build`, but for `Kind::Install`. + fn install<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Install) + } + fn rule<'b>(&'b mut self, name: &'a str, path: &'a str, @@ -1073,6 +1125,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? "test" => Kind::Test, "bench" => Kind::Bench, "dist" => Kind::Dist, + "install" => Kind::Install, _ => return None, }; let rules = self.rules.values().filter(|r| r.kind == kind); @@ -1122,13 +1175,8 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), Subcommand::Test { ref paths, test_args: _ } => (Kind::Test, &paths[..]), Subcommand::Bench { ref paths, test_args: _ } => (Kind::Bench, &paths[..]), - Subcommand::Dist { ref paths, install } => { - if install { - return vec![self.sbuild.name("install")] - } else { - (Kind::Dist, &paths[..]) - } - } + Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]), + Subcommand::Install { ref paths } => (Kind::Install, &paths[..]), Subcommand::Clean => panic!(), }; @@ -1347,10 +1395,6 @@ mod tests { use config::Config; use flags::Flags; - macro_rules! a { - ($($a:expr),*) => (vec![$($a.to_string()),*]) - } - fn build(args: &[&str], extra_host: &[&str], extra_target: &[&str]) -> Build { diff --git a/src/doc/unstable-book/src/library-features/step-trait.md b/src/doc/unstable-book/src/library-features/step-trait.md index e53ca13f7b6f5..56050c20c6915 100644 --- a/src/doc/unstable-book/src/library-features/step-trait.md +++ b/src/doc/unstable-book/src/library-features/step-trait.md @@ -1,7 +1,7 @@ # `step_trait` -The tracking issue for this feature is: [#27741] +The tracking issue for this feature is: [#42168] -[#27741]: https://github.com/rust-lang/rust/issues/27741 +[#42168]: https://github.com/rust-lang/rust/issues/42168 ------------------------ diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index f9b818f5bff35..54919a414786d 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -309,7 +309,7 @@ pub use self::iterator::Iterator; #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] pub use self::range::Step; #[unstable(feature = "step_by", reason = "recent addition", issue = "27741")] diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index bd831d638c0c4..8d370f9675f3e 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -20,7 +20,7 @@ use super::{FusedIterator, TrustedLen}; /// two `Step` objects. #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] pub trait Step: PartialOrd + Sized { /// Steps `self` if possible. fn step(&self, by: &Self) -> Option; @@ -55,7 +55,7 @@ macro_rules! step_impl_unsigned { ($($t:ty)*) => ($( #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] impl Step for $t { #[inline] fn step(&self, by: &$t) -> Option<$t> { @@ -115,7 +115,7 @@ macro_rules! step_impl_signed { ($($t:ty)*) => ($( #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] impl Step for $t { #[inline] fn step(&self, by: &$t) -> Option<$t> { @@ -187,7 +187,7 @@ macro_rules! step_impl_no_between { ($($t:ty)*) => ($( #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] impl Step for $t { #[inline] fn step(&self, by: &$t) -> Option<$t> { diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index fc3af096b1838..4fb1f1757bbf7 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -153,6 +153,13 @@ use marker::Unsize; /// The `Drop` trait is used to run some code when a value goes out of scope. /// This is sometimes called a 'destructor'. /// +/// When a value goes out of scope, if it implements this trait, it will have +/// its `drop` method called. Then any fields the value contains will also +/// be dropped recursively. +/// +/// Because of the recursive dropping, you do not need to implement this trait +/// unless your type needs its own destructor logic. +/// /// # Examples /// /// A trivial implementation of `Drop`. The `drop` method is called when `_x` @@ -171,6 +178,43 @@ use marker::Unsize; /// let _x = HasDrop; /// } /// ``` +/// +/// Showing the recursive nature of `Drop`. When `outer` goes out of scope, the +/// `drop` method will be called first for `Outer`, then for `Inner`. Therefore +/// `main` prints `Dropping Outer!` and then `Dropping Inner!`. +/// +/// ``` +/// struct Inner; +/// struct Outer(Inner); +/// +/// impl Drop for Inner { +/// fn drop(&mut self) { +/// println!("Dropping Inner!"); +/// } +/// } +/// +/// impl Drop for Outer { +/// fn drop(&mut self) { +/// println!("Dropping Outer!"); +/// } +/// } +/// +/// fn main() { +/// let _x = Outer(Inner); +/// } +/// ``` +/// +/// Because variables are dropped in the reverse order they are declared, +/// `main` will print `Declared second!` and then `Declared first!`. +/// +/// ``` +/// struct PrintOnDrop(&'static str); +/// +/// fn main() { +/// let _first = PrintOnDrop("Declared first!"); +/// let _second = PrintOnDrop("Declared second!"); +/// } +/// ``` #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Drop { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index f7c20542cbf2e..6ee5f24e99641 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1002,7 +1002,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { .span_suggestion(err.span, &format!("to force the closure to take ownership of {} \ (and any other referenced variables), \ - use the `move` keyword, as shown:", + use the `move` keyword", cmt_path_or_string), suggestion) .emit(); diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 861880aa265ec..07c6fa236661d 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -203,6 +203,18 @@ impl Diagnostic { /// Prints out a message with a suggested edit of the code. /// + /// In case of short messages and a simple suggestion, + /// rustc displays it as a label like + /// + /// "try adding parentheses: `(tup.0).1`" + /// + /// The message + /// * should not end in any punctuation (a `:` is added automatically) + /// * should not be a question + /// * should not contain any parts like "the following", "as shown" + /// * may look like "to do xyz, use" or "to do xyz, use abc" + /// * may contain a name of a function, variable or type, but not whole expressions + /// /// See `diagnostic::CodeSuggestion` for more information. pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self { self.suggestions.push(CodeSuggestion { diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index a9645f9ab7bb2..24e5040f2a234 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -46,7 +46,7 @@ impl Emitter for EmitterWriter { // don't display multiline suggestions as labels sugg.substitution_parts[0].substitutions[0].find('\n').is_none() { let substitution = &sugg.substitution_parts[0].substitutions[0]; - let msg = format!("help: {} `{}`", sugg.msg, substitution); + let msg = format!("help: {}: `{}`", sugg.msg, substitution); primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg); } else { // if there are multiple suggestions, print them all in full diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6ea666e21dcdd..d37cb48b8c1f9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2307,13 +2307,15 @@ impl<'a> Resolver<'a> { .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::>(); enum_candidates.sort(); for (sp, variant_path, enum_path) in enum_candidates { - let msg = format!("there is an enum variant `{}`, did you mean to use `{}`?", - variant_path, - enum_path); if sp == DUMMY_SP { + let msg = format!("there is an enum variant `{}`, \ + try using `{}`?", + variant_path, + enum_path); err.help(&msg); } else { - err.span_help(sp, &msg); + err.span_suggestion(span, "you can try using the variant's enum", + enum_path); } } } @@ -2322,18 +2324,20 @@ impl<'a> Resolver<'a> { let self_is_available = this.self_value_is_available(path[0].ctxt, span); match candidate { AssocSuggestion::Field => { - err.span_label(span, format!("did you mean `self.{}`?", path_str)); + err.span_suggestion(span, "try", + format!("self.{}", path_str)); if !self_is_available { err.span_label(span, format!("`self` value is only available in \ methods with `self` parameter")); } } AssocSuggestion::MethodWithSelf if self_is_available => { - err.span_label(span, format!("did you mean `self.{}(...)`?", - path_str)); + err.span_suggestion(span, "try", + format!("self.{}", path_str)); } AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => { - err.span_label(span, format!("did you mean `Self::{}`?", path_str)); + err.span_suggestion(span, "try", + format!("Self::{}", path_str)); } } return err; diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 231d30cd2a22d..96783ba0cde64 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -649,9 +649,10 @@ impl<'a> Resolver<'a> { if let Some(suggestion) = suggestion { if suggestion != name { if let MacroKind::Bang = kind { - err.help(&format!("did you mean `{}!`?", suggestion)); + err.span_suggestion(span, "you could try the macro", + format!("{}!", suggestion)); } else { - err.help(&format!("did you mean `{}`?", suggestion)); + err.span_suggestion(span, "try", suggestion.to_string()); } } else { err.help("have you added the `#[macro_use]` on the module/import?"); diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 72ce7d3b5ed71..408837d0e82e3 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -276,7 +276,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match fcx.tcx.sess.codemap().span_to_snippet(self.cast_span) { Ok(s) => { err.span_suggestion(self.cast_span, - "try casting to a reference instead:", + "try casting to a reference instead", format!("&{}{}", mtstr, s)); } Err(_) => { @@ -295,7 +295,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { match fcx.tcx.sess.codemap().span_to_snippet(self.cast_span) { Ok(s) => { err.span_suggestion(self.cast_span, - "try casting to a `Box` instead:", + "try casting to a `Box` instead", format!("Box<{}>", s)); } Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr), diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 59cb61d9b97f0..2c33bcb3a050a 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -290,7 +290,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { from a string reference. String concatenation \ appends the string on the right to the string \ on the left and may require reallocation. This \ - requires ownership of the string on the left."), suggestion); + requires ownership of the string on the left"), suggestion); is_string_addition = true; } diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index acff7faf8a7d0..06fd838ea06d9 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -35,6 +35,8 @@ fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { use sys_common; use sys_common::thread_info; use thread::Thread; + #[cfg(not(feature = "backtrace"))] + use mem; sys::init(); @@ -53,9 +55,12 @@ fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { sys::args::init(argc, argv); // Let's run some code! + #[cfg(feature = "backtrace")] let res = panic::catch_unwind(|| { ::sys_common::backtrace::__rust_begin_short_backtrace(main) }); + #[cfg(not(feature = "backtrace"))] + let res = panic::catch_unwind(mem::transmute::<_, fn()>(main)); sys_common::cleanup(); res.is_err() }; diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs index abdd9ace795f4..cacd84e21025f 100644 --- a/src/libstd/sys/redox/thread_local.rs +++ b/src/libstd/sys/redox/thread_local.rs @@ -64,3 +64,8 @@ pub unsafe fn set(key: Key, value: *mut u8) { pub unsafe fn destroy(key: Key) { keys().remove(&key); } + +#[inline] +pub fn requires_synchronized_create() -> bool { + false +} diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 154406a1d8bd7..75717abb4ad28 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -359,9 +359,12 @@ impl Builder { } unsafe { thread_info::set(imp::guard::current(), their_thread); + #[cfg(feature = "backtrace")] let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { ::sys_common::backtrace::__rust_begin_short_backtrace(f) })); + #[cfg(not(feature = "backtrace"))] + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f)); *their_packet.get() = Some(try_result); } }; diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index 4df23da3c9ce3..83a164bdb9693 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -238,7 +238,7 @@ pub fn check_for_substitution<'a>(reader: &StringReader<'a>, match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) { Some(&(ascii_char, ascii_name)) => { let msg = - format!("unicode character '{}' ({}) looks much like '{}' ({}), but it's not", + format!("unicode character '{}' ({}) looks like '{}' ({}), but it's not", ch, u_name, ascii_char, ascii_name); err.span_help(span, &msg); }, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4741f896d3cc0..963942a016f73 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1507,7 +1507,7 @@ impl<'a> Parser<'a> { s.print_bounds(" +", &bounds)?; s.pclose() }); - err.span_suggestion(sum_span, "try adding parentheses:", sum_with_parens); + err.span_suggestion(sum_span, "try adding parentheses", sum_with_parens); } TyKind::Ptr(..) | TyKind::BareFn(..) => { err.span_label(sum_span, "perhaps you forgot parentheses?"); @@ -5180,7 +5180,7 @@ impl<'a> Parser<'a> { `pub(in path::to::module)`: visible only on the specified path"##; let path = self.parse_path(PathStyle::Mod)?; let path_span = self.prev_span; - let help_msg = format!("make this visible only to module `{}` with `in`:", path); + let help_msg = format!("make this visible only to module `{}` with `in`", path); self.expect(&token::CloseDelim(token::Paren))?; // `)` let mut err = self.span_fatal_help(path_span, msg, suggestion); err.span_suggestion(path_span, &help_msg, format!("in {}", path)); diff --git a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-proc_macro.rs b/src/test/compile-fail-fulldeps/proc-macro/feature-gate-proc_macro.rs index 7e32800e0f9b8..eeede4b8aa13c 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-proc_macro.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/feature-gate-proc_macro.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:attr_proc_macro.rs -// gate-test-proc_macro #![feature(use_extern_macros)] extern crate attr_proc_macro; @@ -21,4 +20,4 @@ struct Foo; fn main() { let _ = Foo; -} \ No newline at end of file +} diff --git a/src/test/compile-fail/feature-gate-global_asm.rs b/src/test/compile-fail/feature-gate-global_asm.rs index 0560abb6af498..77f61ba47b005 100644 --- a/src/test/compile-fail/feature-gate-global_asm.rs +++ b/src/test/compile-fail/feature-gate-global_asm.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-global_asm - global_asm!(""); //~ ERROR `global_asm!` is not stable fn main() {} diff --git a/src/test/parse-fail/unicode-chars.rs b/src/test/parse-fail/unicode-chars.rs index adfaf62b5d3cc..1bdeb121a55d5 100644 --- a/src/test/parse-fail/unicode-chars.rs +++ b/src/test/parse-fail/unicode-chars.rs @@ -9,10 +9,9 @@ // except according to those terms. // compile-flags: -Z parse-only -// ignore-tidy-linelength fn main() { let y = 0; //~^ ERROR unknown start of token: \u{37e} - //~^^ HELP unicode character ';' (Greek Question Mark) looks much like ';' (Semicolon), but it's not + //~^^ HELP unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it's not } diff --git a/src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs b/src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs new file mode 100644 index 0000000000000..db0c19e96f821 --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/attr_proc_macro.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +// force-host +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs b/src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs new file mode 100644 index 0000000000000..89ac11b309d75 --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/bang_proc_macro.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +// force-host +// no-prefer-dynamic +#![feature(proc_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn bang_proc_macro(input: TokenStream) -> TokenStream { + input +} diff --git a/src/test/ui-fulldeps/auxiliary/derive-clona.rs b/src/test/ui-fulldeps/auxiliary/derive-clona.rs new file mode 100644 index 0000000000000..719fbdb15ef2a --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/derive-clona.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Clona)] +pub fn derive_clonea(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/ui-fulldeps/auxiliary/derive-foo.rs b/src/test/ui-fulldeps/auxiliary/derive-foo.rs new file mode 100644 index 0000000000000..64dcf72ba2029 --- /dev/null +++ b/src/test/ui-fulldeps/auxiliary/derive-foo.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(FooWithLongName)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs b/src/test/ui-fulldeps/resolve-error.rs similarity index 86% rename from src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs rename to src/test/ui-fulldeps/resolve-error.rs index ddd8631f02e62..8efcd8081feac 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs +++ b/src/test/ui-fulldeps/resolve-error.rs @@ -36,12 +36,10 @@ macro_rules! attr_proc_mac { #[derive(FooWithLongNan)] //~^ ERROR cannot find derive macro `FooWithLongNan` in this scope -//~^^ HELP did you mean `FooWithLongName`? struct Foo; #[attr_proc_macra] //~^ ERROR cannot find attribute macro `attr_proc_macra` in this scope -//~^^ HELP did you mean `attr_proc_macro`? struct Bar; #[FooWithLongNan] @@ -50,12 +48,10 @@ struct Asdf; #[derive(Dlone)] //~^ ERROR cannot find derive macro `Dlone` in this scope -//~^^ HELP did you mean `Clone`? struct A; #[derive(Dlona)] //~^ ERROR cannot find derive macro `Dlona` in this scope -//~^^ HELP did you mean `Clona`? struct B; #[derive(attr_proc_macra)] @@ -65,16 +61,13 @@ struct C; fn main() { FooWithLongNama!(); //~^ ERROR cannot find macro `FooWithLongNama!` in this scope - //~^^ HELP did you mean `FooWithLongNam!`? attr_proc_macra!(); //~^ ERROR cannot find macro `attr_proc_macra!` in this scope - //~^^ HELP did you mean `attr_proc_mac!`? Dlona!(); //~^ ERROR cannot find macro `Dlona!` in this scope bang_proc_macrp!(); //~^ ERROR cannot find macro `bang_proc_macrp!` in this scope - //~^^ HELP did you mean `bang_proc_macro!`? } diff --git a/src/test/ui-fulldeps/resolve-error.stderr b/src/test/ui-fulldeps/resolve-error.stderr new file mode 100644 index 0000000000000..be7ebae70adf5 --- /dev/null +++ b/src/test/ui-fulldeps/resolve-error.stderr @@ -0,0 +1,62 @@ +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:37:10 + | +37 | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: try: `FooWithLongName` + +error: cannot find attribute macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:41:3 + | +41 | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro` + +error: cannot find attribute macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:45:3 + | +45 | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:49:10 + | +49 | #[derive(Dlone)] + | ^^^^^ help: try: `Clone` + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:53:10 + | +53 | #[derive(Dlona)] + | ^^^^^ help: try: `Clona` + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:57:10 + | +57 | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find macro `FooWithLongNama!` in this scope + --> $DIR/resolve-error.rs:62:5 + | +62 | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam!` + +error: cannot find macro `attr_proc_macra!` in this scope + --> $DIR/resolve-error.rs:65:5 + | +65 | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac!` + +error: cannot find macro `Dlona!` in this scope + --> $DIR/resolve-error.rs:68:5 + | +68 | Dlona!(); + | ^^^^^ + +error: cannot find macro `bang_proc_macrp!` in this scope + --> $DIR/resolve-error.rs:71:5 + | +71 | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro!` + +error: aborting due to 10 previous errors + diff --git a/src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs b/src/test/ui/cast-to-unsized-trait-object-suggestion.rs similarity index 77% rename from src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs rename to src/test/ui/cast-to-unsized-trait-object-suggestion.rs index d18746cdf0ba5..3693fd11d4837 100644 --- a/src/test/compile-fail/cast-to-unsized-trait-object-suggestion.rs +++ b/src/test/ui/cast-to-unsized-trait-object-suggestion.rs @@ -11,10 +11,6 @@ fn main() { &1 as Send; //~^ ERROR cast to unsized type - //~| HELP try casting to a reference instead: - //~| SUGGESTION &1 as &Send; Box::new(1) as Send; //~^ ERROR cast to unsized type - //~| HELP try casting to a `Box` instead: - //~| SUGGESTION Box::new(1) as Box; } diff --git a/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr b/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr new file mode 100644 index 0000000000000..6aa062e42238a --- /dev/null +++ b/src/test/ui/cast-to-unsized-trait-object-suggestion.stderr @@ -0,0 +1,18 @@ +error: cast to unsized type: `&{integer}` as `std::marker::Send` + --> $DIR/cast-to-unsized-trait-object-suggestion.rs:12:5 + | +12 | &1 as Send; + | ^^^^^^---- + | | + | help: try casting to a reference instead: `&Send` + +error: cast to unsized type: `std::boxed::Box<{integer}>` as `std::marker::Send` + --> $DIR/cast-to-unsized-trait-object-suggestion.rs:14:5 + | +14 | Box::new(1) as Send; + | ^^^^^^^^^^^^^^^---- + | | + | help: try casting to a `Box` instead: `Box` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/issue-35675.rs b/src/test/ui/issue-35675.rs similarity index 100% rename from src/test/compile-fail/issue-35675.rs rename to src/test/ui/issue-35675.rs diff --git a/src/test/ui/issue-35675.stderr b/src/test/ui/issue-35675.stderr new file mode 100644 index 0000000000000..c6738e0964a1a --- /dev/null +++ b/src/test/ui/issue-35675.stderr @@ -0,0 +1,65 @@ +error[E0412]: cannot find type `Apple` in this scope + --> $DIR/issue-35675.rs:20:29 + | +20 | fn should_return_fruit() -> Apple { + | ^^^^^ + | | + | not found in this scope + | help: you can try using the variant's enum: `Fruit` + +error[E0425]: cannot find function `Apple` in this scope + --> $DIR/issue-35675.rs:23:5 + | +23 | Apple(5) + | ^^^^^ not found in this scope + | +help: possible candidate is found in another module, you can import it into scope + | use Fruit::Apple; + +error[E0573]: expected type, found variant `Fruit::Apple` + --> $DIR/issue-35675.rs:28:33 + | +28 | fn should_return_fruit_too() -> Fruit::Apple { + | ^^^^^^^^^^^^ + | | + | not a type + | help: you can try using the variant's enum: `Fruit` + +error[E0425]: cannot find function `Apple` in this scope + --> $DIR/issue-35675.rs:31:5 + | +31 | Apple(5) + | ^^^^^ not found in this scope + | +help: possible candidate is found in another module, you can import it into scope + | use Fruit::Apple; + +error[E0573]: expected type, found variant `Ok` + --> $DIR/issue-35675.rs:36:13 + | +36 | fn foo() -> Ok { + | ^^ not a type + | + = help: there is an enum variant `std::prelude::v1::Ok`, try using `std::prelude::v1`? + = help: there is an enum variant `std::prelude::v1::Result::Ok`, try using `std::prelude::v1::Result`? + +error[E0412]: cannot find type `Variant3` in this scope + --> $DIR/issue-35675.rs:44:13 + | +44 | fn bar() -> Variant3 { + | ^^^^^^^^ + | | + | not found in this scope + | help: you can try using the variant's enum: `x::Enum` + +error[E0573]: expected type, found variant `Some` + --> $DIR/issue-35675.rs:49:13 + | +49 | fn qux() -> Some { + | ^^^^ not a type + | + = help: there is an enum variant `std::option::Option::Some`, try using `std::option::Option`? + = help: there is an enum variant `std::prelude::v1::Some`, try using `std::prelude::v1`? + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr index de110ac12b703..26f150811b7db 100644 --- a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr +++ b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of indexed content 19 | let e = f.v[0]; | ^^^^^^ | | - | help: consider using a reference instead `&f.v[0]` + | help: consider using a reference instead: `&f.v[0]` | cannot move out of indexed content error: aborting due to previous error diff --git a/src/test/compile-fail/macro-name-typo.rs b/src/test/ui/macros/macro-name-typo.rs similarity index 93% rename from src/test/compile-fail/macro-name-typo.rs rename to src/test/ui/macros/macro-name-typo.rs index 4840205fee4c3..7489d92dc2411 100644 --- a/src/test/compile-fail/macro-name-typo.rs +++ b/src/test/ui/macros/macro-name-typo.rs @@ -11,5 +11,4 @@ fn main() { printlx!("oh noes!"); //~^ ERROR cannot find macro - //~^^ HELP did you mean `println!`? } diff --git a/src/test/ui/macros/macro-name-typo.stderr b/src/test/ui/macros/macro-name-typo.stderr new file mode 100644 index 0000000000000..7c83250fe8ada --- /dev/null +++ b/src/test/ui/macros/macro-name-typo.stderr @@ -0,0 +1,8 @@ +error: cannot find macro `printlx!` in this scope + --> $DIR/macro-name-typo.rs:12:5 + | +12 | printlx!("oh noes!"); + | ^^^^^^^ help: you could try the macro: `println!` + +error: aborting due to previous error + diff --git a/src/test/compile-fail/macro_undefined.rs b/src/test/ui/macros/macro_undefined.rs similarity index 87% rename from src/test/compile-fail/macro_undefined.rs rename to src/test/ui/macros/macro_undefined.rs index 00c8d44f30602..ac3c356b54999 100644 --- a/src/test/compile-fail/macro_undefined.rs +++ b/src/test/ui/macros/macro_undefined.rs @@ -20,8 +20,6 @@ mod m { fn main() { k!(); //~^ ERROR cannot find macro `k!` in this scope - //~^^ HELP did you mean `kl!`? kl!(); //~^ ERROR cannot find macro `kl!` in this scope - //~^^ HELP have you added the `#[macro_use]` on the module/import? } diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr new file mode 100644 index 0000000000000..b88829c2e23e0 --- /dev/null +++ b/src/test/ui/macros/macro_undefined.stderr @@ -0,0 +1,16 @@ +error: cannot find macro `kl!` in this scope + --> $DIR/macro_undefined.rs:23:5 + | +23 | kl!(); + | ^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `k!` in this scope + --> $DIR/macro_undefined.rs:21:5 + | +21 | k!(); + | ^ help: you could try the macro: `kl!` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/resolve-error.stderr b/src/test/ui/resolve-error.stderr new file mode 100644 index 0000000000000..be7ebae70adf5 --- /dev/null +++ b/src/test/ui/resolve-error.stderr @@ -0,0 +1,62 @@ +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:37:10 + | +37 | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: try: `FooWithLongName` + +error: cannot find attribute macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:41:3 + | +41 | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro` + +error: cannot find attribute macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:45:3 + | +45 | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:49:10 + | +49 | #[derive(Dlone)] + | ^^^^^ help: try: `Clone` + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:53:10 + | +53 | #[derive(Dlona)] + | ^^^^^ help: try: `Clona` + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:57:10 + | +57 | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find macro `FooWithLongNama!` in this scope + --> $DIR/resolve-error.rs:62:5 + | +62 | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam!` + +error: cannot find macro `attr_proc_macra!` in this scope + --> $DIR/resolve-error.rs:65:5 + | +65 | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac!` + +error: cannot find macro `Dlona!` in this scope + --> $DIR/resolve-error.rs:68:5 + | +68 | Dlona!(); + | ^^^^^ + +error: cannot find macro `bang_proc_macrp!` in this scope + --> $DIR/resolve-error.rs:71:5 + | +71 | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro!` + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr index 18eb2fabdacb5..3b5f3e4c36a04 100644 --- a/src/test/ui/resolve/issue-14254.stderr +++ b/src/test/ui/resolve/issue-14254.stderr @@ -2,7 +2,7 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:29:9 | 29 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:32:9 @@ -14,19 +14,19 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:40:9 | 40 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:43:9 | 43 | x; - | ^ did you mean `self.x`? + | ^ help: try: `self.x` error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:46:9 | 46 | y; - | ^ did you mean `self.y`? + | ^ help: try: `self.y` error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:49:9 @@ -38,7 +38,7 @@ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:52:9 | 52 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:55:9 @@ -50,19 +50,19 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:63:9 | 63 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `x` in this scope --> $DIR/issue-14254.rs:66:9 | 66 | x; - | ^ did you mean `self.x`? + | ^ help: try: `self.x` error[E0425]: cannot find value `y` in this scope --> $DIR/issue-14254.rs:69:9 | 69 | y; - | ^ did you mean `self.y`? + | ^ help: try: `self.y` error[E0425]: cannot find value `a` in this scope --> $DIR/issue-14254.rs:72:9 @@ -74,7 +74,7 @@ error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:75:9 | 75 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find value `b` in this scope --> $DIR/issue-14254.rs:78:9 @@ -86,61 +86,61 @@ error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:86:9 | 86 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:89:9 | 89 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:97:9 | 97 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:100:9 | 100 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:108:9 | 108 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:111:9 | 111 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:119:9 | 119 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:122:9 | 122 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error[E0425]: cannot find function `baz` in this scope --> $DIR/issue-14254.rs:130:9 | 130 | baz(); - | ^^^ did you mean `self.baz(...)`? + | ^^^ help: try: `self.baz` error[E0425]: cannot find value `bah` in this scope --> $DIR/issue-14254.rs:133:9 | 133 | bah; - | ^^^ did you mean `Self::bah`? + | ^^^ help: try: `Self::bah` error: main function not found diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 039887d8da65f..9c683f4418972 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -8,13 +8,13 @@ error[E0425]: cannot find function `clone` in this scope --> $DIR/issue-2356.rs:35:5 | 35 | clone(); - | ^^^^^ did you mean `self.clone(...)`? + | ^^^^^ help: try: `self.clone` error[E0425]: cannot find function `default` in this scope --> $DIR/issue-2356.rs:43:5 | 43 | default(); - | ^^^^^^^ did you mean `Self::default`? + | ^^^^^^^ help: try: `Self::default` error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:52:5 @@ -22,14 +22,14 @@ error[E0425]: cannot find value `whiskers` in this scope 52 | whiskers -= other; | ^^^^^^^^ | | - | did you mean `self.whiskers`? + | help: try: `self.whiskers` | `self` value is only available in methods with `self` parameter error[E0425]: cannot find function `shave` in this scope --> $DIR/issue-2356.rs:57:5 | 57 | shave(4); - | ^^^^^ did you mean `Self::shave`? + | ^^^^^ help: try: `Self::shave` error[E0425]: cannot find function `purr` in this scope --> $DIR/issue-2356.rs:60:5 @@ -83,7 +83,7 @@ error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:104:5 | 104 | whiskers = 0; - | ^^^^^^^^ did you mean `self.whiskers`? + | ^^^^^^^^ help: try: `self.whiskers` error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:110:5 @@ -91,7 +91,7 @@ error[E0425]: cannot find value `whiskers` in this scope 110 | whiskers = 4; | ^^^^^^^^ | | - | did you mean `self.whiskers`? + | help: try: `self.whiskers` | `self` value is only available in methods with `self` parameter error[E0425]: cannot find function `purr_louder` in this scope diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr index 7975c168de7d4..77aa545e2ad6b 100644 --- a/src/test/ui/resolve/resolve-assoc-suggestions.stderr +++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr @@ -14,13 +14,13 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-assoc-suggestions.rs:32:9 | 32 | field; - | ^^^^^ did you mean `self.field`? + | ^^^^^ help: try: `self.field` error[E0412]: cannot find type `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:36:16 | 36 | let _: Type; - | ^^^^ did you mean `Self::Type`? + | ^^^^ help: try: `Self::Type` error[E0531]: cannot find tuple struct/variant `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:39:13 @@ -50,7 +50,7 @@ error[E0425]: cannot find value `method` in this scope --> $DIR/resolve-assoc-suggestions.rs:52:9 | 52 | method; - | ^^^^^^ did you mean `self.method(...)`? + | ^^^^^^ help: try: `self.method` error: aborting due to 9 previous errors diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr index e7df8140bc577..3e1b075679a50 100644 --- a/src/test/ui/resolve/resolve-speculative-adjustment.stderr +++ b/src/test/ui/resolve/resolve-speculative-adjustment.stderr @@ -14,13 +14,13 @@ error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-speculative-adjustment.rs:35:9 | 35 | field; - | ^^^^^ did you mean `self.field`? + | ^^^^^ help: try: `self.field` error[E0425]: cannot find function `method` in this scope --> $DIR/resolve-speculative-adjustment.rs:38:9 | 38 | method(); - | ^^^^^^ did you mean `self.method(...)`? + | ^^^^^^ help: try: `self.method` error: aborting due to 4 previous errors diff --git a/src/test/ui/resolve/unresolved_static_type_field.stderr b/src/test/ui/resolve/unresolved_static_type_field.stderr index 5fbaf66e014af..e598851e3628e 100644 --- a/src/test/ui/resolve/unresolved_static_type_field.stderr +++ b/src/test/ui/resolve/unresolved_static_type_field.stderr @@ -4,7 +4,7 @@ error[E0425]: cannot find value `cx` in this scope 19 | f(cx); | ^^ | | - | did you mean `self.cx`? + | help: try: `self.cx` | `self` value is only available in methods with `self` parameter error: aborting due to previous error diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index cd3a41b037c79..e8b3c6629bd53 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -4,7 +4,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&'static str` 12 | let x = "Hello " + "World!"; | ^^^^^^^^^^^^^^^^^^^ `+` can't be used to concatenate two `&str` strings | -help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left. +help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left | let x = "Hello ".to_owned() + "World!"; error[E0369]: binary operation `+` cannot be applied to type `World` diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr index 91e629c44b073..48db5026c9e51 100644 --- a/src/test/ui/span/suggestion-non-ascii.stderr +++ b/src/test/ui/span/suggestion-non-ascii.stderr @@ -2,7 +2,7 @@ error: cannot index a value of type `({integer},)` --> $DIR/suggestion-non-ascii.rs:14:21 | 14 | println!("☃{}", tup[0]); - | ^^^^^^ help: to access tuple elements, use `tup.0` + | ^^^^^^ help: to access tuple elements, use: `tup.0` error: aborting due to previous error diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr index 8a121b1453662..4b1be26c86b0e 100644 --- a/src/test/ui/suggestions/tuple-float-index.stderr +++ b/src/test/ui/suggestions/tuple-float-index.stderr @@ -5,7 +5,7 @@ error: unexpected token: `1.1` | ------------^^^ | | | | | unexpected token - | help: try parenthesizing the first index `((1, (2, 3)).1).1` + | help: try parenthesizing the first index: `((1, (2, 3)).1).1` error: aborting due to previous error diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index ad0d2fa0b3635..791b8d77e0b90 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -70,7 +70,7 @@ pub fn check(path: &Path, bad: &mut bool) { } let filen_underscore = filename.replace("-","_").replace(".rs",""); - test_filen_gate(&filen_underscore, &mut features); + let filename_is_gate_test = test_filen_gate(&filen_underscore, &mut features); contents.truncate(0); t!(t!(File::open(&file), &file).read_to_string(&mut contents)); @@ -92,17 +92,20 @@ pub fn check(path: &Path, bad: &mut bool) { }, None => continue, }; - let found_feature = features.get_mut(feature_name) - .map(|v| { v.has_gate_test = true; () }) - .is_some(); - - let found_lib_feature = features.get_mut(feature_name) - .map(|v| { v.has_gate_test = true; () }) - .is_some(); - - if !(found_feature || found_lib_feature) { - err(&format!("gate-test test found referencing a nonexistent feature '{}'", - feature_name)); + match features.get_mut(feature_name) { + Some(f) => { + if filename_is_gate_test { + err(&format!("The file is already marked as gate test \ + through its name, no need for a \ + 'gate-test-{}' comment", + feature_name)); + } + f.has_gate_test = true; + } + None => { + err(&format!("gate-test test found referencing a nonexistent feature '{}'", + feature_name)); + } } } }); @@ -265,4 +268,4 @@ pub fn collect_lib_features(base_src_path: &Path, } }); lib_features -} \ No newline at end of file +}