From e608549224fc8b108dd3f459d9c2ac7d3b113e96 Mon Sep 17 00:00:00 2001 From: nathanwhit Date: Wed, 11 Sep 2019 22:05:26 -0400 Subject: [PATCH 01/24] Filter out stmts made for the redundant_semicolon lint when pretty-printing --- src/libsyntax/print/pprust.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5d8498f8b5d2..ff3fda8ff930 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1651,9 +1651,18 @@ impl<'a> State<'a> { } } ast::StmtKind::Semi(ref expr) => { - self.space_if_not_bol(); - self.print_expr_outer_attr_style(expr, false); - self.s.word(";"); + match expr.node { + // Filter out empty `Tup` exprs created for the `redundant_semicolon` + // lint, as they shouldn't be visible and interact poorly + // with proc macros. + ast::ExprKind::Tup(ref exprs) if exprs.is_empty() + && expr.attrs.is_empty() => (), + _ => { + self.space_if_not_bol(); + self.print_expr_outer_attr_style(expr, false); + self.s.word(";"); + } + } } ast::StmtKind::Mac(ref mac) => { let (ref mac, style, ref attrs) = **mac; From 96526d401113c28b765d40c99d4d28f499c6b512 Mon Sep 17 00:00:00 2001 From: nathanwhit Date: Wed, 11 Sep 2019 22:10:52 -0400 Subject: [PATCH 02/24] Add test for redundant_semicolon lint interaction with proc macro attrs --- .../redundant-semi-proc-macro-def.rs | 11 ++++++++++ .../redundant-semi-proc-macro.rs | 19 +++++++++++++++++ .../redundant-semi-proc-macro.stderr | 21 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs create mode 100644 src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs create mode 100644 src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr diff --git a/src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs b/src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs new file mode 100644 index 000000000000..ca741393aec0 --- /dev/null +++ b/src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs @@ -0,0 +1,11 @@ +// no-prefer-dynamic +#![crate_type="proc-macro"] +#![crate_name="redundant_semi_proc_macro"] +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn should_preserve_spans(_attr: TokenStream, item: TokenStream) -> TokenStream { + eprintln!("{:?}", item); + item +} diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs new file mode 100644 index 000000000000..f207b235735f --- /dev/null +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs @@ -0,0 +1,19 @@ +// aux-build:redundant-semi-proc-macro-def.rs + +#![deny(redundant_semicolon)] +extern crate redundant_semi_proc_macro; +use redundant_semi_proc_macro::should_preserve_spans; + +#[should_preserve_spans] +fn span_preservation() { + let tst = 123;; //~ ERROR unnecessary trailing semicolon + match tst { + // Redundant semicolons are parsed as empty tuple exprs + // for the lint, so ensure the lint doesn't affect + // empty tuple exprs explicitly in source. + 123 => (), + _ => () + };;; //~ ERROR unnecessary trailing semicolons +} + +fn main() {} diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr new file mode 100644 index 000000000000..5f289c0914d6 --- /dev/null +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -0,0 +1,21 @@ +TokenStream [Ident { ident: "fn", span: #0 bytes(197..199) }, Ident { ident: "span_preservation", span: #0 bytes(200..217) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(217..219) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(227..230) }, Ident { ident: "tst", span: #0 bytes(231..234) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(235..236) }, Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(237), hi: BytePos(240), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(240..241) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(241..242) }, Ident { ident: "match", span: #0 bytes(288..293) }, Ident { ident: "tst", span: #0 bytes(294..297) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(482), hi: BytePos(485), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(486..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(486..488) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(489..491) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(491..492) }, Ident { ident: "_", span: #0 bytes(501..502) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(503..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(503..505) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(506..508) }], span: #0 bytes(298..514) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(514..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(516..517) }], span: #0 bytes(221..561) }] +error: unnecessary trailing semicolon + --> $DIR/redundant-semi-proc-macro.rs:9:19 + | +LL | let tst = 123;; + | ^ help: remove this semicolon + | +note: lint level defined here + --> $DIR/redundant-semi-proc-macro.rs:3:9 + | +LL | #![deny(redundant_semicolon)] + | ^^^^^^^^^^^^^^^^^^^ + +error: unnecessary trailing semicolons + --> $DIR/redundant-semi-proc-macro.rs:16:7 + | +LL | };;; + | ^^ help: remove these semicolons + +error: aborting due to 2 previous errors + From 612ef5f518198448c43959a6416b9da2964f9167 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 12 Sep 2019 17:04:32 -0400 Subject: [PATCH 03/24] add new tests for re_rebalance_coherence --- ...]-foreign[foreign[t],local]-for-foreign.rs | 14 +++++++++++++ ...pl[t]-foreign[local]-for-fundamental[t].rs | 21 +++++++++++++++++++ .../coherence/impl[t]-foreign[local]-for-t.rs | 16 ++++++++++++++ .../impl[t]-foreign[local]-for-t.stderr | 11 ++++++++++ .../coherence/re-rebalance-coherence-rpass.rs | 14 ------------- 5 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr delete mode 100644 src/test/ui/coherence/re-rebalance-coherence-rpass.rs diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs new file mode 100644 index 000000000000..61f2637c0c29 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs @@ -0,0 +1,14 @@ +#![feature(re_rebalance_coherence)] + +// run-pass +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +impl Remote2, Local> for usize { } + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs new file mode 100644 index 000000000000..586b8de9e95c --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs @@ -0,0 +1,21 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// run-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Box { + // FIXME(#64412) -- this is expected to error +} + +impl Remote1 for &T { + // FIXME(#64412) -- this is expected to error +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs new file mode 100644 index 000000000000..6f35c6c9dbc8 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr new file mode 100644 index 000000000000..be7de8cccb46 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr @@ -0,0 +1,11 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[local]-for-t.rs:12:1 + | +LL | impl Remote1 for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/re-rebalance-coherence-rpass.rs b/src/test/ui/coherence/re-rebalance-coherence-rpass.rs deleted file mode 100644 index bacd3b89fad2..000000000000 --- a/src/test/ui/coherence/re-rebalance-coherence-rpass.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(dead_code)] -#![feature(re_rebalance_coherence)] - -// run-pass -// aux-build:re_rebalance_coherence_lib.rs - -extern crate re_rebalance_coherence_lib as lib; -use lib::*; - -struct Oracle; -impl Backend for Oracle {} -impl<'a, T:'a, Tab> QueryFragment for BatchInsert<'a, T, Tab> {} - -fn main() {} From e69d1b67b6603e0635c553eff693a0606d282d75 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Sep 2019 14:57:06 -0400 Subject: [PATCH 04/24] change to check-pass --- .../coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs | 2 +- .../ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs index 61f2637c0c29..54d4bf04a583 100644 --- a/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs +++ b/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs @@ -1,6 +1,6 @@ #![feature(re_rebalance_coherence)] -// run-pass +// check-pass // compile-flags:--crate-name=test // aux-build:coherence_lib.rs diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs index 586b8de9e95c..db671cb9bcab 100644 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs @@ -2,7 +2,7 @@ // compile-flags:--crate-name=test // aux-build:coherence_lib.rs -// run-pass +// check-pass extern crate coherence_lib as lib; use lib::*; From 194d357e03dcee73bfdb32a45175c97f4c3ce422 Mon Sep 17 00:00:00 2001 From: Charles Gleason Date: Tue, 3 Sep 2019 18:42:58 -0400 Subject: [PATCH 05/24] Document `From` trait for `LhsExpr` --- src/libsyntax/parse/parser/expr.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 5b9f0f1df671..c38b134154d6 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -66,6 +66,10 @@ pub(super) enum LhsExpr { } impl From>> for LhsExpr { + /// Converts `Some(attrs)` into `LhsExpr::AttributesParsed(attrs)` + /// and `None` into `LhsExpr::NotYetParsed`. + /// + /// This conversion does not allocate. fn from(o: Option>) -> Self { if let Some(attrs) = o { LhsExpr::AttributesParsed(attrs) @@ -76,6 +80,9 @@ impl From>> for LhsExpr { } impl From> for LhsExpr { + /// Converts the `expr: P` into `LhsExpr::AlreadyParsed(expr)`. + /// + /// This conversion does not allocate. fn from(expr: P) -> Self { LhsExpr::AlreadyParsed(expr) } From 3f004a1bc44859857f05a9f692a578124b3f3e01 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Tue, 17 Sep 2019 14:40:36 +0200 Subject: [PATCH 06/24] Fix re-rebalance coherence implementation for fundamental types Fixes #64412 --- src/librustc/traits/coherence.rs | 10 +++++++++- ...pl[t]-foreign[local]-for-fundamental[t].rs | 5 ++--- ...]-foreign[local]-for-fundamental[t].stderr | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index b6f0addd7710..bc6bcb1f76f9 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -378,7 +378,15 @@ fn orphan_check_trait_ref<'tcx>( // Let Ti be the first such type. // - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti) // - for input_ty in trait_ref.input_types() { + fn uncover_fundamental_ty(ty: Ty<'_>) -> Vec> { + if fundamental_ty(ty) { + ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(ty)).collect() + } else { + vec![ty] + } + } + + for input_ty in trait_ref.input_types().flat_map(uncover_fundamental_ty) { debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty); if ty_is_local(tcx, input_ty, in_crate) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs index db671cb9bcab..54425b6d708a 100644 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs @@ -2,7 +2,6 @@ // compile-flags:--crate-name=test // aux-build:coherence_lib.rs -// check-pass extern crate coherence_lib as lib; use lib::*; @@ -11,11 +10,11 @@ use std::rc::Rc; struct Local; impl Remote1 for Box { - // FIXME(#64412) -- this is expected to error + //~^ ERROR type parameter `T` must be used as the type parameter for some local type } impl Remote1 for &T { - // FIXME(#64412) -- this is expected to error + //~^ ERROR type parameter `T` must be used as the type parameter for some local type } fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr new file mode 100644 index 000000000000..7859665a7bb5 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:12:1 + | +LL | impl Remote1 for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:16:1 + | +LL | impl Remote1 for &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. From a9c38d9d01bd50b5a264cd62fd32cec37f006ab9 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Wed, 18 Sep 2019 22:14:33 +0200 Subject: [PATCH 07/24] Add more tests --- .../impl-foreign[foreign]-for-foreign.rs | 16 +++++++++++++++ .../impl-foreign[foreign]-for-foreign.stderr | 12 +++++++++++ .../impl-foreign[foreign]-for-local.rs | 16 +++++++++++++++ ...[t]-foreign[foreign]-for-fundamental[t].rs | 20 +++++++++++++++++++ ...foreign[foreign]-for-fundamental[t].stderr | 19 ++++++++++++++++++ .../impl[t]-foreign[foreign]-for-t.rs | 16 +++++++++++++++ .../impl[t]-foreign[foreign]-for-t.stderr | 11 ++++++++++ ...reign[fundamental[t],local]-for-foreign.rs | 20 +++++++++++++++++++ ...n[fundamental[t],local]-for-foreign.stderr | 19 ++++++++++++++++++ ...[t]-foreign[fundamental[t]]-for-foreign.rs | 20 +++++++++++++++++++ ...foreign[fundamental[t]]-for-foreign.stderr | 19 ++++++++++++++++++ ...eign[fundamental[t]]-for-fundamental[t].rs | 19 ++++++++++++++++++ ...[fundamental[t]]-for-fundamental[t].stderr | 19 ++++++++++++++++++ ...pl[t]-foreign[fundamental[t]]-for-local.rs | 17 ++++++++++++++++ .../impl[t]-foreign[fundamental[t]]-for-t.rs | 19 ++++++++++++++++++ ...pl[t]-foreign[fundamental[t]]-for-t.stderr | 19 ++++++++++++++++++ ...eign[local, fundamental[t]]-for-foreign.rs | 19 ++++++++++++++++++ .../impl[t]-foreign[local]-for-foreign.rs | 16 +++++++++++++++ .../impl[t]-foreign[local]-for-local.rs | 15 ++++++++++++++ .../impl[t]-foreign[t]-for-foreign.rs | 16 +++++++++++++++ .../impl[t]-foreign[t]-for-foreign.stderr | 11 ++++++++++ .../impl[t]-foreign[t]-for-fundamental.rs | 20 +++++++++++++++++++ .../impl[t]-foreign[t]-for-fundamental.stderr | 19 ++++++++++++++++++ .../coherence/impl[t]-foreign[t]-for-local.rs | 15 ++++++++++++++ .../ui/coherence/impl[t]-foreign[t]-for-t.rs | 16 +++++++++++++++ .../coherence/impl[t]-foreign[t]-for-t.stderr | 11 ++++++++++ 26 files changed, 439 insertions(+) create mode 100644 src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr create mode 100644 src/test/ui/coherence/impl-foreign[foreign]-for-local.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs new file mode 100644 index 000000000000..57738c64e377 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for f64 { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr new file mode 100644 index 000000000000..04e96f29230f --- /dev/null +++ b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr @@ -0,0 +1,12 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign[foreign]-for-foreign.rs:12:1 + | +LL | impl Remote1 for f64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs new file mode 100644 index 000000000000..33e85c164763 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Local { +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs new file mode 100644 index 000000000000..66a4d9d27346 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs @@ -0,0 +1,20 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, T> Remote1 for &'a T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr new file mode 100644 index 000000000000..2467097b1a8b --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:12:1 + | +LL | impl Remote1 for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:16:1 + | +LL | impl<'a, T> Remote1 for &'a T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs new file mode 100644 index 000000000000..0a67ebcbba44 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr new file mode 100644 index 000000000000..5c28406f113f --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr @@ -0,0 +1,11 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[foreign]-for-t.rs:12:1 + | +LL | impl Remote1 for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs new file mode 100644 index 000000000000..24e0f309c455 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs @@ -0,0 +1,20 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote2, Local> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, T> Remote2<&'a T, Local> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr new file mode 100644 index 000000000000..da670bcfc3fc --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t],local]-for-foreign.rs:12:1 + | +LL | impl Remote2, Local> for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t],local]-for-foreign.rs:16:1 + | +LL | impl<'a, T> Remote2<&'a T, Local> for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs new file mode 100644 index 000000000000..71598dae96ab --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs @@ -0,0 +1,20 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, T> Remote1<&'a T> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr new file mode 100644 index 000000000000..dd9702650795 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:12:1 + | +LL | impl Remote1> for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:16:1 + | +LL | impl<'a, T> Remote1<&'a T> for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs new file mode 100644 index 000000000000..7bf0306f29ba --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs @@ -0,0 +1,19 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl<'a, T> Remote1> for &'a T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} +impl<'a, T> Remote1<&'a T> for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr new file mode 100644 index 000000000000..eec57fccea76 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:12:1 + | +LL | impl<'a, T> Remote1> for &'a T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:15:1 + | +LL | impl<'a, T> Remote1<&'a T> for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs new file mode 100644 index 000000000000..54d577c74924 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs @@ -0,0 +1,17 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for Local {} + +impl<'a, T> Remote1<&'a T> for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs new file mode 100644 index 000000000000..7af929006ef7 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs @@ -0,0 +1,19 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} +impl<'a, T> Remote1<&'a T> for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr new file mode 100644 index 000000000000..e017c3ffe6c0 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:12:1 + | +LL | impl Remote1> for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:15:1 + | +LL | impl<'a, T> Remote1<&'a T> for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs new file mode 100644 index 000000000000..be0875d0110f --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs @@ -0,0 +1,19 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local2(Rc); + +impl Remote2> for u32 {} +impl<'a, T> Remote2 for u32 {} +impl Remote2, Box> for u32 {} +impl<'a, T> Remote2, &'a T> for u32 {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs new file mode 100644 index 000000000000..81cf3c3f6eca --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Rc {} +impl Remote1 for Vec> {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs new file mode 100644 index 000000000000..6b1d93cd9444 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs @@ -0,0 +1,15 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs new file mode 100644 index 000000000000..5e89c2077330 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr new file mode 100644 index 000000000000..5544729b5d64 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr @@ -0,0 +1,11 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-foreign.rs:12:1 + | +LL | impl Remote1 for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs new file mode 100644 index 000000000000..300a2c4d48a9 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs @@ -0,0 +1,20 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, A, B> Remote1 for &'a B { + //~^ ERROR type parameter `B` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr new file mode 100644 index 000000000000..be8cc29a6e5b --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:12:1 + | +LL | impl Remote1 for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `B` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:16:1 + | +LL | impl<'a, A, B> Remote1 for &'a B { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `B` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs new file mode 100644 index 000000000000..769147ea7eab --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs @@ -0,0 +1,15 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs new file mode 100644 index 000000000000..c8513380ff73 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr new file mode 100644 index 000000000000..de857afd20b1 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr @@ -0,0 +1,11 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-t.rs:12:1 + | +LL | impl Remote1 for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. From 31b301219f534090690674e43e05c3cbfd2d5005 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Wed, 18 Sep 2019 22:36:04 +0200 Subject: [PATCH 08/24] Split line to fix tidy --- src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs index 57738c64e377..b08fedc5e11c 100644 --- a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs +++ b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs @@ -10,7 +10,8 @@ use std::rc::Rc; struct Local; impl Remote1 for f64 { - //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types [E0117] + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] } fn main() {} From 8112f71fc91bc7618d91bb3180fe80b8fafe1069 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 19 Sep 2019 09:24:42 -0700 Subject: [PATCH 09/24] rustbuild: Turn down compression on exe installers The Windows dist builders are the slowest builders right now, and the distribution phase of them is enormously slow clocking in at around 20 minutes to build all the related installers. This commit starts to optimize these by turning down the compression level in the `exe` installers. These aren't super heavily used so there's no great need for them to be so ultra-compressed, so let's dial back the compression parameters to get closer to the rest of our xz archives. This brings the installer in line with the gz tarball installer locally, and also brings the compression settings on par with the rest of our xz installers. --- src/etc/installer/exe/rust.iss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/etc/installer/exe/rust.iss b/src/etc/installer/exe/rust.iss index c22d60b6c5df..70648beac38b 100644 --- a/src/etc/installer/exe/rust.iss +++ b/src/etc/installer/exe/rust.iss @@ -25,9 +25,9 @@ SourceDir=.\ OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD} DefaultDirName={sd}\Rust -Compression=lzma2/ultra -InternalCompressLevel=ultra -SolidCompression=true +Compression=lzma2/normal +InternalCompressLevel=normal +SolidCompression=no ChangesEnvironment=true ChangesAssociations=no From 1ab5593f951c07a6f0ed05fbbfe8f262863158a0 Mon Sep 17 00:00:00 2001 From: gaolei Date: Thu, 19 Sep 2019 15:13:40 +0800 Subject: [PATCH 10/24] factor out pluralisation remains after #64280 --- src/librustc/lint/builtin.rs | 4 ++-- src/librustc/middle/resolve_lifetime.rs | 4 ++-- src/librustc/traits/error_reporting.rs | 4 ++-- src/librustc/ty/error.rs | 2 +- src/librustc_lint/unused.rs | 22 ++++++++++++++------- src/librustc_resolve/check_unused.rs | 4 +++- src/librustc_resolve/resolve_imports.rs | 4 ++-- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/expr.rs | 4 ++-- src/librustc_typeck/check/method/suggest.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 4 ++-- src/librustc_typeck/check/pat.rs | 14 ++++++------- src/libsyntax/ext/tt/transcribe.rs | 5 +++-- src/libsyntax/parse/diagnostics.rs | 8 ++++---- src/libsyntax/parse/parser/path.rs | 7 +++---- src/libsyntax/parse/parser/ty.rs | 6 +++--- src/libsyntax_ext/format.rs | 3 ++- 17 files changed, 56 insertions(+), 45 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index dd290572d7bb..5906a6388a8b 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -7,7 +7,7 @@ use crate::lint::{LintPass, LateLintPass, LintArray}; use crate::middle::stability; use crate::session::Session; -use errors::{Applicability, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticBuilder, pluralise}; use syntax::ast; use syntax::source_map::Span; use syntax::symbol::Symbol; @@ -524,7 +524,7 @@ pub(crate) fn add_elided_lifetime_in_path_suggestion( }; db.span_suggestion( replace_span, - &format!("indicate the anonymous lifetime{}", if n >= 2 { "s" } else { "" }), + &format!("indicate the anonymous lifetime{}", pluralise!(n)), suggestion, Applicability::MachineApplicable ); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 8836a632a7ca..d833a34385b2 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -17,7 +17,7 @@ use crate::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt}; use crate::rustc::lint; use crate::session::Session; use crate::util::nodemap::{DefIdMap, FxHashMap, FxHashSet, HirIdMap, HirIdSet}; -use errors::{Applicability, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticBuilder, pluralise}; use rustc_macros::HashStable; use std::borrow::Cow; use std::cell::Cell; @@ -3047,7 +3047,7 @@ pub fn report_missing_lifetime_specifiers( span, E0106, "missing lifetime specifier{}", - if count > 1 { "s" } else { "" } + pluralise!(count) ) } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 03cc00d87e3c..0b06ec070381 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -33,7 +33,7 @@ use crate::ty::subst::Subst; use crate::ty::SubtypePredicate; use crate::util::nodemap::{FxHashMap, FxHashSet}; -use errors::{Applicability, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticBuilder, pluralise}; use std::fmt; use syntax::ast; use syntax::symbol::{sym, kw}; @@ -1186,7 +1186,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => format!("{} {}argument{}", arg_length, if distinct && arg_length > 1 { "distinct " } else { "" }, - if arg_length == 1 { "" } else { "s" }), + pluralise!(arg_length)) } }; diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 62910ec32049..5409cbc4129f 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -196,7 +196,7 @@ impl<'tcx> ty::TyS<'tcx> { let n = tcx.lift_to_global(&n).unwrap(); match n.try_eval_usize(tcx, ty::ParamEnv::empty()) { Some(n) => { - format!("array of {} element{}", n, if n != 1 { "s" } else { "" }).into() + format!("array of {} element{}", n, pluralise!(n)).into() } None => "array".into(), } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index c3975098351a..2d4af2f606a2 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -9,7 +9,7 @@ use lint::{LintPass, EarlyLintPass, LateLintPass}; use syntax::ast; use syntax::attr; -use syntax::errors::Applicability; +use syntax::errors::{Applicability, pluralise}; use syntax::feature_gate::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use syntax::print::pprust; use syntax::symbol::{kw, sym}; @@ -48,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { } let ty = cx.tables.expr_ty(&expr); - let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", false); + let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", 1); let mut fn_warned = false; let mut op_warned = false; @@ -135,7 +135,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { span: Span, descr_pre: &str, descr_post: &str, - plural: bool, + plural_len: usize, ) -> bool { if ty.is_unit() || cx.tcx.is_ty_uninhabited_from( cx.tcx.hir().get_module_parent(expr.hir_id), ty) @@ -143,13 +143,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { return true; } - let plural_suffix = if plural { "s" } else { "" }; + let plural_suffix = pluralise!(plural_len); match ty.sty { ty::Adt(..) if ty.is_box() => { let boxed_ty = ty.boxed_ty(); let descr_pre = &format!("{}boxed ", descr_pre); - check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural) + check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural_len) } ty::Adt(def, _) => { check_must_use_def(cx, def.did, span, descr_pre, descr_post) @@ -202,7 +202,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() { let descr_post = &format!(" in tuple element {}", i); let span = *spans.get(i).unwrap_or(&span); - if check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, plural) { + if check_must_use_ty( + cx, + ty, + expr, + span, + descr_pre, + descr_post, + plural_len + ) { has_emitted = true; } } @@ -216,7 +224,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { descr_pre, plural_suffix, ); - check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, true) + check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, n as usize + 1) } // Otherwise, we don't lint, to avoid false positives. _ => false, diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 96d44b4b4c0d..0d85be83e12e 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -26,6 +26,8 @@ use crate::Resolver; use crate::resolve_imports::ImportDirectiveSubclass; +use errors::pluralise; + use rustc::util::nodemap::NodeMap; use rustc::{lint, ty}; use rustc_data_structures::fx::FxHashSet; @@ -295,7 +297,7 @@ impl Resolver<'_> { }).collect::>(); span_snippets.sort(); let msg = format!("unused import{}{}", - if len > 1 { "s" } else { "" }, + pluralise!(len), if !span_snippets.is_empty() { format!(": {}", span_snippets.join(", ")) } else { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e77e8290f1fa..360343169bc3 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -11,7 +11,7 @@ use crate::{Resolver, ResolutionError, Segment, ModuleKind}; use crate::{names_to_string, module_to_string}; use crate::diagnostics::Suggestion; -use errors::Applicability; +use errors::{Applicability, pluralise}; use rustc_data_structures::ptr_key::PtrKey; use rustc::ty; @@ -728,7 +728,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let msg = format!( "unresolved import{} {}", - if paths.len() > 1 { "s" } else { "" }, + pluralise!(paths.len()), paths.join(", "), ); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 09e6b7690039..718d12484f74 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1346,7 +1346,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, E0191, "the value of the associated type{} {} must be specified", - if associated_types.len() == 1 { "" } else { "s" }, + pluralise!(associated_types.len()), names, ); let (suggest, potential_assoc_types_spans) = diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 56bd903040ab..ef3f40dfdd98 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -17,7 +17,7 @@ use crate::util::common::ErrorReported; use crate::util::nodemap::FxHashMap; use crate::astconv::AstConv as _; -use errors::{Applicability, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticBuilder, pluralise}; use syntax::ast; use syntax::symbol::{Symbol, kw, sym}; use syntax::source_map::Span; @@ -1178,7 +1178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { struct_span_err!(tcx.sess, span, E0063, "missing field{} {}{} in initializer of `{}`", - if remaining_fields.len() == 1 { "" } else { "s" }, + pluralise!(remaining_fields.len()), remaining_fields_names, truncated_fields_error, adt_ty) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 3e45b1e98d4e..74e4f28255b1 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -5,7 +5,7 @@ use crate::check::FnCtxt; use crate::middle::lang_items::FnOnceTraitLangItem; use crate::namespace::Namespace; use crate::util::nodemap::FxHashSet; -use errors::{Applicability, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticBuilder, pluralise}; use rustc::hir::{self, ExprKind, Node, QPath}; use rustc::hir::def::{Res, DefKind}; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; @@ -560,7 +560,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let help = format!("{an}other candidate{s} {were} found in the following \ trait{s}, perhaps add a `use` for {one_of_them}:", an = if candidates.len() == 1 {"an" } else { "" }, - s = if candidates.len() == 1 { "" } else { "s" }, + s = pluralise!(candidates.len()), were = if candidates.len() == 1 { "was" } else { "were" }, one_of_them = if candidates.len() == 1 { "it" diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1197160fa950..bd6586aa0777 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -88,7 +88,7 @@ pub mod intrinsic; mod op; use crate::astconv::{AstConv, PathSeg}; -use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId, pluralise}; use rustc::hir::{self, ExprKind, GenericArg, ItemKind, Node, PatKind, QPath}; use rustc::hir::def::{CtorOf, Res, DefKind}; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; @@ -4843,5 +4843,5 @@ fn fatally_break_rust(sess: &Session) { } fn potentially_plural_count(count: usize, word: &str) -> String { - format!("{} {}{}", count, word, if count == 1 { "" } else { "s" }) + format!("{} {}{}", count, word, pluralise!(count)) } diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 8502b89de146..d93a4052cd39 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1,6 +1,6 @@ use crate::check::FnCtxt; use crate::util::nodemap::FxHashMap; -use errors::{Applicability, DiagnosticBuilder}; +use errors::{Applicability, DiagnosticBuilder, pluralise}; use rustc::hir::{self, PatKind, Pat, HirId}; use rustc::hir::def::{Res, DefKind, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; @@ -684,8 +684,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn e0023(&self, pat_span: Span, res: Res, subpats: &'tcx [P], fields: &[ty::FieldDef]) { - let subpats_ending = if subpats.len() == 1 { "" } else { "s" }; - let fields_ending = if fields.len() == 1 { "" } else { "s" }; + let subpats_ending = pluralise!(subpats.len()); + let fields_ending = pluralise!(fields.len()); let res_span = self.tcx.def_span(res.def_id()); struct_span_err!( self.tcx.sess, @@ -1103,10 +1103,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0527, "pattern requires {} element{} but array has {}", min_len, - if min_len != 1 { "s" } else { "" }, + pluralise!(min_len), size, ) - .span_label(span, format!("expected {} element{}", size, if size != 1 { "s" } else { "" })) + .span_label(span, format!("expected {} element{}", size, pluralise!(size))) .emit(); } @@ -1117,14 +1117,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0528, "pattern requires at least {} element{} but array has {}", min_len, - if min_len != 1 { "s" } else { "" }, + pluralise!(min_len), size, ).span_label( span, format!( "pattern cannot match array of {} element{}", size, - if size != 1 { "s" } else { "" }, + pluralise!(size), ), ).emit(); } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 23735727fe8c..f9c07e3a2e4f 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -8,6 +8,7 @@ use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use smallvec::{smallvec, SmallVec}; +use errors::pluralise; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use syntax_pos::hygiene::{ExpnId, Transparency}; @@ -348,10 +349,10 @@ impl LockstepIterSize { "meta-variable `{}` repeats {} time{}, but `{}` repeats {} time{}", l_id, l_len, - if l_len != 1 { "s" } else { "" }, + pluralise!(l_len), r_id, r_len, - if r_len != 1 { "s" } else { "" }, + pluralise!(r_len), ); LockstepIterSize::Contradiction(msg) } diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index b74f2492c351..2d7f4f71ca4e 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -11,7 +11,7 @@ use crate::ptr::P; use crate::symbol::{kw, sym}; use crate::ThinVec; use crate::util::parser::AssocOp; -use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId, pluralise}; use rustc_data_structures::fx::FxHashSet; use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError}; use log::{debug, trace}; @@ -532,15 +532,15 @@ impl<'a> Parser<'a> { self.eat_to_tokens(&[&end]); let span = lo.until(self.token.span); - let plural = number_of_gt > 1 || number_of_shr >= 1; + let total_num_of_gt = number_of_gt + number_of_shr * 2; self.diagnostic() .struct_span_err( span, - &format!("unmatched angle bracket{}", if plural { "s" } else { "" }), + &format!("unmatched angle bracket{}", pluralise!(total_num_of_gt)), ) .span_suggestion( span, - &format!("remove extra angle bracket{}", if plural { "s" } else { "" }), + &format!("remove extra angle bracket{}", pluralise!(total_num_of_gt)), String::new(), Applicability::MachineApplicable, ) diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs index d4b13cc2e012..dcd3c6480174 100644 --- a/src/libsyntax/parse/parser/path.rs +++ b/src/libsyntax/parse/parser/path.rs @@ -9,7 +9,7 @@ use crate::symbol::kw; use std::mem; use log::debug; -use errors::{Applicability}; +use errors::{Applicability, pluralise}; /// Specifies how to parse a path. #[derive(Copy, Clone, PartialEq)] @@ -347,20 +347,19 @@ impl<'a> Parser<'a> { let span = lo.with_hi( lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count) ); - let plural = snapshot.unmatched_angle_bracket_count > 1; self.diagnostic() .struct_span_err( span, &format!( "unmatched angle bracket{}", - if plural { "s" } else { "" } + pluralise!(snapshot.unmatched_angle_bracket_count) ), ) .span_suggestion( span, &format!( "remove extra angle bracket{}", - if plural { "s" } else { "" } + pluralise!(snapshot.unmatched_angle_bracket_count) ), String::new(), Applicability::MachineApplicable, diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index 465e31ac57e6..5697edd8e486 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -11,7 +11,7 @@ use crate::symbol::{kw}; use rustc_target::spec::abi::Abi; -use errors::{Applicability}; +use errors::{Applicability, pluralise}; /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT`, /// `IDENT<::AssocTy>`. @@ -397,7 +397,7 @@ impl<'a> Parser<'a> { } if !negative_bounds.is_empty() || was_negative { - let plural = negative_bounds.len() > 1; + let negative_bounds_len = negative_bounds.len(); let last_span = negative_bounds.last().map(|sp| *sp); let mut err = self.struct_span_err( negative_bounds, @@ -420,7 +420,7 @@ impl<'a> Parser<'a> { } err.span_suggestion_hidden( bound_list, - &format!("remove the trait bound{}", if plural { "s" } else { "" }), + &format!("remove the trait bound{}", pluralise!(negative_bounds_len)), new_bound_list, Applicability::MachineApplicable, ); diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 46c7cbb83de9..26455df17b89 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -5,6 +5,7 @@ use fmt_macros as parse; use errors::DiagnosticBuilder; use errors::Applicability; +use errors::pluralise; use syntax::ast; use syntax::ext::base::{self, *}; @@ -299,7 +300,7 @@ impl<'a, 'b> Context<'a, 'b> { &format!( "{} positional argument{} in format string, but {}", count, - if count != 1 { "s" } else { "" }, + pluralise!(count), self.describe_num_args(), ), ); From fde8cfe130db3826b88247318551d34d2bb63276 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 19 Sep 2019 09:24:42 -0700 Subject: [PATCH 11/24] rustbuild: Turn down compression on msi installers This is the same as #64615 except applied to our MSI installers. The same fix is applied effectively bringing these installers in line with the gz tarball installers, which are about 3x faster to produce locally and likely much faster to produce on CI. --- src/etc/installer/msi/rust.wxs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/installer/msi/rust.wxs b/src/etc/installer/msi/rust.wxs index a471ccc6f5b4..a2e378f7b1db 100644 --- a/src/etc/installer/msi/rust.wxs +++ b/src/etc/installer/msi/rust.wxs @@ -152,7 +152,7 @@ - + From 255dd3ff42aecdc36da800e5bbfe0c09e83fa066 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 19 Sep 2019 11:22:55 -0700 Subject: [PATCH 12/24] rustbuild: Improve output of `dist` step * Pass `/Q` to `iscc` on Windows to supress the thousands of lines of output about compressing documentation. * Print out what's happening before long steps * Use `timeit` to print out timing information for long-running installer assemblies. --- src/bootstrap/dist.rs | 66 ++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 076bcd878df7..50b20763c43d 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -18,7 +18,7 @@ use build_helper::{output, t}; use crate::{Compiler, Mode, LLVM_TOOLS}; use crate::channel; -use crate::util::{is_dylib, exe}; +use crate::util::{is_dylib, exe, timeit}; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::compile; use crate::tool::{self, Tool}; @@ -91,14 +91,15 @@ impl Step for Docs { let name = pkgname(builder, "rust-docs"); - builder.info(&format!("Dist docs ({})", host)); if !builder.config.docs { - builder.info("\tskipping - docs disabled"); return distdir(builder).join(format!("{}-{}.tar.gz", name, host)); } builder.default_doc(None); + builder.info(&format!("Dist docs ({})", host)); + let _time = timeit(builder); + let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); @@ -151,9 +152,7 @@ impl Step for RustcDocs { let name = pkgname(builder, "rustc-docs"); - builder.info(&format!("Dist compiler docs ({})", host)); if !builder.config.compiler_docs { - builder.info("\tskipping - compiler docs disabled"); return distdir(builder).join(format!("{}-{}.tar.gz", name, host)); } @@ -179,6 +178,9 @@ impl Step for RustcDocs { .arg("--component-name=rustc-docs") .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--bulk-dirs=share/doc/rust/html"); + + builder.info(&format!("Dist compiler docs ({})", host)); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); @@ -350,6 +352,7 @@ impl Step for Mingw { } builder.info(&format!("Dist mingw ({})", host)); + let _time = timeit(builder); let name = pkgname(builder, "rust-mingw"); let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); @@ -403,7 +406,6 @@ impl Step for Rustc { let compiler = self.compiler; let host = self.compiler.host; - builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host)); let name = pkgname(builder, "rustc"); let image = tmpdir(builder).join(format!("{}-{}-image", name, host)); let _ = fs::remove_dir_all(&image); @@ -460,6 +462,9 @@ impl Step for Rustc { .arg(format!("--package-name={}-{}", name, host)) .arg("--component-name=rustc") .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host)); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); builder.remove_dir(&overlay); @@ -662,8 +667,6 @@ impl Step for Std { let target = self.target; let name = pkgname(builder, "rust-std"); - builder.info(&format!("Dist std stage{} ({} -> {})", - compiler.stage, &compiler.host, target)); // The only true set of target libraries came from the build triple, so // let's reduce redundant work by only producing archives from that host. @@ -714,6 +717,10 @@ impl Step for Std { .arg(format!("--package-name={}-{}", name, target)) .arg(format!("--component-name=rust-std-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info(&format!("Dist std stage{} ({} -> {})", + compiler.stage, &compiler.host, target)); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); distdir(builder).join(format!("{}-{}.tar.gz", name, target)) @@ -754,11 +761,9 @@ impl Step for Analysis { let compiler = self.compiler; let target = self.target; assert!(builder.config.extended); - builder.info("Dist analysis"); let name = pkgname(builder, "rust-analysis"); if &compiler.host != builder.config.build { - builder.info("\tskipping, not a build host"); return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); } @@ -786,6 +791,9 @@ impl Step for Analysis { .arg(format!("--package-name={}-{}", name, target)) .arg(format!("--component-name=rust-analysis-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info("Dist analysis"); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); distdir(builder).join(format!("{}-{}.tar.gz", name, target)) @@ -874,8 +882,6 @@ impl Step for Src { /// Creates the `rust-src` installer component fn run(self, builder: &Builder<'_>) -> PathBuf { - builder.info("Dist src"); - let name = pkgname(builder, "rust-src"); let image = tmpdir(builder).join(format!("{}-image", name)); let _ = fs::remove_dir_all(&image); @@ -930,6 +936,9 @@ impl Step for Src { .arg(format!("--package-name={}", name)) .arg("--component-name=rust-src") .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info("Dist src"); + let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); @@ -957,8 +966,6 @@ impl Step for PlainSourceTarball { /// Creates the plain source tarball fn run(self, builder: &Builder<'_>) -> PathBuf { - builder.info("Create plain source tarball"); - // Make sure that the root folder of tarball has the correct name let plain_name = format!("{}-src", pkgname(builder, "rustc")); let plain_dst_src = tmpdir(builder).join(&plain_name); @@ -1020,6 +1027,9 @@ impl Step for PlainSourceTarball { .arg("--output").arg(&tarball) .arg("--work-dir=.") .current_dir(tmpdir(builder)); + + builder.info("Create plain source tarball"); + let _time = timeit(builder); builder.run(&mut cmd); distdir(builder).join(&format!("{}.tar.gz", plain_name)) } @@ -1073,7 +1083,6 @@ impl Step for Cargo { let compiler = self.compiler; let target = self.target; - builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/cargo"); let etc = src.join("src/etc"); let release_num = builder.release_num("cargo"); @@ -1126,6 +1135,9 @@ impl Step for Cargo { .arg(format!("--package-name={}-{}", name, target)) .arg("--component-name=cargo") .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); distdir(builder).join(format!("{}-{}.tar.gz", name, target)) } @@ -1161,7 +1173,6 @@ impl Step for Rls { let target = self.target; assert!(builder.config.extended); - builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/rls"); let release_num = builder.release_num("rls"); let name = pkgname(builder, "rls"); @@ -1210,6 +1221,8 @@ impl Step for Rls { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=rls-preview"); + builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } @@ -1245,7 +1258,6 @@ impl Step for Clippy { let target = self.target; assert!(builder.config.extended); - builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/clippy"); let release_num = builder.release_num("clippy"); let name = pkgname(builder, "clippy"); @@ -1299,6 +1311,8 @@ impl Step for Clippy { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=clippy-preview"); + builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } @@ -1334,7 +1348,6 @@ impl Step for Miri { let target = self.target; assert!(builder.config.extended); - builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/miri"); let release_num = builder.release_num("miri"); let name = pkgname(builder, "miri"); @@ -1389,6 +1402,8 @@ impl Step for Miri { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=miri-preview"); + builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } @@ -1423,7 +1438,6 @@ impl Step for Rustfmt { let compiler = self.compiler; let target = self.target; - builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target)); let src = builder.src.join("src/tools/rustfmt"); let release_num = builder.release_num("rustfmt"); let name = pkgname(builder, "rustfmt"); @@ -1476,6 +1490,8 @@ impl Step for Rustfmt { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--component-name=rustfmt-preview"); + builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target)); + let _time = timeit(builder); builder.run(&mut cmd); Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } @@ -1576,6 +1592,7 @@ impl Step for Extended { input_tarballs.push(tarball); } + builder.info("building combined installer"); let mut cmd = rust_installer(builder); cmd.arg("combine") .arg("--product-name=Rust") @@ -1587,7 +1604,9 @@ impl Step for Extended { .arg("--legacy-manifest-dirs=rustlib,cargo") .arg("--input-tarballs").arg(input_tarballs) .arg("--non-installed-overlay").arg(&overlay); + let time = timeit(&builder); builder.run(&mut cmd); + drop(time); let mut license = String::new(); license += &builder.read(&builder.src.join("COPYRIGHT")); @@ -1643,6 +1662,7 @@ impl Step for Extended { }; if target.contains("apple-darwin") { + builder.info("building pkg installer"); let pkg = tmp.join("pkg"); let _ = fs::remove_dir_all(&pkg); @@ -1692,6 +1712,7 @@ impl Step for Extended { pkgname(builder, "rust"), target))) .arg("--package-path").arg(&pkg); + let _time = timeit(builder); builder.run(&mut cmd); } @@ -1742,14 +1763,18 @@ impl Step for Extended { builder.create(&exe.join("LICENSE.txt"), &license); // Generate exe installer + builder.info("building `exe` installer with `iscc`"); let mut cmd = Command::new("iscc"); cmd.arg("rust.iss") + .arg("/Q") .current_dir(&exe); if target.contains("windows-gnu") { cmd.arg("/dMINGW"); } add_env(builder, &mut cmd, target); + let time = timeit(builder); builder.run(&mut cmd); + drop(time); builder.install(&exe.join(format!("{}-{}.exe", pkgname(builder, "rust"), target)), &distdir(builder), 0o755); @@ -1914,6 +1939,7 @@ impl Step for Extended { builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644); builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644); + builder.info(&format!("building `msi` installer with {:?}", light)); let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target); let mut cmd = Command::new(&light); cmd.arg("-nologo") @@ -1946,6 +1972,7 @@ impl Step for Extended { // ICE57 wrongly complains about the shortcuts cmd.arg("-sice:ICE57"); + let _time = timeit(builder); builder.run(&mut cmd); if !builder.config.dry_run { @@ -2114,6 +2141,7 @@ impl Step for LlvmTools { } builder.info(&format!("Dist LlvmTools ({})", target)); + let _time = timeit(builder); let src = builder.src.join("src/llvm-project/llvm"); let name = pkgname(builder, "llvm-tools"); From 3db2c13d893865e8e6929d5259bbac7d89a7ba06 Mon Sep 17 00:00:00 2001 From: Erin Power Date: Thu, 19 Sep 2019 21:53:40 +0200 Subject: [PATCH 13/24] Add Compatibility Notes to RELEASES.md for 1.38.0 --- RELEASES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index d634feba33ac..ecf49278f4b5 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -68,6 +68,13 @@ Misc - [`rustc` will now warn about some incorrect uses of `mem::{uninitialized, zeroed}` that are known to cause undefined behaviour.][63346] +Compatibility Notes +------------------- +- Unfortunately the [`x86_64-unknown-uefi` platform can not be built][62785] + with rustc 1.39.0. +- The [`armv7-unknown-linux-gnueabihf` platform is also known to have + issues][62896] for certain crates such as libc. + [60260]: https://github.com/rust-lang/rust/pull/60260/ [61457]: https://github.com/rust-lang/rust/pull/61457/ [61491]: https://github.com/rust-lang/rust/pull/61491/ @@ -79,7 +86,9 @@ Misc [62735]: https://github.com/rust-lang/rust/pull/62735/ [62766]: https://github.com/rust-lang/rust/pull/62766/ [62784]: https://github.com/rust-lang/rust/pull/62784/ +[62785]: https://github.com/rust-lang/rust/issues/62785/ [62814]: https://github.com/rust-lang/rust/pull/62814/ +[62896]: https://github.com/rust-lang/rust/issues/62896/ [63000]: https://github.com/rust-lang/rust/pull/63000/ [63056]: https://github.com/rust-lang/rust/pull/63056/ [63107]: https://github.com/rust-lang/rust/pull/63107/ From e625f62c517b9546df0d3e8f48bbd07c2a31724a Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 19 Sep 2019 18:33:22 -0700 Subject: [PATCH 14/24] Support run-fail ui tests --- src/tools/compiletest/src/common.rs | 2 ++ src/tools/compiletest/src/header.rs | 5 +++++ src/tools/compiletest/src/runtest.rs | 22 ++++++++++++++++++---- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index edb9eb7d860e..2358a065d62d 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -100,6 +100,7 @@ pub enum PassMode { Check, Build, Run, + RunFail, } impl FromStr for PassMode { @@ -120,6 +121,7 @@ impl fmt::Display for PassMode { PassMode::Check => "check", PassMode::Build => "build", PassMode::Run => "run", + PassMode::RunFail => "run-fail", }; fmt::Display::fmt(s, f) } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 48dd68d0f61e..df56448dd225 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -610,6 +610,11 @@ impl TestProps { panic!("`run-pass` header is only supported in UI tests") } Some(PassMode::Run) + } else if config.parse_name_directive(ln, "run-fail") { + if config.mode != Mode::Ui { + panic!("`run-fail` header is only supported in UI tests") + } + Some(PassMode::RunFail) } else { None }; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index baed27dd1515..ea31f37c7a52 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -326,6 +326,14 @@ impl<'test> TestCx<'test> { self.props.pass_mode(self.config) } + fn should_run(&self) -> bool { + let pass_mode = self.pass_mode(); + match self.config.mode { + Ui => pass_mode == Some(PassMode::Run) || pass_mode == Some(PassMode::RunFail), + mode => panic!("unimplemented for mode {:?}", mode), + } + } + fn should_run_successfully(&self) -> bool { let pass_mode = self.pass_mode(); match self.config.mode { @@ -1534,7 +1542,7 @@ impl<'test> TestCx<'test> { fn compile_test(&self) -> ProcRes { // Only use `make_exe_name` when the test ends up being executed. let will_execute = match self.config.mode { - Ui => self.should_run_successfully(), + Ui => self.should_run(), Incremental => self.revision.unwrap().starts_with("r"), RunFail | RunPassValgrind | MirOpt | DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb | DebugInfoLldb => true, @@ -3107,7 +3115,7 @@ impl<'test> TestCx<'test> { let expected_errors = errors::load_errors(&self.testpaths.file, self.revision); - if self.should_run_successfully() { + if self.should_run() { let proc_res = self.exec_compiled_test(); let run_output_errors = if self.props.check_run_results { self.load_compare_outputs(&proc_res, TestOutput::Run, explicit) @@ -3120,8 +3128,14 @@ impl<'test> TestCx<'test> { &proc_res, ); } - if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); + if self.should_run_successfully() { + if !proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &proc_res); + } + } else { + if proc_res.status.success() { + self.fatal_proc_rec("test run succeeded!", &proc_res); + } } } From 78ff1105f9a6159a89e10b0797224df1ca6ca868 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Wed, 11 Sep 2019 17:13:34 -0700 Subject: [PATCH 15/24] Spawn one subprocess per unit test --- src/libtest/lib.rs | 271 +++++++++++++++++++++++++++++++++++-------- src/libtest/tests.rs | 14 +-- 2 files changed, 228 insertions(+), 57 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 09d5fcc89520..fab1452cb7be 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -21,7 +21,8 @@ #![unstable(feature = "test", issue = "50297")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] #![feature(asm)] -#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc, rustc_private))] +#![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))] +#![feature(rustc_private)] #![feature(nll)] #![feature(set_stdio)] #![feature(panic_unwind)] @@ -56,15 +57,16 @@ use std::any::Any; use std::borrow::Cow; use std::cmp; use std::collections::BTreeMap; +use std::convert::{TryFrom, TryInto}; use std::env; use std::fmt; use std::fs::File; use std::io; use std::io::prelude::*; -use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo}; use std::path::PathBuf; use std::process; -use std::process::Termination; +use std::process::{Command, Termination}; use std::sync::mpsc::{channel, Sender}; use std::sync::{Arc, Mutex}; use std::thread; @@ -76,13 +78,15 @@ mod tests; const TEST_WARN_TIMEOUT_S: u64 = 60; const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in quiet mode +const SECONDARY_TEST_INVOKER_VAR: &'static str = "__RUST_TEST_INVOKE"; + // to be used by rustc to compile tests in libtest pub mod test { pub use crate::{ assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static, - Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, ShouldPanic, - StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, TestOpts, - TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk, + Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, RunStrategy, + ShouldPanic, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, + TestOpts, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk, }; } @@ -275,6 +279,19 @@ impl Options { // The default console test runner. It accepts the command line // arguments and a vector of test_descs. pub fn test_main(args: &[String], tests: Vec, options: Option) { + // If we're being run in SpawnedSecondary mode, run the test here. run_test + // will then exit the process. + if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) { + let test = tests + .into_iter() + .filter(|test| test.desc.name.as_slice() == name) + .next() + .expect("couldn't find a test with the provided name"); + let opts = parse_opts(&[]).unwrap().unwrap(); + run_test(&opts, false, test, RunStrategy::SpawnedSecondary, Concurrent::No); + unreachable!(); + } + let mut opts = match parse_opts(args) { Some(Ok(o)) => o, Some(Err(msg)) => { @@ -677,6 +694,41 @@ pub enum TestResult { unsafe impl Send for TestResult {} +// Return codes for TestResult. +// Start somewhere other than 0 so we know the return code means what we think +// it means. +const TR_OK: i32 = 50; +const TR_FAILED: i32 = 51; +const TR_IGNORED: i32 = 52; +const TR_ALLOWED_FAIL: i32 = 53; + +impl TryFrom for i32 { + type Error = &'static str; + fn try_from(val: TestResult) -> Result { + Ok(match val { + TrOk => TR_OK, + TrFailed => TR_FAILED, + TrIgnored => TR_IGNORED, + TrAllowedFail => TR_ALLOWED_FAIL, + TrFailedMsg(..) | + TrBench(..) => return Err("can't convert variant to i32"), + }) + } +} + +impl TryFrom for TestResult { + type Error = &'static str; + fn try_from(val: i32) -> Result { + Ok(match val { + TR_OK => TrOk, + TR_FAILED => TrFailed, + TR_IGNORED => TrIgnored, + TR_ALLOWED_FAIL => TrAllowedFail, + _ => return Err("unrecognized return code"), + }) + } +} + enum OutputLocation { Pretty(Box), Raw(T), @@ -1021,6 +1073,33 @@ impl Write for Sink { } } +#[derive(Clone)] +pub enum RunStrategy { + /// Runs the test in the current process, and sends the result back over the + /// supplied channel. + InProcess(Sender), + + /// Spawns a subprocess to run the test, and sends the result back over the + /// supplied channel. Requires argv[0] to exist and point to the binary + /// that's currently running. + SpawnPrimary(Sender), + + /// Runs the test in the current process, then exits the process. + /// Prints to stdout the custom result format that the parent process + /// expects in SpawnPrimary mode. + SpawnedSecondary, +} + +impl RunStrategy { + fn monitor_ch(self) -> Option> { + match self { + RunStrategy::InProcess(ch) => Some(ch), + RunStrategy::SpawnPrimary(ch) => Some(ch), + RunStrategy::SpawnedSecondary => None, + } + } +} + pub fn run_tests(opts: &TestOpts, tests: Vec, mut callback: F) -> io::Result<()> where F: FnMut(TestEvent) -> io::Result<()>, @@ -1068,6 +1147,12 @@ where let mut pending = 0; let (tx, rx) = channel::(); + // TODO + let run_strategy = if true { + RunStrategy::SpawnPrimary(tx) + } else { + RunStrategy::InProcess(tx) + }; let mut running_tests: TestMap = HashMap::default(); @@ -1104,7 +1189,7 @@ where while !remaining.is_empty() { let test = remaining.pop().unwrap(); callback(TeWait(test.desc.clone()))?; - run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::No); + run_test(opts, !opts.run_tests, test, run_strategy.clone(), Concurrent::No); let (test, result, stdout) = rx.recv().unwrap(); callback(TeResult(test, result, stdout))?; } @@ -1115,7 +1200,7 @@ where let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S); running_tests.insert(test.desc.clone(), timeout); callback(TeWait(test.desc.clone()))?; //here no pad - run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::Yes); + run_test(opts, !opts.run_tests, test, run_strategy.clone(), Concurrent::Yes); pending += 1; } @@ -1147,7 +1232,7 @@ where // All benchmarks run at the end, in serial. for b in filtered_benchs { callback(TeWait(b.desc.clone()))?; - run_test(opts, false, b, tx.clone(), Concurrent::No); + run_test(opts, false, b, run_strategy.clone(), Concurrent::No); let (test, result, stdout) = rx.recv().unwrap(); callback(TeResult(test, result, stdout))?; } @@ -1374,7 +1459,7 @@ pub fn run_test( opts: &TestOpts, force_ignore: bool, test: TestDescAndFn, - monitor_ch: Sender, + strategy: RunStrategy, concurrency: Concurrent, ) { let TestDescAndFn { desc, testfn } = test; @@ -1384,44 +1469,125 @@ pub fn run_test( && desc.should_panic != ShouldPanic::No; if force_ignore || desc.ignore || ignore_because_panic_abort { - monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap(); + match strategy { + RunStrategy::InProcess(tx) | RunStrategy::SpawnPrimary(tx) => { + tx.send((desc, TrIgnored, Vec::new())).unwrap(); + } + RunStrategy::SpawnedSecondary => panic!(), + } return; } fn run_test_inner( desc: TestDesc, - monitor_ch: Sender, nocapture: bool, + strategy: RunStrategy, testfn: Box, concurrency: Concurrent, ) { // Buffer for capturing standard I/O let data = Arc::new(Mutex::new(Vec::new())); - let data2 = data.clone(); let name = desc.name.clone(); let runtest = move || { - let oldio = if !nocapture { - Some(( - io::set_print(Some(Box::new(Sink(data2.clone())))), - io::set_panic(Some(Box::new(Sink(data2)))), - )) - } else { - None - }; + // TODO split into functions + match strategy { + RunStrategy::InProcess(monitor_ch) => { + let oldio = if !nocapture { + Some(( + io::set_print(Some(Box::new(Sink(data.clone())))), + io::set_panic(Some(Box::new(Sink(data.clone())))), + )) + } else { + None + }; + + let result = catch_unwind(AssertUnwindSafe(testfn)); + + if let Some((printio, panicio)) = oldio { + io::set_print(printio); + io::set_panic(panicio); + } - let result = catch_unwind(AssertUnwindSafe(testfn)); + let test_result = match result { + Ok(()) => calc_result(&desc, Ok(())), + Err(e) => calc_result(&desc, Err(e.as_ref())), + }; + let stdout = data.lock().unwrap().to_vec(); + monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); + } - if let Some((printio, panicio)) = oldio { - io::set_print(printio); - io::set_panic(panicio); - }; + RunStrategy::SpawnPrimary(monitor_ch) => { + let (result, test_output) = (|| { + let args = env::args().collect::>(); + let current_exe = &args[0]; + let output = match Command::new(current_exe) + .env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice()) + .output() { + Ok(out) => out, + Err(e) => { + let err = format!("Failed to spawn {} as child for test: {:?}", + args[0], e); + return (TrFailed, err.into_bytes()); + } + }; + + let std::process::Output { stdout, stderr, status } = output; + let mut test_output = stdout; + test_output.extend_from_slice(&stderr); + + let result = match (move || { + let exit_code = status.code().ok_or("child process was terminated")?; + TestResult::try_from(exit_code).map_err(|_| { + format!("child process returned unexpected exit code {}", exit_code) + }) + })() { + Ok(r) => r, + Err(e) => { + write!(&mut test_output, "Unexpected error: {}", e).unwrap(); + TrFailed + } + }; + + (result, test_output) + })(); + + monitor_ch.send((desc.clone(), result, test_output)).unwrap(); + } - let test_result = calc_result(&desc, result); - let stdout = data.lock().unwrap().to_vec(); - monitor_ch - .send((desc.clone(), test_result, stdout)) - .unwrap(); + RunStrategy::SpawnedSecondary => { + let record_lock = Mutex::new(()); + let builtin_panic_hook = panic::take_hook(); + let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| { + let _lock = record_lock.lock().unwrap(); + + let test_result = match panic_info { + Some(info) => calc_result(&desc, Err(info.payload())), + None => calc_result(&desc, Ok(())), + }; + + // We don't support serializing TrFailedMsg, so just + // print the message out to stderr. + let test_result = match test_result { + TrFailedMsg(msg) => { + eprintln!("{}", msg); + TrFailed + } + _ => test_result, + }; + + if let Some(info) = panic_info { + builtin_panic_hook(info); + } + process::exit(test_result.try_into().unwrap()); + }); + let record_result2 = record_result.clone(); + panic::set_hook(Box::new(move |info| record_result2(Some(&info)))); + testfn(); + record_result(None); + unreachable!("panic=abort callback should have exited the process"); + } + } }; // If the platform is single-threaded we're just going to run @@ -1438,26 +1604,29 @@ pub fn run_test( match testfn { DynBenchFn(bencher) => { - crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { + // Benchmarks aren't expected to panic, so we run them all in-process. + crate::bench::benchmark(opts, desc, strategy.monitor_ch().unwrap(), |harness| { bencher.run(harness) }); } StaticBenchFn(benchfn) => { - crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { + // Benchmarks aren't expected to panic, so we run them all in-process. + crate::bench::benchmark(opts, desc, strategy.monitor_ch().unwrap(), |harness| { (benchfn.clone())(harness) }); } DynTestFn(f) => { + match strategy { + RunStrategy::InProcess(_) => (), + _ => panic!("Cannot run dynamic test fn out-of-process"), + }; + let cb = move || __rust_begin_short_backtrace(f); + run_test_inner(desc, opts.nocapture, strategy, Box::new(cb), concurrency); + } + StaticTestFn(f) => { let cb = move || __rust_begin_short_backtrace(f); - run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb), concurrency) + run_test_inner(desc, opts.nocapture, strategy, Box::new(cb), concurrency); } - StaticTestFn(f) => run_test_inner( - desc, - monitor_ch, - opts.nocapture, - Box::new(move || __rust_begin_short_backtrace(f)), - concurrency, - ), } } @@ -1467,7 +1636,9 @@ fn __rust_begin_short_backtrace(f: F) { f() } -fn calc_result(desc: &TestDesc, task_result: Result<(), Box>) -> TestResult { +fn calc_result<'a>(desc: &TestDesc, + task_result: Result<(), &'a (dyn Any + 'static + Send)>) +-> TestResult { match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk, (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => { @@ -1640,14 +1811,16 @@ where } pub mod bench { - use super::{BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestResult}; + use super::{ + BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestOpts, TestResult + }; use crate::stats; use std::cmp; use std::io; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::sync::{Arc, Mutex}; - pub fn benchmark(desc: TestDesc, monitor_ch: Sender, nocapture: bool, f: F) + pub fn benchmark(opts: &TestOpts, desc: TestDesc, monitor_ch: Sender, f: F) where F: FnMut(&mut Bencher), { @@ -1658,12 +1831,10 @@ pub mod bench { }; let data = Arc::new(Mutex::new(Vec::new())); - let data2 = data.clone(); - - let oldio = if !nocapture { + let oldio = if !opts.nocapture { Some(( - io::set_print(Some(Box::new(Sink(data2.clone())))), - io::set_panic(Some(Box::new(Sink(data2)))), + io::set_print(Some(Box::new(Sink(data.clone())))), + io::set_panic(Some(Box::new(Sink(data.clone())))), )) } else { None @@ -1674,7 +1845,7 @@ pub mod bench { if let Some((printio, panicio)) = oldio { io::set_print(printio); io::set_panic(panicio); - }; + } let test_result = match result { //bs.bench(f) { diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs index afc4217ec1ba..2c4320df1256 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -1,7 +1,7 @@ use super::*; use crate::test::{ - filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, + filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, RunStrategy, ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg, TrIgnored, TrOk, }; @@ -66,7 +66,7 @@ pub fn do_not_run_ignored_tests() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res != TrOk); } @@ -84,7 +84,7 @@ pub fn ignored_tests_result_in_ignored() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrIgnored); } @@ -104,7 +104,7 @@ fn test_should_panic() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -124,7 +124,7 @@ fn test_should_panic_good_message() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -146,7 +146,7 @@ fn test_should_panic_bad_message() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); } @@ -164,7 +164,7 @@ fn test_should_panic_but_succeeds() { testfn: DynTestFn(Box::new(f)), }; let (tx, rx) = channel(); - run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); + run_test(&TestOpts::new(), false, desc, RunStrategy::InProcess, tx, Concurrent::No); let (_, res, _) = rx.recv().unwrap(); assert!(res == TrFailed); } From 52e49198dc367a9428d731f90c4d18b8e84a3bb2 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Wed, 11 Sep 2019 21:22:06 -0700 Subject: [PATCH 16/24] Only spawn subprocesses when panic=abort --- src/librustc_interface/passes.rs | 1 + src/libsyntax_ext/test_harness.rs | 14 ++++- src/libtest/lib.rs | 96 +++++++++++++++++++------------ 3 files changed, 73 insertions(+), 38 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index e8e8da673347..84462f65a4e8 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -446,6 +446,7 @@ fn configure_and_expand_inner<'a>( &mut krate, sess.diagnostic(), &sess.features_untracked(), + sess.panic_strategy(), ) }); diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index 56de0c97f81c..73841a39f588 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -2,6 +2,7 @@ use log::debug; use smallvec::{smallvec, SmallVec}; +use rustc_target::spec::PanicStrategy; use syntax::ast::{self, Ident}; use syntax::attr; use syntax::entry::{self, EntryPointType}; @@ -25,6 +26,7 @@ struct Test { struct TestCtxt<'a> { ext_cx: ExtCtxt<'a>, + panic_strategy: PanicStrategy, def_site: Span, test_cases: Vec, reexport_test_harness_main: Option, @@ -40,6 +42,7 @@ pub fn inject( krate: &mut ast::Crate, span_diagnostic: &errors::Handler, features: &Features, + panic_strategy: PanicStrategy, ) { // Check for #![reexport_test_harness_main = "some_name"] which gives the // main test function the name `some_name` without hygiene. This needs to be @@ -54,7 +57,7 @@ pub fn inject( if should_test { generate_test_harness(sess, resolver, reexport_test_harness_main, - krate, features, test_runner) + krate, features, panic_strategy, test_runner) } } @@ -183,6 +186,7 @@ fn generate_test_harness(sess: &ParseSess, reexport_test_harness_main: Option, krate: &mut ast::Crate, features: &Features, + panic_strategy: PanicStrategy, test_runner: Option) { let mut econfig = ExpansionConfig::default("test".to_string()); econfig.features = Some(features); @@ -203,6 +207,7 @@ fn generate_test_harness(sess: &ParseSess, let cx = TestCtxt { ext_cx, + panic_strategy, def_site, test_cases: Vec::new(), reexport_test_harness_main, @@ -248,9 +253,14 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let ecx = &cx.ext_cx; let test_id = Ident::new(sym::test, sp); + let runner_name = match cx.panic_strategy { + PanicStrategy::Unwind => "test_main_static", + PanicStrategy::Abort => "test_main_static_abort", + }; + // test::test_main_static(...) let mut test_runner = cx.test_runner.clone().unwrap_or( - ecx.path(sp, vec![test_id, ecx.ident_of("test_main_static", sp)])); + ecx.path(sp, vec![test_id, ecx.ident_of(runner_name, sp)])); test_runner.span = sp; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index fab1452cb7be..3a5a33912158 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -261,12 +261,14 @@ impl Metric { #[derive(Copy, Clone, Debug)] pub struct Options { display_output: bool, + panic_abort: bool, } impl Options { pub fn new() -> Options { Options { display_output: false, + panic_abort: false, } } @@ -274,24 +276,16 @@ impl Options { self.display_output = display_output; self } + + pub fn panic_abort(mut self, panic_abort: bool) -> Options { + self.panic_abort = panic_abort; + self + } } // The default console test runner. It accepts the command line // arguments and a vector of test_descs. pub fn test_main(args: &[String], tests: Vec, options: Option) { - // If we're being run in SpawnedSecondary mode, run the test here. run_test - // will then exit the process. - if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) { - let test = tests - .into_iter() - .filter(|test| test.desc.name.as_slice() == name) - .next() - .expect("couldn't find a test with the provided name"); - let opts = parse_opts(&[]).unwrap().unwrap(); - run_test(&opts, false, test, RunStrategy::SpawnedSecondary, Concurrent::No); - unreachable!(); - } - let mut opts = match parse_opts(args) { Some(Ok(o)) => o, Some(Err(msg)) => { @@ -320,32 +314,63 @@ pub fn test_main(args: &[String], tests: Vec, options: Option is used in order to effect ownership-transfer -// semantics into parallel test runners, which in turn requires a Vec<> -// rather than a &[]. +/// A variant optimized for invocation with a static test vector. +/// This will panic (intentionally) when fed any dynamic tests. +/// +/// This is the entry point for the main function generated by `rustc --test` +/// when panic=unwind. pub fn test_main_static(tests: &[&TestDescAndFn]) { let args = env::args().collect::>(); - let owned_tests = tests - .iter() - .map(|t| match t.testfn { - StaticTestFn(f) => TestDescAndFn { - testfn: StaticTestFn(f), - desc: t.desc.clone(), - }, - StaticBenchFn(f) => TestDescAndFn { - testfn: StaticBenchFn(f), - desc: t.desc.clone(), - }, - _ => panic!("non-static tests passed to test::test_main_static"), - }) - .collect(); + let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect(); test_main(&args, owned_tests, None) } +/// A variant optimized for invocation with a static test vector. +/// This will panic (intentionally) when fed any dynamic tests. +/// +/// Runs tests in panic=abort mode, which involves spawning subprocesses for +/// tests. +/// +/// This is the entry point for the main function generated by `rustc --test` +/// when panic=abort. +pub fn test_main_static_abort(tests: &[&TestDescAndFn]) { + // If we're being run in SpawnedSecondary mode, run the test here. run_test + // will then exit the process. + if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) { + let test = tests + .iter() + .filter(|test| test.desc.name.as_slice() == name) + .map(make_owned_test) + .next() + .expect("couldn't find a test with the provided name"); + let opts = parse_opts(&[]).unwrap().unwrap(); + run_test(&opts, false, test, RunStrategy::SpawnedSecondary, Concurrent::No); + unreachable!(); + } + + let args = env::args().collect::>(); + let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect(); + test_main(&args, owned_tests, Some(Options::new().panic_abort(true))) +} + +/// Clones static values for putting into a dynamic vector, which test_main() +/// needs to hand out ownership of tests to parallel test runners. +/// +/// This will panic when fed any dynamic tests, because they cannot be cloned. +fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn { + match test.testfn { + StaticTestFn(f) => TestDescAndFn { + testfn: StaticTestFn(f), + desc: test.desc.clone(), + }, + StaticBenchFn(f) => TestDescAndFn { + testfn: StaticBenchFn(f), + desc: test.desc.clone(), + }, + _ => panic!("non-static tests passed to test::test_main_static"), + } +} + /// Invoked when unit tests terminate. Should panic if the unit /// Tests is considered a failure. By default, invokes `report()` /// and checks for a `0` result. @@ -1147,8 +1172,7 @@ where let mut pending = 0; let (tx, rx) = channel::(); - // TODO - let run_strategy = if true { + let run_strategy = if opts.options.panic_abort { RunStrategy::SpawnPrimary(tx) } else { RunStrategy::InProcess(tx) From c6b4fb7340b19fb686b2852ddc71ddb60f90023f Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 12 Sep 2019 16:19:53 -0700 Subject: [PATCH 17/24] Remove panic_unwind requirement from libtest --- src/libtest/lib.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 3a5a33912158..605c9477361d 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -35,16 +35,6 @@ use getopts; extern crate libc; use term; -// FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind -// on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc -// so we don't link libtest against libunwind (for the time being) -// even though it means that libtest won't be fully functional on -// these platforms. -// -// See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437 -#[cfg(not(all(windows, any(target_arch = "aarch64", target_arch = "arm"))))] -extern crate panic_unwind; - pub use self::ColorConfig::*; use self::NamePadding::*; use self::OutputLocation::*; @@ -1488,11 +1478,7 @@ pub fn run_test( ) { let TestDescAndFn { desc, testfn } = test; - let ignore_because_panic_abort = cfg!(target_arch = "wasm32") - && !cfg!(target_os = "emscripten") - && desc.should_panic != ShouldPanic::No; - - if force_ignore || desc.ignore || ignore_because_panic_abort { + if force_ignore || desc.ignore { match strategy { RunStrategy::InProcess(tx) | RunStrategy::SpawnPrimary(tx) => { tx.send((desc, TrIgnored, Vec::new())).unwrap(); From df24055bcae3269908ed0da22b7119b8d282c5cd Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 12 Sep 2019 19:04:37 -0700 Subject: [PATCH 18/24] Factor inner test runners out, simplify RunStrategy --- src/libtest/lib.rs | 271 ++++++++++++++++++++++----------------------- 1 file changed, 131 insertions(+), 140 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 605c9477361d..f270d0341b22 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -333,9 +333,12 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) { .map(make_owned_test) .next() .expect("couldn't find a test with the provided name"); - let opts = parse_opts(&[]).unwrap().unwrap(); - run_test(&opts, false, test, RunStrategy::SpawnedSecondary, Concurrent::No); - unreachable!(); + let TestDescAndFn { desc, testfn } = test; + let testfn = match testfn { + StaticTestFn(f) => f, + _ => panic!("only static tests are supported"), + }; + run_test_in_spawned_subprocess(desc, Box::new(testfn)); } let args = env::args().collect::>(); @@ -1088,31 +1091,16 @@ impl Write for Sink { } } -#[derive(Clone)] +#[derive(Clone, Copy)] pub enum RunStrategy { /// Runs the test in the current process, and sends the result back over the /// supplied channel. - InProcess(Sender), + InProcess, /// Spawns a subprocess to run the test, and sends the result back over the /// supplied channel. Requires argv[0] to exist and point to the binary /// that's currently running. - SpawnPrimary(Sender), - - /// Runs the test in the current process, then exits the process. - /// Prints to stdout the custom result format that the parent process - /// expects in SpawnPrimary mode. - SpawnedSecondary, -} - -impl RunStrategy { - fn monitor_ch(self) -> Option> { - match self { - RunStrategy::InProcess(ch) => Some(ch), - RunStrategy::SpawnPrimary(ch) => Some(ch), - RunStrategy::SpawnedSecondary => None, - } - } + SpawnPrimary, } pub fn run_tests(opts: &TestOpts, tests: Vec, mut callback: F) -> io::Result<()> @@ -1163,9 +1151,9 @@ where let (tx, rx) = channel::(); let run_strategy = if opts.options.panic_abort { - RunStrategy::SpawnPrimary(tx) + RunStrategy::SpawnPrimary } else { - RunStrategy::InProcess(tx) + RunStrategy::InProcess }; let mut running_tests: TestMap = HashMap::default(); @@ -1203,7 +1191,7 @@ where while !remaining.is_empty() { let test = remaining.pop().unwrap(); callback(TeWait(test.desc.clone()))?; - run_test(opts, !opts.run_tests, test, run_strategy.clone(), Concurrent::No); + run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::No); let (test, result, stdout) = rx.recv().unwrap(); callback(TeResult(test, result, stdout))?; } @@ -1214,7 +1202,7 @@ where let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S); running_tests.insert(test.desc.clone(), timeout); callback(TeWait(test.desc.clone()))?; //here no pad - run_test(opts, !opts.run_tests, test, run_strategy.clone(), Concurrent::Yes); + run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::Yes); pending += 1; } @@ -1246,7 +1234,7 @@ where // All benchmarks run at the end, in serial. for b in filtered_benchs { callback(TeWait(b.desc.clone()))?; - run_test(opts, false, b, run_strategy.clone(), Concurrent::No); + run_test(opts, false, b, run_strategy, tx.clone(), Concurrent::No); let (test, result, stdout) = rx.recv().unwrap(); callback(TeResult(test, result, stdout))?; } @@ -1474,17 +1462,17 @@ pub fn run_test( force_ignore: bool, test: TestDescAndFn, strategy: RunStrategy, + monitor_ch: Sender, concurrency: Concurrent, ) { let TestDescAndFn { desc, testfn } = test; - if force_ignore || desc.ignore { - match strategy { - RunStrategy::InProcess(tx) | RunStrategy::SpawnPrimary(tx) => { - tx.send((desc, TrIgnored, Vec::new())).unwrap(); - } - RunStrategy::SpawnedSecondary => panic!(), - } + let ignore_because_no_process_support = cfg!(target_arch = "wasm32") + && !cfg!(target_os = "emscripten") + && desc.should_panic != ShouldPanic::No; + + if force_ignore || desc.ignore || ignore_because_no_process_support { + monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap(); return; } @@ -1492,111 +1480,16 @@ pub fn run_test( desc: TestDesc, nocapture: bool, strategy: RunStrategy, + monitor_ch: Sender, testfn: Box, concurrency: Concurrent, ) { - // Buffer for capturing standard I/O - let data = Arc::new(Mutex::new(Vec::new())); - let name = desc.name.clone(); + let runtest = move || { - // TODO split into functions match strategy { - RunStrategy::InProcess(monitor_ch) => { - let oldio = if !nocapture { - Some(( - io::set_print(Some(Box::new(Sink(data.clone())))), - io::set_panic(Some(Box::new(Sink(data.clone())))), - )) - } else { - None - }; - - let result = catch_unwind(AssertUnwindSafe(testfn)); - - if let Some((printio, panicio)) = oldio { - io::set_print(printio); - io::set_panic(panicio); - } - - let test_result = match result { - Ok(()) => calc_result(&desc, Ok(())), - Err(e) => calc_result(&desc, Err(e.as_ref())), - }; - let stdout = data.lock().unwrap().to_vec(); - monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); - } - - RunStrategy::SpawnPrimary(monitor_ch) => { - let (result, test_output) = (|| { - let args = env::args().collect::>(); - let current_exe = &args[0]; - let output = match Command::new(current_exe) - .env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice()) - .output() { - Ok(out) => out, - Err(e) => { - let err = format!("Failed to spawn {} as child for test: {:?}", - args[0], e); - return (TrFailed, err.into_bytes()); - } - }; - - let std::process::Output { stdout, stderr, status } = output; - let mut test_output = stdout; - test_output.extend_from_slice(&stderr); - - let result = match (move || { - let exit_code = status.code().ok_or("child process was terminated")?; - TestResult::try_from(exit_code).map_err(|_| { - format!("child process returned unexpected exit code {}", exit_code) - }) - })() { - Ok(r) => r, - Err(e) => { - write!(&mut test_output, "Unexpected error: {}", e).unwrap(); - TrFailed - } - }; - - (result, test_output) - })(); - - monitor_ch.send((desc.clone(), result, test_output)).unwrap(); - } - - RunStrategy::SpawnedSecondary => { - let record_lock = Mutex::new(()); - let builtin_panic_hook = panic::take_hook(); - let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| { - let _lock = record_lock.lock().unwrap(); - - let test_result = match panic_info { - Some(info) => calc_result(&desc, Err(info.payload())), - None => calc_result(&desc, Ok(())), - }; - - // We don't support serializing TrFailedMsg, so just - // print the message out to stderr. - let test_result = match test_result { - TrFailedMsg(msg) => { - eprintln!("{}", msg); - TrFailed - } - _ => test_result, - }; - - if let Some(info) = panic_info { - builtin_panic_hook(info); - } - process::exit(test_result.try_into().unwrap()); - }); - let record_result2 = record_result.clone(); - panic::set_hook(Box::new(move |info| record_result2(Some(&info)))); - testfn(); - record_result(None); - unreachable!("panic=abort callback should have exited the process"); - } + RunStrategy::InProcess => run_test_in_process(desc, nocapture, testfn, monitor_ch), + RunStrategy::SpawnPrimary => spawn_test_subprocess(desc, monitor_ch), } }; @@ -1615,27 +1508,27 @@ pub fn run_test( match testfn { DynBenchFn(bencher) => { // Benchmarks aren't expected to panic, so we run them all in-process. - crate::bench::benchmark(opts, desc, strategy.monitor_ch().unwrap(), |harness| { + crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { bencher.run(harness) }); } StaticBenchFn(benchfn) => { // Benchmarks aren't expected to panic, so we run them all in-process. - crate::bench::benchmark(opts, desc, strategy.monitor_ch().unwrap(), |harness| { + crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { (benchfn.clone())(harness) }); } DynTestFn(f) => { match strategy { - RunStrategy::InProcess(_) => (), + RunStrategy::InProcess => (), _ => panic!("Cannot run dynamic test fn out-of-process"), }; let cb = move || __rust_begin_short_backtrace(f); - run_test_inner(desc, opts.nocapture, strategy, Box::new(cb), concurrency); + run_test_inner(desc, opts.nocapture, strategy, monitor_ch, Box::new(cb), concurrency); } StaticTestFn(f) => { let cb = move || __rust_begin_short_backtrace(f); - run_test_inner(desc, opts.nocapture, strategy, Box::new(cb), concurrency); + run_test_inner(desc, opts.nocapture, strategy, monitor_ch, Box::new(cb), concurrency); } } } @@ -1673,6 +1566,104 @@ fn calc_result<'a>(desc: &TestDesc, } } +fn run_test_in_process(desc: TestDesc, + nocapture: bool, + testfn: Box, + monitor_ch: Sender) { + // Buffer for capturing standard I/O + let data = Arc::new(Mutex::new(Vec::new())); + + let oldio = if !nocapture { + Some(( + io::set_print(Some(Box::new(Sink(data.clone())))), + io::set_panic(Some(Box::new(Sink(data.clone())))), + )) + } else { + None + }; + + let result = catch_unwind(AssertUnwindSafe(testfn)); + + if let Some((printio, panicio)) = oldio { + io::set_print(printio); + io::set_panic(panicio); + } + + let test_result = match result { + Ok(()) => calc_result(&desc, Ok(())), + Err(e) => calc_result(&desc, Err(e.as_ref())), + }; + let stdout = data.lock().unwrap().to_vec(); + monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); +} + +fn spawn_test_subprocess(desc: TestDesc, monitor_ch: Sender) { + let (result, test_output) = (|| { + let args = env::args().collect::>(); + let current_exe = &args[0]; + let output = match Command::new(current_exe) + .env(SECONDARY_TEST_INVOKER_VAR, desc.name.as_slice()) + .output() { + Ok(out) => out, + Err(e) => { + let err = format!("Failed to spawn {} as child for test: {:?}", args[0], e); + return (TrFailed, err.into_bytes()); + } + }; + + let std::process::Output { stdout, stderr, status } = output; + let mut test_output = stdout; + test_output.extend_from_slice(&stderr); + + let result = match (move || { + let exit_code = status.code().ok_or("child process was terminated")?; + TestResult::try_from(exit_code).map_err(|_| { + format!("child process returned unexpected exit code {}", exit_code) + }) + })() { + Ok(r) => r, + Err(e) => { + write!(&mut test_output, "Unexpected error: {}", e).unwrap(); + TrFailed + } + }; + + (result, test_output) + })(); + + monitor_ch.send((desc.clone(), result, test_output)).unwrap(); +} + +fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box) -> ! { + let builtin_panic_hook = panic::take_hook(); + let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| { + let test_result = match panic_info { + Some(info) => calc_result(&desc, Err(info.payload())), + None => calc_result(&desc, Ok(())), + }; + + // We don't support serializing TrFailedMsg, so just + // print the message out to stderr. + let test_result = match test_result { + TrFailedMsg(msg) => { + eprintln!("{}", msg); + TrFailed + } + _ => test_result, + }; + + if let Some(info) = panic_info { + builtin_panic_hook(info); + } + process::exit(test_result.try_into().unwrap()); + }); + let record_result2 = record_result.clone(); + panic::set_hook(Box::new(move |info| record_result2(Some(&info)))); + testfn(); + record_result(None); + unreachable!("panic=abort callback should have exited the process") +} + #[derive(Clone, PartialEq)] pub struct MetricMap(BTreeMap); @@ -1822,7 +1813,7 @@ where pub mod bench { use super::{ - BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestOpts, TestResult + BenchMode, BenchSamples, Bencher, MonitorMsg, Sender, Sink, TestDesc, TestResult }; use crate::stats; use std::cmp; @@ -1830,7 +1821,7 @@ pub mod bench { use std::panic::{catch_unwind, AssertUnwindSafe}; use std::sync::{Arc, Mutex}; - pub fn benchmark(opts: &TestOpts, desc: TestDesc, monitor_ch: Sender, f: F) + pub fn benchmark(desc: TestDesc, monitor_ch: Sender, nocapture: bool, f: F) where F: FnMut(&mut Bencher), { @@ -1841,7 +1832,7 @@ pub mod bench { }; let data = Arc::new(Mutex::new(Vec::new())); - let oldio = if !opts.nocapture { + let oldio = if !nocapture { Some(( io::set_print(Some(Box::new(Sink(data.clone())))), io::set_panic(Some(Box::new(Sink(data.clone())))), From e6015e41705d3b55a5e108cc4b9854ec37a78436 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 13 Sep 2019 17:44:09 -0700 Subject: [PATCH 19/24] Include signal from terminated child process on unix --- src/libtest/formatters/mod.rs | 9 +++++++++ src/libtest/lib.rs | 22 ++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs index cc30b06e5ec3..f431c9de7f11 100644 --- a/src/libtest/formatters/mod.rs +++ b/src/libtest/formatters/mod.rs @@ -21,3 +21,12 @@ pub(crate) trait OutputFormatter { ) -> io::Result<()>; fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result; } + +pub(crate) fn write_stderr_delimiter(test_output: &mut Vec, test_name: &TestName) { + match test_output.last() { + Some(b'\n') => (), + Some(_) => test_output.push(b'\n'), + None => (), + } + write!(test_output, "---- {} stderr ----\n", test_name).unwrap(); +} diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index f270d0341b22..813463ff7dfe 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -56,7 +56,7 @@ use std::io::prelude::*; use std::panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo}; use std::path::PathBuf; use std::process; -use std::process::{Command, Termination}; +use std::process::{ExitStatus, Command, Termination}; use std::sync::mpsc::{channel, Sender}; use std::sync::{Arc, Mutex}; use std::thread; @@ -1613,10 +1613,11 @@ fn spawn_test_subprocess(desc: TestDesc, monitor_ch: Sender) { let std::process::Output { stdout, stderr, status } = output; let mut test_output = stdout; + formatters::write_stderr_delimiter(&mut test_output, &desc.name); test_output.extend_from_slice(&stderr); let result = match (move || { - let exit_code = status.code().ok_or("child process was terminated")?; + let exit_code = get_exit_code(status)?; TestResult::try_from(exit_code).map_err(|_| { format!("child process returned unexpected exit code {}", exit_code) }) @@ -1664,6 +1665,23 @@ fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box Result { + status.code().ok_or("received no exit code from child process".into()) +} + +#[cfg(unix)] +fn get_exit_code(status: ExitStatus) -> Result { + use std::os::unix::process::ExitStatusExt; + match status.code() { + Some(code) => Ok(code), + None => match status.signal() { + Some(signal) => Err(format!("child process exited with signal {}", signal)), + None => Err("child process exited with unknown signal".into()), + } + } +} + #[derive(Clone, PartialEq)] pub struct MetricMap(BTreeMap); From c792c251f38a0de3cc2a2826b34dab18b1949ad0 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Wed, 18 Sep 2019 18:19:13 -0700 Subject: [PATCH 20/24] Use just two return codes to communicate result --- src/libtest/lib.rs | 74 ++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 813463ff7dfe..2a2f32f97162 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -47,7 +47,6 @@ use std::any::Any; use std::borrow::Cow; use std::cmp; use std::collections::BTreeMap; -use std::convert::{TryFrom, TryInto}; use std::env; use std::fmt; use std::fs::File; @@ -70,6 +69,12 @@ const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in qu const SECONDARY_TEST_INVOKER_VAR: &'static str = "__RUST_TEST_INVOKE"; +// Return codes for secondary process. +// Start somewhere other than 0 so we know the return code means what we think +// it means. +const TR_OK: i32 = 50; +const TR_FAILED: i32 = 51; + // to be used by rustc to compile tests in libtest pub mod test { pub use crate::{ @@ -712,41 +717,6 @@ pub enum TestResult { unsafe impl Send for TestResult {} -// Return codes for TestResult. -// Start somewhere other than 0 so we know the return code means what we think -// it means. -const TR_OK: i32 = 50; -const TR_FAILED: i32 = 51; -const TR_IGNORED: i32 = 52; -const TR_ALLOWED_FAIL: i32 = 53; - -impl TryFrom for i32 { - type Error = &'static str; - fn try_from(val: TestResult) -> Result { - Ok(match val { - TrOk => TR_OK, - TrFailed => TR_FAILED, - TrIgnored => TR_IGNORED, - TrAllowedFail => TR_ALLOWED_FAIL, - TrFailedMsg(..) | - TrBench(..) => return Err("can't convert variant to i32"), - }) - } -} - -impl TryFrom for TestResult { - type Error = &'static str; - fn try_from(val: i32) -> Result { - Ok(match val { - TR_OK => TrOk, - TR_FAILED => TrFailed, - TR_IGNORED => TrIgnored, - TR_ALLOWED_FAIL => TrAllowedFail, - _ => return Err("unrecognized return code"), - }) - } -} - enum OutputLocation { Pretty(Box), Raw(T), @@ -1566,6 +1536,15 @@ fn calc_result<'a>(desc: &TestDesc, } } +fn get_result_from_exit_code(desc: &TestDesc, code: i32) -> TestResult { + match (desc.allow_fail, code) { + (_, TR_OK) => TrOk, + (true, TR_FAILED) => TrAllowedFail, + (false, TR_FAILED) => TrFailed, + (_, _) => TrFailedMsg(format!("got unexpected return code {}", code)), + } +} + fn run_test_in_process(desc: TestDesc, nocapture: bool, testfn: Box, @@ -1616,11 +1595,9 @@ fn spawn_test_subprocess(desc: TestDesc, monitor_ch: Sender) { formatters::write_stderr_delimiter(&mut test_output, &desc.name); test_output.extend_from_slice(&stderr); - let result = match (move || { + let result = match (|| -> Result { let exit_code = get_exit_code(status)?; - TestResult::try_from(exit_code).map_err(|_| { - format!("child process returned unexpected exit code {}", exit_code) - }) + Ok(get_result_from_exit_code(&desc, exit_code)) })() { Ok(r) => r, Err(e) => { @@ -1645,18 +1622,19 @@ fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box { - eprintln!("{}", msg); - TrFailed - } - _ => test_result, - }; + if let TrFailedMsg(msg) = &test_result { + eprintln!("{}", msg); + } if let Some(info) = panic_info { builtin_panic_hook(info); } - process::exit(test_result.try_into().unwrap()); + + if let TrOk = test_result { + process::exit(TR_OK); + } else { + process::exit(TR_FAILED); + } }); let record_result2 = record_result.clone(); panic::set_hook(Box::new(move |info| record_result2(Some(&info)))); From c396c126c1cc69a813a986d66749cbf1d004dfd5 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 19 Sep 2019 18:34:23 -0700 Subject: [PATCH 21/24] Add test for libtest panic=abort mode --- src/test/ui/test-panic-abort.rs | 39 +++++++++++++++++++++++++ src/test/ui/test-panic-abort.run.stdout | 30 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 src/test/ui/test-panic-abort.rs create mode 100644 src/test/ui/test-panic-abort.run.stdout diff --git a/src/test/ui/test-panic-abort.rs b/src/test/ui/test-panic-abort.rs new file mode 100644 index 000000000000..9947355863f2 --- /dev/null +++ b/src/test/ui/test-panic-abort.rs @@ -0,0 +1,39 @@ +// no-prefer-dynamic +// compile-flags: --test -Cpanic=abort +// run-flags: --test-threads=1 +// run-fail +// check-run-results + +#![cfg(test)] + +use std::io::Write; + +#[test] +fn it_works() { + assert_eq!(1 + 1, 2); +} + +#[test] +#[should_panic] +fn it_panics() { + assert_eq!(1 + 1, 4); +} + +#[test] +fn it_fails() { + println!("hello, world"); + writeln!(std::io::stdout(), "testing123").unwrap(); + writeln!(std::io::stderr(), "testing321").unwrap(); + assert_eq!(1 + 1, 5); +} + +#[test] +fn it_exits() { + std::process::exit(123); +} + +#[test] +fn it_segfaults() { + let x = unsafe { *(0 as *const u64) }; + println!("output: {}", x); +} diff --git a/src/test/ui/test-panic-abort.run.stdout b/src/test/ui/test-panic-abort.run.stdout new file mode 100644 index 000000000000..0e21b44c6669 --- /dev/null +++ b/src/test/ui/test-panic-abort.run.stdout @@ -0,0 +1,30 @@ + +running 5 tests +test it_exits ... FAILED +test it_fails ... FAILED +test it_panics ... ok +test it_segfaults ... ok +test it_works ... ok + +failures: + +---- it_exits stdout ---- +---- it_exits stderr ---- +note: got unexpected return code 123 +---- it_fails stdout ---- +hello, world +testing123 +---- it_fails stderr ---- +testing321 +thread 'main' panicked at 'assertion failed: `(left == right)` + left: `2`, + right: `5`', $DIR/test-panic-abort.rs:27:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + + +failures: + it_exits + it_fails + +test result: FAILED. 3 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out + From 6f36f8710acfcba8de9688c61136e129e8b11ccb Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 19 Sep 2019 19:33:38 -0700 Subject: [PATCH 22/24] Put panic=abort test support behind -Z panic_abort_tests --- src/librustc/session/config.rs | 2 ++ src/librustc_interface/passes.rs | 1 + src/libsyntax_ext/test_harness.rs | 5 +++++ src/test/ui/test-panic-abort-disabled.rs | 18 ++++++++++++++++++ .../ui/test-panic-abort-disabled.run.stdout | 3 +++ src/test/ui/test-panic-abort.rs | 2 +- 6 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/test-panic-abort-disabled.rs create mode 100644 src/test/ui/test-panic-abort-disabled.run.stdout diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 723855c7c29c..e566a2ae42e5 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1295,6 +1295,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "show extended diagnostic help"), terminal_width: Option = (None, parse_opt_uint, [UNTRACKED], "set the current terminal width"), + panic_abort_tests: bool = (false, parse_bool, [TRACKED], + "support compiling tests with panic=abort"), continue_parse_after_error: bool = (false, parse_bool, [TRACKED], "attempt to recover from parse errors (experimental)"), dep_tasks: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 84462f65a4e8..032bd2c02561 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -447,6 +447,7 @@ fn configure_and_expand_inner<'a>( sess.diagnostic(), &sess.features_untracked(), sess.panic_strategy(), + sess.opts.debugging_opts.panic_abort_tests, ) }); diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index 73841a39f588..158a7c2df8a0 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -43,6 +43,7 @@ pub fn inject( span_diagnostic: &errors::Handler, features: &Features, panic_strategy: PanicStrategy, + enable_panic_abort_tests: bool, ) { // Check for #![reexport_test_harness_main = "some_name"] which gives the // main test function the name `some_name` without hygiene. This needs to be @@ -55,6 +56,10 @@ pub fn inject( // even in non-test builds let test_runner = get_test_runner(span_diagnostic, &krate); + let panic_strategy = match (panic_strategy, enable_panic_abort_tests) { + (PanicStrategy::Abort, true) => PanicStrategy::Abort, + _ => PanicStrategy::Unwind, + }; if should_test { generate_test_harness(sess, resolver, reexport_test_harness_main, krate, features, panic_strategy, test_runner) diff --git a/src/test/ui/test-panic-abort-disabled.rs b/src/test/ui/test-panic-abort-disabled.rs new file mode 100644 index 000000000000..a0e7cb1a0db0 --- /dev/null +++ b/src/test/ui/test-panic-abort-disabled.rs @@ -0,0 +1,18 @@ +// no-prefer-dynamic +// compile-flags: --test -Cpanic=abort +// run-flags: --test-threads=1 +// run-fail +// check-run-results + +#![cfg(test)] + +#[test] +fn it_works() { + assert_eq!(1 + 1, 2); +} + +#[test] +#[should_panic] +fn it_panics() { + assert_eq!(1 + 1, 4); +} diff --git a/src/test/ui/test-panic-abort-disabled.run.stdout b/src/test/ui/test-panic-abort-disabled.run.stdout new file mode 100644 index 000000000000..171fd2edcf63 --- /dev/null +++ b/src/test/ui/test-panic-abort-disabled.run.stdout @@ -0,0 +1,3 @@ + +running 2 tests +test it_panics ... \ No newline at end of file diff --git a/src/test/ui/test-panic-abort.rs b/src/test/ui/test-panic-abort.rs index 9947355863f2..0daccb3ec8aa 100644 --- a/src/test/ui/test-panic-abort.rs +++ b/src/test/ui/test-panic-abort.rs @@ -1,5 +1,5 @@ // no-prefer-dynamic -// compile-flags: --test -Cpanic=abort +// compile-flags: --test -Cpanic=abort -Zpanic_abort_tests // run-flags: --test-threads=1 // run-fail // check-run-results From c3140bae633b265657c0094f6df6edf630d1d917 Mon Sep 17 00:00:00 2001 From: guanqun Date: Sat, 21 Sep 2019 00:22:43 +0800 Subject: [PATCH 23/24] remove the extra comma after the match arm This would follow the same coding style as all the other match arms in this file. --- src/librustc_resolve/late/diagnostics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 0c86d8494fde..df8bd3fa75e1 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -424,7 +424,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { } else { err.note("did you mean to use one of the enum's variants?"); } - }, + } (Res::Def(DefKind::Struct, def_id), _) if ns == ValueNS => { if let Some((ctor_def, ctor_vis)) = self.r.struct_constructors.get(&def_id).cloned() { From 6bd568b675bb7ffc9acff374d32a4f8194a88a62 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 20 Sep 2019 15:02:42 -0700 Subject: [PATCH 24/24] Ignore panic=abort tests on wasm, emscripten --- src/test/ui/test-panic-abort-disabled.rs | 3 +++ src/test/ui/test-panic-abort.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/test/ui/test-panic-abort-disabled.rs b/src/test/ui/test-panic-abort-disabled.rs index a0e7cb1a0db0..ea979258a556 100644 --- a/src/test/ui/test-panic-abort-disabled.rs +++ b/src/test/ui/test-panic-abort-disabled.rs @@ -4,6 +4,9 @@ // run-fail // check-run-results +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support + #![cfg(test)] #[test] diff --git a/src/test/ui/test-panic-abort.rs b/src/test/ui/test-panic-abort.rs index 0daccb3ec8aa..9fe54ab73735 100644 --- a/src/test/ui/test-panic-abort.rs +++ b/src/test/ui/test-panic-abort.rs @@ -4,6 +4,9 @@ // run-fail // check-run-results +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support + #![cfg(test)] use std::io::Write;