diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 21b14d011f911..2e51a786f4682 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -368,8 +368,7 @@ will run all the tests on every platform we support. If it all works out, [merge-queue]: https://buildbot2.rust-lang.org/homu/queue/rust Speaking of tests, Rust has a comprehensive test suite. More information about -it can be found -[here](https://github.com/rust-lang/rust/blob/master/src/test/COMPILER_TESTS.md). +it can be found [here][rctd]. ### External Dependencies [external-dependencies]: #external-dependencies @@ -654,5 +653,5 @@ are: [rustforge]: https://forge.rust-lang.org/ [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/ [ro]: http://www.rustaceans.org/ -[rctd]: ./src/test/COMPILER_TESTS.md +[rctd]: https://rust-lang-nursery.github.io/rustc-guide/tests/intro.html [cheatsheet]: https://buildbot2.rust-lang.org/homu/ diff --git a/RELEASES.md b/RELEASES.md index 7e727e0d41bb3..819c9184364fd 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -31,6 +31,8 @@ Cargo using `--target`][cargo/5614] - [Added the `cargo-fix` subcommand to automatically move project code from 2015 edition to 2018.][cargo/5723] +- [`cargo doc` can now optionally document private types using the + `--document-private-items` flag.][cargo/5543] Misc ---- @@ -68,6 +70,7 @@ Compatibility Notes [51178]: https://github.com/rust-lang/rust/pull/51178/ [51122]: https://github.com/rust-lang/rust/pull/51122 [50494]: https://github.com/rust-lang/rust/pull/50494/ +[cargo/5543]: https://github.com/rust-lang/cargo/pull/5543 [cargo/5614]: https://github.com/rust-lang/cargo/pull/5614/ [cargo/5723]: https://github.com/rust-lang/cargo/pull/5723/ [cargo/5831]: https://github.com/rust-lang/cargo/pull/5831/ @@ -370,6 +373,8 @@ Compatibility Notes - [The maximum number for `repr(align(N))` is now 2²⁹.][50378] Previously you could enter higher numbers but they were not supported by LLVM. Up to 512MB alignment should cover all use cases. +- The `.description()` method on the `std::error::Error` trait + [has been soft-deprecated][50163]. It is no longer required to implement it. [48553]: https://github.com/rust-lang/rust/pull/48553/ [48851]: https://github.com/rust-lang/rust/pull/48851/ @@ -383,6 +388,7 @@ Compatibility Notes [49719]: https://github.com/rust-lang/rust/pull/49719/ [49896]: https://github.com/rust-lang/rust/pull/49896/ [49968]: https://github.com/rust-lang/rust/pull/49968/ +[50163]: https://github.com/rust-lang/rust/pull/50163 [50177]: https://github.com/rust-lang/rust/pull/50177/ [50378]: https://github.com/rust-lang/rust/pull/50378/ [50398]: https://github.com/rust-lang/rust/pull/50398/ diff --git a/config.toml.example b/config.toml.example index 087dc418e2dce..3159c19528af5 100644 --- a/config.toml.example +++ b/config.toml.example @@ -377,6 +377,10 @@ # Whether to verify generated LLVM IR #verify-llvm-ir = false +# Map all debuginfo paths for libstd and crates to `/rust/$sha/$crate/...`, +# generally only set for releases +#remap-debuginfo = false + # ============================================================================= # Options for specific targets # diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 7192cae8956e4..f30f34acf5c6c 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -263,6 +263,10 @@ fn main() { if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } + + if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { + cmd.arg("--remap-path-prefix").arg(&map); + } } else { // Override linker if necessary. if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 5c287f25e26bc..2f7f3058b0473 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -32,7 +32,7 @@ use native; use test; use tool; use util::{add_lib_path, exe, libdir}; -use {Build, DocTests, Mode}; +use {Build, DocTests, Mode, GitRepo}; pub use Compiler; @@ -876,6 +876,10 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_HOST_CRT_STATIC", x.to_string()); } + if let Some(map) = self.build.debuginfo_map(GitRepo::Rustc) { + cargo.env("RUSTC_DEBUGINFO_MAP", map); + } + // Enable usage of unstable features cargo.env("RUSTC_BOOTSTRAP", "1"); self.add_rust_test_threads(&mut cargo); @@ -964,7 +968,7 @@ impl<'a> Builder<'a> { let cc = ccacheify(&self.cc(target)); cargo.env(format!("CC_{}", target), &cc).env("CC", &cc); - let cflags = self.cflags(target).join(" "); + let cflags = self.cflags(target, GitRepo::Rustc).join(" "); cargo .env(format!("CFLAGS_{}", target), cflags.clone()) .env("CFLAGS", cflags.clone()); diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index 698903f128d4d..d5da0cabec84a 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -39,7 +39,7 @@ use std::process::Command; use build_helper::output; use cc; -use Build; +use {Build, GitRepo}; use config::Target; use cache::Interned; @@ -107,7 +107,7 @@ pub fn find(build: &mut Build) { build.cc.insert(target, compiler); build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target))); - build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target))); + build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target, GitRepo::Rustc))); if let Some(ar) = ar { build.verbose(&format!("AR_{} = {:?}", &target, ar)); build.ar.insert(target, ar); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index da0ccf5e1773d..c0661a773e3a7 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -30,7 +30,7 @@ use filetime::FileTime; use serde_json; use util::{exe, libdir, is_dylib, CiEnv}; -use {Compiler, Mode}; +use {Compiler, Mode, GitRepo}; use native; use tool; @@ -895,7 +895,7 @@ pub fn compiler_file(builder: &Builder, target: Interned, file: &str) -> PathBuf { let mut cmd = Command::new(compiler); - cmd.args(builder.cflags(target)); + cmd.args(builder.cflags(target, GitRepo::Rustc)); cmd.arg(format!("-print-file-name={}", file)); let out = output(&mut cmd); PathBuf::from(out.trim()) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 70b21a1567b0f..cc6d76c76f2f2 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -109,6 +109,7 @@ pub struct Config { pub rust_codegen_backends: Vec>, pub rust_codegen_backends_dir: String, pub rust_verify_llvm_ir: bool, + pub rust_remap_debuginfo: bool, pub build: Interned, pub hosts: Vec>, @@ -321,6 +322,7 @@ struct Rust { deny_warnings: Option, backtrace_on_ice: Option, verify_llvm_ir: Option, + remap_debuginfo: Option, } /// TOML representation of how each build target is configured. @@ -557,6 +559,7 @@ impl Config { set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings)); set(&mut config.backtrace_on_ice, rust.backtrace_on_ice); set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir); + set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo); if let Some(ref backends) = rust.codegen_backends { config.rust_codegen_backends = backends.iter() diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2725abdc3d95f..ed6a5f94d0d95 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -237,6 +237,11 @@ pub enum DocTests { Only, } +pub enum GitRepo { + Rustc, + Llvm, +} + /// Global configuration for the build system. /// /// This structure transitively contains all configuration for the build system. @@ -738,6 +743,21 @@ impl Build { self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32) } + fn debuginfo_map(&self, which: GitRepo) -> Option { + if !self.config.rust_remap_debuginfo { + return None + } + + let path = match which { + GitRepo::Rustc => { + let sha = self.rust_info.sha().expect("failed to find sha"); + format!("/rustc/{}", sha) + } + GitRepo::Llvm => format!("/rustc/llvm"), + }; + Some(format!("{}={}", self.src.display(), path)) + } + /// Returns the path to the C compiler for the target specified. fn cc(&self, target: Interned) -> &Path { self.cc[&target].path() @@ -745,7 +765,7 @@ impl Build { /// Returns a list of flags to pass to the C compiler for the target /// specified. - fn cflags(&self, target: Interned) -> Vec { + fn cflags(&self, target: Interned, which: GitRepo) -> Vec { // Filter out -O and /O (the optimization flags) that we picked up from // cc-rs because the build scripts will determine that for themselves. let mut base = self.cc[&target].args().iter() @@ -767,6 +787,16 @@ impl Build { if &*target == "i686-pc-windows-gnu" { base.push("-fno-omit-frame-pointer".into()); } + + if let Some(map) = self.debuginfo_map(which) { + let cc = self.cc(target); + if cc.ends_with("clang") || cc.ends_with("gcc") { + base.push(format!("-fdebug-prefix-map={}", map).into()); + } else if cc.ends_with("clang-cl.exe") { + base.push("-Xclang".into()); + base.push(format!("-fdebug-prefix-map={}", map).into()); + } + } base } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 828a7d14c0437..424264647f0be 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -33,6 +33,7 @@ use util::{self, exe}; use build_helper::up_to_date; use builder::{Builder, RunConfig, ShouldRun, Step}; use cache::Interned; +use GitRepo; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Llvm { @@ -373,8 +374,8 @@ fn configure_cmake(builder: &Builder, } cfg.build_arg("-j").build_arg(builder.jobs().to_string()); - cfg.define("CMAKE_C_FLAGS", builder.cflags(target).join(" ")); - let mut cxxflags = builder.cflags(target).join(" "); + cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" ")); + let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" "); if building_dist_binaries { if builder.config.llvm_static_stdcpp && !target.contains("windows") { cxxflags.push_str(" -static-libstdc++"); @@ -680,7 +681,7 @@ impl Step for Openssl { }; configure.arg(os); configure.env("CC", builder.cc(target)); - for flag in builder.cflags(target) { + for flag in builder.cflags(target, GitRepo::Rustc) { configure.arg(flag); } // There is no specific os target for android aarch64 or x86_64, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 8e42c9c1ec773..92665c09f72aa 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -34,7 +34,7 @@ use tool::{self, Tool, SourceType}; use toolstate::ToolState; use util::{self, dylib_path, dylib_path_var}; use Crate as CargoCrate; -use {DocTests, Mode}; +use {DocTests, Mode, GitRepo}; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -1142,7 +1142,7 @@ impl Step for Compiletest { .arg("--cxx") .arg(builder.cxx(target).unwrap()) .arg("--cflags") - .arg(builder.cflags(target).join(" ")) + .arg(builder.cflags(target, GitRepo::Rustc).join(" ")) .arg("--llvm-components") .arg(llvm_components.trim()) .arg("--llvm-cxxflags") diff --git a/src/ci/run.sh b/src/ci/run.sh index 09a0cf3541d8d..6a571bfad135d 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -55,6 +55,7 @@ export RUST_RELEASE_CHANNEL=nightly if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo" if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions" diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 73c9729feee32..2a9732bf02c98 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -68,15 +68,13 @@ pub enum OptLevel { SizeMin, // -Oz } +/// This is what the `LtoCli` values get mapped to after resolving defaults and +/// and taking other command line options into account. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum Lto { /// Don't do any LTO whatsoever No, - /// Do a full crate graph LTO. The flavor is determined by the compiler - /// (currently the default is "fat"). - Yes, - /// Do a full crate graph LTO with ThinLTO Thin, @@ -88,6 +86,23 @@ pub enum Lto { Fat, } +/// The different settings that the `-C lto` flag can have. +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum LtoCli { + /// `-C lto=no` + No, + /// `-C lto=yes` + Yes, + /// `-C lto` + NoParam, + /// `-C lto=thin` + Thin, + /// `-C lto=fat` + Fat, + /// No `-C lto` flag passed + Unspecified, +} + #[derive(Clone, PartialEq, Hash)] pub enum CrossLangLto { LinkerPlugin(PathBuf), @@ -801,7 +816,8 @@ macro_rules! options { pub const parse_unpretty: Option<&'static str> = Some("`string` or `string=string`"); pub const parse_lto: Option<&'static str> = - Some("one of `thin`, `fat`, or omitted"); + Some("either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \ + `fat`, or omitted"); pub const parse_cross_lang_lto: Option<&'static str> = Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \ or the path to the linker plugin"); @@ -809,7 +825,7 @@ macro_rules! options { #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, Sanitizer, Lto, CrossLangLto}; + use super::{$struct_name, Passes, Sanitizer, LtoCli, CrossLangLto}; use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel}; use std::path::PathBuf; @@ -1002,11 +1018,23 @@ macro_rules! options { } } - fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool { + fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool { + if v.is_some() { + let mut bool_arg = None; + if parse_opt_bool(&mut bool_arg, v) { + *slot = if bool_arg.unwrap() { + LtoCli::Yes + } else { + LtoCli::No + }; + return true + } + } + *slot = match v { - None => Lto::Yes, - Some("thin") => Lto::Thin, - Some("fat") => Lto::Fat, + None => LtoCli::NoParam, + Some("thin") => LtoCli::Thin, + Some("fat") => LtoCli::Fat, Some(_) => return false, }; true @@ -1047,7 +1075,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "extra arguments to append to the linker invocation (space separated)"), link_dead_code: bool = (false, parse_bool, [UNTRACKED], "don't let linker strip dead code (turning it on can be used for code coverage)"), - lto: Lto = (Lto::No, parse_lto, [TRACKED], + lto: LtoCli = (LtoCli::Unspecified, parse_lto, [TRACKED], "perform LLVM link-time optimizations"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (rustc --print target-cpus for details)"), @@ -2384,8 +2412,8 @@ mod dep_tracking { use std::hash::Hash; use std::path::PathBuf; use std::collections::hash_map::DefaultHasher; - use super::{CrateType, DebugInfo, ErrorOutputType, Lto, OptLevel, OutputTypes, - Passes, Sanitizer, CrossLangLto}; + use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes, + Passes, Sanitizer, LtoCli, CrossLangLto}; use syntax::feature_gate::UnstableFeatures; use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple}; use syntax::edition::Edition; @@ -2440,7 +2468,7 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(RelroLevel); impl_dep_tracking_hash_via_hash!(Passes); impl_dep_tracking_hash_via_hash!(OptLevel); - impl_dep_tracking_hash_via_hash!(Lto); + impl_dep_tracking_hash_via_hash!(LtoCli); impl_dep_tracking_hash_via_hash!(DebugInfo); impl_dep_tracking_hash_via_hash!(UnstableFeatures); impl_dep_tracking_hash_via_hash!(OutputTypes); @@ -2514,7 +2542,7 @@ mod tests { use lint; use middle::cstore; use session::config::{build_configuration, build_session_options_and_crate_config}; - use session::config::{Lto, CrossLangLto}; + use session::config::{LtoCli, CrossLangLto}; use session::build_session; use std::collections::{BTreeMap, BTreeSet}; use std::iter::FromIterator; @@ -2948,7 +2976,7 @@ mod tests { // Make sure changing a [TRACKED] option changes the hash opts = reference.clone(); - opts.cg.lto = Lto::Fat; + opts.cg.lto = LtoCli::Fat; assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 272967282e03b..619262abb0bf5 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -550,9 +550,27 @@ impl Session { // lto` and we've for whatever reason forced off ThinLTO via the CLI, // then ensure we can't use a ThinLTO. match self.opts.cg.lto { - config::Lto::No => {} - config::Lto::Yes if self.opts.cli_forced_thinlto_off => return config::Lto::Fat, - other => return other, + config::LtoCli::Unspecified => { + // The compiler was invoked without the `-Clto` flag. Fall + // through to the default handling + } + config::LtoCli::No => { + // The user explicitly opted out of any kind of LTO + return config::Lto::No; + } + config::LtoCli::Yes | + config::LtoCli::Fat | + config::LtoCli::NoParam => { + // All of these mean fat LTO + return config::Lto::Fat; + } + config::LtoCli::Thin => { + return if self.opts.cli_forced_thinlto_off { + config::Lto::Fat + } else { + config::Lto::Thin + }; + } } // Ok at this point the target doesn't require anything and the user @@ -1178,7 +1196,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { if sess.opts.incremental.is_some() { match sess.lto() { - Lto::Yes | Lto::Thin | Lto::Fat => { sess.err("can't perform LTO when compiling incrementally"); diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index d50a56ad84ab2..8248385c12764 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -1666,7 +1666,6 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { fn are_upstream_rust_objects_already_included(sess: &Session) -> bool { match sess.lto() { - Lto::Yes | Lto::Fat => true, Lto::Thin => { // If we defer LTO to the linker, we haven't run LTO ourselves, so diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs index ebb229b7b6bfa..95be2d82123a7 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_llvm/back/linker.rs @@ -205,13 +205,12 @@ impl<'a> GccLinker<'a> { self.linker_arg(&format!("-plugin-opt={}", opt_level)); self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess))); - match self.sess.opts.cg.lto { + match self.sess.lto() { config::Lto::Thin | config::Lto::ThinLocal => { self.linker_arg("-plugin-opt=thin"); } config::Lto::Fat | - config::Lto::Yes | config::Lto::No => { // default to regular LTO } diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 25bc662c408f6..364b469738fc9 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -118,7 +118,7 @@ pub(crate) fn run(cgcx: &CodegenContext, Lto::ThinLocal => SymbolExportLevel::Rust, // We're doing LTO for the entire crate graph - Lto::Yes | Lto::Fat | Lto::Thin => { + Lto::Fat | Lto::Thin => { symbol_export::crates_export_threshold(&cgcx.crate_types) } @@ -201,7 +201,6 @@ pub(crate) fn run(cgcx: &CodegenContext, .map(|c| c.as_ptr()) .collect::>(); match cgcx.lto { - Lto::Yes | // `-C lto` == fat LTO by default Lto::Fat => { assert!(cached_modules.is_empty()); let opt_jobs = fat_lto(cgcx, diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 6b257ed4c3e94..7b78d4fb4ffa9 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -937,7 +937,6 @@ fn need_pre_thin_lto_bitcode_for_incr_comp(sess: &Session) -> bool { } match sess.lto() { - Lto::Yes | Lto::Fat | Lto::No => false, Lto::Thin | @@ -1372,7 +1371,7 @@ fn execute_optimize_work_item(cgcx: &CodegenContext, // require LTO so the request for LTO is always unconditionally // passed down to the backend, but we don't actually want to do // anything about it yet until we've got a final product. - Lto::Yes | Lto::Fat | Lto::Thin => { + Lto::Fat | Lto::Thin => { cgcx.crate_types.len() != 1 || cgcx.crate_types[0] != config::CrateType::Rlib } @@ -1552,7 +1551,7 @@ fn start_executing_work(tcx: TyCtxt, exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); Some(Arc::new(exported_symbols)) } - Lto::Yes | Lto::Fat | Lto::Thin => { + Lto::Fat | Lto::Thin => { exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); for &cnum in tcx.crates().iter() { exported_symbols.insert(cnum, copy_symbols(cnum)); diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 154830c2e77e0..82cc1b7f66166 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -239,6 +239,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeEvaluator { type MemoryKinds = !; const MUT_STATIC_KIND: Option = None; // no mutating of statics allowed + const DETECT_LOOPS: bool = true; fn find_fn<'a>( ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index f7277f8d27610..740d4e038df7e 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -65,6 +65,8 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { /// detector period. pub(super) steps_since_detector_enabled: isize, + /// Extra state to detect loops. + /// FIXME: Move this to the CTFE machine's state, out of the general miri engine. pub(super) loop_detector: InfiniteLoopDetector<'a, 'mir, 'tcx, M>, } @@ -110,6 +112,7 @@ pub struct Frame<'mir, 'tcx: 'mir> { pub stmt: usize, } +// Not using the macro because that does not support types depending on 'tcx impl<'a, 'mir, 'tcx: 'mir> HashStable> for Frame<'mir, 'tcx> { fn hash_stable( &self, @@ -144,11 +147,14 @@ pub enum StackPopCleanup { None { cleanup: bool }, } +// Can't use the macro here because that does not support named enum fields. impl<'a> HashStable> for StackPopCleanup { fn hash_stable( &self, hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { + hasher: &mut StableHasher) + { + mem::discriminant(self).hash_stable(hcx, hasher); match self { StackPopCleanup::Goto(ref block) => block.hash_stable(hcx, hasher), StackPopCleanup::None { cleanup } => cleanup.hash_stable(hcx, hasher), diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 61963f6d3d354..f33cb4791029a 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -12,29 +12,29 @@ //! This separation exists to ensure that no fancy miri features like //! interpreting common C functions leak into CTFE. -use std::hash::Hash; - use rustc::hir::def_id::DefId; -use rustc::ich::StableHashingContext; use rustc::mir::interpret::{Allocation, EvalResult, Scalar}; use rustc::mir; use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt}; -use rustc_data_structures::stable_hasher::HashStable; use super::{EvalContext, PlaceTy, OpTy}; /// Methods of this trait signifies a point where CTFE evaluation would fail /// and some use case dependent behaviour can instead be applied -pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash + for<'a> HashStable> { +pub trait Machine<'mir, 'tcx>: Clone + Eq { /// Additional data that can be accessed via the Memory - type MemoryData: Clone + Eq + Hash + for<'a> HashStable>; + type MemoryData: Clone + Eq; /// Additional memory kinds a machine wishes to distinguish from the builtin ones - type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq + Hash; + type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq; /// The memory kind to use for mutated statics -- or None if those are not supported. const MUT_STATIC_KIND: Option; + /// Whether to attempt to detect infinite loops (any kind of infinite + /// execution, really). + const DETECT_LOOPS: bool; + /// Entry point to all function calls. /// /// Returns either the mir to use for the call, or `None` if execution should diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index d01593ca5e91c..64e0aeaaab7f0 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -13,6 +13,7 @@ //! All high-level functions to write to memory work on places as destinations. use std::convert::TryFrom; +use std::mem; use rustc::ich::StableHashingContext; use rustc::mir; @@ -57,11 +58,13 @@ pub enum Place { }, } +// Can't use the macro here because that does not support named enum fields. impl<'a> HashStable> for Place { fn hash_stable( &self, hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - + hasher: &mut StableHasher) + { + mem::discriminant(self).hash_stable(hcx, hasher); match self { Place::Ptr(mem_place) => mem_place.hash_stable(hcx, hasher), diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 8aa053baae9f0..0e8466905eb76 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -62,14 +62,13 @@ impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M> pub fn observe_and_analyze( &mut self, tcx: &TyCtxt<'b, 'tcx, 'tcx>, - machine: &M, memory: &Memory<'a, 'mir, 'tcx, M>, stack: &[Frame<'mir, 'tcx>], ) -> EvalResult<'tcx, ()> { let mut hcx = tcx.get_stable_hashing_context(); let mut hasher = StableHasher::::new(); - (machine, stack).hash_stable(&mut hcx, &mut hasher); + stack.hash_stable(&mut hcx, &mut hasher); let hash = hasher.finish(); if self.hashes.insert(hash) { @@ -79,7 +78,7 @@ impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M> info!("snapshotting the state of the interpreter"); - if self.snapshots.insert(EvalSnapshot::new(machine, memory, stack)) { + if self.snapshots.insert(EvalSnapshot::new(memory, stack)) { // Spurious collision or first cycle return Ok(()) } @@ -345,7 +344,6 @@ impl<'a, 'b, 'mir, 'tcx, M> SnapshotContext<'b> for Memory<'a, 'mir, 'tcx, M> /// The virtual machine state during const-evaluation at a given point in time. struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { - machine: M, memory: Memory<'a, 'mir, 'tcx, M>, stack: Vec>, } @@ -354,21 +352,20 @@ impl<'a, 'mir, 'tcx, M> EvalSnapshot<'a, 'mir, 'tcx, M> where M: Machine<'mir, 'tcx>, { fn new( - machine: &M, memory: &Memory<'a, 'mir, 'tcx, M>, - stack: &[Frame<'mir, 'tcx>]) -> Self { - + stack: &[Frame<'mir, 'tcx>] + ) -> Self { EvalSnapshot { - machine: machine.clone(), memory: memory.clone(), stack: stack.into(), } } fn snapshot<'b: 'a>(&'b self) - -> (&'b M, MemorySnapshot<'b, 'mir, 'tcx, M>, Vec>) { - let EvalSnapshot{ machine, memory, stack } = self; - (&machine, memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect()) + -> (MemorySnapshot<'b, 'mir, 'tcx, M>, Vec>) + { + let EvalSnapshot{ memory, stack } = self; + (memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect()) } } @@ -384,6 +381,8 @@ impl<'a, 'mir, 'tcx, M> Hash for EvalSnapshot<'a, 'mir, 'tcx, M> } } +// Not using the macro because we need special handling for `memory`, which the macro +// does not support at the same time as the extra bounds on the type. impl<'a, 'b, 'mir, 'tcx, M> HashStable> for EvalSnapshot<'a, 'mir, 'tcx, M> where M: Machine<'mir, 'tcx>, @@ -391,10 +390,10 @@ impl<'a, 'b, 'mir, 'tcx, M> HashStable> fn hash_stable( &self, hcx: &mut StableHashingContext<'b>, - hasher: &mut StableHasher) { - - let EvalSnapshot{ machine, memory, stack } = self; - (machine, &memory.data, stack).hash_stable(hcx, hasher); + hasher: &mut StableHasher) + { + let EvalSnapshot{ memory: _, stack } = self; + stack.hash_stable(hcx, hasher); } } diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index cb8e1284d0968..5bdaf6ba72963 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -65,6 +65,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { } } + if !M::DETECT_LOOPS { + return Ok(()); + } + if self.loop_detector.is_empty() { // First run of the loop detector @@ -75,7 +79,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { self.loop_detector.observe_and_analyze( &self.tcx, - &self.machine, &self.memory, &self.stack[..], ) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 2a8ee4bd8df0e..7f65a5f0b5a63 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -298,11 +298,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { TypeVariableOrigin::TypeInference(pat.span))); let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); - self.demand_eqtype(pat.span, expected, pat_ty); - for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk(elem, &element_tys[i], def_bm, true); + if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) { + err.emit(); + // Walk subpatterns with an expected type of `err` in this case to silence + // further errors being emitted when using the bindings. #50333 + let element_tys_iter = (0..max_len).map(|_| tcx.types.err); + for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk(elem, &tcx.types.err, def_bm, true); + } + tcx.mk_tup(element_tys_iter) + } else { + for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk(elem, &element_tys[i], def_bm, true); + } + pat_ty } - pat_ty } PatKind::Box(ref inner) => { let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span)); diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 016e7adb4c914..0831e29bdddbf 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -97,6 +97,10 @@ fn build_libbacktrace(target: &str) -> Result<(), ()> { .file("../libbacktrace/sort.c") .file("../libbacktrace/state.c"); + let any_debug = env::var("RUSTC_DEBUGINFO").unwrap_or(String::new()) == "true" || + env::var("RUSTC_DEBUGINFO_LINES").unwrap_or(String::new()) == "true"; + build.debug(any_debug); + if target.contains("darwin") { build.file("../libbacktrace/macho.c"); } else if target.contains("windows") { diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 372f3e83e3dcd..63dd12f782fda 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -102,8 +102,8 @@ use sys; /// } /// /// // We are certain that our string doesn't have 0 bytes in the middle, -/// // so we can .unwrap() -/// let c_to_print = CString::new("Hello, world!").unwrap(); +/// // so we can .expect() +/// let c_to_print = CString::new("Hello, world!").expect("CString::new failed"); /// unsafe { /// my_printer(c_to_print.as_ptr()); /// } @@ -175,7 +175,7 @@ pub struct CString { /// unsafe { work_with(data.as_ptr()) } /// } /// -/// let s = CString::new("data data data data").unwrap(); +/// let s = CString::new("data data data data").expect("CString::new failed"); /// work(&s); /// ``` /// @@ -314,7 +314,7 @@ impl CString { /// /// extern { fn puts(s: *const c_char); } /// - /// let to_print = CString::new("Hello!").unwrap(); + /// let to_print = CString::new("Hello!").expect("CString::new failed"); /// unsafe { /// puts(to_print.as_ptr()); /// } @@ -398,7 +398,7 @@ impl CString { /// fn some_extern_function(s: *mut c_char); /// } /// - /// let c_string = CString::new("Hello!").unwrap(); + /// let c_string = CString::new("Hello!").expect("CString::new failed"); /// let raw = c_string.into_raw(); /// unsafe { /// some_extern_function(raw); @@ -428,7 +428,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").unwrap(); + /// let c_string = CString::new("foo").expect("CString::new failed"); /// /// let ptr = c_string.into_raw(); /// @@ -460,12 +460,12 @@ impl CString { /// use std::ffi::CString; /// /// let valid_utf8 = vec![b'f', b'o', b'o']; - /// let cstring = CString::new(valid_utf8).unwrap(); - /// assert_eq!(cstring.into_string().unwrap(), "foo"); + /// let cstring = CString::new(valid_utf8).expect("CString::new failed"); + /// assert_eq!(cstring.into_string().expect("into_string() call failed"), "foo"); /// /// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o']; - /// let cstring = CString::new(invalid_utf8).unwrap(); - /// let err = cstring.into_string().err().unwrap(); + /// let cstring = CString::new(invalid_utf8).expect("CString::new failed"); + /// let err = cstring.into_string().err().expect("into_string().err() failed"); /// assert_eq!(err.utf8_error().valid_up_to(), 1); /// ``` @@ -489,7 +489,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").unwrap(); + /// let c_string = CString::new("foo").expect("CString::new failed"); /// let bytes = c_string.into_bytes(); /// assert_eq!(bytes, vec![b'f', b'o', b'o']); /// ``` @@ -511,7 +511,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").unwrap(); + /// let c_string = CString::new("foo").expect("CString::new failed"); /// let bytes = c_string.into_bytes_with_nul(); /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']); /// ``` @@ -534,7 +534,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").unwrap(); + /// let c_string = CString::new("foo").expect("CString::new failed"); /// let bytes = c_string.as_bytes(); /// assert_eq!(bytes, &[b'f', b'o', b'o']); /// ``` @@ -554,7 +554,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").unwrap(); + /// let c_string = CString::new("foo").expect("CString::new failed"); /// let bytes = c_string.as_bytes_with_nul(); /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']); /// ``` @@ -573,9 +573,10 @@ impl CString { /// ``` /// use std::ffi::{CString, CStr}; /// - /// let c_string = CString::new(b"foo".to_vec()).unwrap(); + /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); /// let c_str = c_string.as_c_str(); - /// assert_eq!(c_str, CStr::from_bytes_with_nul(b"foo\0").unwrap()); + /// assert_eq!(c_str, + /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); /// ``` #[inline] #[stable(feature = "as_c_str", since = "1.20.0")] @@ -592,16 +593,17 @@ impl CString { /// ``` /// use std::ffi::{CString, CStr}; /// - /// let c_string = CString::new(b"foo".to_vec()).unwrap(); + /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); /// let boxed = c_string.into_boxed_c_str(); - /// assert_eq!(&*boxed, CStr::from_bytes_with_nul(b"foo\0").unwrap()); + /// assert_eq!(&*boxed, + /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); /// ``` #[stable(feature = "into_boxed_c_str", since = "1.20.0")] pub fn into_boxed_c_str(self) -> Box { unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) } } - // Bypass "move out of struct which implements [`Drop`] trait" restriction. + /// Bypass "move out of struct which implements [`Drop`] trait" restriction. /// /// [`Drop`]: ../ops/trait.Drop.html fn into_inner(self) -> Box<[u8]> { @@ -1031,7 +1033,7 @@ impl CStr { /// use std::ffi::{CStr, CString}; /// /// unsafe { - /// let cstring = CString::new("hello").unwrap(); + /// let cstring = CString::new("hello").expect("CString::new failed"); /// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul()); /// assert_eq!(cstr, &*cstring); /// } @@ -1058,7 +1060,7 @@ impl CStr { /// # #![allow(unused_must_use)] /// use std::ffi::{CString}; /// - /// let ptr = CString::new("Hello").unwrap().as_ptr(); + /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr(); /// unsafe { /// // `ptr` is dangling /// *ptr; @@ -1067,14 +1069,14 @@ impl CStr { /// /// This happens because the pointer returned by `as_ptr` does not carry any /// lifetime information and the [`CString`] is deallocated immediately after - /// the `CString::new("Hello").unwrap().as_ptr()` expression is evaluated. + /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` expression is evaluated. /// To fix the problem, bind the `CString` to a local variable: /// /// ```no_run /// # #![allow(unused_must_use)] /// use std::ffi::{CString}; /// - /// let hello = CString::new("Hello").unwrap(); + /// let hello = CString::new("Hello").expect("CString::new failed"); /// let ptr = hello.as_ptr(); /// unsafe { /// // `ptr` is valid because `hello` is in scope @@ -1106,7 +1108,7 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap(); + /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); /// assert_eq!(c_str.to_bytes(), b"foo"); /// ``` #[inline] @@ -1132,7 +1134,7 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap(); + /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); /// assert_eq!(c_str.to_bytes_with_nul(), b"foo\0"); /// ``` #[inline] @@ -1159,7 +1161,7 @@ impl CStr { /// ``` /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap(); + /// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); /// assert_eq!(c_str.to_str(), Ok("foo")); /// ``` #[stable(feature = "cstr_to_str", since = "1.4.0")] @@ -1200,7 +1202,8 @@ impl CStr { /// use std::borrow::Cow; /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"Hello World\0").unwrap(); + /// let c_str = CStr::from_bytes_with_nul(b"Hello World\0") + /// .expect("CStr::from_bytes_with_nul failed"); /// assert_eq!(c_str.to_string_lossy(), Cow::Borrowed("Hello World")); /// ``` /// @@ -1210,7 +1213,8 @@ impl CStr { /// use std::borrow::Cow; /// use std::ffi::CStr; /// - /// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0").unwrap(); + /// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0") + /// .expect("CStr::from_bytes_with_nul failed"); /// assert_eq!( /// c_str.to_string_lossy(), /// Cow::Owned(String::from("Hello �World")) as Cow @@ -1231,9 +1235,9 @@ impl CStr { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new(b"foo".to_vec()).unwrap(); + /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); /// let boxed = c_string.into_boxed_c_str(); - /// assert_eq!(boxed.into_c_string(), CString::new("foo").unwrap()); + /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed")); /// ``` #[stable(feature = "into_boxed_c_str", since = "1.20.0")] pub fn into_c_string(self: Box) -> CString { diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs index e429791f2bdd4..feee2422cb662 100644 --- a/src/libsyntax/util/lev_distance.rs +++ b/src/libsyntax/util/lev_distance.rs @@ -11,7 +11,7 @@ use std::cmp; use symbol::Symbol; -/// To find the Levenshtein distance between two strings +/// Find the Levenshtein distance between two strings pub fn lev_distance(a: &str, b: &str) -> usize { // cases which don't require further computation if a.is_empty() { @@ -41,10 +41,12 @@ pub fn lev_distance(a: &str, b: &str) -> usize { } dcol[t_last + 1] } -/// To find the best match for a given string from an iterator of names +/// Find the best match for a given word in the given iterator +/// /// As a loose rule to avoid the obviously incorrect suggestions, it takes /// an optional limit for the maximum allowable edit distance, which defaults /// to one-third of the given word. +/// /// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with /// a lower(upper)case letters mismatch. pub fn find_best_match_for_name<'a, T>(iter_names: T, @@ -105,3 +107,39 @@ fn test_lev_distance() { assert_eq!(lev_distance(b, c), 1); assert_eq!(lev_distance(c, b), 1); } + +#[test] +fn test_find_best_match_for_name() { + use with_globals; + with_globals(|| { + let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")]; + assert_eq!( + find_best_match_for_name(input.iter(), "aaaa", None), + Some(Symbol::intern("aaab")) + ); + + assert_eq!( + find_best_match_for_name(input.iter(), "1111111111", None), + None + ); + + let input = vec![Symbol::intern("aAAA")]; + assert_eq!( + find_best_match_for_name(input.iter(), "AAAA", None), + Some(Symbol::intern("aAAA")) + ); + + let input = vec![Symbol::intern("AAAA")]; + // Returns None because `lev_distance > max_dist / 3` + assert_eq!( + find_best_match_for_name(input.iter(), "aaaa", None), + None + ); + + let input = vec![Symbol::intern("AAAA")]; + assert_eq!( + find_best_match_for_name(input.iter(), "aaaa", Some(4)), + Some(Symbol::intern("AAAA")) + ); + }) +} diff --git a/src/stage0.txt b/src/stage0.txt index a93b25607eb3a..69e8140cdf19d 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2018-08-01 +date: 2018-09-11 rustc: beta cargo: beta diff --git a/src/test/run-make-fulldeps/codegen-options-parsing/Makefile b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile index fda96a8b1fb5e..39e9a9bdd6b68 100644 --- a/src/test/run-make-fulldeps/codegen-options-parsing/Makefile +++ b/src/test/run-make-fulldeps/codegen-options-parsing/Makefile @@ -16,11 +16,11 @@ all: $(RUSTC) -C extra-filename=foo dummy.rs 2>&1 #Option taking no argument $(RUSTC) -C lto= dummy.rs 2>&1 | \ - $(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or' + $(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted' $(RUSTC) -C lto=1 dummy.rs 2>&1 | \ - $(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or' + $(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted' $(RUSTC) -C lto=foo dummy.rs 2>&1 | \ - $(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or' + $(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted' $(RUSTC) -C lto dummy.rs # Should not link dead code... diff --git a/src/test/run-make-fulldeps/lto-smoke/Makefile b/src/test/run-make-fulldeps/lto-smoke/Makefile index 020252e1f8cd3..9b1dc2550b21b 100644 --- a/src/test/run-make-fulldeps/lto-smoke/Makefile +++ b/src/test/run-make-fulldeps/lto-smoke/Makefile @@ -1,6 +1,30 @@ -include ../tools.mk -all: +all: noparam bool_true bool_false thin fat + +noparam: $(RUSTC) lib.rs $(RUSTC) main.rs -C lto $(call RUN,main) + +bool_true: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=yes + $(call RUN,main) + + +bool_false: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=off + $(call RUN,main) + +thin: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=thin + $(call RUN,main) + +fat: + $(RUSTC) lib.rs + $(RUSTC) main.rs -C lto=fat + $(call RUN,main) + diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs new file mode 100644 index 0000000000000..d6ffca09e96d8 --- /dev/null +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs @@ -0,0 +1,37 @@ +// 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. + +// New test for #53818: modifying static memory at compile-time is not allowed. +// The test should never succeed. + +#![feature(const_raw_ptr_deref)] +#![feature(const_let)] + +use std::cell::UnsafeCell; + +struct Foo(UnsafeCell); + +unsafe impl Send for Foo {} +unsafe impl Sync for Foo {} + +static FOO: Foo = Foo(UnsafeCell::new(42)); + +static BAR: () = unsafe { + *FOO.0.get() = 5; + //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants + + // This error is caused by a separate bug that the feature gate error is reported + // even though the feature gate "const_let" is active. + //~| statements in statics are unstable (see issue #48821) +}; + +fn main() { + println!("{}", unsafe { *FOO.0.get() }); +} diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr new file mode 100644 index 0000000000000..8eaed1dcab116 --- /dev/null +++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr @@ -0,0 +1,18 @@ +error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants + --> $DIR/mod-static-with-const-fn.rs:27:6 + | +LL | *FOO.0.get() = 5; + | ^^^^^^^^^^^ + +error[E0658]: statements in statics are unstable (see issue #48821) + --> $DIR/mod-static-with-const-fn.rs:27:5 + | +LL | *FOO.0.get() = 5; + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(const_let)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +Some errors occurred: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/const-size_of-cycle.rs b/src/test/ui/consts/const-size_of-cycle.rs index 04c054f8b6db2..1ea7b973c465b 100644 --- a/src/test/ui/consts/const-size_of-cycle.rs +++ b/src/test/ui/consts/const-size_of-cycle.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-musl +// ignore-x86 // error-pattern: cycle detected struct Foo { diff --git a/src/test/ui/elide-errors-on-mismatched-tuple.rs b/src/test/ui/elide-errors-on-mismatched-tuple.rs new file mode 100644 index 0000000000000..68e579788bca1 --- /dev/null +++ b/src/test/ui/elide-errors-on-mismatched-tuple.rs @@ -0,0 +1,28 @@ +// 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. + +// Hide irrelevant E0277 errors (#50333) + +trait T {} + +struct A; +impl T for A {} +impl A { + fn new() -> Self { + Self {} + } +} + +fn main() { + let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three + //~^ ERROR mismatched types + let ts: Vec<&T> = vec![&a, &b, &c]; + // There is no E0277 error above, as `a`, `b` and `c` are `TyErr` +} diff --git a/src/test/ui/elide-errors-on-mismatched-tuple.stderr b/src/test/ui/elide-errors-on-mismatched-tuple.stderr new file mode 100644 index 0000000000000..b901175d53450 --- /dev/null +++ b/src/test/ui/elide-errors-on-mismatched-tuple.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/elide-errors-on-mismatched-tuple.rs:24:9 + | +LL | let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three + | ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements + | + = note: expected type `(A, A)` + found type `(_, _, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.rs b/src/test/ui/impl-trait/impl-generic-mismatch.rs index d6707f590113c..6cf8000f6ad27 100644 --- a/src/test/ui/impl-trait/impl-generic-mismatch.rs +++ b/src/test/ui/impl-trait/impl-generic-mismatch.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-musl +// ignore-x86 + use std::fmt::Debug; trait Foo { diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.stderr b/src/test/ui/impl-trait/impl-generic-mismatch.stderr index 7ad16b1f8f237..d777779a881e0 100644 --- a/src/test/ui/impl-trait/impl-generic-mismatch.stderr +++ b/src/test/ui/impl-trait/impl-generic-mismatch.stderr @@ -1,5 +1,5 @@ error[E0643]: method `foo` has incompatible signature for trait - --> $DIR/impl-generic-mismatch.rs:18:12 + --> $DIR/impl-generic-mismatch.rs:21:12 | LL | fn foo(&self, _: &impl Debug); | ---------- declaration in trait here @@ -12,7 +12,7 @@ LL | fn foo(&self, _: &impl Debug) { } | -- ^^^^^^^^^^ error[E0643]: method `bar` has incompatible signature for trait - --> $DIR/impl-generic-mismatch.rs:27:23 + --> $DIR/impl-generic-mismatch.rs:30:23 | LL | fn bar(&self, _: &U); | - declaration in trait here @@ -25,7 +25,7 @@ LL | fn bar(&self, _: &U) { } | ^^^^^^^^^^ ^ error[E0643]: method `hash` has incompatible signature for trait - --> $DIR/impl-generic-mismatch.rs:38:33 + --> $DIR/impl-generic-mismatch.rs:41:33 | LL | fn hash(&self, hasher: &mut impl Hasher) {} | ^^^^^^^^^^^ expected generic parameter, found `impl Trait`