diff --git a/Cargo.lock b/Cargo.lock index bc11ff2bbbcc7..95efd04d6f84f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,6 +36,14 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "annotate-snippets" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -2246,7 +2254,7 @@ dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 1.2.0", + "rustfmt-nightly 1.2.1", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3038,8 +3046,9 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.2.0" +version = "1.2.1" dependencies = [ + "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3049,6 +3058,7 @@ dependencies = [ "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3061,7 +3071,7 @@ dependencies = [ "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3987,6 +3997,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4c682378117e4186a492b2252b9537990e1617f44aed9788b9a1149de45477" +"checksum annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e8bcdcd5b291ce85a78f2b9d082a8de9676c12b1840d386d67bc5eea6f9d2b4e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1025aeae2b664ca0ea726a89d574fe8f4e77dd712d443236ad1de00379450cf6" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c552f607960b4..a443b7b5863e5 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1268,11 +1268,11 @@ impl Step for Compiletest { builder.add_rust_test_threads(&mut cmd); if builder.config.sanitizers { - cmd.env("SANITIZER_SUPPORT", "1"); + cmd.env("RUSTC_SANITIZER_SUPPORT", "1"); } if builder.config.profiler { - cmd.env("PROFILER_SUPPORT", "1"); + cmd.env("RUSTC_PROFILER_SUPPORT", "1"); } cmd.env("RUST_TEST_TMPDIR", builder.out.join("tmp")); diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index cccd51b577930..9f9146a1523b3 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -980,6 +980,16 @@ impl<I> DoubleEndedIterator for Enumerate<I> where }) } + #[inline] + fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> { + self.iter.nth_back(n).map(|a| { + let len = self.iter.len(); + // Can safely add, `ExactSizeIterator` promises that the number of + // elements fits into a `usize`. + (self.count + len, a) + }) + } + #[inline] fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> @@ -1789,6 +1799,17 @@ impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator { } } + #[inline] + default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> { + if self.done { + None + } else { + let nth = self.iter.nth_back(n); + self.done = nth.is_none(); + nth + } + } + #[inline] default fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> @@ -1877,6 +1898,11 @@ impl<I> DoubleEndedIterator for Fuse<I> self.iter.next_back() } + #[inline] + fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> { + self.iter.nth_back(n) + } + #[inline] fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 122ef9c79c276..dc1194d1b2d31 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -838,7 +838,7 @@ impl<T> [T] { } /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the - /// beginning of the slice. + /// end of the slice. /// /// The chunks are slices and do not overlap. If `chunk_size` does not divide the length of the /// slice, then the last up to `chunk_size-1` elements will be omitted and can be retrieved @@ -849,7 +849,7 @@ impl<T> [T] { /// /// See [`rchunks`] for a variant of this iterator that also returns the remainder as a smaller /// chunk, and [`chunks_exact`] for the same iterator but starting at the beginning of the - /// slice of the slice. + /// slice. /// /// # Panics /// @@ -890,7 +890,7 @@ impl<T> [T] { /// /// See [`rchunks_mut`] for a variant of this iterator that also returns the remainder as a /// smaller chunk, and [`chunks_exact_mut`] for the same iterator but starting at the beginning - /// of the slice of the slice. + /// of the slice. /// /// # Panics /// diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 8d28be621d647..24c008460447e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -795,6 +795,11 @@ impl DoubleEndedIterator for Bytes<'_> { self.0.next_back() } + #[inline] + fn nth_back(&mut self, n: usize) -> Option<Self::Item> { + self.0.nth_back(n) + } + #[inline] fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index d5b581d336d2f..5247331fba24f 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -389,6 +389,24 @@ fn test_iterator_enumerate_nth() { assert_eq!(i, 3); } +#[test] +fn test_iterator_enumerate_nth_back() { + let xs = [0, 1, 2, 3, 4, 5]; + let mut it = xs.iter().enumerate(); + while let Some((i, &x)) = it.nth_back(0) { + assert_eq!(i, x); + } + + let mut it = xs.iter().enumerate(); + while let Some((i, &x)) = it.nth_back(1) { + assert_eq!(i, x); + } + + let (i, &x) = xs.iter().enumerate().nth_back(3).unwrap(); + assert_eq!(i, x); + assert_eq!(i, 2); +} + #[test] fn test_iterator_enumerate_count() { let xs = [0, 1, 2, 3, 4, 5]; diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index c2265eeb30d74..007eaef74a7ad 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -57,6 +57,14 @@ impl<'a> FnKind<'a> { FnKind::Closure(attrs) => attrs, } } + + pub fn header(&self) -> Option<FnHeader> { + match *self { + FnKind::ItemFn(_, _, header, _, _) => Some(header), + FnKind::Method(_, sig, _, _) => Some(sig.header), + FnKind::Closure(_) => None, + } + } } /// Specifies what nested things a visitor wants to visit. The most diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 1114ef52bbc0c..f50037a746d97 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -175,27 +175,15 @@ impl<'a> FnLikeNode<'a> { } pub fn constness(self) -> ast::Constness { - match self.kind() { - FnKind::ItemFn(_, _, header, ..) => header.constness, - FnKind::Method(_, m, ..) => m.header.constness, - _ => ast::Constness::NotConst - } + self.kind().header().map_or(ast::Constness::NotConst, |header| header.constness) } pub fn asyncness(self) -> ast::IsAsync { - match self.kind() { - FnKind::ItemFn(_, _, header, ..) => header.asyncness, - FnKind::Method(_, m, ..) => m.header.asyncness, - _ => ast::IsAsync::NotAsync - } + self.kind().header().map_or(ast::IsAsync::NotAsync, |header| header.asyncness) } pub fn unsafety(self) -> ast::Unsafety { - match self.kind() { - FnKind::ItemFn(_, _, header, ..) => header.unsafety, - FnKind::Method(_, m, ..) => m.header.unsafety, - _ => ast::Unsafety::Normal - } + self.kind().header().map_or(ast::Unsafety::Normal, |header| header.unsafety) } pub fn kind(self) -> FnKind<'a> { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index dc1ceaf69f013..97a1c83dbffb6 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1467,6 +1467,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "inject the given attribute in the crate"), self_profile: bool = (false, parse_bool, [UNTRACKED], "run the self profiler and output the raw event data"), + self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED], + "specifies which kinds of events get recorded by the self profiler"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emits a section containing stack size metadata"), plt: Option<bool> = (None, parse_opt_bool, [TRACKED], diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index eed516a438175..eecd5cba6d358 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -1138,7 +1138,7 @@ fn build_session_( ) -> Session { let self_profiler = if sopts.debugging_opts.self_profile { - let profiler = SelfProfiler::new(); + let profiler = SelfProfiler::new(&sopts.debugging_opts.self_profile_events); match profiler { Ok(profiler) => { crate::ty::query::QueryName::register_with_profiler(&profiler); diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs index aabf9a401c690..585970e64df8d 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc/util/profiling.rs @@ -27,26 +27,42 @@ pub enum ProfileCategory { Other, } -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum ProfilerEvent { - QueryStart { query_name: &'static str, category: ProfileCategory, time: u64 }, - QueryEnd { query_name: &'static str, category: ProfileCategory, time: u64 }, - GenericActivityStart { category: ProfileCategory, label: Cow<'static, str>, time: u64 }, - GenericActivityEnd { category: ProfileCategory, label: Cow<'static, str>, time: u64 }, - IncrementalLoadResultStart { query_name: &'static str, time: u64 }, - IncrementalLoadResultEnd { query_name: &'static str, time: u64 }, - QueryCacheHit { query_name: &'static str, category: ProfileCategory, time: u64 }, - QueryCount { query_name: &'static str, category: ProfileCategory, count: usize, time: u64 }, - QueryBlockedStart { query_name: &'static str, category: ProfileCategory, time: u64 }, - QueryBlockedEnd { query_name: &'static str, category: ProfileCategory, time: u64 }, +bitflags! { + struct EventFilter: u32 { + const GENERIC_ACTIVITIES = 1 << 0; + const QUERY_PROVIDERS = 1 << 1; + const QUERY_CACHE_HITS = 1 << 2; + const QUERY_BLOCKED = 1 << 3; + const INCR_CACHE_LOADS = 1 << 4; + + const DEFAULT = Self::GENERIC_ACTIVITIES.bits | + Self::QUERY_PROVIDERS.bits | + Self::QUERY_BLOCKED.bits | + Self::INCR_CACHE_LOADS.bits; + + // empty() and none() aren't const-fns unfortunately + const NONE = 0; + const ALL = !Self::NONE.bits; + } } +const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ + ("none", EventFilter::NONE), + ("all", EventFilter::ALL), + ("generic-activity", EventFilter::GENERIC_ACTIVITIES), + ("query-provider", EventFilter::QUERY_PROVIDERS), + ("query-cache-hit", EventFilter::QUERY_CACHE_HITS), + ("query-blocked" , EventFilter::QUERY_BLOCKED), + ("incr-cache-load", EventFilter::INCR_CACHE_LOADS), +]; + fn thread_id_to_u64(tid: ThreadId) -> u64 { unsafe { mem::transmute::<ThreadId, u64>(tid) } } pub struct SelfProfiler { profiler: Profiler, + event_filter_mask: EventFilter, query_event_kind: StringId, generic_activity_event_kind: StringId, incremental_load_result_event_kind: StringId, @@ -55,7 +71,7 @@ pub struct SelfProfiler { } impl SelfProfiler { - pub fn new() -> Result<SelfProfiler, Box<dyn Error>> { + pub fn new(event_filters: &Option<Vec<String>>) -> Result<SelfProfiler, Box<dyn Error>> { let filename = format!("pid-{}.rustc_profile", process::id()); let path = std::path::Path::new(&filename); let profiler = Profiler::new(path)?; @@ -66,8 +82,38 @@ impl SelfProfiler { let query_blocked_event_kind = profiler.alloc_string("QueryBlocked"); let query_cache_hit_event_kind = profiler.alloc_string("QueryCacheHit"); + let mut event_filter_mask = EventFilter::empty(); + + if let Some(ref event_filters) = *event_filters { + let mut unknown_events = vec![]; + for item in event_filters { + if let Some(&(_, mask)) = EVENT_FILTERS_BY_NAME.iter() + .find(|&(name, _)| name == item) { + event_filter_mask |= mask; + } else { + unknown_events.push(item.clone()); + } + } + + // Warn about any unknown event names + if unknown_events.len() > 0 { + unknown_events.sort(); + unknown_events.dedup(); + + warn!("Unknown self-profiler events specified: {}. Available options are: {}.", + unknown_events.join(", "), + EVENT_FILTERS_BY_NAME.iter() + .map(|&(name, _)| name.to_string()) + .collect::<Vec<_>>() + .join(", ")); + } + } else { + event_filter_mask = EventFilter::DEFAULT; + } + Ok(SelfProfiler { profiler, + event_filter_mask, query_event_kind, generic_activity_event_kind, incremental_load_result_event_kind, @@ -86,7 +132,6 @@ impl SelfProfiler { pub fn register_query_name(&self, query_name: QueryName) { let id = SelfProfiler::get_query_name_string_id(query_name); - self.profiler.alloc_string_with_reserved_id(id, query_name.as_str()); } @@ -95,7 +140,9 @@ impl SelfProfiler { &self, label: impl Into<Cow<'static, str>>, ) { - self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::Start); + if self.event_filter_mask.contains(EventFilter::GENERIC_ACTIVITIES) { + self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::Start); + } } #[inline] @@ -103,46 +150,66 @@ impl SelfProfiler { &self, label: impl Into<Cow<'static, str>>, ) { - self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::End); + if self.event_filter_mask.contains(EventFilter::GENERIC_ACTIVITIES) { + self.record(&label.into(), self.generic_activity_event_kind, TimestampKind::End); + } } #[inline] pub fn record_query_hit(&self, query_name: QueryName) { - self.record_query(query_name, self.query_cache_hit_event_kind, TimestampKind::Instant); + if self.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS) { + self.record_query(query_name, self.query_cache_hit_event_kind, TimestampKind::Instant); + } } #[inline] pub fn start_query(&self, query_name: QueryName) { - self.record_query(query_name, self.query_event_kind, TimestampKind::Start); + if self.event_filter_mask.contains(EventFilter::QUERY_PROVIDERS) { + self.record_query(query_name, self.query_event_kind, TimestampKind::Start); + } } #[inline] pub fn end_query(&self, query_name: QueryName) { - self.record_query(query_name, self.query_event_kind, TimestampKind::End); + if self.event_filter_mask.contains(EventFilter::QUERY_PROVIDERS) { + self.record_query(query_name, self.query_event_kind, TimestampKind::End); + } } #[inline] pub fn incremental_load_result_start(&self, query_name: QueryName) { - self.record_query( - query_name, - self.incremental_load_result_event_kind, - TimestampKind::Start - ); + if self.event_filter_mask.contains(EventFilter::INCR_CACHE_LOADS) { + self.record_query( + query_name, + self.incremental_load_result_event_kind, + TimestampKind::Start + ); + } } #[inline] pub fn incremental_load_result_end(&self, query_name: QueryName) { - self.record_query(query_name, self.incremental_load_result_event_kind, TimestampKind::End); + if self.event_filter_mask.contains(EventFilter::INCR_CACHE_LOADS) { + self.record_query( + query_name, + self.incremental_load_result_event_kind, + TimestampKind::End + ); + } } #[inline] pub fn query_blocked_start(&self, query_name: QueryName) { - self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::Start); + if self.event_filter_mask.contains(EventFilter::QUERY_BLOCKED) { + self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::Start); + } } #[inline] pub fn query_blocked_end(&self, query_name: QueryName) { - self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::End); + if self.event_filter_mask.contains(EventFilter::QUERY_BLOCKED) { + self.record_query(query_name, self.query_blocked_event_kind, TimestampKind::End); + } } #[inline] diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 5fea9c8747e0f..0cba15b31668f 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -154,6 +154,7 @@ const X86_WHITELIST: &[(&str, Option<&str>)] = &[ ("popcnt", None), ("rdrand", None), ("rdseed", None), + ("rtm", Some("rtm_target_feature")), ("sha", None), ("sse", None), ("sse2", None), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0cd7fe9159493..d601c962fc6af 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2432,6 +2432,7 @@ fn from_target_feature( Some("cmpxchg16b_target_feature") => rust_features.cmpxchg16b_target_feature, Some("adx_target_feature") => rust_features.adx_target_feature, Some("movbe_target_feature") => rust_features.movbe_target_feature, + Some("rtm_target_feature") => rust_features.rtm_target_feature, Some(name) => bug!("unknown target feature gate {}", name), None => true, }; diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index dea198d8c9178..1772879d01362 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -901,8 +901,7 @@ impl OpenOptions { } fn _open(&self, path: &Path) -> io::Result<File> { - let inner = fs_imp::File::open(path, &self.0)?; - Ok(File { inner }) + fs_imp::File::open(path, &self.0).map(|inner| File { inner }) } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c8b020d8c0b03..c53f28665f633 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -402,6 +402,7 @@ declare_features! ( (active, adx_target_feature, "1.32.0", Some(44839), None), (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), (active, movbe_target_feature, "1.34.0", Some(44839), None), + (active, rtm_target_feature, "1.35.0", Some(44839), None), // Allows macro invocations on modules expressions and statements and // procedural macros to expand to non-items. @@ -2034,28 +2035,22 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn_decl: &'a ast::FnDecl, span: Span, _node_id: NodeId) { - match fn_kind { - FnKind::ItemFn(_, header, _, _) => { - // Check for const fn and async fn declarations. - if header.asyncness.node.is_async() { - gate_feature_post!(&self, async_await, span, "async fn is unstable"); - } + if let Some(header) = fn_kind.header() { + // Check for const fn and async fn declarations. + if header.asyncness.node.is_async() { + gate_feature_post!(&self, async_await, span, "async fn is unstable"); + } - if fn_decl.c_variadic { - gate_feature_post!(&self, c_variadic, span, - "C-varaidic functions are unstable"); - } - // Stability of const fn methods are covered in - // `visit_trait_item` and `visit_impl_item` below; this is - // because default methods don't pass through this point. + // Stability of const fn methods are covered in + // `visit_trait_item` and `visit_impl_item` below; this is + // because default methods don't pass through this point. + self.check_abi(header.abi, span); + } - self.check_abi(header.abi, span); - } - FnKind::Method(_, sig, _, _) => { - self.check_abi(sig.header.abi, span); - } - _ => {} + if fn_decl.c_variadic { + gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable"); } + visit::walk_fn(self, fn_kind, fn_decl, span); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 8f42d47e69cd3..fe74cbd649612 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -31,6 +31,16 @@ pub enum FnKind<'a> { Closure(&'a Expr), } +impl<'a> FnKind<'a> { + pub fn header(&self) -> Option<&'a FnHeader> { + match *self { + FnKind::ItemFn(_, header, _, _) => Some(header), + FnKind::Method(_, sig, _, _) => Some(&sig.header), + FnKind::Closure(_) => None, + } + } +} + /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; diff --git a/src/test/codegen/pgo-instrumentation.rs b/src/test/codegen/pgo-instrumentation.rs new file mode 100644 index 0000000000000..8493ef565d888 --- /dev/null +++ b/src/test/codegen/pgo-instrumentation.rs @@ -0,0 +1,20 @@ +// Test that `-Zpgo-gen` creates expected instrumentation artifacts in LLVM IR. + +// needs-profiler-support +// compile-flags: -Z pgo-gen -Ccodegen-units=1 + +// CHECK: @__llvm_profile_raw_version = +// CHECK: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = private global +// CHECK: @__profd_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = private global +// CHECK: @__profc_{{.*}}pgo_instrumentation{{.*}}main{{.*}} = private global +// CHECK: @__profd_{{.*}}pgo_instrumentation{{.*}}main{{.*}} = private global +// CHECK: @__llvm_profile_filename = {{.*}}"default_%m.profraw\00"{{.*}} + +#[inline(never)] +fn some_function() { + +} + +fn main() { + some_function(); +} diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile index 7c19961b1e420..48181bcbdc6d3 100644 --- a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile +++ b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile @@ -1,8 +1,8 @@ +# needs-profiler-support + -include ../tools.mk all: -ifeq ($(PROFILER_SUPPORT),1) $(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)" test.rs $(call RUN,test) || exit 1 [ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1) -endif diff --git a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile index dc52e91317a5a..20977edb88e87 100644 --- a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile +++ b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile @@ -1,11 +1,11 @@ +# needs-profiler-support + -include ../tools.mk all: -ifeq ($(PROFILER_SUPPORT),1) - $(RUSTC) -O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)/test.profraw" --emit=llvm-ir test.rs + $(RUSTC) -O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)" --emit=llvm-ir test.rs # We expect symbols starting with "__llvm_profile_". $(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll # We do NOT expect the "__imp_" version of these symbols. $(CGREP) -v "__imp___llvm_profile_" < $(TMPDIR)/test.ll # 64 bit $(CGREP) -v "__imp____llvm_profile_" < $(TMPDIR)/test.ll # 32 bit -endif diff --git a/src/test/run-make-fulldeps/pgo-gen/Makefile b/src/test/run-make-fulldeps/pgo-gen/Makefile index 0469c4443d85a..ce44c10a7c2d2 100644 --- a/src/test/run-make-fulldeps/pgo-gen/Makefile +++ b/src/test/run-make-fulldeps/pgo-gen/Makefile @@ -1,8 +1,8 @@ +# needs-profiler-support + -include ../tools.mk all: -ifeq ($(PROFILER_SUPPORT),1) $(RUSTC) -g -Z pgo-gen="$(TMPDIR)" test.rs $(call RUN,test) || exit 1 [ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1) -endif diff --git a/src/test/run-make-fulldeps/profile/Makefile b/src/test/run-make-fulldeps/profile/Makefile index 7300bfc955363..c12712590e48f 100644 --- a/src/test/run-make-fulldeps/profile/Makefile +++ b/src/test/run-make-fulldeps/profile/Makefile @@ -1,9 +1,9 @@ +# needs-profiler-support + -include ../tools.mk all: -ifeq ($(PROFILER_SUPPORT),1) $(RUSTC) -g -Z profile test.rs $(call RUN,test) || exit 1 [ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1) [ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1) -endif diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile index 207615bfbd5c6..51d8a4a947adc 100644 --- a/src/test/run-make-fulldeps/sanitizer-address/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-address/Makefile @@ -1,3 +1,5 @@ +# needs-sanitizer-support + -include ../tools.mk LOG := $(TMPDIR)/log.txt @@ -5,11 +7,9 @@ LOG := $(TMPDIR)/log.txt # NOTE the address sanitizer only supports x86_64 linux and macOS ifeq ($(TARGET),x86_64-apple-darwin) -ASAN_SUPPORT=$(SANITIZER_SUPPORT) EXTRA_RUSTFLAG=-C rpath else ifeq ($(TARGET),x86_64-unknown-linux-gnu) -ASAN_SUPPORT=$(SANITIZER_SUPPORT) # Apparently there are very specific Linux kernels, notably the one that's # currently on Travis CI, which contain a buggy commit that triggers failures in @@ -23,7 +23,5 @@ endif endif all: -ifeq ($(ASAN_SUPPORT),1) $(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) librustc_asan $(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow -endif diff --git a/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile index 4b7fece36d92a..36cde355468be 100644 --- a/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile @@ -1,3 +1,5 @@ +# needs-sanitizer-support + -include ../tools.mk LOG := $(TMPDIR)/log.txt @@ -8,15 +10,12 @@ LOG := $(TMPDIR)/log.txt # is correctly detected. ifeq ($(TARGET),x86_64-unknown-linux-gnu) -ASAN_SUPPORT=$(SANITIZER_SUPPORT) # See comment in sanitizer-address/Makefile for why this is here EXTRA_RUSTFLAG=-C relocation-model=dynamic-no-pic endif all: -ifeq ($(ASAN_SUPPORT),1) $(RUSTC) -g -Z sanitizer=address --crate-type cdylib --target $(TARGET) $(EXTRA_RUSTFLAG) library.rs $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) $(EXTRA_RUSTFLAG) -llibrary program.rs LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow -endif diff --git a/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile index 97f6172142224..b382ff5e7b24f 100644 --- a/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile @@ -1,3 +1,5 @@ +# needs-sanitizer-support + -include ../tools.mk LOG := $(TMPDIR)/log.txt @@ -8,15 +10,11 @@ LOG := $(TMPDIR)/log.txt # is correctly detected. ifeq ($(TARGET),x86_64-unknown-linux-gnu) -ASAN_SUPPORT=$(SANITIZER_SUPPORT) - # See comment in sanitizer-address/Makefile for why this is here EXTRA_RUSTFLAG=-C relocation-model=dynamic-no-pic endif all: -ifeq ($(ASAN_SUPPORT),1) $(RUSTC) -g -Z sanitizer=address --crate-type dylib --target $(TARGET) $(EXTRA_RUSTFLAG) library.rs $(RUSTC) -g -Z sanitizer=address --crate-type bin --target $(TARGET) $(EXTRA_RUSTFLAG) -llibrary program.rs LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow -endif diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile index dc37c0d0bc946..9581ac565ea02 100644 --- a/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-invalid-cratetype/Makefile @@ -1,18 +1,16 @@ +# needs-sanitizer-support + -include ../tools.mk # NOTE the address sanitizer only supports x86_64 linux and macOS ifeq ($(TARGET),x86_64-apple-darwin) -ASAN_SUPPORT=$(SANITIZER_SUPPORT) EXTRA_RUSTFLAG=-C rpath else ifeq ($(TARGET),x86_64-unknown-linux-gnu) -ASAN_SUPPORT=$(SANITIZER_SUPPORT) EXTRA_RUSTFLAG= endif endif all: -ifeq ($(ASAN_SUPPORT),1) $(RUSTC) -Z sanitizer=address --crate-type proc-macro --target $(TARGET) hello.rs 2>&1 | $(CGREP) '-Z sanitizer' -endif diff --git a/src/test/run-make-fulldeps/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile index 0f3c18f9293f5..101e8272ab91e 100644 --- a/src/test/run-make-fulldeps/sanitizer-leak/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-leak/Makefile @@ -1,12 +1,11 @@ -include ../tools.mk +# needs-sanitizer-support # only-linux # only-x86_64 # ignore-test # FIXME(#46126) ThinLTO for libstd broke this test all: -ifdef SANITIZER_SUPPORT $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) librustc_lsan $(TMPDIR)/leak 2>&1 | $(CGREP) 'detected memory leaks' -endif diff --git a/src/test/run-make-fulldeps/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile index 718d9637ea06d..b3376f8a72358 100644 --- a/src/test/run-make-fulldeps/sanitizer-memory/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-memory/Makefile @@ -1,10 +1,9 @@ -include ../tools.mk +# needs-sanitizer-support # only-linux # only-x86_64 all: -ifdef SANITIZER_SUPPORT $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_msan $(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value -endif diff --git a/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile b/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile index 2b444d667bfa3..8fa08688fdd71 100644 --- a/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile @@ -1,18 +1,17 @@ +# needs-sanitizer-support + -include ../tools.mk # This test builds a staticlib, then an executable that links to it. -# The staticlib and executable both are compiled with address sanitizer, +# The staticlib and executable both are compiled with address sanitizer, # and we assert that a fault in the staticlib is correctly detected. ifeq ($(TARGET),x86_64-unknown-linux-gnu) -ASAN_SUPPORT=$(SANITIZER_SUPPORT) EXTRA_RUSTFLAG= endif all: -ifeq ($(ASAN_SUPPORT),1) $(RUSTC) -g -Z sanitizer=address --crate-type staticlib --target $(TARGET) library.rs $(CC) program.c $(call STATICLIB,library) $(call OUT_EXE,program) $(EXTRACFLAGS) $(EXTRACXXFLAGS) LD_LIBRARY_PATH=$(TMPDIR) $(TMPDIR)/program 2>&1 | $(CGREP) stack-buffer-overflow -endif diff --git a/src/test/ui/feature-gates/feature-gate-async-await.rs b/src/test/ui/feature-gates/feature-gate-async-await.rs index 7ee035644bc95..f06b0b3639503 100644 --- a/src/test/ui/feature-gates/feature-gate-async-await.rs +++ b/src/test/ui/feature-gates/feature-gate-async-await.rs @@ -2,6 +2,12 @@ #![feature(futures_api)] +struct S; + +impl S { + async fn foo() {} //~ ERROR async fn is unstable +} + async fn foo() {} //~ ERROR async fn is unstable fn main() { diff --git a/src/test/ui/feature-gates/feature-gate-async-await.stderr b/src/test/ui/feature-gates/feature-gate-async-await.stderr index 6bff254607fca..4132563842235 100644 --- a/src/test/ui/feature-gates/feature-gate-async-await.stderr +++ b/src/test/ui/feature-gates/feature-gate-async-await.stderr @@ -1,5 +1,14 @@ error[E0658]: async fn is unstable - --> $DIR/feature-gate-async-await.rs:5:1 + --> $DIR/feature-gate-async-await.rs:8:5 + | +LL | async fn foo() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/50547 + = help: add #![feature(async_await)] to the crate attributes to enable + +error[E0658]: async fn is unstable + --> $DIR/feature-gate-async-await.rs:11:1 | LL | async fn foo() {} | ^^^^^^^^^^^^^^^^^ @@ -8,7 +17,7 @@ LL | async fn foo() {} = help: add #![feature(async_await)] to the crate attributes to enable error[E0658]: async blocks are unstable - --> $DIR/feature-gate-async-await.rs:8:13 + --> $DIR/feature-gate-async-await.rs:14:13 | LL | let _ = async {}; | ^^^^^^^^ @@ -17,7 +26,7 @@ LL | let _ = async {}; = help: add #![feature(async_await)] to the crate attributes to enable error[E0658]: async closures are unstable - --> $DIR/feature-gate-async-await.rs:9:13 + --> $DIR/feature-gate-async-await.rs:15:13 | LL | let _ = async || {}; | ^^^^^^^^^^^ @@ -25,6 +34,6 @@ LL | let _ = async || {}; = note: for more information, see https://github.com/rust-lang/rust/issues/50547 = help: add #![feature(async_await)] to the crate attributes to enable -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index 84300301b7629..8f3a52ba5d677 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -23,6 +23,7 @@ // gate-test-adx_target_feature // gate-test-cmpxchg16b_target_feature // gate-test-movbe_target_feature +// gate-test-rtm_target_feature // min-llvm-version 6.0 #[target_feature(enable = "avx512bw")] diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index 155298e5062b5..e142125225fb4 100644 --- a/src/test/ui/target-feature-gate.stderr +++ b/src/test/ui/target-feature-gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/target-feature-gate.rs:28:18 + --> $DIR/target-feature-gate.rs:29:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 64882c603bad3..fb6ada89171ab 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -88,6 +88,9 @@ impl EarlyProps { } } + let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some(); + let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some(); + iter_header(testfile, None, &mut |ln| { // we should check if any only-<platform> exists and if it exists // and does not matches the current platform, skip the test @@ -116,6 +119,16 @@ impl EarlyProps { config.parse_needs_matching_clang(ln) { props.ignore = Ignore::Ignore; } + + if !rustc_has_profiler_support && + config.parse_needs_profiler_support(ln) { + props.ignore = Ignore::Ignore; + } + + if !rustc_has_sanitizer_support && + config.parse_needs_sanitizer_support(ln) { + props.ignore = Ignore::Ignore; + } } if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoBoth) && @@ -748,6 +761,14 @@ impl Config { self.parse_name_directive(line, "needs-matching-clang") } + fn parse_needs_profiler_support(&self, line: &str) -> bool { + self.parse_name_directive(line, "needs-profiler-support") + } + + fn parse_needs_sanitizer_support(&self, line: &str) -> bool { + self.parse_name_directive(line, "needs-sanitizer-support") + } + /// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86` /// or `normalize-stderr-32bit`. fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective { diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 09940a70d0a9f..b860feaffccb8 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 09940a70d0a9fabfb4985426aa7d66ca1875c65e +Subproject commit b860feaffccb81199c045e9b1511c2e25825dc0c