Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[beta] backports #71258

Merged
merged 6 commits into from
Apr 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 149 additions & 3 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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() }
Loading