diff --git a/Cargo.lock b/Cargo.lock index 46d8b3de806ff..312f05d6e730e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -590,7 +590,7 @@ name = "crossbeam-deque" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -610,15 +610,15 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1671,6 +1671,14 @@ name = "memoffset" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memoffset" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mime" version = "0.3.13" @@ -3298,6 +3306,11 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "security-framework" version = "0.3.1" @@ -4316,7 +4329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" -"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" @@ -4426,6 +4439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "4c909e78edf61f3aa0dd2086da168cdf304329044bbf248768ca3d20253ec8c0" @@ -4528,6 +4542,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" diff --git a/src/ci/docker/x86_64-gnu-tools/checkregression.py b/src/ci/docker/x86_64-gnu-tools/checkregression.py index 0cc0a6329e5bf..4fbb8c4d20349 100755 --- a/src/ci/docker/x86_64-gnu-tools/checkregression.py +++ b/src/ci/docker/x86_64-gnu-tools/checkregression.py @@ -1,9 +1,18 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +## This script has two purposes: detect any tool that *regressed*, which is used +## during the week before the beta branches to reject PRs; and detect any tool +## that *changed* to see if we need to update the toolstate repo. + import sys import json +# Regressions for these tools during the beta cutoff week do not cause failure. +# See `status_check` in `checktools.sh` for tools that have to pass on the +# beta/stable branches. +REGRESSION_OK = ["rustc-guide", "miri", "embedded-book"] + if __name__ == '__main__': os_name = sys.argv[1] toolstate_file = sys.argv[2] @@ -32,7 +41,8 @@ 'The state of "{}" has {} from "{}" to "{}"' .format(tool, verb, state, new_state) ) - regressed = True + if not (verb == 'regressed' and tool in REGRESSION_OK): + regressed = True if regressed: sys.exit(1) diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index 2191d5d6e4680..4243effdf9b4b 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -25,6 +25,7 @@ python2.7 "$X_PY" test --no-fail-fast \ src/doc/rust-by-example \ src/doc/embedded-book \ src/doc/edition-guide \ + src/doc/rustc-guide \ src/tools/clippy \ src/tools/rls \ src/tools/rustfmt \ @@ -41,7 +42,7 @@ check_tool_failed() { } # This function checks that if a tool's submodule changed, the tool's state must improve -verify_status() { +verify_submodule_changed() { echo "Verifying status of $1..." if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]$2$"; then echo "This PR updated '$2', verifying if status is 'test-pass'..." @@ -66,7 +67,7 @@ verify_status() { check_dispatch() { if [ "$1" = submodule_changed ]; then # ignore $2 (branch id) - verify_status $3 $4 + verify_submodule_changed $3 $4 elif [ "$2" = beta ]; then echo "Requiring test passing for $3..." if check_tool_failed "$3"; then @@ -75,7 +76,12 @@ check_dispatch() { fi } -# list all tools here +# List all tools here. +# This function gets called with "submodule_changed" for each PR that changed a submodule, +# and with "beta_required" for each PR that lands on beta/stable. +# The purpose of this function is to *reject* PRs if a tool is not "test-pass" and +# (a) the tool's submodule has been updated, or (b) we landed on beta/stable and the +# tool has to "test-pass" on that branch. status_check() { check_dispatch $1 beta book src/doc/book check_dispatch $1 beta nomicon src/doc/nomicon @@ -85,7 +91,10 @@ status_check() { check_dispatch $1 beta rls src/tools/rls check_dispatch $1 beta rustfmt src/tools/rustfmt check_dispatch $1 beta clippy-driver src/tools/clippy - # these tools are not required for beta to successfully branch + # These tools are not required on the beta/stable branches, but they *do* cause + # PRs to fail if a submodule update does not fix them. + # They will still cause failure during the beta cutoff week, unless `checkregression.py` + # exempts them from that. check_dispatch $1 nightly miri src/tools/miri check_dispatch $1 nightly embedded-book src/doc/embedded-book check_dispatch $1 nightly rustc-guide src/doc/rustc-guide @@ -97,12 +106,14 @@ status_check() { status_check "submodule_changed" CHECK_NOT="$(readlink -f "$(dirname $0)/checkregression.py")" +# This callback is called by `commit_toolstate_change`, see `repo.sh`. change_toolstate() { # only update the history if python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" changed; then echo 'Toolstate is not changed. Not updating.' else if [ $SIX_WEEK_CYCLE -ge 35 ]; then + # Reject any regressions during the week before beta cutoff. python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed fi sed -i "1 a\\ diff --git a/src/ci/docker/x86_64-gnu-tools/repo.sh b/src/ci/docker/x86_64-gnu-tools/repo.sh index 56186a8b6a686..145f671a8cba5 100644 --- a/src/ci/docker/x86_64-gnu-tools/repo.sh +++ b/src/ci/docker/x86_64-gnu-tools/repo.sh @@ -42,6 +42,13 @@ commit_toolstate_change() { MESSAGE_FILE="$1" shift for RETRY_COUNT in 1 2 3 4 5; do + # Call the callback. + # - If we are in the `auto` branch (pre-landing), this is called from `checktools.sh` and + # the callback is `change_toolstate` in that file. The purpose of this is to publish the + # test results (the new commit-to-toolstate mapping) in the toolstate repo. + # - If we are in the `master` branch (post-landing), this is called by the CI pipeline + # and the callback is `src/tools/publish_toolstate.py`. The purpose is to publish + # the new "current" toolstate in the toolstate repo. "$@" # `git commit` failing means nothing to commit. FAILURE=0 diff --git a/src/doc/unstable-book/src/language-features/slice-patterns.md b/src/doc/unstable-book/src/language-features/slice-patterns.md index 00c81f03ba173..cdb74495884a8 100644 --- a/src/doc/unstable-book/src/language-features/slice-patterns.md +++ b/src/doc/unstable-book/src/language-features/slice-patterns.md @@ -17,7 +17,7 @@ matched against that pattern. For example: fn is_symmetric(list: &[u32]) -> bool { match list { &[] | &[_] => true, - &[x, ref inside.., y] if x == y => is_symmetric(inside), + &[x, ref inside @ .., y] if x == y => is_symmetric(inside), &[..] => false, } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index eb0ea9e08a40e..7121f87d79d95 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -58,6 +58,7 @@ use std::mem; use smallvec::SmallVec; use syntax::attr; use syntax::ast; +use syntax::ptr::P as AstP; use syntax::ast::*; use syntax::errors; use syntax::ext::hygiene::ExpnId; @@ -467,7 +468,7 @@ impl<'a> LoweringContext<'a> { fn visit_pat(&mut self, p: &'tcx Pat) { match p.node { // Doesn't generate a HIR node - PatKind::Paren(..) => {}, + PatKind::Paren(..) | PatKind::Rest => {}, _ => { if let Some(owner) = self.hir_id_owner { self.lctx.lower_node_id_with_owner(p.id, owner); @@ -1156,7 +1157,7 @@ impl<'a> LoweringContext<'a> { &mut self, capture_clause: CaptureBy, closure_node_id: NodeId, - ret_ty: Option>, + ret_ty: Option>, span: Span, body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, ) -> hir::ExprKind { @@ -4171,33 +4172,11 @@ impl<'a> LoweringContext<'a> { let node = match p.node { PatKind::Wild => hir::PatKind::Wild, PatKind::Ident(ref binding_mode, ident, ref sub) => { - match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) { - // `None` can occur in body-less function signatures - res @ None | res @ Some(Res::Local(_)) => { - let canonical_id = match res { - Some(Res::Local(id)) => id, - _ => p.id, - }; - - hir::PatKind::Binding( - self.lower_binding_mode(binding_mode), - self.lower_node_id(canonical_id), - ident, - sub.as_ref().map(|x| self.lower_pat(x)), - ) - } - Some(res) => hir::PatKind::Path(hir::QPath::Resolved( - None, - P(hir::Path { - span: ident.span, - res: self.lower_res(res), - segments: hir_vec![hir::PathSegment::from_ident(ident)], - }), - )), - } + let lower_sub = |this: &mut Self| sub.as_ref().map(|x| this.lower_pat(x)); + self.lower_pat_ident(p, binding_mode, ident, lower_sub) } PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))), - PatKind::TupleStruct(ref path, ref pats, ddpos) => { + PatKind::TupleStruct(ref path, ref pats) => { let qpath = self.lower_qpath( p.id, &None, @@ -4205,11 +4184,8 @@ impl<'a> LoweringContext<'a> { ParamMode::Optional, ImplTraitContext::disallowed(), ); - hir::PatKind::TupleStruct( - qpath, - pats.iter().map(|x| self.lower_pat(x)).collect(), - ddpos, - ) + let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); + hir::PatKind::TupleStruct(qpath, pats, ddpos) } PatKind::Path(ref qself, ref path) => { let qpath = self.lower_qpath( @@ -4246,8 +4222,9 @@ impl<'a> LoweringContext<'a> { .collect(); hir::PatKind::Struct(qpath, fs, etc) } - PatKind::Tuple(ref elts, ddpos) => { - hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos) + PatKind::Tuple(ref pats) => { + let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple"); + hir::PatKind::Tuple(pats, ddpos) } PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)), PatKind::Ref(ref inner, mutbl) => { @@ -4258,15 +4235,138 @@ impl<'a> LoweringContext<'a> { P(self.lower_expr(e2)), self.lower_range_end(end), ), - PatKind::Slice(ref before, ref slice, ref after) => hir::PatKind::Slice( - before.iter().map(|x| self.lower_pat(x)).collect(), - slice.as_ref().map(|x| self.lower_pat(x)), - after.iter().map(|x| self.lower_pat(x)).collect(), - ), + PatKind::Slice(ref pats) => self.lower_pat_slice(pats), + PatKind::Rest => { + // If we reach here the `..` pattern is not semantically allowed. + self.ban_illegal_rest_pat(p.span) + } PatKind::Paren(ref inner) => return self.lower_pat(inner), PatKind::Mac(_) => panic!("Shouldn't exist here"), }; + self.pat_with_node_id_of(p, node) + } + + fn lower_pat_tuple( + &mut self, + pats: &[AstP], + ctx: &str, + ) -> (HirVec>, Option) { + let mut elems = Vec::with_capacity(pats.len()); + let mut rest = None; + + let mut iter = pats.iter().enumerate(); + while let Some((idx, pat)) = iter.next() { + // Interpret the first `..` pattern as a subtuple pattern. + if pat.is_rest() { + rest = Some((idx, pat.span)); + break; + } + // It was not a subslice pattern so lower it normally. + elems.push(self.lower_pat(pat)); + } + + while let Some((_, pat)) = iter.next() { + // There was a previous subtuple pattern; make sure we don't allow more. + if pat.is_rest() { + self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx); + } else { + elems.push(self.lower_pat(pat)); + } + } + + (elems.into(), rest.map(|(ddpos, _)| ddpos)) + } + + fn lower_pat_slice(&mut self, pats: &[AstP]) -> hir::PatKind { + let mut before = Vec::new(); + let mut after = Vec::new(); + let mut slice = None; + let mut prev_rest_span = None; + + let mut iter = pats.iter(); + while let Some(pat) = iter.next() { + // Interpret the first `((ref mut?)? x @)? ..` pattern as a subslice pattern. + match pat.node { + PatKind::Rest => { + prev_rest_span = Some(pat.span); + slice = Some(self.pat_wild_with_node_id_of(pat)); + break; + }, + PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { + prev_rest_span = Some(sub.span); + let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); + let node = self.lower_pat_ident(pat, bm, ident, lower_sub); + slice = Some(self.pat_with_node_id_of(pat, node)); + break; + }, + _ => {} + } + + // It was not a subslice pattern so lower it normally. + before.push(self.lower_pat(pat)); + } + + while let Some(pat) = iter.next() { + // There was a previous subslice pattern; make sure we don't allow more. + let rest_span = match pat.node { + PatKind::Rest => Some(pat.span), + PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => { + // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs. + after.push(self.pat_wild_with_node_id_of(pat)); + Some(sub.span) + }, + _ => None, + }; + if let Some(rest_span) = rest_span { + self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice"); + } else { + after.push(self.lower_pat(pat)); + } + } + + hir::PatKind::Slice(before.into(), slice, after.into()) + } + + fn lower_pat_ident( + &mut self, + p: &Pat, + binding_mode: &BindingMode, + ident: Ident, + lower_sub: impl FnOnce(&mut Self) -> Option>, + ) -> hir::PatKind { + match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) { + // `None` can occur in body-less function signatures + res @ None | res @ Some(Res::Local(_)) => { + let canonical_id = match res { + Some(Res::Local(id)) => id, + _ => p.id, + }; + + hir::PatKind::Binding( + self.lower_binding_mode(binding_mode), + self.lower_node_id(canonical_id), + ident, + lower_sub(self), + ) + } + Some(res) => hir::PatKind::Path(hir::QPath::Resolved( + None, + P(hir::Path { + span: ident.span, + res: self.lower_res(res), + segments: hir_vec![hir::PathSegment::from_ident(ident)], + }), + )), + } + } + + fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> P { + self.pat_with_node_id_of(p, hir::PatKind::Wild) + } + + /// Construct a `Pat` with the `HirId` of `p.id` lowered. + fn pat_with_node_id_of(&mut self, p: &Pat, node: hir::PatKind) -> P { P(hir::Pat { hir_id: self.lower_node_id(p.id), node, @@ -4274,6 +4374,28 @@ impl<'a> LoweringContext<'a> { }) } + /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern. + fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) { + self.diagnostic() + .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx)) + .span_label(sp, &format!("can only be used once per {} pattern", ctx)) + .span_label(prev_sp, "previously used here") + .emit(); + } + + /// Used to ban the `..` pattern in places it shouldn't be semantically. + fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind { + self.diagnostic() + .struct_span_err(sp, "`..` patterns are not allowed here") + .note("only allowed in tuple, tuple struct, and slice patterns") + .emit(); + + // We're not in a list context so `..` can be reasonably treated + // as `_` because it should always be valid and roughly matches the + // intent of `..` (notice that the rest of a single slot is that slot). + hir::PatKind::Wild + } + fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd { match *e { RangeEnd::Included(_) => hir::RangeEnd::Included, diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index fbeda43af42b0..f0bdb0018efe7 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -913,9 +913,12 @@ pub fn compile_unit_metadata( } debug!("compile_unit_metadata: {:?}", name_in_debuginfo); + let rustc_producer = format!( + "rustc version {}", + option_env!("CFG_VERSION").expect("CFG_VERSION"), + ); // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice. - let producer = format!("clang LLVM (rustc version {})", - (option_env!("CFG_VERSION")).expect("CFG_VERSION")); + let producer = format!("clang LLVM ({})", rustc_producer); let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo); @@ -980,6 +983,21 @@ pub fn compile_unit_metadata( gcov_metadata); } + // Insert `llvm.ident` metadata on the wasm32 targets since that will + // get hooked up to the "producer" sections `processed-by` information. + if tcx.sess.opts.target_triple.triple().starts_with("wasm32") { + let name_metadata = llvm::LLVMMDStringInContext( + debug_context.llcontext, + rustc_producer.as_ptr() as *const _, + rustc_producer.as_bytes().len() as c_uint, + ); + llvm::LLVMAddNamedMetadataOperand( + debug_context.llmod, + const_cstr!("llvm.ident").as_ptr(), + llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1), + ); + } + return unit_metadata; }; diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 707b7cae16ce7..3f6a1a72ea61e 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -678,14 +678,6 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, sess.fatal(&format!("failed to run dsymutil: {}", e)) } } - - if sess.opts.target_triple.triple() == "wasm32-unknown-unknown" { - super::wasm::add_producer_section( - &out_filename, - &sess.edition().to_string(), - option_env!("CFG_VERSION").unwrap_or("unknown"), - ); - } } /// Returns a boolean indicating whether the specified crate should be ignored diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index cb8870d0be90c..26091005f25aa 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -901,7 +901,45 @@ pub struct WasmLd<'a> { } impl<'a> WasmLd<'a> { - fn new(cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> { + fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> { + // If the atomics feature is enabled for wasm then we need a whole bunch + // of flags: + // + // * `--shared-memory` - the link won't even succeed without this, flags + // the one linear memory as `shared` + // + // * `--max-memory=1G` - when specifying a shared memory this must also + // be specified. We conservatively choose 1GB but users should be able + // to override this with `-C link-arg`. + // + // * `--import-memory` - it doesn't make much sense for memory to be + // exported in a threaded module because typically you're + // sharing memory and instantiating the module multiple times. As a + // result if it were exported then we'd just have no sharing. + // + // * `--passive-segments` - all memory segments should be passive to + // prevent each module instantiation from reinitializing memory. + // + // * `--export=__wasm_init_memory` - when using `--passive-segments` the + // linker will synthesize this function, and so we need to make sure + // that our usage of `--export` below won't accidentally cause this + // function to get deleted. + // + // * `--export=*tls*` - when `#[thread_local]` symbols are used these + // symbols are how the TLS segments are initialized and configured. + let atomics = sess.opts.cg.target_feature.contains("+atomics") || + sess.target.target.options.features.contains("+atomics"); + if atomics { + cmd.arg("--shared-memory"); + cmd.arg("--max-memory=1073741824"); + cmd.arg("--import-memory"); + cmd.arg("--passive-segments"); + cmd.arg("--export=__wasm_init_memory"); + cmd.arg("--export=__wasm_init_tls"); + cmd.arg("--export=__tls_size"); + cmd.arg("--export=__tls_align"); + cmd.arg("--export=__tls_base"); + } WasmLd { cmd, sess, info } } } @@ -1004,6 +1042,13 @@ impl<'a> Linker for WasmLd<'a> { for sym in self.info.exports[&crate_type].iter() { self.cmd.arg("--export").arg(&sym); } + + // LLD will hide these otherwise-internal symbols since our `--export` + // list above is a whitelist of what to export. Various bits and pieces + // of tooling use this, so be sure these symbols make their way out of + // the linker as well. + self.cmd.arg("--export=__heap_base"); + self.cmd.arg("--export=__data_end"); } fn subsystem(&mut self, _subsystem: &str) { diff --git a/src/librustc_codegen_ssa/back/mod.rs b/src/librustc_codegen_ssa/back/mod.rs index a16d099ee3e4d..901891d85a465 100644 --- a/src/librustc_codegen_ssa/back/mod.rs +++ b/src/librustc_codegen_ssa/back/mod.rs @@ -6,4 +6,3 @@ pub mod command; pub mod symbol_export; pub mod archive; pub mod rpath; -pub mod wasm; diff --git a/src/librustc_codegen_ssa/back/wasm.rs b/src/librustc_codegen_ssa/back/wasm.rs deleted file mode 100644 index 2a9e81a788e52..0000000000000 --- a/src/librustc_codegen_ssa/back/wasm.rs +++ /dev/null @@ -1,191 +0,0 @@ -use std::fs; -use std::path::Path; -use std::str; - -use rustc_serialize::leb128; - -// https://webassembly.github.io/spec/core/binary/modules.html#binary-importsec -const WASM_CUSTOM_SECTION_ID: u8 = 0; - -/// Adds or augment the existing `producers` section to encode information about -/// the Rust compiler used to produce the wasm file. -pub fn add_producer_section( - path: &Path, - rust_version: &str, - rustc_version: &str, -) { - struct Field<'a> { - name: &'a str, - values: Vec>, - } - - #[derive(Copy, Clone)] - struct FieldValue<'a> { - name: &'a str, - version: &'a str, - } - - let wasm = fs::read(path).expect("failed to read wasm output"); - let mut ret = WasmEncoder::new(); - ret.data.extend(&wasm[..8]); - - // skip the 8 byte wasm/version header - let rustc_value = FieldValue { - name: "rustc", - version: rustc_version, - }; - let rust_value = FieldValue { - name: "Rust", - version: rust_version, - }; - let mut fields = Vec::new(); - let mut wrote_rustc = false; - let mut wrote_rust = false; - - // Move all sections from the original wasm file to our output, skipping - // everything except the producers section - for (id, raw) in WasmSections(WasmDecoder::new(&wasm[8..])) { - if id != WASM_CUSTOM_SECTION_ID { - ret.byte(id); - ret.bytes(raw); - continue - } - let mut decoder = WasmDecoder::new(raw); - if decoder.str() != "producers" { - ret.byte(id); - ret.bytes(raw); - continue - } - - // Read off the producers section into our fields outside the loop, - // we'll re-encode the producers section when we're done (to handle an - // entirely missing producers section as well). - info!("rewriting existing producers section"); - - for _ in 0..decoder.u32() { - let name = decoder.str(); - let mut values = Vec::new(); - for _ in 0..decoder.u32() { - let name = decoder.str(); - let version = decoder.str(); - values.push(FieldValue { name, version }); - } - - if name == "language" { - values.push(rust_value); - wrote_rust = true; - } else if name == "processed-by" { - values.push(rustc_value); - wrote_rustc = true; - } - fields.push(Field { name, values }); - } - } - - if !wrote_rust { - fields.push(Field { - name: "language", - values: vec![rust_value], - }); - } - if !wrote_rustc { - fields.push(Field { - name: "processed-by", - values: vec![rustc_value], - }); - } - - // Append the producers section to the end of the wasm file. - let mut section = WasmEncoder::new(); - section.str("producers"); - section.u32(fields.len() as u32); - for field in fields { - section.str(field.name); - section.u32(field.values.len() as u32); - for value in field.values { - section.str(value.name); - section.str(value.version); - } - } - ret.byte(WASM_CUSTOM_SECTION_ID); - ret.bytes(§ion.data); - - fs::write(path, &ret.data).expect("failed to write wasm output"); -} - -struct WasmSections<'a>(WasmDecoder<'a>); - -impl<'a> Iterator for WasmSections<'a> { - type Item = (u8, &'a [u8]); - - fn next(&mut self) -> Option<(u8, &'a [u8])> { - if self.0.data.is_empty() { - return None - } - - // see https://webassembly.github.io/spec/core/binary/modules.html#sections - let id = self.0.byte(); - let section_len = self.0.u32(); - info!("new section {} / {} bytes", id, section_len); - let section = self.0.skip(section_len as usize); - Some((id, section)) - } -} - -struct WasmDecoder<'a> { - data: &'a [u8], -} - -impl<'a> WasmDecoder<'a> { - fn new(data: &'a [u8]) -> WasmDecoder<'a> { - WasmDecoder { data } - } - - fn byte(&mut self) -> u8 { - self.skip(1)[0] - } - - fn u32(&mut self) -> u32 { - let (n, l1) = leb128::read_u32_leb128(self.data); - self.data = &self.data[l1..]; - return n - } - - fn skip(&mut self, amt: usize) -> &'a [u8] { - let (data, rest) = self.data.split_at(amt); - self.data = rest; - data - } - - fn str(&mut self) -> &'a str { - let len = self.u32(); - str::from_utf8(self.skip(len as usize)).unwrap() - } -} - -struct WasmEncoder { - data: Vec, -} - -impl WasmEncoder { - fn new() -> WasmEncoder { - WasmEncoder { data: Vec::new() } - } - - fn u32(&mut self, val: u32) { - leb128::write_u32_leb128(&mut self.data, val); - } - - fn byte(&mut self, val: u8) { - self.data.push(val); - } - - fn bytes(&mut self, val: &[u8]) { - self.u32(val.len() as u32); - self.data.extend_from_slice(val); - } - - fn str(&mut self, val: &str) { - self.bytes(val.as_bytes()) - } -} diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 1baeda41498ed..f759ec7f219d1 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -162,7 +162,7 @@ pub enum PatternKind<'tcx> { /// Matches against a slice, checking the length and extracting elements. /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty. - /// e.g., `&[ref xs..]`. + /// e.g., `&[ref xs @ ..]`. Slice { prefix: Vec>, slice: Option>, diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 562865ef55f4c..7ad37e65f7178 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -287,7 +287,7 @@ impl<'a> AstValidator<'a> { // ``` fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) { match expr.node { - ExprKind::Lit(..) => {} + ExprKind::Lit(..) | ExprKind::Err => {} ExprKind::Path(..) if allow_paths => {} ExprKind::Unary(UnOp::Neg, ref inner) if match inner.node { ExprKind::Lit(_) => true, _ => false } => {} diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 4a4c6799c005e..80fcb45d0b9bc 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -105,20 +105,34 @@ impl TargetDataLayout { let mut dl = TargetDataLayout::default(); let mut i128_align_src = 64; for spec in target.data_layout.split('-') { - match spec.split(':').collect::>()[..] { + let spec_parts = spec.split(':').collect::>(); + + match &*spec_parts { ["e"] => dl.endian = Endian::Little, ["E"] => dl.endian = Endian::Big, [p] if p.starts_with("P") => { dl.instruction_address_space = parse_address_space(&p[1..], "P")? } - ["a", ref a..] => dl.aggregate_align = align(a, "a")?, - ["f32", ref a..] => dl.f32_align = align(a, "f32")?, - ["f64", ref a..] => dl.f64_align = align(a, "f64")?, - [p @ "p", s, ref a..] | [p @ "p0", s, ref a..] => { + // FIXME: Ping cfg(bootstrap) -- Use `ref a @ ..` with new bootstrap compiler. + ["a", ..] => { + let a = &spec_parts[1..]; // FIXME inline into pattern. + dl.aggregate_align = align(a, "a")? + } + ["f32", ..] => { + let a = &spec_parts[1..]; // FIXME inline into pattern. + dl.f32_align = align(a, "f32")? + } + ["f64", ..] => { + let a = &spec_parts[1..]; // FIXME inline into pattern. + dl.f64_align = align(a, "f64")? + } + [p @ "p", s, ..] | [p @ "p0", s, ..] => { + let a = &spec_parts[2..]; // FIXME inline into pattern. dl.pointer_size = size(s, p)?; dl.pointer_align = align(a, p)?; } - [s, ref a..] if s.starts_with("i") => { + [s, ..] if s.starts_with("i") => { + let a = &spec_parts[1..]; // FIXME inline into pattern. let bits = match s[1..].parse::() { Ok(bits) => bits, Err(_) => { @@ -142,7 +156,8 @@ impl TargetDataLayout { dl.i128_align = a; } } - [s, ref a..] if s.starts_with("v") => { + [s, ..] if s.starts_with("v") => { + let a = &spec_parts[1..]; // FIXME inline into pattern. let v_size = size(&s[1..], "v")?; let a = align(a, s)?; if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { diff --git a/src/librustc_target/spec/wasm32_base.rs b/src/librustc_target/spec/wasm32_base.rs index 39a8ce9282573..6f00245b00941 100644 --- a/src/librustc_target/spec/wasm32_base.rs +++ b/src/librustc_target/spec/wasm32_base.rs @@ -132,6 +132,14 @@ pub fn options() -> TargetOptions { // non-relative calls and such later on). relocation_model: "static".to_string(), + // When the atomics feature is activated then these two keys matter, + // otherwise they're basically ignored by the standard library. In this + // mode, however, the `#[thread_local]` attribute works (i.e. + // `has_elf_tls`) and we need to get it to work by specifying + // `local-exec` as that's all that's implemented in LLVM today for wasm. + has_elf_tls: true, + tls_model: "local-exec".to_string(), + .. Default::default() } } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 3f0604b84b7d7..defa6fe4ce15e 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -196,7 +196,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let rhs_ty = self.check_expr(end); // Check that both end-points are of numeric or char type. - let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char(); + let numeric_or_char = |ty: Ty<'_>| { + ty.is_numeric() + || ty.is_char() + || ty.references_error() + }; let lhs_compat = numeric_or_char(lhs_ty); let rhs_compat = numeric_or_char(rhs_ty); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 36977b878dd7e..66c726b2485d1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1818,7 +1818,9 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d ); let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg); err.span_label(sp, &msg); - if let &[ref start.., ref end] = &variant_spans[..] { + if let &[.., ref end] = &variant_spans[..] { + // FIXME: Ping cfg(bootstrap) -- Use `ref start @ ..` with new bootstrap compiler. + let start = &variant_spans[..variant_spans.len() - 1]; for variant_span in start { err.span_label(*variant_span, ""); } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 19d5e8b3e8447..b4c856921198e 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -3497,8 +3497,8 @@ Example of erroneous code: let r = &[1, 2]; match r { - &[a, b, c, rest..] => { // error: pattern requires at least 3 - // elements but array has 2 + &[a, b, c, rest @ ..] => { // error: pattern requires at least 3 + // elements but array has 2 println!("a={}, b={}, c={} rest={:?}", a, b, c, rest); } } @@ -3512,7 +3512,7 @@ requires. You can match an arbitrary number of remaining elements with `..`: let r = &[1, 2, 3, 4, 5]; match r { - &[a, b, c, rest..] => { // ok! + &[a, b, c, rest @ ..] => { // ok! // prints `a=1, b=2, c=3 rest=[4, 5]` println!("a={}, b={}, c={} rest={:?}", a, b, c, rest); } diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 6da77ab57d11e..2e0da0409eb09 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -75,11 +75,6 @@ panic_immediate_abort = ["core/panic_immediate_abort"] # requires rebuilding the standard library to use it. wasm_syscall = [] -# An off-by-default features to enable libstd to assume that wasm-bindgen is in -# the environment for hooking up some thread-related information like the -# current thread id and accessing/getting the current thread's TCB -wasm-bindgen-threads = [] - # Enable std_detect default features for stdarch/crates/std_detect: # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml std_detect_file_io = [] diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs index e22434439f5bb..f842869e08ee6 100644 --- a/src/libstd/sys/wasi/mod.rs +++ b/src/libstd/sys/wasi/mod.rs @@ -47,6 +47,8 @@ pub mod stdio; pub mod thread; #[path = "../wasm/thread_local.rs"] pub mod thread_local; +#[path = "../wasm/fast_thread_local.rs"] +pub mod fast_thread_local; pub mod time; pub mod ext; diff --git a/src/libstd/sys/wasm/fast_thread_local.rs b/src/libstd/sys/wasm/fast_thread_local.rs new file mode 100644 index 0000000000000..ff2198175f0a9 --- /dev/null +++ b/src/libstd/sys/wasm/fast_thread_local.rs @@ -0,0 +1,9 @@ +#![unstable(feature = "thread_local_internals", issue = "0")] + +pub unsafe fn register_dtor(_t: *mut u8, _dtor: unsafe extern fn(*mut u8)) { + // FIXME: right now there is no concept of "thread exit", but this is likely + // going to show up at some point in the form of an exported symbol that the + // wasm runtime is oging to be expected to call. For now we basically just + // ignore the arguments, but if such a function starts to exist it will + // likely look like the OSX implementation in `unix/fast_thread_local.rs` +} diff --git a/src/libstd/sys/wasm/mod.rs b/src/libstd/sys/wasm/mod.rs index 7d157709eb6bf..56cbafcfdb8a2 100644 --- a/src/libstd/sys/wasm/mod.rs +++ b/src/libstd/sys/wasm/mod.rs @@ -37,6 +37,8 @@ pub mod stack_overflow; pub mod thread; pub mod time; pub mod stdio; +pub mod thread_local; +pub mod fast_thread_local; pub use crate::sys_common::os_str_bytes as os_str; @@ -48,13 +50,10 @@ cfg_if::cfg_if! { pub mod mutex; #[path = "rwlock_atomics.rs"] pub mod rwlock; - #[path = "thread_local_atomics.rs"] - pub mod thread_local; } else { pub mod condvar; pub mod mutex; pub mod rwlock; - pub mod thread_local; } } diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs index 61b4003cd3d14..d06965f327849 100644 --- a/src/libstd/sys/wasm/thread.rs +++ b/src/libstd/sys/wasm/thread.rs @@ -59,48 +59,40 @@ pub mod guard { pub unsafe fn init() -> Option { None } } -cfg_if::cfg_if! { - if #[cfg(all(target_feature = "atomics", feature = "wasm-bindgen-threads"))] { - #[link(wasm_import_module = "__wbindgen_thread_xform__")] - extern { - fn __wbindgen_current_id() -> u32; - fn __wbindgen_tcb_get() -> u32; - fn __wbindgen_tcb_set(ptr: u32); +// This is only used by atomics primitives when the `atomics` feature is +// enabled. In that mode we currently just use our own thread-local to store our +// current thread's ID, and then we lazily initialize it to something allocated +// from a global counter. +#[cfg(target_feature = "atomics")] +pub fn my_id() -> u32 { + use crate::sync::atomic::{AtomicU32, Ordering::SeqCst}; + + static NEXT_ID: AtomicU32 = AtomicU32::new(0); + + #[thread_local] + static mut MY_ID: u32 = 0; + + unsafe { + // If our thread ID isn't set yet then we need to allocate one. Do so + // with with a simple "atomically add to a global counter" strategy. + // This strategy doesn't handled what happens when the counter + // overflows, however, so just abort everything once the counter + // overflows and eventually we could have some sort of recycling scheme + // (or maybe this is all totally irrelevant by that point!). In any case + // though we're using a CAS loop instead of a `fetch_add` to ensure that + // the global counter never overflows. + if MY_ID == 0 { + let mut cur = NEXT_ID.load(SeqCst); + MY_ID = loop { + let next = cur.checked_add(1).unwrap_or_else(|| { + crate::arch::wasm32::unreachable() + }); + match NEXT_ID.compare_exchange(cur, next, SeqCst, SeqCst) { + Ok(_) => break next, + Err(i) => cur = i, + } + }; } - pub fn my_id() -> u32 { - unsafe { __wbindgen_current_id() } - } - - // These are currently only ever used in `thread_local_atomics.rs`, if - // you'd like to use them be sure to update that and make sure everyone - // agrees what's what. - pub fn tcb_get() -> *mut u8 { - use crate::mem; - assert_eq!(mem::size_of::<*mut u8>(), mem::size_of::()); - unsafe { __wbindgen_tcb_get() as *mut u8 } - } - - pub fn tcb_set(ptr: *mut u8) { - unsafe { __wbindgen_tcb_set(ptr as u32); } - } - - // FIXME: still need something for hooking exiting a thread to free - // data... - - } else if #[cfg(target_feature = "atomics")] { - pub fn my_id() -> u32 { - panic!("thread ids not implemented on wasm with atomics yet") - } - - pub fn tcb_get() -> *mut u8 { - panic!("thread local data not implemented on wasm with atomics yet") - } - - pub fn tcb_set(_ptr: *mut u8) { - panic!("thread local data not implemented on wasm with atomics yet") - } - } else { - // stubbed out because no functions actually access these intrinsics - // unless atomics are enabled + MY_ID } } diff --git a/src/libstd/sys/wasm/thread_local.rs b/src/libstd/sys/wasm/thread_local.rs index 29e9854bcfccb..8a0ca6f3d25a8 100644 --- a/src/libstd/sys/wasm/thread_local.rs +++ b/src/libstd/sys/wasm/thread_local.rs @@ -1,40 +1,26 @@ -use crate::boxed::Box; -use crate::ptr; - pub type Key = usize; -struct Allocated { - value: *mut u8, - dtor: Option, -} - #[inline] -pub unsafe fn create(dtor: Option) -> Key { - Box::into_raw(Box::new(Allocated { - value: ptr::null_mut(), - dtor, - })) as usize +pub unsafe fn create(_dtor: Option) -> Key { + panic!("should not be used on the wasm target"); } #[inline] -pub unsafe fn set(key: Key, value: *mut u8) { - (*(key as *mut Allocated)).value = value; +pub unsafe fn set(_key: Key, _value: *mut u8) { + panic!("should not be used on the wasm target"); } #[inline] -pub unsafe fn get(key: Key) -> *mut u8 { - (*(key as *mut Allocated)).value +pub unsafe fn get(_key: Key) -> *mut u8 { + panic!("should not be used on the wasm target"); } #[inline] -pub unsafe fn destroy(key: Key) { - let key = Box::from_raw(key as *mut Allocated); - if let Some(f) = key.dtor { - f(key.value); - } +pub unsafe fn destroy(_key: Key) { + panic!("should not be used on the wasm target"); } #[inline] pub fn requires_synchronized_create() -> bool { - false + panic!("should not be used on the wasm target"); } diff --git a/src/libstd/sys/wasm/thread_local_atomics.rs b/src/libstd/sys/wasm/thread_local_atomics.rs deleted file mode 100644 index 3dc0bb24553fd..0000000000000 --- a/src/libstd/sys/wasm/thread_local_atomics.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::sys::thread; -use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; - -const MAX_KEYS: usize = 128; -static NEXT_KEY: AtomicUsize = AtomicUsize::new(0); - -struct ThreadControlBlock { - keys: [*mut u8; MAX_KEYS], -} - -impl ThreadControlBlock { - fn new() -> ThreadControlBlock { - ThreadControlBlock { - keys: [core::ptr::null_mut(); MAX_KEYS], - } - } - - fn get() -> *mut ThreadControlBlock { - let ptr = thread::tcb_get(); - if !ptr.is_null() { - return ptr as *mut ThreadControlBlock - } - let tcb = Box::into_raw(Box::new(ThreadControlBlock::new())); - thread::tcb_set(tcb as *mut u8); - tcb - } -} - -pub type Key = usize; - -pub unsafe fn create(dtor: Option) -> Key { - drop(dtor); // FIXME: need to figure out how to hook thread exit to run this - let key = NEXT_KEY.fetch_add(1, SeqCst); - if key >= MAX_KEYS { - NEXT_KEY.store(MAX_KEYS, SeqCst); - panic!("cannot allocate space for more TLS keys"); - } - // offset by 1 so we never hand out 0. This is currently required by - // `sys_common/thread_local.rs` where it can't cope with keys of value 0 - // because it messes up the atomic management. - return key + 1 -} - -pub unsafe fn set(key: Key, value: *mut u8) { - (*ThreadControlBlock::get()).keys[key - 1] = value; -} - -pub unsafe fn get(key: Key) -> *mut u8 { - (*ThreadControlBlock::get()).keys[key - 1] -} - -pub unsafe fn destroy(_key: Key) { - // FIXME: should implement this somehow, this isn't typically called but it - // can be called if two threads race to initialize a TLS slot and one ends - // up not being needed. -} - -#[inline] -pub fn requires_synchronized_create() -> bool { - false -} diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index dbfad3ef7f4de..a7453f4f9dac2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -519,21 +519,28 @@ impl fmt::Debug for Pat { } impl Pat { + /// Attempt reparsing the pattern as a type. + /// This is intended for use by diagnostics. pub(super) fn to_ty(&self) -> Option> { let node = match &self.node { + // In a type expression `_` is an inference variable. PatKind::Wild => TyKind::Infer, + // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`. PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) => { TyKind::Path(None, Path::from_ident(*ident)) } PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), PatKind::Mac(mac) => TyKind::Mac(mac.clone()), + // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type. PatKind::Ref(pat, mutbl) => pat .to_ty() .map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?, - PatKind::Slice(pats, None, _) if pats.len() == 1 => { - pats[0].to_ty().map(TyKind::Slice)? - } - PatKind::Tuple(pats, None) => { + // A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array, + // when `P` can be reparsed as a type `T`. + PatKind::Slice(pats) if pats.len() == 1 => pats[0].to_ty().map(TyKind::Slice)?, + // A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)` + // assuming `T0` to `Tn` are all syntactically valid as types. + PatKind::Tuple(pats) => { let mut tys = Vec::with_capacity(pats.len()); // FIXME(#48994) - could just be collected into an Option for pat in pats { @@ -559,19 +566,15 @@ impl Pat { return false; } - match self.node { - PatKind::Ident(_, _, Some(ref p)) => p.walk(it), - PatKind::Struct(_, ref fields, _) => fields.iter().all(|field| field.node.pat.walk(it)), - PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => { + match &self.node { + PatKind::Ident(_, _, Some(p)) => p.walk(it), + PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.node.pat.walk(it)), + PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) => { s.iter().all(|p| p.walk(it)) } - PatKind::Box(ref s) | PatKind::Ref(ref s, _) | PatKind::Paren(ref s) => s.walk(it), - PatKind::Slice(ref before, ref slice, ref after) => { - before.iter().all(|p| p.walk(it)) - && slice.iter().all(|p| p.walk(it)) - && after.iter().all(|p| p.walk(it)) - } + PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it), PatKind::Wild + | PatKind::Rest | PatKind::Lit(_) | PatKind::Range(..) | PatKind::Ident(..) @@ -579,6 +582,14 @@ impl Pat { | PatKind::Mac(_) => true, } } + + /// Is this a `..` pattern? + pub fn is_rest(&self) -> bool { + match self.node { + PatKind::Rest => true, + _ => false, + } + } } /// A single field in a struct pattern @@ -630,9 +641,7 @@ pub enum PatKind { Struct(Path, Vec>, /* recovered */ bool), /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). - /// If the `..` pattern fragment is present, then `Option` denotes its position. - /// `0 <= position <= subpats.len()`. - TupleStruct(Path, Vec>, Option), + TupleStruct(Path, Vec>), /// A possibly qualified path pattern. /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants @@ -641,9 +650,7 @@ pub enum PatKind { Path(Option, Path), /// A tuple pattern (`(a, b)`). - /// If the `..` pattern fragment is present, then `Option` denotes its position. - /// `0 <= position <= subpats.len()`. - Tuple(Vec>, Option), + Tuple(Vec>), /// A `box` pattern. Box(P), @@ -657,9 +664,22 @@ pub enum PatKind { /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`). Range(P, P, Spanned), - /// `[a, b, ..i, y, z]` is represented as: - /// `PatKind::Slice(box [a, b], Some(i), box [y, z])` - Slice(Vec>, Option>, Vec>), + /// A slice pattern `[a, b, c]`. + Slice(Vec>), + + /// A rest pattern `..`. + /// + /// Syntactically it is valid anywhere. + /// + /// Semantically however, it only has meaning immediately inside: + /// - a slice pattern: `[a, .., b]`, + /// - a binding pattern immediately inside a slice pattern: `[a, r @ ..]`, + /// - a tuple pattern: `(a, .., b)`, + /// - a tuple struct/variant pattern: `$path(a, .., b)`. + /// + /// In all of these cases, an additional restriction applies, + /// only one rest pattern may occur in the pattern sequences. + Rest, /// Parentheses in patterns used for grouping (i.e., `(PAT)`). Paren(P), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index baf1031de1e7c..528b27d6153df 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -840,14 +840,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn pat_tuple_struct(&self, span: Span, path: ast::Path, subpats: Vec>) -> P { - self.pat(span, PatKind::TupleStruct(path, subpats, None)) + self.pat(span, PatKind::TupleStruct(path, subpats)) } fn pat_struct(&self, span: Span, path: ast::Path, field_pats: Vec>) -> P { self.pat(span, PatKind::Struct(path, field_pats, false)) } fn pat_tuple(&self, span: Span, pats: Vec>) -> P { - self.pat(span, PatKind::Tuple(pats, None)) + self.pat(span, PatKind::Tuple(pats)) } fn pat_some(&self, span: Span, pat: P) -> P { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 72184b0bd6400..384474b08f6ee 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -2151,11 +2151,23 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } fn visit_pat(&mut self, pattern: &'a ast::Pat) { - match pattern.node { - PatKind::Slice(_, Some(ref subslice), _) => { - gate_feature_post!(&self, slice_patterns, - subslice.span, - "syntax for subslices in slice patterns is not yet stabilized"); + match &pattern.node { + PatKind::Slice(pats) => { + for pat in &*pats { + let span = pat.span; + let inner_pat = match &pat.node { + PatKind::Ident(.., Some(pat)) => pat, + _ => pat, + }; + if inner_pat.is_rest() { + gate_feature_post!( + &self, + slice_patterns, + span, + "subslice patterns are unstable" + ); + } + } } PatKind::Box(..) => { gate_feature_post!(&self, box_patterns, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index dc656222fbc10..86525406718b6 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1020,15 +1020,15 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { let Pat { id, node, span } = pat.deref_mut(); vis.visit_id(id); match node { - PatKind::Wild => {} + PatKind::Wild | PatKind::Rest => {} PatKind::Ident(_binding_mode, ident, sub) => { vis.visit_ident(ident); visit_opt(sub, |sub| vis.visit_pat(sub)); } PatKind::Lit(e) => vis.visit_expr(e), - PatKind::TupleStruct(path, pats, _ddpos) => { + PatKind::TupleStruct(path, elems) => { vis.visit_path(path); - visit_vec(pats, |pat| vis.visit_pat(pat)); + visit_vec(elems, |elem| vis.visit_pat(elem)); } PatKind::Path(qself, path) => { vis.visit_qself(qself); @@ -1043,7 +1043,7 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { vis.visit_span(span); }; } - PatKind::Tuple(elts, _ddpos) => visit_vec(elts, |elt| vis.visit_pat(elt)), + PatKind::Tuple(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), PatKind::Box(inner) => vis.visit_pat(inner), PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner), PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => { @@ -1051,11 +1051,7 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { vis.visit_expr(e2); vis.visit_span(span); } - PatKind::Slice(before, slice, after) => { - visit_vec(before, |pat| vis.visit_pat(pat)); - visit_opt(slice, |slice| vis.visit_pat(slice)); - visit_vec(after, |pat| vis.visit_pat(pat)); - } + PatKind::Slice(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), PatKind::Paren(inner) => vis.visit_pat(inner), PatKind::Mac(mac) => vis.visit_mac(mac), } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a5b6f0d683629..8f8ed4111808d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -890,14 +890,13 @@ impl<'a> Parser<'a> { /// Parses a sequence, including the closing delimiter. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_seq_to_end(&mut self, - ket: &TokenKind, - sep: SeqSep, - f: F) - -> PResult<'a, Vec> where - F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { - let (val, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; + pub fn parse_seq_to_end( + &mut self, + ket: &TokenKind, + sep: SeqSep, + f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> PResult<'a, Vec> { + let (val, _, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; if !recovered { self.bump(); } @@ -907,39 +906,39 @@ impl<'a> Parser<'a> { /// Parses a sequence, not including the closing delimiter. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_seq_to_before_end( + pub fn parse_seq_to_before_end( &mut self, ket: &TokenKind, sep: SeqSep, - f: F, - ) -> PResult<'a, (Vec, bool)> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, T> - { + f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> PResult<'a, (Vec, bool, bool)> { self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f) } - crate fn parse_seq_to_before_tokens( + fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType) -> bool { + kets.iter().any(|k| { + match expect { + TokenExpectType::Expect => self.check(k), + TokenExpectType::NoExpect => self.token == **k, + } + }) + } + + crate fn parse_seq_to_before_tokens( &mut self, kets: &[&TokenKind], sep: SeqSep, expect: TokenExpectType, - mut f: F, - ) -> PResult<'a, (Vec, bool /* recovered */)> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, T> - { + mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> PResult<'a, (Vec, bool /* trailing */, bool /* recovered */)> { let mut first = true; let mut recovered = false; + let mut trailing = false; let mut v = vec![]; - while !kets.iter().any(|k| { - match expect { - TokenExpectType::Expect => self.check(k), - TokenExpectType::NoExpect => self.token == **k, - } - }) { - match self.token.kind { - token::CloseDelim(..) | token::Eof => break, - _ => {} - }; + while !self.expect_any_with_type(kets, expect) { + if let token::CloseDelim(..) | token::Eof = self.token.kind { + break + } if let Some(ref t) = sep.sep { if first { first = false; @@ -973,12 +972,8 @@ impl<'a> Parser<'a> { } } } - if sep.trailing_sep_allowed && kets.iter().any(|k| { - match expect { - TokenExpectType::Expect => self.check(k), - TokenExpectType::NoExpect => self.token == **k, - } - }) { + if sep.trailing_sep_allowed && self.expect_any_with_type(kets, expect) { + trailing = true; break; } @@ -986,27 +981,45 @@ impl<'a> Parser<'a> { v.push(t); } - Ok((v, recovered)) + Ok((v, trailing, recovered)) } /// Parses a sequence, including the closing delimiter. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. - fn parse_unspanned_seq( + fn parse_unspanned_seq( &mut self, bra: &TokenKind, ket: &TokenKind, sep: SeqSep, - f: F, - ) -> PResult<'a, Vec> where - F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { + f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> PResult<'a, (Vec, bool)> { self.expect(bra)?; - let (result, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; + let (result, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; if !recovered { self.eat(ket); } - Ok(result) + Ok((result, trailing)) + } + + fn parse_delim_comma_seq( + &mut self, + delim: DelimToken, + f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> PResult<'a, (Vec, bool)> { + self.parse_unspanned_seq( + &token::OpenDelim(delim), + &token::CloseDelim(delim), + SeqSep::trailing_allowed(token::Comma), + f, + ) + } + + fn parse_paren_comma_seq( + &mut self, + f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> PResult<'a, (Vec, bool)> { + self.parse_delim_comma_seq(token::Paren, f) } /// Advance the parser by one token @@ -1804,15 +1817,7 @@ impl<'a> Parser<'a> { AngleBracketedArgs { args, constraints, span }.into() } else { // `(T, U) -> R` - self.bump(); // `(` - let (inputs, recovered) = self.parse_seq_to_before_tokens( - &[&token::CloseDelim(token::Paren)], - SeqSep::trailing_allowed(token::Comma), - TokenExpectType::Expect, - |p| p.parse_ty())?; - if !recovered { - self.bump(); // `)` - } + let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; let span = lo.to(self.prev_span); let output = if self.eat(&token::RArrow) { Some(self.parse_ty_common(false, false, false)?) @@ -2516,12 +2521,7 @@ impl<'a> Parser<'a> { Ok(match self.token.kind { token::OpenDelim(token::Paren) => { // Method call `expr.f()` - let mut args = self.parse_unspanned_seq( - &token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p| Ok(p.parse_expr()?) - )?; + let mut args = self.parse_paren_expr_seq()?; args.insert(0, self_arg); let span = lo.to(self.prev_span); @@ -2606,12 +2606,7 @@ impl<'a> Parser<'a> { match self.token.kind { // expr(...) token::OpenDelim(token::Paren) => { - let seq = self.parse_unspanned_seq( - &token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p| Ok(p.parse_expr()?) - ).map(|es| { + let seq = self.parse_paren_expr_seq().map(|es| { let nd = self.mk_call(e, es); let hi = self.prev_span; self.mk_expr(lo.to(hi), nd, ThinVec::new()) @@ -2635,6 +2630,10 @@ impl<'a> Parser<'a> { return Ok(e); } + fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec>> { + self.parse_paren_comma_seq(|p| p.parse_expr()).map(|(r, _)| r) + } + crate fn process_potential_macro_variable(&mut self) { self.token = match self.token.kind { token::Dollar if self.token.span.ctxt() != SyntaxContext::empty() && @@ -3536,122 +3535,6 @@ impl<'a> Parser<'a> { }; } - // Parses a parenthesized list of patterns like - // `()`, `(p)`, `(p,)`, `(p, q)`, or `(p, .., q)`. Returns: - // - a vector of the patterns that were parsed - // - an option indicating the index of the `..` element - // - a boolean indicating whether a trailing comma was present. - // Trailing commas are significant because (p) and (p,) are different patterns. - fn parse_parenthesized_pat_list(&mut self) -> PResult<'a, (Vec>, Option, bool)> { - self.expect(&token::OpenDelim(token::Paren))?; - let result = match self.parse_pat_list() { - Ok(result) => result, - Err(mut err) => { // recover from parse error in tuple pattern list - err.emit(); - self.consume_block(token::Paren); - return Ok((vec![], Some(0), false)); - } - }; - self.expect(&token::CloseDelim(token::Paren))?; - Ok(result) - } - - fn parse_pat_list(&mut self) -> PResult<'a, (Vec>, Option, bool)> { - let mut fields = Vec::new(); - let mut ddpos = None; - let mut prev_dd_sp = None; - let mut trailing_comma = false; - loop { - if self.eat(&token::DotDot) { - if ddpos.is_none() { - ddpos = Some(fields.len()); - prev_dd_sp = Some(self.prev_span); - } else { - // Emit a friendly error, ignore `..` and continue parsing - let mut err = self.struct_span_err( - self.prev_span, - "`..` can only be used once per tuple or tuple struct pattern", - ); - err.span_label(self.prev_span, "can only be used once per pattern"); - if let Some(sp) = prev_dd_sp { - err.span_label(sp, "previously present here"); - } - err.emit(); - } - } else if !self.check(&token::CloseDelim(token::Paren)) { - fields.push(self.parse_pat(None)?); - } else { - break - } - - trailing_comma = self.eat(&token::Comma); - if !trailing_comma { - break - } - } - - if ddpos == Some(fields.len()) && trailing_comma { - // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed. - let msg = "trailing comma is not permitted after `..`"; - self.struct_span_err(self.prev_span, msg) - .span_label(self.prev_span, msg) - .emit(); - } - - Ok((fields, ddpos, trailing_comma)) - } - - fn parse_pat_vec_elements( - &mut self, - ) -> PResult<'a, (Vec>, Option>, Vec>)> { - let mut before = Vec::new(); - let mut slice = None; - let mut after = Vec::new(); - let mut first = true; - let mut before_slice = true; - - while self.token != token::CloseDelim(token::Bracket) { - if first { - first = false; - } else { - self.expect(&token::Comma)?; - - if self.token == token::CloseDelim(token::Bracket) - && (before_slice || !after.is_empty()) { - break - } - } - - if before_slice { - if self.eat(&token::DotDot) { - - if self.check(&token::Comma) || - self.check(&token::CloseDelim(token::Bracket)) { - slice = Some(P(Pat { - id: ast::DUMMY_NODE_ID, - node: PatKind::Wild, - span: self.prev_span, - })); - before_slice = false; - } - continue - } - } - - let subpat = self.parse_pat(None)?; - if before_slice && self.eat(&token::DotDot) { - slice = Some(subpat); - before_slice = false; - } else if before_slice { - before.push(subpat); - } else { - after.push(subpat); - } - } - - Ok((before, slice, after)) - } - fn parse_pat_field( &mut self, lo: Span, @@ -3847,20 +3730,34 @@ impl<'a> Parser<'a> { } } - // helper function to decide whether to parse as ident binding or to try to do - // something more complex like range patterns + /// Is the current token suitable as the start of a range patterns end? + fn is_pat_range_end_start(&self) -> bool { + self.token.is_path_start() // e.g. `MY_CONST`; + || self.token == token::Dot // e.g. `.5` for recovery; + || self.token.can_begin_literal_or_bool() // e.g. `42`. + } + + // Helper function to decide whether to parse as ident binding + // or to try to do something more complex like range patterns. fn parse_as_ident(&mut self) -> bool { self.look_ahead(1, |t| match t.kind { token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) | - token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false), - // ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the - // range pattern branch - token::DotDot => None, - _ => Some(true), - }).unwrap_or_else(|| self.look_ahead(2, |t| match t.kind { - token::Comma | token::CloseDelim(token::Bracket) => true, - _ => false, - })) + token::DotDotDot | token::DotDotEq | token::DotDot | + token::ModSep | token::Not => false, + _ => true, + }) + } + + /// Parse and throw away a parentesized comma separated + /// sequence of patterns until `)` is reached. + fn skip_pat_list(&mut self) -> PResult<'a, ()> { + while !self.check(&token::CloseDelim(token::Paren)) { + self.parse_pat(None)?; + if !self.eat(&token::Comma) { + return Ok(()) + } + } + Ok(()) } /// A wrapper around `parse_pat` with some special error handling for the @@ -3876,7 +3773,7 @@ impl<'a> Parser<'a> { // later. let comma_span = self.token.span; self.bump(); - if let Err(mut err) = self.parse_pat_list() { + if let Err(mut err) = self.skip_pat_list() { // We didn't expect this to work anyway; we just wanted // to advance to the end of the comma-sequence so we know // the span to suggest parenthesizing @@ -3908,6 +3805,53 @@ impl<'a> Parser<'a> { self.parse_pat_with_range_pat(true, expected) } + /// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery. + fn parse_pat_range_to(&mut self, re: RangeEnd, form: &str) -> PResult<'a, PatKind> { + let lo = self.prev_span; + let end = self.parse_pat_range_end()?; + let range_span = lo.to(end.span); + let begin = self.mk_expr(range_span, ExprKind::Err, ThinVec::new()); + + self.diagnostic() + .struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form)) + .span_suggestion( + range_span, + "try using the minimum value for the type", + format!("MIN{}{}", form, pprust::expr_to_string(&end)), + Applicability::HasPlaceholders, + ) + .emit(); + + Ok(PatKind::Range(begin, end, respan(lo, re))) + } + + /// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern or recover + /// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively. + fn parse_pat_range_end_opt(&mut self, begin: &Expr, form: &str) -> PResult<'a, P> { + if self.is_pat_range_end_start() { + // Parsing e.g. `X..=Y`. + self.parse_pat_range_end() + } else { + // Parsing e.g. `X..`. + let range_span = begin.span.to(self.prev_span); + + self.diagnostic() + .struct_span_err( + range_span, + &format!("`X{}` range patterns are not supported", form), + ) + .span_suggestion( + range_span, + "try using the maximum value for the type", + format!("{}{}MAX", pprust::expr_to_string(&begin), form), + Applicability::HasPlaceholders, + ) + .emit(); + + Ok(self.mk_expr(range_span, ExprKind::Err, ThinVec::new())) + } + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( @@ -3934,20 +3878,41 @@ impl<'a> Parser<'a> { pat = PatKind::Ref(subpat, mutbl); } token::OpenDelim(token::Paren) => { - // Parse (pat,pat,pat,...) as tuple pattern - let (fields, ddpos, trailing_comma) = self.parse_parenthesized_pat_list()?; - pat = if fields.len() == 1 && ddpos.is_none() && !trailing_comma { + // Parse a tuple or parenthesis pattern. + let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; + + // Here, `(pat,)` is a tuple pattern. + // For backward compatibility, `(..)` is a tuple pattern as well. + pat = if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) { PatKind::Paren(fields.into_iter().nth(0).unwrap()) } else { - PatKind::Tuple(fields, ddpos) + PatKind::Tuple(fields) }; } token::OpenDelim(token::Bracket) => { - // Parse [pat,pat,...] as slice pattern + // Parse `[pat, pat,...]` as a slice pattern. + let (slice, _) = self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?; + pat = PatKind::Slice(slice); + } + token::DotDot => { + self.bump(); + pat = if self.is_pat_range_end_start() { + // Parse `..42` for recovery. + self.parse_pat_range_to(RangeEnd::Excluded, "..")? + } else { + // A rest pattern `..`. + PatKind::Rest + }; + } + token::DotDotEq => { + // Parse `..=42` for recovery. self.bump(); - let (before, slice, after) = self.parse_pat_vec_elements()?; - self.expect(&token::CloseDelim(token::Bracket))?; - pat = PatKind::Slice(before, slice, after); + pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?; + } + token::DotDotDot => { + // Parse `...42` for recovery. + self.bump(); + pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?; } // At this point, token != &, &&, (, [ _ => if self.eat_keyword(kw::Underscore) { @@ -4004,10 +3969,10 @@ impl<'a> Parser<'a> { pat = PatKind::Mac(mac); } token::DotDotDot | token::DotDotEq | token::DotDot => { - let end_kind = match self.token.kind { - token::DotDot => RangeEnd::Excluded, - token::DotDotDot => RangeEnd::Included(RangeSyntax::DotDotDot), - token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq), + let (end_kind, form) = match self.token.kind { + token::DotDot => (RangeEnd::Excluded, ".."), + token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."), + token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="), _ => panic!("can only parse `..`/`...`/`..=` for ranges \ (checked above)"), }; @@ -4016,9 +3981,8 @@ impl<'a> Parser<'a> { let span = lo.to(self.prev_span); let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new()); self.bump(); - let end = self.parse_pat_range_end()?; - let op = Spanned { span: op_span, node: end_kind }; - pat = PatKind::Range(begin, end, op); + let end = self.parse_pat_range_end_opt(&begin, form)?; + pat = PatKind::Range(begin, end, respan(op_span, end_kind)); } token::OpenDelim(token::Brace) => { if qself.is_some() { @@ -4045,8 +4009,8 @@ impl<'a> Parser<'a> { return Err(err); } // Parse tuple struct or enum pattern - let (fields, ddpos, _) = self.parse_parenthesized_pat_list()?; - pat = PatKind::TupleStruct(path, fields, ddpos) + let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; + pat = PatKind::TupleStruct(path, fields) } _ => pat = PatKind::Path(qself, path), } @@ -4057,19 +4021,18 @@ impl<'a> Parser<'a> { let op_span = self.token.span; if self.check(&token::DotDot) || self.check(&token::DotDotEq) || self.check(&token::DotDotDot) { - let end_kind = if self.eat(&token::DotDotDot) { - RangeEnd::Included(RangeSyntax::DotDotDot) + let (end_kind, form) = if self.eat(&token::DotDotDot) { + (RangeEnd::Included(RangeSyntax::DotDotDot), "...") } else if self.eat(&token::DotDotEq) { - RangeEnd::Included(RangeSyntax::DotDotEq) + (RangeEnd::Included(RangeSyntax::DotDotEq), "..=") } else if self.eat(&token::DotDot) { - RangeEnd::Excluded + (RangeEnd::Excluded, "..") } else { panic!("impossible case: we already matched \ on a range-operator token") }; - let end = self.parse_pat_range_end()?; - let op = Spanned { span: op_span, node: end_kind }; - pat = PatKind::Range(begin, end, op); + let end = self.parse_pat_range_end_opt(&begin, form)?; + pat = PatKind::Range(begin, end, respan(op_span, end_kind)) } else { pat = PatKind::Lit(begin); } @@ -5359,59 +5322,48 @@ impl<'a> Parser<'a> { fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool) -> PResult<'a, (Vec , bool)> { - self.expect(&token::OpenDelim(token::Paren))?; - let sp = self.token.span; let mut c_variadic = false; - let (args, recovered): (Vec>, bool) = - self.parse_seq_to_before_end( - &token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p| { - let do_not_enforce_named_arguments_for_c_variadic = - |token: &token::Token| -> bool { - if token == &token::DotDotDot { - false - } else { - named_args - } - }; - match p.parse_arg_general( - false, - allow_c_variadic, - do_not_enforce_named_arguments_for_c_variadic - ) { - Ok(arg) => { - if let TyKind::CVarArgs = arg.ty.node { - c_variadic = true; - if p.token != token::CloseDelim(token::Paren) { - let span = p.token.span; - p.span_err(span, - "`...` must be the last argument of a C-variadic function"); - Ok(None) - } else { - Ok(Some(arg)) - } - } else { - Ok(Some(arg)) - } - }, - Err(mut e) => { - e.emit(); - let lo = p.prev_span; - // Skip every token until next possible arg or end. - p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); - // Create a placeholder argument for proper arg count (issue #34264). - let span = lo.to(p.prev_span); - Ok(Some(dummy_arg(Ident::new(kw::Invalid, span)))) + let (args, _): (Vec>, _) = self.parse_paren_comma_seq(|p| { + let do_not_enforce_named_arguments_for_c_variadic = + |token: &token::Token| -> bool { + if token == &token::DotDotDot { + false + } else { + named_args + } + }; + match p.parse_arg_general( + false, + allow_c_variadic, + do_not_enforce_named_arguments_for_c_variadic + ) { + Ok(arg) => { + if let TyKind::CVarArgs = arg.ty.node { + c_variadic = true; + if p.token != token::CloseDelim(token::Paren) { + let span = p.token.span; + p.span_err(span, + "`...` must be the last argument of a C-variadic function"); + Ok(None) + } else { + Ok(Some(arg)) } + } else { + Ok(Some(arg)) } + }, + Err(mut e) => { + e.emit(); + let lo = p.prev_span; + // Skip every token until next possible arg or end. + p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); + // Create a placeholder argument for proper arg count (issue #34264). + let span = lo.to(p.prev_span); + Ok(Some(dummy_arg(Ident::new(kw::Invalid, span)))) } - )?; - - if !recovered { - self.eat(&token::CloseDelim(token::Paren)); - } + } + })?; let args: Vec<_> = args.into_iter().filter_map(|x| x).collect(); @@ -5573,7 +5525,7 @@ impl<'a> Parser<'a> { (vec![self_arg], false) } else if self.eat(&token::Comma) { let mut fn_inputs = vec![self_arg]; - let (mut input, recovered) = self.parse_seq_to_before_end( + let (mut input, _, recovered) = self.parse_seq_to_before_end( &token::CloseDelim(token::Paren), sep, parse_arg_fn)?; fn_inputs.append(&mut input); (fn_inputs, recovered) @@ -5584,7 +5536,9 @@ impl<'a> Parser<'a> { } } } else { - self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)? + let (input, _, recovered) = + self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?; + (input, recovered) }; if !recovered { @@ -6185,26 +6139,20 @@ impl<'a> Parser<'a> { fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec> { // This is the case where we find `struct Foo(T) where T: Copy;` // Unit like structs are handled in parse_item_struct function - let fields = self.parse_unspanned_seq( - &token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p| { - let attrs = p.parse_outer_attributes()?; - let lo = p.token.span; - let vis = p.parse_visibility(true)?; - let ty = p.parse_ty()?; - Ok(StructField { - span: lo.to(ty.span), - vis, - ident: None, - id: ast::DUMMY_NODE_ID, - ty, - attrs, - }) - })?; - - Ok(fields) + self.parse_paren_comma_seq(|p| { + let attrs = p.parse_outer_attributes()?; + let lo = p.token.span; + let vis = p.parse_visibility(true)?; + let ty = p.parse_ty()?; + Ok(StructField { + span: lo.to(ty.span), + vis, + ident: None, + id: ast::DUMMY_NODE_ID, + ty, + attrs, + }) + }).map(|(r, _)| r) } /// Parses a structure field declaration. @@ -7786,11 +7734,8 @@ impl<'a> Parser<'a> { /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`] /// ``` fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> { - self.parse_unspanned_seq(&token::OpenDelim(token::Brace), - &token::CloseDelim(token::Brace), - SeqSep::trailing_allowed(token::Comma), |this| { - Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID)) - }) + self.parse_delim_comma_seq(token::Brace, |p| Ok((p.parse_use_tree()?, ast::DUMMY_NODE_ID))) + .map(|(r, _)| r) } fn parse_rename(&mut self) -> PResult<'a, Option> { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c462357639506..c7be0b123023d 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2368,22 +2368,10 @@ impl<'a> State<'a> { self.print_pat(p); } } - PatKind::TupleStruct(ref path, ref elts, ddpos) => { + PatKind::TupleStruct(ref path, ref elts) => { self.print_path(path, true, 0); self.popen(); - if let Some(ddpos) = ddpos { - self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p)); - if ddpos != 0 { - self.word_space(","); - } - self.s.word(".."); - if ddpos != elts.len() { - self.s.word(","); - self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p)); - } - } else { - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); - } + self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); self.pclose(); } PatKind::Path(None, ref path) => { @@ -2415,23 +2403,11 @@ impl<'a> State<'a> { self.s.space(); self.s.word("}"); } - PatKind::Tuple(ref elts, ddpos) => { + PatKind::Tuple(ref elts) => { self.popen(); - if let Some(ddpos) = ddpos { - self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p)); - if ddpos != 0 { - self.word_space(","); - } - self.s.word(".."); - if ddpos != elts.len() { - self.s.word(","); - self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p)); - } - } else { - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); - if elts.len() == 1 { - self.s.word(","); - } + self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); + if elts.len() == 1 { + self.s.word(","); } self.pclose(); } @@ -2457,26 +2433,12 @@ impl<'a> State<'a> { } self.print_expr(end); } - PatKind::Slice(ref before, ref slice, ref after) => { + PatKind::Slice(ref elts) => { self.s.word("["); - self.commasep(Inconsistent, - &before[..], - |s, p| s.print_pat(p)); - if let Some(ref p) = *slice { - if !before.is_empty() { self.word_space(","); } - if let PatKind::Wild = p.node { - // Print nothing - } else { - self.print_pat(p); - } - self.s.word(".."); - if !after.is_empty() { self.word_space(","); } - } - self.commasep(Inconsistent, - &after[..], - |s, p| s.print_pat(p)); + self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); self.s.word("]"); } + PatKind::Rest => self.s.word(".."), PatKind::Paren(ref inner) => { self.popen(); self.print_pat(inner); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 9ec9550f93ab9..ff6440fb9dceb 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -428,9 +428,9 @@ pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(visitor: &mut V, pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { match pattern.node { - PatKind::TupleStruct(ref path, ref children, _) => { + PatKind::TupleStruct(ref path, ref elems) => { visitor.visit_path(path, pattern.id); - walk_list!(visitor, visit_pat, children); + walk_list!(visitor, visit_pat, elems); } PatKind::Path(ref opt_qself, ref path) => { if let Some(ref qself) = *opt_qself { @@ -446,8 +446,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { visitor.visit_pat(&field.node.pat) } } - PatKind::Tuple(ref tuple_elements, _) => { - walk_list!(visitor, visit_pat, tuple_elements); + PatKind::Tuple(ref elems) => { + walk_list!(visitor, visit_pat, elems); } PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) | @@ -463,11 +463,9 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { visitor.visit_expr(lower_bound); visitor.visit_expr(upper_bound); } - PatKind::Wild => (), - PatKind::Slice(ref prepatterns, ref slice_pattern, ref postpatterns) => { - walk_list!(visitor, visit_pat, prepatterns); - walk_list!(visitor, visit_pat, slice_pattern); - walk_list!(visitor, visit_pat, postpatterns); + PatKind::Wild | PatKind::Rest => {}, + PatKind::Slice(ref elems) => { + walk_list!(visitor, visit_pat, elems); } PatKind::Mac(ref mac) => visitor.visit_mac(mac), } diff --git a/src/llvm-project b/src/llvm-project index f6446fa8e9629..9b64ca5b7e1e3 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit f6446fa8e9629ffb1861303f17930c3aa83ef660 +Subproject commit 9b64ca5b7e1e3583978f9ac8af6d93b220a13d90 diff --git a/src/test/mir-opt/uniform_array_move_out.rs b/src/test/mir-opt/uniform_array_move_out.rs index fac5ef3b03ce1..c249154c71e23 100644 --- a/src/test/mir-opt/uniform_array_move_out.rs +++ b/src/test/mir-opt/uniform_array_move_out.rs @@ -8,7 +8,7 @@ fn move_out_from_end() { fn move_out_by_subslice() { let a = [box 1, box 2]; - let [_y..] = a; + let [_y @ ..] = a; } fn main() { diff --git a/src/test/ui/array-slice-vec/vec-matching-fold.rs b/src/test/ui/array-slice-vec/vec-matching-fold.rs index 2b19c49c42700..f416160db2422 100644 --- a/src/test/ui/array-slice-vec/vec-matching-fold.rs +++ b/src/test/ui/array-slice-vec/vec-matching-fold.rs @@ -11,7 +11,7 @@ fn foldl(values: &[T], U: Clone+Debug, T:Debug, F: FnMut(U, &T) -> U, { match values { - &[ref head, ref tail..] => + &[ref head, ref tail @ ..] => foldl(tail, function(initial, head), function), &[] => { // FIXME: call guards @@ -28,7 +28,7 @@ fn foldr(values: &[T], F: FnMut(&T, U) -> U, { match values { - &[ref head.., ref tail] => + &[ref head @ .., ref tail] => foldr(head, function(tail, initial), function), &[] => { // FIXME: call guards diff --git a/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs index bce03b3375e51..f0602c328b071 100644 --- a/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs +++ b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs @@ -8,7 +8,7 @@ pub fn main() { let x: &[isize] = &[1, 2, 3, 4, 5]; if !x.is_empty() { let el = match x { - &[1, ref tail..] => &tail[0], + &[1, ref tail @ ..] => &tail[0], _ => unreachable!() }; println!("{}", *el); diff --git a/src/test/ui/array-slice-vec/vec-matching.rs b/src/test/ui/array-slice-vec/vec-matching.rs index a37c25160fa76..49c736bd72847 100644 --- a/src/test/ui/array-slice-vec/vec-matching.rs +++ b/src/test/ui/array-slice-vec/vec-matching.rs @@ -14,7 +14,7 @@ fn a() { fn b() { let x = [1, 2, 3]; match x { - [a, b, c..] => { + [a, b, c @ ..] => { assert_eq!(a, 1); assert_eq!(b, 2); let expected: &[_] = &[3]; @@ -22,7 +22,7 @@ fn b() { } } match x { - [a.., b, c] => { + [a @ .., b, c] => { let expected: &[_] = &[1]; assert_eq!(a, expected); assert_eq!(b, 2); @@ -30,7 +30,7 @@ fn b() { } } match x { - [a, b.., c] => { + [a, b @ .., c] => { assert_eq!(a, 1); let expected: &[_] = &[2]; assert_eq!(b, expected); @@ -50,7 +50,7 @@ fn b() { fn b_slice() { let x : &[_] = &[1, 2, 3]; match x { - &[a, b, ref c..] => { + &[a, b, ref c @ ..] => { assert_eq!(a, 1); assert_eq!(b, 2); let expected: &[_] = &[3]; @@ -59,7 +59,7 @@ fn b_slice() { _ => unreachable!() } match x { - &[ref a.., b, c] => { + &[ref a @ .., b, c] => { let expected: &[_] = &[1]; assert_eq!(a, expected); assert_eq!(b, 2); @@ -68,7 +68,7 @@ fn b_slice() { _ => unreachable!() } match x { - &[a, ref b.., c] => { + &[a, ref b @ .., c] => { assert_eq!(a, 1); let expected: &[_] = &[2]; assert_eq!(b, expected); @@ -134,20 +134,6 @@ fn e() { assert_eq!(c, 1); } -fn f() { - let x = &[1, 2, 3, 4, 5]; - let [a, [b, [c, ..].., d].., e] = *x; - assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5)); - - let x: &[isize] = x; - let (a, b, c, d, e) = match *x { - [a, [b, [c, ..].., d].., e] => (a, b, c, d, e), - _ => unimplemented!() - }; - - assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5)); -} - pub fn main() { a(); b(); @@ -155,5 +141,4 @@ pub fn main() { c(); d(); e(); - f(); } diff --git a/src/test/ui/array-slice-vec/vec-tail-matching.rs b/src/test/ui/array-slice-vec/vec-tail-matching.rs index 84d246dff825c..3c7b160dcc540 100644 --- a/src/test/ui/array-slice-vec/vec-tail-matching.rs +++ b/src/test/ui/array-slice-vec/vec-tail-matching.rs @@ -13,14 +13,14 @@ pub fn main() { Foo { string: "baz" } ]; match x { - [ref first, ref tail..] => { + [ref first, ref tail @ ..] => { assert_eq!(first.string, "foo"); assert_eq!(tail.len(), 2); assert_eq!(tail[0].string, "bar"); assert_eq!(tail[1].string, "baz"); match *(tail as &[_]) { - [Foo { .. }, _, Foo { .. }, ref _tail..] => { + [Foo { .. }, _, Foo { .. }, ref _tail @ ..] => { unreachable!(); } [Foo { string: ref a }, Foo { string: ref b }] => { diff --git a/src/test/ui/associated-path-shl.rs b/src/test/ui/associated-path-shl.rs index d159082ab7ad5..20a6fd83faa32 100644 --- a/src/test/ui/associated-path-shl.rs +++ b/src/test/ui/associated-path-shl.rs @@ -5,6 +5,5 @@ fn main() { let _ = <::B>::C; //~ ERROR cannot find type `A` in this scope let <::B>::C; //~ ERROR cannot find type `A` in this scope let 0 ..= <::B>::C; //~ ERROR cannot find type `A` in this scope - //~^ ERROR only char and numeric types are allowed in range patterns <::B>::C; //~ ERROR cannot find type `A` in this scope } diff --git a/src/test/ui/associated-path-shl.stderr b/src/test/ui/associated-path-shl.stderr index 23918ed2e3912..71ee93f4835fb 100644 --- a/src/test/ui/associated-path-shl.stderr +++ b/src/test/ui/associated-path-shl.stderr @@ -23,21 +23,11 @@ LL | let 0 ..= <::B>::C; | ^ not found in this scope error[E0412]: cannot find type `A` in this scope - --> $DIR/associated-path-shl.rs:9:7 + --> $DIR/associated-path-shl.rs:8:7 | LL | <::B>::C; | ^ not found in this scope -error[E0029]: only char and numeric types are allowed in range patterns - --> $DIR/associated-path-shl.rs:7:15 - | -LL | let 0 ..= <::B>::C; - | ^^^^^^^^^^^ ranges require char or numeric types - | - = note: start type: {integer} - = note: end type: [type error] - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0029, E0412. -For more information about an error, try `rustc --explain E0029`. +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/binding/irrefutable-slice-patterns.rs b/src/test/ui/binding/irrefutable-slice-patterns.rs index 733e6b7b57f72..ac733ef6e9c86 100644 --- a/src/test/ui/binding/irrefutable-slice-patterns.rs +++ b/src/test/ui/binding/irrefutable-slice-patterns.rs @@ -4,7 +4,7 @@ #![feature(slice_patterns)] fn foo(s: &[i32]) -> &[i32] { - let &[ref xs..] = s; + let &[ref xs @ ..] = s; xs } diff --git a/src/test/ui/binding/zero_sized_subslice_match.rs b/src/test/ui/binding/zero_sized_subslice_match.rs index 51e1c024bffff..5326fa612a87b 100644 --- a/src/test/ui/binding/zero_sized_subslice_match.rs +++ b/src/test/ui/binding/zero_sized_subslice_match.rs @@ -7,6 +7,6 @@ fn main() { // The subslice used to go out of bounds for zero-sized array items, check that this doesn't // happen anymore match x { - [_, ref y..] => assert_eq!(&x[1] as *const (), &y[0] as *const ()) + [_, ref y @ ..] => assert_eq!(&x[1] as *const (), &y[0] as *const ()) } } diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.nll.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.nll.stderr index f1e1ae18839c4..20f05353d4633 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.nll.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.nll.stderr @@ -192,8 +192,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed LL | let x = &mut v; | ------ borrow of `v` occurs here LL | match v { -LL | &[x..] => println!("{:?}", x), - | ^ use of borrowed `v` +LL | &[x @ ..] => println!("{:?}", x), + | ^^^^^^ use of borrowed `v` ... LL | drop(x); | - borrow later used here @@ -204,8 +204,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed LL | let x = &mut v; | ------ borrow of `v` occurs here ... -LL | &[_, x..] => println!("{:?}", x), - | ^ use of borrowed `v` +LL | &[_, x @ ..] => println!("{:?}", x), + | ^^^^^^ use of borrowed `v` ... LL | drop(x); | - borrow later used here @@ -216,8 +216,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed LL | let x = &mut v; | ------ borrow of `v` occurs here ... -LL | &[x.., _] => println!("{:?}", x), - | ^ use of borrowed `v` +LL | &[x @ .., _] => println!("{:?}", x), + | ^^^^^^ use of borrowed `v` ... LL | drop(x); | - borrow later used here @@ -228,8 +228,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed LL | let x = &mut v; | ------ borrow of `v` occurs here ... -LL | &[_, x.., _] => println!("{:?}", x), - | ^ use of borrowed `v` +LL | &[_, x @ .., _] => println!("{:?}", x), + | ^^^^^^ use of borrowed `v` ... LL | drop(x); | - borrow later used here diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs index c8dbf4e691816..c27d9519dc798 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs @@ -140,22 +140,22 @@ fn main() { let mut v = &[1, 2, 3, 4, 5]; let x = &mut v; match v { - &[x..] => println!("{:?}", x), + &[x @ ..] => println!("{:?}", x), //~^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } match v { - &[_, x..] => println!("{:?}", x), + &[_, x @ ..] => println!("{:?}", x), //~^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } match v { - &[x.., _] => println!("{:?}", x), + &[x @ .., _] => println!("{:?}", x), //~^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } match v { - &[_, x.., _] => println!("{:?}", x), + &[_, x @ .., _] => println!("{:?}", x), //~^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr index 14b9b50f0c32a..38d847a90ff95 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr @@ -192,8 +192,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed LL | let x = &mut v; | ------ borrow of `v` occurs here LL | match v { -LL | &[x..] => println!("{:?}", x), - | ^ use of borrowed `v` +LL | &[x @ ..] => println!("{:?}", x), + | ^^^^^^ use of borrowed `v` ... LL | drop(x); | - borrow later used here @@ -204,8 +204,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed LL | let x = &mut v; | ------ borrow of `v` occurs here ... -LL | &[_, x..] => println!("{:?}", x), - | ^ use of borrowed `v` +LL | &[_, x @ ..] => println!("{:?}", x), + | ^^^^^^ use of borrowed `v` ... LL | drop(x); | - borrow later used here @@ -216,8 +216,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed LL | let x = &mut v; | ------ borrow of `v` occurs here ... -LL | &[x.., _] => println!("{:?}", x), - | ^ use of borrowed `v` +LL | &[x @ .., _] => println!("{:?}", x), + | ^^^^^^ use of borrowed `v` ... LL | drop(x); | - borrow later used here @@ -228,8 +228,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed LL | let x = &mut v; | ------ borrow of `v` occurs here ... -LL | &[_, x.., _] => println!("{:?}", x), - | ^ use of borrowed `v` +LL | &[_, x @ .., _] => println!("{:?}", x), + | ^^^^^^ use of borrowed `v` ... LL | drop(x); | - borrow later used here diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.rs b/src/test/ui/borrowck/borrowck-move-out-from-array.rs index 856b03edd2d72..ee6abf407a304 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.rs +++ b/src/test/ui/borrowck/borrowck-move-out-from-array.rs @@ -10,7 +10,7 @@ fn move_out_from_begin_and_end() { fn move_out_by_const_index_and_subslice() { let a = [box 1, box 2]; let [_x, _] = a; - let [_y..] = a; //~ ERROR [E0382] + let [_y @ ..] = a; //~ ERROR [E0382] } fn main() {} diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr index 16722a456defa..b34c03e6deff8 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr @@ -13,8 +13,8 @@ error[E0382]: use of moved value: `a[..]` | LL | let [_x, _] = a; | -- value moved here -LL | let [_y..] = a; - | ^^ value used here after move +LL | let [_y @ ..] = a; + | ^^^^^^^ value used here after move | = note: move occurs because `a[..]` has type `std::boxed::Box`, which does not implement the `Copy` trait diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs index cc524c1ac3e6e..fa9a3c217db77 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs +++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs @@ -15,7 +15,7 @@ pub fn main() { ]; let x: &[Foo] = &x; match *x { - [_, ref tail..] => { + [_, ref tail @ ..] => { match tail { //~^ ERROR cannot move out of type `[Foo]` &[Foo { string: a }, diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs index 7675147c8ec2a..048813b2b93e6 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs @@ -5,7 +5,7 @@ fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> { match *v { - [ref mut head, ref mut tail..] => { + [ref mut head, ref mut tail @ ..] => { Some((head, tail)) } [] => None diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs index 5de8dd3305e37..a6b54f9537ddc 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs @@ -70,7 +70,7 @@ fn const_index_mixed(s: &mut [i32]) { fn const_index_and_subslice_ok(s: &mut [i32]) { if let [ref first, ref second, ..] = *s { - if let [_, _, ref mut tail..] = *s { + if let [_, _, ref mut tail @ ..] = *s { nop(&[first, second]); nop_subslice(tail); } @@ -79,7 +79,7 @@ fn const_index_and_subslice_ok(s: &mut [i32]) { fn const_index_and_subslice_err(s: &mut [i32]) { if let [ref first, ref second, ..] = *s { - if let [_, ref mut tail..] = *s { //~ERROR + if let [_, ref mut tail @ ..] = *s { //~ERROR nop(&[first, second]); nop_subslice(tail); } @@ -88,7 +88,7 @@ fn const_index_and_subslice_err(s: &mut [i32]) { fn const_index_and_subslice_from_end_ok(s: &mut [i32]) { if let [.., ref second, ref first] = *s { - if let [ref mut tail.., _, _] = *s { + if let [ref mut tail @ .., _, _] = *s { nop(&[first, second]); nop_subslice(tail); } @@ -97,7 +97,7 @@ fn const_index_and_subslice_from_end_ok(s: &mut [i32]) { fn const_index_and_subslice_from_end_err(s: &mut [i32]) { if let [.., ref second, ref first] = *s { - if let [ref mut tail.., _] = *s { //~ERROR + if let [ref mut tail @ .., _] = *s { //~ERROR nop(&[first, second]); nop_subslice(tail); } @@ -105,8 +105,8 @@ fn const_index_and_subslice_from_end_err(s: &mut [i32]) { } fn subslices(s: &mut [i32]) { - if let [_, _, _, ref s1..] = *s { - if let [ref mut s2.., _, _, _] = *s { //~ERROR + if let [_, _, _, ref s1 @ ..] = *s { + if let [ref mut s2 @ .., _, _, _] = *s { //~ERROR nop_subslice(s1); nop_subslice(s2); } diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr index f716ee68b0002..2c019f4461182 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr @@ -89,8 +89,8 @@ error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as im | LL | if let [ref first, ref second, ..] = *s { | ---------- immutable borrow occurs here -LL | if let [_, ref mut tail..] = *s { - | ^^^^^^^^^^^^ mutable borrow occurs here +LL | if let [_, ref mut tail @ ..] = *s { + | ^^^^^^^^^^^^^^^^^ mutable borrow occurs here LL | nop(&[first, second]); | ------ immutable borrow later used here @@ -99,18 +99,18 @@ error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as im | LL | if let [.., ref second, ref first] = *s { | ---------- immutable borrow occurs here -LL | if let [ref mut tail.., _] = *s { - | ^^^^^^^^^^^^ mutable borrow occurs here +LL | if let [ref mut tail @ .., _] = *s { + | ^^^^^^^^^^^^^^^^^ mutable borrow occurs here LL | nop(&[first, second]); | ------ immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable --> $DIR/borrowck-slice-pattern-element-loan.rs:109:17 | -LL | if let [_, _, _, ref s1..] = *s { - | ------ immutable borrow occurs here -LL | if let [ref mut s2.., _, _, _] = *s { - | ^^^^^^^^^^ mutable borrow occurs here +LL | if let [_, _, _, ref s1 @ ..] = *s { + | ----------- immutable borrow occurs here +LL | if let [ref mut s2 @ .., _, _, _] = *s { + | ^^^^^^^^^^^^^^^ mutable borrow occurs here LL | nop_subslice(s1); | -- immutable borrow later used here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs index 100384d78c8ea..53a9bcef74a22 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs @@ -4,7 +4,7 @@ fn a<'a>() -> &'a [isize] { let vec = vec![1, 2, 3, 4]; let vec: &[isize] = &vec; let tail = match vec { - &[_, ref tail..] => tail, + &[_, ref tail @ ..] => tail, _ => panic!("a") }; tail //~ ERROR cannot return value referencing local variable `vec` @@ -14,7 +14,7 @@ fn b<'a>() -> &'a [isize] { let vec = vec![1, 2, 3, 4]; let vec: &[isize] = &vec; let init = match vec { - &[ref init.., _] => init, + &[ref init @ .., _] => init, _ => panic!("b") }; init //~ ERROR cannot return value referencing local variable `vec` @@ -24,7 +24,7 @@ fn c<'a>() -> &'a [isize] { let vec = vec![1, 2, 3, 4]; let vec: &[isize] = &vec; let slice = match vec { - &[_, ref slice.., _] => slice, + &[_, ref slice @ .., _] => slice, _ => panic!("c") }; slice //~ ERROR cannot return value referencing local variable `vec` diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs index 4d99a92b18ba8..dd9023f6d9f79 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs @@ -4,7 +4,7 @@ fn a() { let mut v = vec![1, 2, 3]; let vb: &mut [isize] = &mut v; match vb { - &mut [_a, ref tail..] => { + &mut [_a, ref tail @ ..] => { v.push(tail[0] + tail[1]); //~ ERROR cannot borrow } _ => {} diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs index efc52530716c8..420223009a45b 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs @@ -5,7 +5,7 @@ fn main() { let mut a = [1, 2, 3, 4]; let t = match a { - [1, 2, ref tail..] => tail, + [1, 2, ref tail @ ..] => tail, _ => unreachable!() }; println!("t[0]: {}", t[0]); diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr index b2f553ba49f70..9f8e6fe3b6898 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr @@ -1,8 +1,8 @@ error[E0506]: cannot assign to `a[_]` because it is borrowed --> $DIR/borrowck-vec-pattern-move-tail.rs:12:5 | -LL | [1, 2, ref tail..] => tail, - | -------- borrow of `a[_]` occurs here +LL | [1, 2, ref tail @ ..] => tail, + | ------------- borrow of `a[_]` occurs here ... LL | a[2] = 0; | ^^^^^^^^ assignment to borrowed `a[_]` occurs here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs index 6448149391def..a215305f684dd 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs @@ -19,7 +19,7 @@ fn b() { let mut vec = vec![box 1, box 2, box 3]; let vec: &mut [Box] = &mut vec; match vec { - &mut [ref _b..] => { + &mut [ref _b @ ..] => { //~^ borrow of `vec[_]` occurs here vec[0] = box 4; //~ ERROR cannot assign //~^ NOTE assignment to borrowed `vec[_]` occurs here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr index 072501f23ff84..f54a3a4072cd2 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr @@ -13,8 +13,8 @@ LL | _a.use_ref(); error[E0506]: cannot assign to `vec[_]` because it is borrowed --> $DIR/borrowck-vec-pattern-nesting.rs:24:13 | -LL | &mut [ref _b..] => { - | ------ borrow of `vec[_]` occurs here +LL | &mut [ref _b @ ..] => { + | ----------- borrow of `vec[_]` occurs here LL | LL | vec[0] = box 4; | ^^^^^^ assignment to borrowed `vec[_]` occurs here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs index e602e75886d95..c35be2f6be62c 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs @@ -4,7 +4,7 @@ fn a<'a>() -> &'a isize { let vec = vec![1, 2, 3, 4]; let vec: &[isize] = &vec; let tail = match vec { - &[_a, ref tail..] => &tail[0], + &[_a, ref tail @ ..] => &tail[0], _ => panic!("foo") }; tail //~ ERROR cannot return value referencing local variable `vec` diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index 9226145d9354d..f3f5c382275fe 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -217,7 +217,7 @@ async fn subslice_pattern_from_end_with_drop(a: Rc, arg: bool, arg2: if arg { let [.., _x, _] = arr; } else { - let [_, _y..] = arr; + let [_, _y @ ..] = arr; } a.alloc().await; } @@ -226,7 +226,7 @@ async fn subslice_pattern_reassign(a: Rc) { let mut ar = [a.alloc().await, a.alloc().await, a.alloc().await]; let [_, _, _x] = ar; ar = [a.alloc().await, a.alloc().await, a.alloc().await]; - let [_, _y..] = ar; + let [_, _y @ ..] = ar; a.alloc().await; } diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index eb1a3f3a9f9cb..8516bc3d96424 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -237,7 +237,7 @@ fn subslice_pattern_from_end(a: &Allocator, arg: bool) { if arg { let[.., _x, _] = a; } else { - let[_, _y..] = a; + let[_, _y @ ..] = a; } } @@ -251,7 +251,7 @@ fn subslice_pattern_from_end_with_drop(a: &Allocator, arg: bool, arg2: bool) { if arg { let[.., _x, _] = a; } else { - let[_, _y..] = a; + let[_, _y @ ..] = a; } } @@ -266,7 +266,7 @@ fn subslice_pattern_reassign(a: &Allocator) { let mut ar = [a.alloc(), a.alloc(), a.alloc()]; let[_, _, _x] = ar; ar = [a.alloc(), a.alloc(), a.alloc()]; - let[_, _y..] = ar; + let[_, _y @ ..] = ar; } fn panic_after_return(a: &Allocator) -> Ptr<'_> { diff --git a/src/test/ui/error-codes/E0528.rs b/src/test/ui/error-codes/E0528.rs index f2681fa043dab..17d03b14fc6e1 100644 --- a/src/test/ui/error-codes/E0528.rs +++ b/src/test/ui/error-codes/E0528.rs @@ -3,7 +3,7 @@ fn main() { let r = &[1, 2]; match r { - &[a, b, c, rest..] => { + &[a, b, c, rest @ ..] => { //~^ ERROR E0528 } } diff --git a/src/test/ui/error-codes/E0528.stderr b/src/test/ui/error-codes/E0528.stderr index a7205af50542a..0f566091145bf 100644 --- a/src/test/ui/error-codes/E0528.stderr +++ b/src/test/ui/error-codes/E0528.stderr @@ -1,8 +1,8 @@ error[E0528]: pattern requires at least 3 elements but array has 2 --> $DIR/E0528.rs:6:10 | -LL | &[a, b, c, rest..] => { - | ^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements +LL | &[a, b, c, rest @ ..] => { + | ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements error: aborting due to previous error diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs index d95c4b0999405..d97b693f52098 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs +++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs @@ -2,7 +2,9 @@ fn main() { match [5..4, 99..105, 43..44] { - [_, 99.., _] => {}, //~ ERROR unexpected token: `,` + [_, 99.., _] => {}, + //~^ ERROR `X..` range patterns are not supported + //~| ERROR mismatched types _ => {}, } } diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr index 359725a41c105..4ecd8515ee164 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr +++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr @@ -1,8 +1,20 @@ -error: unexpected token: `,` - --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:17 +error: `X..` range patterns are not supported + --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13 | LL | [_, 99.., _] => {}, - | ^ + | ^^^^ help: try using the maximum value for the type: `99..MAX` -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13 + | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this match expression has type `std::ops::Range<{integer}>` +LL | [_, 99.., _] => {}, + | ^^^^ expected struct `std::ops::Range`, found integer + | + = note: expected type `std::ops::Range<{integer}>` + found type `{integer}` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs index 95677e34dd798..09f459c9862ee 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs +++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs @@ -2,7 +2,10 @@ fn main() { match [5..4, 99..105, 43..44] { - [_, 99..] => {}, //~ ERROR unexpected token: `]` + [_, 99..] => {}, + //~^ ERROR `X..` range patterns are not supported + //~| ERROR pattern requires 2 elements but array has 3 + //~| ERROR mismatched types _ => {}, } } diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr index 8f849d7b3f87c..922d26923158b 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr +++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr @@ -1,8 +1,27 @@ -error: unexpected token: `]` - --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:17 +error: `X..` range patterns are not supported + --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13 | LL | [_, 99..] => {}, - | ^ + | ^^^^ help: try using the maximum value for the type: `99..MAX` -error: aborting due to previous error +error[E0527]: pattern requires 2 elements but array has 3 + --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:9 + | +LL | [_, 99..] => {}, + | ^^^^^^^^^ expected 3 elements + +error[E0308]: mismatched types + --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13 + | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this match expression has type `std::ops::Range<{integer}>` +LL | [_, 99..] => {}, + | ^^^^ expected struct `std::ops::Range`, found integer + | + = note: expected type `std::ops::Range<{integer}>` + found type `{integer}` + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0308, E0527. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs index 3bf5da710ef9f..95e58b1d48c88 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs +++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs @@ -2,7 +2,10 @@ fn main() { match [5..4, 99..105, 43..44] { - [..9, 99..100, _] => {}, //~ ERROR expected one of `,` or `]`, found `9` + [..9, 99..100, _] => {}, + //~^ ERROR `..X` range patterns are not supported + //~| ERROR mismatched types + //~| ERROR mismatched types _ => {}, } } diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr index a09ba3562e098..8907b875f8e11 100644 --- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr +++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr @@ -1,8 +1,31 @@ -error: expected one of `,` or `]`, found `9` - --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12 +error: `..X` range patterns are not supported + --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10 | LL | [..9, 99..100, _] => {}, - | ^ expected one of `,` or `]` here + | ^^^ help: try using the minimum value for the type: `MIN..9` -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10 + | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this match expression has type `std::ops::Range<{integer}>` +LL | [..9, 99..100, _] => {}, + | ^^^ expected struct `std::ops::Range`, found integer + | + = note: expected type `std::ops::Range<{integer}>` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15 + | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this match expression has type `std::ops::Range<{integer}>` +LL | [..9, 99..100, _] => {}, + | ^^^^^^^ expected struct `std::ops::Range`, found integer + | + = note: expected type `std::ops::Range<{integer}>` + found type `{integer}` + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs b/src/test/ui/feature-gates/feature-gate-slice-patterns.rs index 0165321debe6b..f2a1b135b69cb 100644 --- a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs +++ b/src/test/ui/feature-gates/feature-gate-slice-patterns.rs @@ -3,15 +3,15 @@ fn main() { let x = [1, 2, 3, 4, 5]; match x { - [1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized - [1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized - [.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + [1, 2, ..] => {} //~ ERROR subslice patterns are unstable + [1, .., 5] => {} //~ ERROR subslice patterns are unstable + [.., 4, 5] => {} //~ ERROR subslice patterns are unstable } let x = [ 1, 2, 3, 4, 5 ]; match x { - [ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized - [ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized - [ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized + [ xs @ .., 4, 5 ] => {} //~ ERROR subslice patterns are unstable + [ 1, xs @ .., 5 ] => {} //~ ERROR subslice patterns are unstable + [ 1, 2, xs @ .. ] => {} //~ ERROR subslice patterns are unstable } } diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr index e88fddaa81fbe..d4946a42b8f3d 100644 --- a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr +++ b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr @@ -1,4 +1,4 @@ -error[E0658]: syntax for subslices in slice patterns is not yet stabilized +error[E0658]: subslice patterns are unstable --> $DIR/feature-gate-slice-patterns.rs:6:16 | LL | [1, 2, ..] => {} @@ -7,7 +7,7 @@ LL | [1, 2, ..] => {} = note: for more information, see https://github.com/rust-lang/rust/issues/62254 = help: add `#![feature(slice_patterns)]` to the crate attributes to enable -error[E0658]: syntax for subslices in slice patterns is not yet stabilized +error[E0658]: subslice patterns are unstable --> $DIR/feature-gate-slice-patterns.rs:7:13 | LL | [1, .., 5] => {} @@ -16,7 +16,7 @@ LL | [1, .., 5] => {} = note: for more information, see https://github.com/rust-lang/rust/issues/62254 = help: add `#![feature(slice_patterns)]` to the crate attributes to enable -error[E0658]: syntax for subslices in slice patterns is not yet stabilized +error[E0658]: subslice patterns are unstable --> $DIR/feature-gate-slice-patterns.rs:8:10 | LL | [.., 4, 5] => {} @@ -25,29 +25,29 @@ LL | [.., 4, 5] => {} = note: for more information, see https://github.com/rust-lang/rust/issues/62254 = help: add `#![feature(slice_patterns)]` to the crate attributes to enable -error[E0658]: syntax for subslices in slice patterns is not yet stabilized +error[E0658]: subslice patterns are unstable --> $DIR/feature-gate-slice-patterns.rs:13:11 | -LL | [ xs.., 4, 5 ] => {} - | ^^ +LL | [ xs @ .., 4, 5 ] => {} + | ^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/62254 = help: add `#![feature(slice_patterns)]` to the crate attributes to enable -error[E0658]: syntax for subslices in slice patterns is not yet stabilized +error[E0658]: subslice patterns are unstable --> $DIR/feature-gate-slice-patterns.rs:14:14 | -LL | [ 1, xs.., 5 ] => {} - | ^^ +LL | [ 1, xs @ .., 5 ] => {} + | ^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/62254 = help: add `#![feature(slice_patterns)]` to the crate attributes to enable -error[E0658]: syntax for subslices in slice patterns is not yet stabilized +error[E0658]: subslice patterns are unstable --> $DIR/feature-gate-slice-patterns.rs:15:17 | -LL | [ 1, 2, xs.. ] => {} - | ^^ +LL | [ 1, 2, xs @ .. ] => {} + | ^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/62254 = help: add `#![feature(slice_patterns)]` to the crate attributes to enable diff --git a/src/test/ui/issues/issue-12369.rs b/src/test/ui/issues/issue-12369.rs index 8df8efefd05ed..0866131807463 100644 --- a/src/test/ui/issues/issue-12369.rs +++ b/src/test/ui/issues/issue-12369.rs @@ -6,7 +6,7 @@ fn main() { let v: isize = match &*sl { &[] => 0, &[a,b,c] => 3, - &[a, ref rest..] => a, - &[10,a, ref rest..] => 10 //~ ERROR: unreachable pattern + &[a, ref rest @ ..] => a, + &[10,a, ref rest @ ..] => 10 //~ ERROR: unreachable pattern }; } diff --git a/src/test/ui/issues/issue-12369.stderr b/src/test/ui/issues/issue-12369.stderr index fec9078dc4090..f27425e28c61d 100644 --- a/src/test/ui/issues/issue-12369.stderr +++ b/src/test/ui/issues/issue-12369.stderr @@ -1,8 +1,8 @@ error: unreachable pattern --> $DIR/issue-12369.rs:10:9 | -LL | &[10,a, ref rest..] => 10 - | ^^^^^^^^^^^^^^^^^^^ +LL | &[10,a, ref rest @ ..] => 10 + | ^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here --> $DIR/issue-12369.rs:2:9 diff --git a/src/test/ui/issues/issue-15080.rs b/src/test/ui/issues/issue-15080.rs index 4558118a8091c..b11b1cda38ae1 100644 --- a/src/test/ui/issues/issue-15080.rs +++ b/src/test/ui/issues/issue-15080.rs @@ -7,11 +7,11 @@ fn main() { let mut result = vec![]; loop { x = match *x { - [1, n, 3, ref rest..] => { + [1, n, 3, ref rest @ ..] => { result.push(n); rest } - [n, ref rest..] => { + [n, ref rest @ ..] => { result.push(n); rest } diff --git a/src/test/ui/issues/issue-15104.rs b/src/test/ui/issues/issue-15104.rs index 3a03a52c32485..ee977541137db 100644 --- a/src/test/ui/issues/issue-15104.rs +++ b/src/test/ui/issues/issue-15104.rs @@ -9,6 +9,6 @@ fn count_members(v: &[usize]) -> usize { match *v { [] => 0, [_] => 1, - [_, ref xs..] => 1 + count_members(xs) + [_, ref xs @ ..] => 1 + count_members(xs) } } diff --git a/src/test/ui/issues/issue-17877.rs b/src/test/ui/issues/issue-17877.rs index af22b1ad8f0bc..fefa3f2f87304 100644 --- a/src/test/ui/issues/issue-17877.rs +++ b/src/test/ui/issues/issue-17877.rs @@ -7,8 +7,8 @@ fn main() { }, 42_usize); assert_eq!(match [0u8; 1024] { - [1, _..] => 0_usize, - [0, _..] => 1_usize, + [1, ..] => 0_usize, + [0, ..] => 1_usize, _ => 2_usize }, 1_usize); } diff --git a/src/test/ui/issues/issue-26158.rs b/src/test/ui/issues/issue-26158.rs deleted file mode 100644 index 11f47b6d02a73..0000000000000 --- a/src/test/ui/issues/issue-26158.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(slice_patterns)] - -fn main() { - let x: &[u32] = &[]; - let &[[ref _a, ref _b..]..] = x; //~ ERROR refutable pattern -} diff --git a/src/test/ui/issues/issue-26158.stderr b/src/test/ui/issues/issue-26158.stderr deleted file mode 100644 index 3a4dd79e81053..0000000000000 --- a/src/test/ui/issues/issue-26158.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0005]: refutable pattern in local binding: `&[]` not covered - --> $DIR/issue-26158.rs:5:9 - | -LL | let &[[ref _a, ref _b..]..] = x; - | ^^^^^^^^^^^^^^^^^^^^^^^ pattern `&[]` not covered - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0005`. diff --git a/src/test/ui/issues/issue-37598.rs b/src/test/ui/issues/issue-37598.rs index 1bec3d340d665..31b3aba6bc204 100644 --- a/src/test/ui/issues/issue-37598.rs +++ b/src/test/ui/issues/issue-37598.rs @@ -1,11 +1,10 @@ -// build-pass (FIXME(62277): could be check-pass?) -#![allow(dead_code)] +// check-pass #![feature(slice_patterns)] fn check(list: &[u8]) { match list { &[] => {}, - &[_u1, _u2, ref _next..] => {}, + &[_u1, _u2, ref _next @ ..] => {}, &[_u1] => {}, } } diff --git a/src/test/ui/issues/issue-7784.rs b/src/test/ui/issues/issue-7784.rs index b75e547079ef5..5b70bd6e5ff54 100644 --- a/src/test/ui/issues/issue-7784.rs +++ b/src/test/ui/issues/issue-7784.rs @@ -24,7 +24,7 @@ fn main() { assert_eq!(d, "baz"); let out = bar("baz", "foo"); - let [a, xs.., d] = out; + let [a, xs @ .., d] = out; assert_eq!(a, "baz"); assert_eq!(xs, ["foo", "foo"]); assert_eq!(d, "baz"); diff --git a/src/test/ui/match/match-vec-mismatch.rs b/src/test/ui/match/match-vec-mismatch.rs index 5e61c1b22a085..a0ef92743ac5a 100644 --- a/src/test/ui/match/match-vec-mismatch.rs +++ b/src/test/ui/match/match-vec-mismatch.rs @@ -19,10 +19,10 @@ fn main() { match [0, 1, 2] { [0] => {}, //~ ERROR pattern requires - [0, 1, x..] => { + [0, 1, x @ ..] => { let a: [_; 1] = x; } - [0, 1, 2, 3, x..] => {} //~ ERROR pattern requires + [0, 1, 2, 3, x @ ..] => {} //~ ERROR pattern requires }; match does_not_exist { //~ ERROR cannot find value `does_not_exist` in this scope diff --git a/src/test/ui/match/match-vec-mismatch.stderr b/src/test/ui/match/match-vec-mismatch.stderr index 47f9d48e26290..2f1bbb7621659 100644 --- a/src/test/ui/match/match-vec-mismatch.stderr +++ b/src/test/ui/match/match-vec-mismatch.stderr @@ -19,8 +19,8 @@ LL | [0] => {}, error[E0528]: pattern requires at least 4 elements but array has 3 --> $DIR/match-vec-mismatch.rs:25:9 | -LL | [0, 1, 2, 3, x..] => {} - | ^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements +LL | [0, 1, 2, 3, x @ ..] => {} + | ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements error[E0282]: type annotations needed --> $DIR/match-vec-mismatch.rs:36:9 diff --git a/src/test/ui/match/match-vec-unreachable.rs b/src/test/ui/match/match-vec-unreachable.rs index 9e167f37ba9d9..78810525bad0f 100644 --- a/src/test/ui/match/match-vec-unreachable.rs +++ b/src/test/ui/match/match-vec-unreachable.rs @@ -23,7 +23,7 @@ fn main() { let x: Vec = vec!['a', 'b', 'c']; let x: &[char] = &x; match *x { - ['a', 'b', 'c', ref _tail..] => {} + ['a', 'b', 'c', ref _tail @ ..] => {} ['a', 'b', 'c'] => {} //~ ERROR unreachable pattern _ => {} } diff --git a/src/test/ui/non-exhaustive/non-exhaustive-match.rs b/src/test/ui/non-exhaustive/non-exhaustive-match.rs index e888bcf516891..8cc5f4042cccb 100644 --- a/src/test/ui/non-exhaustive/non-exhaustive-match.rs +++ b/src/test/ui/non-exhaustive/non-exhaustive-match.rs @@ -32,14 +32,14 @@ fn main() { let vec = vec![Some(42), None, Some(21)]; let vec: &[Option] = &vec; match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered - [Some(..), None, ref tail..] => {} - [Some(..), Some(..), ref tail..] => {} + [Some(..), None, ref tail @ ..] => {} + [Some(..), Some(..), ref tail @ ..] => {} [None] => {} } let vec = vec![1]; let vec: &[isize] = &vec; match *vec { - [_, ref tail..] => (), + [_, ref tail @ ..] => (), [] => () } let vec = vec![0.5f32]; @@ -53,10 +53,10 @@ fn main() { let vec = vec![Some(42), None, Some(21)]; let vec: &[Option] = &vec; match *vec { - [Some(..), None, ref tail..] => {} - [Some(..), Some(..), ref tail..] => {} - [None, None, ref tail..] => {} - [None, Some(..), ref tail..] => {} + [Some(..), None, ref tail @ ..] => {} + [Some(..), Some(..), ref tail @ ..] => {} + [None, None, ref tail @ ..] => {} + [None, Some(..), ref tail @ ..] => {} [Some(_)] => {} [None] => {} [] => {} diff --git a/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs b/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs index 9fcd4bdad7264..4ca1cbcebccf5 100644 --- a/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs +++ b/src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs @@ -77,7 +77,7 @@ fn vectors_with_nested_enums() { [Enum::Second(true), Enum::First] => (), [Enum::Second(true), Enum::Second(true)] => (), [Enum::Second(false), _] => (), - [_, _, ref tail.., _] => () + [_, _, ref tail @ .., _] => () } } diff --git a/src/test/ui/parser/match-vec-invalid.rs b/src/test/ui/parser/match-vec-invalid.rs index e5e85ba8ca602..00f4374b256d2 100644 --- a/src/test/ui/parser/match-vec-invalid.rs +++ b/src/test/ui/parser/match-vec-invalid.rs @@ -1,7 +1,13 @@ fn main() { - let a = Vec::new(); + let a: &[u8] = &[]; match a { - [1, tail.., tail..] => {}, //~ ERROR: expected one of `,` or `@`, found `..` + [1, tail @ .., tail @ ..] => {}, + //~^ ERROR identifier `tail` is bound more than once in the same pattern + //~| ERROR subslice patterns are unstable + //~| ERROR subslice patterns are unstable + //~| ERROR `..` can only be used once per slice pattern _ => () } } + +const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/match-vec-invalid.stderr b/src/test/ui/parser/match-vec-invalid.stderr index fee8d248dcf07..0956ac21b7f1e 100644 --- a/src/test/ui/parser/match-vec-invalid.stderr +++ b/src/test/ui/parser/match-vec-invalid.stderr @@ -1,8 +1,45 @@ -error: expected one of `,` or `@`, found `..` - --> $DIR/match-vec-invalid.rs:4:25 +error[E0416]: identifier `tail` is bound more than once in the same pattern + --> $DIR/match-vec-invalid.rs:4:24 | -LL | [1, tail.., tail..] => {}, - | ^^ expected one of `,` or `@` here +LL | [1, tail @ .., tail @ ..] => {}, + | ^^^^ used in a pattern more than once -error: aborting due to previous error +error[E0658]: subslice patterns are unstable + --> $DIR/match-vec-invalid.rs:4:13 + | +LL | [1, tail @ .., tail @ ..] => {}, + | ^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/62254 + = help: add `#![feature(slice_patterns)]` to the crate attributes to enable + +error[E0658]: subslice patterns are unstable + --> $DIR/match-vec-invalid.rs:4:24 + | +LL | [1, tail @ .., tail @ ..] => {}, + | ^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/62254 + = help: add `#![feature(slice_patterns)]` to the crate attributes to enable + +error: `..` can only be used once per slice pattern + --> $DIR/match-vec-invalid.rs:4:31 + | +LL | [1, tail @ .., tail @ ..] => {}, + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error[E0308]: mismatched types + --> $DIR/match-vec-invalid.rs:13:30 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to 5 previous errors +Some errors have detailed explanations: E0308, E0416, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-lt-bracket-6.rs b/src/test/ui/parser/pat-lt-bracket-6.rs index 9bad0cb25c1e4..7b9721830993e 100644 --- a/src/test/ui/parser/pat-lt-bracket-6.rs +++ b/src/test/ui/parser/pat-lt-bracket-6.rs @@ -1,3 +1,9 @@ fn main() { + struct Test(&'static u8, [u8; 0]); + let x = Test(&0, []); + let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[` + //~^ ERROR subslice patterns are unstable } + +const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/pat-lt-bracket-6.stderr b/src/test/ui/parser/pat-lt-bracket-6.stderr index 2ee4bdb20fe88..201465b2c850c 100644 --- a/src/test/ui/parser/pat-lt-bracket-6.stderr +++ b/src/test/ui/parser/pat-lt-bracket-6.stderr @@ -1,8 +1,28 @@ error: expected one of `)`, `,`, or `@`, found `[` - --> $DIR/pat-lt-bracket-6.rs:2:19 + --> $DIR/pat-lt-bracket-6.rs:5:19 | LL | let Test(&desc[..]) = x; | ^ expected one of `)`, `,`, or `@` here -error: aborting due to previous error +error[E0658]: subslice patterns are unstable + --> $DIR/pat-lt-bracket-6.rs:5:20 + | +LL | let Test(&desc[..]) = x; + | ^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/62254 + = help: add `#![feature(slice_patterns)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/pat-lt-bracket-6.rs:9:30 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-lt-bracket-7.rs b/src/test/ui/parser/pat-lt-bracket-7.rs index 36c0d7733733a..020fdb845e8b5 100644 --- a/src/test/ui/parser/pat-lt-bracket-7.rs +++ b/src/test/ui/parser/pat-lt-bracket-7.rs @@ -1,3 +1,8 @@ fn main() { - for thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[` + struct Thing(u8, [u8; 0]); + let foo = core::iter::empty(); + + for Thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[` } + +const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/pat-lt-bracket-7.stderr b/src/test/ui/parser/pat-lt-bracket-7.stderr index 5552ea46d9b9d..17557efa49e80 100644 --- a/src/test/ui/parser/pat-lt-bracket-7.stderr +++ b/src/test/ui/parser/pat-lt-bracket-7.stderr @@ -1,8 +1,18 @@ error: expected one of `)`, `,`, or `@`, found `[` - --> $DIR/pat-lt-bracket-7.rs:2:16 + --> $DIR/pat-lt-bracket-7.rs:5:16 | -LL | for thing(x[]) in foo {} +LL | for Thing(x[]) in foo {} | ^ expected one of `)`, `,`, or `@` here -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/pat-lt-bracket-7.rs:8:30 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-tuple-2.rs b/src/test/ui/parser/pat-tuple-2.rs index fd25499381a28..a8f3debd3d634 100644 --- a/src/test/ui/parser/pat-tuple-2.rs +++ b/src/test/ui/parser/pat-tuple-2.rs @@ -1,6 +1,7 @@ +// check-pass + fn main() { match (0, 1, 2) { (pat, ..,) => {} - //~^ ERROR trailing comma is not permitted after `..` } } diff --git a/src/test/ui/parser/pat-tuple-2.stderr b/src/test/ui/parser/pat-tuple-2.stderr deleted file mode 100644 index c3a5c39a8e32a..0000000000000 --- a/src/test/ui/parser/pat-tuple-2.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: trailing comma is not permitted after `..` - --> $DIR/pat-tuple-2.rs:3:17 - | -LL | (pat, ..,) => {} - | ^ trailing comma is not permitted after `..` - -error: aborting due to previous error - diff --git a/src/test/ui/parser/pat-tuple-3.rs b/src/test/ui/parser/pat-tuple-3.rs index e1e975d3c3ea0..1486ab231aab4 100644 --- a/src/test/ui/parser/pat-tuple-3.rs +++ b/src/test/ui/parser/pat-tuple-3.rs @@ -1,6 +1,6 @@ fn main() { match (0, 1, 2) { (.., pat, ..) => {} - //~^ ERROR `..` can only be used once per tuple or tuple struct pattern + //~^ ERROR `..` can only be used once per tuple pattern } } diff --git a/src/test/ui/parser/pat-tuple-3.stderr b/src/test/ui/parser/pat-tuple-3.stderr index c9f14bb90429b..9ac0611c5c933 100644 --- a/src/test/ui/parser/pat-tuple-3.stderr +++ b/src/test/ui/parser/pat-tuple-3.stderr @@ -1,10 +1,10 @@ -error: `..` can only be used once per tuple or tuple struct pattern +error: `..` can only be used once per tuple pattern --> $DIR/pat-tuple-3.rs:3:19 | LL | (.., pat, ..) => {} - | -- ^^ can only be used once per pattern + | -- ^^ can only be used once per tuple pattern | | - | previously present here + | previously used here error: aborting due to previous error diff --git a/src/test/ui/parser/pat-tuple-4.rs b/src/test/ui/parser/pat-tuple-4.rs index 76f60d94bc86e..2f03160430a22 100644 --- a/src/test/ui/parser/pat-tuple-4.rs +++ b/src/test/ui/parser/pat-tuple-4.rs @@ -1,5 +1,11 @@ fn main() { + const PAT: u8 = 0; + match 0 { - (.. pat) => {} //~ ERROR expected one of `)` or `,`, found `pat` + (.. PAT) => {} + //~^ ERROR `..X` range patterns are not supported + //~| ERROR exclusive range pattern syntax is experimental } } + +const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/pat-tuple-4.stderr b/src/test/ui/parser/pat-tuple-4.stderr index 26b92fae31391..af3ecce184649 100644 --- a/src/test/ui/parser/pat-tuple-4.stderr +++ b/src/test/ui/parser/pat-tuple-4.stderr @@ -1,8 +1,28 @@ -error: expected one of `)` or `,`, found `pat` - --> $DIR/pat-tuple-4.rs:3:13 +error: `..X` range patterns are not supported + --> $DIR/pat-tuple-4.rs:5:10 | -LL | (.. pat) => {} - | ^^^ expected one of `)` or `,` here +LL | (.. PAT) => {} + | ^^^^^^ help: try using the minimum value for the type: `MIN..PAT` -error: aborting due to previous error +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/pat-tuple-4.rs:5:10 + | +LL | (.. PAT) => {} + | ^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/37854 + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/pat-tuple-4.rs:11:30 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-tuple-5.rs b/src/test/ui/parser/pat-tuple-5.rs index d4f05a5eb523e..5334ef93bb3bd 100644 --- a/src/test/ui/parser/pat-tuple-5.rs +++ b/src/test/ui/parser/pat-tuple-5.rs @@ -1,5 +1,10 @@ fn main() { + const PAT: u8 = 0; + match (0, 1) { - (pat ..) => {} //~ ERROR unexpected token: `)` + (PAT ..) => {} + //~^ ERROR `X..` range patterns are not supported + //~| ERROR exclusive range pattern syntax is experimental + //~| ERROR mismatched types } } diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr index f9832214c6800..09ebdc29a2161 100644 --- a/src/test/ui/parser/pat-tuple-5.stderr +++ b/src/test/ui/parser/pat-tuple-5.stderr @@ -1,8 +1,30 @@ -error: unexpected token: `)` - --> $DIR/pat-tuple-5.rs:3:16 +error: `X..` range patterns are not supported + --> $DIR/pat-tuple-5.rs:5:10 | -LL | (pat ..) => {} - | ^ +LL | (PAT ..) => {} + | ^^^^^^ help: try using the maximum value for the type: `PAT..MAX` -error: aborting due to previous error +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/pat-tuple-5.rs:5:10 + | +LL | (PAT ..) => {} + | ^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/37854 + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/pat-tuple-5.rs:5:10 + | +LL | match (0, 1) { + | ------ this match expression has type `({integer}, {integer})` +LL | (PAT ..) => {} + | ^^^^^^ expected tuple, found u8 + | + = note: expected type `({integer}, {integer})` + found type `u8` + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs new file mode 100644 index 0000000000000..c66652ff4fa01 --- /dev/null +++ b/src/test/ui/parser/recover-range-pats.rs @@ -0,0 +1,123 @@ +// Here we test all kinds of range patterns in terms of parsing / recovery. +// We want to ensure that: +// 1. Things parse as they should. +// 2. Or at least we have parser recovery if they don't. + +#![feature(exclusive_range_pattern)] +#![deny(ellipsis_inclusive_range_patterns)] + +fn main() {} + +const X: u8 = 0; +const Y: u8 = 3; + +fn exclusive_from_to() { + if let 0..3 = 0 {} // OK. + if let 0..Y = 0 {} // OK. + if let X..3 = 0 {} // OK. + if let X..Y = 0 {} // OK. + if let true..Y = 0 {} //~ ERROR only char and numeric types + if let X..true = 0 {} //~ ERROR only char and numeric types + if let .0..Y = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part + if let X.. .0 = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part +} + +fn inclusive_from_to() { + if let 0..=3 = 0 {} // OK. + if let 0..=Y = 0 {} // OK. + if let X..=3 = 0 {} // OK. + if let X..=Y = 0 {} // OK. + if let true..=Y = 0 {} //~ ERROR only char and numeric types + if let X..=true = 0 {} //~ ERROR only char and numeric types + if let .0..=Y = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part + if let X..=.0 = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part +} + +fn inclusive2_from_to() { + if let 0...3 = 0 {} //~ ERROR `...` range patterns are deprecated + if let 0...Y = 0 {} //~ ERROR `...` range patterns are deprecated + if let X...3 = 0 {} //~ ERROR `...` range patterns are deprecated + if let X...Y = 0 {} //~ ERROR `...` range patterns are deprecated + if let true...Y = 0 {} //~ ERROR only char and numeric types + //~^ ERROR `...` range patterns are deprecated + if let X...true = 0 {} //~ ERROR only char and numeric types + //~^ ERROR `...` range patterns are deprecated + if let .0...Y = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part + //~| ERROR `...` range patterns are deprecated + if let X... .0 = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part + //~| ERROR `...` range patterns are deprecated +} + +fn exclusive_from() { + if let 0.. = 0 {} //~ ERROR `X..` range patterns are not supported + if let X.. = 0 {} //~ ERROR `X..` range patterns are not supported + if let true.. = 0 {} //~ ERROR `X..` range patterns are not supported + //~^ ERROR only char and numeric types + if let .0.. = 0 {} //~ ERROR `X..` range patterns are not supported + //~^ ERROR float literals must have an integer part + //~| ERROR mismatched types +} + +fn inclusive_from() { + if let 0..= = 0 {} //~ ERROR `X..=` range patterns are not supported + if let X..= = 0 {} //~ ERROR `X..=` range patterns are not supported + if let true..= = 0 {} //~ ERROR `X..=` range patterns are not supported + //~| ERROR only char and numeric types + if let .0..= = 0 {} //~ ERROR `X..=` range patterns are not supported + //~^ ERROR float literals must have an integer part + //~| ERROR mismatched types +} + +fn inclusive2_from() { + if let 0... = 0 {} //~ ERROR `X...` range patterns are not supported + //~^ ERROR `...` range patterns are deprecated + if let X... = 0 {} //~ ERROR `X...` range patterns are not supported + //~^ ERROR `...` range patterns are deprecated + if let true... = 0 {} //~ ERROR `X...` range patterns are not supported + //~^ ERROR `...` range patterns are deprecated + //~| ERROR only char and numeric types + if let .0... = 0 {} //~ ERROR `X...` range patterns are not supported + //~^ ERROR float literals must have an integer part + //~| ERROR `...` range patterns are deprecated + //~| ERROR mismatched types +} + +fn exclusive_to() { + if let ..0 = 0 {} //~ ERROR `..X` range patterns are not supported + if let ..Y = 0 {} //~ ERROR `..X` range patterns are not supported + if let ..true = 0 {} //~ ERROR `..X` range patterns are not supported + //~| ERROR only char and numeric types + if let .. .0 = 0 {} //~ ERROR `..X` range patterns are not supported + //~^ ERROR float literals must have an integer part + //~| ERROR mismatched types +} + +fn inclusive_to() { + if let ..=3 = 0 {} //~ ERROR `..=X` range patterns are not supported + if let ..=Y = 0 {} //~ ERROR `..=X` range patterns are not supported + if let ..=true = 0 {} //~ ERROR `..=X` range patterns are not supported + //~| ERROR only char and numeric types + if let ..=.0 = 0 {} //~ ERROR `..=X` range patterns are not supported + //~^ ERROR float literals must have an integer part + //~| ERROR mismatched types +} + +fn inclusive2_to() { + if let ...3 = 0 {} //~ ERROR `...X` range patterns are not supported + //~^ ERROR `...` range patterns are deprecated + if let ...Y = 0 {} //~ ERROR `...X` range patterns are not supported + //~^ ERROR `...` range patterns are deprecated + if let ...true = 0 {} //~ ERROR `...X` range patterns are not supported + //~^ ERROR `...` range patterns are deprecated + //~| ERROR only char and numeric types + if let ....3 = 0 {} //~ ERROR `...X` range patterns are not supported + //~^ ERROR float literals must have an integer part + //~| ERROR `...` range patterns are deprecated + //~| ERROR mismatched types +} diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr new file mode 100644 index 0000000000000..c50d5e6eb6153 --- /dev/null +++ b/src/test/ui/parser/recover-range-pats.stderr @@ -0,0 +1,538 @@ +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:21:12 + | +LL | if let .0..Y = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:23:16 + | +LL | if let X.. .0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:34:12 + | +LL | if let .0..=Y = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:36:16 + | +LL | if let X..=.0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:49:12 + | +LL | if let .0...Y = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:52:17 + | +LL | if let X... .0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: `X..` range patterns are not supported + --> $DIR/recover-range-pats.rs:58:12 + | +LL | if let 0.. = 0 {} + | ^^^ help: try using the maximum value for the type: `0..MAX` + +error: `X..` range patterns are not supported + --> $DIR/recover-range-pats.rs:59:12 + | +LL | if let X.. = 0 {} + | ^^^ help: try using the maximum value for the type: `X..MAX` + +error: `X..` range patterns are not supported + --> $DIR/recover-range-pats.rs:60:12 + | +LL | if let true.. = 0 {} + | ^^^^^^ help: try using the maximum value for the type: `true..MAX` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:62:12 + | +LL | if let .0.. = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: `X..` range patterns are not supported + --> $DIR/recover-range-pats.rs:62:12 + | +LL | if let .0.. = 0 {} + | ^^^^ help: try using the maximum value for the type: `0.0..MAX` + +error: `X..=` range patterns are not supported + --> $DIR/recover-range-pats.rs:68:12 + | +LL | if let 0..= = 0 {} + | ^^^^ help: try using the maximum value for the type: `0..=MAX` + +error: `X..=` range patterns are not supported + --> $DIR/recover-range-pats.rs:69:12 + | +LL | if let X..= = 0 {} + | ^^^^ help: try using the maximum value for the type: `X..=MAX` + +error: `X..=` range patterns are not supported + --> $DIR/recover-range-pats.rs:70:12 + | +LL | if let true..= = 0 {} + | ^^^^^^^ help: try using the maximum value for the type: `true..=MAX` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:72:12 + | +LL | if let .0..= = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: `X..=` range patterns are not supported + --> $DIR/recover-range-pats.rs:72:12 + | +LL | if let .0..= = 0 {} + | ^^^^^ help: try using the maximum value for the type: `0.0..=MAX` + +error: `X...` range patterns are not supported + --> $DIR/recover-range-pats.rs:78:12 + | +LL | if let 0... = 0 {} + | ^^^^ help: try using the maximum value for the type: `0...MAX` + +error: `X...` range patterns are not supported + --> $DIR/recover-range-pats.rs:80:12 + | +LL | if let X... = 0 {} + | ^^^^ help: try using the maximum value for the type: `X...MAX` + +error: `X...` range patterns are not supported + --> $DIR/recover-range-pats.rs:82:12 + | +LL | if let true... = 0 {} + | ^^^^^^^ help: try using the maximum value for the type: `true...MAX` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:85:12 + | +LL | if let .0... = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: `X...` range patterns are not supported + --> $DIR/recover-range-pats.rs:85:12 + | +LL | if let .0... = 0 {} + | ^^^^^ help: try using the maximum value for the type: `0.0...MAX` + +error: `..X` range patterns are not supported + --> $DIR/recover-range-pats.rs:92:12 + | +LL | if let ..0 = 0 {} + | ^^^ help: try using the minimum value for the type: `MIN..0` + +error: `..X` range patterns are not supported + --> $DIR/recover-range-pats.rs:93:12 + | +LL | if let ..Y = 0 {} + | ^^^ help: try using the minimum value for the type: `MIN..Y` + +error: `..X` range patterns are not supported + --> $DIR/recover-range-pats.rs:94:12 + | +LL | if let ..true = 0 {} + | ^^^^^^ help: try using the minimum value for the type: `MIN..true` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:96:15 + | +LL | if let .. .0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: `..X` range patterns are not supported + --> $DIR/recover-range-pats.rs:96:12 + | +LL | if let .. .0 = 0 {} + | ^^^^^ help: try using the minimum value for the type: `MIN..0.0` + +error: `..=X` range patterns are not supported + --> $DIR/recover-range-pats.rs:102:12 + | +LL | if let ..=3 = 0 {} + | ^^^^ help: try using the minimum value for the type: `MIN..=3` + +error: `..=X` range patterns are not supported + --> $DIR/recover-range-pats.rs:103:12 + | +LL | if let ..=Y = 0 {} + | ^^^^ help: try using the minimum value for the type: `MIN..=Y` + +error: `..=X` range patterns are not supported + --> $DIR/recover-range-pats.rs:104:12 + | +LL | if let ..=true = 0 {} + | ^^^^^^^ help: try using the minimum value for the type: `MIN..=true` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:106:15 + | +LL | if let ..=.0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: `..=X` range patterns are not supported + --> $DIR/recover-range-pats.rs:106:12 + | +LL | if let ..=.0 = 0 {} + | ^^^^^ help: try using the minimum value for the type: `MIN..=0.0` + +error: `...X` range patterns are not supported + --> $DIR/recover-range-pats.rs:112:12 + | +LL | if let ...3 = 0 {} + | ^^^^ help: try using the minimum value for the type: `MIN...3` + +error: `...X` range patterns are not supported + --> $DIR/recover-range-pats.rs:114:12 + | +LL | if let ...Y = 0 {} + | ^^^^ help: try using the minimum value for the type: `MIN...Y` + +error: `...X` range patterns are not supported + --> $DIR/recover-range-pats.rs:116:12 + | +LL | if let ...true = 0 {} + | ^^^^^^^ help: try using the minimum value for the type: `MIN...true` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:119:15 + | +LL | if let ....3 = 0 {} + | ^^ help: must have an integer part: `0.3` + +error: `...X` range patterns are not supported + --> $DIR/recover-range-pats.rs:119:12 + | +LL | if let ....3 = 0 {} + | ^^^^^ help: try using the minimum value for the type: `MIN...0.3` + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:41:13 + | +LL | if let 0...3 = 0 {} + | ^^^ help: use `..=` for an inclusive range + | +note: lint level defined here + --> $DIR/recover-range-pats.rs:7:9 + | +LL | #![deny(ellipsis_inclusive_range_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:42:13 + | +LL | if let 0...Y = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:43:13 + | +LL | if let X...3 = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:44:13 + | +LL | if let X...Y = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:45:16 + | +LL | if let true...Y = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:47:13 + | +LL | if let X...true = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:49:14 + | +LL | if let .0...Y = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:52:13 + | +LL | if let X... .0 = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:78:13 + | +LL | if let 0... = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:80:13 + | +LL | if let X... = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:82:16 + | +LL | if let true... = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:85:14 + | +LL | if let .0... = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:112:12 + | +LL | if let ...3 = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:114:12 + | +LL | if let ...Y = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:116:12 + | +LL | if let ...true = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:119:12 + | +LL | if let ....3 = 0 {} + | ^^^ help: use `..=` for an inclusive range + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:19:12 + | +LL | if let true..Y = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: bool + = note: end type: u8 + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:20:15 + | +LL | if let X..true = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: u8 + = note: end type: bool + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:21:12 + | +LL | if let .0..Y = 0 {} + | ^^^^^ expected integer, found floating-point number + | + = note: expected type `{integer}` + found type `{float}` + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:23:12 + | +LL | if let X.. .0 = 0 {} + | ^^^^^^ expected integer, found floating-point number + | + = note: expected type `u8` + found type `{float}` + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:32:12 + | +LL | if let true..=Y = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: bool + = note: end type: u8 + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:33:16 + | +LL | if let X..=true = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: u8 + = note: end type: bool + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:34:12 + | +LL | if let .0..=Y = 0 {} + | ^^^^^^ expected integer, found floating-point number + | + = note: expected type `{integer}` + found type `{float}` + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:36:12 + | +LL | if let X..=.0 = 0 {} + | ^^^^^^ expected integer, found floating-point number + | + = note: expected type `u8` + found type `{float}` + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:45:12 + | +LL | if let true...Y = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: bool + = note: end type: u8 + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:47:16 + | +LL | if let X...true = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: u8 + = note: end type: bool + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:49:12 + | +LL | if let .0...Y = 0 {} + | ^^^^^^ expected integer, found floating-point number + | + = note: expected type `{integer}` + found type `{float}` + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:52:12 + | +LL | if let X... .0 = 0 {} + | ^^^^^^^ expected integer, found floating-point number + | + = note: expected type `u8` + found type `{float}` + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:60:12 + | +LL | if let true.. = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: bool + = note: end type: [type error] + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:62:12 + | +LL | if let .0.. = 0 {} + | ^^^^ expected integer, found floating-point number + | + = note: expected type `{integer}` + found type `{float}` + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:70:12 + | +LL | if let true..= = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: bool + = note: end type: [type error] + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:72:12 + | +LL | if let .0..= = 0 {} + | ^^^^^ expected integer, found floating-point number + | + = note: expected type `{integer}` + found type `{float}` + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:82:12 + | +LL | if let true... = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: bool + = note: end type: [type error] + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:85:12 + | +LL | if let .0... = 0 {} + | ^^^^^ expected integer, found floating-point number + | + = note: expected type `{integer}` + found type `{float}` + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:94:14 + | +LL | if let ..true = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: [type error] + = note: end type: bool + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:96:12 + | +LL | if let .. .0 = 0 {} + | ^^^^^ expected integer, found floating-point number + | + = note: expected type `{integer}` + found type `{float}` + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:104:15 + | +LL | if let ..=true = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: [type error] + = note: end type: bool + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:106:12 + | +LL | if let ..=.0 = 0 {} + | ^^^^^ expected integer, found floating-point number + | + = note: expected type `{integer}` + found type `{float}` + +error[E0029]: only char and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:116:15 + | +LL | if let ...true = 0 {} + | ^^^^ ranges require char or numeric types + | + = note: start type: [type error] + = note: end type: bool + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:119:12 + | +LL | if let ....3 = 0 {} + | ^^^^^ expected integer, found floating-point number + | + = note: expected type `{integer}` + found type `{float}` + +error: aborting due to 76 previous errors + +Some errors have detailed explanations: E0029, E0308. +For more information about an error, try `rustc --explain E0029`. diff --git a/src/test/ui/parser/recover-tuple-pat.rs b/src/test/ui/parser/recover-tuple-pat.rs index 488e8db6b8789..7fded752d675e 100644 --- a/src/test/ui/parser/recover-tuple-pat.rs +++ b/src/test/ui/parser/recover-tuple-pat.rs @@ -1,12 +1,12 @@ +// NOTE: This doesn't recover anymore. + fn main() { let x = (1, 2, 3, 4); match x { (1, .., 4) => {} (1, .=., 4) => { let _: usize = ""; } //~^ ERROR expected pattern, found `.` - //~| ERROR mismatched types (.=., 4) => {} - //~^ ERROR expected pattern, found `.` (1, 2, 3, 4) => {} } } diff --git a/src/test/ui/parser/recover-tuple-pat.stderr b/src/test/ui/parser/recover-tuple-pat.stderr index 5919aa72355ac..93a6a66a63082 100644 --- a/src/test/ui/parser/recover-tuple-pat.stderr +++ b/src/test/ui/parser/recover-tuple-pat.stderr @@ -1,24 +1,8 @@ error: expected pattern, found `.` - --> $DIR/recover-tuple-pat.rs:5:13 + --> $DIR/recover-tuple-pat.rs:7:13 | LL | (1, .=., 4) => { let _: usize = ""; } | ^ expected pattern -error: expected pattern, found `.` - --> $DIR/recover-tuple-pat.rs:8:10 - | -LL | (.=., 4) => {} - | ^ expected pattern - -error[E0308]: mismatched types - --> $DIR/recover-tuple-pat.rs:5:41 - | -LL | (1, .=., 4) => { let _: usize = ""; } - | ^^ expected usize, found reference - | - = note: expected type `usize` - found type `&'static str` - -error: aborting due to 3 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfc-2005-default-binding-mode/slice.rs index fd85bf7f16007..1484b8c4a1f13 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/slice.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/slice.rs @@ -4,6 +4,6 @@ pub fn main() { let sl: &[u8] = b"foo"; match sl { //~ ERROR non-exhaustive patterns - [first, remainder..] => {}, + [first, remainder @ ..] => {}, }; } diff --git a/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs index 939a3c4a1fd7a..38b0941aad0a6 100644 --- a/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs +++ b/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs @@ -5,7 +5,7 @@ fn slice_pat() { let sl: &[u8] = b"foo"; match sl { - [first, remainder..] => { + [first, remainder @ ..] => { let _: &u8 = first; assert_eq!(first, &b'f'); assert_eq!(remainder, b"oo"); diff --git a/src/test/ui/trailing-comma.rs b/src/test/ui/trailing-comma.rs index f34e6b7606dd7..929c35a9e1122 100644 --- a/src/test/ui/trailing-comma.rs +++ b/src/test/ui/trailing-comma.rs @@ -25,7 +25,7 @@ pub fn main() { let (_, _,) = (1, 1,); let [_, _,] = [1, 1,]; let [_, _, .., _,] = [1, 1, 1, 1,]; - let [_, _, _.., _,] = [1, 1, 1, 1,]; + let [_, _, _, ..,] = [1, 1, 1, 1,]; let x: Foo = Foo::(1); diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 8f9061d7c1811..b8dcba3afc3a1 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -1,6 +1,12 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +## This script publishes the new "current" toolstate in the toolstate repo (not to be +## confused with publishing the test results, which happens in +## `src/ci/docker/x86_64-gnu-tools/checktools.sh`). +## It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts +## when a new commit lands on `master` (i.e., after it passed all checks on `auto`). + import sys import re import os