Skip to content

Commit

Permalink
Auto merge of rust-lang#71258 - Mark-Simulacrum:beta-next, r=Mark-Sim…
Browse files Browse the repository at this point in the history
…ulacrum

[beta] backports

This includes:
* Do not reuse post LTO products when exports change rust-lang#71131
* macro_rules: `NtLifetime` cannot start with an identifier rust-lang#70768
* Update RELEASES.md for 1.43.0 rust-lang#70354

r? @ghost
  • Loading branch information
bors committed Apr 18, 2020
2 parents 934ae77 + 6d0fbd1 commit 062dea0
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 27 deletions.
152 changes: 149 additions & 3 deletions 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<Arc<[T]>>`,`TryFrom<Box<[T]>>`, and `TryFrom<Rc<[T]>>`
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<str>`.][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_<name>` pointing to a binary's
executable path when running integration tests or benchmarks.][cargo/7697]
`<name>` 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)
==========================

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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).
Expand Down
91 changes: 69 additions & 22 deletions src/librustc_codegen_llvm/back/lto.rs
Expand Up @@ -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");
Expand All @@ -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.)
Expand All @@ -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);
Expand Down Expand Up @@ -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<String, Vec<String>>,
// key = llvm name of exporting module, value = list of modules it exports to
exports: FxHashMap<String, Vec<String>>,
}

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)?;
Expand All @@ -906,16 +939,20 @@ impl ThinLTOImports {
Ok(())
}

fn load_from_file(path: &Path) -> io::Result<ThinLTOImports> {
fn load_from_file(path: &Path) -> io::Result<ThinLTOImportMaps> {
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<String> = None;
let mut current_imports: Vec<String> = 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 &current_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
Expand All @@ -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);
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_expand/mbe/macro_parser.rs
Expand Up @@ -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,
}
}
Expand Down
26 changes: 26 additions & 0 deletions 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() }

0 comments on commit 062dea0

Please sign in to comment.