From 24093a6bdb33319bed76b3bc8d3f2efda63967c2 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 4 Sep 2018 17:57:17 +0200 Subject: [PATCH 01/14] Allow for opting out of ThinLTO and clean up LTO related cli flag handling. --- src/librustc/session/config.rs | 60 ++++++++++++++----- src/librustc/session/mod.rs | 25 ++++++-- src/librustc_codegen_llvm/back/link.rs | 1 - src/librustc_codegen_llvm/back/linker.rs | 3 +- src/librustc_codegen_llvm/back/lto.rs | 3 +- src/librustc_codegen_llvm/back/write.rs | 5 +- .../codegen-options-parsing/Makefile | 6 +- src/test/run-make-fulldeps/lto-smoke/Makefile | 26 +++++++- 8 files changed, 97 insertions(+), 32 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index ee3fabc58d53f..28e473a1383bf 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)"), @@ -2373,8 +2401,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; @@ -2429,7 +2457,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); @@ -2503,7 +2531,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; @@ -2937,7 +2965,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 778c388c7dec7..9e99d3af6d10b 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -547,9 +547,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 @@ -1174,7 +1192,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 c1dda02264ed1..d852eb0bc6834 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 1c0f89193b209..3940673dc79c2 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -928,7 +928,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 | @@ -1363,7 +1362,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 } @@ -1543,7 +1542,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/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) + From 72ba0ba3d7ce8a5d34bbffaca4be5da5b988499f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 5 Sep 2018 23:54:07 +0200 Subject: [PATCH 02/14] Replace unwrap calls in example by expect --- src/libstd/ffi/c_str.rs | 64 ++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 2b87094926cf5..d9d9e9476b977 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -101,8 +101,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()); /// } @@ -174,7 +174,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); /// ``` /// @@ -313,7 +313,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()); /// } @@ -397,7 +397,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); @@ -427,7 +427,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(); /// @@ -459,12 +459,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); /// ``` @@ -488,7 +488,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']); /// ``` @@ -510,7 +510,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']); /// ``` @@ -533,7 +533,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']); /// ``` @@ -553,7 +553,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']); /// ``` @@ -572,9 +572,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")] @@ -591,16 +592,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]> { @@ -1030,7 +1032,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); /// } @@ -1057,7 +1059,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; @@ -1066,14 +1068,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 @@ -1105,7 +1107,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] @@ -1131,7 +1133,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] @@ -1158,7 +1160,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")] @@ -1199,7 +1201,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")); /// ``` /// @@ -1209,7 +1212,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 @@ -1230,9 +1234,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 { From e25e2abe4831e6c1ae3b93f6c4209276272ff0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Saparelli?= Date: Sun, 9 Sep 2018 10:36:17 +1200 Subject: [PATCH 03/14] Add Error::description soft-deprecation to RELEASES --- RELEASES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 7e727e0d41bb3..0cd89101ad187 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -370,6 +370,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 +385,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/ From 3cb736af7573a2226c4ed0be518fc84ae69d560e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Sep 2018 10:06:39 +0200 Subject: [PATCH 04/14] miri loop detector hashing: fix enum hashing to also consider discriminant; do not hash extra machine state standalone miri is not interested in loop detection --- src/librustc_mir/const_eval.rs | 1 + src/librustc_mir/interpret/eval_context.rs | 8 +++++- src/librustc_mir/interpret/machine.rs | 14 +++++------ src/librustc_mir/interpret/place.rs | 7 ++++-- src/librustc_mir/interpret/snapshot.rs | 29 +++++++++++----------- src/librustc_mir/interpret/step.rs | 5 +++- 6 files changed, 38 insertions(+), 26 deletions(-) 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 545333e879176..2835a46e7662d 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[..], ) From 5595aeb6b7eda6b96cb2fe882401213c4fc04c6f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 30 Aug 2018 10:25:07 -0700 Subject: [PATCH 05/14] Add rustc SHA to released DWARF debuginfo This commit updates the debuginfo that is encoded in all of our released artifacts by default. Currently it has paths like `/checkout/src/...` but these are a little inconsistent and have changed over time. This commit instead attempts to actually define the file paths in our debuginfo to be consistent between releases. All debuginfo paths are now intended to be `/rustc/$sha` where `$sha` is the git sha of the released compiler. Sub-paths are all paths into the git repo at that `$sha`. --- config.toml.example | 4 +++ src/bootstrap/bin/rustc.rs | 4 +++ src/bootstrap/builder.rs | 8 +++-- src/bootstrap/cc_detect.rs | 4 +-- src/bootstrap/compile.rs | 4 +-- src/bootstrap/config.rs | 3 ++ src/bootstrap/lib.rs | 32 ++++++++++++++++++- src/bootstrap/native.rs | 7 ++-- src/bootstrap/test.rs | 4 +-- src/ci/run.sh | 1 + src/libstd/build.rs | 4 +++ src/test/ui/consts/const-size_of-cycle.rs | 2 ++ .../ui/impl-trait/impl-generic-mismatch.rs | 3 ++ .../impl-trait/impl-generic-mismatch.stderr | 6 ++-- 14 files changed, 71 insertions(+), 15 deletions(-) diff --git a/config.toml.example b/config.toml.example index 35f69cd05b607..d569bede0e1ab 100644 --- a/config.toml.example +++ b/config.toml.example @@ -373,6 +373,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 bf4d39c4947e5..872ff132a6998 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -108,6 +108,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>, @@ -319,6 +320,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. @@ -554,6 +556,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 caf38d766f54e..8b115b439ed05 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 { @@ -369,8 +370,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++"); @@ -676,7 +677,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 f762d9414cff3..911e16423ccf1 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"; @@ -1140,7 +1140,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/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/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/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` From 09973d227d0cb61eadea535d678febcfd94b50c9 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 11 Sep 2018 08:31:47 +0200 Subject: [PATCH 06/14] Add some unit tests for find_best_match_for_name There were only some UI tests that covered this function. Since there's more diagnostic work going on, I think it makes sense to have this unit tested. --- src/libsyntax/util/lev_distance.rs | 42 ++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) 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")) + ); + }) +} From dfd04e1eb4927917216b5a2f4b977da2c326ca13 Mon Sep 17 00:00:00 2001 From: James Duley Date: Tue, 11 Sep 2018 17:14:08 +0100 Subject: [PATCH 07/14] Update stage0 to latest beta Fixes bootstrap on AArch64 --- src/stage0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 3d7099a9682e1911b18cf440738ab97ae2fecc6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 14 Aug 2018 16:46:28 -0700 Subject: [PATCH 08/14] Do not emit E0277 on incorrect tuple destructured binding --- src/librustc_typeck/check/_match.rs | 15 ++++++++-- src/librustc_typeck/check/demand.rs | 1 + .../ui/elide-errors-on-mismatched-tuple.rs | 28 +++++++++++++++++++ .../elide-errors-on-mismatched-tuple.stderr | 12 ++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/elide-errors-on-mismatched-tuple.rs create mode 100644 src/test/ui/elide-errors-on-mismatched-tuple.stderr diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 2a8ee4bd8df0e..ca2b892018b5f 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -299,10 +299,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 self.has_errors.get() { + let element_tys_iter = (0..max_len).map(|_| tcx.types.err); + let element_tys = tcx.mk_type_list(element_tys_iter); + for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk(elem, &tcx.types.err, def_bm, true); + } + tcx.mk_ty(ty::TyTuple(element_tys)) + } 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/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 4e22ead8db987..47bbc95aa496b 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -50,6 +50,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) { + self.has_errors.set(true); err.emit(); } } 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`. From 633a47becb0a64156694827fa44481b16cb4c891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 19 Aug 2018 15:12:09 -0700 Subject: [PATCH 09/14] Simplify the recovered tuple ty --- src/librustc_typeck/check/_match.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index ca2b892018b5f..b7b1751a8ea5f 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -301,11 +301,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.demand_eqtype(pat.span, expected, pat_ty); if self.has_errors.get() { let element_tys_iter = (0..max_len).map(|_| tcx.types.err); - let element_tys = tcx.mk_type_list(element_tys_iter); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat_walk(elem, &tcx.types.err, def_bm, true); } - tcx.mk_ty(ty::TyTuple(element_tys)) + 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); From 5f8bf91e968b1816f9a1c746749c2136069fbcd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Sep 2018 17:06:11 -0700 Subject: [PATCH 10/14] address review comment, reduce scope --- src/librustc_typeck/check/_match.rs | 4 ++-- src/librustc_typeck/check/demand.rs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index b7b1751a8ea5f..a7b266143ba92 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -298,8 +298,8 @@ 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); - if self.has_errors.get() { + if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) { + err.emit(); 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); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 47bbc95aa496b..4e22ead8db987 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -50,7 +50,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) { - self.has_errors.set(true); err.emit(); } } From 3d6c2606a4cbb0f23f31f7dcf3c5e365e7fa402a Mon Sep 17 00:00:00 2001 From: Andrew Xu Date: Wed, 12 Sep 2018 12:27:28 +0800 Subject: [PATCH 11/14] Add a test that tries to modify static memory at compile-time --- .../const-eval/mod-static-with-const-fn.rs | 37 +++++++++++++++++++ .../mod-static-with-const-fn.stderr | 18 +++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/test/ui/consts/const-eval/mod-static-with-const-fn.rs create mode 100644 src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr 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`. From 3c1efcd6a738ce4aa256e49a2506eec5804c75aa Mon Sep 17 00:00:00 2001 From: Aaron Power Date: Wed, 12 Sep 2018 11:19:23 +0100 Subject: [PATCH 12/14] Updated 1.29 release notes with --document-private-items flag --- RELEASES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 7e727e0d41bb3..c1884c2732dc3 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/ From 63cd81c7d6eecc580b72fe1b5028a35ca9e19ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 12 Sep 2018 10:47:55 -0700 Subject: [PATCH 13/14] Add comment explaining reasoning --- src/librustc_typeck/check/_match.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index a7b266143ba92..7f65a5f0b5a63 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -300,6 +300,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); 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); From f656fe3b5df0cea8a1c93077a2208e56e8fdbe9f Mon Sep 17 00:00:00 2001 From: Kazuyoshi Kato Date: Wed, 12 Sep 2018 21:21:43 -0700 Subject: [PATCH 14/14] COMPILER_TESTS.md has been moved The document is now hosted at rust-lang-nursery.github.io. --- CONTRIBUTING.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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/