From 1825810a898842b4660fd684cea66906b7e32500 Mon Sep 17 00:00:00 2001 From: Soveu Date: Tue, 16 Feb 2021 18:48:42 +0100 Subject: [PATCH 01/24] Vec::dedup optimization --- library/alloc/src/vec/mod.rs | 50 +++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index b6166617789a0..88f9f624aba2d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1514,15 +1514,53 @@ impl Vec { /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); /// ``` #[stable(feature = "dedup_by", since = "1.16.0")] - pub fn dedup_by(&mut self, same_bucket: F) + pub fn dedup_by(&mut self, mut same_bucket: F) where F: FnMut(&mut T, &mut T) -> bool, { - let len = { - let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket); - dedup.len() - }; - self.truncate(len); + let len = self.len(); + if len <= 1 { + return; + } + + let ptr = self.as_mut_ptr(); + /* Offset of the element we want to check if it is duplicate */ + let mut read: usize = 1; + /* Offset of the place where we want to place the non-duplicate + * when we find it. */ + let mut write: usize = 1; + + /* Drop items while going through Vec, it should be more efficient than + * doing slice partition_dedup + truncate */ + + /* INVARIANT: len > read >= write > write-1 >= 0 + * SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr + * are always in-bounds and read_ptr never aliases prev_ptr */ + unsafe { + while read < len { + let read_ptr = ptr.add(read); + let prev_ptr = ptr.add(write.wrapping_sub(1)); + + if same_bucket(&mut *read_ptr, &mut *prev_ptr) { + /* We have found duplicate, drop it in-place */ + ptr::drop_in_place(read_ptr); + } else { + let write_ptr = ptr.add(write); + + /* Looks like doing just `copy` can be faster than + * conditional `copy_nonoverlapping` */ + ptr::copy(read_ptr, write_ptr, 1); + + /* We have filled that place, so go further */ + write += 1; + } + + read += 1; + } + + /* `write` items are inside vec, rest is already dropped */ + self.set_len(write); + } } /// Appends an element to the back of a collection. From c114894b90971ad7c6743ca5961f276cae1e2b27 Mon Sep 17 00:00:00 2001 From: Soveu Date: Wed, 17 Feb 2021 17:21:12 +0100 Subject: [PATCH 02/24] Vec::dedup optimization - panic gracefully --- library/alloc/src/vec/mod.rs | 81 +++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 16 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 88f9f624aba2d..e65adb6c77eda 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1523,43 +1523,92 @@ impl Vec { return; } - let ptr = self.as_mut_ptr(); - /* Offset of the element we want to check if it is duplicate */ - let mut read: usize = 1; - /* Offset of the place where we want to place the non-duplicate - * when we find it. */ - let mut write: usize = 1; + /* INVARIANT: vec.len() > read >= write > write-1 >= 0 */ + struct FillGapOnDrop<'a, T, A: core::alloc::Allocator> { + /* Offset of the element we want to check if it is duplicate */ + read: usize, + + /* Offset of the place where we want to place the non-duplicate + * when we find it. */ + write: usize, + + /* The Vec that would need correction if `same_bucket` panicked */ + vec: &'a mut Vec, + } + + impl<'a, T, A: core::alloc::Allocator> Drop for FillGapOnDrop<'a, T, A> { + fn drop(&mut self) { + /* This code gets executed either at the end of `dedup_by` or + * when `same_bucket` panics */ + + /* SAFETY (if finishing successfully): self.read == len, so + * no data is copied and length is set correctly */ + + /* SAFETY (if panicing): invariant guarantees that `read - write` + * and `len - read` never overflow and that the copy is always + * in-bounds. */ + unsafe { + let ptr = self.vec.as_mut_ptr(); + let len = self.vec.len(); + + /* How many items were left when `same_bucket` paniced. + * Basically vec[read..].len() */ + let items_left = len - self.read; + + /* Pointer to first item in vec[write..write+items_left] slice */ + let dropped_ptr = ptr.add(self.write); + /* Pointer to first item in vec[read..] slice */ + let valid_ptr = ptr.add(self.read); + + /* Copy `vec[read..]` to `vec[write..write+items_left]`. + * The slices can overlap, so `copy_nonoverlapping` cannot be used */ + ptr::copy(valid_ptr, dropped_ptr, items_left); + + /* How many items have been already dropped + * Basically vec[read..write].len() */ + let dropped = self.read - self.write; + + self.vec.set_len(len - dropped); + } + } + } + + let mut gap = FillGapOnDrop { read: 1, write: 1, vec: self }; + + let ptr = gap.vec.as_mut_ptr(); /* Drop items while going through Vec, it should be more efficient than * doing slice partition_dedup + truncate */ - /* INVARIANT: len > read >= write > write-1 >= 0 - * SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr + /* SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr * are always in-bounds and read_ptr never aliases prev_ptr */ unsafe { - while read < len { - let read_ptr = ptr.add(read); - let prev_ptr = ptr.add(write.wrapping_sub(1)); + while gap.read < len { + let read_ptr = ptr.add(gap.read); + let prev_ptr = ptr.add(gap.write.wrapping_sub(1)); if same_bucket(&mut *read_ptr, &mut *prev_ptr) { /* We have found duplicate, drop it in-place */ ptr::drop_in_place(read_ptr); } else { - let write_ptr = ptr.add(write); + let write_ptr = ptr.add(gap.write); /* Looks like doing just `copy` can be faster than * conditional `copy_nonoverlapping` */ ptr::copy(read_ptr, write_ptr, 1); /* We have filled that place, so go further */ - write += 1; + gap.write += 1; } - read += 1; + gap.read += 1; } - /* `write` items are inside vec, rest is already dropped */ - self.set_len(write); + /* Technically we could let `gap` clean up with its Drop, but + * when `same_bucket` is guaranteed to not panic, this bloats a little + * the codegen, so we just do it manually */ + gap.vec.set_len(gap.write); + mem::forget(gap); } } From 12c6a12d62fda3d5d070fe3915f03154ff7c80df Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Thu, 18 Feb 2021 14:27:11 -0500 Subject: [PATCH 03/24] Emit error when trying to use assembler syntax directives in `asm!` --- compiler/rustc_builtin_macros/src/asm.rs | 53 +++++++++++++++++++++++- src/test/ui/asm/inline-syntax.rs | 14 +++++++ src/test/ui/asm/inline-syntax.stderr | 36 ++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/asm/inline-syntax.rs create mode 100644 src/test/ui/asm/inline-syntax.stderr diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 36cd6c281b42a..168dee6678d68 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -7,7 +7,10 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_expand::base::{self, *}; use rustc_parse::parser::Parser; use rustc_parse_format as parse; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::{ + symbol::{kw, sym, Symbol}, + BytePos, +}; use rustc_span::{InnerSpan, Span}; struct AsmArgs { @@ -465,6 +468,54 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P { + if let Some(idx) = s.find(".intel_syntax") { + let mut end = idx + ".intel_syntax".len(); + if let Some(prefix_idx) = s.split_at(end).1.find("noprefix") { + // Should be a space and it should be immediately after + if prefix_idx == 1 { + end += " noprefix".len(); + } + } + + let syntax_span = + template_span.from_inner(InnerSpan::new(idx + 1, end + 1)); + let mut err = ecx.struct_span_err(syntax_span, "intel sytnax is the default syntax, and trying to use this directive may cause issues"); + err.span_suggestion( + syntax_span, + "Remove this assembler directive", + s.replace(&s[idx..end], "").to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + } + + if let Some(idx) = s.find(".att_syntax") { + let mut end = idx + ".att_syntax".len(); + if let Some(prefix_idx) = s.split_at(end).1.find("noprefix") { + // Should be a space and it should be immediately after + if prefix_idx == 1 { + end += " noprefix".len(); + } + } + + let syntax_span = + template_span.from_inner(InnerSpan::new(idx + 1, end + 1)); + let mut err = ecx.struct_span_err(syntax_span, "using the .att_syntax directive may cause issues, use the att_syntax option instead"); + let asm_end = sp.hi() - BytePos(2); + let suggestions = vec![ + (syntax_span, "".to_string()), + ( + Span::new(asm_end, asm_end, sp.ctxt()), + ", options(att_syntax)".to_string(), + ), + ]; + err.multipart_suggestion( + "Remove the assembler directive and replace it with options(att_syntax)", + suggestions, + Applicability::MachineApplicable, + ); + err.emit(); + } template.push(ast::InlineAsmTemplatePiece::String(s.to_string())) } parse::Piece::NextArgument(arg) => { diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs new file mode 100644 index 0000000000000..ec8ff0718857b --- /dev/null +++ b/src/test/ui/asm/inline-syntax.rs @@ -0,0 +1,14 @@ +#![feature(asm, llvm_asm)] + +fn main() { + unsafe { + asm!(".intel_syntax noprefix", "nop"); + //~^ ERROR intel sytnax is the default syntax + asm!(".intel_syntax aaa noprefix", "nop"); + //~^ ERROR intel sytnax is the default syntax + asm!(".att_syntax noprefix", "nop"); + //~^ ERROR using the .att_syntax directive may cause issues + asm!(".att_syntax bbb noprefix", "nop"); + //~^ ERROR using the .att_syntax directive may cause issues + } +} diff --git a/src/test/ui/asm/inline-syntax.stderr b/src/test/ui/asm/inline-syntax.stderr new file mode 100644 index 0000000000000..bd792660c6ae4 --- /dev/null +++ b/src/test/ui/asm/inline-syntax.stderr @@ -0,0 +1,36 @@ +error: intel sytnax is the default syntax, and trying to use this directive may cause issues + --> $DIR/inline-syntax.rs:5:15 + | +LL | asm!(".intel_syntax noprefix", "nop"); + | ^^^^^^^^^^^^^^^^^^^^^^ help: Remove this assembler directive + +error: intel sytnax is the default syntax, and trying to use this directive may cause issues + --> $DIR/inline-syntax.rs:7:15 + | +LL | asm!(".intel_syntax aaa noprefix", "nop"); + | ^^^^^^^^^^^^^ help: Remove this assembler directive: `aaa noprefix` + +error: using the .att_syntax directive may cause issues, use the att_syntax option instead + --> $DIR/inline-syntax.rs:9:15 + | +LL | asm!(".att_syntax noprefix", "nop"); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: Remove the assembler directive and replace it with options(att_syntax) + | +LL | asm!("", "nop", options(att_syntax)); + | -- ^^^^^^^^^^^^^^^^^^^^^ + +error: using the .att_syntax directive may cause issues, use the att_syntax option instead + --> $DIR/inline-syntax.rs:11:15 + | +LL | asm!(".att_syntax bbb noprefix", "nop"); + | ^^^^^^^^^^^ + | +help: Remove the assembler directive and replace it with options(att_syntax) + | +LL | asm!(" bbb noprefix", "nop", options(att_syntax)); + | -- ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + From 39dcd01bf5e0c69c487f18903f44074f49ef205b Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Sat, 20 Feb 2021 01:17:18 -0500 Subject: [PATCH 04/24] Take into account target default syntax --- compiler/rustc_builtin_macros/src/asm.rs | 120 ++++++++++++++--------- src/test/ui/asm/inline-syntax.rs | 13 ++- src/test/ui/asm/inline-syntax.stderr | 34 +++++-- 3 files changed, 107 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 168dee6678d68..bb529f9e5c2b4 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -12,6 +12,7 @@ use rustc_span::{ BytePos, }; use rustc_span::{InnerSpan, Span}; +use rustc_target::asm::InlineAsmArch; struct AsmArgs { templates: Vec>, @@ -427,6 +428,65 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P ast::LlvmAsmDialect::Intel, + _ => ast::LlvmAsmDialect::Att, + }; + + let snippet = snippet.trim_matches('"'); + match default_dialect { + ast::LlvmAsmDialect::Intel => { + if let Some(span) = check_syntax_directive(snippet, ".intel_syntax") { + let span = template_span.from_inner(span); + let mut err = ecx.struct_span_err(span, "intel syntax is the default syntax on this target, and trying to use this directive may cause issues"); + err.span_suggestion( + span, + "remove this assembler directive", + "".to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + } + + if let Some(span) = check_syntax_directive(snippet, ".att_syntax") { + let span = template_span.from_inner(span); + let mut err = ecx.struct_span_err(span, "using the .att_syntax directive may cause issues, use the att_syntax option instead"); + let asm_end = sp.hi() - BytePos(2); + let suggestions = vec![ + (span, "".to_string()), + ( + Span::new(asm_end, asm_end, sp.ctxt()), + ", options(att_syntax)".to_string(), + ), + ]; + err.multipart_suggestion( + "remove the assembler directive and replace it with options(att_syntax)", + suggestions, + Applicability::MachineApplicable, + ); + err.emit(); + } + } + ast::LlvmAsmDialect::Att => { + if let Some(span) = check_syntax_directive(snippet, ".att_syntax") { + let span = template_span.from_inner(span); + let mut err = ecx.struct_span_err(span, "att syntax is the default syntax on this target, and trying to use this directive may cause issues"); + err.span_suggestion( + span, + "remove this assembler directive", + "".to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + } + + // Use of .intel_syntax is ignored + } + } + } + let mut parser = parse::Parser::new( template_str, str_style, @@ -468,54 +528,6 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P { - if let Some(idx) = s.find(".intel_syntax") { - let mut end = idx + ".intel_syntax".len(); - if let Some(prefix_idx) = s.split_at(end).1.find("noprefix") { - // Should be a space and it should be immediately after - if prefix_idx == 1 { - end += " noprefix".len(); - } - } - - let syntax_span = - template_span.from_inner(InnerSpan::new(idx + 1, end + 1)); - let mut err = ecx.struct_span_err(syntax_span, "intel sytnax is the default syntax, and trying to use this directive may cause issues"); - err.span_suggestion( - syntax_span, - "Remove this assembler directive", - s.replace(&s[idx..end], "").to_string(), - Applicability::MachineApplicable, - ); - err.emit(); - } - - if let Some(idx) = s.find(".att_syntax") { - let mut end = idx + ".att_syntax".len(); - if let Some(prefix_idx) = s.split_at(end).1.find("noprefix") { - // Should be a space and it should be immediately after - if prefix_idx == 1 { - end += " noprefix".len(); - } - } - - let syntax_span = - template_span.from_inner(InnerSpan::new(idx + 1, end + 1)); - let mut err = ecx.struct_span_err(syntax_span, "using the .att_syntax directive may cause issues, use the att_syntax option instead"); - let asm_end = sp.hi() - BytePos(2); - let suggestions = vec![ - (syntax_span, "".to_string()), - ( - Span::new(asm_end, asm_end, sp.ctxt()), - ", options(att_syntax)".to_string(), - ), - ]; - err.multipart_suggestion( - "Remove the assembler directive and replace it with options(att_syntax)", - suggestions, - Applicability::MachineApplicable, - ); - err.emit(); - } template.push(ast::InlineAsmTemplatePiece::String(s.to_string())) } parse::Piece::NextArgument(arg) => { @@ -682,3 +694,15 @@ pub fn expand_asm<'cx>( } } } + +fn check_syntax_directive>(piece: S, syntax: &str) -> Option { + let piece = piece.as_ref(); + if let Some(idx) = piece.find(syntax) { + let end = + idx + &piece[idx..].find(|c| matches!(c, '\n' | ';')).unwrap_or(piece[idx..].len()); + // Offset by one because these represent the span with the " removed + Some(InnerSpan::new(idx + 1, end + 1)) + } else { + None + } +} diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs index ec8ff0718857b..31e7f2cc79662 100644 --- a/src/test/ui/asm/inline-syntax.rs +++ b/src/test/ui/asm/inline-syntax.rs @@ -3,12 +3,21 @@ fn main() { unsafe { asm!(".intel_syntax noprefix", "nop"); - //~^ ERROR intel sytnax is the default syntax + //~^ ERROR intel syntax is the default syntax on this target asm!(".intel_syntax aaa noprefix", "nop"); - //~^ ERROR intel sytnax is the default syntax + //~^ ERROR intel syntax is the default syntax on this target asm!(".att_syntax noprefix", "nop"); //~^ ERROR using the .att_syntax directive may cause issues asm!(".att_syntax bbb noprefix", "nop"); //~^ ERROR using the .att_syntax directive may cause issues + asm!(".intel_syntax noprefix; nop"); + //~^ ERROR intel syntax is the default syntax on this target + + asm!( + r" + .intel_syntax noprefix + nop" + ); + //~^^^ ERROR intel syntax is the default syntax on this target } } diff --git a/src/test/ui/asm/inline-syntax.stderr b/src/test/ui/asm/inline-syntax.stderr index bd792660c6ae4..241b302ad6472 100644 --- a/src/test/ui/asm/inline-syntax.stderr +++ b/src/test/ui/asm/inline-syntax.stderr @@ -1,14 +1,14 @@ -error: intel sytnax is the default syntax, and trying to use this directive may cause issues +error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues --> $DIR/inline-syntax.rs:5:15 | LL | asm!(".intel_syntax noprefix", "nop"); - | ^^^^^^^^^^^^^^^^^^^^^^ help: Remove this assembler directive + | ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive -error: intel sytnax is the default syntax, and trying to use this directive may cause issues +error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues --> $DIR/inline-syntax.rs:7:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); - | ^^^^^^^^^^^^^ help: Remove this assembler directive: `aaa noprefix` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive error: using the .att_syntax directive may cause issues, use the att_syntax option instead --> $DIR/inline-syntax.rs:9:15 @@ -16,7 +16,7 @@ error: using the .att_syntax directive may cause issues, use the att_syntax opti LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ | -help: Remove the assembler directive and replace it with options(att_syntax) +help: remove the assembler directive and replace it with options(att_syntax) | LL | asm!("", "nop", options(att_syntax)); | -- ^^^^^^^^^^^^^^^^^^^^^ @@ -25,12 +25,26 @@ error: using the .att_syntax directive may cause issues, use the att_syntax opti --> $DIR/inline-syntax.rs:11:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | -help: Remove the assembler directive and replace it with options(att_syntax) +help: remove the assembler directive and replace it with options(att_syntax) | -LL | asm!(" bbb noprefix", "nop", options(att_syntax)); - | -- ^^^^^^^^^^^^^^^^^^^^^ +LL | asm!("", "nop", options(att_syntax)); + | -- ^^^^^^^^^^^^^^^^^^^^^ + +error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues + --> $DIR/inline-syntax.rs:13:15 + | +LL | asm!(".intel_syntax noprefix; nop"); + | ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive + +error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues + --> $DIR/inline-syntax.rs:18:14 + | +LL | .intel_syntax noprefix + | ______________^ +LL | | nop" + | |_ help: remove this assembler directive -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors From 68f41b8328d76e171a17a0ac60351f576b9116b5 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 23 Feb 2021 00:41:41 -0500 Subject: [PATCH 05/24] Add more links between hash and btree collections - Link from `core::hash` to `HashMap` and `HashSet` - Link from HashMap and HashSet to the module-level documentation on when to use the collection - Link from several collections to Wikipedia articles on the general concept --- library/alloc/src/collections/btree/map.rs | 7 ++++--- library/core/src/hash/mod.rs | 10 ++++++++-- library/std/src/collections/hash/map.rs | 3 ++- library/std/src/collections/hash/set.rs | 3 ++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 801615b3dc261..a4bcfa33e0dce 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -20,15 +20,15 @@ use Entry::*; /// We might temporarily have fewer elements during methods. pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; -// A tree in a `BTreeMap` is a tree in the `node` module with addtional invariants: +// A tree in a `BTreeMap` is a tree in the `node` module with additional invariants: // - Keys must appear in ascending order (according to the key's type). // - If the root node is internal, it must contain at least 1 element. // - Every non-root node contains at least MIN_LEN elements. // -// An empty map may be represented both by the absense of a root node or by a +// An empty map may be represented both by the absence of a root node or by a // root node that is an empty leaf. -/// A map based on a B-Tree. +/// A map based on a [B-Tree]. /// /// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing /// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal @@ -62,6 +62,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; /// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and /// non-termination. /// +/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree /// [`Cell`]: core::cell::Cell /// [`RefCell`]: core::cell::RefCell /// diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index cd47f97496a4a..2ff87f4890727 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -1,7 +1,13 @@ //! Generic hashing support. //! -//! This module provides a generic way to compute the hash of a value. The -//! simplest way to make a type hashable is to use `#[derive(Hash)]`: +//! This module provides a generic way to compute the [hash] of a value. +//! Hashes are most commonly used with [`HashMap`] and [`HashSet`]. +//! +//! [hash]: https://en.wikipedia.org/wiki/Hash_function +//! [`HashMap`]: ../../std/collections/struct.HashMap.html +//! [`HashSet`]: ../../std/collections/struct.HashSet.html + +//! The simplest way to make a type hashable is to use `#[derive(Hash)]`: //! //! # Examples //! diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 27f7191831d41..95cb1fd1668b0 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -15,7 +15,7 @@ use crate::iter::{FromIterator, FusedIterator}; use crate::ops::Index; use crate::sys; -/// A hash map implemented with quadratic probing and SIMD lookup. +/// A [hash map] implemented with quadratic probing and SIMD lookup. /// /// By default, `HashMap` uses a hashing algorithm selected to provide /// resistance against HashDoS attacks. The algorithm is randomly seeded, and a @@ -60,6 +60,7 @@ use crate::sys; /// The original C++ version of SwissTable can be found [here], and this /// [CppCon talk] gives an overview of how the algorithm works. /// +/// [hash map]: crate::collections#use-a-hashmap-when /// [hashing algorithms available on crates.io]: https://crates.io/keywords/hasher /// [SwissTable]: https://abseil.io/blog/20180927-swisstables /// [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 912e975aa0a4c..8c801b9f1285d 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -19,7 +19,7 @@ use super::map::{map_try_reserve_error, RandomState}; // for `bucket.val` in the case of HashSet. I suppose we would need HKT // to get rid of it properly. -/// A hash set implemented as a `HashMap` where the value is `()`. +/// A [hash set] implemented as a `HashMap` where the value is `()`. /// /// As with the [`HashMap`] type, a `HashSet` requires that the elements /// implement the [`Eq`] and [`Hash`] traits. This can frequently be achieved by @@ -105,6 +105,7 @@ use super::map::{map_try_reserve_error, RandomState}; /// // use the values stored in the set /// ``` /// +/// [hash set]: crate::collections#use-the-set-variant-of-any-of-these-maps-when /// [`HashMap`]: crate::collections::HashMap /// [`RefCell`]: crate::cell::RefCell /// [`Cell`]: crate::cell::Cell From 05ae66607fe2aaab786e6444f4b674499fd79319 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Mon, 8 Mar 2021 12:16:12 -0500 Subject: [PATCH 06/24] Move default inline asm dialect to Session --- compiler/rustc_builtin_macros/src/asm.rs | 8 ++------ compiler/rustc_session/src/session.rs | 7 +++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index bb529f9e5c2b4..8d8b3f4f6aaac 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -12,7 +12,6 @@ use rustc_span::{ BytePos, }; use rustc_span::{InnerSpan, Span}; -use rustc_target::asm::InlineAsmArch; struct AsmArgs { templates: Vec>, @@ -403,6 +402,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P, sp: Span, args: AsmArgs) -> P ast::LlvmAsmDialect::Intel, - _ => ast::LlvmAsmDialect::Att, - }; - let snippet = snippet.trim_matches('"'); match default_dialect { ast::LlvmAsmDialect::Intel => { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a7ceb9e06a519..83ab066c7c3ad 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -784,6 +784,13 @@ impl Session { } } + pub fn inline_asm_dialect(&self) -> rustc_ast::LlvmAsmDialect { + match self.asm_arch { + Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) => rustc_ast::LlvmAsmDialect::Intel, + _ => rustc_ast::LlvmAsmDialect::Att, + } + } + pub fn relocation_model(&self) -> RelocModel { self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model) } From 4b13b8120e67e2b3173c8f6ce0d175847b745085 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Mon, 8 Mar 2021 23:48:08 -0500 Subject: [PATCH 07/24] Test x86 and arm outputs --- src/test/ui/asm/inline-syntax.arm.stderr | 14 +++++++++ src/test/ui/asm/inline-syntax.rs | 29 ++++++++++++++----- ...tax.stderr => inline-syntax.x86_64.stderr} | 12 ++++---- 3 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/asm/inline-syntax.arm.stderr rename src/test/ui/asm/{inline-syntax.stderr => inline-syntax.x86_64.stderr} (89%) diff --git a/src/test/ui/asm/inline-syntax.arm.stderr b/src/test/ui/asm/inline-syntax.arm.stderr new file mode 100644 index 0000000000000..b1b61f0211a37 --- /dev/null +++ b/src/test/ui/asm/inline-syntax.arm.stderr @@ -0,0 +1,14 @@ +error: att syntax is the default syntax on this target, and trying to use this directive may cause issues + --> $DIR/inline-syntax.rs:22:15 + | +LL | asm!(".att_syntax noprefix", "nop"); + | ^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive + +error: att syntax is the default syntax on this target, and trying to use this directive may cause issues + --> $DIR/inline-syntax.rs:25:15 + | +LL | asm!(".att_syntax bbb noprefix", "nop"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs index 31e7f2cc79662..9e9c7badfcace 100644 --- a/src/test/ui/asm/inline-syntax.rs +++ b/src/test/ui/asm/inline-syntax.rs @@ -1,23 +1,38 @@ -#![feature(asm, llvm_asm)] +// revisions: x86_64 arm +//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu +//[arm] compile-flags: --target armv7-unknown-linux-gnueabihf + +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +#[lang = "sized"] +trait Sized {} fn main() { unsafe { asm!(".intel_syntax noprefix", "nop"); - //~^ ERROR intel syntax is the default syntax on this target + //[x86_64]~^ ERROR intel syntax is the default syntax on this target asm!(".intel_syntax aaa noprefix", "nop"); - //~^ ERROR intel syntax is the default syntax on this target + //[x86_64]~^ ERROR intel syntax is the default syntax on this target asm!(".att_syntax noprefix", "nop"); - //~^ ERROR using the .att_syntax directive may cause issues + //[x86_64]~^ ERROR using the .att_syntax directive may cause issues + //[arm]~^^ att syntax is the default syntax on this target asm!(".att_syntax bbb noprefix", "nop"); - //~^ ERROR using the .att_syntax directive may cause issues + //[x86_64]~^ ERROR using the .att_syntax directive may cause issues + //[arm]~^^ att syntax is the default syntax on this target asm!(".intel_syntax noprefix; nop"); - //~^ ERROR intel syntax is the default syntax on this target + //[x86_64]~^ ERROR intel syntax is the default syntax on this target asm!( r" .intel_syntax noprefix nop" ); - //~^^^ ERROR intel syntax is the default syntax on this target + //[x86_64]~^^^ ERROR intel syntax is the default syntax on this target } } diff --git a/src/test/ui/asm/inline-syntax.stderr b/src/test/ui/asm/inline-syntax.x86_64.stderr similarity index 89% rename from src/test/ui/asm/inline-syntax.stderr rename to src/test/ui/asm/inline-syntax.x86_64.stderr index 241b302ad6472..c54c2742a5791 100644 --- a/src/test/ui/asm/inline-syntax.stderr +++ b/src/test/ui/asm/inline-syntax.x86_64.stderr @@ -1,17 +1,17 @@ error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:5:15 + --> $DIR/inline-syntax.rs:18:15 | LL | asm!(".intel_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:7:15 + --> $DIR/inline-syntax.rs:20:15 | LL | asm!(".intel_syntax aaa noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive error: using the .att_syntax directive may cause issues, use the att_syntax option instead - --> $DIR/inline-syntax.rs:9:15 + --> $DIR/inline-syntax.rs:22:15 | LL | asm!(".att_syntax noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | asm!("", "nop", options(att_syntax)); | -- ^^^^^^^^^^^^^^^^^^^^^ error: using the .att_syntax directive may cause issues, use the att_syntax option instead - --> $DIR/inline-syntax.rs:11:15 + --> $DIR/inline-syntax.rs:25:15 | LL | asm!(".att_syntax bbb noprefix", "nop"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,13 +33,13 @@ LL | asm!("", "nop", options(att_syntax)); | -- ^^^^^^^^^^^^^^^^^^^^^ error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:13:15 + --> $DIR/inline-syntax.rs:28:15 | LL | asm!(".intel_syntax noprefix; nop"); | ^^^^^^^^^^^^^^^^^^^^^^ help: remove this assembler directive error: intel syntax is the default syntax on this target, and trying to use this directive may cause issues - --> $DIR/inline-syntax.rs:18:14 + --> $DIR/inline-syntax.rs:33:14 | LL | .intel_syntax noprefix | ______________^ From 2abab1f688fe0d4a740b216b298f32fbb48b653b Mon Sep 17 00:00:00 2001 From: Soveu Date: Mon, 15 Mar 2021 20:24:35 +0100 Subject: [PATCH 08/24] Vec::dedup optimization - add tests --- library/alloc/tests/lib.rs | 1 + library/alloc/tests/vec.rs | 73 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index dd98f806451d8..fd1612f316bfd 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -21,6 +21,7 @@ #![feature(vecdeque_binary_search)] #![feature(slice_group_by)] #![feature(vec_extend_from_within)] +#![feature(slice_partition_dedup)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 2969da58d4268..1d28fc9eebf82 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2096,3 +2096,76 @@ fn test_extend_from_within() { assert_eq!(v, ["a", "b", "c", "b", "c", "a", "b"]); } + +#[test] +fn test_vec_dedup_by() { + let mut vec: Vec = vec![1, -1, 2, 3, 1, -5, 5, -2, 2]; + + vec.dedup_by(|a, b| a.abs() == b.abs()); + + assert_eq!(vec, [1, 2, 3, 1, -5, -2]); +} + +#[test] +fn test_vec_dedup_empty() { + let mut vec: Vec = Vec::new(); + + vec.dedup(); + + assert_eq!(vec, []); +} + +#[test] +fn test_vec_dedup_one() { + let mut vec = vec![12i32]; + + vec.dedup(); + + assert_eq!(vec, [12]); +} + +#[test] +fn test_vec_dedup_multiple_ident() { + let mut vec = vec![12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11]; + + vec.dedup(); + + assert_eq!(vec, [12, 11]); +} + +#[test] +fn test_vec_dedup_partialeq() { + #[derive(Debug)] + struct Foo(i32, i32); + + impl PartialEq for Foo { + fn eq(&self, other: &Foo) -> bool { + self.0 == other.0 + } + } + + let mut vec = vec![Foo(0, 1), Foo(0, 5), Foo(1, 7), Foo(1, 9)]; + + vec.dedup(); + assert_eq!(vec, [Foo(0, 1), Foo(1, 7)]); +} + +#[test] +fn test_vec_dedup() { + let mut vec: Vec = Vec::with_capacity(8); + let mut template = vec.clone(); + + for x in 0u8..255u8 { + vec.clear(); + template.clear(); + + let iter = (0..8).map(move |bit| (x >> bit) & 1 == 1); + vec.extend(iter); + template.extend_from_slice(&vec); + + let (dedup, _) = template.partition_dedup(); + vec.dedup(); + + assert_eq!(vec, dedup); + } +} From afdbc9ece176ccac7b1d156efcb397d089d88b5a Mon Sep 17 00:00:00 2001 From: Soveu Date: Mon, 15 Mar 2021 20:36:29 +0100 Subject: [PATCH 09/24] Vec::dedup optimization - finishing polishes --- library/alloc/src/vec/mod.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index e65adb6c77eda..19198d4eeefd9 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1538,13 +1538,9 @@ impl Vec { impl<'a, T, A: core::alloc::Allocator> Drop for FillGapOnDrop<'a, T, A> { fn drop(&mut self) { - /* This code gets executed either at the end of `dedup_by` or - * when `same_bucket` panics */ + /* This code gets executed when `same_bucket` panics */ - /* SAFETY (if finishing successfully): self.read == len, so - * no data is copied and length is set correctly */ - - /* SAFETY (if panicing): invariant guarantees that `read - write` + /* SAFETY: invariant guarantees that `read - write` * and `len - read` never overflow and that the copy is always * in-bounds. */ unsafe { @@ -1553,7 +1549,7 @@ impl Vec { /* How many items were left when `same_bucket` paniced. * Basically vec[read..].len() */ - let items_left = len - self.read; + let items_left = len.wrapping_sub(self.read); /* Pointer to first item in vec[write..write+items_left] slice */ let dropped_ptr = ptr.add(self.write); @@ -1566,7 +1562,7 @@ impl Vec { /* How many items have been already dropped * Basically vec[read..write].len() */ - let dropped = self.read - self.write; + let dropped = self.read.wrapping_sub(self.write); self.vec.set_len(len - dropped); } @@ -1574,7 +1570,6 @@ impl Vec { } let mut gap = FillGapOnDrop { read: 1, write: 1, vec: self }; - let ptr = gap.vec.as_mut_ptr(); /* Drop items while going through Vec, it should be more efficient than @@ -1593,8 +1588,9 @@ impl Vec { } else { let write_ptr = ptr.add(gap.write); - /* Looks like doing just `copy` can be faster than - * conditional `copy_nonoverlapping` */ + /* Because `read_ptr` can be equal to `write_ptr`, we either + * have to use `copy` or conditional `copy_nonoverlapping`. + * Looks like the first option is faster. */ ptr::copy(read_ptr, write_ptr, 1); /* We have filled that place, so go further */ From d6a7c1d47fdf68626b5535ff24bd115e4aba7d71 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 15 Mar 2021 15:54:25 -0400 Subject: [PATCH 10/24] Extend `proc_macro_back_compat` lint to `procedural-masquerade` We now lint on *any* use of `procedural-masquerade` crate. While this crate still exists, its main reverse dependency (`cssparser`) no longer depends on it. Any crates still depending off should stop doing so, as it only exists to support very old Rust versions. If a crate actually needs to support old versions of rustc via `procedural-masquerade`, then they'll just need to accept the warning until we remove it entirely (at the same time as the back-compat hack). The latest version of `procedural-masquerade` does not work with the latest rustc, but trying to check for the version seems like more trouble than it's worth. While working on this, I realized that the `proc-macro-hack` check was never actually doing anything. The corresponding enum variant in `proc-macro-hack` is named `Value` or `Nested` - it has never been called `Input`. Due to a strange Crater issue, the Crater run that tested adding this did *not* end up testing it - some of the crates that would have failed did not actually have their tests checked, making it seem as though the `proc-macro-hack` check was working. The Crater issue is being discussed at https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra/topic/Nearly.20identical.20Crater.20runs.20processed.20a.20crate.20differently/near/230406661 Despite the `proc-macro-hack` check not actually doing anything, we haven't gotten any reports from users about their build being broken. I went ahead and removed it entirely, since it's clear that no one is being affected by the `proc-macro-hack` regression in practice. --- compiler/rustc_ast/src/token.rs | 27 ------------- compiler/rustc_expand/src/base.rs | 40 +++++++++++++++++++ compiler/rustc_expand/src/proc_macro.rs | 3 +- .../rustc_expand/src/proc_macro_server.rs | 2 +- .../issue-73933-procedural-masquerade.rs | 13 ++++++ .../issue-73933-procedural-masquerade.stderr | 25 ++++++++++++ .../issue-73933-procedural-masquerade.stdout | 22 ++++++++++ 7 files changed, 103 insertions(+), 29 deletions(-) create mode 100644 src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs create mode 100644 src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr create mode 100644 src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 093f7f2668c46..7e58426d27de4 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -784,33 +784,6 @@ impl Nonterminal { NtTT(tt) => tt.span(), } } - - /// This nonterminal looks like some specific enums from - /// `proc-macro-hack` and `procedural-masquerade` crates. - /// We need to maintain some special pretty-printing behavior for them due to incorrect - /// asserts in old versions of those crates and their wide use in the ecosystem. - /// See issue #73345 for more details. - /// FIXME(#73933): Remove this eventually. - pub fn pretty_printing_compatibility_hack(&self) -> bool { - let item = match self { - NtItem(item) => item, - NtStmt(stmt) => match &stmt.kind { - ast::StmtKind::Item(item) => item, - _ => return false, - }, - _ => return false, - }; - - let name = item.ident.name; - if name == sym::ProceduralMasqueradeDummyType || name == sym::ProcMacroHack { - if let ast::ItemKind::Enum(enum_def, _) = &item.kind { - if let [variant] = &*enum_def.variants { - return variant.ident.name == sym::Input; - } - } - } - false - } } impl PartialEq for Nonterminal { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index dd93fe8350e42..ce65793051837 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -10,6 +10,8 @@ use rustc_attr::{self as attr, Deprecation, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{DiagnosticBuilder, ErrorReported}; +use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; +use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::DefId; @@ -1241,3 +1243,41 @@ pub fn get_exprs_from_tts( } Some(es) } + +/// This nonterminal looks like some specific enums from +/// `proc-macro-hack` and `procedural-masquerade` crates. +/// We need to maintain some special pretty-printing behavior for them due to incorrect +/// asserts in old versions of those crates and their wide use in the ecosystem. +/// See issue #73345 for more details. +/// FIXME(#73933): Remove this eventually. +pub(crate) fn pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &ParseSess) -> bool { + let item = match nt { + Nonterminal::NtItem(item) => item, + Nonterminal::NtStmt(stmt) => match &stmt.kind { + ast::StmtKind::Item(item) => item, + _ => return false, + }, + _ => return false, + }; + + let name = item.ident.name; + if name == sym::ProceduralMasqueradeDummyType { + if let ast::ItemKind::Enum(enum_def, _) = &item.kind { + if let [variant] = &*enum_def.variants { + if variant.ident.name == sym::Input { + sess.buffer_lint_with_diagnostic( + &PROC_MACRO_BACK_COMPAT, + item.ident.span, + ast::CRATE_NODE_ID, + "using `procedural-masquerade` crate", + BuiltinLintDiagnostics::ProcMacroBackCompat( + "The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. \ + Versions of this crate below 0.1.7 will eventually stop compiling.".to_string()) + ); + return true; + } + } + } + } + false +} diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 8cbaa7c945a81..61b776ff2d280 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -90,7 +90,8 @@ impl MultiItemModifier for ProcMacroDerive { } _ => unreachable!(), }; - let input = if item.pretty_printing_compatibility_hack() { + let input = if crate::base::pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess) + { TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into() } else { nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::Yes) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 837fad905800a..67edfe19da383 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -187,7 +187,7 @@ impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec)> delimiter: Delimiter::None, stream, span: DelimSpan::from_single(span), - flatten: nt.pretty_printing_compatibility_hack(), + flatten: crate::base::pretty_printing_compatibility_hack(&nt, sess), }) } } diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs new file mode 100644 index 0000000000000..abc3d2691a307 --- /dev/null +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs @@ -0,0 +1,13 @@ +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive(Print)] +enum ProceduralMasqueradeDummyType { //~ WARN using +//~| WARN this was previously + Input +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr new file mode 100644 index 0000000000000..0b930705e3510 --- /dev/null +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr @@ -0,0 +1,25 @@ +warning: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:8:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(proc_macro_back_compat)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + +warning: 1 warning emitted + +Future incompatibility report: Future breakage date: None, diagnostic: +warning: using `procedural-masquerade` crate + --> $DIR/issue-73933-procedural-masquerade.rs:8:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(proc_macro_back_compat)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling. + diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout new file mode 100644 index 0000000000000..8edd68f8a3b84 --- /dev/null +++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout @@ -0,0 +1,22 @@ +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #0 bytes(100..104), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: #0 bytes(105..134), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: #0 bytes(186..191), + }, + ], + span: #0 bytes(135..193), + }, +] From 2285f11724e2fa3251c94c9ab7672544099600e2 Mon Sep 17 00:00:00 2001 From: Soveu Date: Mon, 15 Mar 2021 21:26:22 +0100 Subject: [PATCH 11/24] Vec::dedup optimization - add test for panic --- library/alloc/tests/vec.rs | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 1d28fc9eebf82..536fb4af5647d 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -7,6 +7,7 @@ use std::mem::{size_of, swap}; use std::ops::Bound::*; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::rc::Rc; +use std::sync::atomic::{AtomicU32, Ordering}; use std::vec::{Drain, IntoIter}; struct DropCounter<'a> { @@ -2169,3 +2170,56 @@ fn test_vec_dedup() { assert_eq!(vec, dedup); } } + +#[test] +fn test_vec_dedup_panicking() { + #[derive(Debug)] + struct Panic { + drop_counter: &'static AtomicU32, + value: bool, + index: usize, + } + + impl PartialEq for Panic { + fn eq(&self, other: &Self) -> bool { + self.value == other.value + } + } + + impl Drop for Panic { + fn drop(&mut self) { + let x = self.drop_counter.fetch_add(1, Ordering::SeqCst); + assert!(x != 4); + } + } + + static DROP_COUNTER: AtomicU32 = AtomicU32::new(0); + let expected = [ + Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 }, + Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 }, + Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 }, + Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 }, + ]; + let mut vec = vec![ + Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 }, + // these elements get deduplicated + Panic { drop_counter: &DROP_COUNTER, value: false, index: 1 }, + Panic { drop_counter: &DROP_COUNTER, value: false, index: 2 }, + Panic { drop_counter: &DROP_COUNTER, value: false, index: 3 }, + Panic { drop_counter: &DROP_COUNTER, value: false, index: 4 }, + // here it panics + Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 }, + Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 }, + Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 }, + ]; + + let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + vec.dedup(); + })); + + let ok = vec.iter().zip(expected.iter()).all(|(x, y)| x.index == y.index); + + if !ok { + panic!("expected: {:?}\ngot: {:?}\n", expected, vec); + } +} From 1796cc0e6c43f1958d746c94608503c900b3a28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 13 Mar 2021 00:00:00 +0000 Subject: [PATCH 12/24] Make source-based code coverage compatible with MIR inlining When codegenning code coverage use the instance that coverage data was originally generated for, to ensure basic level of compatibility with MIR inlining. --- .../src/coverageinfo/mapgen.rs | 2 +- .../rustc_codegen_ssa/src/coverageinfo/map.rs | 21 +++++++--- .../rustc_codegen_ssa/src/mir/coverageinfo.rs | 25 +++++++---- .../rustc_codegen_ssa/src/mir/statement.rs | 2 +- .../rustc_mir/src/transform/coverage/query.rs | 41 +++++++++++++++---- compiler/rustc_mir/src/transform/inline.rs | 9 ---- compiler/rustc_session/src/config.rs | 19 --------- 7 files changed, 68 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 444a9d4ba0463..1cea927f50c45 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -254,7 +254,7 @@ fn save_function_record( /// /// 1. The file name of an "Unreachable" function must match the file name of the existing /// codegenned (covered) function to which the unreachable code regions will be added. -/// 2. The function to which the unreachable code regions will be added must not be a genaric +/// 2. The function to which the unreachable code regions will be added must not be a generic /// function (must not have type parameters) because the coverage tools will get confused /// if the codegenned function has more than one instantiation and additional `CodeRegion`s /// attached to only one of those instantiations. diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs index 549b8d41f5130..af6482fdbc24f 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::coverage::{ use rustc_middle::ty::Instance; use rustc_middle::ty::TyCtxt; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Expression { lhs: ExpressionOperandId, op: Op, @@ -64,7 +64,9 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Adds a code region to be counted by an injected counter intrinsic. pub fn add_counter(&mut self, id: CounterValueReference, region: CodeRegion) { - self.counters[id].replace(region).expect_none("add_counter called with duplicate `id`"); + if let Some(previous_region) = self.counters[id].replace(region.clone()) { + assert_eq!(previous_region, region, "add_counter: code region for id changed"); + } } /// Both counters and "counter expressions" (or simply, "expressions") can be operands in other @@ -94,9 +96,18 @@ impl<'tcx> FunctionCoverage<'tcx> { expression_id, lhs, op, rhs, region ); let expression_index = self.expression_index(u32::from(expression_id)); - self.expressions[expression_index] - .replace(Expression { lhs, op, rhs, region }) - .expect_none("add_counter_expression called with duplicate `id_descending_from_max`"); + if let Some(previous_expression) = self.expressions[expression_index].replace(Expression { + lhs, + op, + rhs, + region: region.clone(), + }) { + assert_eq!( + previous_expression, + Expression { lhs, op, rhs, region }, + "add_counter_expression: expression for id changed" + ); + } } /// Add a region that will be marked as "unreachable", with a constant "zero counter". diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index a115d35866638..5ab1baafb57de 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -2,27 +2,38 @@ use crate::traits::*; use rustc_middle::mir::coverage::*; use rustc_middle::mir::Coverage; +use rustc_middle::mir::SourceScope; use super::FunctionCx; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage) { + pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) { + // Determine the instance that coverage data was originally generated for. + let scope_data = &self.mir.source_scopes[scope]; + let instance = if let Some((inlined_instance, _)) = scope_data.inlined { + self.monomorphize(inlined_instance) + } else if let Some(inlined_scope) = scope_data.inlined_parent_scope { + self.monomorphize(self.mir.source_scopes[inlined_scope].inlined.unwrap().0) + } else { + self.instance + }; + let Coverage { kind, code_region } = coverage; match kind { CoverageKind::Counter { function_source_hash, id } => { - if bx.set_function_source_hash(self.instance, function_source_hash) { + if bx.set_function_source_hash(instance, function_source_hash) { // If `set_function_source_hash()` returned true, the coverage map is enabled, // so continue adding the counter. if let Some(code_region) = code_region { // Note: Some counters do not have code regions, but may still be referenced // from expressions. In that case, don't add the counter to the coverage map, // but do inject the counter intrinsic. - bx.add_coverage_counter(self.instance, id, code_region); + bx.add_coverage_counter(instance, id, code_region); } - let coverageinfo = bx.tcx().coverageinfo(self.instance.def_id()); + let coverageinfo = bx.tcx().coverageinfo(instance.def_id()); - let fn_name = bx.create_pgo_func_name_var(self.instance); + let fn_name = bx.create_pgo_func_name_var(instance); let hash = bx.const_u64(function_source_hash); let num_counters = bx.const_u32(coverageinfo.num_counters); let index = bx.const_u32(u32::from(id)); @@ -34,11 +45,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } CoverageKind::Expression { id, lhs, op, rhs } => { - bx.add_coverage_counter_expression(self.instance, id, lhs, op, rhs, code_region); + bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region); } CoverageKind::Unreachable => { bx.add_coverage_unreachable( - self.instance, + instance, code_region.expect("unreachable regions always have code regions"), ); } diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 5523e5f2e8604..fe7f6288adb27 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -112,7 +112,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx } mir::StatementKind::Coverage(box ref coverage) => { - self.codegen_coverage(&mut bx, coverage.clone()); + self.codegen_coverage(&mut bx, coverage.clone(), statement.source_info.scope); bx } mir::StatementKind::CopyNonOverlapping(box mir::CopyNonOverlapping { diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir/src/transform/coverage/query.rs index 4b455a6a1ba72..de8447f1974e7 100644 --- a/compiler/rustc_mir/src/transform/coverage/query.rs +++ b/compiler/rustc_mir/src/transform/coverage/query.rs @@ -1,8 +1,7 @@ use super::*; use rustc_middle::mir::coverage::*; -use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{self, Coverage, CoverageInfo, Location}; +use rustc_middle::mir::{self, Body, Coverage, CoverageInfo}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; @@ -85,10 +84,21 @@ impl CoverageVisitor { } } } -} -impl Visitor<'_> for CoverageVisitor { - fn visit_coverage(&mut self, coverage: &Coverage, _location: Location) { + fn visit_body(&mut self, body: &Body<'_>) { + for bb_data in body.basic_blocks().iter() { + for statement in bb_data.statements.iter() { + if let StatementKind::Coverage(box ref coverage) = statement.kind { + if is_inlined(body, statement) { + continue; + } + self.visit_coverage(coverage); + } + } + } + } + + fn visit_coverage(&mut self, coverage: &Coverage) { if self.add_missing_operands { match coverage.kind { CoverageKind::Expression { lhs, rhs, .. } => { @@ -129,10 +139,14 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo } fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option { - for bb_data in mir_body(tcx, def_id).basic_blocks().iter() { + let body = mir_body(tcx, def_id); + for bb_data in body.basic_blocks().iter() { for statement in bb_data.statements.iter() { if let StatementKind::Coverage(box ref coverage) = statement.kind { if let Some(code_region) = coverage.code_region.as_ref() { + if is_inlined(body, statement) { + continue; + } return Some(code_region.file_name); } } @@ -151,13 +165,17 @@ fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> { } fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> { - mir_body(tcx, def_id) - .basic_blocks() + let body = mir_body(tcx, def_id); + body.basic_blocks() .iter() .map(|data| { data.statements.iter().filter_map(|statement| match statement.kind { StatementKind::Coverage(box ref coverage) => { - coverage.code_region.as_ref() // may be None + if is_inlined(body, statement) { + None + } else { + coverage.code_region.as_ref() // may be None + } } _ => None, }) @@ -165,3 +183,8 @@ fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx Cod .flatten() .collect() } + +fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool { + let scope_data = &body.source_scopes[statement.source_info.scope]; + scope_data.inlined.is_some() || scope_data.inlined_parent_scope.is_some() +} diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index cf85503b3d54b..26e7555a61d23 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -39,15 +39,6 @@ struct CallSite<'tcx> { /// Returns true if MIR inlining is enabled in the current compilation session. crate fn is_enabled(tcx: TyCtxt<'_>) -> bool { - if tcx.sess.opts.debugging_opts.instrument_coverage { - // Since `Inline` happens after `InstrumentCoverage`, the function-specific coverage - // counters can be invalidated, such as by merging coverage counter statements from - // a pre-inlined function into a different function. This kind of change is invalid, - // so inlining must be skipped. Note: This check is performed here so inlining can - // be disabled without preventing other optimizations (regardless of `mir_opt_level`). - return false; - } - if let Some(enabled) = tcx.sess.opts.debugging_opts.inline_mir { return enabled; } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c1be90efc7299..75078a1231163 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1937,25 +1937,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } Some(SymbolManglingVersion::V0) => {} } - - if let Some(mir_opt_level) = debugging_opts.mir_opt_level { - if mir_opt_level > 1 { - // Functions inlined during MIR transform can, at best, make it impossible to - // effectively cover inlined functions, and, at worst, break coverage map generation - // during LLVM codegen. For example, function counter IDs are only unique within a - // function. Inlining after these counters are injected can produce duplicate counters, - // resulting in an invalid coverage map (and ICE); so this option combination is not - // allowed. - early_warn( - error_format, - &format!( - "`-Z mir-opt-level={}` (or any level > 1) enables function inlining, which \ - is incompatible with `-Z instrument-coverage`. Inlining will be disabled.", - mir_opt_level, - ), - ); - } - } } if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") { From 5a9538acb55f0980728a159996fdeff77b845455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 13 Mar 2021 00:00:00 +0000 Subject: [PATCH 13/24] Functions inlined into reachable functions are reachable Consider functions to be reachable for code coverage purposes, either when they reach the code generation directly, or indirectly as inlined part of another function. --- .../src/coverageinfo/mapgen.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 8 ++++++ .../src/monomorphize/partitioning/mod.rs | 25 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 1cea927f50c45..352638aa88ee8 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -284,7 +284,7 @@ fn add_unreachable_coverage<'tcx>( let all_def_ids: DefIdSet = tcx.mir_keys(LOCAL_CRATE).iter().map(|local_def_id| local_def_id.to_def_id()).collect(); - let (codegenned_def_ids, _) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); + let codegenned_def_ids = tcx.codegened_and_inlined_items(LOCAL_CRATE); let mut unreachable_def_ids_by_file: FxHashMap> = FxHashMap::default(); for &non_codegenned_def_id in all_def_ids.difference(codegenned_def_ids) { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b03b26d64606c..f912653d920ca 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1397,6 +1397,14 @@ rustc_queries! { query is_codegened_item(def_id: DefId) -> bool { desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) } } + + /// All items participating in code generation together with items inlined into them. + query codegened_and_inlined_items(_: CrateNum) + -> &'tcx DefIdSet { + eval_always + desc { "codegened_and_inlined_items" } + } + query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> { desc { "codegen_unit" } } diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs index b68a8104fba72..dc2379fd92b83 100644 --- a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs +++ b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs @@ -424,8 +424,33 @@ fn collect_and_partition_mono_items<'tcx>( (tcx.arena.alloc(mono_items), codegen_units) } +fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx DefIdSet { + let (items, cgus) = tcx.collect_and_partition_mono_items(cnum); + let mut visited = DefIdSet::default(); + let mut result = items.clone(); + + for cgu in cgus { + for (item, _) in cgu.items() { + if let MonoItem::Fn(ref instance) = item { + let did = instance.def_id(); + if !visited.insert(did) { + continue; + } + for scope in &tcx.instance_mir(instance.def).source_scopes { + if let Some((ref inlined, _)) = scope.inlined { + result.insert(inlined.def_id()); + } + } + } + } + } + + tcx.arena.alloc(result) +} + pub fn provide(providers: &mut Providers) { providers.collect_and_partition_mono_items = collect_and_partition_mono_items; + providers.codegened_and_inlined_items = codegened_and_inlined_items; providers.is_codegened_item = |tcx, def_id| { let (all_mono_items, _) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); From ad8f9af7cbeae48db0606cb5e39cbc04e5e35789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 13 Mar 2021 00:00:00 +0000 Subject: [PATCH 14/24] Remove inline-instrument-coverage-fail.rs test case --- .../inline-instrument-coverage-fail.rs | 21 ------------------- .../inline-instrument-coverage-fail.stderr | 2 -- 2 files changed, 23 deletions(-) delete mode 100644 src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs delete mode 100644 src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr diff --git a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs deleted file mode 100644 index 8ed7f25d2bbdb..0000000000000 --- a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Ensures -Zmir-opt-level=3 (specifically, inlining) is not allowed with -Zinstrument-coverage. -// Regression test for issue #80060. -// -// needs-profiler-support -// build-pass -// compile-flags: -Zmir-opt-level=3 -Zinstrument-coverage -#[inline(never)] -fn foo() {} - -pub fn baz() { - bar(); -} - -#[inline(always)] -fn bar() { - foo(); -} - -fn main() { - bar(); -} diff --git a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr deleted file mode 100644 index d482afc395d19..0000000000000 --- a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr +++ /dev/null @@ -1,2 +0,0 @@ -warning: `-Z mir-opt-level=3` (or any level > 1) enables function inlining, which is incompatible with `-Z instrument-coverage`. Inlining will be disabled. - From 4b6cc0c20488a598b97f887cbc747aee61bee7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 15 Mar 2021 00:00:00 +0000 Subject: [PATCH 15/24] Add support for compile-flags in coverage tests --- src/test/run-make-fulldeps/coverage-reports/Makefile | 6 +++--- src/test/run-make-fulldeps/coverage-spanview/Makefile | 8 ++------ src/test/run-make-fulldeps/coverage/async.rs | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile index 31583eaa8fee5..af75ec5e24d13 100644 --- a/src/test/run-make-fulldeps/coverage-reports/Makefile +++ b/src/test/run-make-fulldeps/coverage-reports/Makefile @@ -82,13 +82,13 @@ endif %: $(SOURCEDIR)/lib/%.rs # Compile the test library with coverage instrumentation $(RUSTC) $(SOURCEDIR)/lib/$@.rs \ - $$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/lib/$@.rs && echo "--edition=2018" ) \ + $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/lib/$@.rs) \ --crate-type rlib -Zinstrument-coverage %: $(SOURCEDIR)/%.rs # Compile the test program with coverage instrumentation $(RUSTC) $(SOURCEDIR)/$@.rs \ - $$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/$@.rs && echo "--edition=2018" ) \ + $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/$@.rs) \ -L "$(TMPDIR)" -Zinstrument-coverage # Run it in order to generate some profiling data, @@ -107,7 +107,7 @@ endif # Run it through rustdoc as well to cover doctests LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \ $(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \ - $$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/$@.rs && echo "--edition=2018" ) \ + $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/$@.rs) \ -L "$(TMPDIR)" -Zinstrument-coverage \ -Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@ diff --git a/src/test/run-make-fulldeps/coverage-spanview/Makefile b/src/test/run-make-fulldeps/coverage-spanview/Makefile index cd54ac0ed4c75..b0bfa7074db94 100644 --- a/src/test/run-make-fulldeps/coverage-spanview/Makefile +++ b/src/test/run-make-fulldeps/coverage-spanview/Makefile @@ -38,9 +38,7 @@ endif %: $(SOURCEDIR)/lib/%.rs # Compile the test library with coverage instrumentation $(RUSTC) $(SOURCEDIR)/lib/$@.rs \ - $$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/lib/$@.rs && \ - echo "--edition=2018" \ - ) \ + $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/lib/$@.rs) \ --crate-type rlib \ -Ztrim-diagnostic-paths=no \ -Zinstrument-coverage \ @@ -70,9 +68,7 @@ endif %: $(SOURCEDIR)/%.rs # Compile the test program with coverage instrumentation $(RUSTC) $(SOURCEDIR)/$@.rs \ - $$( grep -q '^\/\/ require-rust-edition-2018' $(SOURCEDIR)/$@.rs && \ - echo "--edition=2018" \ - ) \ + $$( sed -nE 's#^// compile-flags:(.*)#\1# p' $(SOURCEDIR)/$@.rs) \ -L "$(TMPDIR)" \ -Ztrim-diagnostic-paths=no \ -Zinstrument-coverage \ diff --git a/src/test/run-make-fulldeps/coverage/async.rs b/src/test/run-make-fulldeps/coverage/async.rs index 5553af92465ca..d5ec32deac125 100644 --- a/src/test/run-make-fulldeps/coverage/async.rs +++ b/src/test/run-make-fulldeps/coverage/async.rs @@ -1,6 +1,6 @@ #![allow(unused_assignments, dead_code)] -// require-rust-edition-2018 +// compile-flags: --edition=2018 async fn c(x: u8) -> u8 { if x == 8 { From 0d84e0b68c78006c4aa6f5ec021d92277be7d3cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 16 Mar 2021 00:00:00 +0000 Subject: [PATCH 16/24] Add test case for -Zinline-mir & -Zinstrument-coverage --- .../expected_show_coverage.async.txt | 2 +- .../expected_show_coverage.inline.txt | 53 +++++ .../expected_show_coverage.uses_crate.txt | 4 +- ....display.-------.InstrumentCoverage.0.html | 161 +++++++++++++++ ...ne.error.-------.InstrumentCoverage.0.html | 79 ++++++++ ...e.length.-------.InstrumentCoverage.0.html | 82 ++++++++ ...ine.main.-------.InstrumentCoverage.0.html | 94 +++++++++ ...ermutate.-------.InstrumentCoverage.0.html | 183 ++++++++++++++++++ ...utations.-------.InstrumentCoverage.0.html | 113 +++++++++++ ...ine.swap.-------.InstrumentCoverage.0.html | 173 +++++++++++++++++ src/test/run-make-fulldeps/coverage/inline.rs | 51 +++++ 11 files changed, 992 insertions(+), 3 deletions(-) create mode 100644 src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt create mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html create mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html create mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html create mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html create mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html create mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html create mode 100644 src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html create mode 100644 src/test/run-make-fulldeps/coverage/inline.rs diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt index 824bddaa40155..3f9403e6f70b8 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt @@ -1,6 +1,6 @@ 1| |#![allow(unused_assignments, dead_code)] 2| | - 3| |// require-rust-edition-2018 + 3| |// compile-flags: --edition=2018 4| | 5| 1|async fn c(x: u8) -> u8 { 6| 1| if x == 8 { diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt new file mode 100644 index 0000000000000..6148d89ed75e1 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt @@ -0,0 +1,53 @@ + 1| |// compile-flags: -Zinline-mir + 2| | + 3| |use std::fmt::Display; + 4| | + 5| 1|fn main() { + 6| 1| permutations(&['a', 'b', 'c']); + 7| 1|} + 8| | + 9| |#[inline(always)] + 10| 1|fn permutations(xs: &[T]) { + 11| 1| let mut ys = xs.to_owned(); + 12| 1| permutate(&mut ys, 0); + 13| 1|} + 14| | + 15| 16|fn permutate(xs: &mut [T], k: usize) { + 16| 16| let n = length(xs); + 17| 16| if k == n { + 18| 6| display(xs); + 19| 10| } else if k < n { + 20| 15| for i in k..n { + ^10 + 21| 15| swap(xs, i, k); + 22| 15| permutate(xs, k + 1); + 23| 15| swap(xs, i, k); + 24| 15| } + 25| 0| } else { + 26| 0| error(); + 27| 0| } + 28| 16|} + 29| | + 30| 16|fn length(xs: &[T]) -> usize { + 31| 16| xs.len() + 32| 16|} + 33| | + 34| |#[inline] + 35| 30|fn swap(xs: &mut [T], i: usize, j: usize) { + 36| 30| let t = xs[i]; + 37| 30| xs[i] = xs[j]; + 38| 30| xs[j] = t; + 39| 30|} + 40| | + 41| 6|fn display(xs: &[T]) { + 42| 18| for x in xs { + 43| 18| print!("{}", x); + 44| 18| } + 45| 6| println!(); + 46| 6|} + 47| | + 48| |#[inline(always)] + 49| |fn error() { + 50| | panic!("error"); + 51| |} + diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt index 0c28305dd7725..bc2f673349a67 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_crate.txt @@ -19,12 +19,12 @@ 18| 2| println!("used_only_from_bin_crate_generic_function with {:?}", arg); 19| 2|} ------------------ - | used_crate::used_only_from_bin_crate_generic_function::<&str>: + | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec>: | 17| 1|pub fn used_only_from_bin_crate_generic_function(arg: T) { | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); | 19| 1|} ------------------ - | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec>: + | used_crate::used_only_from_bin_crate_generic_function::<&str>: | 17| 1|pub fn used_only_from_bin_crate_generic_function(arg: T) { | 18| 1| println!("used_only_from_bin_crate_generic_function with {:?}", arg); | 19| 1|} diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html new file mode 100644 index 0000000000000..6287516636ea9 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.display.-------.InstrumentCoverage.0.html @@ -0,0 +1,161 @@ + + + + +inline.display - Coverage Spans + + + +
@0,1⦊fn display<T: Display>(xs: &[T]) ⦉@0,1{ + for @6,8,9,10,11⦊x⦉@6,8,9,10,11 in @6,8,9,10,11⦊xs { + print!("{}", x); + }⦉@6,8,9,10,11 + @5,12,13⦊println!(); +}⦉@5,12,13
+ + diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html new file mode 100644 index 0000000000000..bbf19c3e446f9 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.error.-------.InstrumentCoverage.0.html @@ -0,0 +1,79 @@ + + + + +inline.error - Coverage Spans + + + +
@0,1⦊fn error() { + panic!("error"); +}⦉@0,1
+ + diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html new file mode 100644 index 0000000000000..8e8efb6d9f6b1 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.length.-------.InstrumentCoverage.0.html @@ -0,0 +1,82 @@ + + + + +inline.length - Coverage Spans + + + +
@0,1⦊fn length<T>(xs: &[T]) -> usize { + xs.len() +}⦉@0,1
+ + diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html new file mode 100644 index 0000000000000..4ec2e9beede30 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.main.-------.InstrumentCoverage.0.html @@ -0,0 +1,94 @@ + + + + +inline.main - Coverage Spans + + + +
@0,1⦊fn main() { + permutations(&['a', 'b', 'c']); +}⦉@0,1
+ + diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html new file mode 100644 index 0000000000000..fd72973ccd076 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutate.-------.InstrumentCoverage.0.html @@ -0,0 +1,183 @@ + + + + +inline.permutate - Coverage Spans + + + +
@0,1⦊fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) { + let n = length(xs); + if k == n⦉@0,1 @2,4⦊{ + display(xs); + }⦉@2,4 else if @3⦊k < n⦉@3 { + for @12,14,15,16,17,18⦊i⦉@12,14,15,16,17,18 in @5,7⦊k..n⦉@5,7 @12,14,15,16,17,18⦊{ + swap(xs, i, k); + permutate(xs, k + 1); + swap(xs, i, k); + }⦉@12,14,15,16,17,18 + } else @6,19⦊{ + error(); + }⦉@6,19 +}@21⦊⦉@21
+ + diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html new file mode 100644 index 0000000000000..4bfd22f3cd903 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.permutations.-------.InstrumentCoverage.0.html @@ -0,0 +1,113 @@ + + + + +inline.permutations - Coverage Spans + + + +
@0,1,2,3,4⦊fn permutations<T: Copy + Display>(xs: &[T]) { + let mut ys = xs.to_owned(); + permutate(&mut ys, 0); +}⦉@0,1,2,3,4
+ + diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html new file mode 100644 index 0000000000000..4c3f63093d30e --- /dev/null +++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.inline/inline.swap.-------.InstrumentCoverage.0.html @@ -0,0 +1,173 @@ + + + + +inline.swap - Coverage Spans + + + +
@0,1,2,3,4⦊fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) { + let t = xs[i]; + xs[i] = xs[j]; + xs[j] = t; +}⦉@0,1,2,3,4
+ + diff --git a/src/test/run-make-fulldeps/coverage/inline.rs b/src/test/run-make-fulldeps/coverage/inline.rs new file mode 100644 index 0000000000000..9cfab9ddbadf2 --- /dev/null +++ b/src/test/run-make-fulldeps/coverage/inline.rs @@ -0,0 +1,51 @@ +// compile-flags: -Zinline-mir + +use std::fmt::Display; + +fn main() { + permutations(&['a', 'b', 'c']); +} + +#[inline(always)] +fn permutations(xs: &[T]) { + let mut ys = xs.to_owned(); + permutate(&mut ys, 0); +} + +fn permutate(xs: &mut [T], k: usize) { + let n = length(xs); + if k == n { + display(xs); + } else if k < n { + for i in k..n { + swap(xs, i, k); + permutate(xs, k + 1); + swap(xs, i, k); + } + } else { + error(); + } +} + +fn length(xs: &[T]) -> usize { + xs.len() +} + +#[inline] +fn swap(xs: &mut [T], i: usize, j: usize) { + let t = xs[i]; + xs[i] = xs[j]; + xs[j] = t; +} + +fn display(xs: &[T]) { + for x in xs { + print!("{}", x); + } + println!(); +} + +#[inline(always)] +fn error() { + panic!("error"); +} From bd2737fc96b8a8a6ad7e1d4546de9c64108a0a0e Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Tue, 16 Mar 2021 10:50:45 +0000 Subject: [PATCH 17/24] ci/docker: Add SDK/NDK level 21 to android docker for 32bit platforms Certain features of Linux (getauxval() and epoll_create1()) are only available in android SDK/NDK levels 18 and 21 respectively. The 32bit platform is currently on level 14 for compatibility with Android 4.0. This patch adds SDK/NDK level 21 to the docker for 32 bit platforms, while leaving the default setup at level 14. With this done, projects such as `rustup` which rely on these dockers can build with modern ecosystem crates such as tokio 1.0, by using the level 21 toolchain, but those which do not need to switch will be unaffected, since the level 14 toolchain remains available. Signed-off-by: Daniel Silverstone --- src/ci/docker/host-x86_64/dist-android/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ci/docker/host-x86_64/dist-android/Dockerfile b/src/ci/docker/host-x86_64/dist-android/Dockerfile index ee727359f3961..2f0496d7dd4ba 100644 --- a/src/ci/docker/host-x86_64/dist-android/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-android/Dockerfile @@ -9,6 +9,8 @@ RUN . /scripts/android-ndk.sh && \ download_ndk android-ndk-r15c-linux-x86_64.zip && \ make_standalone_toolchain arm 14 && \ make_standalone_toolchain x86 14 && \ + make_standalone_toolchain arm 21 && \ + make_standalone_toolchain x86 21 && \ make_standalone_toolchain arm64 21 && \ make_standalone_toolchain x86_64 21 && \ remove_ndk From b0092bc995fa3e6633c3aaa1d0a56006ab7ad1e3 Mon Sep 17 00:00:00 2001 From: Soveu Date: Tue, 16 Mar 2021 14:41:26 +0100 Subject: [PATCH 18/24] Vec::dedup optimization - add benches --- library/alloc/benches/lib.rs | 1 + library/alloc/benches/vec.rs | 89 ++++++++++++++++++++++++++++++++++++ library/alloc/tests/vec.rs | 2 +- 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs index 32edb86d10119..38a8f65f1695a 100644 --- a/library/alloc/benches/lib.rs +++ b/library/alloc/benches/lib.rs @@ -4,6 +4,7 @@ #![feature(btree_drain_filter)] #![feature(map_first_last)] #![feature(repr_simd)] +#![feature(slice_partition_dedup)] #![feature(test)] extern crate test; diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index 89893b6209c0a..73eb353f6e7d4 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -671,3 +671,92 @@ fn bench_map_fast(b: &mut Bencher) { let data = black_box([(0, 0); LEN]); b.iter(|| map_fast(&data)); } + +fn random_sorted_fill(mut seed: u32, buf: &mut [u32]) { + let mask = if buf.len() < 8192 { + 0xFF + } else if buf.len() < 200_000 { + 0xFFFF + } else { + 0xFFFF_FFFF + }; + + for item in buf.iter_mut() { + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + + *item = seed & mask; + } + + buf.sort(); +} + +fn bench_vec_dedup_old(b: &mut Bencher, sz: usize) { + let mut template = vec![0u32; sz]; + b.bytes = std::mem::size_of_val(template.as_slice()) as u64; + random_sorted_fill(0x43, &mut template); + + let mut vec = template.clone(); + b.iter(|| { + let len = { + let (dedup, _) = vec.partition_dedup(); + dedup.len() + }; + vec.truncate(len); + + black_box(vec.first()); + vec.clear(); + vec.extend_from_slice(&template); + }); +} + +fn bench_vec_dedup_new(b: &mut Bencher, sz: usize) { + let mut template = vec![0u32; sz]; + b.bytes = std::mem::size_of_val(template.as_slice()) as u64; + random_sorted_fill(0x43, &mut template); + + let mut vec = template.clone(); + b.iter(|| { + vec.dedup(); + black_box(vec.first()); + vec.clear(); + vec.extend_from_slice(&template); + }); +} + +#[bench] +fn bench_dedup_old_100(b: &mut Bencher) { + bench_vec_dedup_old(b, 100); +} +#[bench] +fn bench_dedup_new_100(b: &mut Bencher) { + bench_vec_dedup_new(b, 100); +} + +#[bench] +fn bench_dedup_old_1000(b: &mut Bencher) { + bench_vec_dedup_old(b, 1000); +} +#[bench] +fn bench_dedup_new_1000(b: &mut Bencher) { + bench_vec_dedup_new(b, 1000); +} + +#[bench] +fn bench_dedup_old_10000(b: &mut Bencher) { + bench_vec_dedup_old(b, 10000); +} +#[bench] +fn bench_dedup_new_10000(b: &mut Bencher) { + bench_vec_dedup_new(b, 10000); +} + +#[bench] +fn bench_dedup_old_100000(b: &mut Bencher) { + bench_vec_dedup_old(b, 100000); +} +#[bench] +fn bench_dedup_new_100000(b: &mut Bencher) { + bench_vec_dedup_new(b, 100000); +} diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index e4a20dd932451..c142536cd2dfb 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2267,4 +2267,4 @@ fn test_extend_from_within_panicing_clone() { std::panic::catch_unwind(move || vec.extend_from_within(..)).unwrap_err(); assert_eq!(count.load(Ordering::SeqCst), 4); -} \ No newline at end of file +} From 5bd50ef9be0d234224402ad080e55e4cf3b48546 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 16 Mar 2021 17:14:23 +0100 Subject: [PATCH 19/24] Simplify C compilation for Fortanix-SGX target --- .../docker/host-x86_64/dist-various-2/Dockerfile | 10 ++++------ .../x86_64-fortanix-unknown-sgx-clang-wrap.sh | 14 -------------- 2 files changed, 4 insertions(+), 20 deletions(-) delete mode 100755 src/ci/docker/host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 7bb3cb1451688..de3a99f34fcfa 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -45,10 +45,10 @@ ENV \ CC_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-gcc-8 \ CXX_armv7_unknown_linux_gnueabi=arm-linux-gnueabi-g++-8 \ AR_x86_64_fortanix_unknown_sgx=ar \ - CC_x86_64_fortanix_unknown_sgx=x86_64-fortanix-unknown-sgx-clang-11 \ - CFLAGS_x86_64_fortanix_unknown_sgx="-mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \ - CXX_x86_64_fortanix_unknown_sgx=x86_64-fortanix-unknown-sgx-clang++-11 \ - CXXFLAGS_x86_64_fortanix_unknown_sgx="-mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \ + CC_x86_64_fortanix_unknown_sgx=clang-11 \ + CFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \ + CXX_x86_64_fortanix_unknown_sgx=clang++-11 \ + CXXFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \ AR_i686_unknown_freebsd=i686-unknown-freebsd11-ar \ CC_i686_unknown_freebsd=i686-unknown-freebsd11-clang \ CXX_i686_unknown_freebsd=i686-unknown-freebsd11-clang++ \ @@ -71,8 +71,6 @@ COPY host-x86_64/dist-various-2/build-solaris-toolchain.sh /tmp/ RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/ -COPY host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh /usr/bin/x86_64-fortanix-unknown-sgx-clang-11 -RUN ln -s /usr/bin/x86_64-fortanix-unknown-sgx-clang-11 /usr/bin/x86_64-fortanix-unknown-sgx-clang++-11 RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/ diff --git a/src/ci/docker/host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh b/src/ci/docker/host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh deleted file mode 100755 index c4ff44c37b1e3..0000000000000 --- a/src/ci/docker/host-x86_64/dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -args=("$@") - -for i in "${!args[@]}"; do - # x86_64-fortanix-unknown-sgx doesn't have a C sysroot for things like - # stdint.h and the C++ STL. Unlike GCC, clang will not use the host's - # sysroot instead. Force it. - if [ "${args[$i]}" = "--target=x86_64-fortanix-unknown-sgx" ]; then - args[$i]="--target=x86_64-unknown-linux-gnu" - fi -done - -exec "${0/x86_64-fortanix-unknown-sgx-clang/clang}" "${args[@]}" From e3031fe22ae19965967f4fdf8bf46b017902a06a Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 16 Mar 2021 17:33:03 -0400 Subject: [PATCH 20/24] Allow registering tool lints with `register_tool` Previously, there was no way to add a custom tool prefix, even if the tool itself had registered a lint: ``` #![feature(register_tool)] #![register_tool(xyz)] #![warn(xyz::my_lint)] ``` ``` $ rustc unknown-lint.rs --crate-type lib error[E0710]: an unknown tool name found in scoped lint: `xyz::my_lint` --> unknown-lint.rs:3:9 | 3 | #![warn(xyz::my_lint)] | ^^^ ``` This allows opting-in to lints from other tools using `register_tool`. --- compiler/rustc_ast/src/attr/mod.rs | 4 -- compiler/rustc_lint/src/context.rs | 2 +- compiler/rustc_lint/src/levels.rs | 46 +++++++++++++++++----- src/test/ui/lint/register-tool-lint.rs | 11 ++++++ src/test/ui/lint/register-tool-lint.stderr | 27 +++++++++++++ src/test/ui/tool_lints.rs | 6 +-- src/test/ui/tool_lints.stderr | 12 ++++-- src/test/ui/unknown-lint-tool-name.rs | 12 +++--- src/test/ui/unknown-lint-tool-name.stderr | 24 ++++++++--- 9 files changed, 112 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/lint/register-tool-lint.rs create mode 100644 src/test/ui/lint/register-tool-lint.stderr diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 40b0cefd83aa6..2c5e180f80d49 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -33,10 +33,6 @@ impl MarkedAttrs { } } -pub fn is_known_lint_tool(m_item: Ident) -> bool { - [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item.name) -} - impl NestedMetaItem { /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`. pub fn meta_item(&self) -> Option<&MetaItem> { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 42ead89ca4f85..1e98464f13a82 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -714,7 +714,7 @@ impl<'a> EarlyContext<'a> { sess, krate, lint_store, - builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store), + builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store, &krate.attrs), buffered, } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index b3bdaf5bdc7d0..360cccb58d54f 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1,13 +1,12 @@ use crate::context::{CheckLintNameResult, LintStore}; use crate::late::unerased_lint_store; use rustc_ast as ast; -use rustc_ast::attr; use rustc_ast::unwrap_or; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::{intravisit, HirId}; use rustc_middle::hir::map::Map; use rustc_middle::lint::LevelAndSource; @@ -32,7 +31,8 @@ use std::cmp; fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap { assert_eq!(cnum, LOCAL_CRATE); let store = unerased_lint_store(tcx); - let levels = LintLevelsBuilder::new(tcx.sess, false, &store); + let crate_attrs = tcx.get_attrs(DefId { krate: cnum, index: CRATE_DEF_INDEX }); + let levels = LintLevelsBuilder::new(tcx.sess, false, &store, crate_attrs); let mut builder = LintLevelMapBuilder { levels, tcx, store }; let krate = tcx.hir().krate(); @@ -56,6 +56,7 @@ pub struct LintLevelsBuilder<'s> { cur: u32, warn_about_weird_lints: bool, store: &'s LintStore, + crate_attrs: &'s [ast::Attribute], } pub struct BuilderPush { @@ -64,7 +65,12 @@ pub struct BuilderPush { } impl<'s> LintLevelsBuilder<'s> { - pub fn new(sess: &'s Session, warn_about_weird_lints: bool, store: &'s LintStore) -> Self { + pub fn new( + sess: &'s Session, + warn_about_weird_lints: bool, + store: &'s LintStore, + crate_attrs: &'s [ast::Attribute], + ) -> Self { let mut builder = LintLevelsBuilder { sess, sets: LintLevelSets::new(), @@ -72,6 +78,7 @@ impl<'s> LintLevelsBuilder<'s> { id_to_set: Default::default(), warn_about_weird_lints, store, + crate_attrs, }; builder.process_command_line(sess, store); assert_eq!(builder.sets.list.len(), 1); @@ -304,15 +311,22 @@ impl<'s> LintLevelsBuilder<'s> { }; let tool_name = if meta_item.path.segments.len() > 1 { let tool_ident = meta_item.path.segments[0].ident; - if !attr::is_known_lint_tool(tool_ident) { - struct_span_err!( + if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) { + let mut err = struct_span_err!( sess, tool_ident.span, E0710, - "an unknown tool name found in scoped lint: `{}`", + "unknown tool name `{}` found in scoped lint: `{}`", + tool_ident.name, pprust::path_to_string(&meta_item.path), - ) - .emit(); + ); + if sess.is_nightly_build() { + err.help(&format!( + "add `#![register_tool({})]` to the crate root", + tool_ident.name + )); + } + err.emit(); continue; } @@ -559,6 +573,20 @@ impl<'s> LintLevelsBuilder<'s> { } } +fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool { + if [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item) { + return true; + } + // Look for registered tools + // NOTE: does no error handling; error handling is done by rustc_resolve. + sess.filter_by_name(attrs, sym::register_tool) + .filter_map(|attr| attr.meta_item_list()) + .flat_map(std::convert::identity) + .filter_map(|nested_meta| nested_meta.ident()) + .map(|ident| ident.name) + .any(|name| name == m_item) +} + struct LintLevelMapBuilder<'a, 'tcx> { levels: LintLevelsBuilder<'tcx>, tcx: TyCtxt<'tcx>, diff --git a/src/test/ui/lint/register-tool-lint.rs b/src/test/ui/lint/register-tool-lint.rs new file mode 100644 index 0000000000000..0ba5a37b167cd --- /dev/null +++ b/src/test/ui/lint/register-tool-lint.rs @@ -0,0 +1,11 @@ +#![crate_type = "lib"] +#![feature(register_tool)] +#![register_tool(xyz)] +#![warn(xyz::my_lint)] // this should not error +#![warn(abc::my_lint)] +//~^ ERROR unknown tool name `abc` found in scoped lint +//~| HELP add `#![register_tool(abc)]` +//~| ERROR unknown tool name `abc` +//~| HELP add `#![register_tool(abc)]` +//~| ERROR unknown tool name `abc` +//~| HELP add `#![register_tool(abc)]` diff --git a/src/test/ui/lint/register-tool-lint.stderr b/src/test/ui/lint/register-tool-lint.stderr new file mode 100644 index 0000000000000..750c74cec1eb9 --- /dev/null +++ b/src/test/ui/lint/register-tool-lint.stderr @@ -0,0 +1,27 @@ +error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint` + --> $DIR/register-tool-lint.rs:5:9 + | +LL | #![warn(abc::my_lint)] + | ^^^ + | + = help: add `#![register_tool(abc)]` to the crate root + +error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint` + --> $DIR/register-tool-lint.rs:5:9 + | +LL | #![warn(abc::my_lint)] + | ^^^ + | + = help: add `#![register_tool(abc)]` to the crate root + +error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint` + --> $DIR/register-tool-lint.rs:5:9 + | +LL | #![warn(abc::my_lint)] + | ^^^ + | + = help: add `#![register_tool(abc)]` to the crate root + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0710`. diff --git a/src/test/ui/tool_lints.rs b/src/test/ui/tool_lints.rs index 9c8540eede792..9e4aa7a939acb 100644 --- a/src/test/ui/tool_lints.rs +++ b/src/test/ui/tool_lints.rs @@ -1,5 +1,5 @@ #[warn(foo::bar)] -//~^ ERROR an unknown tool name found in scoped lint: `foo::bar` -//~| ERROR an unknown tool name found in scoped lint: `foo::bar` -//~| ERROR an unknown tool name found in scoped lint: `foo::bar` +//~^ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` +//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` +//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` fn main() {} diff --git a/src/test/ui/tool_lints.stderr b/src/test/ui/tool_lints.stderr index 1bcd7fd735de8..e06f6ddc1ca3a 100644 --- a/src/test/ui/tool_lints.stderr +++ b/src/test/ui/tool_lints.stderr @@ -1,20 +1,26 @@ -error[E0710]: an unknown tool name found in scoped lint: `foo::bar` +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/tool_lints.rs:1:8 | LL | #[warn(foo::bar)] | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root -error[E0710]: an unknown tool name found in scoped lint: `foo::bar` +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/tool_lints.rs:1:8 | LL | #[warn(foo::bar)] | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root -error[E0710]: an unknown tool name found in scoped lint: `foo::bar` +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/tool_lints.rs:1:8 | LL | #[warn(foo::bar)] | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root error: aborting due to 3 previous errors diff --git a/src/test/ui/unknown-lint-tool-name.rs b/src/test/ui/unknown-lint-tool-name.rs index 182aec34b4781..84ab7c1944ab2 100644 --- a/src/test/ui/unknown-lint-tool-name.rs +++ b/src/test/ui/unknown-lint-tool-name.rs @@ -1,8 +1,8 @@ -#![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar` - //~| ERROR an unknown tool name found in scoped lint: `foo::bar` - //~| ERROR an unknown tool name found in scoped lint: `foo::bar` +#![deny(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` + //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` + //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` -#[allow(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar` - //~| ERROR an unknown tool name found in scoped lint: `foo::bar` - //~| ERROR an unknown tool name found in scoped lint: `foo::bar` +#[allow(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` + //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` + //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` fn main() {} diff --git a/src/test/ui/unknown-lint-tool-name.stderr b/src/test/ui/unknown-lint-tool-name.stderr index 414816d229cdb..1d145515abf66 100644 --- a/src/test/ui/unknown-lint-tool-name.stderr +++ b/src/test/ui/unknown-lint-tool-name.stderr @@ -1,38 +1,50 @@ -error[E0710]: an unknown tool name found in scoped lint: `foo::bar` +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/unknown-lint-tool-name.rs:1:9 | LL | #![deny(foo::bar)] | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root -error[E0710]: an unknown tool name found in scoped lint: `foo::bar` +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/unknown-lint-tool-name.rs:5:9 | LL | #[allow(foo::bar)] | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root -error[E0710]: an unknown tool name found in scoped lint: `foo::bar` +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/unknown-lint-tool-name.rs:1:9 | LL | #![deny(foo::bar)] | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root -error[E0710]: an unknown tool name found in scoped lint: `foo::bar` +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/unknown-lint-tool-name.rs:5:9 | LL | #[allow(foo::bar)] | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root -error[E0710]: an unknown tool name found in scoped lint: `foo::bar` +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/unknown-lint-tool-name.rs:1:9 | LL | #![deny(foo::bar)] | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root -error[E0710]: an unknown tool name found in scoped lint: `foo::bar` +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` --> $DIR/unknown-lint-tool-name.rs:5:9 | LL | #[allow(foo::bar)] | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root error: aborting due to 6 previous errors From f414c33e5ed47182c95d3859816424a093e0a7a9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 17 Mar 2021 11:33:07 +0900 Subject: [PATCH 21/24] Display error details when a `mmap` call fails --- library/std/src/sys/unix/stack_overflow.rs | 5 +++-- library/std/src/sys/unix/thread.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs index d7bba50c76ab8..2a487fff54ae7 100644 --- a/library/std/src/sys/unix/stack_overflow.rs +++ b/library/std/src/sys/unix/stack_overflow.rs @@ -39,6 +39,7 @@ impl Drop for Handler { ))] mod imp { use super::Handler; + use crate::io; use crate::mem; use crate::ptr; @@ -149,11 +150,11 @@ mod imp { 0, ); if stackp == MAP_FAILED { - panic!("failed to allocate an alternative stack"); + panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); } let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE); if guard_result != 0 { - panic!("failed to set up alternative stack guard page"); + panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); } stackp.add(page_size()) } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 40c9630751416..01a12dcf5a2af 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -231,6 +231,7 @@ pub mod guard { use libc::{mmap, mprotect}; use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE}; + use crate::io; use crate::ops::Range; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sys::os; @@ -361,12 +362,12 @@ pub mod guard { 0, ); if result != stackaddr || result == MAP_FAILED { - panic!("failed to allocate a guard page"); + panic!("failed to allocate a guard page: {}", io::Error::last_os_error()); } let result = mprotect(stackaddr, page_size, PROT_NONE); if result != 0 { - panic!("failed to protect the guard page"); + panic!("failed to protect the guard page: {}", io::Error::last_os_error()); } let guardaddr = stackaddr as usize; From a7491d932fdfe9ccb1950c1ab660c0bf493cc7bb Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 17 Mar 2021 09:27:34 -0400 Subject: [PATCH 22/24] fix whitespace Co-authored-by: Yuki Okushi --- library/core/src/hash/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 2ff87f4890727..05154f18a9f70 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -6,7 +6,7 @@ //! [hash]: https://en.wikipedia.org/wiki/Hash_function //! [`HashMap`]: ../../std/collections/struct.HashMap.html //! [`HashSet`]: ../../std/collections/struct.HashSet.html - +//! //! The simplest way to make a type hashable is to use `#[derive(Hash)]`: //! //! # Examples From ee98c6fea4b96abd8cad6616291657dc05329045 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 17 Mar 2021 13:48:25 +0100 Subject: [PATCH 23/24] Don't show HTML diff if tidy isn't installed for rustdoc tests --- src/tools/compiletest/src/main.rs | 2 +- src/tools/compiletest/src/runtest.rs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index b32a6f08638cc..1d4b5e1247de7 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -44,7 +44,7 @@ fn main() { } if !config.has_tidy && config.mode == Mode::Rustdoc { - eprintln!("warning: `tidy` is not installed; generated diffs will be harder to read"); + eprintln!("warning: `tidy` is not installed; diffs will not be generated"); } log_config(&config); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 9a82591e5a75a..4f5003529a3cb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2365,6 +2365,9 @@ impl<'test> TestCx<'test> { } fn compare_to_default_rustdoc(&mut self, out_dir: &Path) { + if !self.config.has_tidy { + return; + } println!("info: generating a diff against nightly rustdoc"); let suffix = @@ -2426,10 +2429,8 @@ impl<'test> TestCx<'test> { } } }; - if self.config.has_tidy { - tidy_dir(out_dir); - tidy_dir(&compare_dir); - } + tidy_dir(out_dir); + tidy_dir(&compare_dir); let pager = { let output = Command::new("git").args(&["config", "--get", "core.pager"]).output().ok(); From 9a3e23fed212efcac3b7728ef2cef598feb078c6 Mon Sep 17 00:00:00 2001 From: Justin Restivo Date: Wed, 17 Mar 2021 10:32:39 -0400 Subject: [PATCH 24/24] riscvgc-unknown-none-elf use lp64d ABI --- compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs index 33a785fdfee48..aa823b13fddf2 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs @@ -11,6 +11,7 @@ pub fn target() -> Target { options: TargetOptions { linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_string()), + llvm_abiname: "lp64d".to_string(), cpu: "generic-rv64".to_string(), max_atomic_width: Some(64), atomic_cas: true,