diff --git a/Cargo.lock b/Cargo.lock index f99e58e59b8e5..4cb64882cb7e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4805,18 +4805,18 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" [[package]] name = "semver" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] @@ -4833,9 +4833,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -4853,9 +4853,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "indexmap", "itoa", @@ -5133,9 +5133,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.102" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -5309,6 +5309,7 @@ dependencies = [ "lazy_static", "miropt-test-tools", "regex", + "semver", "termcolor", "walkdir", ] diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 63bc0d552c11e..b2b7b9d75bd37 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -638,7 +638,7 @@ fn report_missing_placeholders( if show_doc_note { diag.note(concat!( stringify!($kind), - " formatting not supported; see the documentation for `std::fmt`", + " formatting is not supported; see the documentation for `std::fmt`", )); } if suggestions.len() > 0 { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index cdb901b7f8603..10d8db5393da9 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1392,7 +1392,7 @@ declare_lint! { /// /// The attribute must be used in conjunction with the /// [`closure_track_caller` feature flag]. Otherwise, the `#[track_caller]` - /// annotation will function as as no-op. + /// annotation will function as a no-op. /// /// [`closure_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/closure-track-caller.html UNGATED_ASYNC_FN_TRACK_CALLER, diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 5f84d5c8b9495..c18abaef8e256 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -29,7 +29,7 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } -/// Implements the AST traversal for early lint passes. `T` provides the the +/// Implements the AST traversal for early lint passes. `T` provides the /// `check_*` methods. pub struct EarlyContextAndPass<'a, T: EarlyLintPass> { context: EarlyContext<'a>, diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index e2876938d7056..b2a2656746eec 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -40,7 +40,7 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } -/// Implements the AST traversal for late lint passes. `T` provides the the +/// Implements the AST traversal for late lint passes. `T` provides the /// `check_*` methods. pub struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> { context: LateContext<'tcx>, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 2ee3f551529f9..1a264d2d5af9a 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -3,15 +3,15 @@ //! ## Overview //! //! There are two visitors, one for immutable and one for mutable references, -//! but both are generated by the following macro. The code is written according -//! to the following conventions: +//! but both are generated by the `make_mir_visitor` macro. +//! The code is written according to the following conventions: //! //! - introduce a `visit_foo` and a `super_foo` method for every MIR type //! - `visit_foo`, by default, calls `super_foo` //! - `super_foo`, by default, destructures the `foo` and calls `visit_foo` //! -//! This allows you as a user to override `visit_foo` for types are -//! interested in, and invoke (within that method) call +//! This allows you to override `visit_foo` for types you are +//! interested in, and invoke (within that method call) //! `self.super_foo` to get the default behavior. Just as in an OO //! language, you should never call `super` methods ordinarily except //! in that circumstance. diff --git a/compiler/rustc_trait_selection/src/solve/overflow.rs b/compiler/rustc_trait_selection/src/solve/overflow.rs index 8d73a83aec96e..fdd6adb681be4 100644 --- a/compiler/rustc_trait_selection/src/solve/overflow.rs +++ b/compiler/rustc_trait_selection/src/solve/overflow.rs @@ -36,7 +36,7 @@ impl OverflowData { #[inline] pub(super) fn has_overflow(&self, depth: usize) -> bool { - self.current_limit.value_within_limit(depth + self.additional_depth) + !self.current_limit.value_within_limit(depth + self.additional_depth) } /// Updating the current limit when hitting overflow. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 9cf43fc7a2193..f3998e98583ec 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -934,8 +934,7 @@ def main(): if len(sys.argv) > 1 and sys.argv[1] == 'help': sys.argv = [sys.argv[0], '-h'] + sys.argv[2:] - help_triggered = ( - '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) + help_triggered = len(sys.argv) == 1 or any(x in ["-h", "--help", "--version"] for x in sys.argv) try: bootstrap(help_triggered) if not help_triggered: diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 07a9c48365f44..025a4379f45a3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1960,7 +1960,6 @@ pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocCont variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(), ), None => VariantKind::Struct(VariantStruct { - ctor_kind: None, fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(), }), }; @@ -1985,7 +1984,6 @@ fn clean_variant_data<'tcx>( let kind = match variant { hir::VariantData::Struct(..) => VariantKind::Struct(VariantStruct { - ctor_kind: None, fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(), }), hir::VariantData::Tuple(..) => { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 77ec024262123..6d55a6794f581 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2111,7 +2111,6 @@ impl Union { /// only as a variant in an enum. #[derive(Clone, Debug)] pub(crate) struct VariantStruct { - pub(crate) ctor_kind: Option, pub(crate) fields: Vec, } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 40dfb06975067..c16d6477fc379 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1229,16 +1229,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str(")"); } clean::VariantKind::Struct(ref s) => { - render_struct( - w, - v, - None, - s.ctor_kind, - &s.fields, - " ", - false, - cx, - ); + render_struct(w, v, None, None, &s.fields, " ", false, cx); } }, _ => unreachable!(), diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index bc0458bcd28f2..6f8a306d665b1 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -76,8 +76,6 @@ } * { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; box-sizing: border-box; } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 310a01194eaf8..7db470359672f 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -410,7 +410,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { /// This method will create a new module and push it onto the "modules stack" then call /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead - /// add into into the list of modules of the current module. + /// add into the list of modules of the current module. fn enter_mod(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, name: Symbol) { self.modules.push(Module::new(name, id, m.spans.inner_span)); diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.rs b/src/test/ui/borrowck/borrowck-drop-from-guard.rs index 4995029a70f7e..0f320af265760 100644 --- a/src/test/ui/borrowck/borrowck-drop-from-guard.rs +++ b/src/test/ui/borrowck/borrowck-drop-from-guard.rs @@ -1,3 +1,5 @@ +#![feature(if_let_guard)] + fn foo(_:String) {} fn main() @@ -8,4 +10,11 @@ fn main() Some(_) => {} None => { foo(my_str); } //~ ERROR [E0382] } + + let my_str = "hello".to_owned(); + match Some(42) { + Some(_) if let Some(()) = { drop(my_str); None } => {} + Some(_) => {} + None => { foo(my_str); } //~ ERROR [E0382] + } } diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr index eaf4bb38bc590..9fa28efd8554d 100644 --- a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr +++ b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `my_str` - --> $DIR/borrowck-drop-from-guard.rs:9:23 + --> $DIR/borrowck-drop-from-guard.rs:11:23 | LL | let my_str = "hello".to_owned(); | ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait @@ -15,6 +15,23 @@ help: consider cloning the value if the performance cost is acceptable LL | Some(_) if { drop(my_str.clone()); false } => {} | ++++++++ -error: aborting due to previous error +error[E0382]: use of moved value: `my_str` + --> $DIR/borrowck-drop-from-guard.rs:18:23 + | +LL | let my_str = "hello".to_owned(); + | ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait +LL | match Some(42) { +LL | Some(_) if let Some(()) = { drop(my_str); None } => {} + | ------ value moved here +LL | Some(_) => {} +LL | None => { foo(my_str); } + | ^^^^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if let Some(()) = { drop(my_str.clone()); None } => {} + | ++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs index 9cbceeb945ccc..d80a9e81576f4 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs @@ -1,9 +1,11 @@ +#![feature(if_let_guard)] + enum Enum<'a> { A(&'a isize), B(bool), } -fn foo() -> isize { +fn if_guard() -> isize { let mut n = 42; let mut x = Enum::A(&mut n); match x { @@ -16,6 +18,17 @@ fn foo() -> isize { } } -fn main() { - foo(); +fn if_let_guard() -> isize { + let mut n = 42; + let mut x = Enum::A(&mut n); + match x { + Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1, + //~^ ERROR cannot assign `x` in match guard + Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1, + //~^ ERROR cannot mutably borrow `x` in match guard + Enum::A(p) => *p, + Enum::B(_) => 2, + } } + +fn main() {} diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr index 6d05e97252d92..dbb3272fdc351 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr @@ -1,5 +1,5 @@ error[E0510]: cannot assign `x` in match guard - --> $DIR/borrowck-mutate-in-guard.rs:10:25 + --> $DIR/borrowck-mutate-in-guard.rs:12:25 | LL | match x { | - value is immutable in match guard @@ -7,7 +7,7 @@ LL | Enum::A(_) if { x = Enum::B(false); false } => 1, | ^^^^^^^^^^^^^^^^^^ cannot assign error[E0510]: cannot mutably borrow `x` in match guard - --> $DIR/borrowck-mutate-in-guard.rs:12:33 + --> $DIR/borrowck-mutate-in-guard.rs:14:33 | LL | match x { | - value is immutable in match guard @@ -15,6 +15,23 @@ LL | match x { LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, | ^^^^^^ cannot mutably borrow -error: aborting due to 2 previous errors +error[E0510]: cannot assign `x` in match guard + --> $DIR/borrowck-mutate-in-guard.rs:25:40 + | +LL | match x { + | - value is immutable in match guard +LL | Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1, + | ^^^^^^^^^^^^^^^^^^ cannot assign + +error[E0510]: cannot mutably borrow `x` in match guard + --> $DIR/borrowck-mutate-in-guard.rs:27:48 + | +LL | match x { + | - value is immutable in match guard +... +LL | Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1, + | ^^^^^^ cannot mutably borrow + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0510`. diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.rs b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs index 07125b98a1f7d..5b824adc6e273 100644 --- a/src/test/ui/borrowck/issue-31287-drop-in-guard.rs +++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs @@ -1,8 +1,15 @@ +#![feature(if_let_guard)] + fn main() { let a = Some("...".to_owned()); let b = match a { Some(_) if { drop(a); false } => None, x => x, //~ ERROR use of moved value: `a` }; - println!("{:?}", b); + + let a = Some("...".to_owned()); + let b = match a { + Some(_) if let Some(()) = { drop(a); None } => None, + x => x, //~ ERROR use of moved value: `a` + }; } diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr index ad898fcabd9db..18f371c20735a 100644 --- a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr +++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `a` - --> $DIR/issue-31287-drop-in-guard.rs:5:9 + --> $DIR/issue-31287-drop-in-guard.rs:7:9 | LL | let a = Some("...".to_owned()); | - move occurs because `a` has type `Option`, which does not implement the `Copy` trait @@ -14,6 +14,22 @@ help: consider cloning the value if the performance cost is acceptable LL | Some(_) if { drop(a.clone()); false } => None, | ++++++++ -error: aborting due to previous error +error[E0382]: use of moved value: `a` + --> $DIR/issue-31287-drop-in-guard.rs:13:9 + | +LL | let a = Some("...".to_owned()); + | - move occurs because `a` has type `Option`, which does not implement the `Copy` trait +LL | let b = match a { +LL | Some(_) if let Some(()) = { drop(a); None } => None, + | - value moved here +LL | x => x, + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if let Some(()) = { drop(a.clone()); None } => None, + | ++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr index a8a2a47fe46e1..c2619d6df58b3 100644 --- a/src/test/ui/fmt/ifmt-bad-arg.stderr +++ b/src/test/ui/fmt/ifmt-bad-arg.stderr @@ -170,7 +170,7 @@ LL | format!("foo %s baz", "bar"); | | | help: format specifiers use curly braces: `{}` | - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` error: invalid format string: expected `'}'`, found `'t'` --> $DIR/ifmt-bad-arg.rs:75:1 diff --git a/src/test/ui/fmt/issue-89173.rs b/src/test/ui/fmt/issue-89173.rs index 96277d4d0d9d7..fc99af4085921 100644 --- a/src/test/ui/fmt/issue-89173.rs +++ b/src/test/ui/fmt/issue-89173.rs @@ -10,5 +10,5 @@ fn main() { //~| NOTE: argument never used //~| NOTE: argument never used //~| NOTE: format specifiers use curly braces, and you have to use a positional or named parameter for the width - //~| NOTE: printf formatting not supported + //~| NOTE: printf formatting is not supported } diff --git a/src/test/ui/fmt/issue-89173.stderr b/src/test/ui/fmt/issue-89173.stderr index 7b21e0a4fc896..ddeb769eadc52 100644 --- a/src/test/ui/fmt/issue-89173.stderr +++ b/src/test/ui/fmt/issue-89173.stderr @@ -12,7 +12,7 @@ note: format specifiers use curly braces, and you have to use a positional or na | LL | print!("%0*x", width, num); | ^^^^ - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-29723.rs b/src/test/ui/issues/issue-29723.rs index ce91022f093d4..399e9ba0df730 100644 --- a/src/test/ui/issues/issue-29723.rs +++ b/src/test/ui/issues/issue-29723.rs @@ -1,5 +1,7 @@ // test for https://github.com/rust-lang/rust/issues/29723 +#![feature(if_let_guard)] + fn main() { let s = String::new(); let _s = match 0 { @@ -11,4 +13,10 @@ fn main() { //~^ ERROR use of moved value: `s` } }; + + let s = String::new(); + let _s = match 0 { + 0 if let Some(()) = { drop(s); None } => String::from("oops"), + _ => s //~ ERROR use of moved value: `s` + }; } diff --git a/src/test/ui/issues/issue-29723.stderr b/src/test/ui/issues/issue-29723.stderr index 92ee5cf22b719..044d8a9b5dd1d 100644 --- a/src/test/ui/issues/issue-29723.stderr +++ b/src/test/ui/issues/issue-29723.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `s` - --> $DIR/issue-29723.rs:10:13 + --> $DIR/issue-29723.rs:12:13 | LL | let s = String::new(); | - move occurs because `s` has type `String`, which does not implement the `Copy` trait @@ -15,6 +15,22 @@ help: consider cloning the value if the performance cost is acceptable LL | 0 if { drop(s.clone()); false } => String::from("oops"), | ++++++++ -error: aborting due to previous error +error[E0382]: use of moved value: `s` + --> $DIR/issue-29723.rs:20:14 + | +LL | let s = String::new(); + | - move occurs because `s` has type `String`, which does not implement the `Copy` trait +LL | let _s = match 0 { +LL | 0 if let Some(()) = { drop(s); None } => String::from("oops"), + | - value moved here +LL | _ => s + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | 0 if let Some(()) = { drop(s.clone()); None } => String::from("oops"), + | ++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index ff5236dc949b2..7971c2ab2b9b2 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -8,7 +8,7 @@ LL | println!("%.*3$s %s!\n", "Hello,", "World", 4); | | argument never used | multiple missing formatting specifiers | - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` help: format specifiers use curly braces | LL | println!("{:.2$} {}!\n", "Hello,", "World", 4); @@ -22,7 +22,7 @@ LL | println!("%1$*2$.*3$f", 123.456); | | | help: format specifiers use curly braces: `{0:1$.2$}` | - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` error: multiple unused formatting arguments --> $DIR/format-foreign.rs:6:7 @@ -37,7 +37,7 @@ LL | | "###, "Hello,", "World", 4); | |____| argument never used | multiple missing formatting specifiers | - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` help: format specifiers use curly braces | LL ~ println!(r###"{:.2$} @@ -60,7 +60,7 @@ LL | println!("Hi there, $NAME.", NAME="Tim"); | | | help: format specifiers use curly braces: `{NAME}` | - = note: shell formatting not supported; see the documentation for `std::fmt` + = note: shell formatting is not supported; see the documentation for `std::fmt` error: multiple unused formatting arguments --> $DIR/format-foreign.rs:15:32 @@ -72,7 +72,7 @@ LL | println!("$1 $0 $$ $NAME", 1, 2, NAME=3); | | argument never used | multiple missing formatting specifiers | - = note: shell formatting not supported; see the documentation for `std::fmt` + = note: shell formatting is not supported; see the documentation for `std::fmt` help: format specifiers use curly braces | LL | println!("{1} {0} $$ {NAME}", 1, 2, NAME=3); diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr index 7423c7b7c8b47..fad87fa2aeea8 100644 --- a/src/test/ui/macros/format-unused-lables.stderr +++ b/src/test/ui/macros/format-unused-lables.stderr @@ -44,7 +44,7 @@ LL | "things" LL | , UNUSED="args"); | ^^^^^^ named argument never used | - = note: shell formatting not supported; see the documentation for `std::fmt` + = note: shell formatting is not supported; see the documentation for `std::fmt` error: aborting due to 4 previous errors diff --git a/src/test/ui/macros/issue-92267.stderr b/src/test/ui/macros/issue-92267.stderr index d2d66c81198ec..5359f68cd5517 100644 --- a/src/test/ui/macros/issue-92267.stderr +++ b/src/test/ui/macros/issue-92267.stderr @@ -10,7 +10,7 @@ note: format specifiers use curly braces, and the conversion specifier ` | LL | pub fn main() { println!("🦀%%%", 0) } | ^^ - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs index 7253d35ed2d4f..ccfc8937fd72e 100644 --- a/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs +++ b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs @@ -5,6 +5,8 @@ // See further discussion on rust-lang/rust#24535, // rust-lang/rfcs#1006, and rust-lang/rfcs#107 +#![feature(if_let_guard)] + fn main() { rust_issue_24535(); rfcs_issue_1006_1(); @@ -23,6 +25,12 @@ fn rust_issue_24535() { 3 if compare(&a, &mut 3) => (), _ => panic!("nope"), } + + match a { + 0 => panic!("nope"), + 3 if let true = compare(&a, &mut 3) => (), + _ => panic!("nope"), + } } fn rfcs_issue_1006_1() { diff --git a/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs b/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs index 4109c10e2e46b..85feda5824b40 100644 --- a/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs +++ b/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs @@ -7,6 +7,8 @@ // reaches the panic code when executed, despite the compiler warning // about that match arm being unreachable. +#![feature(if_let_guard)] + fn main() { let b = &mut true; match b { @@ -17,4 +19,16 @@ fn main() { &mut true => { println!("You might think we should get here"); }, _ => panic!("surely we could never get here, since rustc warns it is unreachable."), } + + let b = &mut true; + match b { + //~^ ERROR use of moved value: `b` [E0382] + &mut false => {} + _ if let Some(()) = { + (|| { let bar = b; *bar = false; })(); + None + } => {} + &mut true => {} + _ => {} + } } diff --git a/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr index 9be1a9279992b..ae7978004576b 100644 --- a/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `b` - --> $DIR/issue-27282-move-match-input-into-guard.rs:12:5 + --> $DIR/issue-27282-move-match-input-into-guard.rs:14:5 | LL | let b = &mut true; | - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait @@ -11,6 +11,19 @@ LL | _ if { (|| { let bar = b; *bar = false; })(); | | | value moved into closure here -error: aborting due to previous error +error[E0382]: use of moved value: `b` + --> $DIR/issue-27282-move-match-input-into-guard.rs:24:5 + | +LL | let b = &mut true; + | - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait +LL | match b { + | ^^^^^^^ value used here after move +... +LL | (|| { let bar = b; *bar = false; })(); + | -- - variable moved due to use in closure + | | + | value moved into closure here + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs index afa0ba780de46..833ca8afd618e 100644 --- a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs +++ b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs @@ -2,6 +2,8 @@ // mutable borrows in match guards by hiding the mutable borrow in a // guard behind a move (of the ref mut pattern id) within a closure. +#![feature(if_let_guard)] + fn main() { match Some(&4) { None => {}, @@ -10,4 +12,12 @@ fn main() { //~^ ERROR cannot move out of `foo` in pattern guard [E0507] Some(s) => std::process::exit(*s), } + + match Some(&4) { + None => {}, + ref mut foo + if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {}, + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + Some(s) => std::process::exit(*s), + } } diff --git a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr index a0d32616f83b7..45119018d4e60 100644 --- a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr +++ b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/issue-27282-move-ref-mut-into-guard.rs:9:19 + --> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19 | LL | if { (|| { let bar = foo; bar.take() })(); false } => {}, | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait @@ -8,6 +8,16 @@ LL | if { (|| { let bar = foo; bar.take() })(); false } => {}, | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34 + | +LL | if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {}, + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/nll/issue-27282-mutation-in-guard.rs b/src/test/ui/nll/issue-27282-mutation-in-guard.rs index 395c7d214d0ce..4f41fc23fc34b 100644 --- a/src/test/ui/nll/issue-27282-mutation-in-guard.rs +++ b/src/test/ui/nll/issue-27282-mutation-in-guard.rs @@ -1,3 +1,5 @@ +#![feature(if_let_guard)] + fn main() { match Some(&4) { None => {}, @@ -10,4 +12,15 @@ fn main() { Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."), _ => println!("Here is some supposedly unreachable code."), } + + match Some(&4) { + None => {}, + ref mut foo + if let Some(()) = { + (|| { let bar = foo; bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard + None + } => {}, + Some(_) => {}, + } } diff --git a/src/test/ui/nll/issue-27282-mutation-in-guard.stderr b/src/test/ui/nll/issue-27282-mutation-in-guard.stderr index c4ce7e62fda82..1ba696593afff 100644 --- a/src/test/ui/nll/issue-27282-mutation-in-guard.stderr +++ b/src/test/ui/nll/issue-27282-mutation-in-guard.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/issue-27282-mutation-in-guard.rs:6:18 + --> $DIR/issue-27282-mutation-in-guard.rs:8:18 | LL | (|| { let bar = foo; bar.take() })(); | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait @@ -8,6 +8,16 @@ LL | (|| { let bar = foo; bar.take() })(); | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/issue-27282-mutation-in-guard.rs:20:18 + | +LL | (|| { let bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs index 82d8b9e9ed977..ac06b2b01028f 100644 --- a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs +++ b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs @@ -3,7 +3,9 @@ // It reborrows instead of moving the `ref mut` pattern borrow. This // means that our conservative check for mutation in guards will // reject it. But I want to make sure that we continue to reject it -// (under NLL) even when that conservaive check goes away. +// (under NLL) even when that conservative check goes away. + +#![feature(if_let_guard)] fn main() { let mut b = &mut true; @@ -15,4 +17,14 @@ fn main() { &mut true => { println!("You might think we should get here"); }, _ => panic!("surely we could never get here, since rustc warns it is unreachable."), } + + let mut b = &mut true; + match b { + &mut false => {}, + ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })(); + //~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard + None } => { &mut *r; }, + &mut true => {}, + _ => {}, + } } diff --git a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr index 48433432de1bd..5eb7a25bf9f50 100644 --- a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr +++ b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard - --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:12:25 + --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:14:25 | LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); | ^^ -- mutable borrow occurs due to use of `r` in closure @@ -8,6 +8,16 @@ LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); | = note: variables bound in patterns are immutable until the end of the pattern guard -error: aborting due to previous error +error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard + --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:24:40 + | +LL | ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })(); + | ^^ -- mutable borrow occurs due to use of `r` in closure + | | + | cannot borrow as mutable + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs index 252f7f8ba07cf..1afc7931a6b62 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.rs +++ b/src/test/ui/nll/match-cfg-fake-edges.rs @@ -1,6 +1,8 @@ // Test that we have enough false edges to avoid exposing the exact matching // algorithm in borrow checking. +#![feature(if_let_guard)] + fn guard_always_precedes_arm(y: i32) { let mut x; // x should always be initialized, as the only way to reach the arm is @@ -9,6 +11,12 @@ fn guard_always_precedes_arm(y: i32) { 0 | 2 if { x = 2; true } => x, _ => 2, }; + + let mut x; + match y { + 0 | 2 if let Some(()) = { x = 2; Some(()) } => x, + _ => 2, + }; } fn guard_may_be_skipped(y: i32) { @@ -23,6 +31,16 @@ fn guard_may_be_skipped(y: i32) { } => 2, _ => 3, }; + + let x; + match y { + _ if let Some(()) = { x = 2; Some(()) } => 1, + _ if let Some(()) = { + x; //~ ERROR E0381 + None + } => 2, + _ => 3, + }; } fn guard_may_be_taken(y: bool) { @@ -37,6 +55,16 @@ fn guard_may_be_taken(y: bool) { } false => 3, }; + + let x = String::new(); + match y { + false if let Some(()) = { drop(x); Some(()) } => 1, + true => { + x; //~ ERROR use of moved value: `x` + 2 + } + false => 3, + }; } fn main() {} diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr index f72ed3af71823..a6261345ceac7 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.stderr +++ b/src/test/ui/nll/match-cfg-fake-edges.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `x` isn't initialized - --> $DIR/match-cfg-fake-edges.rs:21:13 + --> $DIR/match-cfg-fake-edges.rs:29:13 | LL | let x; | - binding declared here but left uninitialized @@ -15,8 +15,25 @@ help: consider assigning a value LL | let x = 0; | +++ +error[E0381]: used binding `x` isn't initialized + --> $DIR/match-cfg-fake-edges.rs:39:13 + | +LL | let x; + | - binding declared here but left uninitialized +LL | match y { +LL | _ if let Some(()) = { x = 2; Some(()) } => 1, + | ----- binding initialized here in some conditions +LL | _ if let Some(()) = { +LL | x; + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x = 0; + | +++ + error[E0382]: use of moved value: `x` - --> $DIR/match-cfg-fake-edges.rs:35:13 + --> $DIR/match-cfg-fake-edges.rs:53:13 | LL | let x = String::new(); | - move occurs because `x` has type `String`, which does not implement the `Copy` trait @@ -32,7 +49,24 @@ help: consider cloning the value if the performance cost is acceptable LL | false if { drop(x.clone()); true } => 1, | ++++++++ -error: aborting due to 2 previous errors +error[E0382]: use of moved value: `x` + --> $DIR/match-cfg-fake-edges.rs:63:13 + | +LL | let x = String::new(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | match y { +LL | false if let Some(()) = { drop(x); Some(()) } => 1, + | - value moved here +LL | true => { +LL | x; + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | false if let Some(()) = { drop(x.clone()); Some(()) } => 1, + | ++++++++ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0381, E0382. For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/nll/match-guards-always-borrow.rs b/src/test/ui/nll/match-guards-always-borrow.rs index 87dba187ba2c2..ff63cc092734a 100644 --- a/src/test/ui/nll/match-guards-always-borrow.rs +++ b/src/test/ui/nll/match-guards-always-borrow.rs @@ -1,3 +1,5 @@ +#![feature(if_let_guard)] + // Here is arielb1's basic example from rust-lang/rust#27282 // that AST borrowck is flummoxed by: @@ -10,6 +12,15 @@ fn should_reject_destructive_mutate_in_guard() { false } => { }, Some(s) => std::process::exit(*s), } + + match Some(&4) { + None => {}, + ref mut foo if let Some(()) = { + (|| { let bar = foo; bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + None } => { }, + Some(s) => std::process::exit(*s), + } } // Here below is a case that needs to keep working: we only use the @@ -18,7 +29,13 @@ fn should_reject_destructive_mutate_in_guard() { fn allow_mutate_in_arm_body() { match Some(&4) { None => {}, - ref mut foo if foo.is_some() && false => { foo.take(); () } + ref mut foo if foo.is_some() => { foo.take(); () } + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + ref mut foo if let Some(_) = foo => { foo.take(); () } Some(s) => std::process::exit(*s), } } @@ -29,7 +46,13 @@ fn allow_mutate_in_arm_body() { fn allow_move_into_arm_body() { match Some(&4) { None => {}, - mut foo if foo.is_some() && false => { foo.take(); () } + mut foo if foo.is_some() => { foo.unwrap(); () } + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + mut foo if let Some(_) = foo => { foo.unwrap(); () } Some(s) => std::process::exit(*s), } } diff --git a/src/test/ui/nll/match-guards-always-borrow.stderr b/src/test/ui/nll/match-guards-always-borrow.stderr index c0fb5f65382dc..fa01d3a6fd1e0 100644 --- a/src/test/ui/nll/match-guards-always-borrow.stderr +++ b/src/test/ui/nll/match-guards-always-borrow.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/match-guards-always-borrow.rs:8:14 + --> $DIR/match-guards-always-borrow.rs:10:14 | LL | (|| { let bar = foo; bar.take() })(); | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait @@ -8,6 +8,16 @@ LL | (|| { let bar = foo; bar.take() })(); | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/match-guards-always-borrow.rs:19:14 + | +LL | (|| { let bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs index 81ae19ebf8a72..3a9e1654b1c2d 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.rs +++ b/src/test/ui/nll/match-guards-partially-borrow.rs @@ -5,7 +5,9 @@ // Test that we don't allow mutating the value being matched on in a way that // changes which patterns it matches, until we have chosen an arm. -fn ok_mutation_in_guard(mut q: i32) { +#![feature(if_let_guard)] + +fn ok_mutation_in_if_guard(mut q: i32) { match q { // OK, mutation doesn't change which patterns g matches _ if { q = 1; false } => (), @@ -13,7 +15,15 @@ fn ok_mutation_in_guard(mut q: i32) { } } -fn ok_mutation_in_guard2(mut u: bool) { +fn ok_mutation_in_if_let_guard(mut q: i32) { + match q { + // OK, mutation doesn't change which patterns g matches + _ if let Some(()) = { q = 1; None } => (), + _ => (), + } +} + +fn ok_mutation_in_if_guard2(mut u: bool) { // OK value of u is unused before modification match u { _ => (), @@ -25,7 +35,19 @@ fn ok_mutation_in_guard2(mut u: bool) { } } -fn ok_mutation_in_guard4(mut w: (&mut bool,)) { +fn ok_mutation_in_if_let_guard2(mut u: bool) { + // OK value of u is unused before modification + match u { + _ => (), + _ if let Some(()) = { + u = true; + None + } => (), + x => (), + } +} + +fn ok_mutation_in_if_guard4(mut w: (&mut bool,)) { // OK value of u is unused before modification match w { _ => (), @@ -37,7 +59,19 @@ fn ok_mutation_in_guard4(mut w: (&mut bool,)) { } } -fn ok_indirect_mutation_in_guard(mut p: &bool) { +fn ok_mutation_in_if_let_guard4(mut w: (&mut bool,)) { + // OK value of u is unused before modification + match w { + _ => (), + _ if let Some(()) = { + *w.0 = true; + None + } => (), + x => (), + } +} + +fn ok_indirect_mutation_in_if_guard(mut p: &bool) { match *p { // OK, mutation doesn't change which patterns s matches _ if { @@ -48,7 +82,18 @@ fn ok_indirect_mutation_in_guard(mut p: &bool) { } } -fn mutation_invalidates_pattern_in_guard(mut q: bool) { +fn ok_indirect_mutation_in_if_let_guard(mut p: &bool) { + match *p { + // OK, mutation doesn't change which patterns s matches + _ if let Some(()) = { + p = &true; + None + } => (), + _ => (), + } +} + +fn mutation_invalidates_pattern_in_if_guard(mut q: bool) { match q { // q doesn't match the pattern with the guard by the end of the guard. false if { @@ -59,7 +104,18 @@ fn mutation_invalidates_pattern_in_guard(mut q: bool) { } } -fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) { +fn mutation_invalidates_pattern_in_if_let_guard(mut q: bool) { + match q { + // q doesn't match the pattern with the guard by the end of the guard. + false if let Some(()) = { + q = true; //~ ERROR + Some(()) + } => (), + _ => (), + } +} + +fn mutation_invalidates_previous_pattern_in_if_guard(mut r: bool) { match r { // r matches a previous pattern by the end of the guard. true => (), @@ -71,7 +127,19 @@ fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) { } } -fn match_on_borrowed_early_end(mut s: bool) { +fn mutation_invalidates_previous_pattern_in_if_let_guard(mut r: bool) { + match r { + // r matches a previous pattern by the end of the guard. + true => (), + _ if let Some(()) = { + r = true; //~ ERROR + Some(()) + } => (), + _ => (), + } +} + +fn match_on_borrowed_early_end_if_guard(mut s: bool) { let h = &mut s; // OK value of s is unused before modification. match s { @@ -84,7 +152,20 @@ fn match_on_borrowed_early_end(mut s: bool) { } } -fn bad_mutation_in_guard(mut t: bool) { +fn match_on_borrowed_early_end_if_let_guard(mut s: bool) { + let h = &mut s; + // OK value of s is unused before modification. + match s { + _ if let Some(()) = { + *h = !*h; + None + } => (), + true => (), + false => (), + } +} + +fn bad_mutation_in_if_guard(mut t: bool) { match t { true => (), false if { @@ -95,7 +176,18 @@ fn bad_mutation_in_guard(mut t: bool) { } } -fn bad_mutation_in_guard2(mut x: Option>) { +fn bad_mutation_in_if_let_guard(mut t: bool) { + match t { + true => (), + false if let Some(()) = { + t = true; //~ ERROR + None + } => (), + false => (), + } +} + +fn bad_mutation_in_if_guard2(mut x: Option>) { // Check that nested patterns are checked. match x { None => (), @@ -111,7 +203,23 @@ fn bad_mutation_in_guard2(mut x: Option>) { } } -fn bad_mutation_in_guard3(mut t: bool) { +fn bad_mutation_in_if_let_guard2(mut x: Option>) { + // Check that nested patterns are checked. + match x { + None => (), + Some(None) => (), + _ if let Some(()) = { + match x { + Some(ref mut r) => *r = None, //~ ERROR + _ => return, + }; + None + } => (), + Some(Some(r)) => println!("{}", r), + } +} + +fn bad_mutation_in_if_guard3(mut t: bool) { match t { s if { t = !t; //~ ERROR @@ -121,7 +229,17 @@ fn bad_mutation_in_guard3(mut t: bool) { } } -fn bad_indirect_mutation_in_guard(mut y: &bool) { +fn bad_mutation_in_if_let_guard3(mut t: bool) { + match t { + s if let Some(()) = { + t = !t; //~ ERROR + None + } => (), // What value should `s` have in the arm? + _ => (), + } +} + +fn bad_indirect_mutation_in_if_guard(mut y: &bool) { match *y { true => (), false if { @@ -132,7 +250,18 @@ fn bad_indirect_mutation_in_guard(mut y: &bool) { } } -fn bad_indirect_mutation_in_guard2(mut z: &bool) { +fn bad_indirect_mutation_in_if_let_guard(mut y: &bool) { + match *y { + true => (), + false if let Some(()) = { + y = &true; //~ ERROR + None + } => (), + false => (), + } +} + +fn bad_indirect_mutation_in_if_guard2(mut z: &bool) { match z { &true => (), &false if { @@ -143,8 +272,19 @@ fn bad_indirect_mutation_in_guard2(mut z: &bool) { } } -fn bad_indirect_mutation_in_guard3(mut a: &bool) { - // Same as bad_indirect_mutation_in_guard2, but using match ergonomics +fn bad_indirect_mutation_in_if_let_guard2(mut z: &bool) { + match z { + &true => (), + &false if let Some(()) = { + z = &true; //~ ERROR + None + } => (), + &false => (), + } +} + +fn bad_indirect_mutation_in_if_guard3(mut a: &bool) { + // Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics match a { true => (), false if { @@ -155,7 +295,19 @@ fn bad_indirect_mutation_in_guard3(mut a: &bool) { } } -fn bad_indirect_mutation_in_guard4(mut b: &bool) { +fn bad_indirect_mutation_in_if_let_guard3(mut a: &bool) { + // Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics + match a { + true => (), + false if let Some(()) = { + a = &true; //~ ERROR + None + } => (), + false => (), + } +} + +fn bad_indirect_mutation_in_if_guard4(mut b: &bool) { match b { &_ => (), &_ if { @@ -166,4 +318,15 @@ fn bad_indirect_mutation_in_guard4(mut b: &bool) { } } +fn bad_indirect_mutation_in_if_let_guard4(mut b: &bool) { + match b { + &_ => (), + &_ if let Some(()) = { + b = &true; //~ ERROR + None + } => (), + &b => (), + } +} + fn main() {} diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr index 48e3a7c699318..60b8dee71a863 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.stderr +++ b/src/test/ui/nll/match-guards-partially-borrow.stderr @@ -1,5 +1,5 @@ error[E0510]: cannot assign `q` in match guard - --> $DIR/match-guards-partially-borrow.rs:55:13 + --> $DIR/match-guards-partially-borrow.rs:100:13 | LL | match q { | - value is immutable in match guard @@ -7,8 +7,26 @@ LL | match q { LL | q = true; | ^^^^^^^^ cannot assign +error[E0510]: cannot assign `q` in match guard + --> $DIR/match-guards-partially-borrow.rs:111:13 + | +LL | match q { + | - value is immutable in match guard +... +LL | q = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `r` in match guard + --> $DIR/match-guards-partially-borrow.rs:123:13 + | +LL | match r { + | - value is immutable in match guard +... +LL | r = true; + | ^^^^^^^^ cannot assign + error[E0510]: cannot assign `r` in match guard - --> $DIR/match-guards-partially-borrow.rs:67:13 + --> $DIR/match-guards-partially-borrow.rs:135:13 | LL | match r { | - value is immutable in match guard @@ -17,7 +35,16 @@ LL | r = true; | ^^^^^^^^ cannot assign error[E0510]: cannot assign `t` in match guard - --> $DIR/match-guards-partially-borrow.rs:91:13 + --> $DIR/match-guards-partially-borrow.rs:172:13 + | +LL | match t { + | - value is immutable in match guard +... +LL | t = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `t` in match guard + --> $DIR/match-guards-partially-borrow.rs:183:13 | LL | match t { | - value is immutable in match guard @@ -26,7 +53,16 @@ LL | t = true; | ^^^^^^^^ cannot assign error[E0510]: cannot mutably borrow `x.0` in match guard - --> $DIR/match-guards-partially-borrow.rs:105:22 + --> $DIR/match-guards-partially-borrow.rs:197:22 + | +LL | match x { + | - value is immutable in match guard +... +LL | Some(ref mut r) => *r = None, + | ^^^^^^^^^ cannot mutably borrow + +error[E0510]: cannot mutably borrow `x.0` in match guard + --> $DIR/match-guards-partially-borrow.rs:213:22 | LL | match x { | - value is immutable in match guard @@ -35,7 +71,7 @@ LL | Some(ref mut r) => *r = None, | ^^^^^^^^^ cannot mutably borrow error[E0506]: cannot assign to `t` because it is borrowed - --> $DIR/match-guards-partially-borrow.rs:117:13 + --> $DIR/match-guards-partially-borrow.rs:225:13 | LL | s if { | - borrow of `t` occurs here @@ -45,8 +81,28 @@ LL | false LL | } => (), // What value should `s` have in the arm? | - borrow later used here +error[E0506]: cannot assign to `t` because it is borrowed + --> $DIR/match-guards-partially-borrow.rs:235:13 + | +LL | s if let Some(()) = { + | - borrow of `t` occurs here +LL | t = !t; + | ^^^^^^ assignment to borrowed `t` occurs here +LL | None +LL | } => (), // What value should `s` have in the arm? + | - borrow later used here + +error[E0510]: cannot assign `y` in match guard + --> $DIR/match-guards-partially-borrow.rs:246:13 + | +LL | match *y { + | -- value is immutable in match guard +... +LL | y = &true; + | ^^^^^^^^^ cannot assign + error[E0510]: cannot assign `y` in match guard - --> $DIR/match-guards-partially-borrow.rs:128:13 + --> $DIR/match-guards-partially-borrow.rs:257:13 | LL | match *y { | -- value is immutable in match guard @@ -55,7 +111,16 @@ LL | y = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `z` in match guard - --> $DIR/match-guards-partially-borrow.rs:139:13 + --> $DIR/match-guards-partially-borrow.rs:268:13 + | +LL | match z { + | - value is immutable in match guard +... +LL | z = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `z` in match guard + --> $DIR/match-guards-partially-borrow.rs:279:13 | LL | match z { | - value is immutable in match guard @@ -64,7 +129,16 @@ LL | z = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `a` in match guard - --> $DIR/match-guards-partially-borrow.rs:151:13 + --> $DIR/match-guards-partially-borrow.rs:291:13 + | +LL | match a { + | - value is immutable in match guard +... +LL | a = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `a` in match guard + --> $DIR/match-guards-partially-borrow.rs:303:13 | LL | match a { | - value is immutable in match guard @@ -73,7 +147,16 @@ LL | a = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `b` in match guard - --> $DIR/match-guards-partially-borrow.rs:162:13 + --> $DIR/match-guards-partially-borrow.rs:314:13 + | +LL | match b { + | - value is immutable in match guard +... +LL | b = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `b` in match guard + --> $DIR/match-guards-partially-borrow.rs:325:13 | LL | match b { | - value is immutable in match guard @@ -81,7 +164,7 @@ LL | match b { LL | b = &true; | ^^^^^^^^^ cannot assign -error: aborting due to 9 previous errors +error: aborting due to 18 previous errors Some errors have detailed explanations: E0506, E0510. For more information about an error, try `rustc --explain E0506`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs index d1f685f3e7a6d..6f0d2b045918d 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs @@ -1,6 +1,8 @@ +#![feature(if_let_guard)] + enum VecWrapper { A(Vec) } -fn foo(x: VecWrapper) -> usize { +fn if_guard(x: VecWrapper) -> usize { match x { VecWrapper::A(v) if { drop(v); false } => 1, //~^ ERROR cannot move out of `v` in pattern guard @@ -8,6 +10,15 @@ fn foo(x: VecWrapper) -> usize { } } +fn if_let_guard(x: VecWrapper) -> usize { + match x { + VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1, + //~^ ERROR cannot move out of `v` in pattern guard + VecWrapper::A(v) => v.len() + } +} + fn main() { - foo(VecWrapper::A(vec![107])); + if_guard(VecWrapper::A(vec![107])); + if_let_guard(VecWrapper::A(vec![107])); } diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr index 6c3d1caf80715..a749361bf30ee 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr @@ -1,11 +1,19 @@ error[E0507]: cannot move out of `v` in pattern guard - --> $DIR/rfc-reject-double-move-across-arms.rs:5:36 + --> $DIR/rfc-reject-double-move-across-arms.rs:7:36 | LL | VecWrapper::A(v) if { drop(v); false } => 1, | ^ move occurs because `v` has type `Vec`, which does not implement the `Copy` trait | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `v` in pattern guard + --> $DIR/rfc-reject-double-move-across-arms.rs:15:51 + | +LL | VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1, + | ^ move occurs because `v` has type `Vec`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs index 571f51c900120..827335f6a8494 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs @@ -1,6 +1,8 @@ +#![feature(if_let_guard)] + struct A { a: Box } -fn foo(n: i32) { +fn if_guard(n: i32) { let x = A { a: Box::new(n) }; let _y = match x { A { a: v } if { drop(v); true } => v, @@ -9,6 +11,16 @@ fn foo(n: i32) { }; } +fn if_let_guard(n: i32) { + let x = A { a: Box::new(n) }; + let _y = match x { + A { a: v } if let Some(()) = { drop(v); Some(()) } => v, + //~^ ERROR cannot move out of `v` in pattern guard + _ => Box::new(0), + }; +} + fn main() { - foo(107); + if_guard(107); + if_let_guard(107); } diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr index d1204bc26011f..9285492b22450 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr @@ -1,11 +1,19 @@ error[E0507]: cannot move out of `v` in pattern guard - --> $DIR/rfc-reject-double-move-in-first-arm.rs:6:30 + --> $DIR/rfc-reject-double-move-in-first-arm.rs:8:30 | LL | A { a: v } if { drop(v); true } => v, | ^ move occurs because `v` has type `Box`, which does not implement the `Copy` trait | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `v` in pattern guard + --> $DIR/rfc-reject-double-move-in-first-arm.rs:17:45 + | +LL | A { a: v } if let Some(()) = { drop(v); Some(()) } => v, + | ^ move occurs because `v` has type `Box`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index fff83a1d097b3..5f5ae3a65efa8 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -11,6 +11,7 @@ miropt-test-tools = { path = "../miropt-test-tools" } lazy_static = "1" walkdir = "2" ignore = "0.4.18" +semver = "1.0.14" termcolor = "1.1.3" [[bin]] diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index ce7e7ac5cd4ca..4075f2616b0fd 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -69,3 +69,4 @@ pub mod ui_tests; pub mod unit_tests; pub mod unstable_book; pub mod walk; +pub mod x_version; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 6714c63ee62a1..7bb8ddc6949ef 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -58,7 +58,7 @@ fn main() { let handle = s.spawn(|| { let mut flag = false; - $p::check($($args),* , &mut flag); + $p::check($($args, )* &mut flag); if (flag) { bad.store(true, Ordering::Relaxed); } @@ -107,6 +107,8 @@ fn main() { check!(alphabetical, &compiler_path); check!(alphabetical, &library_path); + check!(x_version, &root_path, &cargo); + let collected = { drain_handles(&mut handles); diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs new file mode 100644 index 0000000000000..5dc6a0588c32b --- /dev/null +++ b/src/tools/tidy/src/x_version.rs @@ -0,0 +1,65 @@ +use semver::Version; +use std::io::ErrorKind; +use std::path::Path; +use std::process::{Command, Stdio}; + +pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { + let result = Command::new("x").arg("--wrapper-version").stdout(Stdio::piped()).spawn(); + // This runs the command inside a temporary directory. + // This allows us to compare output of result to see if `--wrapper-version` is not a recognized argument to x. + let temp_result = Command::new("x") + .arg("--wrapper-version") + .current_dir(std::env::temp_dir()) + .stdout(Stdio::piped()) + .spawn(); + + let (child, temp_child) = match (result, temp_result) { + (Ok(child), Ok(temp_child)) => (child, temp_child), + (Err(e), _) | (_, Err(e)) => match e.kind() { + ErrorKind::NotFound => return, + _ => return tidy_error!(bad, "failed to run `x`: {}", e), + }, + }; + + let output = child.wait_with_output().unwrap(); + let temp_output = temp_child.wait_with_output().unwrap(); + + if output != temp_output { + return tidy_error!( + bad, + "Current version of x does not support the `--wrapper-version` argument\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" + ); + } + + if output.status.success() { + let version = String::from_utf8_lossy(&output.stdout); + let version = Version::parse(version.trim_end()).unwrap(); + + if let Some(expected) = get_x_wrapper_version(root, cargo) { + if version < expected { + return tidy_error!( + bad, + "Current version of x is {version}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" + ); + } + } else { + return tidy_error!( + bad, + "Unable to parse the latest version of `x` at `src/tools/x/Cargo.toml`" + ); + } + } else { + return tidy_error!(bad, "failed to check version of `x`: {}", output.status); + } +} + +// Parse latest version out of `x` Cargo.toml +fn get_x_wrapper_version(root: &Path, cargo: &Path) -> Option { + let mut cmd = cargo_metadata::MetadataCommand::new(); + cmd.cargo_path(cargo) + .manifest_path(root.join("src/tools/x/Cargo.toml")) + .no_deps() + .features(cargo_metadata::CargoOpt::AllFeatures); + let mut metadata = t!(cmd.exec()); + metadata.packages.pop().map(|x| x.version) +} diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs index f07ff43efe987..01f7187851e38 100644 --- a/src/tools/x/src/main.rs +++ b/src/tools/x/src/main.rs @@ -52,6 +52,14 @@ fn exec_or_status(command: &mut Command) -> io::Result { } fn main() { + match env::args().skip(1).next().as_deref() { + Some("--wrapper-version") => { + let version = env!("CARGO_PKG_VERSION"); + println!("{}", version); + return; + } + _ => {} + } let current = match env::current_dir() { Ok(dir) => dir, Err(err) => {