From 946fb894a667bf256936e356a80d36fe50341005 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 27 Feb 2019 17:21:31 -0700 Subject: [PATCH 01/11] Permit unwinding through FFI by default See #58794 for context. --- src/librustc_mir/build/mod.rs | 2 +- src/test/ui/abort-on-c-abi.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4e970aee42cf4..6a3bb8b8b86a2 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -502,7 +502,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool { // This is a special case: some functions have a C abi but are meant to // unwind anyway. Don't stop them. match unwind_attr { - None => true, + None => false, // FIXME(#58794) Some(UnwindAttr::Allowed) => false, Some(UnwindAttr::Aborts) => true, } diff --git a/src/test/ui/abort-on-c-abi.rs b/src/test/ui/abort-on-c-abi.rs index cd7dd1b6a452f..2f08730ec6132 100644 --- a/src/test/ui/abort-on-c-abi.rs +++ b/src/test/ui/abort-on-c-abi.rs @@ -1,6 +1,7 @@ // run-pass #![allow(unused_must_use)] +#![feature(unwind_attributes)] // Since we mark some ABIs as "nounwind" to LLVM, we must make sure that // we never unwind through them. @@ -13,6 +14,7 @@ use std::io::prelude::*; use std::io; use std::process::{Command, Stdio}; +#[unwind(aborts)] // FIXME(#58794) extern "C" fn panic_in_ffi() { panic!("Test"); } From ceaf4dd3facbd220c3a349422bdbc2b665e4aa31 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 2 Apr 2019 14:53:57 -0700 Subject: [PATCH 02/11] Revert "Allow a dirty MirBuilt for make_extern and make_method_extern" This reverts commit b4a6f597934f16f89e27058a32a514c9572f148f. --- src/test/incremental/hashes/function_interfaces.rs | 2 +- src/test/incremental/hashes/inherent_impls.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 84680a52ff3ce..4515e36166eb8 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -94,7 +94,7 @@ pub unsafe fn make_unsafe() {} pub fn make_extern() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, mir_built, typeck_tables_of, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub extern "C" fn make_extern() {} diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 882383e841957..538fd2c29203b 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -263,7 +263,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,mir_built,fn_sig,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub extern fn make_method_extern(&self) { } } From 46049e70f6fee53a316ae707402490feaf296a6c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 10 May 2019 15:10:15 -0700 Subject: [PATCH 03/11] Force #[unwind(aborts)] in test/codegen/c-variadic.rs --- src/test/codegen/c-variadic.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/codegen/c-variadic.rs b/src/test/codegen/c-variadic.rs index 13be5ced27fa9..bb90a9653f573 100644 --- a/src/test/codegen/c-variadic.rs +++ b/src/test/codegen/c-variadic.rs @@ -2,6 +2,7 @@ #![crate_type = "lib"] #![feature(c_variadic)] +#![feature(unwind_attributes)] #![no_std] use core::ffi::VaList; @@ -10,6 +11,7 @@ extern "C" { fn foreign_c_variadic_1(_: VaList, ...); } +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_0() { // Ensure that we correctly call foreign C-variadic functions. // CHECK: invoke void (i32, ...) @foreign_c_variadic_0(i32 0) @@ -24,20 +26,24 @@ pub unsafe extern "C" fn use_foreign_c_variadic_0() { // Ensure that we do not remove the `va_list` passed to the foreign function when // removing the "spoofed" `VaListImpl` that is used by Rust defined C-variadics. +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) { // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap) foreign_c_variadic_1(ap); } +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) { // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 42) foreign_c_variadic_1(ap, 42i32); } +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) { // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42) foreign_c_variadic_1(ap, 2i32, 42i32); } +#[unwind(aborts)] // FIXME(#58794) pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) { // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, i32 2, i32 42, i32 0) foreign_c_variadic_1(ap, 2i32, 42i32, 0i32); From 31b4b771c9efa37e7f76545a68ed0afc3cdf4cee Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Aug 2019 20:41:52 +0300 Subject: [PATCH 04/11] pprust: Do not print spaces before some tokens --- src/libsyntax/print/pprust.rs | 14 +++++++++++++- src/test/pretty/attr-literals.rs | 4 ++-- src/test/pretty/block-comment-wchar.pp | 5 +---- src/test/pretty/delimited-token-groups.rs | 2 +- src/test/pretty/do1.rs | 2 +- src/test/pretty/match-block-expr.rs | 2 +- src/test/ui/macros/macro-first-set.rs | 2 +- .../proc-macro/auxiliary/attr-stmt-expr-rpass.rs | 4 ++-- src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs | 4 ++-- 9 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index bda761244d5ca..536687bdbed45 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -152,6 +152,18 @@ pub fn to_string(f: F) -> String where printer.s.eof() } +// This makes comma-separated lists look slightly nicer, +// and also addresses a specific regression described in issue #63896. +fn tt_prepend_space(tt: &TokenTree) -> bool { + match tt { + TokenTree::Token(token) => match token.kind { + token::Comma => false, + _ => true, + } + _ => true, + } +} + fn binop_to_string(op: BinOpToken) -> &'static str { match op { token::Plus => "+", @@ -684,7 +696,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::DerefM fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) { for (i, tt) in tts.into_trees().enumerate() { - if i != 0 { + if i != 0 && tt_prepend_space(&tt) { self.space(); } self.print_tt(tt, convert_dollar_crate); diff --git a/src/test/pretty/attr-literals.rs b/src/test/pretty/attr-literals.rs index bcd6ffaaf815b..9db7e27b16103 100644 --- a/src/test/pretty/attr-literals.rs +++ b/src/test/pretty/attr-literals.rs @@ -5,10 +5,10 @@ #![feature(rustc_attrs)] fn main() { - #![rustc_dummy("hi" , 1 , 2 , 1.012 , pi = 3.14 , bye , name ("John"))] + #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name ("John"))] #[rustc_dummy = 8] fn f() { } - #[rustc_dummy(1 , 2 , 3)] + #[rustc_dummy(1, 2, 3)] fn g() { } } diff --git a/src/test/pretty/block-comment-wchar.pp b/src/test/pretty/block-comment-wchar.pp index f15d7cdc44ccd..9317b36ba497b 100644 --- a/src/test/pretty/block-comment-wchar.pp +++ b/src/test/pretty/block-comment-wchar.pp @@ -99,8 +99,5 @@ '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', '\u{2009}', '\u{200A}', '\u{2028}', '\u{2029}', '\u{202F}', '\u{205F}', '\u{3000}']; - for c in &chars { - let ws = c.is_whitespace(); - println!("{} {}" , c , ws); - } + for c in &chars { let ws = c.is_whitespace(); println!("{} {}", c, ws); } } diff --git a/src/test/pretty/delimited-token-groups.rs b/src/test/pretty/delimited-token-groups.rs index 768f27ad23a8e..7bbb7dc911f93 100644 --- a/src/test/pretty/delimited-token-groups.rs +++ b/src/test/pretty/delimited-token-groups.rs @@ -5,7 +5,7 @@ macro_rules! mac { ($ ($ tt : tt) *) => () } mac! { - struct S { field1 : u8 , field2 : u16 , } impl Clone for S + struct S { field1 : u8, field2 : u16, } impl Clone for S { fn clone () -> S { diff --git a/src/test/pretty/do1.rs b/src/test/pretty/do1.rs index 7be835cb22f2d..233ccdb0098b3 100644 --- a/src/test/pretty/do1.rs +++ b/src/test/pretty/do1.rs @@ -2,4 +2,4 @@ fn f(f: F) where F: Fn(isize) { f(10) } -fn main() { f(|i| { assert_eq!(i , 10) }) } +fn main() { f(|i| { assert_eq!(i, 10) }) } diff --git a/src/test/pretty/match-block-expr.rs b/src/test/pretty/match-block-expr.rs index 0db6574b0737f..10903e928cda8 100644 --- a/src/test/pretty/match-block-expr.rs +++ b/src/test/pretty/match-block-expr.rs @@ -2,5 +2,5 @@ fn main() { let x = match { 5 } { 1 => 5, 2 => 6, _ => 7, }; - assert_eq!(x , 7); + assert_eq!(x, 7); } diff --git a/src/test/ui/macros/macro-first-set.rs b/src/test/ui/macros/macro-first-set.rs index a21e4cd201a4f..34529cdaa64f1 100644 --- a/src/test/ui/macros/macro-first-set.rs +++ b/src/test/ui/macros/macro-first-set.rs @@ -25,7 +25,7 @@ macro_rules! foo_26444 { } fn test_26444() { - assert_eq!("a , b , c , d , e", foo_26444!(a, b; c; d, e)); + assert_eq!("a, b, c, d, e", foo_26444!(a, b; c; d, e)); assert_eq!("f", foo_26444!(; f ;)); } diff --git a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs index d81e16d9d2961..f1de3709b166b 100644 --- a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs +++ b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs @@ -17,7 +17,7 @@ pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\" , string);"); + assert_eq!(item.to_string(), "println!(\"{}\", string);"); item } @@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\" , string)"); + assert_eq!(item.to_string(), "println!(\"{}\", string)"); item } diff --git a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs index 0a82cbedd77ce..d2180def5b760 100644 --- a/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs +++ b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs @@ -17,7 +17,7 @@ pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\" , string);"); + assert_eq!(item.to_string(), "println!(\"{}\", string);"); item } @@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "println!(\"{}\" , string)"); + assert_eq!(item.to_string(), "println!(\"{}\", string)"); item } From 3a93713dc374702a68cd359841624f3fef6781f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 26 Aug 2019 17:46:14 -0700 Subject: [PATCH 05/11] Account for doc comments coming from proc macros without spans --- .../passes/check_code_block_syntax.rs | 2 +- .../passes/collect_intra_doc_links.rs | 4 ++-- src/librustdoc/passes/mod.rs | 21 ++++++++++--------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 357e17d2d1bc4..67aa014a788f2 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { // We couldn't calculate the span of the markdown block that had the error, so our // diagnostics are going to be a bit lacking. let mut diag = self.cx.sess().struct_span_warn( - super::span_of_attrs(&item.attrs), + super::span_of_attrs(&item.attrs).unwrap_or(item.source.span()), "doc comment contains an invalid Rust code block", ); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 5c9fac7eab421..7f4a17225e644 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -464,7 +464,7 @@ fn resolution_failure( } }; let attrs = &item.attrs; - let sp = span_of_attrs(attrs); + let sp = span_of_attrs(attrs).unwrap_or(item.source.span()); let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, @@ -516,7 +516,7 @@ fn ambiguity_error( } }; let attrs = &item.attrs; - let sp = span_of_attrs(attrs); + let sp = span_of_attrs(attrs).unwrap_or(item.source.span()); let mut msg = format!("`{}` is ", path_str); diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 641a6df221446..49a34c7e46281 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -339,7 +339,7 @@ pub fn look_for_tests<'tcx>( find_testable_code(&dox, &mut tests, ErrorCodes::No); if check_missing_code == true && tests.found_tests == 0 { - let sp = span_of_attrs(&item.attrs).substitute_dummy(item.source.span()); + let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span()); let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::MISSING_DOC_CODE_EXAMPLES, hir_id, @@ -352,20 +352,23 @@ pub fn look_for_tests<'tcx>( let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::PRIVATE_DOC_TESTS, hir_id, - span_of_attrs(&item.attrs), + span_of_attrs(&item.attrs).unwrap_or(item.source.span()), "Documentation test in private item"); diag.emit(); } } /// Returns a span encompassing all the given attributes. -crate fn span_of_attrs(attrs: &clean::Attributes) -> Span { +crate fn span_of_attrs(attrs: &clean::Attributes) -> Option { if attrs.doc_strings.is_empty() { - return DUMMY_SP; + return None; } let start = attrs.doc_strings[0].span(); + if start == DUMMY_SP { + return None; + } let end = attrs.doc_strings.last().expect("No doc strings provided").span(); - start.to(end) + Some(start.to(end)) } /// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code. @@ -391,7 +394,7 @@ crate fn source_span_for_markdown_range( let snippet = cx .sess() .source_map() - .span_to_snippet(span_of_attrs(attrs)) + .span_to_snippet(span_of_attrs(attrs)?) .ok()?; let starting_line = markdown[..md_range.start].matches('\n').count(); @@ -441,10 +444,8 @@ crate fn source_span_for_markdown_range( } } - let sp = span_of_attrs(attrs).from_inner(InnerSpan::new( + Some(span_of_attrs(attrs)?.from_inner(InnerSpan::new( md_range.start + start_bytes, md_range.end + start_bytes + end_bytes, - )); - - Some(sp) + ))) } From ee6de6cf44d8606e2661cfe16b7d4128fbeb0ca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 26 Aug 2019 21:12:59 -0700 Subject: [PATCH 06/11] add regression test --- .../auxiliary/through-proc-macro-aux.rs | 20 +++++++++++++++++++ src/test/rustdoc/through-proc-macro.rs | 12 +++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/rustdoc/auxiliary/through-proc-macro-aux.rs create mode 100644 src/test/rustdoc/through-proc-macro.rs diff --git a/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs b/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs new file mode 100644 index 0000000000000..5c4a01ee3a74a --- /dev/null +++ b/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs @@ -0,0 +1,20 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] +#![crate_name="some_macros"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream { + item // This doesn't erase the spans. +} + +#[proc_macro_attribute] +pub fn second(_attr: TokenStream, item: TokenStream) -> TokenStream { + // Make a new `TokenStream` to erase the spans: + let mut out: TokenStream = TokenStream::new(); + out.extend(item); + out +} diff --git a/src/test/rustdoc/through-proc-macro.rs b/src/test/rustdoc/through-proc-macro.rs new file mode 100644 index 0000000000000..348c9eea2dcbf --- /dev/null +++ b/src/test/rustdoc/through-proc-macro.rs @@ -0,0 +1,12 @@ +// aux-build:through-proc-macro-aux.rs +// build-aux-docs +#![warn(intra_doc_link_resolution_failure)] +extern crate some_macros; + +#[some_macros::second] +pub enum Boom { + /// [Oooops] + Bam, +} + +fn main() {} From 852014a0128f70aed046b5cf710603a52d99b07d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 1 Sep 2019 14:54:57 +0300 Subject: [PATCH 07/11] Support "soft" feature-gating using a lint Use it for feature-gating `#[bench]` --- src/libcore/macros.rs | 6 ++++-- src/librustc/ich/impls_syntax.rs | 3 ++- src/librustc/lint/builtin.rs | 7 +++++++ src/librustc/middle/stability.rs | 22 ++++++++++++++------ src/librustc_resolve/macros.rs | 4 ++-- src/libsyntax/attr/builtin.rs | 28 +++++++++++--------------- src/libsyntax_pos/symbol.rs | 1 + src/test/ui/feature-gates/bench.rs | 4 ++++ src/test/ui/feature-gates/bench.stderr | 10 +++++++++ 9 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/feature-gates/bench.rs create mode 100644 src/test/ui/feature-gates/bench.stderr diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index f9dc53874acb1..680fcd12c4f2b 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -1281,8 +1281,10 @@ pub(crate) mod builtin { pub macro test($item:item) { /* compiler built-in */ } /// Attribute macro applied to a function to turn it into a benchmark test. - #[unstable(feature = "test", issue = "50297", - reason = "`bench` is a part of custom test frameworks which are unstable")] + #[cfg_attr(not(boostrap_stdarch_ignore_this), unstable(soft, feature = "test", issue = "50297", + reason = "`bench` is a part of custom test frameworks which are unstable"))] + #[cfg_attr(boostrap_stdarch_ignore_this, unstable(feature = "test", issue = "50297", + reason = "`bench` is a part of custom test frameworks which are unstable"))] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 5cc8324b31606..daa69efe2849d 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -136,9 +136,10 @@ for ::syntax::attr::StabilityLevel { hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { - ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => { + ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue, ref is_soft } => { reason.hash_stable(hcx, hasher); issue.hash_stable(hcx, hasher); + is_soft.hash_stable(hcx, hasher); } ::syntax::attr::StabilityLevel::Stable { ref since } => { since.hash_stable(hcx, hasher); diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 6d9a6bb77dd55..dd290572d7bb7 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -395,6 +395,12 @@ declare_lint! { "reservation of a two-phased borrow conflicts with other shared borrows" } +declare_lint! { + pub SOFT_UNSTABLE, + Deny, + "a feature gate that doesn't break dependent crates" +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -460,6 +466,7 @@ declare_lint_pass! { NESTED_IMPL_TRAIT, MUTABLE_BORROW_RESERVATION_CONFLICT, INDIRECT_STRUCTURAL_MATCH, + SOFT_UNSTABLE, ] } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 5ab762ab225f9..0d22c37cd6d71 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -438,6 +438,7 @@ impl<'tcx> Index<'tcx> { level: attr::StabilityLevel::Unstable { reason: Some(Symbol::intern(reason)), issue: 27812, + is_soft: false, }, feature: sym::rustc_private, rustc_depr: None, @@ -480,7 +481,7 @@ pub fn provide(providers: &mut Providers<'_>) { } pub fn report_unstable( - sess: &Session, feature: Symbol, reason: Option, issue: u32, span: Span + sess: &Session, feature: Symbol, reason: Option, issue: u32, is_soft: bool, span: Span ) { let msg = match reason { Some(r) => format!("use of unstable library feature '{}': {}", feature, r), @@ -505,7 +506,13 @@ pub fn report_unstable( let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone()); let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id); if fresh { - emit_feature_err(&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg); + if is_soft { + sess.buffer_lint(lint::builtin::SOFT_UNSTABLE, CRATE_NODE_ID, span, &msg); + } else { + emit_feature_err( + &sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg + ); + } } } @@ -621,6 +628,7 @@ pub enum EvalResult { feature: Symbol, reason: Option, issue: u32, + is_soft: bool, }, /// The item does not have the `#[stable]` or `#[unstable]` marker assigned. Unmarked, @@ -720,7 +728,9 @@ impl<'tcx> TyCtxt<'tcx> { } match stability { - Some(&Stability { level: attr::Unstable { reason, issue }, feature, .. }) => { + Some(&Stability { + level: attr::Unstable { reason, issue, is_soft }, feature, .. + }) => { if span.allows_unstable(feature) { debug!("stability: skipping span={:?} since it is internal", span); return EvalResult::Allow; @@ -744,7 +754,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - EvalResult::Deny { feature, reason, issue } + EvalResult::Deny { feature, reason, issue, is_soft } } Some(_) => { // Stable APIs are always ok to call and deprecated APIs are @@ -767,8 +777,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn check_stability(self, def_id: DefId, id: Option, span: Span) { match self.eval_stability(def_id, id, span) { EvalResult::Allow => {} - EvalResult::Deny { feature, reason, issue } => - report_unstable(self.sess, feature, reason, issue, span), + EvalResult::Deny { feature, reason, issue, is_soft } => + report_unstable(self.sess, feature, reason, issue, is_soft, span), EvalResult::Unmarked => { // The API could be uncallable for other reasons, for example when a private module // was referenced. diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0ab6f19ac60a2..50ab0749d7f32 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -797,10 +797,10 @@ impl<'a> Resolver<'a> { fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) { let span = path.span; if let Some(stability) = &ext.stability { - if let StabilityLevel::Unstable { reason, issue } = stability.level { + if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level { let feature = stability.feature; if !self.active_features.contains(&feature) && !span.allows_unstable(feature) { - stability::report_unstable(self.session, feature, reason, issue, span); + stability::report_unstable(self.session, feature, reason, issue, is_soft, span); } } if let Some(depr) = &stability.rustc_depr { diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 5fb513783fbaa..b5037b75f79e7 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -154,23 +154,10 @@ pub struct Stability { #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)] pub enum StabilityLevel { // Reason for the current stability level and the relevant rust-lang issue - Unstable { reason: Option, issue: u32 }, + Unstable { reason: Option, issue: u32, is_soft: bool }, Stable { since: Symbol }, } -impl Stability { - pub fn unstable(feature: Symbol, reason: Option, issue: u32) -> Stability { - Stability { - level: StabilityLevel::Unstable { reason, issue }, - feature, - rustc_depr: None, - const_stability: None, - promotable: false, - allow_const_fn_ptr: false, - } - } -} - impl StabilityLevel { pub fn is_unstable(&self) -> bool { if let StabilityLevel::Unstable {..} = *self { @@ -356,19 +343,27 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, let mut feature = None; let mut reason = None; let mut issue = None; + let mut is_soft = false; for meta in metas { if let Some(mi) = meta.meta_item() { match mi.name_or_empty() { sym::feature => if !get(mi, &mut feature) { continue 'outer }, sym::reason => if !get(mi, &mut reason) { continue 'outer }, sym::issue => if !get(mi, &mut issue) { continue 'outer }, + sym::soft => { + if !mi.is_word() { + let msg = "`soft` should not have any arguments"; + sess.span_diagnostic.span_err(mi.span, msg); + } + is_soft = true; + } _ => { handle_errors( sess, meta.span(), AttrError::UnknownMetaItem( mi.path.to_string(), - &["feature", "reason", "issue"] + &["feature", "reason", "issue", "soft"] ), ); continue 'outer @@ -400,7 +395,8 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, "incorrect 'issue'"); continue } - } + }, + is_soft, }, feature, rustc_depr: None, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 2d9556233d15f..e301a06997003 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -623,6 +623,7 @@ symbols! { size, slice_patterns, slicing_syntax, + soft, Some, specialization, speed, diff --git a/src/test/ui/feature-gates/bench.rs b/src/test/ui/feature-gates/bench.rs new file mode 100644 index 0000000000000..d8a09625e9639 --- /dev/null +++ b/src/test/ui/feature-gates/bench.rs @@ -0,0 +1,4 @@ +#[bench] //~ ERROR use of unstable library feature 'test' +fn bench() {} + +fn main() {} diff --git a/src/test/ui/feature-gates/bench.stderr b/src/test/ui/feature-gates/bench.stderr new file mode 100644 index 0000000000000..25ddcc5e36169 --- /dev/null +++ b/src/test/ui/feature-gates/bench.stderr @@ -0,0 +1,10 @@ +error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable + --> $DIR/bench.rs:1:3 + | +LL | #[bench] + | ^^^^^ + | + = note: `#[deny(soft_unstable)]` on by default + +error: aborting due to previous error + From 0c044190d412301bfddad7d2184455f7903835c6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Sep 2019 22:23:53 +0300 Subject: [PATCH 08/11] Turn `soft_unstable` into a future-compatibility lint --- src/librustc_lint/lib.rs | 7 ++++++- src/test/ui/feature-gates/bench.rs | 1 + src/test/ui/feature-gates/bench.stderr | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 3a540fdf4b91f..5648f9d0fdb3c 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -433,7 +433,12 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(INDIRECT_STRUCTURAL_MATCH), reference: "issue #62411 ", edition: None, - } + }, + FutureIncompatibleInfo { + id: LintId::of(SOFT_UNSTABLE), + reference: "issue #64266 ", + edition: None, + }, ]); // Register renamed and removed lints. diff --git a/src/test/ui/feature-gates/bench.rs b/src/test/ui/feature-gates/bench.rs index d8a09625e9639..afe4dc7d54c9b 100644 --- a/src/test/ui/feature-gates/bench.rs +++ b/src/test/ui/feature-gates/bench.rs @@ -1,4 +1,5 @@ #[bench] //~ ERROR use of unstable library feature 'test' + //~| WARN this was previously accepted fn bench() {} fn main() {} diff --git a/src/test/ui/feature-gates/bench.stderr b/src/test/ui/feature-gates/bench.stderr index 25ddcc5e36169..b9e24e931d42b 100644 --- a/src/test/ui/feature-gates/bench.stderr +++ b/src/test/ui/feature-gates/bench.stderr @@ -5,6 +5,8 @@ LL | #[bench] | ^^^^^ | = note: `#[deny(soft_unstable)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 error: aborting due to previous error From 2fe39b6d45f79bc127c6ce633091e2faabc8f275 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 2 Sep 2019 13:50:44 +0200 Subject: [PATCH 09/11] Update xLTO compatibility table in rustc book. --- src/doc/rustc/src/linker-plugin-lto.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index 2ae726c4ba61d..6f1bbe60569fd 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -105,5 +105,6 @@ The following table shows known good combinations of toolchain versions. | Rust 1.34 | ✗ | ✓ | | Rust 1.35 | ✗ | ✓ | | Rust 1.36 | ✗ | ✓ | +| Rust 1.37 | ✗ | ✓ | Note that the compatibility policy for this feature might change in the future. From 29e4a428fa7db7f9228448cb85a561916638be78 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Fri, 6 Sep 2019 12:41:54 -0700 Subject: [PATCH 10/11] Include compiler-rt in the source tarball In #60981 we switched to using src/llvm-project/compiler-rt inside compiler-builtins rather than a separate copy of it. In order to have the "c" feature turn on in builds from the source tarball, we need to include that path in its creation. fixes #64239 --- src/bootstrap/dist.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index bd012a887c26e..552965863d10a 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -808,6 +808,7 @@ fn copy_src_dirs(builder: &Builder<'_>, src_dirs: &[&str], exclude_dirs: &[&str] "llvm-project/lld", "llvm-project\\lld", "llvm-project/lldb", "llvm-project\\lldb", "llvm-project/llvm", "llvm-project\\llvm", + "llvm-project/compiler-rt", "llvm-project\\compiler-rt", ]; if spath.contains("llvm-project") && !spath.ends_with("llvm-project") && !LLVM_PROJECTS.iter().any(|path| spath.contains(path)) From e0862784a1550dc1e07249c8967179a09b091141 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 9 Sep 2019 20:32:03 +0200 Subject: [PATCH 11/11] Update LLVM submodule --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 48818e9f5d0f2..71fe7ec06b85f 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 48818e9f5d0f2d5978a9b43ad1a2e8d0b83f6aa0 +Subproject commit 71fe7ec06b85f612fc0e4eb4134c7a7d0f23fac5