Auto merge of #82929 - m-ou-se:rollup-7fwrewh, r=m-ou-se

Rollup of 8 pull requests

Successful merges:

 - #81127 (Improve sift_down performance in BinaryHeap)
 - #81879 (Added #[repr(transparent)] to core::cmp::Reverse)
 - #82048 (or-patterns: disallow in `let` bindings)
 - #82731 (Bump libc dependency of std to 0.2.88.)
 - #82799 (Add regression test for #75525)
 - #82841 (Change x64 size checks to not apply to x32.)
 - #82883 (Update Cargo)
 - #82887 (Update CONTRIBUTING.md)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-03-09 09:43:55 +00:00
commit 3a5d45f68c
67 changed files with 767 additions and 425 deletions

View File

@ -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

View File

@ -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",

View File

@ -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<ForeignItemKind> for ItemKind {

View File

@ -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)]

View File

@ -189,7 +189,7 @@ pub struct TokenStream(pub(crate) Lrc<Vec<TreeAndSpacing>>);
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)]

View File

@ -52,7 +52,7 @@ pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
// `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)]

View File

@ -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);

View File

@ -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:

View File

@ -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]

View File

@ -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<PredicateObligation<'tcx>>;

View File

@ -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);
}
<Self as UnusedDelimLint>::check_stmt(self, cx, s)

View File

@ -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> {

View File

@ -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<Tag = ()> {
Ptr(Pointer<Tag>),
}
#[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<Tag = ()> {
Uninit,
}
#[cfg(target_arch = "x86_64")]
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(ScalarMaybeUninit, 24);
impl<Tag> From<Scalar<Tag>> for ScalarMaybeUninit<Tag> {

View File

@ -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<V, T> ProjectionElem<V, T> {
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
// 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

View File

@ -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> {

View File

@ -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)]

View File

@ -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> {

View File

@ -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> {

View File

@ -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)]

View File

@ -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:

View File

@ -32,7 +32,7 @@ pub enum Immediate<Tag = ()> {
ScalarPair(ScalarMaybeUninit<Tag>, ScalarMaybeUninit<Tag>),
}
#[cfg(target_arch = "x86_64")]
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Immediate, 56);
impl<Tag> From<ScalarMaybeUninit<Tag>> for Immediate<Tag> {
@ -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<Tag: Copy> 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> {

View File

@ -33,7 +33,7 @@ pub enum MemPlaceMeta<Tag = ()> {
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<Tag> MemPlaceMeta<Tag> {
@ -74,7 +74,7 @@ pub struct MemPlace<Tag = ()> {
pub meta: MemPlaceMeta<Tag>,
}
#[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<Tag = ()> {
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> {

View File

@ -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`)

View File

@ -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)
{

View File

@ -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<Pat>> {
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<Pat>, 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<Pat>> {
// 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<Pat>, 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<Pat>, 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<Span>) -> bool {
fn eat_or_separator(&mut self, lo: Option<Span>) -> 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) {

View File

@ -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<Local>> {
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();

View File

@ -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]

View File

@ -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> {

View File

@ -566,7 +566,7 @@ impl<T: Ord> BinaryHeap<T> {
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<T: Ord> BinaryHeap<T> {
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

View File

@ -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<T>(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T);
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]

View File

@ -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" }

View File

@ -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 {

View File

@ -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 }
}

View File

@ -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
}

View File

@ -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<E<{integer}>>`
| | |
| | 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<E<{integer}>>`
| | |
| | expected integer, found enum `E`
| first introduced with type `{integer}` here
|
= note: expected type `{integer}`
found type `E<{integer}>`

View File

@ -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<S, T, U> {
@ -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));

View File

@ -3,28 +3,28 @@
const fn foo((Ok(a) | Err(a)): Result<i32, i32>) {
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
}];
}

View File

@ -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
}

View File

@ -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 <https://github.com/rust-lang/rust/issues/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`.

View File

@ -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

View File

@ -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 <https://github.com/rust-lang/rust/issues/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`.

View File

@ -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

View File

@ -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

View File

@ -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) {}

View File

@ -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<u8, &mut u8> = Ok(0);
let (Ok(ref mut a) | Err(a)): Result<u8, &mut u8> = 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
}

View File

@ -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<u8, &mut u8> = Ok(0);
| - ^ bound in different ways
| |
| first binding
LL | let (Ok(ref mut a) | Err(a)): Result<u8, &mut u8> = 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 _`

View File

@ -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) => {}

View File

@ -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

View File

@ -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 {}
}

View File

@ -3,7 +3,7 @@
// run-pass
fn or_pat_let(x: Result<u32, u32>) -> u32 {
let Ok(y) | Err(y) = x;
let (Ok(y) | Err(y)) = x;
y
}

View File

@ -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
}

View File

@ -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

View File

@ -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<u8> = 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<E<u8>> = 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

View File

@ -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`
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:20
|
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:10
|
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:12
|
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:22
|
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:39:19
--> $DIR/missing-bindings.rs:46:22
|
LL | let A(a, b) | B(a) = X;
| - ^^^^ pattern doesn't bind `b`
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:12
|
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:33
|
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 `a` is not bound in all patterns
--> $DIR/missing-bindings.rs:43:9
|
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
|
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
|
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: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:11
--> $DIR/missing-bindings.rs:46:33
|
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
|
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
|
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
|
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

View File

@ -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() {}

View File

@ -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`.

View File

@ -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

View File

@ -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

View File

@ -37,11 +37,11 @@ fn main() {
if let &(Ok(x) | Err(x)) = res {
drop::<u8>(x);
}
let Ok(mut x) | &Err(mut x) = res;
let (Ok(mut x) | &Err(mut x)) = res;
drop::<u8>(x);
let &(Ok(x) | Err(x)) = res;
drop::<u8>(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::<u8>(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::<u8>(x);
match tri {

View File

@ -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
}

View File

@ -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`.

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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 `|`

@ -1 +1 @@
Subproject commit c68432f1e5cbbc09833699a951b1b5b059651dff
Subproject commit 970bc67c3775781b9708c8a36893576b9459c64a

View File

@ -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()
}