diff --git a/Cargo.lock b/Cargo.lock
index e9fb097df92d2..84ad4d485dc00 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2347,9 +2347,9 @@ dependencies = [
[[package]]
name = "psm"
-version = "0.1.8"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "659ecfea2142a458893bb7673134bad50b752fea932349c213d6a23874ce3aa7"
+checksum = "092d385624a084892d07374caa7b0994956692cf40650419a1f1a787a8d229cf"
dependencies = [
"cc",
]
diff --git a/README.md b/README.md
index 42fc0a63c0ffb..c2ded10f05a36 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,9 @@
-# The Rust Programming Language
+
+
+
This is the main source code repository for [Rust]. It contains the compiler,
-standard library, and documentation.
+standard library, and documentation.
[Rust]: https://www.rust-lang.org
@@ -17,9 +19,9 @@ Read ["Installation"] from [The Book].
_Note: If you wish to contribute to the compiler, you should read [this
chapter][rustcguidebuild] of the rustc-dev-guide instead of this section._
-The Rust build system has a Python script called `x.py` to bootstrap building
-the compiler. More information about it may be found by running `./x.py --help`
-or reading the [rustc dev guide][rustcguidebuild].
+The Rust build system uses a Python script called `x.py` to build the compiler,
+which manages the bootstrapping process. More information about it can be found
+by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
@@ -54,9 +56,8 @@ or reading the [rustc dev guide][rustcguidebuild].
$ cp config.toml.example config.toml
```
- It is recommended that if you plan to use the Rust build system to create
- an installation (using `./x.py install`) that you set the `prefix` value
- in the `[install]` section to a directory that you have write permissions.
+ If you plan to use `x.py install` to create an installation, it is recommended
+ that you set the `prefix` value in the `[install]` section to a directory.
Create install directory if you are not installing in default directory
@@ -143,8 +144,8 @@ shell with:
```
Currently, building Rust only works with some known versions of Visual Studio. If
-you have a more recent version installed the build system doesn't understand
-then you may need to force rustbuild to use an older version. This can be done
+you have a more recent version installed and the build system doesn't understand,
+you may need to force rustbuild to use an older version. This can be done
by manually calling the appropriate vcvars file before running the bootstrap.
```batch
diff --git a/src/doc/unstable-book/src/language-features/track-caller.md b/src/doc/unstable-book/src/language-features/track-caller.md
deleted file mode 100644
index afc11a2b9492c..0000000000000
--- a/src/doc/unstable-book/src/language-features/track-caller.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# `track_caller`
-
-The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809).
-
-------------------------
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index f1b560b9b9685..3320ebdf821d0 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -384,7 +384,10 @@ impl Box {
///
/// unsafe {
/// let ptr = alloc(Layout::new::()) as *mut i32;
- /// *ptr = 5;
+ /// // In general .write is required to avoid attempting to destruct
+ /// // the (uninitialized) previous contents of `ptr`, though for this
+ /// // simple example `*ptr = 5` would have worked as well.
+ /// ptr.write(5);
/// let x = Box::from_raw(ptr);
/// }
/// ```
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 5d09018759191..80be8c158023d 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1956,7 +1956,40 @@ extern "rust-intrinsic" {
/// generation.
#[cfg(not(bootstrap))]
#[lang = "count_code_region"]
- pub fn count_code_region(index: u32);
+ pub fn count_code_region(index: u32, start_byte_pos: u32, end_byte_pos: u32);
+
+ /// Internal marker for code coverage expressions, injected into the MIR when the
+ /// "instrument-coverage" option is enabled. This intrinsic is not converted into a
+ /// backend intrinsic call, but its arguments are extracted during the production of a
+ /// "coverage map", which is injected into the generated code, as additional data.
+ /// This marker identifies a code region and two other counters or counter expressions
+ /// whose sum is the number of times the code region was executed.
+ #[cfg(not(bootstrap))]
+ pub fn coverage_counter_add(
+ index: u32,
+ left_index: u32,
+ right_index: u32,
+ start_byte_pos: u32,
+ end_byte_pos: u32,
+ );
+
+ /// This marker identifies a code region and two other counters or counter expressions
+ /// whose difference is the number of times the code region was executed.
+ /// (See `coverage_counter_add` for more information.)
+ #[cfg(not(bootstrap))]
+ pub fn coverage_counter_subtract(
+ index: u32,
+ left_index: u32,
+ right_index: u32,
+ start_byte_pos: u32,
+ end_byte_pos: u32,
+ );
+
+ /// This marker identifies a code region to be added to the "coverage map" to indicate source
+ /// code that can never be reached.
+ /// (See `coverage_counter_add` for more information.)
+ #[cfg(not(bootstrap))]
+ pub fn coverage_unreachable(start_byte_pos: u32, end_byte_pos: u32);
/// See documentation of `<*const T>::guaranteed_eq` for details.
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index aeb52bffbf24c..b732dacae1c5b 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -118,7 +118,7 @@
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stmt_expr_attributes)]
-#![feature(track_caller)]
+#![cfg_attr(bootstrap, feature(track_caller))]
#![feature(transparent_unions)]
#![feature(unboxed_closures)]
#![feature(unsized_locals)]
diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs
index 3cfdde60135b7..13c0e8daf740f 100644
--- a/src/libcore/macros/mod.rs
+++ b/src/libcore/macros/mod.rs
@@ -1,6 +1,6 @@
#[doc(include = "panic.md")]
#[macro_export]
-#[allow_internal_unstable(core_panic, track_caller)]
+#[allow_internal_unstable(core_panic, const_caller_location)]
#[stable(feature = "core", since = "1.6.0")]
macro_rules! panic {
() => (
diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs
index c7009b76e8148..543aa969330ae 100644
--- a/src/libcore/panic.rs
+++ b/src/libcore/panic.rs
@@ -190,7 +190,6 @@ impl<'a> Location<'a> {
/// # Examples
///
/// ```
- /// #![feature(track_caller)]
/// use core::panic::Location;
///
/// /// Returns the [`Location`] at which it is called.
@@ -206,7 +205,7 @@ impl<'a> Location<'a> {
///
/// let fixed_location = get_just_one_location();
/// assert_eq!(fixed_location.file(), file!());
- /// assert_eq!(fixed_location.line(), 15);
+ /// assert_eq!(fixed_location.line(), 14);
/// assert_eq!(fixed_location.column(), 5);
///
/// // running the same untracked function in a different location gives us the same result
@@ -217,7 +216,7 @@ impl<'a> Location<'a> {
///
/// let this_location = get_caller_location();
/// assert_eq!(this_location.file(), file!());
- /// assert_eq!(this_location.line(), 29);
+ /// assert_eq!(this_location.line(), 28);
/// assert_eq!(this_location.column(), 21);
///
/// // running the tracked function in a different location produces a different value
@@ -226,13 +225,8 @@ impl<'a> Location<'a> {
/// assert_ne!(this_location.line(), another_location.line());
/// assert_ne!(this_location.column(), another_location.column());
/// ```
- // FIXME: When stabilizing this method, please also update the documentation
- // of `intrinsics::caller_location`.
- #[unstable(
- feature = "track_caller",
- reason = "uses #[track_caller] which is not yet stable",
- issue = "47809"
- )]
+ #[stable(feature = "track_caller", since = "1.46.0")]
+ #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
#[track_caller]
pub const fn caller() -> &'static Location<'static> {
crate::intrinsics::caller_location()
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 86faa1f086ce2..501cd3748282b 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -9,7 +9,7 @@ use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_ast::attr;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, BinOpToken, DelimToken, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::util::parser::{self, AssocOp, Fixity};
use rustc_ast::util::{classify, comments};
use rustc_span::edition::Edition;
@@ -293,7 +293,7 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(),
token::NtLifetime(e) => e.to_string(),
token::NtLiteral(ref e) => expr_to_string(e),
- token::NtTT(ref tree) => tt_to_string(tree.clone()),
+ token::NtTT(ref tree) => tt_to_string(tree),
token::NtVis(ref e) => vis_to_string(e),
}
}
@@ -314,11 +314,11 @@ pub fn expr_to_string(e: &ast::Expr) -> String {
to_string(|s| s.print_expr(e))
}
-pub fn tt_to_string(tt: tokenstream::TokenTree) -> String {
+pub fn tt_to_string(tt: &TokenTree) -> String {
to_string(|s| s.print_tt(tt, false))
}
-pub fn tts_to_string(tokens: TokenStream) -> String {
+pub fn tts_to_string(tokens: &TokenStream) -> String {
to_string(|s| s.print_tts(tokens, false))
}
@@ -585,7 +585,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
false,
None,
delim.to_token(),
- tokens.clone(),
+ tokens,
true,
span,
),
@@ -594,7 +594,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
if let MacArgs::Eq(_, tokens) = &item.args {
self.space();
self.word_space("=");
- self.print_tts(tokens.clone(), true);
+ self.print_tts(tokens, true);
}
}
}
@@ -635,9 +635,9 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
/// appropriate macro, transcribe back into the grammar we just parsed from,
/// and then pretty-print the resulting AST nodes (so, e.g., we print
/// expression arguments as expressions). It can be done! I think.
- fn print_tt(&mut self, tt: tokenstream::TokenTree, convert_dollar_crate: bool) {
+ fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) {
match tt {
- TokenTree::Token(ref token) => {
+ TokenTree::Token(token) => {
self.word(token_to_string_ext(&token, convert_dollar_crate));
if let token::DocComment(..) = token.kind {
self.hardbreak()
@@ -648,7 +648,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
None,
false,
None,
- delim,
+ *delim,
tts,
convert_dollar_crate,
dspan.entire(),
@@ -657,14 +657,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
}
}
- fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) {
- let mut iter = tts.into_trees().peekable();
+ fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) {
+ let mut iter = tts.trees().peekable();
while let Some(tt) = iter.next() {
- let show_space =
- if let Some(next) = iter.peek() { tt_prepend_space(next, &tt) } else { false };
- self.print_tt(tt, convert_dollar_crate);
- if show_space {
- self.space();
+ self.print_tt(&tt, convert_dollar_crate);
+ if let Some(next) = iter.peek() {
+ if tt_prepend_space(next, &tt) {
+ self.space();
+ }
}
}
}
@@ -675,7 +675,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere
has_bang: bool,
ident: Option,
delim: DelimToken,
- tts: TokenStream,
+ tts: &TokenStream,
convert_dollar_crate: bool,
span: Span,
) {
@@ -1253,7 +1253,7 @@ impl<'a> State<'a> {
has_bang,
Some(item.ident),
macro_def.body.delim(),
- macro_def.body.inner_tokens(),
+ ¯o_def.body.inner_tokens(),
true,
item.span,
);
@@ -1577,7 +1577,7 @@ impl<'a> State<'a> {
true,
None,
m.args.delim(),
- m.args.inner_tokens(),
+ &m.args.inner_tokens(),
true,
m.span(),
);
diff --git a/src/librustc_builtin_macros/log_syntax.rs b/src/librustc_builtin_macros/log_syntax.rs
index ae3a889428ae4..ede34a7612589 100644
--- a/src/librustc_builtin_macros/log_syntax.rs
+++ b/src/librustc_builtin_macros/log_syntax.rs
@@ -7,7 +7,7 @@ pub fn expand_log_syntax<'cx>(
sp: rustc_span::Span,
tts: TokenStream,
) -> Box {
- println!("{}", pprust::tts_to_string(tts));
+ println!("{}", pprust::tts_to_string(&tts));
// any so that `log_syntax` can be invoked as an expression and item.
base::DummyResult::any_valid(sp)
diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs
index 1b164eae5a345..e46cf67e64d66 100644
--- a/src/librustc_builtin_macros/source_util.rs
+++ b/src/librustc_builtin_macros/source_util.rs
@@ -71,7 +71,7 @@ pub fn expand_stringify(
tts: TokenStream,
) -> Box {
let sp = cx.with_def_site_ctxt(sp);
- let s = pprust::tts_to_string(tts);
+ let s = pprust::tts_to_string(&tts);
base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
}
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index e99fb8dcae1e5..d5e0d7d36ee7a 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -150,6 +150,11 @@ pub fn compile_codegen_unit(
cx.create_used_variable()
}
+ // Finalize code coverage by injecting the coverage map
+ if cx.sess().opts.debugging_opts.instrument_coverage {
+ cx.coverageinfo_finalize();
+ }
+
// Finalize debuginfo
if cx.sess().opts.debuginfo != DebugInfo::None {
cx.debuginfo_finalize();
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 7ff5ac5cbdc10..e9a001bab7540 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -1,5 +1,6 @@
use crate::attributes;
use crate::callee::get_fn;
+use crate::coverageinfo;
use crate::debuginfo;
use crate::llvm;
use crate::llvm_util;
@@ -77,6 +78,7 @@ pub struct CodegenCx<'ll, 'tcx> {
pub pointee_infos: RefCell, Size), Option>>,
pub isize_ty: &'ll Type,
+ pub coverage_cx: Option>,
pub dbg_cx: Option>,
eh_personality: Cell>,
@@ -256,6 +258,13 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
+ let coverage_cx = if tcx.sess.opts.debugging_opts.instrument_coverage {
+ let covctx = coverageinfo::CrateCoverageContext::new();
+ Some(covctx)
+ } else {
+ None
+ };
+
let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
let dctx = debuginfo::CrateDebugContext::new(llmod);
debuginfo::metadata::compile_unit_metadata(tcx, &codegen_unit.name().as_str(), &dctx);
@@ -285,6 +294,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
scalar_lltypes: Default::default(),
pointee_infos: Default::default(),
isize_ty,
+ coverage_cx,
dbg_cx,
eh_personality: Cell::new(None),
rust_try_fn: Cell::new(None),
@@ -296,6 +306,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
crate fn statics_to_rauw(&self) -> &RefCell> {
&self.statics_to_rauw
}
+
+ #[inline]
+ pub fn coverage_context(&'a self) -> &'a coverageinfo::CrateCoverageContext<'tcx> {
+ self.coverage_cx.as_ref().unwrap()
+ }
}
impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
@@ -749,8 +764,6 @@ impl CodegenCx<'b, 'tcx> {
ifn!("llvm.lifetime.start.p0i8", fn(t_i64, i8p) -> void);
ifn!("llvm.lifetime.end.p0i8", fn(t_i64, i8p) -> void);
- ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void);
-
ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32);
ifn!("llvm.localescape", fn(...) -> void);
@@ -765,6 +778,10 @@ impl CodegenCx<'b, 'tcx> {
ifn!("llvm.va_end", fn(i8p) -> void);
ifn!("llvm.va_copy", fn(i8p, i8p) -> void);
+ if self.sess().opts.debugging_opts.instrument_coverage {
+ ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void);
+ }
+
if self.sess().opts.debuginfo != DebugInfo::None {
ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void);
ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void);
diff --git a/src/librustc_codegen_llvm/coverageinfo/mod.rs b/src/librustc_codegen_llvm/coverageinfo/mod.rs
new file mode 100644
index 0000000000000..ff9f8f7aeaa54
--- /dev/null
+++ b/src/librustc_codegen_llvm/coverageinfo/mod.rs
@@ -0,0 +1,126 @@
+use crate::builder::Builder;
+use crate::common::CodegenCx;
+use log::debug;
+use rustc_codegen_ssa::coverageinfo::map::*;
+use rustc_codegen_ssa::traits::{CoverageInfoBuilderMethods, CoverageInfoMethods};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::ty::Instance;
+
+use std::cell::RefCell;
+
+/// A context object for maintaining all state needed by the coverageinfo module.
+pub struct CrateCoverageContext<'tcx> {
+ // Coverage region data for each instrumented function identified by DefId.
+ pub(crate) coverage_regions: RefCell, FunctionCoverageRegions>>,
+}
+
+impl<'tcx> CrateCoverageContext<'tcx> {
+ pub fn new() -> Self {
+ Self { coverage_regions: Default::default() }
+ }
+}
+
+/// Generates and exports the Coverage Map.
+// FIXME(richkadel): Actually generate and export the coverage map to LLVM.
+// The current implementation is actually just debug messages to show the data is available.
+pub fn finalize(cx: &CodegenCx<'_, '_>) {
+ let coverage_regions = &*cx.coverage_context().coverage_regions.borrow();
+ for instance in coverage_regions.keys() {
+ let coverageinfo = cx.tcx.coverageinfo(instance.def_id());
+ debug_assert!(coverageinfo.num_counters > 0);
+ debug!(
+ "Generate coverage map for: {:?}, hash: {}, num_counters: {}",
+ instance, coverageinfo.hash, coverageinfo.num_counters
+ );
+ let function_coverage_regions = &coverage_regions[instance];
+ for (index, region) in function_coverage_regions.indexed_regions() {
+ match region.kind {
+ CoverageKind::Counter => debug!(
+ " Counter {}, for {}..{}",
+ index, region.coverage_span.start_byte_pos, region.coverage_span.end_byte_pos
+ ),
+ CoverageKind::CounterExpression(lhs, op, rhs) => debug!(
+ " CounterExpression {} = {} {:?} {}, for {}..{}",
+ index,
+ lhs,
+ op,
+ rhs,
+ region.coverage_span.start_byte_pos,
+ region.coverage_span.end_byte_pos
+ ),
+ }
+ }
+ for unreachable in function_coverage_regions.unreachable_regions() {
+ debug!(
+ " Unreachable code region: {}..{}",
+ unreachable.start_byte_pos, unreachable.end_byte_pos
+ );
+ }
+ }
+}
+
+impl CoverageInfoMethods for CodegenCx<'ll, 'tcx> {
+ fn coverageinfo_finalize(&self) {
+ finalize(self)
+ }
+}
+
+impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
+ fn add_counter_region(
+ &mut self,
+ instance: Instance<'tcx>,
+ index: u32,
+ start_byte_pos: u32,
+ end_byte_pos: u32,
+ ) {
+ debug!(
+ "adding counter to coverage map: instance={:?}, index={}, byte range {}..{}",
+ instance, index, start_byte_pos, end_byte_pos,
+ );
+ let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut();
+ coverage_regions.entry(instance).or_default().add_counter(
+ index,
+ start_byte_pos,
+ end_byte_pos,
+ );
+ }
+
+ fn add_counter_expression_region(
+ &mut self,
+ instance: Instance<'tcx>,
+ index: u32,
+ lhs: u32,
+ op: CounterOp,
+ rhs: u32,
+ start_byte_pos: u32,
+ end_byte_pos: u32,
+ ) {
+ debug!(
+ "adding counter expression to coverage map: instance={:?}, index={}, {} {:?} {}, byte range {}..{}",
+ instance, index, lhs, op, rhs, start_byte_pos, end_byte_pos,
+ );
+ let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut();
+ coverage_regions.entry(instance).or_default().add_counter_expression(
+ index,
+ lhs,
+ op,
+ rhs,
+ start_byte_pos,
+ end_byte_pos,
+ );
+ }
+
+ fn add_unreachable_region(
+ &mut self,
+ instance: Instance<'tcx>,
+ start_byte_pos: u32,
+ end_byte_pos: u32,
+ ) {
+ debug!(
+ "adding unreachable code to coverage map: instance={:?}, byte range {}..{}",
+ instance, start_byte_pos, end_byte_pos,
+ );
+ let mut coverage_regions = self.coverage_context().coverage_regions.borrow_mut();
+ coverage_regions.entry(instance).or_default().add_unreachable(start_byte_pos, end_byte_pos);
+ }
+}
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 130c0cf1877c6..de90ac0bac1d3 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -13,12 +13,15 @@ use rustc_ast::ast;
use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
+use rustc_codegen_ssa::coverageinfo::CounterOp;
use rustc_codegen_ssa::glue;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::MemFlags;
use rustc_hir as hir;
+use rustc_middle::mir::coverage;
+use rustc_middle::mir::Operand;
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
use rustc_middle::ty::{self, Ty};
use rustc_middle::{bug, span_bug};
@@ -81,6 +84,53 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu
}
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
+ fn is_codegen_intrinsic(
+ &mut self,
+ intrinsic: &str,
+ args: &Vec>,
+ caller_instance: ty::Instance<'tcx>,
+ ) -> bool {
+ match intrinsic {
+ "count_code_region" => {
+ use coverage::count_code_region_args::*;
+ self.add_counter_region(
+ caller_instance,
+ op_to_u32(&args[COUNTER_INDEX]),
+ op_to_u32(&args[START_BYTE_POS]),
+ op_to_u32(&args[END_BYTE_POS]),
+ );
+ true // Also inject the counter increment in the backend
+ }
+ "coverage_counter_add" | "coverage_counter_subtract" => {
+ use coverage::coverage_counter_expression_args::*;
+ self.add_counter_expression_region(
+ caller_instance,
+ op_to_u32(&args[COUNTER_EXPRESSION_INDEX]),
+ op_to_u32(&args[LEFT_INDEX]),
+ if intrinsic == "coverage_counter_add" {
+ CounterOp::Add
+ } else {
+ CounterOp::Subtract
+ },
+ op_to_u32(&args[RIGHT_INDEX]),
+ op_to_u32(&args[START_BYTE_POS]),
+ op_to_u32(&args[END_BYTE_POS]),
+ );
+ false // Does not inject backend code
+ }
+ "coverage_unreachable" => {
+ use coverage::coverage_unreachable_args::*;
+ self.add_unreachable_region(
+ caller_instance,
+ op_to_u32(&args[START_BYTE_POS]),
+ op_to_u32(&args[END_BYTE_POS]),
+ );
+ false // Does not inject backend code
+ }
+ _ => true, // Unhandled intrinsics should be passed to `codegen_intrinsic_call()`
+ }
+ }
+
fn codegen_intrinsic_call(
&mut self,
instance: ty::Instance<'tcx>,
@@ -143,15 +193,16 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
// FIXME(richkadel): The current implementation assumes the MIR for the given
// caller_instance represents a single function. Validate and/or correct if inlining
// and/or monomorphization invalidates these assumptions.
- let coverage_data = tcx.coverage_data(caller_instance.def_id());
+ let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
let mangled_fn = tcx.symbol_name(caller_instance);
let (mangled_fn_name, _len_val) = self.const_str(mangled_fn.name);
- let hash = self.const_u64(coverage_data.hash);
- let num_counters = self.const_u32(coverage_data.num_counters);
- let index = args[0].immediate();
+ let hash = self.const_u64(coverageinfo.hash);
+ let num_counters = self.const_u32(coverageinfo.num_counters);
+ use coverage::count_code_region_args::*;
+ let index = args[COUNTER_INDEX].immediate();
debug!(
"count_code_region to LLVM intrinsic instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})",
- mangled_fn.name, hash, num_counters, index
+ mangled_fn.name, hash, num_counters, index,
);
self.instrprof_increment(mangled_fn_name, hash, num_counters, index)
}
@@ -2131,3 +2182,7 @@ fn float_type_width(ty: Ty<'_>) -> Option {
_ => None,
}
}
+
+fn op_to_u32<'tcx>(op: &Operand<'tcx>) -> u32 {
+ Operand::scalar_from_const(op).to_u32().expect("Scalar is u32")
+}
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 55ee660d9f700..565968f9952e5 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -55,6 +55,7 @@ mod callee;
mod common;
mod consts;
mod context;
+mod coverageinfo;
mod debuginfo;
mod declare;
mod intrinsic;
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index a34029410784a..3adaa07db91b0 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -1597,6 +1597,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
cmd.arg(format!("--dynamic-linker={}ld.so.1", prefix));
}
+ // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
+ cmd.add_eh_frame_header();
+
// NO-OPT-OUT, OBJECT-FILES-NO
if crt_objects_fallback {
cmd.no_crt_objects();
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index d6ef94bfd1727..54f55c806d035 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -129,6 +129,7 @@ pub trait Linker {
fn group_start(&mut self);
fn group_end(&mut self);
fn linker_plugin_lto(&mut self);
+ fn add_eh_frame_header(&mut self) {}
fn finalize(&mut self);
}
@@ -615,6 +616,19 @@ impl<'a> Linker for GccLinker<'a> {
}
}
}
+
+ // Add the `GNU_EH_FRAME` program header which is required to locate unwinding information.
+ // Some versions of `gcc` add it implicitly, some (e.g. `musl-gcc`) don't,
+ // so we just always add it.
+ fn add_eh_frame_header(&mut self) {
+ // The condition here is "uses ELF" basically.
+ if !self.sess.target.target.options.is_like_osx
+ && !self.sess.target.target.options.is_like_windows
+ && self.sess.target.target.target_os != "uefi"
+ {
+ self.linker_arg("--eh-frame-hdr");
+ }
+ }
}
pub struct MsvcLinker<'a> {
diff --git a/src/librustc_codegen_ssa/coverageinfo/map.rs b/src/librustc_codegen_ssa/coverageinfo/map.rs
new file mode 100644
index 0000000000000..3bd262cf2b213
--- /dev/null
+++ b/src/librustc_codegen_ssa/coverageinfo/map.rs
@@ -0,0 +1,83 @@
+use rustc_data_structures::fx::FxHashMap;
+use std::collections::hash_map;
+use std::slice;
+
+#[derive(Copy, Clone, Debug)]
+pub enum CounterOp {
+ Add,
+ Subtract,
+}
+
+pub enum CoverageKind {
+ Counter,
+ CounterExpression(u32, CounterOp, u32),
+}
+
+pub struct CoverageSpan {
+ pub start_byte_pos: u32,
+ pub end_byte_pos: u32,
+}
+
+pub struct CoverageRegion {
+ pub kind: CoverageKind,
+ pub coverage_span: CoverageSpan,
+}
+
+/// Collects all of the coverage regions associated with (a) injected counters, (b) counter
+/// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero),
+/// for a given Function. Counters and counter expressions are indexed because they can be operands
+/// in an expression.
+///
+/// Note, it's important to distinguish the `unreachable` region type from what LLVM's refers to as
+/// a "gap region" (or "gap area"). A gap region is a code region within a counted region (either
+/// counter or expression), but the line or lines in the gap region are not executable (such as
+/// lines with only whitespace or comments). According to LLVM Code Coverage Mapping documentation,
+/// "A count for a gap area is only used as the line execution count if there are no other regions
+/// on a line."
+#[derive(Default)]
+pub struct FunctionCoverageRegions {
+ indexed: FxHashMap,
+ unreachable: Vec,
+}
+
+impl FunctionCoverageRegions {
+ pub fn add_counter(&mut self, index: u32, start_byte_pos: u32, end_byte_pos: u32) {
+ self.indexed.insert(
+ index,
+ CoverageRegion {
+ kind: CoverageKind::Counter,
+ coverage_span: CoverageSpan { start_byte_pos, end_byte_pos },
+ },
+ );
+ }
+
+ pub fn add_counter_expression(
+ &mut self,
+ index: u32,
+ lhs: u32,
+ op: CounterOp,
+ rhs: u32,
+ start_byte_pos: u32,
+ end_byte_pos: u32,
+ ) {
+ self.indexed.insert(
+ index,
+ CoverageRegion {
+ kind: CoverageKind::CounterExpression(lhs, op, rhs),
+ coverage_span: CoverageSpan { start_byte_pos, end_byte_pos },
+ },
+ );
+ }
+
+ pub fn add_unreachable(&mut self, start_byte_pos: u32, end_byte_pos: u32) {
+ self.unreachable.push(CoverageSpan { start_byte_pos, end_byte_pos });
+ }
+
+ pub fn indexed_regions(&self) -> hash_map::Iter<'_, u32, CoverageRegion> {
+ self.indexed.iter()
+ }
+
+ pub fn unreachable_regions(&self) -> slice::Iter<'_, CoverageSpan> {
+ self.unreachable.iter()
+ }
+}
diff --git a/src/librustc_codegen_ssa/coverageinfo/mod.rs b/src/librustc_codegen_ssa/coverageinfo/mod.rs
new file mode 100644
index 0000000000000..304f8e19da4e6
--- /dev/null
+++ b/src/librustc_codegen_ssa/coverageinfo/mod.rs
@@ -0,0 +1,3 @@
+pub mod map;
+
+pub use map::CounterOp;
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index bd3721850f35f..618df15f5bcbe 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -34,6 +34,7 @@ use std::path::{Path, PathBuf};
pub mod back;
pub mod base;
pub mod common;
+pub mod coverageinfo;
pub mod debuginfo;
pub mod glue;
pub mod meth;
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 480f9a5032087..7514eb8e889a8 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -651,6 +651,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
if intrinsic.is_some() && intrinsic != Some("drop_in_place") {
+ let intrinsic = intrinsic.unwrap();
+
+ // `is_codegen_intrinsic()` allows the backend implementation to perform compile-time
+ // operations before converting the `args` to backend values.
+ if !bx.is_codegen_intrinsic(intrinsic, &args, self.instance) {
+ // If the intrinsic call was fully addressed by the `is_codegen_intrinsic()` call
+ // (as a compile-time operation), return immediately. This avoids the need to
+ // convert the arguments, the call to `codegen_intrinsic_call()`, and the return
+ // value handling.
+ return;
+ }
+
let dest = match ret_dest {
_ if fn_abi.ret.is_indirect() => llargs[0],
ReturnDest::Nothing => {
@@ -670,7 +682,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// third argument must be constant. This is
// checked by const-qualification, which also
// promotes any complex rvalues to constants.
- if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") {
+ if i == 2 && intrinsic.starts_with("simd_shuffle") {
if let mir::Operand::Constant(constant) = arg {
let c = self.eval_mir_constant(constant);
let (llval, ty) = self.simd_shuffle_indices(
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index 7ffc9f15bffdc..994d8e0395dc7 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -1,5 +1,6 @@
use super::abi::AbiBuilderMethods;
use super::asm::AsmBuilderMethods;
+use super::coverageinfo::CoverageInfoBuilderMethods;
use super::debuginfo::DebugInfoBuilderMethods;
use super::intrinsic::IntrinsicCallMethods;
use super::type_::ArgAbiMethods;
@@ -29,6 +30,7 @@ pub enum OverflowOp {
pub trait BuilderMethods<'a, 'tcx>:
HasCodegen<'tcx>
+ + CoverageInfoBuilderMethods<'tcx>
+ DebugInfoBuilderMethods
+ ArgAbiMethods<'tcx>
+ AbiBuilderMethods<'tcx>
diff --git a/src/librustc_codegen_ssa/traits/coverageinfo.rs b/src/librustc_codegen_ssa/traits/coverageinfo.rs
new file mode 100644
index 0000000000000..d80f90fa4fa0d
--- /dev/null
+++ b/src/librustc_codegen_ssa/traits/coverageinfo.rs
@@ -0,0 +1,35 @@
+use super::BackendTypes;
+use crate::coverageinfo::CounterOp;
+use rustc_middle::ty::Instance;
+
+pub trait CoverageInfoMethods: BackendTypes {
+ fn coverageinfo_finalize(&self);
+}
+
+pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
+ fn add_counter_region(
+ &mut self,
+ instance: Instance<'tcx>,
+ index: u32,
+ start_byte_pos: u32,
+ end_byte_pos: u32,
+ );
+
+ fn add_counter_expression_region(
+ &mut self,
+ instance: Instance<'tcx>,
+ index: u32,
+ lhs: u32,
+ op: CounterOp,
+ rhs: u32,
+ start_byte_pos: u32,
+ end_byte_pos: u32,
+ );
+
+ fn add_unreachable_region(
+ &mut self,
+ instance: Instance<'tcx>,
+ start_byte_pos: u32,
+ end_byte_pos: u32,
+ );
+}
diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs
index f62019498511c..e713cc948c10d 100644
--- a/src/librustc_codegen_ssa/traits/intrinsic.rs
+++ b/src/librustc_codegen_ssa/traits/intrinsic.rs
@@ -1,5 +1,6 @@
use super::BackendTypes;
use crate::mir::operand::OperandRef;
+use rustc_middle::mir::Operand;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_target::abi::call::FnAbi;
@@ -18,6 +19,16 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
caller_instance: ty::Instance<'tcx>,
);
+ /// Intrinsic-specific pre-codegen processing, if any is required. Some intrinsics are handled
+ /// at compile time and do not generate code. Returns true if codegen is required or false if
+ /// the intrinsic does not need code generation.
+ fn is_codegen_intrinsic(
+ &mut self,
+ intrinsic: &str,
+ args: &Vec>,
+ caller_instance: ty::Instance<'tcx>,
+ ) -> bool;
+
fn abort(&mut self);
fn assume(&mut self, val: Self::Value);
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;
diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs
index 6b782731d535c..0ac519dd0b17c 100644
--- a/src/librustc_codegen_ssa/traits/mod.rs
+++ b/src/librustc_codegen_ssa/traits/mod.rs
@@ -19,6 +19,7 @@ mod asm;
mod backend;
mod builder;
mod consts;
+mod coverageinfo;
mod debuginfo;
mod declare;
mod intrinsic;
@@ -32,6 +33,7 @@ pub use self::asm::{AsmBuilderMethods, AsmMethods, InlineAsmOperandRef};
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
pub use self::builder::{BuilderMethods, OverflowOp};
pub use self::consts::ConstMethods;
+pub use self::coverageinfo::{CoverageInfoBuilderMethods, CoverageInfoMethods};
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
pub use self::declare::{DeclareMethods, PreDefineMethods};
pub use self::intrinsic::IntrinsicCallMethods;
@@ -56,6 +58,7 @@ pub trait CodegenMethods<'tcx>:
+ MiscMethods<'tcx>
+ ConstMethods<'tcx>
+ StaticMethods
+ + CoverageInfoMethods
+ DebugInfoMethods<'tcx>
+ DeclareMethods<'tcx>
+ AsmMethods
@@ -72,6 +75,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
+ MiscMethods<'tcx>
+ ConstMethods<'tcx>
+ StaticMethods
+ + CoverageInfoMethods
+ DebugInfoMethods<'tcx>
+ DeclareMethods<'tcx>
+ AsmMethods
diff --git a/src/librustc_error_codes/error_codes/E0736.md b/src/librustc_error_codes/error_codes/E0736.md
index 8a60dc320599b..0f3d41ba66dc4 100644
--- a/src/librustc_error_codes/error_codes/E0736.md
+++ b/src/librustc_error_codes/error_codes/E0736.md
@@ -3,8 +3,6 @@
Erroneous code example:
```compile_fail,E0736
-#![feature(track_caller)]
-
#[naked]
#[track_caller]
fn foo() {}
diff --git a/src/librustc_error_codes/error_codes/E0737.md b/src/librustc_error_codes/error_codes/E0737.md
index c6553e97b7e91..ab5e60692b4da 100644
--- a/src/librustc_error_codes/error_codes/E0737.md
+++ b/src/librustc_error_codes/error_codes/E0737.md
@@ -5,8 +5,6 @@ restrictions.
Erroneous code example:
```compile_fail,E0737
-#![feature(track_caller)]
-
#[track_caller]
extern "C" fn foo() {}
```
diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md
index 707751066edbc..8d9039bef93f6 100644
--- a/src/librustc_error_codes/error_codes/E0739.md
+++ b/src/librustc_error_codes/error_codes/E0739.md
@@ -3,7 +3,6 @@
Erroneous code example:
```compile_fail,E0739
-#![feature(track_caller)]
#[track_caller]
struct Bar {
a: u8,
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 0c1418d3cad27..362913ceadf18 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -5,7 +5,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(crate_visibility_modifier)]
#![feature(nll)]
-#![feature(track_caller)]
+#![cfg_attr(bootstrap, feature(track_caller))]
pub use emitter::ColorConfig;
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index 8cdb5b09c9e8b..28a3970918ee6 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -224,7 +224,7 @@ fn generic_extension<'cx>(
let sess = cx.parse_sess;
if cx.trace_macros() {
- let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone()));
+ let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(&arg));
trace_macros_note(&mut cx.expansions, sp, msg);
}
@@ -300,7 +300,7 @@ fn generic_extension<'cx>(
}
if cx.trace_macros() {
- let msg = format!("to `{}`", pprust::tts_to_string(tts.clone()));
+ let msg = format!("to `{}`", pprust::tts_to_string(&tts));
trace_macros_note(&mut cx.expansions, sp, msg);
}
diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs
index c88b5a37f718a..e5e530227e43a 100644
--- a/src/librustc_expand/proc_macro_server.rs
+++ b/src/librustc_expand/proc_macro_server.rs
@@ -413,7 +413,7 @@ impl server::TokenStream for Rustc<'_> {
)
}
fn to_string(&mut self, stream: &Self::TokenStream) -> String {
- pprust::tts_to_string(stream.clone())
+ pprust::tts_to_string(stream)
}
fn from_token_tree(
&mut self,
diff --git a/src/librustc_feature/accepted.rs b/src/librustc_feature/accepted.rs
index b164b21913d6e..d93c17b05b498 100644
--- a/src/librustc_feature/accepted.rs
+++ b/src/librustc_feature/accepted.rs
@@ -265,6 +265,9 @@ declare_features! (
(accepted, const_if_match, "1.45.0", Some(49146), None),
/// Allows the use of `loop` and `while` in constants.
(accepted, const_loop, "1.45.0", Some(52000), None),
+ /// Allows `#[track_caller]` to be used which provides
+ /// accurate caller location reporting during panic (RFC 2091).
+ (accepted, track_caller, "1.46.0", Some(47809), None),
// -------------------------------------------------------------------------
// feature-group-end: accepted features
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 8660d6a8d6410..b9a55377949f2 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -494,10 +494,6 @@ declare_features! (
/// Allows the use of raw-dylibs (RFC 2627).
(active, raw_dylib, "1.40.0", Some(58713), None),
- /// Allows `#[track_caller]` to be used which provides
- /// accurate caller location reporting during panic (RFC 2091).
- (active, track_caller, "1.40.0", Some(47809), None),
-
/// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
/// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
/// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs
index 524a357971029..c9a34f033758b 100644
--- a/src/librustc_feature/builtin_attrs.rs
+++ b/src/librustc_feature/builtin_attrs.rs
@@ -260,6 +260,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
ungated!(cold, Whitelisted, template!(Word)),
ungated!(no_builtins, Whitelisted, template!(Word)),
ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)),
+ ungated!(track_caller, Whitelisted, template!(Word)),
gated!(
no_sanitize, Whitelisted,
template!(List: "address, memory, thread"),
@@ -333,7 +334,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)),
gated!(ffi_pure, Whitelisted, template!(Word), experimental!(ffi_pure)),
gated!(ffi_const, Whitelisted, template!(Word), experimental!(ffi_const)),
- gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)),
gated!(
register_attr, CrateLevel, template!(List: "attr1, attr2, ..."),
experimental!(register_attr),
diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs
index 4dde33283f575..c5dedab979326 100644
--- a/src/librustc_index/vec.rs
+++ b/src/librustc_index/vec.rs
@@ -536,7 +536,8 @@ impl IndexVec {
}
/// Create an `IndexVec` with `n` elements, where the value of each
- /// element is the result of `func(i)`
+ /// element is the result of `func(i)`. (The underlying vector will
+ /// be allocated only once, with a capacity of at least `n`.)
#[inline]
pub fn from_fn_n(func: impl FnMut(I) -> T, n: usize) -> Self {
let indices = (0..n).map(I::new);
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index d861b444c8816..e35dbbc0c2f24 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -500,7 +500,6 @@ fn test_debugging_options_tracking_hash() {
untracked!(print_link_args, true);
untracked!(print_llvm_passes, true);
untracked!(print_mono_items, Some(String::from("abc")));
- untracked!(print_region_graph, true);
untracked!(print_type_sizes, true);
untracked!(query_dep_graph, true);
untracked!(query_stats, true);
diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs
index 676346fbebdd1..96b8ca27183ed 100644
--- a/src/librustc_middle/lib.rs
+++ b/src/librustc_middle/lib.rs
@@ -42,7 +42,7 @@
#![feature(or_patterns)]
#![feature(range_is_empty)]
#![feature(min_specialization)]
-#![feature(track_caller)]
+#![cfg_attr(bootstrap, feature(track_caller))]
#![feature(trusted_len)]
#![feature(stmt_expr_attributes)]
#![feature(test)]
diff --git a/src/librustc_middle/mir/coverage/mod.rs b/src/librustc_middle/mir/coverage/mod.rs
new file mode 100644
index 0000000000000..327f321bd7534
--- /dev/null
+++ b/src/librustc_middle/mir/coverage/mod.rs
@@ -0,0 +1,24 @@
+//! Metadata from source code coverage analysis and instrumentation.
+
+/// Positional arguments to `libcore::count_code_region()`
+pub mod count_code_region_args {
+ pub const COUNTER_INDEX: usize = 0;
+ pub const START_BYTE_POS: usize = 1;
+ pub const END_BYTE_POS: usize = 2;
+}
+
+/// Positional arguments to `libcore::coverage_counter_add()` and
+/// `libcore::coverage_counter_subtract()`
+pub mod coverage_counter_expression_args {
+ pub const COUNTER_EXPRESSION_INDEX: usize = 0;
+ pub const LEFT_INDEX: usize = 1;
+ pub const RIGHT_INDEX: usize = 2;
+ pub const START_BYTE_POS: usize = 3;
+ pub const END_BYTE_POS: usize = 4;
+}
+
+/// Positional arguments to `libcore::coverage_unreachable()`
+pub mod coverage_unreachable_args {
+ pub const START_BYTE_POS: usize = 0;
+ pub const END_BYTE_POS: usize = 1;
+}
diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs
index 0ed0d9050078c..a3eddd3ff7ba7 100644
--- a/src/librustc_middle/mir/mod.rs
+++ b/src/librustc_middle/mir/mod.rs
@@ -40,6 +40,7 @@ use std::{iter, mem, option};
use self::predecessors::{PredecessorCache, Predecessors};
pub use self::query::*;
+pub mod coverage;
pub mod interpret;
pub mod mono;
mod predecessors;
@@ -2307,6 +2308,18 @@ impl<'tcx> Operand<'tcx> {
})
}
+ /// Convenience helper to make a `Scalar` from the given `Operand`, assuming that `Operand`
+ /// wraps a constant literal value. Panics if this is not the case.
+ pub fn scalar_from_const(operand: &Operand<'tcx>) -> Scalar {
+ match operand {
+ Operand::Constant(constant) => match constant.literal.val.try_to_scalar() {
+ Some(scalar) => scalar,
+ _ => panic!("{:?}: Scalar value expected", constant.literal.val),
+ },
+ _ => panic!("{:?}: Constant expected", operand),
+ }
+ }
+
pub fn to_copy(&self) -> Self {
match *self {
Operand::Copy(_) | Operand::Constant(_) => self.clone(),
@@ -2980,18 +2993,3 @@ impl Location {
}
}
}
-
-/// Coverage data associated with each function (MIR) instrumented with coverage counters, when
-/// compiled with `-Zinstrument_coverage`. The query `tcx.coverage_data(DefId)` computes these
-/// values on demand (during code generation). This query is only valid after executing the MIR pass
-/// `InstrumentCoverage`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub struct CoverageData {
- /// A hash value that can be used by the consumer of the coverage profile data to detect
- /// changes to the instrumented source of the associated MIR body (typically, for an
- /// individual function).
- pub hash: u64,
-
- /// The total number of coverage region counters added to the MIR `Body`.
- pub num_counters: u32,
-}
diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs
index 9ad79230a4f6d..8dddaf40c8264 100644
--- a/src/librustc_middle/mir/query.rs
+++ b/src/librustc_middle/mir/query.rs
@@ -309,3 +309,17 @@ pub struct DestructuredConst<'tcx> {
pub variant: Option,
pub fields: &'tcx [&'tcx ty::Const<'tcx>],
}
+
+/// Coverage information summarized from a MIR if instrumented for source code coverage (see
+/// compiler option `-Zinstrument-coverage`). This information is generated by the
+/// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+pub struct CoverageInfo {
+ /// A hash value that can be used by the consumer of the coverage profile data to detect
+ /// changes to the instrumented source of the associated MIR body (typically, for an
+ /// individual function).
+ pub hash: u64,
+
+ /// The total number of coverage region counters added to the MIR `Body`.
+ pub num_counters: u32,
+}
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index ba5a8c3ec2052..c9201855462ee 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -231,8 +231,10 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
}
- query coverage_data(key: DefId) -> mir::CoverageData {
- desc { |tcx| "retrieving coverage data from MIR for `{}`", tcx.def_path_str(key) }
+ /// Returns coverage summary info for a function, after executing the `InstrumentCoverage`
+ /// MIR pass (assuming the -Zinstrument-coverage option is enabled).
+ query coverageinfo(key: DefId) -> mir::CoverageInfo {
+ desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key) }
storage(ArenaCacheSelector<'tcx>)
cache_on_disk_if { key.is_local() }
}
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 88ba28dab82e1..a2bd65e82e24e 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -410,7 +410,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.copy_op(self.operand_index(args[0], index)?, dest)?;
}
// FIXME(#73156): Handle source code coverage in const eval
- sym::count_code_region => (),
+ sym::count_code_region
+ | sym::coverage_counter_add
+ | sym::coverage_counter_subtract
+ | sym::coverage_unreachable => (),
_ => return Ok(false),
}
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 068d055fa78f8..c03be2a8fcd69 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -39,7 +39,14 @@ struct CallSite<'tcx> {
impl<'tcx> MirPass<'tcx> for Inline {
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
- Inliner { tcx, source }.run_pass(body);
+ if tcx.sess.opts.debugging_opts.instrument_coverage {
+ // The current implementation of source code coverage injects code region counters
+ // into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code-
+ // based function.
+ debug!("function inlining is disabled when compiling with `instrument_coverage`");
+ } else {
+ Inliner { tcx, source }.run_pass(body);
+ }
}
}
}
diff --git a/src/librustc_mir/transform/instrument_coverage.rs b/src/librustc_mir/transform/instrument_coverage.rs
index 06b648ab5a908..25e154f2e9597 100644
--- a/src/librustc_mir/transform/instrument_coverage.rs
+++ b/src/librustc_mir/transform/instrument_coverage.rs
@@ -5,65 +5,71 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::lang_items;
use rustc_middle::hir;
use rustc_middle::ich::StableHashingContext;
-use rustc_middle::mir::interpret::{ConstValue, Scalar};
+use rustc_middle::mir::coverage::*;
+use rustc_middle::mir::interpret::Scalar;
+use rustc_middle::mir::CoverageInfo;
use rustc_middle::mir::{
- self, traversal, BasicBlock, BasicBlockData, CoverageData, Operand, Place, SourceInfo,
- StatementKind, Terminator, TerminatorKind, START_BLOCK,
+ self, traversal, BasicBlock, BasicBlockData, Operand, Place, SourceInfo, StatementKind,
+ Terminator, TerminatorKind, START_BLOCK,
};
use rustc_middle::ty;
use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::FnDef;
use rustc_middle::ty::TyCtxt;
-use rustc_middle::ty::{ConstKind, FnDef};
use rustc_span::def_id::DefId;
-use rustc_span::Span;
+use rustc_span::{Pos, Span};
/// Inserts call to count_code_region() as a placeholder to be replaced during code generation with
/// the intrinsic llvm.instrprof.increment.
pub struct InstrumentCoverage;
-/// The `query` provider for `CoverageData`, requested by `codegen_intrinsic_call()` when
+/// The `query` provider for `CoverageInfo`, requested by `codegen_intrinsic_call()` when
/// constructing the arguments for `llvm.instrprof.increment`.
pub(crate) fn provide(providers: &mut Providers<'_>) {
- providers.coverage_data = |tcx, def_id| {
- let mir_body = tcx.optimized_mir(def_id);
- // FIXME(richkadel): The current implementation assumes the MIR for the given DefId
- // represents a single function. Validate and/or correct if inlining and/or monomorphization
- // invalidates these assumptions.
- let count_code_region_fn =
- tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None);
- let mut num_counters: u32 = 0;
- // The `num_counters` argument to `llvm.instrprof.increment` is the number of injected
- // counters, with each counter having an index from `0..num_counters-1`. MIR optimization
- // may split and duplicate some BasicBlock sequences. Simply counting the calls may not
- // not work; but computing the num_counters by adding `1` to the highest index (for a given
- // instrumented function) is valid.
- for (_, data) in traversal::preorder(mir_body) {
- if let Some(terminator) = &data.terminator {
- if let TerminatorKind::Call { func: Operand::Constant(func), args, .. } =
- &terminator.kind
- {
- if let FnDef(called_fn_def_id, _) = func.literal.ty.kind {
- if called_fn_def_id == count_code_region_fn {
- if let Operand::Constant(constant) =
- args.get(0).expect("count_code_region has at least one arg")
- {
- if let ConstKind::Value(ConstValue::Scalar(value)) =
- constant.literal.val
- {
- let index = value
- .to_u32()
- .expect("count_code_region index at arg0 is u32");
- num_counters = std::cmp::max(num_counters, index + 1);
- }
- }
- }
- }
+ providers.coverageinfo = |tcx, def_id| coverageinfo_from_mir(tcx, def_id);
+}
+
+fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, mir_def_id: DefId) -> CoverageInfo {
+ let mir_body = tcx.optimized_mir(mir_def_id);
+ // FIXME(richkadel): The current implementation assumes the MIR for the given DefId
+ // represents a single function. Validate and/or correct if inlining (which should be disabled
+ // if -Zinstrument-coverage is enabled) and/or monomorphization invalidates these assumptions.
+ let count_code_region_fn = tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None);
+
+ // The `num_counters` argument to `llvm.instrprof.increment` is the number of injected
+ // counters, with each counter having an index from `0..num_counters-1`. MIR optimization
+ // may split and duplicate some BasicBlock sequences. Simply counting the calls may not
+ // not work; but computing the num_counters by adding `1` to the highest index (for a given
+ // instrumented function) is valid.
+ let mut num_counters: u32 = 0;
+ for terminator in traversal::preorder(mir_body)
+ .map(|(_, data)| (data, count_code_region_fn))
+ .filter_map(terminators_that_call_given_fn)
+ {
+ if let TerminatorKind::Call { args, .. } = &terminator.kind {
+ let index_arg = args.get(count_code_region_args::COUNTER_INDEX).expect("arg found");
+ let index =
+ mir::Operand::scalar_from_const(index_arg).to_u32().expect("index arg is u32");
+ num_counters = std::cmp::max(num_counters, index + 1);
+ }
+ }
+ let hash = if num_counters > 0 { hash_mir_source(tcx, mir_def_id) } else { 0 };
+ CoverageInfo { num_counters, hash }
+}
+
+fn terminators_that_call_given_fn(
+ (data, fn_def_id): (&'tcx BasicBlockData<'tcx>, DefId),
+) -> Option<&'tcx Terminator<'tcx>> {
+ if let Some(terminator) = &data.terminator {
+ if let TerminatorKind::Call { func: Operand::Constant(func), .. } = &terminator.kind {
+ if let FnDef(called_fn_def_id, _) = func.literal.ty.kind {
+ if called_fn_def_id == fn_def_id {
+ return Some(&terminator);
}
}
}
- let hash = if num_counters > 0 { hash_mir_source(tcx, def_id) } else { 0 };
- CoverageData { num_counters, hash }
- };
+ }
+ None
}
struct Instrumentor<'tcx> {
@@ -102,17 +108,16 @@ impl<'tcx> Instrumentor<'tcx> {
fn inject_counters(&mut self, mir_body: &mut mir::Body<'tcx>) {
// FIXME(richkadel): As a first step, counters are only injected at the top of each
// function. The complete solution will inject counters at each conditional code branch.
- let top_of_function = START_BLOCK;
- let entire_function = mir_body.span;
-
- self.inject_counter(mir_body, top_of_function, entire_function);
+ let code_region = mir_body.span;
+ let next_block = START_BLOCK;
+ self.inject_counter(mir_body, code_region, next_block);
}
fn inject_counter(
&mut self,
mir_body: &mut mir::Body<'tcx>,
- next_block: BasicBlock,
code_region: Span,
+ next_block: BasicBlock,
) {
let injection_point = code_region.shrink_to_lo();
@@ -121,12 +126,20 @@ impl<'tcx> Instrumentor<'tcx> {
self.tcx.require_lang_item(lang_items::CountCodeRegionFnLangItem, None),
injection_point,
);
- let counter_index = Operand::const_from_scalar(
- self.tcx,
- self.tcx.types.u32,
- Scalar::from_u32(self.next_counter()),
- injection_point,
- );
+
+ let index = self.next_counter();
+
+ let mut args = Vec::new();
+
+ use count_code_region_args::*;
+ debug_assert_eq!(COUNTER_INDEX, args.len());
+ args.push(self.const_u32(index, injection_point));
+
+ debug_assert_eq!(START_BYTE_POS, args.len());
+ args.push(self.const_u32(code_region.lo().to_u32(), injection_point));
+
+ debug_assert_eq!(END_BYTE_POS, args.len());
+ args.push(self.const_u32(code_region.hi().to_u32(), injection_point));
let mut patch = MirPatch::new(mir_body);
@@ -136,7 +149,7 @@ impl<'tcx> Instrumentor<'tcx> {
new_block,
TerminatorKind::Call {
func: count_code_region_fn,
- args: vec![counter_index],
+ args,
// new_block will swapped with the next_block, after applying patch
destination: Some((Place::from(temp), new_block)),
cleanup: None,
@@ -154,6 +167,10 @@ impl<'tcx> Instrumentor<'tcx> {
// `next_block`), just swap the indexes, leaving the rest of the graph unchanged.
mir_body.basic_blocks_mut().swap(next_block, new_block);
}
+
+ fn const_u32(&self, value: u32, span: Span) -> Operand<'tcx> {
+ Operand::const_from_scalar(self.tcx, self.tcx.types.u32, Scalar::from_u32(value), span)
+ }
}
fn function_handle<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: DefId, span: Span) -> Operand<'tcx> {
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
index 6ac5d41ec6135..18b92bf29bf1b 100644
--- a/src/librustc_mir_build/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -4,8 +4,8 @@
//! This file includes the logic for exhaustiveness and usefulness checking for
//! pattern-matching. Specifically, given a list of patterns for a type, we can
//! tell whether:
-//! (a) the patterns cover every possible constructor for the type [exhaustiveness]
-//! (b) each pattern is necessary [usefulness]
+//! (a) the patterns cover every possible constructor for the type (exhaustiveness)
+//! (b) each pattern is necessary (usefulness)
//!
//! The algorithm implemented here is a modified version of the one described in:
//! http://moscova.inria.fr/~maranget/papers/warn/index.html
@@ -101,53 +101,54 @@
//! To match the paper, the top of the stack is at the beginning / on the left.
//!
//! There are two important operations on pattern-stacks necessary to understand the algorithm:
-//! 1. We can pop a given constructor off the top of a stack. This operation is called
-//! `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or
-//! `None`) and `p` a pattern-stack.
-//! If the pattern on top of the stack can cover `c`, this removes the constructor and
-//! pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns.
-//! Otherwise the pattern-stack is discarded.
-//! This essentially filters those pattern-stacks whose top covers the constructor `c` and
-//! discards the others.
//!
-//! For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we
-//! pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the
-//! `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get
-//! nothing back.
+//! 1. We can pop a given constructor off the top of a stack. This operation is called
+//! `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or
+//! `None`) and `p` a pattern-stack.
+//! If the pattern on top of the stack can cover `c`, this removes the constructor and
+//! pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns.
+//! Otherwise the pattern-stack is discarded.
+//! This essentially filters those pattern-stacks whose top covers the constructor `c` and
+//! discards the others.
//!
-//! This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1`
-//! on top of the stack, and we have four cases:
-//! 1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We
-//! push onto the stack the arguments of this constructor, and return the result:
-//! r_1, .., r_a, p_2, .., p_n
-//! 1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and
-//! return nothing.
-//! 1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has
-//! arguments (its arity), and return the resulting stack:
-//! _, .., _, p_2, .., p_n
-//! 1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
-//! stack:
-//! S(c, (r_1, p_2, .., p_n))
-//! S(c, (r_2, p_2, .., p_n))
+//! For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we
+//! pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the
+//! `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get
+//! nothing back.
//!
-//! 2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is
-//! a pattern-stack.
-//! This is used when we know there are missing constructor cases, but there might be
-//! existing wildcard patterns, so to check the usefulness of the matrix, we have to check
-//! all its *other* components.
+//! This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1`
+//! on top of the stack, and we have four cases:
+//! 1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We
+//! push onto the stack the arguments of this constructor, and return the result:
+//! r_1, .., r_a, p_2, .., p_n
+//! 1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and
+//! return nothing.
+//! 1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has
+//! arguments (its arity), and return the resulting stack:
+//! _, .., _, p_2, .., p_n
+//! 1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
+//! stack:
+//! S(c, (r_1, p_2, .., p_n))
+//! S(c, (r_2, p_2, .., p_n))
//!
-//! It is computed as follows. We look at the pattern `p_1` on top of the stack,
-//! and we have three cases:
-//! 1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing.
-//! 1.2. `p_1 = _`. We return the rest of the stack:
-//! p_2, .., p_n
-//! 1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
-//! stack.
-//! D((r_1, p_2, .., p_n))
-//! D((r_2, p_2, .., p_n))
+//! 2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is
+//! a pattern-stack.
+//! This is used when we know there are missing constructor cases, but there might be
+//! existing wildcard patterns, so to check the usefulness of the matrix, we have to check
+//! all its *other* components.
//!
-//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the
-//! exhaustive integer matching rules, so they're written here for posterity.
+//! It is computed as follows. We look at the pattern `p_1` on top of the stack,
+//! and we have three cases:
+//! 1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing.
+//! 1.2. `p_1 = _`. We return the rest of the stack:
+//! p_2, .., p_n
+//! 1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
+//! stack.
+//! D((r_1, p_2, .., p_n))
+//! D((r_2, p_2, .., p_n))
+//!
+//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the
+//! exhaustive integer matching rules, so they're written here for posterity.
//!
//! Both those operations extend straightforwardly to a list or pattern-stacks, i.e. a matrix, by
//! working row-by-row. Popping a constructor ends up keeping only the matrix rows that start with
@@ -168,66 +169,66 @@
//!
//! Inductive step. (`n > 0`, i.e., whether there's at least one column
//! [which may then be expanded into further columns later])
-//! We're going to match on the top of the new pattern-stack, `p_1`.
-//! - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern.
-//! Then, the usefulness of `p_1` can be reduced to whether it is useful when
-//! we ignore all the patterns in the first column of `P` that involve other constructors.
-//! This is where `S(c, P)` comes in:
-//! `U(P, p) := U(S(c, P), S(c, p))`
-//! This special case is handled in `is_useful_specialized`.
+//! We're going to match on the top of the new pattern-stack, `p_1`.
+//! - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern.
+//! Then, the usefulness of `p_1` can be reduced to whether it is useful when
+//! we ignore all the patterns in the first column of `P` that involve other constructors.
+//! This is where `S(c, P)` comes in:
+//! `U(P, p) := U(S(c, P), S(c, p))`
+//! This special case is handled in `is_useful_specialized`.
//!
-//! For example, if `P` is:
-//! [
-//! [Some(true), _],
-//! [None, 0],
-//! ]
-//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only
-//! matches values that row 2 doesn't. For row 1 however, we need to dig into the
-//! arguments of `Some` to know whether some new value is covered. So we compute
-//! `U([[true, _]], [false, 0])`.
+//! For example, if `P` is:
+//! [
+//! [Some(true), _],
+//! [None, 0],
+//! ]
+//! and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only
+//! matches values that row 2 doesn't. For row 1 however, we need to dig into the
+//! arguments of `Some` to know whether some new value is covered. So we compute
+//! `U([[true, _]], [false, 0])`.
//!
-//! - If `p_1 == _`, then we look at the list of constructors that appear in the first
-//! component of the rows of `P`:
-//! + If there are some constructors that aren't present, then we might think that the
-//! wildcard `_` is useful, since it covers those constructors that weren't covered
-//! before.
-//! That's almost correct, but only works if there were no wildcards in those first
-//! components. So we need to check that `p` is useful with respect to the rows that
-//! start with a wildcard, if there are any. This is where `D` comes in:
-//! `U(P, p) := U(D(P), D(p))`
+//! - If `p_1 == _`, then we look at the list of constructors that appear in the first
+//! component of the rows of `P`:
+//! + If there are some constructors that aren't present, then we might think that the
+//! wildcard `_` is useful, since it covers those constructors that weren't covered
+//! before.
+//! That's almost correct, but only works if there were no wildcards in those first
+//! components. So we need to check that `p` is useful with respect to the rows that
+//! start with a wildcard, if there are any. This is where `D` comes in:
+//! `U(P, p) := U(D(P), D(p))`
//!
-//! For example, if `P` is:
-//! [
-//! [_, true, _],
-//! [None, false, 1],
-//! ]
-//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we
-//! only had row 2, we'd know that `p` is useful. However row 1 starts with a
-//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
+//! For example, if `P` is:
+//! [
+//! [_, true, _],
+//! [None, false, 1],
+//! ]
+//! and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we
+//! only had row 2, we'd know that `p` is useful. However row 1 starts with a
+//! wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
//!
-//! + Otherwise, all possible constructors (for the relevant type) are present. In this
-//! case we must check whether the wildcard pattern covers any unmatched value. For
-//! that, we can think of the `_` pattern as a big OR-pattern that covers all
-//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for
-//! example. The wildcard pattern is useful in this case if it is useful when
-//! specialized to one of the possible constructors. So we compute:
-//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
+//! + Otherwise, all possible constructors (for the relevant type) are present. In this
+//! case we must check whether the wildcard pattern covers any unmatched value. For
+//! that, we can think of the `_` pattern as a big OR-pattern that covers all
+//! possible constructors. For `Option`, that would mean `_ = None | Some(_)` for
+//! example. The wildcard pattern is useful in this case if it is useful when
+//! specialized to one of the possible constructors. So we compute:
+//! `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
//!
-//! For example, if `P` is:
-//! [
-//! [Some(true), _],
-//! [None, false],
-//! ]
-//! and `p` is [_, false], both `None` and `Some` constructors appear in the first
-//! components of `P`. We will therefore try popping both constructors in turn: we
-//! compute U([[true, _]], [_, false]) for the `Some` constructor, and U([[false]],
-//! [false]) for the `None` constructor. The first case returns true, so we know that
-//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched
-//! before.
+//! For example, if `P` is:
+//! [
+//! [Some(true), _],
+//! [None, false],
+//! ]
+//! and `p` is [_, false], both `None` and `Some` constructors appear in the first
+//! components of `P`. We will therefore try popping both constructors in turn: we
+//! compute `U([[true, _]], [_, false])` for the `Some` constructor, and `U([[false]],
+//! [false])` for the `None` constructor. The first case returns true, so we know that
+//! `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched
+//! before.
//!
-//! - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately:
-//! `U(P, p) := U(P, (r_1, p_2, .., p_n))
-//! || U(P, (r_2, p_2, .., p_n))`
+//! - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately:
+//! `U(P, p) := U(P, (r_1, p_2, .., p_n))
+//! || U(P, (r_2, p_2, .., p_n))`
//!
//! Modifications to the algorithm
//! ------------------------------
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index fc9ffc3092447..16a118cb48c91 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -376,7 +376,14 @@ impl<'a> Parser<'a> {
/// let _ = vec![1, 2, 3].into_iter().collect::>>>();
/// ^^ help: remove extra angle brackets
/// ```
- pub(super) fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) {
+ ///
+ /// If `true` is returned, then trailing brackets were recovered, tokens were consumed
+ /// up until one of the tokens in 'end' was encountered, and an error was emitted.
+ pub(super) fn check_trailing_angle_brackets(
+ &mut self,
+ segment: &PathSegment,
+ end: &[&TokenKind],
+ ) -> bool {
// This function is intended to be invoked after parsing a path segment where there are two
// cases:
//
@@ -409,7 +416,7 @@ impl<'a> Parser<'a> {
parsed_angle_bracket_args,
);
if !parsed_angle_bracket_args {
- return;
+ return false;
}
// Keep the span at the start so we can highlight the sequence of `>` characters to be
@@ -447,18 +454,18 @@ impl<'a> Parser<'a> {
number_of_gt, number_of_shr,
);
if number_of_gt < 1 && number_of_shr < 1 {
- return;
+ return false;
}
// Finally, double check that we have our end token as otherwise this is the
// second case.
if self.look_ahead(position, |t| {
trace!("check_trailing_angle_brackets: t={:?}", t);
- *t == end
+ end.contains(&&t.kind)
}) {
// Eat from where we started until the end token so that parsing can continue
// as if we didn't have those extra angle brackets.
- self.eat_to_tokens(&[&end]);
+ self.eat_to_tokens(end);
let span = lo.until(self.token.span);
let total_num_of_gt = number_of_gt + number_of_shr * 2;
@@ -473,7 +480,9 @@ impl<'a> Parser<'a> {
Applicability::MachineApplicable,
)
.emit();
+ return true;
}
+ false
}
/// Check to see if a pair of chained operators looks like an attempt at chained comparison,
@@ -1415,7 +1424,7 @@ impl<'a> Parser<'a> {
if self.token != token::Lt {
err.span_suggestion(
pat.span,
- "if this was a parameter name, give it a type",
+ "if this is a parameter name, give it a type",
format!("{}: TypeName", ident),
Applicability::HasPlaceholders,
);
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index 2745b18a8cd51..fb38fdc26c782 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -867,7 +867,7 @@ impl<'a> Parser<'a> {
let fn_span_lo = self.token.span;
let segment = self.parse_path_segment(PathStyle::Expr)?;
- self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
+ self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]);
if self.check(&token::OpenDelim(token::Paren)) {
// Method call `expr.f()`
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 10df16964da08..fa6264c98e4f0 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -9,7 +9,7 @@ use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind,
use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind};
use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind};
use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData};
-use rustc_ast::ast::{FnHeader, ForeignItem, PathSegment, Visibility, VisibilityKind};
+use rustc_ast::ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, TokenKind};
@@ -1262,6 +1262,25 @@ impl<'a> Parser<'a> {
sp,
&format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)),
);
+
+ // Try to recover extra trailing angle brackets
+ let mut recovered = false;
+ if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind {
+ if let Some(last_segment) = segments.last() {
+ recovered = self.check_trailing_angle_brackets(
+ last_segment,
+ &[&token::Comma, &token::CloseDelim(token::Brace)],
+ );
+ if recovered {
+ // Handle a case like `Vec>,` where we can continue parsing fields
+ // after the comma
+ self.eat(&token::Comma);
+ // `check_trailing_angle_brackets` already emitted a nicer error
+ err.cancel();
+ }
+ }
+ }
+
if self.token.is_ident() {
// This is likely another field; emit the diagnostic and keep going
err.span_suggestion(
@@ -1271,6 +1290,14 @@ impl<'a> Parser<'a> {
Applicability::MachineApplicable,
);
err.emit();
+ recovered = true;
+ }
+
+ if recovered {
+ // Make sure an error was emitted (either by recovering an angle bracket,
+ // or by finding an identifier as the next token), since we're
+ // going to continue parsing
+ assert!(self.sess.span_diagnostic.has_errors());
} else {
return Err(err);
}
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index 5210614548da3..67e9b3af4a8cf 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -169,7 +169,7 @@ impl<'a> Parser<'a> {
// `PathStyle::Expr` is only provided at the root invocation and never in
// `parse_path_segment` to recurse and therefore can be checked to maintain
// this invariant.
- self.check_trailing_angle_brackets(&segment, token::ModSep);
+ self.check_trailing_angle_brackets(&segment, &[&token::ModSep]);
}
segments.push(segment);
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index 9337f241d7022..2ad7d09cbf415 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -881,8 +881,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
(default: no)"),
instrument_coverage: bool = (false, parse_bool, [TRACKED],
"instrument the generated code with LLVM code region counters to (in the \
- future) generate coverage reports (default: no; note, the compiler build \
- config must include `profiler = true`)"),
+ future) generate coverage reports; disables/overrides some optimization \
+ options (note, the compiler build config must include `profiler = true`) \
+ (default: no)"),
instrument_mcount: bool = (false, parse_bool, [TRACKED],
"insert function instrument code for mcount-based tracing (default: no)"),
keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
@@ -958,9 +959,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"print the LLVM optimization passes being run (default: no)"),
print_mono_items: Option = (None, parse_opt_string, [UNTRACKED],
"print the result of the monomorphization collection pass"),
- print_region_graph: bool = (false, parse_bool, [UNTRACKED],
- "prints region inference graph. \
- Use with RUST_REGION_GRAPH=help for more info (default: no)"),
print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
"print layout information for each type encountered (default: no)"),
profile: bool = (false, parse_bool, [TRACKED],
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 857734037afe7..1159269190224 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -242,6 +242,9 @@ symbols! {
core,
core_intrinsics,
count_code_region,
+ coverage_counter_add,
+ coverage_counter_subtract,
+ coverage_unreachable,
crate_id,
crate_in_paths,
crate_local,
diff --git a/src/librustc_target/spec/cloudabi_base.rs b/src/librustc_target/spec/cloudabi_base.rs
index 3659c9ecdfca6..39039435f5815 100644
--- a/src/librustc_target/spec/cloudabi_base.rs
+++ b/src/librustc_target/spec/cloudabi_base.rs
@@ -7,7 +7,6 @@ pub fn opts() -> TargetOptions {
vec![
"-Wl,-Bstatic".to_string(),
"-Wl,--no-dynamic-linker".to_string(),
- "-Wl,--eh-frame-hdr".to_string(),
"-Wl,--gc-sections".to_string(),
],
);
diff --git a/src/librustc_target/spec/fuchsia_base.rs b/src/librustc_target/spec/fuchsia_base.rs
index dd55788b664ea..6f432dc11718d 100644
--- a/src/librustc_target/spec/fuchsia_base.rs
+++ b/src/librustc_target/spec/fuchsia_base.rs
@@ -6,7 +6,6 @@ pub fn opts() -> TargetOptions {
LinkerFlavor::Lld(LldFlavor::Ld),
vec![
"--build-id".to_string(),
- "--eh-frame-hdr".to_string(),
"--hash-style=gnu".to_string(),
"-z".to_string(),
"max-page-size=4096".to_string(),
diff --git a/src/librustc_target/spec/linux_musl_base.rs b/src/librustc_target/spec/linux_musl_base.rs
index 0fdd876080677..b90e91d2901a8 100644
--- a/src/librustc_target/spec/linux_musl_base.rs
+++ b/src/librustc_target/spec/linux_musl_base.rs
@@ -1,15 +1,9 @@
use crate::spec::crt_objects::{self, CrtObjectsFallback};
-use crate::spec::{LinkerFlavor, TargetOptions};
+use crate::spec::TargetOptions;
pub fn opts() -> TargetOptions {
let mut base = super::linux_base::opts();
- // At least when this was tested, the linker would not add the
- // `GNU_EH_FRAME` program header to executables generated, which is required
- // when unwinding to locate the unwinding information. I'm not sure why this
- // argument is *not* necessary for normal builds, but it can't hurt!
- base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--eh-frame-hdr".to_string());
-
base.pre_link_objects_fallback = crt_objects::pre_musl_fallback();
base.post_link_objects_fallback = crt_objects::post_musl_fallback();
base.crt_objects_fallback = Some(CrtObjectsFallback::Musl);
diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs
index 0c74454d0c5fe..b3bda97c8a570 100644
--- a/src/librustc_target/spec/mipsel_sony_psp.rs
+++ b/src/librustc_target/spec/mipsel_sony_psp.rs
@@ -6,10 +6,7 @@ const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");
pub fn target() -> TargetResult {
let mut pre_link_args = LinkArgs::new();
- pre_link_args.insert(
- LinkerFlavor::Lld(LldFlavor::Ld),
- vec!["--eh-frame-hdr".to_string(), "--emit-relocs".to_string()],
- );
+ pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["--emit-relocs".to_string()]);
Ok(Target {
llvm_target: "mipsel-sony-psp".to_string(),
diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
index d01545619c8fa..3b5233a3e677d 100644
--- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
@@ -5,7 +5,6 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};
pub fn target() -> Result {
const PRE_LINK_ARGS: &[&str] = &[
"--as-needed",
- "--eh-frame-hdr",
"-z",
"noexecstack",
"-e",
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 1c0b22ca7370b..6205088adadb7 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -352,7 +352,17 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
return;
}
- "count_code_region" => (0, vec![tcx.types.u32], tcx.mk_unit()),
+ "count_code_region" => {
+ (0, vec![tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit())
+ }
+
+ "coverage_counter_add" | "coverage_counter_subtract" => (
+ 0,
+ vec![tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32],
+ tcx.mk_unit(),
+ ),
+
+ "coverage_unreachable" => (0, vec![tcx.types.u32, tcx.types.u32], tcx.mk_unit()),
ref other => {
struct_span_err!(
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index d972cf6db18cf..0b3386c05d54b 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -1281,11 +1281,84 @@ mod self_upper_keyword {}
#[doc(keyword = "static")]
//
-/// A place that is valid for the duration of a program.
+/// A static item is a value which is valid for the entire duration of your
+/// program (a `'static` lifetime).
///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// On the surface, `static` items seem very similar to [`const`]s: both contain
+/// a value, both require type annotations and both can only be initialized with
+/// constant functions and values. However, `static`s are notably different in
+/// that they represent a location in memory. That means that you can have
+/// references to `static` items and potentially even modify them, making them
+/// essentially global variables.
///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// Static items do not call [`drop`] at the end of the program.
+///
+/// There are two types of `static` items: those declared in association with
+/// the [`mut`] keyword and those without.
+///
+/// Static items cannot be moved:
+///
+/// ```rust,compile_fail,E0507
+/// static VEC: Vec = vec![];
+///
+/// fn move_vec(v: Vec) -> Vec {
+/// v
+/// }
+///
+/// // This line causes an error
+/// move_vec(VEC);
+/// ```
+///
+/// # Simple `static`s
+///
+/// Accessing non-[`mut`] `static` items is considered safe, but some
+/// restrictions apply. Most notably, the type of a `static` value needs to
+/// implement the [`Sync`] trait, ruling out interior mutability containers
+/// like [`RefCell`]. See the [Reference] for more information.
+///
+/// ```rust
+/// static FOO: [i32; 5] = [1, 2, 3, 4, 5];
+///
+/// let r1 = &FOO as *const _;
+/// let r2 = &FOO as *const _;
+/// // With a strictly read-only static, references will have the same adress
+/// assert_eq!(r1, r2);
+/// // A static item can be used just like a variable in many cases
+/// println!("{:?}", FOO);
+/// ```
+///
+/// # Mutable `static`s
+///
+/// If a `static` item is declared with the [`mut`] keyword, then it is allowed
+/// to be modified by the program. However, accessing mutable `static`s can
+/// cause undefined behavior in a number of ways, for example due to data races
+/// in a multithreaded context. As such, all accesses to mutable `static`s
+/// require an [`unsafe`] block.
+///
+/// Despite their unsafety, mutable `static`s are necessary in many contexts:
+/// they can be used to represent global state shared by the whole program or in
+/// [`extern`] blocks to bind to variables from C libraries.
+///
+/// In an [`extern`] block:
+///
+/// ```rust,no_run
+/// # #![allow(dead_code)]
+/// extern "C" {
+/// static mut ERROR_MESSAGE: *mut std::os::raw::c_char;
+/// }
+/// ```
+///
+/// Mutable `static`s, just like simple `static`s, have some restrictions that
+/// apply to them. See the [Reference] for more information.
+///
+/// [`const`]: keyword.const.html
+/// [`extern`]: keyword.extern.html
+/// [`mut`]: keyword.mut.html
+/// [`unsafe`]: keyword.unsafe.html
+/// [`drop`]: mem/fn.drop.html
+/// [`Sync`]: marker/trait.Sync.html
+/// [`RefCell`]: cell/struct.RefCell.html
+/// [Reference]: ../reference/items/static-items.html
mod static_keyword {}
#[doc(keyword = "struct")]
@@ -1463,9 +1536,44 @@ mod true_keyword {}
//
/// Define an alias for an existing type.
///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// The syntax is `type Name = ExistingType;`.
///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// # Examples
+///
+/// `type` does **not** create a new type:
+///
+/// ```rust
+/// type Meters = u32;
+/// type Kilograms = u32;
+///
+/// let m: Meters = 3;
+/// let k: Kilograms = 3;
+///
+/// assert_eq!(m, k);
+/// ```
+///
+/// In traits, `type` is used to declare an [associated type]:
+///
+/// ```rust
+/// trait Iterator {
+/// // associated type declaration
+/// type Item;
+/// fn next(&mut self) -> Option;
+/// }
+///
+/// struct Once(Option);
+///
+/// impl Iterator for Once {
+/// // associated type definition
+/// type Item = T;
+/// fn next(&mut self) -> Option {
+/// self.0.take()
+/// }
+/// }
+/// ```
+///
+/// [`trait`]: keyword.trait.html
+/// [associated type]: ../reference/items/associated-items.html#associated-types
mod type_keyword {}
#[doc(keyword = "unsafe")]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index ef699ede2a140..372038df54f2e 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -316,7 +316,7 @@
#![feature(toowned_clone_into)]
#![feature(total_cmp)]
#![feature(trace_macros)]
-#![feature(track_caller)]
+#![cfg_attr(bootstrap, feature(track_caller))]
#![feature(try_reserve)]
#![feature(unboxed_closures)]
#![feature(untagged_unions)]
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 640c9f3636d4b..193ab5b47ef13 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -61,6 +61,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound,
c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound,
c::ERROR_NO_DATA => return ErrorKind::BrokenPipe,
+ c::ERROR_INVALID_PARAMETER => return ErrorKind::InvalidInput,
c::ERROR_SEM_TIMEOUT
| c::WAIT_TIMEOUT
| c::ERROR_DRIVER_CANCEL_TIMEOUT
diff --git a/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff
index 8a079f0da4b01..af2899c887a94 100644
--- a/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff
+++ b/src/test/mir-opt/instrument_coverage/rustc.bar.InstrumentCoverage.diff
@@ -7,19 +7,31 @@
bb0: {
+ StorageLive(_1); // scope 0 at $DIR/instrument_coverage.rs:18:1: 20:2
-+ _1 = const std::intrinsics::count_code_region(const 0_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:1: 20:2
++ _1 = const std::intrinsics::count_code_region(const 0_u32, const 484_u32, const 513_u32) -> bb2; // scope 0 at $DIR/instrument_coverage.rs:18:1: 20:2
+ // ty::Const
-+ // + ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}
++ // + ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region}
+ // + val: Value(Scalar())
+ // mir::Constant
+ // + span: $DIR/instrument_coverage.rs:18:1: 18:1
-+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}, val: Value(Scalar()) }
++ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar()) }
+ // ty::Const
+ // + ty: u32
+ // + val: Value(Scalar(0x00000000))
+ // mir::Constant
+ // + span: $DIR/instrument_coverage.rs:18:1: 18:1
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) }
++ // ty::Const
++ // + ty: u32
++ // + val: Value(Scalar(0x000001e4))
++ // mir::Constant
++ // + span: $DIR/instrument_coverage.rs:18:1: 18:1
++ // + literal: Const { ty: u32, val: Value(Scalar(0x000001e4)) }
++ // ty::Const
++ // + ty: u32
++ // + val: Value(Scalar(0x00000201))
++ // mir::Constant
++ // + span: $DIR/instrument_coverage.rs:18:1: 18:1
++ // + literal: Const { ty: u32, val: Value(Scalar(0x00000201)) }
+ }
+
+ bb1 (cleanup): {
diff --git a/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff
index 3c2ec1dc06b70..4a300230f8a97 100644
--- a/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff
+++ b/src/test/mir-opt/instrument_coverage/rustc.main.InstrumentCoverage.diff
@@ -11,19 +11,31 @@
bb0: {
- falseUnwind -> [real: bb1, cleanup: bb2]; // scope 0 at $DIR/instrument_coverage.rs:10:5: 14:6
+ StorageLive(_4); // scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2
-+ _4 = const std::intrinsics::count_code_region(const 0_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2
++ _4 = const std::intrinsics::count_code_region(const 0_u32, const 387_u32, const 465_u32) -> bb7; // scope 0 at $DIR/instrument_coverage.rs:9:1: 15:2
+ // ty::Const
-+ // + ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}
++ // + ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region}
+ // + val: Value(Scalar())
+ // mir::Constant
+ // + span: $DIR/instrument_coverage.rs:9:1: 9:1
-+ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) {std::intrinsics::count_code_region}, val: Value(Scalar()) }
++ // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32, u32, u32) {std::intrinsics::count_code_region}, val: Value(Scalar()) }
+ // ty::Const
+ // + ty: u32
+ // + val: Value(Scalar(0x00000000))
+ // mir::Constant
+ // + span: $DIR/instrument_coverage.rs:9:1: 9:1
+ // + literal: Const { ty: u32, val: Value(Scalar(0x00000000)) }
++ // ty::Const
++ // + ty: u32
++ // + val: Value(Scalar(0x00000183))
++ // mir::Constant
++ // + span: $DIR/instrument_coverage.rs:9:1: 9:1
++ // + literal: Const { ty: u32, val: Value(Scalar(0x00000183)) }
++ // ty::Const
++ // + ty: u32
++ // + val: Value(Scalar(0x000001d1))
++ // mir::Constant
++ // + span: $DIR/instrument_coverage.rs:9:1: 9:1
++ // + literal: Const { ty: u32, val: Value(Scalar(0x000001d1)) }
}
bb1: {
diff --git a/src/test/ui/anon-params/anon-params-denied-2018.stderr b/src/test/ui/anon-params/anon-params-denied-2018.stderr
index e7a806a846820..840294db0830a 100644
--- a/src/test/ui/anon-params/anon-params-denied-2018.stderr
+++ b/src/test/ui/anon-params/anon-params-denied-2018.stderr
@@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name
|
LL | fn foo(self: i32);
| ^^^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
|
LL | fn foo(i32: TypeName);
| ^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ help: if this is a `self` type, give it a parameter name
|
LL | fn bar_with_default_impl(self: String, String) {}
| ^^^^^^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
|
LL | fn bar_with_default_impl(String: TypeName, String) {}
| ^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL | fn bar_with_default_impl(String, String) {}
| ^ expected one of `:`, `@`, or `|`
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
|
LL | fn bar_with_default_impl(String, String: TypeName) {}
| ^^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL | fn baz(a:usize, b, c: usize) -> usize {
| ^ expected one of `:`, `@`, or `|`
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
|
LL | fn baz(a:usize, b: TypeName, c: usize) -> usize {
| ^^^^^^^^^^^
diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs
index 8cff16aa75f69..9931697e4129c 100644
--- a/src/test/ui/asm/sym.rs
+++ b/src/test/ui/asm/sym.rs
@@ -3,7 +3,7 @@
// only-linux
// run-pass
-#![feature(asm, track_caller, thread_local)]
+#![feature(asm, thread_local)]
extern "C" fn f1() -> i32 {
111
diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs
deleted file mode 100644
index 5865cf0a4f754..0000000000000
--- a/src/test/ui/feature-gates/feature-gate-track_caller.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#[track_caller]
-fn f() {}
-//~^^ ERROR the `#[track_caller]` attribute is an experimental feature
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr
deleted file mode 100644
index 8ceab501617ee..0000000000000
--- a/src/test/ui/feature-gates/feature-gate-track_caller.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: the `#[track_caller]` attribute is an experimental feature
- --> $DIR/feature-gate-track_caller.rs:1:1
- |
-LL | #[track_caller]
- | ^^^^^^^^^^^^^^^
- |
- = note: see issue #47809 for more information
- = help: add `#![feature(track_caller)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs
new file mode 100644
index 0000000000000..4f90bd98c63e5
--- /dev/null
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs
@@ -0,0 +1,50 @@
+#![allow(dead_code)]
+
+#![forbid(non_camel_case_types)]
+#![feature(non_ascii_idents)]
+
+// Some scripts (e.g., hiragana) don't have a concept of
+// upper/lowercase
+
+// 1. non_camel_case_types
+
+// Can start with non-lowercase letter
+struct Θχ;
+struct ヒa;
+
+struct χa;
+//~^ ERROR type `χa` should have an upper camel case name
+
+// If there's already leading or trailing underscores, they get trimmed before checking.
+// This is fine:
+struct _ヒb;
+
+// This is not:
+struct __χa;
+//~^ ERROR type `__χa` should have an upper camel case name
+
+// Besides this, we cannot have two continous underscores in the middle.
+
+struct 对__否;
+//~^ ERROR type `对__否` should have an upper camel case name
+
+struct ヒ__χ;
+//~^ ERROR type `ヒ__χ` should have an upper camel case name
+
+// also cannot have lowercase letter next to a underscore.
+// so this triggers the lint:
+
+struct Hello_你好;
+//~^ ERROR type `Hello_你好` should have an upper camel case name
+
+struct Hello_World;
+//~^ ERROR type `Hello_World` should have an upper camel case name
+
+struct 你_ӟ;
+//~^ ERROR type `你_ӟ` should have an upper camel case name
+
+// and this is ok:
+
+struct 你_好;
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr b/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr
new file mode 100644
index 0000000000000..371002656591c
--- /dev/null
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode-1.stderr
@@ -0,0 +1,50 @@
+error: type `χa` should have an upper camel case name
+ --> $DIR/lint-nonstandard-style-unicode-1.rs:15:8
+ |
+LL | struct χa;
+ | ^^ help: convert the identifier to upper camel case: `Χa`
+ |
+note: the lint level is defined here
+ --> $DIR/lint-nonstandard-style-unicode-1.rs:3:11
+ |
+LL | #![forbid(non_camel_case_types)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: type `__χa` should have an upper camel case name
+ --> $DIR/lint-nonstandard-style-unicode-1.rs:23:8
+ |
+LL | struct __χa;
+ | ^^^^ help: convert the identifier to upper camel case: `Χa`
+
+error: type `对__否` should have an upper camel case name
+ --> $DIR/lint-nonstandard-style-unicode-1.rs:28:8
+ |
+LL | struct 对__否;
+ | ^^^^^^ help: convert the identifier to upper camel case: `对_否`
+
+error: type `ヒ__χ` should have an upper camel case name
+ --> $DIR/lint-nonstandard-style-unicode-1.rs:31:8
+ |
+LL | struct ヒ__χ;
+ | ^^^^^ help: convert the identifier to upper camel case: `ヒΧ`
+
+error: type `Hello_你好` should have an upper camel case name
+ --> $DIR/lint-nonstandard-style-unicode-1.rs:37:8
+ |
+LL | struct Hello_你好;
+ | ^^^^^^^^^^ help: convert the identifier to upper camel case: `Hello你好`
+
+error: type `Hello_World` should have an upper camel case name
+ --> $DIR/lint-nonstandard-style-unicode-1.rs:40:8
+ |
+LL | struct Hello_World;
+ | ^^^^^^^^^^^ help: convert the identifier to upper camel case: `HelloWorld`
+
+error: type `你_ӟ` should have an upper camel case name
+ --> $DIR/lint-nonstandard-style-unicode-1.rs:43:8
+ |
+LL | struct 你_ӟ;
+ | ^^^^ help: convert the identifier to upper camel case: `你Ӟ`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs
new file mode 100644
index 0000000000000..813e0ea5c5708
--- /dev/null
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode-2.rs
@@ -0,0 +1,30 @@
+#![allow(dead_code)]
+
+#![forbid(non_snake_case)]
+#![feature(non_ascii_idents)]
+
+// Some scripts (e.g., hiragana) don't have a concept of
+// upper/lowercase
+
+// 2. non_snake_case
+
+// Can only use non-uppercase letters.
+// So this works:
+
+fn 编程() {}
+
+// but this doesn't:
+
+fn Ц() {}
+//~^ ERROR function `Ц` should have a snake case name
+
+// besides this, you cannot use continous underscores in the middle
+
+fn 分__隔() {}
+//~^ ERROR function `分__隔` should have a snake case name
+
+// but you can use them both at the beginning and at the end.
+
+fn _______不_连_续_的_存_在_______() {}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr b/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr
new file mode 100644
index 0000000000000..0b309e315a411
--- /dev/null
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode-2.stderr
@@ -0,0 +1,20 @@
+error: function `Ц` should have a snake case name
+ --> $DIR/lint-nonstandard-style-unicode-2.rs:18:4
+ |
+LL | fn Ц() {}
+ | ^ help: convert the identifier to snake case: `ц`
+ |
+note: the lint level is defined here
+ --> $DIR/lint-nonstandard-style-unicode-2.rs:3:11
+ |
+LL | #![forbid(non_snake_case)]
+ | ^^^^^^^^^^^^^^
+
+error: function `分__隔` should have a snake case name
+ --> $DIR/lint-nonstandard-style-unicode-2.rs:23:4
+ |
+LL | fn 分__隔() {}
+ | ^^^^^^ help: convert the identifier to snake case: `分_隔`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs
new file mode 100644
index 0000000000000..b17c2de39a0c0
--- /dev/null
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode-3.rs
@@ -0,0 +1,25 @@
+#![allow(dead_code)]
+
+#![forbid(non_upper_case_globals)]
+#![feature(non_ascii_idents)]
+
+// Some scripts (e.g., hiragana) don't have a concept of
+// upper/lowercase
+
+// 3. non_upper_case_globals
+
+// Can only use non-lowercase letters.
+// So this works:
+
+static ラ: usize = 0;
+
+// but this doesn't:
+
+static τεχ: f32 = 3.14159265;
+//~^ ERROR static variable `τεχ` should have an upper case name
+
+// This has no limit at all on underscore usages.
+
+static __密__封__线__内__禁__止__答__题__: bool = true;
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr b/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr
new file mode 100644
index 0000000000000..44bd5ad55ff5c
--- /dev/null
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode-3.stderr
@@ -0,0 +1,14 @@
+error: static variable `τεχ` should have an upper case name
+ --> $DIR/lint-nonstandard-style-unicode-3.rs:18:8
+ |
+LL | static τεχ: f32 = 3.14159265;
+ | ^^^ help: convert the identifier to upper case: `ΤΕΧ`
+ |
+note: the lint level is defined here
+ --> $DIR/lint-nonstandard-style-unicode-3.rs:3:11
+ |
+LL | #![forbid(non_upper_case_globals)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode.rs b/src/test/ui/lint/lint-nonstandard-style-unicode.rs
deleted file mode 100644
index 9f16cb20fb32c..0000000000000
--- a/src/test/ui/lint/lint-nonstandard-style-unicode.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// check-pass
-
-#![allow(dead_code)]
-
-#![forbid(non_camel_case_types)]
-#![forbid(non_upper_case_globals)]
-#![feature(non_ascii_idents)]
-
-// Some scripts (e.g., hiragana) don't have a concept of
-// upper/lowercase
-
-struct ヒ;
-
-static ラ: usize = 0;
-
-pub fn main() {}
diff --git a/src/test/ui/macros/issue-68060.rs b/src/test/ui/macros/issue-68060.rs
index bc70f8ffec2b2..8772e98b6e9bb 100644
--- a/src/test/ui/macros/issue-68060.rs
+++ b/src/test/ui/macros/issue-68060.rs
@@ -1,5 +1,3 @@
-#![feature(track_caller)]
-
fn main() {
(0..)
.map(
diff --git a/src/test/ui/macros/issue-68060.stderr b/src/test/ui/macros/issue-68060.stderr
index 22187c4a4098a..b9b2f946c5967 100644
--- a/src/test/ui/macros/issue-68060.stderr
+++ b/src/test/ui/macros/issue-68060.stderr
@@ -1,5 +1,5 @@
error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
- --> $DIR/issue-68060.rs:6:13
+ --> $DIR/issue-68060.rs:4:13
|
LL | #[target_feature(enable = "")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -11,13 +11,13 @@ LL | |_| (),
= help: add `#![feature(target_feature_11)]` to the crate attributes to enable
error: the feature named `` is not valid for this target
- --> $DIR/issue-68060.rs:6:30
+ --> $DIR/issue-68060.rs:4:30
|
LL | #[target_feature(enable = "")]
| ^^^^^^^^^^^ `` is not valid for this target
error[E0737]: `#[track_caller]` requires Rust ABI
- --> $DIR/issue-68060.rs:9:13
+ --> $DIR/issue-68060.rs:7:13
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs
index e6d0c94a02fac..825a11972aeeb 100644
--- a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs
+++ b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs
@@ -9,7 +9,6 @@
// merged.
#![feature(test, stmt_expr_attributes)]
-#![feature(track_caller)]
#![deny(overflowing_literals)]
extern crate test;
diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs
index 6f19ee9c7dc0d..5c4272504e061 100644
--- a/src/test/ui/parser/inverted-parameters.rs
+++ b/src/test/ui/parser/inverted-parameters.rs
@@ -20,7 +20,7 @@ fn pattern((i32, i32) (a, b)) {}
fn fizz(i32) {}
//~^ ERROR expected one of `:`, `@`
-//~| HELP if this was a parameter name, give it a type
+//~| HELP if this is a parameter name, give it a type
//~| HELP if this is a `self` type, give it a parameter name
//~| HELP if this is a type, explicitly ignore the parameter name
diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr
index 043ff65f74e1a..ae180af93e373 100644
--- a/src/test/ui/parser/inverted-parameters.stderr
+++ b/src/test/ui/parser/inverted-parameters.stderr
@@ -39,7 +39,7 @@ help: if this is a `self` type, give it a parameter name
|
LL | fn fizz(self: i32) {}
| ^^^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
|
LL | fn fizz(i32: TypeName) {}
| ^^^^^^^^^^^^^
diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr
index 9f138bf84ce19..bc3329dcbc23d 100644
--- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr
+++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr
@@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name
|
LL | fn foo(self: x) {
| ^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
|
LL | fn foo(x: TypeName) {
| ^^^^^^^^^^^
diff --git a/src/test/ui/parser/recover-field-extra-angle-brackets.rs b/src/test/ui/parser/recover-field-extra-angle-brackets.rs
new file mode 100644
index 0000000000000..5e0e00bcb5e8d
--- /dev/null
+++ b/src/test/ui/parser/recover-field-extra-angle-brackets.rs
@@ -0,0 +1,14 @@
+// Tests that we recover from extra trailing angle brackets
+// in a struct field
+
+struct BadStruct {
+ first: Vec>, //~ ERROR unmatched angle bracket
+ second: bool
+}
+
+fn bar(val: BadStruct) {
+ val.first;
+ val.second;
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/recover-field-extra-angle-brackets.stderr b/src/test/ui/parser/recover-field-extra-angle-brackets.stderr
new file mode 100644
index 0000000000000..318e55f6e99ac
--- /dev/null
+++ b/src/test/ui/parser/recover-field-extra-angle-brackets.stderr
@@ -0,0 +1,8 @@
+error: unmatched angle bracket
+ --> $DIR/recover-field-extra-angle-brackets.rs:5:19
+ |
+LL | first: Vec>,
+ | ^ help: remove extra angle bracket
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2091-track-caller/call-chain.rs b/src/test/ui/rfc-2091-track-caller/call-chain.rs
index 3f1c8f7abe8b8..fefb84de729fe 100644
--- a/src/test/ui/rfc-2091-track-caller/call-chain.rs
+++ b/src/test/ui/rfc-2091-track-caller/call-chain.rs
@@ -1,7 +1,5 @@
// run-pass
-#![feature(track_caller)]
-
use std::panic::Location;
struct Foo;
diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
index edf9ba2c41a15..05240908917bc 100644
--- a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
+++ b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs
@@ -6,7 +6,7 @@
// run-pass
// compile-flags: -Z unleash-the-miri-inside-of-you
-#![feature(core_intrinsics, const_caller_location, track_caller, const_fn)]
+#![feature(core_intrinsics, const_caller_location, const_fn)]
type L = &'static std::panic::Location<'static>;
diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs
index 090e912c1d0ba..f244b74e391ff 100644
--- a/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs
+++ b/src/test/ui/rfc-2091-track-caller/caller-location-intrinsic.rs
@@ -1,7 +1,5 @@
// run-pass
-#![feature(track_caller)]
-
#[inline(never)]
#[track_caller]
fn codegen_caller_loc() -> &'static core::panic::Location<'static> {
@@ -15,13 +13,13 @@ macro_rules! caller_location_from_macro {
fn main() {
let loc = codegen_caller_loc();
assert_eq!(loc.file(), file!());
- assert_eq!(loc.line(), 16);
+ assert_eq!(loc.line(), 14);
assert_eq!(loc.column(), 15);
// `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
// i.e. point to where the macro was invoked, instead of the macro itself.
let loc2 = caller_location_from_macro!();
assert_eq!(loc2.file(), file!());
- assert_eq!(loc2.line(), 23);
+ assert_eq!(loc2.line(), 21);
assert_eq!(loc2.column(), 16);
}
diff --git a/src/test/ui/rfc-2091-track-caller/const-caller-location.rs b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs
index 0614c52c66036..8030a4d967a67 100644
--- a/src/test/ui/rfc-2091-track-caller/const-caller-location.rs
+++ b/src/test/ui/rfc-2091-track-caller/const-caller-location.rs
@@ -1,6 +1,6 @@
// run-pass
-#![feature(const_fn, track_caller)]
+#![feature(const_caller_location, const_fn)]
use std::panic::Location;
diff --git a/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs b/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
index 1fb75ef35ffc1..6681119557d79 100644
--- a/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
+++ b/src/test/ui/rfc-2091-track-caller/diverging-caller-location.rs
@@ -6,8 +6,6 @@
//! we don't inspect the location returned -- it would be difficult to distinguish between the
//! explicit panic and a failed assertion. That it compiles and runs is enough for this one.
-#![feature(track_caller)]
-
#[track_caller]
fn doesnt_return() -> ! {
let _location = core::panic::Location::caller();
diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
index d6560231871c9..6f4290e2a5ee9 100644
--- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs
@@ -1,5 +1,3 @@
-#![feature(track_caller)]
-
#[track_caller(1)]
fn f() {}
//~^^ ERROR malformed `track_caller` attribute input
diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
index 8906fa59506a7..e7ddf8df4ab53 100644
--- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr
@@ -1,5 +1,5 @@
error: malformed `track_caller` attribute input
- --> $DIR/error-odd-syntax.rs:3:1
+ --> $DIR/error-odd-syntax.rs:1:1
|
LL | #[track_caller(1)]
| ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]`
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
index 1145f7786c78b..074e1ceb791ce 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs
@@ -1,5 +1,3 @@
-#![feature(track_caller)]
-
#[track_caller]
extern "C" fn f() {}
//~^^ ERROR `#[track_caller]` requires Rust ABI
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
index e08c52fabd6b7..bcc0c8170e655 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
+++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr
@@ -1,11 +1,11 @@
error[E0737]: `#[track_caller]` requires Rust ABI
- --> $DIR/error-with-invalid-abi.rs:3:1
+ --> $DIR/error-with-invalid-abi.rs:1:1
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
error[E0737]: `#[track_caller]` requires Rust ABI
- --> $DIR/error-with-invalid-abi.rs:8:5
+ --> $DIR/error-with-invalid-abi.rs:6:5
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
index f457384833335..2b110c9a32515 100644
--- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
+++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs
@@ -1,4 +1,4 @@
-#![feature(naked_functions, track_caller)]
+#![feature(naked_functions)]
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
#[naked]
diff --git a/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
index 76e62b89ab818..74217f47084a3 100644
--- a/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
+++ b/src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs
@@ -1,7 +1,5 @@
// run-pass
-#![feature(track_caller)]
-
macro_rules! caller_location_from_macro {
() => (core::panic::Location::caller());
}
@@ -9,13 +7,13 @@ macro_rules! caller_location_from_macro {
fn main() {
let loc = core::panic::Location::caller();
assert_eq!(loc.file(), file!());
- assert_eq!(loc.line(), 10);
+ assert_eq!(loc.line(), 8);
assert_eq!(loc.column(), 15);
// `Location::caller()` in a macro should behave similarly to `file!` and `line!`,
// i.e. point to where the macro was invoked, instead of the macro itself.
let loc2 = caller_location_from_macro!();
assert_eq!(loc2.file(), file!());
- assert_eq!(loc2.line(), 17);
+ assert_eq!(loc2.line(), 15);
assert_eq!(loc2.column(), 16);
}
diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
index 0fd59b4bf4918..bc0ca9552806f 100644
--- a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
+++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs
@@ -1,5 +1,3 @@
-#![feature(track_caller)]
-
#[track_caller]
struct S;
//~^^ ERROR attribute should be applied to function
diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
index c2fb8fa1eb6ca..6666dcfa6e599 100644
--- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
+++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr
@@ -1,5 +1,5 @@
error[E0739]: attribute should be applied to function
- --> $DIR/only-for-fns.rs:3:1
+ --> $DIR/only-for-fns.rs:1:1
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs
index eef83b3d68f97..ada150b25cf2c 100644
--- a/src/test/ui/rfc-2091-track-caller/pass.rs
+++ b/src/test/ui/rfc-2091-track-caller/pass.rs
@@ -1,6 +1,4 @@
// run-pass
-#![feature(track_caller)]
-
#[track_caller]
fn f() {}
diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
index 76a380ed3e30d..efcc1f6942de1 100644
--- a/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
+++ b/src/test/ui/rfc-2091-track-caller/track-caller-attribute.rs
@@ -1,7 +1,5 @@
// run-pass
-#![feature(track_caller)]
-
use std::panic::Location;
#[track_caller]
@@ -20,21 +18,21 @@ fn nested_tracked() -> &'static Location<'static> {
fn main() {
let location = Location::caller();
assert_eq!(location.file(), file!());
- assert_eq!(location.line(), 21);
+ assert_eq!(location.line(), 19);
assert_eq!(location.column(), 20);
let tracked = tracked();
assert_eq!(tracked.file(), file!());
- assert_eq!(tracked.line(), 26);
+ assert_eq!(tracked.line(), 24);
assert_eq!(tracked.column(), 19);
let nested = nested_intrinsic();
assert_eq!(nested.file(), file!());
- assert_eq!(nested.line(), 13);
+ assert_eq!(nested.line(), 11);
assert_eq!(nested.column(), 5);
let contained = nested_tracked();
assert_eq!(contained.file(), file!());
- assert_eq!(contained.line(), 17);
+ assert_eq!(contained.line(), 15);
assert_eq!(contained.column(), 5);
}
diff --git a/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs
index 23c17d743c43c..5115f687c2632 100644
--- a/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs
+++ b/src/test/ui/rfc-2091-track-caller/track-caller-ffi.rs
@@ -1,7 +1,5 @@
// run-pass
-#![feature(track_caller)]
-
use std::panic::Location;
extern "Rust" {
@@ -30,21 +28,21 @@ mod provides {
fn main() {
let location = Location::caller();
assert_eq!(location.file(), file!());
- assert_eq!(location.line(), 31);
+ assert_eq!(location.line(), 29);
assert_eq!(location.column(), 20);
let tracked = unsafe { rust_track_caller_ffi_test_tracked() };
assert_eq!(tracked.file(), file!());
- assert_eq!(tracked.line(), 36);
+ assert_eq!(tracked.line(), 34);
assert_eq!(tracked.column(), 28);
let untracked = unsafe { rust_track_caller_ffi_test_untracked() };
assert_eq!(untracked.file(), file!());
- assert_eq!(untracked.line(), 26);
+ assert_eq!(untracked.line(), 24);
assert_eq!(untracked.column(), 9);
let contained = rust_track_caller_ffi_test_nested_tracked();
assert_eq!(contained.file(), file!());
- assert_eq!(contained.line(), 14);
+ assert_eq!(contained.line(), 12);
assert_eq!(contained.column(), 14);
}
diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
index b17c1efb3d38c..5fcfea96d547a 100644
--- a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
+++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
@@ -1,7 +1,5 @@
// run-pass
-#![feature(track_caller)]
-
fn pass_to_ptr_call(f: fn(T), x: T) {
f(x);
}
diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
index 8ee4d4fa16871..4415d850c241c 100644
--- a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
+++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
@@ -1,7 +1,5 @@
// run-pass
-#![feature(track_caller)]
-
fn ptr_call(f: fn()) {
f();
}
diff --git a/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
index 0a5f92bb635e5..4db4c29e53d58 100644
--- a/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
+++ b/src/test/ui/rfc-2091-track-caller/tracked-trait-impls.rs
@@ -1,7 +1,5 @@
// run-pass
-#![feature(track_caller)]
-
macro_rules! assert_expansion_site_is_tracked {
() => {{
let location = std::panic::Location::caller();
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
index 1e51567a9b1c4..5516d4a4c1c1c 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
@@ -9,7 +9,7 @@ help: if this is a `self` type, give it a parameter name
|
LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); }
| ^^^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
|
LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); }
| ^^^^^^^^^^^^^
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
index 116f5ddd5b4b2..40c3219bf27b0 100644
--- a/src/test/ui/span/issue-34264.stderr
+++ b/src/test/ui/span/issue-34264.stderr
@@ -21,7 +21,7 @@ LL | fn foo(Option, String) {}
| ^ expected one of `:`, `@`, or `|`
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
|
LL | fn foo(Option, String: TypeName) {}
| ^^^^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ help: if this is a `self` type, give it a parameter name
|
LL | fn bar(self: x, y: usize) {}
| ^^^^^^^
-help: if this was a parameter name, give it a type
+help: if this is a parameter name, give it a type
|
LL | fn bar(x: TypeName, y: usize) {}
| ^^^^^^^^^^^