diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b600074c19770..2827a46ae6f73 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,31 @@ # Contributing to Rust -Thank you for your interest in contributing to Rust! +Thank you for your interest in contributing to Rust! There are many ways to contribute +and we appreciate all of them. -To get started, read the [Contributing to Rust] chapter of the [rustc-dev-guide]. +Documentation for contributing to Rust is located in the [Guide to Rustc Development](https://rustc-dev-guide.rust-lang.org/), +commonly known as the [rustc-dev-guide]. Despite the name, this guide documents +not just how to develop rustc (the Rust compiler), but also how to contribute to any part +of the Rust project. + +To get started with contributing, please read the [Contributing to Rust] chapter of the guide. +That chapter explains how to get your development environment set up and how to get help. + +## About the [rustc-dev-guide] + +The [rustc-dev-guide] is meant to help document how rustc –the Rust compiler– works, +as well as to help new contributors get involved in rustc development. It is recommend +to read and understand the [rustc-dev-guide] before making a contribution. This guide +talks about the different bots in the Rust ecosystem, the Rust development tools, +bootstrapping, the compiler architecture, source code representation, and more. + +## [Getting help](https://rustc-dev-guide.rust-lang.org/getting-started.html#asking-questions) + +There are many ways you can get help when you're stuck. Rust has many platforms for this: +[internals], [rust-zulip], and [rust-discord]. It is recommended to ask for help on +the [rust-zulip], but any of these platforms are a great way to seek help and even +find a mentor! You can learn more about asking questions and getting help in the +[Asking Questions](https://rustc-dev-guide.rust-lang.org/getting-started.html#asking-questions) chapter of the [rustc-dev-guide]. ## Bug reports @@ -13,3 +36,6 @@ refer to [this section][contributing-bug-reports] and [open an issue][issue temp [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ [contributing-bug-reports]: https://rustc-dev-guide.rust-lang.org/contributing.html#bug-reports [issue template]: https://github.com/rust-lang/rust/issues/new/choose +[internals]: https://internals.rust-lang.org +[rust-discord]: http://discord.gg/rust-lang +[rust-zulip]: https://rust-lang.zulipchat.com diff --git a/Cargo.lock b/Cargo.lock index c067fca5545d6..120403b3bf64c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,7 +37,7 @@ version = "0.0.0" dependencies = [ "compiler_builtins", "core", - "rand", + "rand 0.7.3", "rand_xorshift", ] @@ -325,6 +325,7 @@ dependencies = [ "openssl", "percent-encoding 2.1.0", "pretty_env_logger", + "rand 0.8.3", "rustc-workspace-hack", "rustfix", "same-file", @@ -757,7 +758,7 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" name = "core" version = "0.0.0" dependencies = [ - "rand", + "rand 0.7.3", ] [[package]] @@ -1662,7 +1663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f" dependencies = [ "bitmaps", - "rand_core", + "rand_core 0.5.1", "rand_xoshiro", "sized-chunks", "typenum", @@ -1867,7 +1868,7 @@ dependencies = [ "lazy_static", "log", "parking_lot", - "rand", + "rand 0.7.3", "serde", ] @@ -1912,9 +1913,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.85" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" +checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" dependencies = [ "rustc-std-workspace-core", ] @@ -2308,7 +2309,7 @@ dependencies = [ "hex 0.4.2", "libc", "log", - "rand", + "rand 0.7.3", "rustc-workspace-hack", "rustc_version", "shell-escape", @@ -2508,7 +2509,7 @@ dependencies = [ "log", "mio-named-pipes", "miow 0.3.6", - "rand", + "rand 0.7.3", "tokio", "winapi 0.3.9", ] @@ -2645,7 +2646,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" dependencies = [ "phf_shared", - "rand", + "rand 0.7.3", ] [[package]] @@ -2892,12 +2893,24 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom 0.1.14", "libc", - "rand_chacha", - "rand_core", - "rand_hc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", "rand_pcg", ] +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha 0.3.0", + "rand_core 0.6.2", + "rand_hc 0.3.0", +] + [[package]] name = "rand_chacha" version = "0.2.2" @@ -2905,7 +2918,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.2", ] [[package]] @@ -2917,13 +2940,31 @@ dependencies = [ "getrandom 0.1.14", ] +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom 0.2.0", +] + [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core 0.6.2", ] [[package]] @@ -2932,7 +2973,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" dependencies = [ - "rand_core", + "rand_core 0.5.1", ] [[package]] @@ -2941,7 +2982,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" dependencies = [ - "rand_core", + "rand_core 0.5.1", ] [[package]] @@ -2950,7 +2991,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" dependencies = [ - "rand_core", + "rand_core 0.5.1", ] [[package]] @@ -3082,7 +3123,7 @@ dependencies = [ "num_cpus", "ordslice", "racer", - "rand", + "rand 0.7.3", "rayon", "regex", "rls-analysis", @@ -3153,7 +3194,7 @@ dependencies = [ "env_logger 0.7.1", "futures 0.3.12", "log", - "rand", + "rand 0.7.3", "rls-data", "rls-ipc", "serde", @@ -3933,7 +3974,7 @@ dependencies = [ name = "rustc_incremental" version = "0.0.0" dependencies = [ - "rand", + "rand 0.7.3", "rustc_ast", "rustc_data_structures", "rustc_fs_util", @@ -4975,7 +5016,7 @@ dependencies = [ "panic_abort", "panic_unwind", "profiler_builtins", - "rand", + "rand 0.7.3", "rustc-demangle", "unwind", "wasi", @@ -5106,7 +5147,7 @@ checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ "cfg-if 0.1.10", "libc", - "rand", + "rand 0.7.3", "redox_syscall 0.1.57", "remove_dir_all", "winapi 0.3.9", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 77a98f4c45c53..d6297addc0cef 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1073,7 +1073,7 @@ pub struct Expr { } // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Expr, 120); impl Expr { @@ -2755,7 +2755,7 @@ pub enum ItemKind { MacroDef(MacroDef), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(ItemKind, 112); impl ItemKind { @@ -2829,7 +2829,7 @@ pub enum AssocItemKind { MacCall(MacCall), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(AssocItemKind, 72); impl AssocItemKind { @@ -2881,7 +2881,7 @@ pub enum ForeignItemKind { MacCall(MacCall), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(ForeignItemKind, 72); impl From for ItemKind { diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 90bfb01d6c791..71792acb37d13 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -244,7 +244,7 @@ pub enum TokenKind { } // `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(TokenKind, 16); #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] @@ -682,7 +682,7 @@ pub enum Nonterminal { } // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Nonterminal, 48); #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)] diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 9ac05f316f034..c5c3142602b9b 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -189,7 +189,7 @@ pub struct TokenStream(pub(crate) Lrc>); pub type TreeAndSpacing = (TokenTree, Spacing); // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(TokenStream, 8); #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a0be7442d597a..1db39fbfba502 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -52,7 +52,7 @@ pub type PResult<'a, T> = Result>; // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. // (See also the comment on `DiagnosticBuilderInner`.) -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16); #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 3cc501e423c0b..1938cdd1e46f4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3088,7 +3088,7 @@ impl<'hir> Node<'hir> { } // Some nodes are used a lot. Make sure they don't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { rustc_data_structures::static_assert_size!(super::Block<'static>, 48); rustc_data_structures::static_assert_size!(super::Expr<'static>, 72); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 09eecd715f03b..3df58cb7857f1 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -408,7 +408,7 @@ pub enum SubregionOrigin<'tcx> { } // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(SubregionOrigin<'_>, 32); /// Times when we replace late-bound regions with variables: diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 3690a88c0d973..f9170ef5dc346 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -27,7 +27,7 @@ #[macro_use] extern crate rustc_macros; -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[macro_use] extern crate rustc_data_structures; #[macro_use] diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index aaf5e958c269d..0882d682e1537 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -56,7 +56,7 @@ pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(PredicateObligation<'_>, 32); pub type PredicateObligations<'tcx> = Vec>; diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index e222f82f20a91..997b91363201f 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -872,7 +872,7 @@ impl EarlyLintPass for UnusedParens { fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { if let StmtKind::Local(ref local) = s.kind { - self.check_unused_parens_pat(cx, &local.pat, false, false); + self.check_unused_parens_pat(cx, &local.pat, true, false); } ::check_stmt(self, cx, s) diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 1589ab28e4043..b2b969e9b34e8 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -40,7 +40,7 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<' struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg) } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(InterpErrorInfo<'_>, 8); /// Packages the kind of error we got from the const code interpreter @@ -444,7 +444,7 @@ impl dyn MachineStopType { } } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(InterpError<'_>, 72); pub enum InterpError<'tcx> { diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 4bb39fe4a527e..a07ccd4d2b528 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -44,7 +44,7 @@ pub enum ConstValue<'tcx> { }, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstValue<'_>, 32); impl<'tcx> ConstValue<'tcx> { @@ -111,7 +111,7 @@ pub enum Scalar { Ptr(Pointer), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Scalar, 24); // We want the `Debug` output to be readable as it is used by `derive(Debug)` for @@ -509,7 +509,7 @@ pub enum ScalarMaybeUninit { Uninit, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ScalarMaybeUninit, 24); impl From> for ScalarMaybeUninit { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index f202336578071..42bbc9a0d9552 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -951,7 +951,7 @@ pub struct LocalDecl<'tcx> { } // `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(LocalDecl<'_>, 56); /// Extra information about a some locals that's used for diagnostics and for @@ -1468,7 +1468,7 @@ pub struct Statement<'tcx> { } // `Statement` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Statement<'_>, 32); impl Statement<'_> { @@ -1755,7 +1755,7 @@ impl ProjectionElem { pub type PlaceElem<'tcx> = ProjectionElem>; // At least on 64 bit systems, `PlaceElem` should not be larger than two pointers. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(PlaceElem<'_>, 24); /// Alias for projections as they appear in `UserTypeProjection`, where we diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 3c7a6aa00c3fe..3961fd938be26 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -17,7 +17,7 @@ pub struct PlaceTy<'tcx> { } // At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(PlaceTy<'_>, 16); impl<'tcx> PlaceTy<'tcx> { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 9deeaf462d65d..0bd0a701fb2e7 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -340,7 +340,7 @@ impl ObligationCauseCode<'_> { } // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ObligationCauseCode<'_>, 32); #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index ed953b981130a..e7b2c9efd63cf 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -23,7 +23,7 @@ pub struct Const<'tcx> { pub val: ConstKind<'tcx>, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index a2638d8bddad0..98c215407a8e0 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -37,7 +37,7 @@ pub enum ConstKind<'tcx> { Error(ty::DelaySpanBugEmitted), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstKind<'_>, 40); impl<'tcx> ConstKind<'tcx> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c27a337554e67..6b9186d476b69 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -483,7 +483,7 @@ impl<'tcx> TyS<'tcx> { } // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(TyS<'_>, 32); impl<'tcx> Ord for TyS<'tcx> { @@ -1030,7 +1030,7 @@ crate struct PredicateInner<'tcx> { outer_exclusive_binder: ty::DebruijnIndex, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(PredicateInner<'_>, 40); #[derive(Clone, Copy, Lift)] diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 6c074d3af5c4b..2cd969d7a16ab 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -231,7 +231,7 @@ impl TyKind<'tcx> { } // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(TyKind<'_>, 24); /// A closure can be modeled as a struct that looks like: diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index 901ed6809f24f..2c4aba19e4a2e 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -32,7 +32,7 @@ pub enum Immediate { ScalarPair(ScalarMaybeUninit, ScalarMaybeUninit), } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Immediate, 56); impl From> for Immediate { @@ -95,7 +95,7 @@ pub struct ImmTy<'tcx, Tag = ()> { pub layout: TyAndLayout<'tcx>, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(ImmTy<'_>, 72); impl std::fmt::Display for ImmTy<'tcx, Tag> { @@ -162,7 +162,7 @@ pub struct OpTy<'tcx, Tag = ()> { pub layout: TyAndLayout<'tcx>, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(OpTy<'_, ()>, 80); impl<'tcx, Tag> std::ops::Deref for OpTy<'tcx, Tag> { diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_mir/src/interpret/place.rs index 392f739e84fd6..7ba79e6f75989 100644 --- a/compiler/rustc_mir/src/interpret/place.rs +++ b/compiler/rustc_mir/src/interpret/place.rs @@ -33,7 +33,7 @@ pub enum MemPlaceMeta { Poison, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(MemPlaceMeta, 24); impl MemPlaceMeta { @@ -74,7 +74,7 @@ pub struct MemPlace { pub meta: MemPlaceMeta, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(MemPlace, 56); #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable)] @@ -87,7 +87,7 @@ pub enum Place { Local { frame: usize, local: mir::Local }, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Place, 64); #[derive(Copy, Clone, Debug)] @@ -96,7 +96,7 @@ pub struct PlaceTy<'tcx, Tag = ()> { pub layout: TyAndLayout<'tcx>, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(PlaceTy<'_>, 80); impl<'tcx, Tag> std::ops::Deref for PlaceTy<'tcx, Tag> { @@ -114,7 +114,7 @@ pub struct MPlaceTy<'tcx, Tag = ()> { pub layout: TyAndLayout<'tcx>, } -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 72); impl<'tcx, Tag> std::ops::Deref for MPlaceTy<'tcx, Tag> { diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index ed3d3927825af..ce0098fdf860b 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -96,7 +96,7 @@ crate enum StmtKind<'tcx> { } // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Expr<'_>, 168); /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 9668a24bf8ab6..a28595e6fae67 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1757,8 +1757,9 @@ impl<'a> Parser<'a> { let (pat, ty) = if is_name_required || this.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); - let pat = this.parse_fn_param_pat()?; - if let Err(mut err) = this.expect(&token::Colon) { + let (pat, colon) = this.parse_fn_param_pat_colon()?; + if !colon { + let mut err = this.unexpected::<()>().unwrap_err(); return if let Some(ident) = this.parameter_without_type(&mut err, pat, is_name_required, first_param) { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 9e2e7359ca96e..5a68afdfa59f7 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -31,6 +31,18 @@ pub enum RecoverComma { No, } +/// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid +/// emitting duplicate diagnostics. +#[derive(Debug, Clone, Copy)] +enum EatOrResult { + /// We recovered from a trailing vert. + TrailingVert, + /// We ate an `|` (or `||` and recovered). + AteOr, + /// We did not eat anything (i.e. the current token is not `|` or `||`). + None, +} + impl<'a> Parser<'a> { /// Parses a pattern. /// @@ -55,9 +67,26 @@ impl<'a> Parser<'a> { gate_or: GateOr, rc: RecoverComma, ) -> PResult<'a, P> { + self.parse_pat_allow_top_alt_inner(expected, gate_or, rc).map(|(pat, _)| pat) + } + + /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true = + /// recovered). + fn parse_pat_allow_top_alt_inner( + &mut self, + expected: Expected, + gate_or: GateOr, + rc: RecoverComma, + ) -> PResult<'a, (P, bool)> { + // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated + // suggestions (which bothers rustfix). + // // Allow a '|' before the pats (RFCs 1925, 2530, and 2535). - let leading_vert_span = - if self.eat_or_separator(None) { Some(self.prev_token.span) } else { None }; + let (leading_vert_span, mut trailing_vert) = match self.eat_or_separator(None) { + EatOrResult::AteOr => (Some(self.prev_token.span), false), + EatOrResult::TrailingVert => (None, true), + EatOrResult::None => (None, false), + }; // Parse the first pattern (`p_0`). let first_pat = self.parse_pat_no_top_alt(expected)?; @@ -77,16 +106,24 @@ impl<'a> Parser<'a> { // If there was a leading vert, treat this as an or-pattern. This improves // diagnostics. let span = leading_vert_span.to(self.prev_token.span); - return Ok(self.mk_pat(span, PatKind::Or(vec![first_pat]))); + return Ok((self.mk_pat(span, PatKind::Or(vec![first_pat])), trailing_vert)); } - return Ok(first_pat); + return Ok((first_pat, trailing_vert)); } // Parse the patterns `p_1 | ... | p_n` where `n > 0`. let lo = leading_vert_span.unwrap_or(first_pat.span); let mut pats = vec![first_pat]; - while self.eat_or_separator(Some(lo)) { + loop { + match self.eat_or_separator(Some(lo)) { + EatOrResult::AteOr => {} + EatOrResult::None => break, + EatOrResult::TrailingVert => { + trailing_vert = true; + break; + } + } let pat = self.parse_pat_no_top_alt(expected).map_err(|mut err| { err.span_label(lo, WHILE_PARSING_OR_MSG); err @@ -101,15 +138,63 @@ impl<'a> Parser<'a> { self.sess.gated_spans.gate(sym::or_patterns, or_pattern_span); } - Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats))) + Ok((self.mk_pat(or_pattern_span, PatKind::Or(pats)), trailing_vert)) } - /// Parse the pattern for a function or function pointer parameter. - pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P> { - // We actually do _not_ allow top-level or-patterns in function params, but we use - // `parse_pat_allow_top_alt` anyway so that we can detect when a user tries to use it. This - // allows us to print a better error message. - // + /// Parse a pattern and (maybe) a `Colon` in positions where a pattern may be followed by a + /// type annotation (e.g. for `let` bindings or `fn` params). + /// + /// Generally, this corresponds to `pat_no_top_alt` followed by an optional `Colon`. It will + /// eat the `Colon` token if one is present. + /// + /// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false` + /// otherwise). + pub(super) fn parse_pat_before_ty( + &mut self, + expected: Expected, + gate_or: GateOr, + rc: RecoverComma, + syntax_loc: &str, + ) -> PResult<'a, (P, bool)> { + // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level + // or-patterns so that we can detect when a user tries to use it. This allows us to print a + // better error message. + let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, gate_or, rc)?; + let colon = self.eat(&token::Colon); + + if let PatKind::Or(pats) = &pat.kind { + let msg = format!("top-level or-patterns are not allowed in {}", syntax_loc); + let (help, fix) = if pats.len() == 1 { + // If all we have is a leading vert, then print a special message. This is the case + // if `parse_pat_allow_top_alt` returns an or-pattern with one variant. + let msg = "remove the `|`"; + let fix = pprust::pat_to_string(&pat); + (msg, fix) + } else { + let msg = "wrap the pattern in parentheses"; + let fix = format!("({})", pprust::pat_to_string(&pat)); + (msg, fix) + }; + + if trailing_vert { + // We already emitted an error and suggestion to remove the trailing vert. Don't + // emit again. + self.sess.span_diagnostic.delay_span_bug(pat.span, &msg); + } else { + self.struct_span_err(pat.span, &msg) + .span_suggestion(pat.span, help, fix, Applicability::MachineApplicable) + .emit(); + } + } + + Ok((pat, colon)) + } + + /// Parse the pattern for a function or function pointer parameter, followed by a colon. + /// + /// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false` + /// otherwise). + pub(super) fn parse_fn_param_pat_colon(&mut self) -> PResult<'a, (P, bool)> { // In order to get good UX, we first recover in the case of a leading vert for an illegal // top-level or-pat. Normally, this means recovering both `|` and `||`, but in this case, // a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that @@ -128,53 +213,28 @@ impl<'a> Parser<'a> { self.bump(); } - let pat = self.parse_pat_allow_top_alt(PARAM_EXPECTED, GateOr::No, RecoverComma::No)?; - - if let PatKind::Or(..) = &pat.kind { - self.ban_illegal_fn_param_or_pat(&pat); - } - - Ok(pat) - } - - /// Ban `A | B` immediately in a parameter pattern and suggest wrapping in parens. - fn ban_illegal_fn_param_or_pat(&self, pat: &Pat) { - // If all we have a leading vert, then print a special message. This is the case if - // `parse_pat_allow_top_alt` returns an or-pattern with one variant. - let (msg, fix) = match &pat.kind { - PatKind::Or(pats) if pats.len() == 1 => { - let msg = "remove the leading `|`"; - let fix = pprust::pat_to_string(pat); - (msg, fix) - } - - _ => { - let msg = "wrap the pattern in parentheses"; - let fix = format!("({})", pprust::pat_to_string(pat)); - (msg, fix) - } - }; - - self.struct_span_err(pat.span, "an or-pattern parameter must be wrapped in parentheses") - .span_suggestion(pat.span, msg, fix, Applicability::MachineApplicable) - .emit(); + self.parse_pat_before_ty( + PARAM_EXPECTED, + GateOr::No, + RecoverComma::No, + "function parameters", + ) } /// Eat the or-pattern `|` separator. /// If instead a `||` token is encountered, recover and pretend we parsed `|`. - fn eat_or_separator(&mut self, lo: Option) -> bool { + fn eat_or_separator(&mut self, lo: Option) -> EatOrResult { if self.recover_trailing_vert(lo) { - return false; - } - - match self.token.kind { - token::OrOr => { - // Found `||`; Recover and pretend we parsed `|`. - self.ban_unexpected_or_or(lo); - self.bump(); - true - } - _ => self.eat(&token::BinOp(token::Or)), + EatOrResult::TrailingVert + } else if matches!(self.token.kind, token::OrOr) { + // Found `||`; Recover and pretend we parsed `|`. + self.ban_unexpected_or_or(lo); + self.bump(); + EatOrResult::AteOr + } else if self.eat(&token::BinOp(token::Or)) { + EatOrResult::AteOr + } else { + EatOrResult::None } } @@ -190,14 +250,14 @@ impl<'a> Parser<'a> { matches!( &token.uninterpolate().kind, token::FatArrow // e.g. `a | => 0,`. - | token::Ident(kw::If, false) // e.g. `a | if expr`. - | token::Eq // e.g. `let a | = 0`. - | token::Semi // e.g. `let a |;`. - | token::Colon // e.g. `let a | :`. - | token::Comma // e.g. `let (a |,)`. - | token::CloseDelim(token::Bracket) // e.g. `let [a | ]`. - | token::CloseDelim(token::Paren) // e.g. `let (a | )`. - | token::CloseDelim(token::Brace) // e.g. `let A { f: a | }`. + | token::Ident(kw::If, false) // e.g. `a | if expr`. + | token::Eq // e.g. `let a | = 0`. + | token::Semi // e.g. `let a |;`. + | token::Colon // e.g. `let a | :`. + | token::Comma // e.g. `let (a |,)`. + | token::CloseDelim(token::Bracket) // e.g. `let [a | ]`. + | token::CloseDelim(token::Paren) // e.g. `let (a | )`. + | token::CloseDelim(token::Brace) // e.g. `let A { f: a | }`. ) }); match (is_end_ahead, &self.token.kind) { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index a0f9616f72ae1..f6599927c6e6d 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -13,7 +13,8 @@ use rustc_ast::token::{self, TokenKind}; use rustc_ast::util::classify; use rustc_ast::AstLike; use rustc_ast::{AttrStyle, AttrVec, Attribute, MacCall, MacCallStmt, MacStmtStyle}; -use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID}; +use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt}; +use rustc_ast::{StmtKind, DUMMY_NODE_ID}; use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::{BytePos, Span}; use rustc_span::symbol::{kw, sym}; @@ -220,9 +221,10 @@ impl<'a> Parser<'a> { /// Parses a local variable declaration. fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; - let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?; + let (pat, colon) = + self.parse_pat_before_ty(None, GateOr::Yes, RecoverComma::Yes, "`let` bindings")?; - let (err, ty) = if self.eat(&token::Colon) { + let (err, ty) = if colon { // Save the state of the parser before parsing type normally, in case there is a `:` // instead of an `=` typo. let parser_snapshot_before_type = self.clone(); diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index e1f8d59991f21..aea3d8eef65d0 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -23,7 +23,7 @@ #[macro_use] extern crate rustc_macros; -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[macro_use] extern crate rustc_data_structures; #[macro_use] diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 3c447a7d1f9bb..7d451fc234106 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -87,7 +87,7 @@ pub struct PendingPredicateObligation<'tcx> { } // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(PendingPredicateObligation<'_>, 56); impl<'a, 'tcx> FulfillmentContext<'tcx> { diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 4377780e15f45..b5e66d37ab494 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -566,7 +566,7 @@ impl BinaryHeap { let mut child = 2 * hole.pos() + 1; // Loop invariant: child == 2 * hole.pos() + 1. - while child < end - 1 { + while child <= end.saturating_sub(2) { // compare with the greater of the two children // SAFETY: child < end - 1 < self.len() and // child + 1 < end <= self.len(), so they're valid indexes. @@ -625,7 +625,7 @@ impl BinaryHeap { let mut child = 2 * hole.pos() + 1; // Loop invariant: child == 2 * hole.pos() + 1. - while child < end - 1 { + while child <= end.saturating_sub(2) { // SAFETY: child < end - 1 < self.len() and // child + 1 < end <= self.len(), so they're valid indexes. // child == 2 * hole.pos() + 1 != hole.pos() and diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 4a15b185a83e7..5bab1fb93dbb5 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -579,6 +579,7 @@ impl Ordering { /// ``` #[derive(PartialEq, Eq, Debug, Copy, Clone, Default, Hash)] #[stable(feature = "reverse_cmp_key", since = "1.19.0")] +#[repr(transparent)] pub struct Reverse(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T); #[stable(feature = "reverse_cmp_key", since = "1.19.0")] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 275fcc4c29299..f0f5558fd1608 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -16,7 +16,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.85", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.88", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.39" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a94ee918c2467..2636467196a33 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -93,7 +93,7 @@ crate struct Item { } // `Item` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Item, 48); impl fmt::Debug for Item { diff --git a/src/test/codegen/issue-75525-bounds-checks.rs b/src/test/codegen/issue-75525-bounds-checks.rs new file mode 100644 index 0000000000000..a03c63c1d0948 --- /dev/null +++ b/src/test/codegen/issue-75525-bounds-checks.rs @@ -0,0 +1,27 @@ +// Regression test for #75525, verifies that no bounds checks are generated. + +// min-llvm-version: 12.0.0 +// compile-flags: -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @f0 +// CHECK-NOT: panic +#[no_mangle] +pub fn f0(idx: usize, buf: &[u8; 10]) -> u8 { + if idx < 8 { buf[idx + 1] } else { 0 } +} + +// CHECK-LABEL: @f1 +// CHECK-NOT: panic +#[no_mangle] +pub fn f1(idx: usize, buf: &[u8; 10]) -> u8 { + if idx > 5 && idx < 8 { buf[idx - 1] } else { 0 } +} + +// CHECK-LABEL: @f2 +// CHECK-NOT: panic +#[no_mangle] +pub fn f2(idx: usize, buf: &[u8; 10]) -> u8 { + if idx > 5 && idx < 8 { buf[idx] } else { 0 } +} diff --git a/src/test/ui/or-patterns/already-bound-name.rs b/src/test/ui/or-patterns/already-bound-name.rs index 726e17b7ec226..543d7c21c8317 100644 --- a/src/test/ui/or-patterns/already-bound-name.rs +++ b/src/test/ui/or-patterns/already-bound-name.rs @@ -18,10 +18,10 @@ fn main() { let (A(a, _) | B(a), a) = (A(0, 1), 2); //~^ ERROR identifier `a` is bound more than once in the same pattern - let A(a, a) | B(a) = A(0, 1); + let (A(a, a) | B(a)) = A(0, 1); //~^ ERROR identifier `a` is bound more than once in the same pattern - let B(a) | A(a, a) = A(0, 1); + let (B(a) | A(a, a)) = A(0, 1); //~^ ERROR identifier `a` is bound more than once in the same pattern match A(0, 1) { @@ -29,17 +29,17 @@ fn main() { //~^ ERROR identifier `a` is bound more than once in the same pattern } - let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); + let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); //~^ ERROR identifier `a` is bound more than once in the same pattern //~| ERROR identifier `a` is bound more than once in the same pattern //~| ERROR mismatched types - let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); //~^ ERROR identifier `a` is bound more than once in the same pattern //~| ERROR identifier `a` is bound more than once in the same pattern //~| ERROR variable `a` is not bound in all patterns - let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); //~^ ERROR identifier `a` is bound more than once in the same pattern //~| ERROR identifier `a` is bound more than once in the same pattern } diff --git a/src/test/ui/or-patterns/already-bound-name.stderr b/src/test/ui/or-patterns/already-bound-name.stderr index 97933ca122944..483154a5e3274 100644 --- a/src/test/ui/or-patterns/already-bound-name.stderr +++ b/src/test/ui/or-patterns/already-bound-name.stderr @@ -23,16 +23,16 @@ LL | let (A(a, _) | B(a), a) = (A(0, 1), 2); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:21:14 + --> $DIR/already-bound-name.rs:21:15 | -LL | let A(a, a) | B(a) = A(0, 1); - | ^ used in a pattern more than once +LL | let (A(a, a) | B(a)) = A(0, 1); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:24:21 + --> $DIR/already-bound-name.rs:24:22 | -LL | let B(a) | A(a, a) = A(0, 1); - | ^ used in a pattern more than once +LL | let (B(a) | A(a, a)) = A(0, 1); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern --> $DIR/already-bound-name.rs:28:21 @@ -41,55 +41,55 @@ LL | B(a) | A(a, a) => {} // Let's ensure `match` has no funny business. | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:32:36 + --> $DIR/already-bound-name.rs:32:37 | -LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:32:46 + --> $DIR/already-bound-name.rs:32:47 | -LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:37:36 + --> $DIR/already-bound-name.rs:37:37 | -LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:37:46 + --> $DIR/already-bound-name.rs:37:47 | -LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0408]: variable `a` is not bound in all patterns - --> $DIR/already-bound-name.rs:37:9 + --> $DIR/already-bound-name.rs:37:10 | -LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^^^^ pattern doesn't bind `a` - variable not in all patterns +LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^^^^ pattern doesn't bind `a` - variable not in all patterns error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:42:49 + --> $DIR/already-bound-name.rs:42:50 | -LL | let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:42:59 + --> $DIR/already-bound-name.rs:42:60 | -LL | let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0308]: mismatched types - --> $DIR/already-bound-name.rs:32:31 + --> $DIR/already-bound-name.rs:32:32 | -LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); - | - ^ ------- this expression has type `E>` - | | | - | | expected integer, found enum `E` - | first introduced with type `{integer}` here +LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + | - ^ ------- this expression has type `E>` + | | | + | | expected integer, found enum `E` + | first introduced with type `{integer}` here | = note: expected type `{integer}` found type `E<{integer}>` diff --git a/src/test/ui/or-patterns/consistent-bindings.rs b/src/test/ui/or-patterns/consistent-bindings.rs index 3ee57978bb009..853ddcf241232 100644 --- a/src/test/ui/or-patterns/consistent-bindings.rs +++ b/src/test/ui/or-patterns/consistent-bindings.rs @@ -8,9 +8,9 @@ fn main() { // One level: - let Ok(a) | Err(a) = Ok(0); - let Ok(ref a) | Err(ref a) = Ok(0); - let Ok(ref mut a) | Err(ref mut a) = Ok(0); + let (Ok(a) | Err(a)) = Ok(0); + let (Ok(ref a) | Err(ref a)) = Ok(0); + let (Ok(ref mut a) | Err(ref mut a)) = Ok(0); // Two levels: enum Tri { @@ -20,10 +20,10 @@ fn main() { } use Tri::*; - let Ok((V1(a) | V2(a) | V3(a), b)) | Err(Ok((a, b)) | Err((a, b))): Result<_, Result<_, _>> = + let (Ok((V1(a) | V2(a) | V3(a), b)) | Err(Ok((a, b)) | Err((a, b)))): Result<_, Result<_, _>> = Ok((V1(1), 1)); - let Ok((V1(a) | V2(a) | V3(a), ref b)) | Err(Ok((a, ref b)) | Err((a, ref b))): Result< + let (Ok((V1(a) | V2(a) | V3(a), ref b)) | Err(Ok((a, ref b)) | Err((a, ref b)))): Result< _, Result<_, _>, > = Ok((V1(1), 1)); diff --git a/src/test/ui/or-patterns/const-fn.rs b/src/test/ui/or-patterns/const-fn.rs index f4af2f0d2dd40..55c6f60915fa8 100644 --- a/src/test/ui/or-patterns/const-fn.rs +++ b/src/test/ui/or-patterns/const-fn.rs @@ -3,28 +3,28 @@ const fn foo((Ok(a) | Err(a)): Result) { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; } const X: () = { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; }; static Y: () = { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; }; static mut Z: () = { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; }; fn main() { let _: [(); { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; 2 }]; } diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs index a4ea4e25d861e..6c592550ec257 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs @@ -5,4 +5,5 @@ fn main() {} #[cfg(FALSE)] fn gated_leading_vert_in_let() { let | A; //~ ERROR or-patterns syntax is experimental + //~^ ERROR top-level or-patterns are not allowed } diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr index 499f60dd545ff..d556532cd6ad8 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr @@ -1,3 +1,9 @@ +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/feature-gate-or_patterns-leading-let.rs:7:9 + | +LL | let | A; + | ^^^ help: remove the `|`: `A` + error[E0658]: or-patterns syntax is experimental --> $DIR/feature-gate-or_patterns-leading-let.rs:7:9 | @@ -7,6 +13,6 @@ LL | let | A; = note: see issue #54883 for more information = help: add `#![feature(or_patterns)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.rs b/src/test/ui/or-patterns/feature-gate-or_patterns.rs index e638838147a4d..8bb45e606be96 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.rs +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.rs @@ -26,7 +26,9 @@ fn or_patterns() { // Gated: let | A | B; //~ ERROR or-patterns syntax is experimental + //~^ ERROR top-level or-patterns are not allowed let A | B; //~ ERROR or-patterns syntax is experimental + //~^ ERROR top-level or-patterns are not allowed for | A | B in 0 {} //~ ERROR or-patterns syntax is experimental for A | B in 0 {} //~ ERROR or-patterns syntax is experimental fn fun((A | B): _) {} //~ ERROR or-patterns syntax is experimental diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr index c01d17c0b3d7e..7988af5b94213 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr @@ -1,3 +1,15 @@ +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/feature-gate-or_patterns.rs:28:9 + | +LL | let | A | B; + | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/feature-gate-or_patterns.rs:30:9 + | +LL | let A | B; + | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` + error[E0658]: or-patterns syntax is experimental --> $DIR/feature-gate-or_patterns.rs:5:14 | @@ -17,7 +29,7 @@ LL | let | A | B; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:29:9 + --> $DIR/feature-gate-or_patterns.rs:30:9 | LL | let A | B; | ^^^^^ @@ -26,7 +38,7 @@ LL | let A | B; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:30:9 + --> $DIR/feature-gate-or_patterns.rs:32:9 | LL | for | A | B in 0 {} | ^^^^^^^ @@ -35,7 +47,7 @@ LL | for | A | B in 0 {} = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:31:9 + --> $DIR/feature-gate-or_patterns.rs:33:9 | LL | for A | B in 0 {} | ^^^^^ @@ -44,7 +56,7 @@ LL | for A | B in 0 {} = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:32:13 + --> $DIR/feature-gate-or_patterns.rs:34:13 | LL | fn fun((A | B): _) {} | ^^^^^ @@ -53,7 +65,7 @@ LL | fn fun((A | B): _) {} = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:33:15 + --> $DIR/feature-gate-or_patterns.rs:35:15 | LL | let _ = |(A | B): u8| (); | ^^^^^ @@ -62,7 +74,7 @@ LL | let _ = |(A | B): u8| (); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:34:10 + --> $DIR/feature-gate-or_patterns.rs:36:10 | LL | let (A | B); | ^^^^^ @@ -71,7 +83,7 @@ LL | let (A | B); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:35:10 + --> $DIR/feature-gate-or_patterns.rs:37:10 | LL | let (A | B,); | ^^^^^ @@ -80,7 +92,7 @@ LL | let (A | B,); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:36:11 + --> $DIR/feature-gate-or_patterns.rs:38:11 | LL | let A(B | C); | ^^^^^ @@ -89,7 +101,7 @@ LL | let A(B | C); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:37:14 + --> $DIR/feature-gate-or_patterns.rs:39:14 | LL | let E::V(B | C); | ^^^^^ @@ -98,7 +110,7 @@ LL | let E::V(B | C); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:38:17 + --> $DIR/feature-gate-or_patterns.rs:40:17 | LL | let S { f1: B | C, f2 }; | ^^^^^ @@ -107,7 +119,7 @@ LL | let S { f1: B | C, f2 }; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:39:20 + --> $DIR/feature-gate-or_patterns.rs:41:20 | LL | let E::V { f1: B | C, f2 }; | ^^^^^ @@ -116,7 +128,7 @@ LL | let E::V { f1: B | C, f2 }; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:40:10 + --> $DIR/feature-gate-or_patterns.rs:42:10 | LL | let [A | B]; | ^^^^^ @@ -169,6 +181,6 @@ LL | accept_pat!([p | q]); = note: see issue #54883 for more information = help: add `#![feature(or_patterns)]` to the crate attributes to enable -error: aborting due to 19 previous errors +error: aborting due to 21 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.fixed b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed index bbc75d2b411eb..65e04325e16bd 100644 --- a/src/test/ui/or-patterns/fn-param-wrap-parens.fixed +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed @@ -11,4 +11,4 @@ enum E { A, B } use E::*; #[cfg(FALSE)] -fn fun1((A | B): E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses +fn fun1((A | B): E) {} //~ ERROR top-level or-patterns are not allowed diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.rs b/src/test/ui/or-patterns/fn-param-wrap-parens.rs index 65b93dcbf7467..aeb4a05ea808e 100644 --- a/src/test/ui/or-patterns/fn-param-wrap-parens.rs +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.rs @@ -11,4 +11,4 @@ enum E { A, B } use E::*; #[cfg(FALSE)] -fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses +fn fun1(A | B: E) {} //~ ERROR top-level or-patterns are not allowed diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.stderr b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr index 0e6424a430043..96193c17ae23f 100644 --- a/src/test/ui/or-patterns/fn-param-wrap-parens.stderr +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr @@ -1,4 +1,4 @@ -error: an or-pattern parameter must be wrapped in parentheses +error: top-level or-patterns are not allowed in function parameters --> $DIR/fn-param-wrap-parens.rs:14:9 | LL | fn fun1(A | B: E) {} diff --git a/src/test/ui/or-patterns/inconsistent-modes.rs b/src/test/ui/or-patterns/inconsistent-modes.rs index fd5cb01ab42c5..2300e9f9f3b7b 100644 --- a/src/test/ui/or-patterns/inconsistent-modes.rs +++ b/src/test/ui/or-patterns/inconsistent-modes.rs @@ -4,23 +4,23 @@ #![allow(non_camel_case_types)] fn main() { // One level: - let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0); + let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0); //~^ ERROR variable `a` is bound inconsistently - let Ok(ref mut a) | Err(a): Result = Ok(0); + let (Ok(ref mut a) | Err(a)): Result = Ok(0); //~^ ERROR variable `a` is bound inconsistently - let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); + let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); //~^ ERROR variable `a` is bound inconsistently //~| ERROR mismatched types - let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); + let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); //~^ ERROR variable `a` is bound inconsistently //~| ERROR variable `b` is bound inconsistently //~| ERROR mismatched types // Two levels: - let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0); + let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0); //~^ ERROR variable `a` is bound inconsistently // Three levels: - let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1); + let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1); //~^ ERROR variable `a` is bound inconsistently } diff --git a/src/test/ui/or-patterns/inconsistent-modes.stderr b/src/test/ui/or-patterns/inconsistent-modes.stderr index 15790771043df..99791431eaf25 100644 --- a/src/test/ui/or-patterns/inconsistent-modes.stderr +++ b/src/test/ui/or-patterns/inconsistent-modes.stderr @@ -1,74 +1,74 @@ error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:7:25 + --> $DIR/inconsistent-modes.rs:7:26 | -LL | let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0); - | - ^ bound in different ways - | | - | first binding +LL | let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0); + | - ^ bound in different ways + | | + | first binding error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:9:29 + --> $DIR/inconsistent-modes.rs:9:30 | -LL | let Ok(ref mut a) | Err(a): Result = Ok(0); - | - ^ bound in different ways - | | - | first binding +LL | let (Ok(ref mut a) | Err(a)): Result = Ok(0); + | - ^ bound in different ways + | | + | first binding error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:11:33 + --> $DIR/inconsistent-modes.rs:11:34 | -LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); - | - first binding ^ bound in different ways +LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); + | - first binding ^ bound in different ways error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:14:39 + --> $DIR/inconsistent-modes.rs:14:40 | -LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); - | - first binding ^ bound in different ways +LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + | - first binding ^ bound in different ways error[E0409]: variable `b` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:14:46 + --> $DIR/inconsistent-modes.rs:14:47 | -LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); - | - first binding ^ bound in different ways +LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + | - first binding ^ bound in different ways error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:20:38 + --> $DIR/inconsistent-modes.rs:20:39 | -LL | let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0); - | - ^ bound in different ways - | | - | first binding +LL | let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0); + | - ^ bound in different ways + | | + | first binding error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:24:33 + --> $DIR/inconsistent-modes.rs:24:34 | -LL | let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1); - | - ^ bound in different ways - | | - | first binding +LL | let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1); + | - ^ bound in different ways + | | + | first binding error[E0308]: mismatched types - --> $DIR/inconsistent-modes.rs:11:25 + --> $DIR/inconsistent-modes.rs:11:26 | -LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); - | ----- ^^^^^^^^^ -------------------- expected due to this - | | | - | | types differ in mutability - | first introduced with type `&&u8` here +LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); + | ----- ^^^^^^^^^ -------------------- expected due to this + | | | + | | types differ in mutability + | first introduced with type `&&u8` here | = note: expected type `&&u8` found type `&mut &mut u8` = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/inconsistent-modes.rs:14:31 + --> $DIR/inconsistent-modes.rs:14:32 | -LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); - | ----- ^^^^^^^^^ ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>` - | | | - | | types differ in mutability - | first introduced with type `&{integer}` here +LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + | ----- ^^^^^^^^^ ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>` + | | | + | | types differ in mutability + | first introduced with type `&{integer}` here | = note: expected type `&{integer}` found type `&mut _` diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs index 59533cefea64c..8e83acc6dcbc0 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs @@ -1,7 +1,7 @@ #![feature(or_patterns)] fn main() { - let 0 | (1 | 2) = 0; //~ ERROR refutable pattern in local binding + let (0 | (1 | 2)) = 0; //~ ERROR refutable pattern in local binding match 0 { //~^ ERROR non-exhaustive patterns 0 | (1 | 2) => {} diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr index 2acf1f41c6fa6..9ed942d9e0fd5 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -1,16 +1,16 @@ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered - --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:9 + --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:10 | -LL | let 0 | (1 | 2) = 0; - | ^^^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered +LL | let (0 | (1 | 2)) = 0; + | ^^^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let 0 | (1 | 2) = 0 { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let (0 | (1 | 2)) = 0 { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:5:11 diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs index 1de563dedbf18..2f080ebf7830b 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs @@ -3,7 +3,7 @@ #![feature(or_patterns)] fn main() { - let 0 | (1 | _) = 0; + let (0 | (1 | _)) = 0; if let 0 | (1 | 2) = 0 {} if let x @ 0 | x @ (1 | 2) = 0 {} } diff --git a/src/test/ui/or-patterns/let-pattern.rs b/src/test/ui/or-patterns/let-pattern.rs index 07e37412ce842..7f22aa9d9f980 100644 --- a/src/test/ui/or-patterns/let-pattern.rs +++ b/src/test/ui/or-patterns/let-pattern.rs @@ -3,7 +3,7 @@ // run-pass fn or_pat_let(x: Result) -> u32 { - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; y } diff --git a/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs b/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs index 5c5c68f81d1f2..cf98a472106e8 100644 --- a/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs +++ b/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs @@ -8,7 +8,7 @@ async fn a((x | s): String) {} //~| ERROR variable `s` is not bound in all patterns async fn b() { - let x | s = String::new(); + let (x | s) = String::new(); //~^ ERROR variable `x` is not bound in all patterns //~| ERROR variable `s` is not bound in all patterns } diff --git a/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr b/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr index 998577cf4b5e0..d5c77ee39c99c 100644 --- a/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr +++ b/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr @@ -15,20 +15,20 @@ LL | async fn a((x | s): String) {} | variable not in all patterns error[E0408]: variable `s` is not bound in all patterns - --> $DIR/mismatched-bindings-async-fn.rs:11:9 + --> $DIR/mismatched-bindings-async-fn.rs:11:10 | -LL | let x | s = String::new(); - | ^ - variable not in all patterns - | | - | pattern doesn't bind `s` +LL | let (x | s) = String::new(); + | ^ - variable not in all patterns + | | + | pattern doesn't bind `s` error[E0408]: variable `x` is not bound in all patterns - --> $DIR/mismatched-bindings-async-fn.rs:11:13 + --> $DIR/mismatched-bindings-async-fn.rs:11:14 | -LL | let x | s = String::new(); - | - ^ pattern doesn't bind `x` - | | - | variable not in all patterns +LL | let (x | s) = String::new(); + | - ^ pattern doesn't bind `x` + | | + | variable not in all patterns error: aborting due to 4 previous errors diff --git a/src/test/ui/or-patterns/missing-bindings.rs b/src/test/ui/or-patterns/missing-bindings.rs index 67cf52fa8c418..5dd1f16b65580 100644 --- a/src/test/ui/or-patterns/missing-bindings.rs +++ b/src/test/ui/or-patterns/missing-bindings.rs @@ -17,7 +17,7 @@ fn check_handling_of_paths() { } use bar::foo::{alpha, charlie}; - let alpha | beta | charlie = alpha; //~ ERROR variable `beta` is not bound in all patterns + let (alpha | beta | charlie) = alpha; //~ ERROR variable `beta` is not bound in all patterns match Some(alpha) { Some(alpha | beta) => {} //~ ERROR variable `beta` is not bound in all patterns } @@ -31,19 +31,19 @@ fn check_misc_nesting() { // One level: const X: E = B(0); - let A(a, _) | _ = X; //~ ERROR variable `a` is not bound in all patterns - let _ | B(a) = X; //~ ERROR variable `a` is not bound in all patterns - let A(..) | B(a) = X; //~ ERROR variable `a` is not bound in all patterns - let A(a, _) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns - let A(_, a) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns - let A(a, b) | B(a) = X; //~ ERROR variable `b` is not bound in all patterns + let (A(a, _) | _) = X; //~ ERROR variable `a` is not bound in all patterns + let (_ | B(a)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(..) | B(a)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(a, _) | B(_)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(_, a) | B(_)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(a, b) | B(a)) = X; //~ ERROR variable `b` is not bound in all patterns // Two levels: const Y: E> = B(B(0)); - let A(A(..) | B(_), _) | B(a) = Y; //~ ERROR variable `a` is not bound in all patterns - let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y; + let (A(A(..) | B(_), _) | B(a)) = Y; //~ ERROR variable `a` is not bound in all patterns + let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; //~^ ERROR variable `a` is not bound in all patterns - let A(A(a, b) | B(c), d) | B(e) = Y; + let (A(A(a, b) | B(c), d) | B(e)) = Y; //~^ ERROR variable `a` is not bound in all patterns //~| ERROR variable `a` is not bound in all patterns //~| ERROR variable `b` is not bound in all patterns diff --git a/src/test/ui/or-patterns/missing-bindings.stderr b/src/test/ui/or-patterns/missing-bindings.stderr index 57270e4412351..4702bc6bbf322 100644 --- a/src/test/ui/or-patterns/missing-bindings.stderr +++ b/src/test/ui/or-patterns/missing-bindings.stderr @@ -1,11 +1,11 @@ error[E0408]: variable `beta` is not bound in all patterns - --> $DIR/missing-bindings.rs:20:9 + --> $DIR/missing-bindings.rs:20:10 | -LL | let alpha | beta | charlie = alpha; - | ^^^^^ ---- ^^^^^^^ pattern doesn't bind `beta` - | | | - | | variable not in all patterns - | pattern doesn't bind `beta` +LL | let (alpha | beta | charlie) = alpha; + | ^^^^^ ---- ^^^^^^^ pattern doesn't bind `beta` + | | | + | | variable not in all patterns + | pattern doesn't bind `beta` error[E0408]: variable `beta` is not bound in all patterns --> $DIR/missing-bindings.rs:22:14 @@ -16,132 +16,132 @@ LL | Some(alpha | beta) => {} | pattern doesn't bind `beta` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:34:19 + --> $DIR/missing-bindings.rs:34:20 | -LL | let A(a, _) | _ = X; - | - ^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(a, _) | _) = X; + | - ^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:35:9 + --> $DIR/missing-bindings.rs:35:10 | -LL | let _ | B(a) = X; - | ^ - variable not in all patterns - | | - | pattern doesn't bind `a` +LL | let (_ | B(a)) = X; + | ^ - variable not in all patterns + | | + | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:36:9 + --> $DIR/missing-bindings.rs:36:10 | -LL | let A(..) | B(a) = X; - | ^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `a` +LL | let (A(..) | B(a)) = X; + | ^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:37:19 + --> $DIR/missing-bindings.rs:37:20 | -LL | let A(a, _) | B(_) = X; - | - ^^^^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(a, _) | B(_)) = X; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:38:19 + --> $DIR/missing-bindings.rs:38:20 | -LL | let A(_, a) | B(_) = X; - | - ^^^^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(_, a) | B(_)) = X; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:39:19 + --> $DIR/missing-bindings.rs:39:20 | -LL | let A(a, b) | B(a) = X; - | - ^^^^ pattern doesn't bind `b` - | | - | variable not in all patterns +LL | let (A(a, b) | B(a)) = X; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:43:9 + --> $DIR/missing-bindings.rs:43:10 | -LL | let A(A(..) | B(_), _) | B(a) = Y; - | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `a` +LL | let (A(A(..) | B(_), _) | B(a)) = Y; + | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:44:11 + --> $DIR/missing-bindings.rs:44:12 | -LL | let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y; - | ^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `a` +LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; + | ^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:21 + --> $DIR/missing-bindings.rs:46:22 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:21 + --> $DIR/missing-bindings.rs:46:22 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `b` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:11 + --> $DIR/missing-bindings.rs:46:12 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | ^^^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `c` +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | ^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `c` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:32 + --> $DIR/missing-bindings.rs:46:33 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:32 + --> $DIR/missing-bindings.rs:46:33 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `b` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:32 + --> $DIR/missing-bindings.rs:46:33 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `c` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `c` + | | + | variable not in all patterns error[E0408]: variable `d` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:32 + --> $DIR/missing-bindings.rs:46:33 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `d` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `d` + | | + | variable not in all patterns error[E0408]: variable `e` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:9 + --> $DIR/missing-bindings.rs:46:10 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `e` +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `e` error[E0408]: variable `a` is not bound in all patterns --> $DIR/missing-bindings.rs:62:29 diff --git a/src/test/ui/or-patterns/nested-undelimited-precedence.rs b/src/test/ui/or-patterns/nested-undelimited-precedence.rs new file mode 100644 index 0000000000000..208662b1c425d --- /dev/null +++ b/src/test/ui/or-patterns/nested-undelimited-precedence.rs @@ -0,0 +1,46 @@ +// This test tests the precedence of `|` (or-patterns) undelimited nested patterns. In particular, +// we want to reserve the syntactic space of a pattern followed by a type annotation for possible +// future type ascription, so we need to make sure that any time a pattern is followed by type +// annotation (for now), the pattern is not a top-level or-pattern. However, there are also a few +// types of patterns that allow undelimited subpatterns that could cause the same ambiguity. +// Currently, those should be impossible due to precedence rule. This test enforces that. + +#![feature(or_patterns)] + +enum E { + A, + B, +} + +fn foo() { + use E::*; + + // ok + let b @ (A | B): E = A; + + let b @ A | B: E = A; //~ERROR `b` is not bound in all patterns + //~^ ERROR top-level or-patterns are not allowed +} + +enum F { + A(usize), + B(usize), +} + +fn bar() { + use F::*; + + // ok + let (A(x) | B(x)): F = A(3); + + let &A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed + let &&A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed + let &mut A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed + let &&mut A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed +} + +fn main() {} diff --git a/src/test/ui/or-patterns/nested-undelimited-precedence.stderr b/src/test/ui/or-patterns/nested-undelimited-precedence.stderr new file mode 100644 index 0000000000000..1d78d5193cb88 --- /dev/null +++ b/src/test/ui/or-patterns/nested-undelimited-precedence.stderr @@ -0,0 +1,86 @@ +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:21:9 + | +LL | let b @ A | B: E = A; + | ^^^^^^^^^ help: wrap the pattern in parentheses: `(b @ A | B)` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:36:9 + | +LL | let &A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&A(_) | B(_))` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:38:9 + | +LL | let &&A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&A(_) | B(_))` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:40:9 + | +LL | let &mut A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&mut A(_) | B(_))` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:42:9 + | +LL | let &&mut A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&mut A(_) | B(_))` + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/nested-undelimited-precedence.rs:21:17 + | +LL | let b @ A | B: E = A; + | - ^ pattern doesn't bind `b` + | | + | variable not in all patterns + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:36:9 + | +LL | let &A(_) | B(_): F = A(3); + | ^^^^^ - expected due to this + | | + | expected enum `F`, found reference + | + = note: expected enum `F` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:38:9 + | +LL | let &&A(_) | B(_): F = A(3); + | ^^^^^^ - expected due to this + | | + | expected enum `F`, found reference + | + = note: expected enum `F` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:40:9 + | +LL | let &mut A(_) | B(_): F = A(3); + | ^^^^^^^^^ - expected due to this + | | + | expected enum `F`, found `&mut _` + | + = note: expected enum `F` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:42:9 + | +LL | let &&mut A(_) | B(_): F = A(3); + | ^^^^^^^^^^ - expected due to this + | | + | expected enum `F`, found reference + | + = note: expected enum `F` + found reference `&_` + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0308, E0408. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs index 5ec7dc6962c18..11c8a7b69f948 100644 --- a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs +++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs @@ -52,10 +52,10 @@ fn main() { = Some((0u8, Some((1u16, 2u32)))) {} - let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2); + let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2); //~^ ERROR mismatched types - let (x, y) | (y, x) = (0u8, 1u16); + let ((x, y) | (y, x)) = (0u8, 1u16); //~^ ERROR mismatched types //~| ERROR mismatched types diff --git a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr index 00dba053a59d3..26e14b539dbf2 100644 --- a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr +++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr @@ -187,35 +187,35 @@ LL | = Some((0u8, Some((1u16, 2u32)))) = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:55:39 + --> $DIR/or-patterns-binding-type-mismatch.rs:55:40 | -LL | let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2); - | - ^ ---------------- this expression has type `Blah` - | | | - | | expected `usize`, found `isize` - | first introduced with type `usize` here +LL | let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2); + | - ^ ---------------- this expression has type `Blah` + | | | + | | expected `usize`, found `isize` + | first introduced with type `usize` here | = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:58:19 + --> $DIR/or-patterns-binding-type-mismatch.rs:58:20 | -LL | let (x, y) | (y, x) = (0u8, 1u16); - | - ^ ----------- this expression has type `(u8, u16)` - | | | - | | expected `u16`, found `u8` - | first introduced with type `u16` here +LL | let ((x, y) | (y, x)) = (0u8, 1u16); + | - ^ ----------- this expression has type `(u8, u16)` + | | | + | | expected `u16`, found `u8` + | first introduced with type `u16` here | = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:58:22 + --> $DIR/or-patterns-binding-type-mismatch.rs:58:23 | -LL | let (x, y) | (y, x) = (0u8, 1u16); - | - ^ ----------- this expression has type `(u8, u16)` - | | | - | | expected `u8`, found `u16` - | first introduced with type `u8` here +LL | let ((x, y) | (y, x)) = (0u8, 1u16); + | - ^ ----------- this expression has type `(u8, u16)` + | | | + | | expected `u8`, found `u16` + | first introduced with type `u8` here | = note: a binding must have the same type in all alternatives diff --git a/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs b/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs index 3b6047c7be47d..f98b038ae81af 100644 --- a/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs +++ b/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs @@ -37,11 +37,11 @@ fn main() { if let &(Ok(x) | Err(x)) = res { drop::(x); } - let Ok(mut x) | &Err(mut x) = res; + let (Ok(mut x) | &Err(mut x)) = res; drop::(x); let &(Ok(x) | Err(x)) = res; drop::(x); - let Ok(x) | Err(x) = res; + let (Ok(x) | Err(x)) = res; drop::<&u8>(x); for Ok(mut x) | &Err(mut x) in std::iter::once(res) { drop::(x); @@ -119,9 +119,9 @@ fn main() { } let tri = &Tri::A(&Ok(0)); - let Tri::A(Ok(mut x) | Err(mut x)) + let (Tri::A(Ok(mut x) | Err(mut x)) | Tri::B(&Ok(mut x) | Err(mut x)) - | &Tri::C(Ok(mut x) | Err(mut x)) = tri; + | &Tri::C(Ok(mut x) | Err(mut x))) = tri; drop::(x); match tri { diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs index cbc24eb26fa47..27a5374ff1848 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs @@ -14,8 +14,19 @@ fn no_top_level_or_patterns() { // -------- This looks like an or-pattern but is in fact `|A| (B: E | ())`. // ...and for now neither do we allow or-patterns at the top level of functions. - fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses + fn fun1(A | B: E) {} + //~^ ERROR top-level or-patterns are not allowed fn fun2(| A | B: E) {} - //~^ ERROR an or-pattern parameter must be wrapped in parentheses + //~^ ERROR top-level or-patterns are not allowed + + // We don't allow top-level or-patterns before type annotation in let-statements because we + // want to reserve this syntactic space for possible future type ascription. + let A | B: E = A; + //~^ ERROR top-level or-patterns are not allowed + + let | A | B: E = A; + //~^ ERROR top-level or-patterns are not allowed + + let (A | B): E = A; // ok -- wrapped in parens } diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index db4d827757b03..929b2088f76ce 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -1,15 +1,27 @@ -error: an or-pattern parameter must be wrapped in parentheses +error: top-level or-patterns are not allowed in function parameters --> $DIR/or-patterns-syntactic-fail.rs:17:13 | LL | fn fun1(A | B: E) {} | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` -error: an or-pattern parameter must be wrapped in parentheses - --> $DIR/or-patterns-syntactic-fail.rs:19:13 +error: top-level or-patterns are not allowed in function parameters + --> $DIR/or-patterns-syntactic-fail.rs:20:13 | LL | fn fun2(| A | B: E) {} | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/or-patterns-syntactic-fail.rs:25:9 + | +LL | let A | B: E = A; + | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/or-patterns-syntactic-fail.rs:28:9 + | +LL | let | A | B: E = A; + | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` + error[E0369]: no implementation for `E | ()` --> $DIR/or-patterns-syntactic-fail.rs:13:22 | @@ -20,6 +32,6 @@ LL | let _ = |A | B: E| (); | = note: an implementation of `std::ops::BitOr` might be missing for `E` -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs index 5fe72caf9c1ff..3da238f7b9a45 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs @@ -23,11 +23,11 @@ accept_pat!([p | q]); #[cfg(FALSE)] fn or_patterns() { // Top level of `let`: - let | A | B; - let A | B; - let A | B: u8; - let A | B = 0; - let A | B: u8 = 0; + let (| A | B); + let (A | B); + let (A | B): u8; + let (A | B) = 0; + let (A | B): u8 = 0; // Top level of `for`: for | A | B in 0 {} @@ -69,10 +69,10 @@ fn or_patterns() { let [A | B, .. | ..]; // These bind as `(prefix p) | q` as opposed to `prefix (p | q)`: - let box 0 | 1; // Unstable; we *can* the precedence if we want. - let &0 | 1; - let &mut 0 | 1; - let x @ 0 | 1; - let ref x @ 0 | 1; - let ref mut x @ 0 | 1; + let (box 0 | 1); // Unstable; we *can* change the precedence if we want. + let (&0 | 1); + let (&mut 0 | 1); + let (x @ 0 | 1); + let (ref x @ 0 | 1); + let (ref mut x @ 0 | 1); } diff --git a/src/test/ui/or-patterns/remove-leading-vert.fixed b/src/test/ui/or-patterns/remove-leading-vert.fixed index c8fac4faa2a66..d23858d42d146 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.fixed +++ b/src/test/ui/or-patterns/remove-leading-vert.fixed @@ -9,7 +9,7 @@ fn main() {} #[cfg(FALSE)] fn leading() { - fn fun1( A: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses + fn fun1( A: E) {} //~ ERROR top-level or-patterns are not allowed fn fun2( A: E) {} //~ ERROR unexpected `||` before function parameter let ( | A): E; let ( | A): (E); //~ ERROR unexpected token `||` in pattern @@ -40,6 +40,9 @@ fn trailing() { //~^ ERROR a trailing `|` is not allowed in an or-pattern } + // These test trailing-vert in `let` bindings, but they also test that we don't emit a + // duplicate suggestion that would confuse rustfix. + let a : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern let a = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern let a ; //~ ERROR a trailing `|` is not allowed in an or-pattern diff --git a/src/test/ui/or-patterns/remove-leading-vert.rs b/src/test/ui/or-patterns/remove-leading-vert.rs index 2cf6b27ab1aac..e753765b3e795 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.rs +++ b/src/test/ui/or-patterns/remove-leading-vert.rs @@ -9,7 +9,7 @@ fn main() {} #[cfg(FALSE)] fn leading() { - fn fun1( | A: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses + fn fun1( | A: E) {} //~ ERROR top-level or-patterns are not allowed fn fun2( || A: E) {} //~ ERROR unexpected `||` before function parameter let ( | A): E; let ( || A): (E); //~ ERROR unexpected token `||` in pattern @@ -40,6 +40,9 @@ fn trailing() { //~^ ERROR a trailing `|` is not allowed in an or-pattern } + // These test trailing-vert in `let` bindings, but they also test that we don't emit a + // duplicate suggestion that would confuse rustfix. + let a | : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern let a | = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern let a | ; //~ ERROR a trailing `|` is not allowed in an or-pattern diff --git a/src/test/ui/or-patterns/remove-leading-vert.stderr b/src/test/ui/or-patterns/remove-leading-vert.stderr index 5c9efd44a187f..0a2b143288dab 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.stderr +++ b/src/test/ui/or-patterns/remove-leading-vert.stderr @@ -1,8 +1,8 @@ -error: an or-pattern parameter must be wrapped in parentheses +error: top-level or-patterns are not allowed in function parameters --> $DIR/remove-leading-vert.rs:12:14 | LL | fn fun1( | A: E) {} - | ^^^ help: remove the leading `|`: `A` + | ^^^ help: remove the `|`: `A` error: unexpected `||` before function parameter --> $DIR/remove-leading-vert.rs:13:14 @@ -135,7 +135,7 @@ LL | | A | B | => {} | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:43:11 + --> $DIR/remove-leading-vert.rs:46:11 | LL | let a | : u8 = 0; | - ^ help: remove the `|` @@ -143,7 +143,7 @@ LL | let a | : u8 = 0; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:44:11 + --> $DIR/remove-leading-vert.rs:47:11 | LL | let a | = 0; | - ^ help: remove the `|` @@ -151,7 +151,7 @@ LL | let a | = 0; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:45:11 + --> $DIR/remove-leading-vert.rs:48:11 | LL | let a | ; | - ^ help: remove the `|` diff --git a/src/tools/cargo b/src/tools/cargo index c68432f1e5cbb..970bc67c37757 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit c68432f1e5cbbc09833699a951b1b5b059651dff +Subproject commit 970bc67c3775781b9708c8a36893576b9459c64a diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index 63d9b7f864597..c89a087657509 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -885,7 +885,9 @@ struct MinifyingSugg<'a>(Sugg<'a>); impl<'a> MinifyingSugg<'a> { fn as_str(&self) -> &str { - let Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s) = &self.0; + let s = match &self.0 { + Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s) => s, + }; s.as_ref() }