diff --git a/RELEASES.md b/RELEASES.md index 7e18f1befddec..36597b1864f25 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,152 @@ +Version 1.43.0 (2020-04-23) +========================== + +Language +-------- +- [Fixed using binary operations with `&{number}` (e.g. `&1.0`) not having + the type inferred correctly.][68129] +- [Attributes such as `#[cfg()]` can now be used on `if` expressions.][69201] + +**Syntax only changes** +- [Allow `type Foo: Ord` syntactically.][69361] +- [Fuse associated and extern items up to defaultness.][69194] +- [Syntactically allow `self` in all `fn` contexts.][68764] +- [Merge `fn` syntax + cleanup item parsing.][68728] +- [`item` macro fragments can be interpolated into `trait`s, `impl`s, and `extern` blocks.][69366] + For example, you may now write: + ```rust + macro_rules! mac_trait { + ($i:item) => { + trait T { $i } + } + } + mac_trait! { + fn foo() {} + } + ``` + +These are still rejected *semantically*, so you will likely receive an error but +these changes can be seen and parsed by macros and +conditional compilation. + + +Compiler +-------- +- [You can now pass multiple lint flags to rustc to override the previous + flags.][67885] For example; `rustc -D unused -A unused-variables` denies + everything in the `unused` lint group except `unused-variables` which + is explicitly allowed. However, passing `rustc -A unused-variables -D unused` denies + everything in the `unused` lint group **including** `unused-variables` since + the allow flag is specified before the deny flag (and therefore overridden). +- [rustc will now prefer your system MinGW libraries over its bundled libraries + if they are available on `windows-gnu`.][67429] +- [rustc now buffers errors/warnings printed in JSON.][69227] + +Libraries +--------- +- [`Arc<[T; N]>`, `Box<[T; N]>`, and `Rc<[T; N]>`, now implement + `TryFrom>`,`TryFrom>`, and `TryFrom>` + respectively.][69538] **Note** These conversions are only available when `N` + is `0..=32`. +- [You can now use associated constants on floats and integers directly, rather + than having to import the module.][68952] e.g. You can now write `u32::MAX` or + `f32::NAN` with no imports. +- [`u8::is_ascii` is now `const`.][68984] +- [`String` now implements `AsMut`.][68742] +- [Added the `primitive` module to `std` and `core`.][67637] This module + reexports Rust's primitive types. This is mainly useful in macros + where you want avoid these types being shadowed. +- [Relaxed some of the trait bounds on `HashMap` and `HashSet`.][67642] +- [`string::FromUtf8Error` now implements `Clone + Eq`.][68738] + +Stabilized APIs +--------------- +- [`Once::is_completed`] +- [`f32::LOG10_2`] +- [`f32::LOG2_10`] +- [`f64::LOG10_2`] +- [`f64::LOG2_10`] +- [`iter::once_with`] + +Cargo +----- +- [You can now set config `[profile]`s in your `.cargo/config`, or through + your environment.][cargo/7823] +- [Cargo will now set `CARGO_BIN_EXE_` pointing to a binary's + executable path when running integration tests or benchmarks.][cargo/7697] + `` is the name of your binary as-is e.g. If you wanted the executable + path for a binary named `my-program`you would use `env!("CARGO_BIN_EXE_my-program")`. + +Misc +---- +- [Certain checks in the `const_err` lint were deemed unrelated to const + evaluation][69185], and have been moved to the `unconditional_panic` and + `arithmetic_overflow` lints. + +Compatibility Notes +------------------- + +- [Having trailing syntax in the `assert!` macro is now a hard error.][69548] This + has been a warning since 1.36.0. +- [Fixed `Self` not having the correctly inferred type.][69340] This incorrectly + led to some instances being accepted, and now correctly emits a hard error. + +[69340]: https://github.com/rust-lang/rust/pull/69340 + +Internal Only +------------- +These changes provide no direct user facing benefits, but represent significant +improvements to the internals and overall performance of `rustc` and +related tools. + +- [All components are now built with `opt-level=3` instead of `2`.][67878] +- [Improved how rustc generates drop code.][67332] +- [Improved performance from `#[inline]`-ing certain hot functions.][69256] +- [traits: preallocate 2 Vecs of known initial size][69022] +- [Avoid exponential behaviour when relating types][68772] +- [Skip `Drop` terminators for enum variants without drop glue][68943] +- [Improve performance of coherence checks][68966] +- [Deduplicate types in the generator witness][68672] +- [Invert control in struct_lint_level.][68725] + +[67332]: https://github.com/rust-lang/rust/pull/67332/ +[67429]: https://github.com/rust-lang/rust/pull/67429/ +[67637]: https://github.com/rust-lang/rust/pull/67637/ +[67642]: https://github.com/rust-lang/rust/pull/67642/ +[67878]: https://github.com/rust-lang/rust/pull/67878/ +[67885]: https://github.com/rust-lang/rust/pull/67885/ +[68129]: https://github.com/rust-lang/rust/pull/68129/ +[68672]: https://github.com/rust-lang/rust/pull/68672/ +[68725]: https://github.com/rust-lang/rust/pull/68725/ +[68728]: https://github.com/rust-lang/rust/pull/68728/ +[68738]: https://github.com/rust-lang/rust/pull/68738/ +[68742]: https://github.com/rust-lang/rust/pull/68742/ +[68764]: https://github.com/rust-lang/rust/pull/68764/ +[68772]: https://github.com/rust-lang/rust/pull/68772/ +[68943]: https://github.com/rust-lang/rust/pull/68943/ +[68952]: https://github.com/rust-lang/rust/pull/68952/ +[68966]: https://github.com/rust-lang/rust/pull/68966/ +[68984]: https://github.com/rust-lang/rust/pull/68984/ +[69022]: https://github.com/rust-lang/rust/pull/69022/ +[69185]: https://github.com/rust-lang/rust/pull/69185/ +[69194]: https://github.com/rust-lang/rust/pull/69194/ +[69201]: https://github.com/rust-lang/rust/pull/69201/ +[69227]: https://github.com/rust-lang/rust/pull/69227/ +[69548]: https://github.com/rust-lang/rust/pull/69548/ +[69256]: https://github.com/rust-lang/rust/pull/69256/ +[69361]: https://github.com/rust-lang/rust/pull/69361/ +[69366]: https://github.com/rust-lang/rust/pull/69366/ +[69538]: https://github.com/rust-lang/rust/pull/69538/ +[cargo/7823]: https://github.com/rust-lang/cargo/pull/7823 +[cargo/7697]: https://github.com/rust-lang/cargo/pull/7697 +[`Once::is_completed`]: https://doc.rust-lang.org/std/sync/struct.Once.html#method.is_completed +[`f32::LOG10_2`]: https://doc.rust-lang.org/std/f32/consts/constant.LOG10_2.html +[`f32::LOG2_10`]: https://doc.rust-lang.org/std/f32/consts/constant.LOG2_10.html +[`f64::LOG10_2`]: https://doc.rust-lang.org/std/f64/consts/constant.LOG10_2.html +[`f64::LOG2_10`]: https://doc.rust-lang.org/std/f64/consts/constant.LOG2_10.html +[`iter::once_with`]: https://doc.rust-lang.org/std/iter/fn.once_with.html + + Version 1.42.0 (2020-03-12) ========================== @@ -4838,7 +4987,6 @@ Version 1.11.0 (2016-08-18) Language -------- -* [`cfg_attr` works on `path` attributes](https://github.com/rust-lang/rust/pull/34546) * [Support nested `cfg_attr` attributes](https://github.com/rust-lang/rust/pull/34216) * [Allow statement-generating braced macro invocations at the end of blocks](https://github.com/rust-lang/rust/pull/34436) * [Macros can be expanded inside of trait definitions](https://github.com/rust-lang/rust/pull/34213) @@ -4957,8 +5105,6 @@ Version 1.10.0 (2016-07-07) Language -------- -* [Allow `concat_idents!` in type positions as well as in expression - positions](https://github.com/rust-lang/rust/pull/33735). * [`Copy` types are required to have a trivial implementation of `Clone`](https://github.com/rust-lang/rust/pull/33420). [RFC 1521](https://github.com/rust-lang/rfcs/blob/master/text/1521-copy-clone-semantics.md). * [Single-variant enums support the `#[repr(..)]` attribute](https://github.com/rust-lang/rust/pull/33355). diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 310cae978bf5e..447ba8c8a8ae6 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -463,15 +463,18 @@ fn thin_lto( // If previous imports have been deleted, or we get an IO error // reading the file storing them, then we'll just use `None` as the // prev_import_map, which will force the code to be recompiled. - let prev = - if path.exists() { ThinLTOImports::load_from_file(&path).ok() } else { None }; - let curr = ThinLTOImports::from_thin_lto_data(data); + let prev = if path.exists() { + ThinLTOImportMaps::load_from_file(&path).ok() + } else { + None + }; + let curr = ThinLTOImportMaps::from_thin_lto_data(data); (Some(path), prev, curr) } else { // If we don't compile incrementally, we don't need to load the // import data from LLVM. assert!(green_modules.is_empty()); - let curr = ThinLTOImports::default(); + let curr = ThinLTOImportMaps::default(); (None, None, curr) }; info!("thin LTO import map loaded"); @@ -497,10 +500,14 @@ fn thin_lto( let module_name = module_name_to_str(module_name); // If (1.) the module hasn't changed, and (2.) none of the modules - // it imports from has changed, *and* (3.) the import-set itself has - // not changed from the previous compile when it was last - // ThinLTO'ed, then we can re-use the post-ThinLTO version of the - // module. Otherwise, freshly perform LTO optimization. + // it imports from nor exports to have changed, *and* (3.) the + // import and export sets themselves have not changed from the + // previous compile when it was last ThinLTO'ed, then we can re-use + // the post-ThinLTO version of the module. Otherwise, freshly + // perform LTO optimization. + // + // (Note that globally, the export set is just the inverse of the + // import set.) // // This strategy means we can always save the computed imports as // canon: when we reuse the post-ThinLTO version, condition (3.) @@ -509,19 +516,30 @@ fn thin_lto( // version, the current import set *is* the correct one, since we // are doing the ThinLTO in this current compilation cycle.) // - // See rust-lang/rust#59535. + // For more discussion, see rust-lang/rust#59535 (where the import + // issue was discovered) and rust-lang/rust#69798 (where the + // analogous export issue was discovered). if let (Some(prev_import_map), true) = (prev_import_map.as_ref(), green_modules.contains_key(module_name)) { assert!(cgcx.incr_comp_session_dir.is_some()); - let prev_imports = prev_import_map.modules_imported_by(module_name); - let curr_imports = curr_import_map.modules_imported_by(module_name); + let prev_imports = prev_import_map.imports_of(module_name); + let curr_imports = curr_import_map.imports_of(module_name); + let prev_exports = prev_import_map.exports_of(module_name); + let curr_exports = curr_import_map.exports_of(module_name); let imports_all_green = curr_imports .iter() .all(|imported_module| green_modules.contains_key(imported_module)); + let exports_all_green = curr_exports + .iter() + .all(|exported_module| green_modules.contains_key(exported_module)); - if imports_all_green && equivalent_as_sets(prev_imports, curr_imports) { + if imports_all_green + && equivalent_as_sets(prev_imports, curr_imports) + && exports_all_green + && equivalent_as_sets(prev_exports, curr_exports) + { let work_product = green_modules[module_name].clone(); copy_jobs.push(work_product); info!(" - {}: re-used", module_name); @@ -881,17 +899,32 @@ pub unsafe fn optimize_thin_module( Ok(module) } +/// Summarizes module import/export relationships used by LLVM's ThinLTO pass. +/// +/// Note that we tend to have two such instances of `ThinLTOImportMaps` in use: +/// one loaded from a file that represents the relationships used during the +/// compilation associated with the incremetnal build artifacts we are +/// attempting to reuse, and another constructed via `from_thin_lto_data`, which +/// captures the relationships of ThinLTO in the current compilation. #[derive(Debug, Default)] -pub struct ThinLTOImports { +pub struct ThinLTOImportMaps { // key = llvm name of importing module, value = list of modules it imports from imports: FxHashMap>, + // key = llvm name of exporting module, value = list of modules it exports to + exports: FxHashMap>, } -impl ThinLTOImports { - fn modules_imported_by(&self, llvm_module_name: &str) -> &[String] { +impl ThinLTOImportMaps { + /// Returns modules imported by `llvm_module_name` during some ThinLTO pass. + fn imports_of(&self, llvm_module_name: &str) -> &[String] { self.imports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[]) } + /// Returns modules exported by `llvm_module_name` during some ThinLTO pass. + fn exports_of(&self, llvm_module_name: &str) -> &[String] { + self.exports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[]) + } + fn save_to_file(&self, path: &Path) -> io::Result<()> { use std::io::Write; let file = File::create(path)?; @@ -906,16 +939,20 @@ impl ThinLTOImports { Ok(()) } - fn load_from_file(path: &Path) -> io::Result { + fn load_from_file(path: &Path) -> io::Result { use std::io::BufRead; let mut imports = FxHashMap::default(); - let mut current_module = None; - let mut current_imports = vec![]; + let mut exports: FxHashMap<_, Vec<_>> = FxHashMap::default(); + let mut current_module: Option = None; + let mut current_imports: Vec = vec![]; let file = File::open(path)?; for line in io::BufReader::new(file).lines() { let line = line?; if line.is_empty() { let importing_module = current_module.take().expect("Importing module not set"); + for imported in ¤t_imports { + exports.entry(imported.clone()).or_default().push(importing_module.clone()); + } imports.insert(importing_module, mem::replace(&mut current_imports, vec![])); } else if line.starts_with(' ') { // Space marks an imported module @@ -927,17 +964,17 @@ impl ThinLTOImports { current_module = Some(line.trim().to_string()); } } - Ok(ThinLTOImports { imports }) + Ok(ThinLTOImportMaps { imports, exports }) } /// Loads the ThinLTO import map from ThinLTOData. - unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports { + unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImportMaps { unsafe extern "C" fn imported_module_callback( payload: *mut libc::c_void, importing_module_name: *const libc::c_char, imported_module_name: *const libc::c_char, ) { - let map = &mut *(payload as *mut ThinLTOImports); + let map = &mut *(payload as *mut ThinLTOImportMaps); let importing_module_name = CStr::from_ptr(importing_module_name); let importing_module_name = module_name_to_str(&importing_module_name); let imported_module_name = CStr::from_ptr(imported_module_name); @@ -951,8 +988,18 @@ impl ThinLTOImports { .get_mut(importing_module_name) .unwrap() .push(imported_module_name.to_owned()); + + if !map.exports.contains_key(imported_module_name) { + map.exports.insert(imported_module_name.to_owned(), vec![]); + } + + map.exports + .get_mut(imported_module_name) + .unwrap() + .push(importing_module_name.to_owned()); } - let mut map = ThinLTOImports::default(); + + let mut map = ThinLTOImportMaps::default(); llvm::LLVMRustGetThinLTOModuleImports( data, imported_module_callback, diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index a035461acc6e8..5f75b99d91b7c 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -762,7 +762,7 @@ fn may_begin_with(token: &Token, name: Name) -> bool { /// Checks whether the non-terminal may contain a single (non-keyword) identifier. fn may_be_ident(nt: &token::Nonterminal) -> bool { match *nt { - token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) => false, + token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_) => false, _ => true, } } diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_export_added.rs b/src/test/incremental/thinlto/cgu_invalidated_when_export_added.rs new file mode 100644 index 0000000000000..4d48a5f0ac528 --- /dev/null +++ b/src/test/incremental/thinlto/cgu_invalidated_when_export_added.rs @@ -0,0 +1,26 @@ +// revisions: cfail1 cfail2 +// build-pass + +// rust-lang/rust#69798: +// +// This is analgous to cgu_invalidated_when_import_added, but it covers a +// problem uncovered where a change to the *export* set caused a link failure +// when reusing post-LTO optimized object code. + +pub struct Foo {} +impl Drop for Foo { + fn drop(&mut self) { + println!("Dropping Foo"); + } +} +#[no_mangle] +pub extern "C" fn run() { + thread_local! { pub static FOO : Foo = Foo { } ; } + + #[cfg(cfail2)] + { + FOO.with(|_f| ()) + } +} + +pub fn main() { run() } diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_export_removed.rs b/src/test/incremental/thinlto/cgu_invalidated_when_export_removed.rs new file mode 100644 index 0000000000000..e85b4856f3a96 --- /dev/null +++ b/src/test/incremental/thinlto/cgu_invalidated_when_export_removed.rs @@ -0,0 +1,26 @@ +// revisions: cfail1 cfail2 +// build-pass + +// rust-lang/rust#69798: +// +// This is analgous to cgu_invalidated_when_export_added, but it covers the +// other direction. This is analogous to cgu_invalidated_when_import_added: we +// include it, because it may uncover bugs in variant implementation strategies. + +pub struct Foo {} +impl Drop for Foo { + fn drop(&mut self) { + println!("Dropping Foo"); + } +} +#[no_mangle] +pub extern "C" fn run() { + thread_local! { pub static FOO : Foo = Foo { } ; } + + #[cfg(cfail1)] + { + FOO.with(|_f| ()) + } +} + +pub fn main() { run() } diff --git a/src/test/ui/macros/issue-70446.rs b/src/test/ui/macros/issue-70446.rs new file mode 100644 index 0000000000000..407094d55ffef --- /dev/null +++ b/src/test/ui/macros/issue-70446.rs @@ -0,0 +1,13 @@ +// check-pass + +macro_rules! foo { + ($(: $p:path)? $(: $l:lifetime)? ) => { bar! {$(: $p)? $(: $l)? } }; +} + +macro_rules! bar { + ($(: $p:path)? $(: $l:lifetime)? ) => {}; +} + +foo! {: 'a } + +fn main() {} diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 25e684ff43d77..1a00011965d59 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -40,7 +40,7 @@ 'adamgreig', 'andre-richter', 'jamesmunns', 'korken89', 'ryankurte', 'thejpster', 'therealprof', }, - 'edition-guide': {'ehuss', 'Centril', 'steveklabnik'}, + 'edition-guide': {'ehuss', 'steveklabnik'}, 'rustc-dev-guide': {'mark-i-m', 'spastorino', 'amanjeev', 'JohnTitor'}, }