diff --git a/Cargo.lock b/Cargo.lock index 6384560b672b1..a447ab0a8127a 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" @@ -3312,6 +3320,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" @@ -4330,7 +4343,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" @@ -4440,6 +4453,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" @@ -4542,6 +4556,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/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile index f03aff060c103..8c052db1b0dde 100644 --- a/src/ci/docker/dist-powerpc-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc-linux/Dockerfile @@ -36,7 +36,3 @@ ENV HOSTS=powerpc-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS - -# FIXME(#36150) this will fail the bootstrap. Probably means something bad is -# happening! -ENV NO_LLVM_ASSERTIONS 1 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/libcore/macros.rs b/src/libcore/macros.rs index 17781798946ed..218c164a7dc35 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -657,13 +657,13 @@ macro_rules! uninit_array { ); } -/// Built-in macros to the compiler itself. +/// Definitions of built-in macros. /// -/// These macros do not have any corresponding definition with a `macro_rules!` -/// macro, but are documented here. Their implementations can be found hardcoded -/// into libsyntax itself. -#[cfg(rustdoc)] -mod builtin { +/// Most of the macro properties (stability, visibility, etc.) are taken from the source code here, +/// with exception of expansion functions transforming macro inputs into outputs, +/// those functions are provided by the compiler. +#[cfg(not(bootstrap))] +pub(crate) mod builtin { /// Causes compilation to fail with the given error message when encountered. /// @@ -950,7 +950,7 @@ mod builtin { /// Same as `column`, but less likely to be shadowed. #[unstable(feature = "__rust_unstable_column", issue = "0", - reason = "internal implementation detail of the `column` macro")] + reason = "internal implementation detail of the `panic` macro")] #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] pub macro __rust_unstable_column() { /* compiler built-in */ } diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 501a41d0d1c76..de79e2fa260ce 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -44,3 +44,50 @@ pub use crate::option::Option::{self, Some, None}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use crate::result::Result::{self, Ok, Err}; + +// Re-exported built-in macros +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] +#[doc(no_inline)] +pub use crate::macros::builtin::{ + Clone, + Copy, + Debug, + Decodable, + Default, + Encodable, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, + RustcDecodable, + RustcEncodable, + __rust_unstable_column, + asm, + assert, + bench, + cfg, + column, + compile_error, + concat, + concat_idents, + env, + file, + format_args, + format_args_nl, + global_allocator, + global_asm, + include, + include_bytes, + include_str, + line, + log_syntax, + module_path, + option_env, + stringify, + test, + test_case, + trace_macros, +}; diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 6f841bd2adf41..65e293642874c 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -217,7 +217,7 @@ impl fmt::Debug for Context<'_> { /// This handle encapsulates a [`RawWaker`] instance, which defines the /// executor-specific wakeup behavior. /// -/// Implements [`Clone`], [`Send`], and [`Sync`]. +/// Implements [`Clone`], [`trait@Send`], and [`trait@Sync`]. /// /// [`RawWaker`]: struct.RawWaker.html #[repr(transparent)] diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index f3edb5f862117..c0a661908a654 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -12,10 +12,6 @@ newtype_index! { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum CrateNum { - /// Virtual crate for builtin macros - // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get - // `CrateNum`s. - BuiltinMacros, /// A special CrateNum that we use for the tcx.rcache when decoding from /// the incr. comp. cache. ReservedForIncrCompCache, @@ -26,7 +22,6 @@ impl ::std::fmt::Debug for CrateNum { fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { match self { CrateNum::Index(id) => write!(fmt, "crate{}", id.private), - CrateNum::BuiltinMacros => write!(fmt, "builtin macros crate"), CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"), } } @@ -86,7 +81,6 @@ impl fmt::Display for CrateNum { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { CrateNum::Index(id) => fmt::Display::fmt(&id.private, f), - CrateNum::BuiltinMacros => write!(f, "builtin macros crate"), CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"), } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 288fd2714e251..bc2c835e21050 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; @@ -468,7 +469,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); @@ -1157,7 +1158,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 { @@ -4009,8 +4010,7 @@ impl<'a> LoweringContext<'a> { let mut vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); if let ItemKind::MacroDef(ref def) = i.node { - if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) || - attr::contains_name(&i.attrs, sym::rustc_builtin_macro) { + if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) { let body = self.lower_token_stream(def.stream()); let hir_id = self.lower_node_id(i.id); self.exported_macros.push(hir::MacroDef { @@ -4173,33 +4173,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, @@ -4207,11 +4185,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( @@ -4248,8 +4223,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) => { @@ -4260,15 +4236,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, @@ -4276,6 +4375,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, @@ -5754,13 +5875,21 @@ impl<'a> LoweringContext<'a> { } fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) { - self.sess.buffer_lint_with_diagnostic( - builtin::BARE_TRAIT_OBJECTS, - id, - span, - "trait objects without an explicit `dyn` are deprecated", - builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global), - ) + // FIXME(davidtwco): This is a hack to detect macros which produce spans of the + // call site which do not have a macro backtrace. See #61963. + let is_macro_callsite = self.sess.source_map() + .span_to_snippet(span) + .map(|snippet| snippet.starts_with("#[")) + .unwrap_or(true); + if !is_macro_callsite { + self.sess.buffer_lint_with_diagnostic( + builtin::BARE_TRAIT_OBJECTS, + id, + span, + "trait objects without an explicit `dyn` are deprecated", + builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global), + ) + } } fn wrap_in_try_constructor( diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 1cc7cfda0120a..2754c55ea0685 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -372,7 +372,10 @@ fn configure_and_expand_inner<'a>( crate_loader, &resolver_arenas, ); - syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts, sess.edition()); + syntax_ext::register_builtin_macros(&mut resolver, sess.edition()); + syntax_ext::plugin_macro_defs::inject( + &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition() + ); // Expand all macros sess.profiler(|p| p.start_activity("macro expansion")); 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 b550029d9786d..473ba21c77b6d 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_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index cfba42580fcef..f52f7d9cfb3c3 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -13,7 +13,7 @@ use crate::{resolve_error, resolve_struct_error, ResolutionError, Determinacy}; use rustc::bug; use rustc::hir::def::{self, *}; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use rustc::middle::cstore::CrateStore; use rustc_metadata::cstore::LoadedMacro; @@ -31,7 +31,6 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, Nod use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant}; use syntax::ext::base::SyntaxExtension; use syntax::ext::hygiene::ExpnId; -use syntax::ext::tt::macro_rules; use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; use syntax::span_err; @@ -748,7 +747,7 @@ impl<'a> Resolver<'a> { }; if let Some(id) = self.definitions.as_local_node_id(def_id) { self.local_macro_def_scopes[&id] - } else if def_id.krate == CrateNum::BuiltinMacros { + } else if self.is_builtin_macro(Some(def_id)) { self.injected_crate.unwrap_or(self.graph_root) } else { let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap(); @@ -756,13 +755,16 @@ impl<'a> Resolver<'a> { } } - pub fn get_macro(&mut self, res: Res) -> Option> { - let def_id = match res { - Res::Def(DefKind::Macro(..), def_id) => def_id, + crate fn get_macro(&mut self, res: Res) -> Option> { + match res { + Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id), Res::NonMacroAttr(attr_kind) => - return Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)), - _ => return None, - }; + Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)), + _ => None, + } + } + + crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option> { if let Some(ext) = self.macro_map.get(&def_id) { return Some(ext.clone()); } @@ -772,10 +774,7 @@ impl<'a> Resolver<'a> { LoadedMacro::ProcMacro(ext) => return Some(ext), }; - let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess, - &self.session.features_untracked(), - ¯o_def, - self.cstore.crate_edition_untracked(def_id.krate))); + let ext = self.compile_macro(¯o_def, self.cstore.crate_edition_untracked(def_id.krate)); self.macro_map.insert(def_id, ext.clone()); Some(ext) } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 90a4107f773e1..aeb6f23da5aa6 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -35,17 +35,12 @@ enum AssocSuggestion { struct TypoSuggestion { candidate: Symbol, - - /// The kind of the binding ("crate", "module", etc.) - kind: &'static str, - - /// An appropriate article to refer to the binding ("a", "an", etc.) - article: &'static str, + res: Res, } impl TypoSuggestion { fn from_res(candidate: Symbol, res: Res) -> TypoSuggestion { - TypoSuggestion { candidate, kind: res.descr(), article: res.article() } + TypoSuggestion { candidate, res } } } @@ -59,7 +54,9 @@ fn add_typo_suggestion( err: &mut DiagnosticBuilder<'_>, suggestion: Option, span: Span ) -> bool { if let Some(suggestion) = suggestion { - let msg = format!("{} {} with a similar name exists", suggestion.article, suggestion.kind); + let msg = format!( + "{} {} with a similar name exists", suggestion.res.article(), suggestion.res.descr() + ); err.span_suggestion( span, &msg, suggestion.candidate.to_string(), Applicability::MaybeIncorrect ); @@ -566,7 +563,7 @@ impl<'a> Resolver<'a> { filter_fn: &impl Fn(Res) -> bool, ) -> Option { let mut suggestions = Vec::new(); - self.visit_scopes(scope_set, parent_scope, ident, |this, scope, _| { + self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| { match scope { Scope::DeriveHelpers => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); @@ -611,16 +608,6 @@ impl<'a> Resolver<'a> { } })); } - Scope::BuiltinMacros => { - suggestions.extend(this.builtin_macros.iter().filter_map(|(name, binding)| { - let res = binding.res(); - if filter_fn(res) { - Some(TypoSuggestion::from_res(*name, res)) - } else { - None - } - })); - } Scope::BuiltinAttrs => { let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin); if filter_fn(res) { @@ -656,7 +643,11 @@ impl<'a> Resolver<'a> { } Scope::StdLibPrelude => { if let Some(prelude) = this.prelude { - add_module_candidates(prelude, &mut suggestions, filter_fn); + let mut tmp_suggestions = Vec::new(); + add_module_candidates(prelude, &mut tmp_suggestions, filter_fn); + suggestions.extend(tmp_suggestions.into_iter().filter(|s| { + use_prelude || this.is_builtin_macro(s.res.opt_def_id()) + })); } } Scope::BuiltinTypes => { @@ -733,11 +724,7 @@ impl<'a> Resolver<'a> { ); if filter_fn(crate_mod) { - Some(TypoSuggestion { - candidate: ident.name, - article: "a", - kind: "crate", - }) + Some(TypoSuggestion::from_res(ident.name, crate_mod)) } else { None } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d718d3f78f4e2..a5e498fa75643 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -114,7 +114,6 @@ enum Scope<'a> { CrateRoot, Module(Module<'a>), MacroUsePrelude, - BuiltinMacros, BuiltinAttrs, LegacyPluginHelpers, ExternPrelude, @@ -1679,7 +1678,7 @@ pub struct Resolver<'a> { crate_loader: &'a mut CrateLoader<'a>, macro_names: FxHashSet, - builtin_macros: FxHashMap>, + builtin_macros: FxHashMap, macro_use_prelude: FxHashMap>, pub all_macros: FxHashMap, macro_map: FxHashMap>, @@ -2021,7 +2020,7 @@ impl<'a> Resolver<'a> { crate_loader, macro_names: FxHashSet::default(), - builtin_macros: FxHashMap::default(), + builtin_macros: Default::default(), macro_use_prelude: FxHashMap::default(), all_macros: FxHashMap::default(), macro_map: FxHashMap::default(), @@ -2068,6 +2067,11 @@ impl<'a> Resolver<'a> { f(self, MacroNS); } + fn is_builtin_macro(&mut self, def_id: Option) -> bool { + def_id.and_then(|def_id| self.get_macro_by_def_id(def_id)) + .map_or(false, |ext| ext.is_builtin) + } + fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId { loop { match self.macro_defs.get(&ctxt.outer_expn()) { @@ -2146,7 +2150,7 @@ impl<'a> Resolver<'a> { scope_set: ScopeSet, parent_scope: &ParentScope<'a>, ident: Ident, - mut visitor: impl FnMut(&mut Self, Scope<'a>, Ident) -> Option, + mut visitor: impl FnMut(&mut Self, Scope<'a>, /*use_prelude*/ bool, Ident) -> Option, ) -> Option { // General principles: // 1. Not controlled (user-defined) names should have higher priority than controlled names @@ -2185,8 +2189,8 @@ impl<'a> Resolver<'a> { // 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled). // 4a. User-defined prelude from macro-use // (open, the open part is from macro expansions, not controlled). - // 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled) - // 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins). + // 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled). + // 4c. Standard library prelude (de-facto closed, controlled). // 6. Language prelude: builtin attributes (closed, controlled). // 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers, // but introduced by legacy plugins using `register_attribute`. Priority is somewhere @@ -2214,17 +2218,16 @@ impl<'a> Resolver<'a> { Scope::CrateRoot => true, Scope::Module(..) => true, Scope::MacroUsePrelude => use_prelude || rust_2015, - Scope::BuiltinMacros => true, Scope::BuiltinAttrs => true, Scope::LegacyPluginHelpers => use_prelude || rust_2015, Scope::ExternPrelude => use_prelude || is_absolute_path, Scope::ToolPrelude => use_prelude, - Scope::StdLibPrelude => use_prelude, + Scope::StdLibPrelude => use_prelude || ns == MacroNS, Scope::BuiltinTypes => true, }; if visit { - if let break_result @ Some(..) = visitor(self, scope, ident) { + if let break_result @ Some(..) = visitor(self, scope, use_prelude, ident) { return break_result; } } @@ -2263,7 +2266,6 @@ impl<'a> Resolver<'a> { } } Scope::MacroUsePrelude => Scope::StdLibPrelude, - Scope::BuiltinMacros => Scope::BuiltinAttrs, Scope::BuiltinAttrs => Scope::LegacyPluginHelpers, Scope::LegacyPluginHelpers => break, // nowhere else to search Scope::ExternPrelude if is_absolute_path => break, @@ -2272,7 +2274,7 @@ impl<'a> Resolver<'a> { Scope::StdLibPrelude => match ns { TypeNS => Scope::BuiltinTypes, ValueNS => break, // nowhere else to search - MacroNS => Scope::BuiltinMacros, + MacroNS => Scope::BuiltinAttrs, } Scope::BuiltinTypes => break, // nowhere else to search }; diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 3760cabcd898a..88850c5988b7b 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -1,18 +1,19 @@ use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy}; use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak}; -use crate::{Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding}; +use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding}; use crate::{resolve_error, KNOWN_TOOLS}; use crate::ModuleOrUniformRoot; use crate::Namespace::*; use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use crate::resolve_imports::ImportResolver; -use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::hir::def::{self, DefKind, NonMacroAttrKind}; use rustc::hir::map::DefCollector; use rustc::middle::stability; use rustc::{ty, lint, span_bug}; use syntax::ast::{self, Ident, ItemKind}; use syntax::attr::{self, StabilityLevel}; +use syntax::edition::Edition; use syntax::ext::base::{self, Indeterminate}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; @@ -182,21 +183,8 @@ impl<'a> base::Resolver for Resolver<'a> { invocation.output_legacy_scope.set(Some(visitor.current_legacy_scope)); } - fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc) { - let def_id = DefId { - krate: CrateNum::BuiltinMacros, - index: DefIndex::from(self.macro_map.len()), - }; - let kind = ext.macro_kind(); - self.macro_map.insert(def_id, ext); - let binding = self.arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Res(Res::Def(DefKind::Macro(kind), def_id), false), - ambiguity: None, - span: DUMMY_SP, - vis: ty::Visibility::Public, - expansion: ExpnId::root(), - }); - if self.builtin_macros.insert(ident.name, binding).is_some() { + fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) { + if self.builtin_macros.insert(ident.name, ext).is_some() { self.session.span_err(ident.span, &format!("built-in macro `{}` was already defined", ident)); } @@ -449,8 +437,8 @@ impl<'a> Resolver<'a> { let mut determinacy = Determinacy::Determined; // Go through all the scopes and try to resolve the name. - let break_result = - self.visit_scopes(scope_set, parent_scope, orig_ident, |this, scope, ident| { + let break_result = self.visit_scopes(scope_set, parent_scope, orig_ident, + |this, scope, use_prelude, ident| { let result = match scope { Scope::DeriveHelpers => { let mut result = Err(Determinacy::Determined); @@ -535,10 +523,6 @@ impl<'a> Resolver<'a> { this.graph_root.unresolved_invocations.borrow().is_empty() )) } - Scope::BuiltinMacros => match this.builtin_macros.get(&ident.name).cloned() { - Some(binding) => Ok((binding, Flags::PRELUDE)), - None => Err(Determinacy::Determined), - } Scope::BuiltinAttrs => if is_builtin_attr_name(ident.name) { let binding = (Res::NonMacroAttr(NonMacroAttrKind::Builtin), ty::Visibility::Public, DUMMY_SP, ExpnId::root()) @@ -579,7 +563,9 @@ impl<'a> Resolver<'a> { false, path_span, ) { - result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)); + if use_prelude || this.is_builtin_macro(binding.res().opt_def_id()) { + result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)); + } } } result @@ -844,18 +830,42 @@ impl<'a> Resolver<'a> { } } + /// Compile the macro into a `SyntaxExtension` and possibly replace it with a pre-defined + /// extension partially or entirely for built-in macros and legacy plugin macros. + crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> Lrc { + let mut result = macro_rules::compile( + &self.session.parse_sess, self.session.features_untracked(), item, edition + ); + + if result.is_builtin { + // The macro was marked with `#[rustc_builtin_macro]`. + if let Some(ext) = self.builtin_macros.remove(&item.ident.name) { + if ext.is_builtin { + // The macro is a built-in, replace only the expander function. + result.kind = ext.kind; + // Also reset its edition to the global one for compatibility. + result.edition = self.session.edition(); + } else { + // The macro is from a plugin, the in-source definition is dummy, + // take all the data from the resolver. + result = ext; + } + } else { + let msg = format!("cannot find a built-in macro with name `{}`", item.ident); + self.session.span_err(item.span, &msg); + } + } + + Lrc::new(result) + } + pub fn define_macro(&mut self, item: &ast::Item, expansion: ExpnId, current_legacy_scope: &mut LegacyScope<'a>) { let (ext, ident, span, is_legacy) = match &item.node { ItemKind::MacroDef(def) => { - let ext = Lrc::new(macro_rules::compile( - &self.session.parse_sess, - &self.session.features_untracked(), - item, - self.session.edition(), - )); + let ext = self.compile_macro(item, self.session.edition()); (ext, item.ident, item.span, def.legacy) } ItemKind::Fn(..) => match proc_macro_stub(item) { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 1960c06e86e4c..59438883d60bc 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -21,8 +21,8 @@ use rustc::lint::builtin::{ PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS, }; -use rustc::hir::def_id::{CrateNum, DefId}; -use rustc::hir::def::{self, DefKind, PartialRes, Export}; +use rustc::hir::def_id::DefId; +use rustc::hir::def::{self, PartialRes, Export}; use rustc::session::DiagnosticMessageId; use rustc::util::nodemap::FxHashSet; use rustc::{bug, span_bug}; @@ -1214,17 +1214,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() { - let mut res = binding.res(); - if let Res::Def(DefKind::Macro(_), def_id) = res { - // `DefId`s from the "built-in macro crate" should not leak from resolve because - // later stages are not ready to deal with them and produce lots of ICEs. Replace - // them with `Res::Err` until some saner scheme is implemented for built-in macros. - if def_id.krate == CrateNum::BuiltinMacros { - this.session.span_err(directive.span, "cannot import a built-in macro"); - res = Res::Err; - } - } - this.import_res_map.entry(directive.id).or_default()[ns] = Some(res); + this.import_res_map.entry(directive.id).or_default()[ns] = Some(binding.res()); }); self.check_for_redundant_imports( @@ -1388,7 +1378,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let res = binding.res(); if res != Res::Err { if let Some(def_id) = res.opt_def_id() { - if !def_id.is_local() && def_id.krate != CrateNum::BuiltinMacros { + if !def_id.is_local() { self.cstore.export_macros_untracked(def_id.krate); } } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index dfdf560d41906..2b349613dc54f 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -10,7 +10,7 @@ //! //! SpanUtils is used to manipulate spans. In particular, to extract sub-spans //! from spans (e.g., the span for `bar` from the above example path). -//! DumpVisitor walks the AST and processes it, and JsonDumper is used for +//! DumpVisitor walks the AST and processes it, and Dumper is used for //! recording the output. use rustc::hir::def::{Res, DefKind as HirDefKind}; @@ -38,7 +38,7 @@ use syntax_pos::*; use crate::{escape, generated_code, id_from_def_id, id_from_node_id, lower_attributes, PathCollector, SaveContext}; -use crate::json_dumper::{Access, DumpOutput, JsonDumper}; +use crate::dumper::{Access, Dumper}; use crate::span_utils::SpanUtils; use crate::sig; @@ -75,10 +75,10 @@ macro_rules! access_from_vis { }; } -pub struct DumpVisitor<'l, 'tcx, 'll, O: DumpOutput> { +pub struct DumpVisitor<'l, 'tcx, 'll> { save_ctxt: SaveContext<'l, 'tcx>, tcx: TyCtxt<'tcx>, - dumper: &'ll mut JsonDumper, + dumper: &'ll mut Dumper, span: SpanUtils<'l>, @@ -92,11 +92,11 @@ pub struct DumpVisitor<'l, 'tcx, 'll, O: DumpOutput> { // macro_calls: FxHashSet, } -impl<'l, 'tcx, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { +impl<'l, 'tcx, 'll> DumpVisitor<'l, 'tcx, 'll> { pub fn new( save_ctxt: SaveContext<'l, 'tcx>, - dumper: &'ll mut JsonDumper, - ) -> DumpVisitor<'l, 'tcx, 'll, O> { + dumper: &'ll mut Dumper, + ) -> DumpVisitor<'l, 'tcx, 'll> { let span_utils = SpanUtils::new(&save_ctxt.tcx.sess); DumpVisitor { tcx: save_ctxt.tcx, @@ -111,7 +111,7 @@ impl<'l, 'tcx, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { fn nest_scope(&mut self, scope_id: NodeId, f: F) where - F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>), + F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll>), { let parent_scope = self.cur_scope; self.cur_scope = scope_id; @@ -121,7 +121,7 @@ impl<'l, 'tcx, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { fn nest_tables(&mut self, item_id: NodeId, f: F) where - F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, O>), + F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll>), { let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id); if self.tcx.has_typeck_tables(item_def_id) { @@ -1311,7 +1311,7 @@ impl<'l, 'tcx, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } } -impl<'l, 'tcx, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, O> { +impl<'l, 'tcx, 'll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll> { fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], id: NodeId) { // Since we handle explicit modules ourselves in visit_item, this should // only get called for the root module of a crate. diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/dumper.rs similarity index 65% rename from src/librustc_save_analysis/json_dumper.rs rename to src/librustc_save_analysis/dumper.rs index 82b78369e1339..6fb55e6c99055 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/dumper.rs @@ -1,80 +1,33 @@ -use std::io::Write; - use rls_data::config::Config; use rls_data::{self, Analysis, CompilationOptions, CratePreludeData, Def, DefKind, Impl, Import, MacroRef, Ref, RefKind, Relation}; use rls_span::{Column, Row}; -use log::error; - #[derive(Debug)] pub struct Access { pub reachable: bool, pub public: bool, } -pub struct JsonDumper { +pub struct Dumper { result: Analysis, config: Config, - output: O, -} - -pub trait DumpOutput { - fn dump(&mut self, result: &Analysis); -} - -pub struct WriteOutput<'b, W: Write> { - output: &'b mut W, -} - -impl<'b, W: Write> DumpOutput for WriteOutput<'b, W> { - fn dump(&mut self, result: &Analysis) { - if let Err(e) = serde_json::to_writer(self.output.by_ref(), result) { - error!("Can't serialize save-analysis: {:?}", e); - } - } -} - -pub struct CallbackOutput<'b> { - callback: &'b mut dyn FnMut(&Analysis), -} - -impl<'b> DumpOutput for CallbackOutput<'b> { - fn dump(&mut self, result: &Analysis) { - (self.callback)(result) - } } -impl<'b, W: Write> JsonDumper> { - pub fn new(writer: &'b mut W, config: Config) -> JsonDumper> { - JsonDumper { - output: WriteOutput { output: writer }, +impl Dumper { + pub fn new(config: Config) -> Dumper { + Dumper { config: config.clone(), result: Analysis::new(config), } } -} - -impl<'b> JsonDumper> { - pub fn with_callback( - callback: &'b mut dyn FnMut(&Analysis), - config: Config, - ) -> JsonDumper> { - JsonDumper { - output: CallbackOutput { callback }, - config: config.clone(), - result: Analysis::new(config), - } - } -} -impl Drop for JsonDumper { - fn drop(&mut self) { - self.output.dump(&self.result); + pub fn to_output(self, f: impl FnOnce(&Analysis)) { + f(&self.result) } } -impl<'b, O: DumpOutput + 'b> JsonDumper { +impl Dumper { pub fn crate_prelude(&mut self, data: CratePreludeData) { self.result.prelude = Some(data) } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index c987a46b56737..ade5e2eca60ba 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -7,7 +7,7 @@ #![recursion_limit="256"] -mod json_dumper; +mod dumper; mod dump_visitor; #[macro_use] mod span_utils; @@ -39,7 +39,7 @@ use syntax::visit::{self, Visitor}; use syntax::print::pprust::{arg_to_string, ty_to_string}; use syntax_pos::*; -use json_dumper::JsonDumper; +use dumper::Dumper; use dump_visitor::DumpVisitor; use span_utils::SpanUtils; @@ -1075,17 +1075,19 @@ impl<'a> SaveHandler for DumpHandler<'a> { input: &'l Input, ) { let sess = &save_ctxt.tcx.sess; - let file_name = { - let (mut output, file_name) = self.output_file(&save_ctxt); - let mut dumper = JsonDumper::new(&mut output, save_ctxt.config.clone()); - let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); + let (output, file_name) = self.output_file(&save_ctxt); + let mut dumper = Dumper::new(save_ctxt.config.clone()); + let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); - visitor.dump_crate_info(cratename, krate); - visitor.dump_compilation_options(input, cratename); - visit::walk_crate(&mut visitor, krate); + visitor.dump_crate_info(cratename, krate); + visitor.dump_compilation_options(input, cratename); + visit::walk_crate(&mut visitor, krate); - file_name - }; + dumper.to_output(|analysis| { + if let Err(e) = serde_json::to_writer(output, analysis) { + error!("Can't serialize save-analysis: {:?}", e); + } + }); if sess.opts.debugging_opts.emit_artifact_notifications { sess.parse_sess.span_diagnostic @@ -1107,17 +1109,19 @@ impl<'b> SaveHandler for CallbackHandler<'b> { cratename: &str, input: &'l Input, ) { - // We're using the JsonDumper here because it has the format of the + // We're using the Dumper here because it has the format of the // save-analysis results that we will pass to the callback. IOW, we are - // using the JsonDumper to collect the save-analysis results, but not + // using the Dumper to collect the save-analysis results, but not // actually to dump them to a file. This is all a bit convoluted and // there is certainly a simpler design here trying to get out (FIXME). - let mut dumper = JsonDumper::with_callback(self.callback, save_ctxt.config.clone()); + let mut dumper = Dumper::new(save_ctxt.config.clone()); let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); visitor.dump_crate_info(cratename, krate); visitor.dump_compilation_options(input, cratename); visit::walk_crate(&mut visitor, krate); + + dumper.to_output(|a| (self.callback)(a)) } } 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_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index de42a6a35c89a..6a6bc31958982 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 21cd4b694ae4c..298043cbbaf72 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/error.rs b/src/libstd/error.rs index 5b1e78a113917..117a430eec6b9 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -254,8 +254,8 @@ impl<'a, E: Error + 'a> From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + Send + Sync + 'a> From for Box { - /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] + - /// [`Send`] + [`Sync`]. + /// Converts a type of [`Error`] + [`trait@Send`] + [`trait@Sync`] into a box of + /// dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -298,7 +298,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { - /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a [`String`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -362,7 +362,7 @@ impl From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&str> for Box { - /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a [`str`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -405,7 +405,7 @@ impl From<&str> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From> for Box { - /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`Error`]: ../error/trait.Error.html diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fbc68c610ee39..722c08a22a6b6 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -221,14 +221,15 @@ #![cfg_attr(test, feature(print_internals, set_stdio, test, update_panic_count))] #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), - feature(global_asm, slice_index_methods, - decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))] + feature(slice_index_methods, decl_macro, coerce_unsized, + sgx_platform, ptr_wrapping_offset_from))] #![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array, maybe_uninit_extra))] // std is implemented with unstable features, many of which are internal // compiler details that will never be stable // NB: the following list is sorted to minimize merge conflicts. +#![cfg_attr(not(bootstrap), feature(__rust_unstable_column))] #![feature(alloc_error_handler)] #![feature(alloc_layout_extra)] #![feature(allocator_api)] @@ -251,6 +252,7 @@ #![feature(const_cstr_unchecked)] #![feature(const_raw_ptr_deref)] #![feature(core_intrinsics)] +#![feature(custom_test_frameworks)] #![feature(doc_alias)] #![feature(doc_cfg)] #![feature(doc_keyword)] @@ -262,7 +264,9 @@ #![feature(exhaustive_patterns)] #![feature(external_doc)] #![feature(fn_traits)] +#![feature(format_args_nl)] #![feature(generator_trait)] +#![feature(global_asm)] #![feature(hash_raw_entry)] #![feature(hashmap_internals)] #![feature(int_error_internals)] @@ -272,6 +276,7 @@ #![feature(libc)] #![feature(link_args)] #![feature(linkage)] +#![feature(log_syntax)] #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] #![feature(mem_take)] @@ -303,6 +308,7 @@ #![feature(thread_local)] #![feature(todo_macro)] #![feature(toowned_clone_into)] +#![feature(trace_macros)] #![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(untagged_unions)] @@ -510,6 +516,36 @@ mod std_detect; #[cfg(not(test))] pub use std_detect::detect; +// Document built-in macros in the crate root for consistency with libcore and existing tradition. +// FIXME: Attribute and derive macros are not reexported because rustdoc renders them +// as reexports rather than as macros, and that's not what we want. +#[cfg(rustdoc)] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +pub use crate::prelude::v1::{ + __rust_unstable_column, + asm, + assert, + cfg, + column, + compile_error, + concat, + concat_idents, + env, + file, + format_args, + format_args_nl, + global_asm, + include, + include_bytes, + include_str, + line, + log_syntax, + module_path, + option_env, + stringify, + trace_macros, +}; + // Include a number of private modules that exist solely to provide // the rustdoc documentation for primitive types. Using `include!` // because rustdoc only looks for these modules at the crate level. diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index b3e09d6974229..839b4c5656a09 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -365,534 +365,3 @@ macro_rules! assert_approx_eq { "{} is not approximately equal to {}", *a, *b); }) } - -/// Built-in macros to the compiler itself. -/// -/// These macros do not have any corresponding definition with a `macro_rules!` -/// macro, but are documented here. Their implementations can be found hardcoded -/// into libsyntax itself. -#[cfg(rustdoc)] -mod builtin { - - /// Causes compilation to fail with the given error message when encountered. - /// - /// This macro should be used when a crate uses a conditional compilation strategy to provide - /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`], - /// which emits an error at *runtime*, rather than during compilation. - /// - /// # Examples - /// - /// Two such examples are macros and `#[cfg]` environments. - /// - /// Emit better compiler error if a macro is passed invalid values. Without the final branch, - /// the compiler would still emit an error, but the error's message would not mention the two - /// valid values. - /// - /// ```compile_fail - /// macro_rules! give_me_foo_or_bar { - /// (foo) => {}; - /// (bar) => {}; - /// ($x:ident) => { - /// compile_error!("This macro only accepts `foo` or `bar`"); - /// } - /// } - /// - /// give_me_foo_or_bar!(neither); - /// // ^ will fail at compile time with message "This macro only accepts `foo` or `bar`" - /// ``` - /// - /// Emit compiler error if one of a number of features isn't available. - /// - /// ```compile_fail - /// #[cfg(not(any(feature = "foo", feature = "bar")))] - /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate."); - /// ``` - /// - /// [`panic!`]: ../std/macro.panic.html - #[stable(feature = "compile_error_macro", since = "1.20.0")] - #[rustc_builtin_macro] - macro_rules! compile_error { - ($msg:expr) => ({ /* compiler built-in */ }); - ($msg:expr,) => ({ /* compiler built-in */ }); - } - - /// Constructs parameters for the other string-formatting macros. - /// - /// This macro functions by taking a formatting string literal containing - /// `{}` for each additional argument passed. `format_args!` prepares the - /// additional parameters to ensure the output can be interpreted as a string - /// and canonicalizes the arguments into a single type. Any value that implements - /// the [`Display`] trait can be passed to `format_args!`, as can any - /// [`Debug`] implementation be passed to a `{:?}` within the formatting string. - /// - /// This macro produces a value of type [`fmt::Arguments`]. This value can be - /// passed to the macros within [`std::fmt`] for performing useful redirection. - /// All other formatting macros ([`format!`], [`write!`], [`println!`], etc) are - /// proxied through this one. `format_args!`, unlike its derived macros, avoids - /// heap allocations. - /// - /// You can use the [`fmt::Arguments`] value that `format_args!` returns - /// in `Debug` and `Display` contexts as seen below. The example also shows - /// that `Debug` and `Display` format to the same thing: the interpolated - /// format string in `format_args!`. - /// - /// ```rust - /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); - /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); - /// assert_eq!("1 foo 2", display); - /// assert_eq!(display, debug); - /// ``` - /// - /// For more information, see the documentation in [`std::fmt`]. - /// - /// [`Display`]: ../std/fmt/trait.Display.html - /// [`Debug`]: ../std/fmt/trait.Debug.html - /// [`fmt::Arguments`]: ../std/fmt/struct.Arguments.html - /// [`std::fmt`]: ../std/fmt/index.html - /// [`format!`]: ../std/macro.format.html - /// [`write!`]: ../std/macro.write.html - /// [`println!`]: ../std/macro.println.html - /// - /// # Examples - /// - /// ``` - /// use std::fmt; - /// - /// let s = fmt::format(format_args!("hello {}", "world")); - /// assert_eq!(s, format!("hello {}", "world")); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! format_args { - ($fmt:expr) => ({ /* compiler built-in */ }); - ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }); - } - - /// Inspects an environment variable at compile time. - /// - /// This macro will expand to the value of the named environment variable at - /// compile time, yielding an expression of type `&'static str`. - /// - /// If the environment variable is not defined, then a compilation error - /// will be emitted. To not emit a compile error, use the [`option_env!`] - /// macro instead. - /// - /// [`option_env!`]: ../std/macro.option_env.html - /// - /// # Examples - /// - /// ``` - /// let path: &'static str = env!("PATH"); - /// println!("the $PATH variable at the time of compiling was: {}", path); - /// ``` - /// - /// You can customize the error message by passing a string as the second - /// parameter: - /// - /// ```compile_fail - /// let doc: &'static str = env!("documentation", "what's that?!"); - /// ``` - /// - /// If the `documentation` environment variable is not defined, you'll get - /// the following error: - /// - /// ```text - /// error: what's that?! - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! env { - ($name:expr) => ({ /* compiler built-in */ }); - ($name:expr,) => ({ /* compiler built-in */ }); - } - - /// Optionally inspects an environment variable at compile time. - /// - /// If the named environment variable is present at compile time, this will - /// expand into an expression of type `Option<&'static str>` whose value is - /// `Some` of the value of the environment variable. If the environment - /// variable is not present, then this will expand to `None`. See - /// [`Option`][option] for more information on this type. - /// - /// A compile time error is never emitted when using this macro regardless - /// of whether the environment variable is present or not. - /// - /// [option]: ../std/option/enum.Option.html - /// - /// # Examples - /// - /// ``` - /// let key: Option<&'static str> = option_env!("SECRET_KEY"); - /// println!("the secret key might be: {:?}", key); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! option_env { - ($name:expr) => ({ /* compiler built-in */ }); - ($name:expr,) => ({ /* compiler built-in */ }); - } - - /// Concatenates identifiers into one identifier. - /// - /// This macro takes any number of comma-separated identifiers, and - /// concatenates them all into one, yielding an expression which is a new - /// identifier. Note that hygiene makes it such that this macro cannot - /// capture local variables. Also, as a general rule, macros are only - /// allowed in item, statement or expression position. That means while - /// you may use this macro for referring to existing variables, functions or - /// modules etc, you cannot define a new one with it. - /// - /// # Examples - /// - /// ``` - /// #![feature(concat_idents)] - /// - /// # fn main() { - /// fn foobar() -> u32 { 23 } - /// - /// let f = concat_idents!(foo, bar); - /// println!("{}", f()); - /// - /// // fn concat_idents!(new, fun, name) { } // not usable in this way! - /// # } - /// ``` - #[unstable(feature = "concat_idents_macro", issue = "29599")] - #[rustc_builtin_macro] - macro_rules! concat_idents { - ($($e:ident),+) => ({ /* compiler built-in */ }); - ($($e:ident,)+) => ({ /* compiler built-in */ }); - } - - /// Concatenates literals into a static string slice. - /// - /// This macro takes any number of comma-separated literals, yielding an - /// expression of type `&'static str` which represents all of the literals - /// concatenated left-to-right. - /// - /// Integer and floating point literals are stringified in order to be - /// concatenated. - /// - /// # Examples - /// - /// ``` - /// let s = concat!("test", 10, 'b', true); - /// assert_eq!(s, "test10btrue"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! concat { - ($($e:expr),*) => ({ /* compiler built-in */ }); - ($($e:expr,)*) => ({ /* compiler built-in */ }); - } - - /// Expands to the line number on which it was invoked. - /// - /// With [`column!`] and [`file!`], these macros provide debugging information for - /// developers about the location within the source. - /// - /// The expanded expression has type `u32` and is 1-based, so the first line - /// in each file evaluates to 1, the second to 2, etc. This is consistent - /// with error messages by common compilers or popular editors. - /// The returned line is *not necessarily* the line of the `line!` invocation itself, - /// but rather the first macro invocation leading up to the invocation - /// of the `line!` macro. - /// - /// [`column!`]: macro.column.html - /// [`file!`]: macro.file.html - /// - /// # Examples - /// - /// ``` - /// let current_line = line!(); - /// println!("defined on line: {}", current_line); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! line { () => ({ /* compiler built-in */ }) } - - /// Expands to the column number at which it was invoked. - /// - /// With [`line!`] and [`file!`], these macros provide debugging information for - /// developers about the location within the source. - /// - /// The expanded expression has type `u32` and is 1-based, so the first column - /// in each line evaluates to 1, the second to 2, etc. This is consistent - /// with error messages by common compilers or popular editors. - /// The returned column is *not necessarily* the line of the `column!` invocation itself, - /// but rather the first macro invocation leading up to the invocation - /// of the `column!` macro. - /// - /// [`line!`]: macro.line.html - /// [`file!`]: macro.file.html - /// - /// # Examples - /// - /// ``` - /// let current_col = column!(); - /// println!("defined on column: {}", current_col); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! column { () => ({ /* compiler built-in */ }) } - - /// Expands to the file name in which it was invoked. - /// - /// With [`line!`] and [`column!`], these macros provide debugging information for - /// developers about the location within the source. - /// - /// - /// The expanded expression has type `&'static str`, and the returned file - /// is not the invocation of the `file!` macro itself, but rather the - /// first macro invocation leading up to the invocation of the `file!` - /// macro. - /// - /// [`line!`]: macro.line.html - /// [`column!`]: macro.column.html - /// - /// # Examples - /// - /// ``` - /// let this_file = file!(); - /// println!("defined in file: {}", this_file); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! file { () => ({ /* compiler built-in */ }) } - - /// Stringifies its arguments. - /// - /// This macro will yield an expression of type `&'static str` which is the - /// stringification of all the tokens passed to the macro. No restrictions - /// are placed on the syntax of the macro invocation itself. - /// - /// Note that the expanded results of the input tokens may change in the - /// future. You should be careful if you rely on the output. - /// - /// # Examples - /// - /// ``` - /// let one_plus_one = stringify!(1 + 1); - /// assert_eq!(one_plus_one, "1 + 1"); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) } - - /// Includes a utf8-encoded file as a string. - /// - /// The file is located relative to the current file. (similarly to how - /// modules are found) - /// - /// This macro will yield an expression of type `&'static str` which is the - /// contents of the file. - /// - /// # Examples - /// - /// Assume there are two files in the same directory with the following - /// contents: - /// - /// File 'spanish.in': - /// - /// ```text - /// adiós - /// ``` - /// - /// File 'main.rs': - /// - /// ```ignore (cannot-doctest-external-file-dependency) - /// fn main() { - /// let my_str = include_str!("spanish.in"); - /// assert_eq!(my_str, "adiós\n"); - /// print!("{}", my_str); - /// } - /// ``` - /// - /// Compiling 'main.rs' and running the resulting binary will print "adiós". - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! include_str { - ($file:expr) => ({ /* compiler built-in */ }); - ($file:expr,) => ({ /* compiler built-in */ }); - } - - /// Includes a file as a reference to a byte array. - /// - /// The file is located relative to the current file. (similarly to how - /// modules are found) - /// - /// This macro will yield an expression of type `&'static [u8; N]` which is - /// the contents of the file. - /// - /// # Examples - /// - /// Assume there are two files in the same directory with the following - /// contents: - /// - /// File 'spanish.in': - /// - /// ```text - /// adiós - /// ``` - /// - /// File 'main.rs': - /// - /// ```ignore (cannot-doctest-external-file-dependency) - /// fn main() { - /// let bytes = include_bytes!("spanish.in"); - /// assert_eq!(bytes, b"adi\xc3\xb3s\n"); - /// print!("{}", String::from_utf8_lossy(bytes)); - /// } - /// ``` - /// - /// Compiling 'main.rs' and running the resulting binary will print "adiós". - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! include_bytes { - ($file:expr) => ({ /* compiler built-in */ }); - ($file:expr,) => ({ /* compiler built-in */ }); - } - - /// Expands to a string that represents the current module path. - /// - /// The current module path can be thought of as the hierarchy of modules - /// leading back up to the crate root. The first component of the path - /// returned is the name of the crate currently being compiled. - /// - /// # Examples - /// - /// ``` - /// mod test { - /// pub fn foo() { - /// assert!(module_path!().ends_with("test")); - /// } - /// } - /// - /// test::foo(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! module_path { () => ({ /* compiler built-in */ }) } - - /// Evaluates boolean combinations of configuration flags at compile-time. - /// - /// In addition to the `#[cfg]` attribute, this macro is provided to allow - /// boolean expression evaluation of configuration flags. This frequently - /// leads to less duplicated code. - /// - /// The syntax given to this macro is the same syntax as the [`cfg`] - /// attribute. - /// - /// [`cfg`]: ../reference/conditional-compilation.html#the-cfg-attribute - /// - /// # Examples - /// - /// ``` - /// let my_directory = if cfg!(windows) { - /// "windows-specific-directory" - /// } else { - /// "unix-directory" - /// }; - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) } - - /// Parses a file as an expression or an item according to the context. - /// - /// The file is located relative to the current file (similarly to how - /// modules are found). - /// - /// Using this macro is often a bad idea, because if the file is - /// parsed as an expression, it is going to be placed in the - /// surrounding code unhygienically. This could result in variables - /// or functions being different from what the file expected if - /// there are variables or functions that have the same name in - /// the current file. - /// - /// # Examples - /// - /// Assume there are two files in the same directory with the following - /// contents: - /// - /// File 'monkeys.in': - /// - /// ```ignore (only-for-syntax-highlight) - /// ['🙈', '🙊', '🙉'] - /// .iter() - /// .cycle() - /// .take(6) - /// .collect::() - /// ``` - /// - /// File 'main.rs': - /// - /// ```ignore (cannot-doctest-external-file-dependency) - /// fn main() { - /// let my_string = include!("monkeys.in"); - /// assert_eq!("🙈🙊🙉🙈🙊🙉", my_string); - /// println!("{}", my_string); - /// } - /// ``` - /// - /// Compiling 'main.rs' and running the resulting binary will print - /// "🙈🙊🙉🙈🙊🙉". - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! include { - ($file:expr) => ({ /* compiler built-in */ }); - ($file:expr,) => ({ /* compiler built-in */ }); - } - - /// Asserts that a boolean expression is `true` at runtime. - /// - /// This will invoke the [`panic!`] macro if the provided expression cannot be - /// evaluated to `true` at runtime. - /// - /// # Uses - /// - /// Assertions are always checked in both debug and release builds, and cannot - /// be disabled. See [`debug_assert!`] for assertions that are not enabled in - /// release builds by default. - /// - /// Unsafe code relies on `assert!` to enforce run-time invariants that, if - /// violated could lead to unsafety. - /// - /// Other use-cases of `assert!` include testing and enforcing run-time - /// invariants in safe code (whose violation cannot result in unsafety). - /// - /// # Custom Messages - /// - /// This macro has a second form, where a custom panic message can - /// be provided with or without arguments for formatting. See [`std::fmt`] - /// for syntax for this form. - /// - /// [`panic!`]: macro.panic.html - /// [`debug_assert!`]: macro.debug_assert.html - /// [`std::fmt`]: ../std/fmt/index.html - /// - /// # Examples - /// - /// ``` - /// // the panic message for these assertions is the stringified value of the - /// // expression given. - /// assert!(true); - /// - /// fn some_computation() -> bool { true } // a very simple function - /// - /// assert!(some_computation()); - /// - /// // assert with a custom message - /// let x = true; - /// assert!(x, "x wasn't true!"); - /// - /// let a = 3; let b = 27; - /// assert!(a + b == 30, "a = {}, b = {}", a, b); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_builtin_macro] - macro_rules! assert { - ($cond:expr) => ({ /* compiler built-in */ }); - ($cond:expr,) => ({ /* compiler built-in */ }); - ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ }); - } -} diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index a863bebf4a264..7b12d2ee6f081 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -7,9 +7,13 @@ #![stable(feature = "rust1", since = "1.0.0")] // Re-exported core operators +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] -pub use crate::marker::{Copy, Send, Sized, Sync, Unpin}; +pub use crate::marker::Copy; +#[stable(feature = "rust1", since = "1.0.0")] +#[doc(no_inline)] +pub use crate::marker::{Send, Sized, Sync, Unpin}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; @@ -20,15 +24,18 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; pub use crate::mem::drop; // Re-exported types and traits +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::clone::Clone; +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::convert::{AsRef, AsMut, Into, From}; +#[cfg(bootstrap)] #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::default::Default; @@ -45,6 +52,60 @@ pub use crate::option::Option::{self, Some, None}; #[doc(no_inline)] pub use crate::result::Result::{self, Ok, Err}; +// Re-exported built-in macros +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use core::prelude::v1::{ + __rust_unstable_column, + asm, + assert, + cfg, + column, + compile_error, + concat, + concat_idents, + env, + file, + format_args, + format_args_nl, + global_asm, + include, + include_bytes, + include_str, + line, + log_syntax, + module_path, + option_env, + stringify, + trace_macros, +}; + +// FIXME: Attribute and derive macros are not documented because for them rustdoc generates +// dead links which fail link checker testing. +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] +#[doc(hidden)] +pub use core::prelude::v1::{ + Clone, + Copy, + Debug, + Decodable, + Default, + Encodable, + Eq, + Hash, + Ord, + PartialEq, + PartialOrd, + RustcDecodable, + RustcEncodable, + bench, + global_allocator, + test, + test_case, +}; // The file so far is equivalent to src/libcore/prelude/v1.rs, // and below to src/liballoc/prelude.rs. diff --git a/src/libstd/sys/unix/io.rs b/src/libstd/sys/unix/io.rs index 72954ff20ef95..bc854e772e16f 100644 --- a/src/libstd/sys/unix/io.rs +++ b/src/libstd/sys/unix/io.rs @@ -29,6 +29,7 @@ impl<'a> IoSlice<'a> { } } +#[repr(transparent)] pub struct IoSliceMut<'a> { vec: iovec, _p: PhantomData<&'a mut [u8]>, diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs index cc8f1e16fa01d..a5bddad708b19 100644 --- a/src/libstd/sys/wasi/io.rs +++ b/src/libstd/sys/wasi/io.rs @@ -29,6 +29,7 @@ impl<'a> IoSlice<'a> { } } +#[repr(transparent)] pub struct IoSliceMut<'a> { vec: __wasi_iovec_t, _p: PhantomData<&'a mut [u8]>, diff --git a/src/libstd/sys/windows/io.rs b/src/libstd/sys/windows/io.rs index c045a63e9118f..f0da2323f4f57 100644 --- a/src/libstd/sys/windows/io.rs +++ b/src/libstd/sys/windows/io.rs @@ -29,6 +29,7 @@ impl<'a> IoSlice<'a> { } } +#[repr(transparent)] pub struct IoSliceMut<'a> { vec: c::WSABUF, _p: PhantomData<&'a mut [u8]>, 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/base.rs b/src/libsyntax/ext/base.rs index 11b7a984aaa00..0ab14bee160da 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -592,6 +592,9 @@ pub struct SyntaxExtension { pub helper_attrs: Vec, /// Edition of the crate in which this macro is defined. pub edition: Edition, + /// Built-in macros have a couple of special properties (meaning of `$crate`, + /// availability in `#[no_implicit_prelude]` modules), so we have to keep this flag. + pub is_builtin: bool, } impl SyntaxExtensionKind { @@ -636,6 +639,7 @@ impl SyntaxExtension { deprecation: None, helper_attrs: Vec::new(), edition, + is_builtin: false, kind, } } @@ -687,7 +691,7 @@ pub trait Resolver { fn resolve_dollar_crates(&mut self); fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, derives: &[ExpnId]); - fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc); + fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); fn resolve_imports(&mut self); 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/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 817d8547e8760..2a2df76d30c1d 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -437,6 +437,7 @@ pub fn compile( deprecation: attr::find_deprecation(&sess, &def.attrs, def.span), helper_attrs: Vec::new(), edition, + is_builtin: attr::contains_name(&def.attrs, sym::rustc_builtin_macro), } } 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 16e0bace92584..36cd656f7277e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2369,22 +2369,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) => { @@ -2416,23 +2404,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(); } @@ -2458,26 +2434,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/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index e491e93256d1c..1a86509928841 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -1,11 +1,7 @@ //! The compiler code necessary to implement the `#[derive]` extensions. -use rustc_data_structures::sync::Lrc; use syntax::ast::{self, MetaItem}; -use syntax::attr::Deprecation; -use syntax::edition::Edition; -use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier}; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; +use syntax::ext::base::{Annotatable, ExtCtxt, MultiItemModifier}; use syntax::ext::build::AstBuilder; use syntax::ptr::P; use syntax::symbol::{Symbol, sym}; @@ -43,8 +39,8 @@ pub mod ord; pub mod generic; -struct BuiltinDerive( - fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)) +crate struct BuiltinDerive( + crate fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)) ); impl MultiItemModifier for BuiltinDerive { @@ -60,82 +56,6 @@ impl MultiItemModifier for BuiltinDerive { } } -macro_rules! derive_traits { - ($( [$deprecation:expr] $name:ident => $func:path, )+) => { - pub fn is_builtin_trait(name: ast::Name) -> bool { - match name { - $( sym::$name )|+ => true, - _ => false, - } - } - - pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) { - let allow_internal_unstable = Some([ - sym::core_intrinsics, - sym::rustc_attrs, - Symbol::intern("derive_clone_copy"), - Symbol::intern("derive_eq"), - Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize - ][..].into()); - - $( - resolver.add_builtin( - ast::Ident::with_empty_ctxt(sym::$name), - Lrc::new(SyntaxExtension { - deprecation: $deprecation.map(|msg| Deprecation { - since: Some(Symbol::intern("1.0.0")), - note: Some(Symbol::intern(msg)), - }), - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($func))), - edition, - ) - }), - ); - )+ - } - } -} - -derive_traits! { - [None] - Clone => clone::expand_deriving_clone, - - [None] - Hash => hash::expand_deriving_hash, - - [None] - RustcEncodable => encodable::expand_deriving_rustc_encodable, - - [None] - RustcDecodable => decodable::expand_deriving_rustc_decodable, - - [None] - PartialEq => partial_eq::expand_deriving_partial_eq, - [None] - Eq => eq::expand_deriving_eq, - [None] - PartialOrd => partial_ord::expand_deriving_partial_ord, - [None] - Ord => ord::expand_deriving_ord, - - [None] - Debug => debug::expand_deriving_debug, - - [None] - Default => default::expand_deriving_default, - - [None] - Copy => bounds::expand_deriving_copy, - - // deprecated - [Some("derive(Encodable) is deprecated in favor of derive(RustcEncodable)")] - Encodable => encodable::expand_deriving_encodable, - [Some("derive(Decodable) is deprecated in favor of derive(RustcDecodable)")] - Decodable => decodable::expand_deriving_decodable, -} - /// Construct a name for the inner type parameter that can't collide with any type parameters of /// the item. This is achieved by starting with a base and then concatenating the names of all /// other type parameters. diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 400bfe796bb07..7940abed24597 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -5,19 +5,25 @@ #![deny(rust_2018_idioms)] #![deny(unused_lifetimes)] -#![feature(in_band_lifetimes)] +#![feature(crate_visibility_modifier)] +#![feature(decl_macro)] +#![feature(nll)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] -#![feature(decl_macro)] -#![feature(nll)] #![feature(rustc_diagnostic_macros)] #![feature(unicode_internals)] -#![recursion_limit="256"] - extern crate proc_macro; +use crate::deriving::*; + +use syntax::ast::Ident; +use syntax::edition::Edition; +use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, MacroExpanderFn}; +use syntax::ext::source_util; +use syntax::symbol::sym; + mod error_codes; mod asm; @@ -38,147 +44,71 @@ mod test_case; mod trace_macros; pub mod deriving; +pub mod plugin_macro_defs; pub mod proc_macro_decls; pub mod proc_macro_impl; -use rustc_data_structures::sync::Lrc; -use syntax::ast; -use syntax::attr::Stability; -use syntax::ext::base::MacroExpanderFn; -use syntax::ext::base::{NamedSyntaxExtension, SyntaxExtension, SyntaxExtensionKind}; -use syntax::edition::Edition; -use syntax::symbol::{sym, Symbol}; - -const EXPLAIN_ASM: &str = - "inline assembly is not stable enough for use and is subject to change"; -const EXPLAIN_GLOBAL_ASM: &str = - "`global_asm!` is not stable enough for use and is subject to change"; -const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &str = - "custom test frameworks are an unstable feature"; -const EXPLAIN_LOG_SYNTAX: &str = - "`log_syntax!` is not stable enough for use and is subject to change"; -const EXPLAIN_CONCAT_IDENTS: &str = - "`concat_idents` is not stable enough for use and is subject to change"; -const EXPLAIN_FORMAT_ARGS_NL: &str = - "`format_args_nl` is only for internal language use and is subject to change"; -const EXPLAIN_TRACE_MACROS: &str = - "`trace_macros` is not stable enough for use and is subject to change"; -const EXPLAIN_UNSTABLE_COLUMN: &str = - "internal implementation detail of the `column` macro"; - -pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, - user_exts: Vec, - edition: Edition) { - deriving::register_builtin_derives(resolver, edition); - - let mut register = |name, ext| { - resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext)); - }; - - macro_rules! register { - ($( $name:ident: $f:expr, )*) => { $( - register(sym::$name, SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition - )); - )* } +pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, edition: Edition) { + let mut register = |name, kind| resolver.register_builtin_macro( + Ident::with_empty_ctxt(name), SyntaxExtension { + is_builtin: true, ..SyntaxExtension::default(kind, edition) + }, + ); + macro register_bang($($name:ident: $f:expr,)*) { + $(register(sym::$name, SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)));)* + } + macro register_attr($($name:ident: $f:expr,)*) { + $(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Box::new($f)));)* } - macro_rules! register_unstable { - ($( [$feature:expr, $reason:expr, $issue:expr] $name:ident: $f:expr, )*) => { $( - register(sym::$name, SyntaxExtension { - stability: Some(Stability::unstable( - $feature, Some(Symbol::intern($reason)), $issue - )), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition - ) - }); - )* } + macro register_derive($($name:ident: $f:expr,)*) { + $(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($f))));)* } - use syntax::ext::source_util::*; - register! { - line: expand_line, - column: expand_column, - file: expand_file, - stringify: expand_stringify, - include: expand_include, - include_str: expand_include_str, - include_bytes: expand_include_bytes, - module_path: expand_mod, + register_bang! { + __rust_unstable_column: source_util::expand_column, + asm: asm::expand_asm, + assert: assert::expand_assert, cfg: cfg::expand_cfg, + column: source_util::expand_column, + compile_error: compile_error::expand_compile_error, + concat_idents: concat_idents::expand_syntax_ext, concat: concat::expand_syntax_ext, env: env::expand_env, - option_env: env::expand_option_env, - compile_error: compile_error::expand_compile_error, - assert: assert::expand_assert, - } - - register_unstable! { - [sym::__rust_unstable_column, EXPLAIN_UNSTABLE_COLUMN, 0] - __rust_unstable_column: expand_column, - [sym::asm, EXPLAIN_ASM, 29722] - asm: asm::expand_asm, - [sym::global_asm, EXPLAIN_GLOBAL_ASM, 35119] + file: source_util::expand_file, + format_args_nl: format::expand_format_args_nl, + format_args: format::expand_format_args, global_asm: global_asm::expand_global_asm, - [sym::concat_idents, EXPLAIN_CONCAT_IDENTS, 29599] - concat_idents: concat_idents::expand_syntax_ext, - [sym::log_syntax, EXPLAIN_LOG_SYNTAX, 29598] + include_bytes: source_util::expand_include_bytes, + include_str: source_util::expand_include_str, + include: source_util::expand_include, + line: source_util::expand_line, log_syntax: log_syntax::expand_syntax_ext, - [sym::trace_macros, EXPLAIN_TRACE_MACROS, 29598] + module_path: source_util::expand_mod, + option_env: env::expand_option_env, + stringify: source_util::expand_stringify, trace_macros: trace_macros::expand_trace_macros, } - let allow_internal_unstable = Some([sym::test, sym::rustc_attrs][..].into()); - register(sym::test_case, SyntaxExtension { - stability: Some(Stability::unstable( - sym::custom_test_frameworks, - Some(Symbol::intern(EXPLAIN_CUSTOM_TEST_FRAMEWORKS)), - 50297, - )), - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(test_case::expand)), edition - ) - }); - register(sym::test, SyntaxExtension { - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_test)), edition - ) - }); - register(sym::bench, SyntaxExtension { - allow_internal_unstable, - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_bench)), edition - ) - }); - register(sym::global_allocator, SyntaxExtension { - allow_internal_unstable: Some([sym::rustc_attrs][..].into()), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyAttr(Box::new(global_allocator::expand)), edition - ) - }); - - let allow_internal_unstable = Some([sym::fmt_internals][..].into()); - register(sym::format_args, SyntaxExtension { - allow_internal_unstable: allow_internal_unstable.clone(), - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition - ) - }); - register(sym::format_args_nl, SyntaxExtension { - stability: Some(Stability::unstable( - sym::format_args_nl, - Some(Symbol::intern(EXPLAIN_FORMAT_ARGS_NL)), - 0, - )), - allow_internal_unstable, - ..SyntaxExtension::default( - SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition - ) - }); + register_attr! { + bench: test::expand_bench, + global_allocator: global_allocator::expand, + test: test::expand_test, + test_case: test_case::expand, + } - for (name, ext) in user_exts { - register(name, ext); + register_derive! { + Clone: clone::expand_deriving_clone, + Copy: bounds::expand_deriving_copy, + Debug: debug::expand_deriving_debug, + Decodable: decodable::expand_deriving_decodable, + Default: default::expand_deriving_default, + Encodable: encodable::expand_deriving_encodable, + Eq: eq::expand_deriving_eq, + Hash: hash::expand_deriving_hash, + Ord: ord::expand_deriving_ord, + PartialEq: partial_eq::expand_deriving_partial_eq, + PartialOrd: partial_ord::expand_deriving_partial_ord, + RustcDecodable: decodable::expand_deriving_rustc_decodable, + RustcEncodable: encodable::expand_deriving_rustc_encodable, } } diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs new file mode 100644 index 0000000000000..2fd1a42db95f3 --- /dev/null +++ b/src/libsyntax_ext/plugin_macro_defs.rs @@ -0,0 +1,64 @@ +//! Each macro must have a definition, so `#[plugin]` attributes +//! inject a dummy `macro_rules` item for each macro they define. + +use syntax::ast::*; +use syntax::attr; +use syntax::edition::Edition; +use syntax::ext::base::{Resolver, NamedSyntaxExtension}; +use syntax::parse::token; +use syntax::ptr::P; +use syntax::source_map::respan; +use syntax::symbol::sym; +use syntax::tokenstream::*; +use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::hygiene::{ExpnId, ExpnInfo, ExpnKind, MacroKind}; + +use std::mem; + +fn plugin_macro_def(name: Name, span: Span) -> P { + let rustc_builtin_macro = Attribute { + id: attr::mk_attr_id(), + style: AttrStyle::Outer, + path: Path::from_ident(Ident::new(sym::rustc_builtin_macro, span)), + tokens: TokenStream::empty(), + is_sugared_doc: false, + span, + }; + + let parens: TreeAndJoint = TokenTree::Delimited( + DelimSpan::from_single(span), token::Paren, TokenStream::empty() + ).into(); + let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens]; + + P(Item { + ident: Ident::new(name, span), + attrs: vec![rustc_builtin_macro], + id: DUMMY_NODE_ID, + node: ItemKind::MacroDef(MacroDef { tokens: TokenStream::new(trees), legacy: true }), + vis: respan(span, VisibilityKind::Inherited), + span: span, + tokens: None, + }) +} + +pub fn inject( + krate: &mut Crate, + resolver: &mut dyn Resolver, + named_exts: Vec, + edition: Edition, +) { + if !named_exts.is_empty() { + let mut extra_items = Vec::new(); + let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( + ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition, + [sym::rustc_attrs][..].into(), + )); + for (name, ext) in named_exts { + resolver.register_builtin_macro(Ident::with_empty_ctxt(name), ext); + extra_items.push(plugin_macro_def(name, span)); + } + // The `macro_rules` items must be inserted before any other items. + mem::swap(&mut extra_items, &mut krate.module.items); + krate.module.items.append(&mut extra_items); + } +} diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index 08c40dde56c85..303d5f00deb1a 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -1,7 +1,5 @@ use std::mem; -use crate::deriving; - use syntax::ast::{self, Ident}; use syntax::attr; use syntax::source_map::{ExpnInfo, ExpnKind, respan}; @@ -136,10 +134,6 @@ impl<'a> CollectProcMacros<'a> { self.handler.span_err(trait_attr.span, &format!("`{}` cannot be a name of derive macro", trait_ident)); } - if deriving::is_builtin_trait(trait_ident.name) { - self.handler.span_err(trait_attr.span, - "cannot override a built-in derive macro"); - } let attributes_attr = list.get(1); let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { 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/run-make-fulldeps/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs index b834e5cc463a4..75d95a4eaf146 100644 --- a/src/test/run-make-fulldeps/simd-ffi/simd.rs +++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs @@ -5,7 +5,7 @@ #![feature(no_core, optin_builtin_traits)] #![no_core] -#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items)] +#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)] #[repr(C)] @@ -74,3 +74,7 @@ pub mod marker { #[lang = "freeze"] auto trait Freeze {} + +#[macro_export] +#[rustc_builtin_macro] +macro_rules! Copy { () => () } diff --git a/src/test/run-pass/array-slice-vec/vec-matching-fold.rs b/src/test/run-pass/array-slice-vec/vec-matching-fold.rs index 2b19c49c42700..f416160db2422 100644 --- a/src/test/run-pass/array-slice-vec/vec-matching-fold.rs +++ b/src/test/run-pass/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/run-pass/array-slice-vec/vec-matching-legal-tail-element-borrow.rs b/src/test/run-pass/array-slice-vec/vec-matching-legal-tail-element-borrow.rs index bce03b3375e51..f0602c328b071 100644 --- a/src/test/run-pass/array-slice-vec/vec-matching-legal-tail-element-borrow.rs +++ b/src/test/run-pass/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/run-pass/array-slice-vec/vec-matching.rs b/src/test/run-pass/array-slice-vec/vec-matching.rs index a37c25160fa76..49c736bd72847 100644 --- a/src/test/run-pass/array-slice-vec/vec-matching.rs +++ b/src/test/run-pass/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/run-pass/array-slice-vec/vec-tail-matching.rs b/src/test/run-pass/array-slice-vec/vec-tail-matching.rs index 84d246dff825c..3c7b160dcc540 100644 --- a/src/test/run-pass/array-slice-vec/vec-tail-matching.rs +++ b/src/test/run-pass/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/run-pass/binding/irrefutable-slice-patterns.rs b/src/test/run-pass/binding/irrefutable-slice-patterns.rs index 733e6b7b57f72..ac733ef6e9c86 100644 --- a/src/test/run-pass/binding/irrefutable-slice-patterns.rs +++ b/src/test/run-pass/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/run-pass/binding/zero_sized_subslice_match.rs b/src/test/run-pass/binding/zero_sized_subslice_match.rs index 51e1c024bffff..5326fa612a87b 100644 --- a/src/test/run-pass/binding/zero_sized_subslice_match.rs +++ b/src/test/run-pass/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/run-pass/borrowck/borrowck-slice-pattern-element-loan.rs b/src/test/run-pass/borrowck/borrowck-slice-pattern-element-loan.rs index 7675147c8ec2a..048813b2b93e6 100644 --- a/src/test/run-pass/borrowck/borrowck-slice-pattern-element-loan.rs +++ b/src/test/run-pass/borrowck/borrowck-slice-pattern-element-loan.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/run-pass/drop/dynamic-drop-async.rs b/src/test/run-pass/drop/dynamic-drop-async.rs index 9226145d9354d..f3f5c382275fe 100644 --- a/src/test/run-pass/drop/dynamic-drop-async.rs +++ b/src/test/run-pass/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/run-pass/drop/dynamic-drop.rs b/src/test/run-pass/drop/dynamic-drop.rs index eb1a3f3a9f9cb..8516bc3d96424 100644 --- a/src/test/run-pass/drop/dynamic-drop.rs +++ b/src/test/run-pass/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/run-pass/issues/issue-15080.rs b/src/test/run-pass/issues/issue-15080.rs index 4558118a8091c..b11b1cda38ae1 100644 --- a/src/test/run-pass/issues/issue-15080.rs +++ b/src/test/run-pass/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/run-pass/issues/issue-15104.rs b/src/test/run-pass/issues/issue-15104.rs index 3a03a52c32485..ee977541137db 100644 --- a/src/test/run-pass/issues/issue-15104.rs +++ b/src/test/run-pass/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/run-pass/issues/issue-17877.rs b/src/test/run-pass/issues/issue-17877.rs index af22b1ad8f0bc..fefa3f2f87304 100644 --- a/src/test/run-pass/issues/issue-17877.rs +++ b/src/test/run-pass/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/run-pass/issues/issue-7784.rs b/src/test/run-pass/issues/issue-7784.rs index b75e547079ef5..5b70bd6e5ff54 100644 --- a/src/test/run-pass/issues/issue-7784.rs +++ b/src/test/run-pass/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/run-pass/rfcs/rfc-2005-default-binding-mode/slice.rs b/src/test/run-pass/rfcs/rfc-2005-default-binding-mode/slice.rs index 939a3c4a1fd7a..38b0941aad0a6 100644 --- a/src/test/run-pass/rfcs/rfc-2005-default-binding-mode/slice.rs +++ b/src/test/run-pass/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/run-pass/trailing-comma.rs b/src/test/run-pass/trailing-comma.rs index 197af295a42c7..45029721c5100 100644 --- a/src/test/run-pass/trailing-comma.rs +++ b/src/test/run-pass/trailing-comma.rs @@ -24,7 +24,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/test/rustdoc/intra-link-builtin-macros.rs b/src/test/rustdoc/intra-link-builtin-macros.rs new file mode 100644 index 0000000000000..4d40eb3b88f1b --- /dev/null +++ b/src/test/rustdoc/intra-link-builtin-macros.rs @@ -0,0 +1,3 @@ +// @has intra_link_builtin_macros/index.html +// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/core/macro.cfg.html' +//! [cfg] diff --git a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs index 86441b4f73548..c2685c7f74c30 100644 --- a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs @@ -3,20 +3,21 @@ #![feature(plugin_registrar)] #![feature(rustc_private)] -extern crate syntax; - -extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; +extern crate rustc_plugin; +extern crate syntax; -use syntax::symbol::Symbol; -use syntax::feature_gate::AttributeType; use rustc_plugin::Registry; - +use syntax::ext::base::SyntaxExtension; +use syntax::feature_gate::AttributeType; +use syntax::symbol::Symbol; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_attribute(Symbol::intern("foo"), AttributeType::Normal); reg.register_attribute(Symbol::intern("bar"), AttributeType::CrateLevel); reg.register_attribute(Symbol::intern("baz"), AttributeType::Whitelisted); + reg.register_syntax_extension( + Symbol::intern("mac"), SyntaxExtension::dummy_bang(reg.sess.edition()) + ); } diff --git a/src/test/ui-fulldeps/deprecated-derive.stderr b/src/test/ui-fulldeps/deprecated-derive.stderr index efaf82d9be165..1518c0cc541d2 100644 --- a/src/test/ui-fulldeps/deprecated-derive.stderr +++ b/src/test/ui-fulldeps/deprecated-derive.stderr @@ -2,7 +2,7 @@ warning: use of deprecated item 'Encodable': derive(Encodable) is deprecated in --> $DIR/deprecated-derive.rs:8:10 | LL | #[derive(Encodable)] - | ^^^^^^^^^ + | ^^^^^^^^^ help: replace the use of the deprecated item: `RustcEncodable` | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/plugin-reexport.rs b/src/test/ui-fulldeps/plugin-reexport.rs new file mode 100644 index 0000000000000..4d8ede1680830 --- /dev/null +++ b/src/test/ui-fulldeps/plugin-reexport.rs @@ -0,0 +1,10 @@ +// edition:2018 +// aux-build:attr-plugin-test.rs +// ignore-stage1 + +#![feature(plugin)] +#![plugin(attr_plugin_test)] + +pub use mac as reexport; //~ ERROR `mac` is private, and cannot be re-exported + +fn main() {} diff --git a/src/test/ui-fulldeps/plugin-reexport.stderr b/src/test/ui-fulldeps/plugin-reexport.stderr new file mode 100644 index 0000000000000..4ac64b8d04b87 --- /dev/null +++ b/src/test/ui-fulldeps/plugin-reexport.stderr @@ -0,0 +1,15 @@ +error[E0364]: `mac` is private, and cannot be re-exported + --> $DIR/plugin-reexport.rs:8:9 + | +LL | pub use mac as reexport; + | ^^^^^^^^^^^^^^^ + | +note: consider marking `mac` as `pub` in the imported module + --> $DIR/plugin-reexport.rs:8:9 + | +LL | pub use mac as reexport; + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0364`. 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/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.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/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-gate/issue-43106-gating-of-bench.rs b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs index 2d8868995f435..31eee88d1fac6 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs @@ -1,17 +1,10 @@ -// error-pattern: `main` function not found - -// At time of authorship, a crate-level #![bench] with no `--test` -// will cause compilation to error unconditionally with "main function -// not found" (despite having one), similar to #[bench]. -// -// (The non-crate level cases are in -// issue-43106-gating-of-builtin-attrs.rs.) - +// The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs. // See issue-12997-1.rs and issue-12997-2.rs to see how `#[bench]` is // handled in "weird places" when `--test` is passed. #![feature(custom_inner_attributes)] #![bench = "4100"] +//~^ ERROR cannot determine resolution for the attribute macro `bench` -fn main() { } +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr index 37b5e792dc239..d0305c5160f7e 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr @@ -1,17 +1,10 @@ -warning: attribute must be of the form `#[bench]` - --> $DIR/issue-43106-gating-of-bench.rs:15:1 +error: cannot determine resolution for the attribute macro `bench` + --> $DIR/issue-43106-gating-of-bench.rs:7:4 | LL | #![bench = "4100"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ | - = note: `#[warn(ill_formed_attribute_input)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 - -error[E0601]: `main` function not found in crate `issue_43106_gating_of_bench` - | - = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-bench.rs` + = note: import resolution is stuck, try simplifying macro imports error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs index c0c49d353007c..d343746955f39 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs @@ -1,12 +1,6 @@ -// error-pattern: `main` function not found - -// At time of authorship, crate-level #[test] attribute with no -// `--test` signals unconditional error complaining of missing main -// function (despite having one), similar to #[bench]. -// -// (The non-crate level cases are in -// issue-43106-gating-of-builtin-attrs.rs.) +// The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs. #![test = "4200"] +//~^ ERROR cannot determine resolution for the attribute macro `test` -fn main() { } +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr index dbffabf3e02f9..a7d3a1e16840e 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr @@ -1,17 +1,10 @@ -warning: attribute must be of the form `#[test]` - --> $DIR/issue-43106-gating-of-test.rs:10:1 +error: cannot determine resolution for the attribute macro `test` + --> $DIR/issue-43106-gating-of-test.rs:3:4 | LL | #![test = "4200"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ | - = note: `#[warn(ill_formed_attribute_input)]` on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57571 - -error[E0601]: `main` function not found in crate `issue_43106_gating_of_test` - | - = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-test.rs` + = note: import resolution is stuck, try simplifying macro imports error: aborting due to previous error -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs index 827ac3af8f1fa..506b21dc7d544 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs @@ -1,4 +1,4 @@ -#![feature(intrinsics, lang_items, no_core)] +#![feature(intrinsics, lang_items, no_core, rustc_attrs)] #![crate_type="rlib"] #![no_core] @@ -88,3 +88,7 @@ fn main() { cfg!(target_has_atomic = "ptr"); //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change } + +#[macro_export] +#[rustc_builtin_macro] +macro_rules! cfg { () => () } 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/imports/glob-shadowing.stderr b/src/test/ui/imports/glob-shadowing.stderr index 7962fcb9aec1d..4ef446f93c860 100644 --- a/src/test/ui/imports/glob-shadowing.stderr +++ b/src/test/ui/imports/glob-shadowing.stderr @@ -4,7 +4,7 @@ error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope LL | let x = env!("PATH"); | ^^^ ambiguous name | - = note: `env` could refer to a built-in macro + = note: `env` could refer to a macro from prelude note: `env` could also refer to the macro imported here --> $DIR/glob-shadowing.rs:9:9 | @@ -19,7 +19,7 @@ error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope LL | let x = env!("PATH"); | ^^^ ambiguous name | - = note: `env` could refer to a built-in macro + = note: `env` could refer to a macro from prelude note: `env` could also refer to the macro imported here --> $DIR/glob-shadowing.rs:17:13 | diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr index 13d3227d8b38f..5afdd8889ae7d 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -27,7 +27,7 @@ error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded LL | include!(); | ^^^^^^^ ambiguous name | - = note: `include` could refer to a built-in macro + = note: `include` could refer to a macro from prelude note: `include` could also refer to the macro defined here --> $DIR/local-modularized-tricky-fail-1.rs:17:5 | 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-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-28134.rs b/src/test/ui/issues/issue-28134.rs index 2bd4f93791d38..fa692db4bf66c 100644 --- a/src/test/ui/issues/issue-28134.rs +++ b/src/test/ui/issues/issue-28134.rs @@ -1,3 +1,3 @@ // compile-flags: --test -#![test] //~ ERROR only functions may be used as tests +#![test] //~ ERROR cannot determine resolution for the attribute macro `test` diff --git a/src/test/ui/issues/issue-28134.stderr b/src/test/ui/issues/issue-28134.stderr index b9189480048d8..5f8d27dd043b1 100644 --- a/src/test/ui/issues/issue-28134.stderr +++ b/src/test/ui/issues/issue-28134.stderr @@ -1,8 +1,10 @@ -error: only functions may be used as tests - --> $DIR/issue-28134.rs:3:1 +error: cannot determine resolution for the attribute macro `test` + --> $DIR/issue-28134.rs:3:4 | LL | #![test] - | ^^^^^^^^ + | ^^^^ + | + = note: import resolution is stuck, try simplifying macro imports error: aborting due to previous error 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/macros/unknown-builtin.rs b/src/test/ui/macros/unknown-builtin.rs new file mode 100644 index 0000000000000..a96b99ae4ff78 --- /dev/null +++ b/src/test/ui/macros/unknown-builtin.rs @@ -0,0 +1,14 @@ +// error-pattern: cannot find a built-in macro with name `line` + +#![feature(rustc_attrs)] + +#[rustc_builtin_macro] +macro_rules! unknown { () => () } //~ ERROR cannot find a built-in macro with name `unknown` + +#[rustc_builtin_macro] +macro_rules! line { () => () } + +fn main() { + line!(); + std::prelude::v1::line!(); +} diff --git a/src/test/ui/macros/unknown-builtin.stderr b/src/test/ui/macros/unknown-builtin.stderr new file mode 100644 index 0000000000000..33b7b055b4e4b --- /dev/null +++ b/src/test/ui/macros/unknown-builtin.stderr @@ -0,0 +1,14 @@ +error: cannot find a built-in macro with name `unknown` + --> $DIR/unknown-builtin.rs:6:1 + | +LL | macro_rules! unknown { () => () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find a built-in macro with name `line` + --> <::core::macros::builtin::line macros>:1:1 + | +LL | () => { } + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + 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/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs index 04c88dcef50ac..5531b32362125 100644 --- a/src/test/ui/proc-macro/attribute.rs +++ b/src/test/ui/proc-macro/attribute.rs @@ -40,8 +40,7 @@ pub fn foo8(input: TokenStream) -> TokenStream { input } //~^ ERROR: `self` cannot be a name of derive macro pub fn foo9(input: TokenStream) -> TokenStream { input } -#[proc_macro_derive(PartialEq)] -//~^ ERROR: cannot override a built-in derive macro +#[proc_macro_derive(PartialEq)] // OK pub fn foo10(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d11, a)] diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr index e632875cb16e5..1503f62cb6c1a 100644 --- a/src/test/ui/proc-macro/attribute.stderr +++ b/src/test/ui/proc-macro/attribute.stderr @@ -40,56 +40,50 @@ error: `self` cannot be a name of derive macro LL | #[proc_macro_derive(self)] | ^^^^ -error: cannot override a built-in derive macro - --> $DIR/attribute.rs:43:21 - | -LL | #[proc_macro_derive(PartialEq)] - | ^^^^^^^^^ - error: second argument must be `attributes` - --> $DIR/attribute.rs:47:26 + --> $DIR/attribute.rs:46:26 | LL | #[proc_macro_derive(d11, a)] | ^ error: attribute must be of form: `attributes(foo, bar)` - --> $DIR/attribute.rs:47:26 + --> $DIR/attribute.rs:46:26 | LL | #[proc_macro_derive(d11, a)] | ^ error: attribute must be of form: `attributes(foo, bar)` - --> $DIR/attribute.rs:52:26 + --> $DIR/attribute.rs:51:26 | LL | #[proc_macro_derive(d12, attributes)] | ^^^^^^^^^^ error: not a meta item - --> $DIR/attribute.rs:56:37 + --> $DIR/attribute.rs:55:37 | LL | #[proc_macro_derive(d13, attributes("a"))] | ^^^ error: must only be one word - --> $DIR/attribute.rs:60:37 + --> $DIR/attribute.rs:59:37 | LL | #[proc_macro_derive(d14, attributes(a = ""))] | ^^^^^^ error: must only be one word - --> $DIR/attribute.rs:64:37 + --> $DIR/attribute.rs:63:37 | LL | #[proc_macro_derive(d15, attributes(m::a))] | ^^^^ error: must only be one word - --> $DIR/attribute.rs:68:37 + --> $DIR/attribute.rs:67:37 | LL | #[proc_macro_derive(d16, attributes(a(b)))] | ^^^^ error: `self` cannot be a name of derive helper attribute - --> $DIR/attribute.rs:72:37 + --> $DIR/attribute.rs:71:37 | LL | #[proc_macro_derive(d17, attributes(self))] | ^^^^ @@ -106,5 +100,5 @@ error: malformed `proc_macro_derive` attribute input LL | #[proc_macro_derive = ""] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors 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/rfc-2126-extern-absolute-paths/not-whitelisted.rs b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs index dd21de75aaf75..acb4bbebe7f53 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs @@ -3,7 +3,7 @@ // Tests that arbitrary crates (other than `core`, `std` and `meta`) // aren't allowed without `--extern`, even if they're in the sysroot. use alloc; //~ ERROR unresolved import `alloc` -use test; //~ ERROR cannot import a built-in macro +use test; // OK, imports the built-in attribute macro `#[test]`, but not the `test` crate. use proc_macro; // OK, imports the built-in `proc_macro` attribute, but not the `proc_macro` crate. fn main() {} diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr index 4e3fff98e6f4b..f324378d4ca68 100644 --- a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr +++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr @@ -1,15 +1,9 @@ -error: cannot import a built-in macro - --> $DIR/not-whitelisted.rs:6:5 - | -LL | use test; - | ^^^^ - error[E0432]: unresolved import `alloc` --> $DIR/not-whitelisted.rs:5:5 | LL | use alloc; | ^^^^^ no `alloc` external crate -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs b/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs index d717884c901b3..48c33d720dcad 100644 --- a/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs +++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs @@ -1,11 +1,6 @@ // edition:2018 -// Built-in macro -use env as env_imported; //~ ERROR cannot import a built-in macro - // Tool attribute use rustfmt::skip as imported_rustfmt_skip; //~ ERROR unresolved import `rustfmt` -fn main() { - env_imported!("PATH"); -} +fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr index 42daf7c6fb12f..97d4c736751aa 100644 --- a/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr +++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr @@ -1,15 +1,9 @@ -error: cannot import a built-in macro - --> $DIR/prelude-fail.rs:4:5 - | -LL | use env as env_imported; - | ^^^^^^^^^^^^^^^^^^^ - error[E0432]: unresolved import `rustfmt` - --> $DIR/prelude-fail.rs:7:5 + --> $DIR/prelude-fail.rs:4:5 | LL | use rustfmt::skip as imported_rustfmt_skip; | ^^^^^^^ `rustfmt` is a tool module, not a module -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/uniform-paths/prelude.rs b/src/test/ui/rust-2018/uniform-paths/prelude.rs index dca9587c5d369..65763614ce028 100644 --- a/src/test/ui/rust-2018/uniform-paths/prelude.rs +++ b/src/test/ui/rust-2018/uniform-paths/prelude.rs @@ -10,9 +10,13 @@ use Vec as ImportedVec; // Built-in type use u8 as imported_u8; +// Built-in macro +use env as env_imported; + type A = imported_u8; fn main() { imported_vec![0]; ImportedVec::::new(); + env_imported!("PATH"); } diff --git a/src/test/ui/rust-unstable-column-gated.stderr b/src/test/ui/rust-unstable-column-gated.stderr index c581a16dbb038..7db1b01fb0e63 100644 --- a/src/test/ui/rust-unstable-column-gated.stderr +++ b/src/test/ui/rust-unstable-column-gated.stderr @@ -1,4 +1,4 @@ -error[E0658]: use of unstable library feature '__rust_unstable_column': internal implementation detail of the `column` macro +error[E0658]: use of unstable library feature '__rust_unstable_column': internal implementation detail of the `panic` macro --> $DIR/rust-unstable-column-gated.rs:2:20 | LL | println!("{}", __rust_unstable_column!()); diff --git a/src/test/ui/suggestions/auxiliary/issue-61963-1.rs b/src/test/ui/suggestions/auxiliary/issue-61963-1.rs new file mode 100644 index 0000000000000..6c2df7e84e07c --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/issue-61963-1.rs @@ -0,0 +1,40 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Group, TokenStream, TokenTree}; + +// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2. + +#[proc_macro_derive(DomObject)] +pub fn expand_token_stream(input: TokenStream) -> TokenStream { + // Construct a dummy span - `#0 bytes(0..0)` - which is present in the input because + // of the specially crafted generated tokens in the `attribute-crate` proc-macro. + let dummy_span = input.clone().into_iter().nth(0).unwrap().span(); + + // Define what the macro would output if constructed properly from the source using syn/quote. + let output: TokenStream = "impl Bar for ((), Qux >) { } + impl Bar for ((), Box) { }".parse().unwrap(); + + let mut tokens: Vec<_> = output.into_iter().collect(); + // Adjust token spans to match the original crate (which would use `quote`). Some of the + // generated tokens point to the dummy span. + for token in tokens.iter_mut() { + if let TokenTree::Group(group) = token { + let mut tokens: Vec<_> = group.stream().into_iter().collect(); + for token in tokens.iter_mut().skip(2) { + token.set_span(dummy_span); + } + + let mut stream = TokenStream::new(); + stream.extend(tokens); + *group = Group::new(group.delimiter(), stream); + } + } + + let mut output = TokenStream::new(); + output.extend(tokens); + output +} diff --git a/src/test/ui/suggestions/auxiliary/issue-61963.rs b/src/test/ui/suggestions/auxiliary/issue-61963.rs new file mode 100644 index 0000000000000..e86f1610ab0d0 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/issue-61963.rs @@ -0,0 +1,41 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Group, Spacing, Punct, TokenTree, TokenStream}; + +// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2. + +#[proc_macro_attribute] +pub fn dom_struct(_: TokenStream, input: TokenStream) -> TokenStream { + // Construct the expected output tokens - the input but with a `#[derive(DomObject)]` applied. + let attributes: TokenStream = + "#[derive(DomObject)]".to_string().parse().unwrap(); + let output: TokenStream = attributes.into_iter() + .chain(input.into_iter()).collect(); + + let mut tokens: Vec<_> = output.into_iter().collect(); + // Adjust the spacing of `>` tokens to match what `quote` would produce. + for token in tokens.iter_mut() { + if let TokenTree::Group(group) = token { + let mut tokens: Vec<_> = group.stream().into_iter().collect(); + for token in tokens.iter_mut() { + if let TokenTree::Punct(p) = token { + if p.as_char() == '>' { + *p = Punct::new('>', Spacing::Alone); + } + } + } + + let mut stream = TokenStream::new(); + stream.extend(tokens); + *group = Group::new(group.delimiter(), stream); + } + } + + let mut output = TokenStream::new(); + output.extend(tokens); + output +} diff --git a/src/test/ui/suggestions/issue-61963.rs b/src/test/ui/suggestions/issue-61963.rs new file mode 100644 index 0000000000000..c9d738f5a283e --- /dev/null +++ b/src/test/ui/suggestions/issue-61963.rs @@ -0,0 +1,24 @@ +// aux-build:issue-61963.rs +// aux-build:issue-61963-1.rs +#![deny(bare_trait_objects)] + +#[macro_use] +extern crate issue_61963; +#[macro_use] +extern crate issue_61963_1; + +// This test checks that the bare trait object lint does not trigger on macro attributes that +// generate code which would trigger the lint. + +pub struct Baz; +pub trait Bar { } +pub struct Qux(T); + +#[dom_struct] +pub struct Foo { + qux: Qux>, + bar: Box, + //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-61963.stderr b/src/test/ui/suggestions/issue-61963.stderr new file mode 100644 index 0000000000000..46943f40066ff --- /dev/null +++ b/src/test/ui/suggestions/issue-61963.stderr @@ -0,0 +1,14 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:20:14 + | +LL | bar: Box, + | ^^^ help: use `dyn`: `dyn Bar` + | +note: lint level defined here + --> $DIR/issue-61963.rs:3:9 + | +LL | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error +