From 953f6ecb6adc37b4f8e52102c1e7ca86cc5bc92c Mon Sep 17 00:00:00 2001 From: Mikhail Babenko Date: Fri, 7 Feb 2020 23:38:13 +0300 Subject: [PATCH 01/27] fix lifetime shadowing check in GATs --- src/librustc_resolve/lifetimes.rs | 6 ++++-- .../ui/generic-associated-types/shadowing.rs | 4 ++-- .../generic-associated-types/shadowing.stderr | 21 +++++++++++++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs index 0ba9b4f17068e..c527d6050cabc 100644 --- a/src/librustc_resolve/lifetimes.rs +++ b/src/librustc_resolve/lifetimes.rs @@ -747,7 +747,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: true, }; - self.with(scope, |_old_scope, this| { + self.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &generics.params); this.visit_generics(generics); for bound in bounds { this.visit_param_bound(bound); @@ -804,7 +805,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: true, }; - self.with(scope, |_old_scope, this| { + self.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &generics.params); this.visit_generics(generics); this.visit_ty(ty); }); diff --git a/src/test/ui/generic-associated-types/shadowing.rs b/src/test/ui/generic-associated-types/shadowing.rs index 7277c0d87c6ff..5c308948bd3f8 100644 --- a/src/test/ui/generic-associated-types/shadowing.rs +++ b/src/test/ui/generic-associated-types/shadowing.rs @@ -2,8 +2,8 @@ #![feature(generic_associated_types)] trait Shadow<'a> { - //FIXME(#44265): The lifetime parameter shadowing should cause an error. type Bar<'a>; + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope } trait NoShadow<'a> { @@ -11,8 +11,8 @@ trait NoShadow<'a> { } impl<'a> NoShadow<'a> for &'a u32 { - //FIXME(#44265): The lifetime parameter shadowing should cause an error. type Bar<'a> = i32; + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope } trait ShadowT { diff --git a/src/test/ui/generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr index 50c12e822e7db..1cb6f071f3a19 100644 --- a/src/test/ui/generic-associated-types/shadowing.stderr +++ b/src/test/ui/generic-associated-types/shadowing.stderr @@ -14,6 +14,22 @@ LL | impl NoShadowT for Option { LL | type Bar = i32; | ^ already used +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/shadowing.rs:5:14 + | +LL | trait Shadow<'a> { + | -- first declared here +LL | type Bar<'a>; + | ^^ lifetime 'a already in scope + +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/shadowing.rs:14:14 + | +LL | impl<'a> NoShadow<'a> for &'a u32 { + | -- first declared here +LL | type Bar<'a> = i32; + | ^^ lifetime 'a already in scope + error: type-generic associated types are not yet implemented --> $DIR/shadowing.rs:19:5 | @@ -30,6 +46,7 @@ LL | type Bar; // OK | = note: for more information, see https://github.com/rust-lang/rust/issues/44265 -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0403`. +Some errors have detailed explanations: E0403, E0496. +For more information about an error, try `rustc --explain E0403`. From 91b4a24219f33b7ad28b5ba147d50bc160c6f56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 13 Feb 2020 00:00:00 +0000 Subject: [PATCH 02/27] Enable use after scope detection in the new LLVM pass manager Implementation of 08a1c566a792dcf9657d293155f7ada87746bb65 for the new LLVM pass manager, support for which landed in the meantime. --- src/rustllvm/PassWrapper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 15e2251d76321..8cebcaccfaad7 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -761,14 +761,14 @@ LLVMRustOptimizeWithNewPassManager( } if (SanitizerOptions->SanitizeAddress) { - // FIXME: Rust does not expose the UseAfterScope option. PipelineStartEPCallbacks.push_back([&](ModulePassManager &MPM) { MPM.addPass(RequireAnalysisPass()); }); OptimizerLastEPCallbacks.push_back( [SanitizerOptions](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(AddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeRecover)); + /*CompileKernel=*/false, SanitizerOptions->SanitizeRecover, + /*UseAfterScope=*/true)); } ); PipelineStartEPCallbacks.push_back( From 57a62f5335c1e8178802d00dfac94212726ee240 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Thu, 13 Feb 2020 10:16:28 +0100 Subject: [PATCH 03/27] Add comment to SGX entry code --- src/libstd/sys/sgx/abi/entry.S | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index ed4db287229dc..1f06c9da3a993 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -151,6 +151,7 @@ elf_entry: pushfq andq $~0x40400, (%rsp) popfq +/* check for abort */ bt $0,.Laborted(%rip) jc .Lreentry_panic .endm From 4f17dce4dc722e56d5d5069e7317feb17c1de5cc Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 07:15:43 +0100 Subject: [PATCH 04/27] StripUnconfigured::in_cfg: simplify with slice patterns --- src/librustc_parse/config.rs | 52 +++++++++++------------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 8dec64c579e88..3c37501be4162 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -347,7 +347,13 @@ impl<'a> StripUnconfigured<'a> { if !is_cfg(attr) { return true; } - + let meta_item = match validate_attr::parse_meta(self.sess, attr) { + Ok(meta_item) => meta_item, + Err(mut err) => { + err.emit(); + return true; + } + }; let error = |span, msg, suggestion: &str| { let mut err = self.sess.span_diagnostic.struct_span_err(span, msg); if !suggestion.is_empty() { @@ -361,41 +367,15 @@ impl<'a> StripUnconfigured<'a> { err.emit(); true }; - - let meta_item = match validate_attr::parse_meta(self.sess, attr) { - Ok(meta_item) => meta_item, - Err(mut err) => { - err.emit(); - return true; - } - }; - let nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() { - nested_meta_items - } else { - return error( - meta_item.span, - "`cfg` is not followed by parentheses", - "cfg(/* predicate */)", - ); - }; - - if nested_meta_items.is_empty() { - return error(meta_item.span, "`cfg` predicate is not specified", ""); - } else if nested_meta_items.len() > 1 { - return error( - nested_meta_items.last().unwrap().span(), - "multiple `cfg` predicates are specified", - "", - ); - } - - match nested_meta_items[0].meta_item() { - Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features), - None => error( - nested_meta_items[0].span(), - "`cfg` predicate key cannot be a literal", - "", - ), + let span = meta_item.span; + match meta_item.meta_item_list() { + None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"), + Some([]) => error(span, "`cfg` predicate is not specified", ""), + Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""), + Some([single]) => match single.meta_item() { + Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features), + None => error(single.span(), "`cfg` predicate key cannot be a literal", ""), + }, } }) } From b8b32a9be341761c3927843c27042febbe8ea39a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 07:42:19 +0100 Subject: [PATCH 05/27] simplify config::features --- src/librustc_parse/config.rs | 37 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 3c37501be4162..3f544494704bc 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -207,30 +207,29 @@ pub fn features( edition: Edition, allow_features: &Option>, ) -> (ast::Crate, Features) { - let features; - { - let mut strip_unconfigured = StripUnconfigured { sess, features: None }; + let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - let unconfigured_attrs = krate.attrs.clone(); - let err_count = sess.span_diagnostic.err_count(); - if let Some(attrs) = strip_unconfigured.configure(krate.attrs) { - krate.attrs = attrs; - } else { - // the entire crate is unconfigured + let unconfigured_attrs = krate.attrs.clone(); + let diag = &sess.span_diagnostic; + let err_count = diag.err_count(); + let features = match strip_unconfigured.configure(krate.attrs) { + None => { + // The entire crate is unconfigured. krate.attrs = Vec::new(); krate.module.items = Vec::new(); - return (krate, Features::default()); + Features::default() } - - features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features); - - // Avoid reconfiguring malformed `cfg_attr`s - if err_count == sess.span_diagnostic.err_count() { - strip_unconfigured.features = Some(&features); - strip_unconfigured.configure(unconfigured_attrs); + Some(attrs) => { + krate.attrs = attrs; + let features = get_features(diag, &krate.attrs, edition, allow_features); + if err_count == diag.err_count() { + // Avoid reconfiguring malformed `cfg_attr`s. + strip_unconfigured.features = Some(&features); + strip_unconfigured.configure(unconfigured_attrs); + } + features } - } - + }; (krate, features) } From 64ea295fe92236e5e5162722f5242f5837af7ee1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 08:14:31 +0100 Subject: [PATCH 06/27] expand: extract error_derive_forbidden_on_non_adt --- src/librustc_expand/expand.rs | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 90692fe1ec9dd..c7c7f62918d72 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -451,28 +451,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => unreachable!(), }; if !item.derive_allowed() { - let attr = attr::find_by_name(item.attrs(), sym::derive) - .expect("`derive` attribute should exist"); - let span = attr.span; - let mut err = self.cx.struct_span_err( - span, - "`derive` may only be applied to structs, enums and unions", - ); - if let ast::AttrStyle::Inner = attr.style { - let trait_list = derives - .iter() - .map(|t| pprust::path_to_string(t)) - .collect::>(); - let suggestion = format!("#[derive({})]", trait_list.join(", ")); - err.span_suggestion( - span, - "try an outer attribute", - suggestion, - // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT - Applicability::MaybeIncorrect, - ); - } - err.emit(); + self.error_derive_forbidden_on_non_adt(&derives, &item); } let mut item = self.fully_configure(item); @@ -521,6 +500,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fragment_with_placeholders } + fn error_derive_forbidden_on_non_adt(&self, derives: &[Path], item: &Annotatable) { + let attr = + attr::find_by_name(item.attrs(), sym::derive).expect("`derive` attribute should exist"); + let span = attr.span; + let mut err = self + .cx + .struct_span_err(span, "`derive` may only be applied to structs, enums and unions"); + if let ast::AttrStyle::Inner = attr.style { + let trait_list = derives.iter().map(|t| pprust::path_to_string(t)).collect::>(); + let suggestion = format!("#[derive({})]", trait_list.join(", ")); + err.span_suggestion( + span, + "try an outer attribute", + suggestion, + // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT + Applicability::MaybeIncorrect, + ); + } + err.emit(); + } + fn resolve_imports(&mut self) { if self.monotonic { self.cx.resolver.resolve_imports(); From 10f342abae4e9aafb02c3adaaa050f43eb0e2dd0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 13 Feb 2020 11:16:54 +0100 Subject: [PATCH 07/27] miri: fix exact_div --- src/librustc_mir/interpret/intrinsics.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index f85da760ada6d..33070f7e65671 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -410,8 +410,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx> { // Performs an exact division, resulting in undefined behavior where // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`. - // First, check x % y != 0. - if self.binary_op(BinOp::Rem, a, b)?.to_bits()? != 0 { + // First, check x % y != 0 (or if that computation overflows). + let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, a, b)?; + if overflow || res.to_bits(a.layout.size)? != 0 { // Then, check if `b` is -1, which is the "min_value / -1" case. let minus1 = Scalar::from_int(-1, dest.layout.size); let b_scalar = b.to_scalar().unwrap(); @@ -421,6 +422,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub_format!("exact_div: {} cannot be divided by {} without remainder", a, b,) } } + // `Rem` says this is all right, so we can let `Div` do its job. self.binop_ignore_overflow(BinOp::Div, a, b, dest) } } From acad03342412961536641d53628d7ccaa189279b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 08:25:49 +0100 Subject: [PATCH 08/27] expand: extract error_recursion_limit_reached --- src/librustc_expand/expand.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index c7c7f62918d72..da9660184099e 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -606,21 +606,26 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment { - if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { - let expn_data = self.cx.current_expansion.id.expn_data(); - let suggested_limit = self.cx.ecfg.recursion_limit * 2; - let mut err = self.cx.struct_span_err( + fn error_recursion_limit_reached(&mut self) { + let expn_data = self.cx.current_expansion.id.expn_data(); + let suggested_limit = self.cx.ecfg.recursion_limit * 2; + self.cx + .struct_span_err( expn_data.call_site, &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()), - ); - err.help(&format!( + ) + .help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", suggested_limit, self.cx.ecfg.crate_name, - )); - err.emit(); - self.cx.trace_macros_diag(); - FatalError.raise(); + )) + .emit(); + self.cx.trace_macros_diag(); + FatalError.raise(); + } + + fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment { + if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { + self.error_recursion_limit_reached(); } let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); From 7518492315346ac3821ad9264e08721a571742c8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 08:43:33 +0100 Subject: [PATCH 09/27] expand: extract error_wrong_fragment_kind --- src/librustc_expand/expand.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index da9660184099e..136cc1d94a078 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -623,6 +623,18 @@ impl<'a, 'b> MacroExpander<'a, 'b> { FatalError.raise(); } + /// A macro's expansion does not fit in this fragment kind. + /// For example, a non-type macro in a type position. + fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::Mac, span: Span) { + let msg = format!( + "non-{kind} macro in {kind} position: {path}", + kind = kind.name(), + path = pprust::path_to_string(&mac.path), + ); + self.cx.span_err(span, &msg); + self.cx.trace_macros_diag(); + } + fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment { if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { self.error_recursion_limit_reached(); @@ -643,13 +655,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let result = if let Some(result) = fragment_kind.make_from(tok_result) { result } else { - let msg = format!( - "non-{kind} macro in {kind} position: {path}", - kind = fragment_kind.name(), - path = pprust::path_to_string(&mac.path), - ); - self.cx.span_err(span, &msg); - self.cx.trace_macros_diag(); + self.error_wrong_fragment_kind(fragment_kind, &mac, span); fragment_kind.dummy(span) }; self.cx.current_expansion.prior_type_ascription = prev; From fcce5fa6e7ba67db63674dc7369125875c7f39a2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 09:11:59 +0100 Subject: [PATCH 10/27] expand: simplify classify_* --- src/librustc_expand/expand.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 136cc1d94a078..91195d379d71c 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1041,13 +1041,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } /// If `item` is an attr invocation, remove and return the macro attribute and derive traits. - fn classify_item( + fn classify_item( &mut self, - item: &mut T, - ) -> (Option, Vec, /* after_derive */ bool) - where - T: HasAttrs, - { + item: &mut impl HasAttrs, + ) -> (Option, Vec, /* after_derive */ bool) { let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); item.visit_attrs(|mut attrs| { @@ -1061,9 +1058,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { /// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough /// to the unused-attributes lint (making it an error on statements and expressions /// is a breaking change) - fn classify_nonitem( + fn classify_nonitem( &mut self, - nonitem: &mut T, + nonitem: &mut impl HasAttrs, ) -> (Option, /* after_derive */ bool) { let (mut attr, mut after_derive) = (None, false); From dc6bd6a12347f27c937c19adfda542f694fb61c5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 09:59:37 +0100 Subject: [PATCH 11/27] expand: simplify flat_map_item --- src/librustc_expand/expand.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 91195d379d71c..ee0b7fa00de26 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1383,11 +1383,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - ast::ItemKind::Mod(ast::Mod { inner, .. }) => { - if item.ident == Ident::invalid() { - return noop_flat_map_item(item, self); - } - + ast::ItemKind::Mod(ast::Mod { inner, .. }) if item.ident != Ident::invalid() => { let orig_directory_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); module.mod_path.push(item.ident); From ec434500157c47143a9b5600a7e34522c49f4e8e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 10:06:52 +0100 Subject: [PATCH 12/27] expand: simplify flat_map_item wrt. inline module detection --- src/librustc_expand/expand.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index ee0b7fa00de26..316dd02bd9581 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1383,17 +1383,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - ast::ItemKind::Mod(ast::Mod { inner, .. }) if item.ident != Ident::invalid() => { + ast::ItemKind::Mod(ast::Mod { inner, inline, .. }) + if item.ident != Ident::invalid() => + { let orig_directory_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); module.mod_path.push(item.ident); - // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`). - // In the non-inline case, `inner` is never the dummy span (cf. `parse_item_mod`). - // Thus, if `inner` is the dummy span, we know the module is inline. - let inline_module = item.span.contains(inner) || inner.is_dummy(); - - if inline_module { + if inline { if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) { self.cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None }; From 9fed2d587c9d9f28003e23255b863897bd22a8b2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 04:21:16 +0100 Subject: [PATCH 13/27] parser: extract common foreign item code for each kind --- src/librustc_parse/parser/item.rs | 88 ++++++++----------------------- 1 file changed, 21 insertions(+), 67 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index ccd55c5c08a70..0a8f37708621a 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -740,7 +740,8 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); - let (name, kind, generics) = if self.eat_keyword(kw::Type) { + + let (ident, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_assoc_ty()? } else if self.check_fn_front_matter() { let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?; @@ -751,17 +752,9 @@ impl<'a> Parser<'a> { self.parse_assoc_const()? }; - Ok(AssocItem { - id: DUMMY_NODE_ID, - span: lo.to(self.prev_span), - ident: name, - attrs, - vis, - defaultness, - generics, - kind, - tokens: None, - }) + let span = lo.to(self.prev_span); + let id = DUMMY_NODE_ID; + Ok(AssocItem { id, span, ident, attrs, vis, defaultness, generics, kind, tokens: None }) } /// This parses the grammar: @@ -967,7 +960,7 @@ impl<'a> Parser<'a> { Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs)) } - /// Parses a foreign item. + /// Parses a foreign item (one in an `extern { ... }` block). pub fn parse_foreign_item(&mut self) -> PResult<'a, P> { maybe_whole!(self, NtForeignItem, |ni| ni); @@ -975,27 +968,17 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; - if self.check_keyword(kw::Type) { + let (ident, kind) = if self.check_keyword(kw::Type) { // FOREIGN TYPE ITEM - self.parse_item_foreign_type(vis, lo, attrs) + self.parse_item_foreign_type()? } else if self.check_fn_front_matter() { // FOREIGN FUNCTION ITEM let (ident, sig, generics, body) = self.parse_fn(&mut false, &mut attrs, |_| true)?; - let kind = ForeignItemKind::Fn(sig, generics, body); - let span = lo.to(self.prev_span); - Ok(P(ast::ForeignItem { - ident, - attrs, - kind, - id: DUMMY_NODE_ID, - span, - vis, - tokens: None, - })) + (ident, ForeignItemKind::Fn(sig, generics, body)) } else if self.is_static_global() { // FOREIGN STATIC ITEM self.bump(); // `static` - self.parse_item_foreign_static(vis, lo, attrs) + self.parse_item_foreign_static()? } else if self.token.is_keyword(kw::Const) { // Treat `const` as `static` for error recovery, but don't add it to expected tokens. self.bump(); // `const` @@ -1007,66 +990,37 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ) .emit(); - self.parse_item_foreign_static(vis, lo, attrs) + self.parse_item_foreign_static()? } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), &mut false)? { - let kind = ForeignItemKind::Macro(mac); - let span = lo.to(self.prev_span); - let ident = Ident::invalid(); - Ok(P(ForeignItem { ident, span, id: DUMMY_NODE_ID, attrs, vis, kind, tokens: None })) + (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { if !attrs.is_empty() { self.expected_item_err(&attrs)?; } - self.unexpected() - } + self.unexpected()? + }; + + let span = lo.to(self.prev_span); + Ok(P(ast::ForeignItem { ident, attrs, kind, id: DUMMY_NODE_ID, span, vis, tokens: None })) } /// Parses a static item from a foreign module. /// Assumes that the `static` keyword is already parsed. - fn parse_item_foreign_static( - &mut self, - vis: ast::Visibility, - lo: Span, - attrs: Vec, - ) -> PResult<'a, P> { + fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { let mutbl = self.parse_mutability(); let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; - let hi = self.token.span; self.expect_semi()?; - Ok(P(ForeignItem { - ident, - attrs, - kind: ForeignItemKind::Static(ty, mutbl), - id: DUMMY_NODE_ID, - span: lo.to(hi), - vis, - tokens: None, - })) + Ok((ident, ForeignItemKind::Static(ty, mutbl))) } /// Parses a type from a foreign module. - fn parse_item_foreign_type( - &mut self, - vis: ast::Visibility, - lo: Span, - attrs: Vec, - ) -> PResult<'a, P> { + fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { self.expect_keyword(kw::Type)?; - let ident = self.parse_ident()?; - let hi = self.token.span; self.expect_semi()?; - Ok(P(ast::ForeignItem { - ident, - attrs, - kind: ForeignItemKind::Ty, - id: DUMMY_NODE_ID, - span: lo.to(hi), - vis, - tokens: None, - })) + Ok((ident, ForeignItemKind::Ty)) } fn is_static_global(&mut self) -> bool { From 7737d0ffdef6f3d7395e80291e3143522f46b95b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 06:43:33 +0100 Subject: [PATCH 14/27] parser: unify item list parsing. as a consequence, `trait X { #![attr] }` becomes legal. --- src/librustc_ast_pretty/pprust.rs | 1 + src/librustc_expand/expand.rs | 2 +- src/librustc_parse/parser/item.rs | 102 ++++++++---------- src/test/pretty/trait-inner-attr.rs | 7 ++ src/test/ui/parser/attrs-after-extern-mod.rs | 10 +- .../ui/parser/attrs-after-extern-mod.stderr | 2 +- .../ui/parser/doc-before-extern-rbrace.rs | 4 +- .../ui/parser/doc-before-extern-rbrace.stderr | 7 +- .../ui/parser/doc-inside-trait-item.stderr | 2 +- src/test/ui/parser/duplicate-visibility.rs | 3 + .../ui/parser/duplicate-visibility.stderr | 2 +- src/test/ui/parser/inner-attr-in-trait-def.rs | 9 ++ 12 files changed, 80 insertions(+), 71 deletions(-) create mode 100644 src/test/pretty/trait-inner-attr.rs create mode 100644 src/test/ui/parser/inner-attr-in-trait-def.rs diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index b1fa818d0a8cf..75938470b6fca 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1269,6 +1269,7 @@ impl<'a> State<'a> { self.print_where_clause(&generics.where_clause); self.s.word(" "); self.bopen(); + self.print_inner_attributes(&item.attrs); for trait_item in trait_items { self.print_assoc_item(trait_item); } diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 90692fe1ec9dd..0968e92c20314 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -867,7 +867,7 @@ pub fn parse_ast_fragment<'a>( AstFragmentKind::ForeignItems => { let mut items = SmallVec::new(); while this.token != token::Eof { - items.push(this.parse_foreign_item()?); + items.push(this.parse_foreign_item(&mut false)?); } AstFragment::ForeignItems(items) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 0a8f37708621a..f4ca84b005b84 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -515,7 +515,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; - let (impl_items, attrs) = self.parse_impl_body()?; + let (impl_items, attrs) = self.parse_item_list(|p, at_end| p.parse_impl_item(at_end))?; let item_kind = match ty_second { Some(ty_second) => { @@ -571,15 +571,21 @@ impl<'a> Parser<'a> { Ok((Ident::invalid(), item_kind, Some(attrs))) } - fn parse_impl_body(&mut self) -> PResult<'a, (Vec>, Vec)> { + fn parse_item_list( + &mut self, + mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, T>, + ) -> PResult<'a, (Vec, Vec)> { self.expect(&token::OpenDelim(token::Brace))?; let attrs = self.parse_inner_attributes()?; - let mut impl_items = Vec::new(); + let mut items = Vec::new(); while !self.eat(&token::CloseDelim(token::Brace)) { + if self.recover_doc_comment_before_brace() { + continue; + } let mut at_end = false; - match self.parse_impl_item(&mut at_end) { - Ok(impl_item) => impl_items.push(impl_item), + match parse_item(self, &mut at_end) { + Ok(item) => items.push(item), Err(mut err) => { err.emit(); if !at_end { @@ -589,7 +595,30 @@ impl<'a> Parser<'a> { } } } - Ok((impl_items, attrs)) + Ok((items, attrs)) + } + + /// Recover on a doc comment before `}`. + fn recover_doc_comment_before_brace(&mut self) -> bool { + if let token::DocComment(_) = self.token.kind { + if self.look_ahead(1, |tok| tok == &token::CloseDelim(token::Brace)) { + struct_span_err!( + self.diagnostic(), + self.token.span, + E0584, + "found a documentation comment that doesn't document anything", + ) + .span_label(self.token.span, "this doc comment doesn't document anything") + .help( + "doc comments must come before what they document, maybe a \ + comment was intended with `//`?", + ) + .emit(); + self.bump(); + return true; + } + } + false } /// Parses defaultness (i.e., `default` or nothing). @@ -660,39 +689,8 @@ impl<'a> Parser<'a> { } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - self.expect(&token::OpenDelim(token::Brace))?; - let mut trait_items = vec![]; - while !self.eat(&token::CloseDelim(token::Brace)) { - if let token::DocComment(_) = self.token.kind { - if self.look_ahead(1, |tok| tok == &token::CloseDelim(token::Brace)) { - struct_span_err!( - self.diagnostic(), - self.token.span, - E0584, - "found a documentation comment that doesn't document anything", - ) - .help( - "doc comments must come before what they document, maybe a \ - comment was intended with `//`?", - ) - .emit(); - self.bump(); - continue; - } - } - let mut at_end = false; - match self.parse_trait_item(&mut at_end) { - Ok(item) => trait_items.push(item), - Err(mut e) => { - e.emit(); - if !at_end { - self.consume_block(token::Brace, ConsumeClosingDelim::Yes); - break; - } - } - } - } - Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None)) + let (items, attrs) = self.parse_item_list(|p, at_end| p.parse_trait_item(at_end))?; + Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items), Some(attrs))) } } @@ -942,26 +940,18 @@ impl<'a> Parser<'a> { &mut self, lo: Span, abi: Option, - visibility: Visibility, + vis: Visibility, mut attrs: Vec, ) -> PResult<'a, P> { - self.expect(&token::OpenDelim(token::Brace))?; - - attrs.extend(self.parse_inner_attributes()?); - - let mut foreign_items = vec![]; - while !self.eat(&token::CloseDelim(token::Brace)) { - foreign_items.push(self.parse_foreign_item()?); - } - - let prev_span = self.prev_span; - let m = ast::ForeignMod { abi, items: foreign_items }; - let invalid = Ident::invalid(); - Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs)) + let (items, iattrs) = self.parse_item_list(|p, at_end| p.parse_foreign_item(at_end))?; + attrs.extend(iattrs); + let span = lo.to(self.prev_span); + let m = ast::ForeignMod { abi, items }; + Ok(self.mk_item(span, Ident::invalid(), ItemKind::ForeignMod(m), vis, attrs)) } /// Parses a foreign item (one in an `extern { ... }` block). - pub fn parse_foreign_item(&mut self) -> PResult<'a, P> { + pub fn parse_foreign_item(&mut self, at_end: &mut bool) -> PResult<'a, P> { maybe_whole!(self, NtForeignItem, |ni| ni); let mut attrs = self.parse_outer_attributes()?; @@ -973,7 +963,7 @@ impl<'a> Parser<'a> { self.parse_item_foreign_type()? } else if self.check_fn_front_matter() { // FOREIGN FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(&mut false, &mut attrs, |_| true)?; + let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, |_| true)?; (ident, ForeignItemKind::Fn(sig, generics, body)) } else if self.is_static_global() { // FOREIGN STATIC ITEM @@ -991,7 +981,7 @@ impl<'a> Parser<'a> { ) .emit(); self.parse_item_foreign_static()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), &mut false)? { + } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), at_end)? { (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { if !attrs.is_empty() { diff --git a/src/test/pretty/trait-inner-attr.rs b/src/test/pretty/trait-inner-attr.rs new file mode 100644 index 0000000000000..bb4fb1459bd64 --- /dev/null +++ b/src/test/pretty/trait-inner-attr.rs @@ -0,0 +1,7 @@ +// pp-exact + +trait Foo { + #![allow(bar)] +} + +fn main() { } diff --git a/src/test/ui/parser/attrs-after-extern-mod.rs b/src/test/ui/parser/attrs-after-extern-mod.rs index 4bdd16471cd80..ea899dca7b221 100644 --- a/src/test/ui/parser/attrs-after-extern-mod.rs +++ b/src/test/ui/parser/attrs-after-extern-mod.rs @@ -1,13 +1,7 @@ -// Constants (static variables) can be used to match in patterns, but mutable -// statics cannot. This ensures that there's some form of error if this is -// attempted. +// Make sure there's an error when given `extern { ... #[attr] }`. -extern crate libc; +fn main() {} extern { - static mut rust_dbg_static_mut: libc::c_int; - pub fn rust_dbg_static_mut_check_four(); #[cfg(stage37)] //~ ERROR expected item after attributes } - -pub fn main() {} diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr index cecdab4d63197..a02e738a2c38e 100644 --- a/src/test/ui/parser/attrs-after-extern-mod.stderr +++ b/src/test/ui/parser/attrs-after-extern-mod.stderr @@ -1,5 +1,5 @@ error: expected item after attributes - --> $DIR/attrs-after-extern-mod.rs:10:19 + --> $DIR/attrs-after-extern-mod.rs:6:19 | LL | #[cfg(stage37)] | ^ diff --git a/src/test/ui/parser/doc-before-extern-rbrace.rs b/src/test/ui/parser/doc-before-extern-rbrace.rs index 695d4da1dca60..040206b80ffd0 100644 --- a/src/test/ui/parser/doc-before-extern-rbrace.rs +++ b/src/test/ui/parser/doc-before-extern-rbrace.rs @@ -1,4 +1,6 @@ +fn main() {} + extern { /// hi - //~^ ERROR expected item after doc comment + //~^ ERROR found a documentation comment that doesn't document anything } diff --git a/src/test/ui/parser/doc-before-extern-rbrace.stderr b/src/test/ui/parser/doc-before-extern-rbrace.stderr index 8cc9c916a7afd..0edceb268a7f5 100644 --- a/src/test/ui/parser/doc-before-extern-rbrace.stderr +++ b/src/test/ui/parser/doc-before-extern-rbrace.stderr @@ -1,8 +1,11 @@ -error: expected item after doc comment - --> $DIR/doc-before-extern-rbrace.rs:2:5 +error[E0584]: found a documentation comment that doesn't document anything + --> $DIR/doc-before-extern-rbrace.rs:4:5 | LL | /// hi | ^^^^^^ this doc comment doesn't document anything + | + = help: doc comments must come before what they document, maybe a comment was intended with `//`? error: aborting due to previous error +For more information about this error, try `rustc --explain E0584`. diff --git a/src/test/ui/parser/doc-inside-trait-item.stderr b/src/test/ui/parser/doc-inside-trait-item.stderr index 261e27b6e0d18..246255a0a4675 100644 --- a/src/test/ui/parser/doc-inside-trait-item.stderr +++ b/src/test/ui/parser/doc-inside-trait-item.stderr @@ -2,7 +2,7 @@ error[E0584]: found a documentation comment that doesn't document anything --> $DIR/doc-inside-trait-item.rs:3:5 | LL | /// empty doc - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ this doc comment doesn't document anything | = help: doc comments must come before what they document, maybe a comment was intended with `//`? diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index a8f0b7d61b985..edbf508ecdb76 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -1,4 +1,7 @@ // error-pattern: expected one of `(`, `async`, `const`, `extern`, `fn` + +fn main() {} + extern { pub pub fn foo(); } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index cba4058e48255..92cf348796943 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,5 +1,5 @@ error: expected one of `(`, `async`, `const`, `extern`, `fn`, `static`, `type`, or `unsafe`, found keyword `pub` - --> $DIR/duplicate-visibility.rs:3:9 + --> $DIR/duplicate-visibility.rs:6:9 | LL | pub pub fn foo(); | ^^^ expected one of 8 possible tokens diff --git a/src/test/ui/parser/inner-attr-in-trait-def.rs b/src/test/ui/parser/inner-attr-in-trait-def.rs new file mode 100644 index 0000000000000..8dba6b362cdfa --- /dev/null +++ b/src/test/ui/parser/inner-attr-in-trait-def.rs @@ -0,0 +1,9 @@ +// check-pass + +#![deny(non_camel_case_types)] + +fn main() {} + +trait foo_bar { + #![allow(non_camel_case_types)] +} From 511dfdb8b3d8c6d395b1b5a205c3464ae802509f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 07:00:19 +0100 Subject: [PATCH 15/27] parser: extract `recover_missing_kw_before_item` --- src/librustc_parse/parser/item.rs | 174 +++++++++++++++--------------- 1 file changed, 90 insertions(+), 84 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index f4ca84b005b84..acbae7dfd6810 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -203,101 +203,107 @@ impl<'a> Parser<'a> { return Ok(Some(macro_def)); } - // Verify whether we have encountered a struct or method definition where the user forgot to - // add the `struct` or `fn` keyword after writing `pub`: `pub S {}` if vis.node.is_pub() && self.check_ident() && self.look_ahead(1, |t| *t != token::Not) { - // Space between `pub` keyword and the identifier - // - // pub S {} - // ^^^ `sp` points here - let sp = self.prev_span.between(self.token.span); - let full_sp = self.prev_span.to(self.token.span); - let ident_sp = self.token.span; - if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) { - // possible public struct definition where `struct` was forgotten - let ident = self.parse_ident().unwrap(); - let msg = format!("add `struct` here to parse `{}` as a public struct", ident); - let mut err = self.struct_span_err(sp, "missing `struct` for struct definition"); + self.recover_missing_kw_before_item()?; + } + self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) + } + + /// Recover on encountering a struct or method definition where the user + /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`. + fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> { + // Space between `pub` keyword and the identifier + // + // pub S {} + // ^^^ `sp` points here + let sp = self.prev_span.between(self.token.span); + let full_sp = self.prev_span.to(self.token.span); + let ident_sp = self.token.span; + if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) { + // possible public struct definition where `struct` was forgotten + let ident = self.parse_ident().unwrap(); + let msg = format!("add `struct` here to parse `{}` as a public struct", ident); + let mut err = self.struct_span_err(sp, "missing `struct` for struct definition"); + err.span_suggestion_short( + sp, + &msg, + " struct ".into(), + Applicability::MaybeIncorrect, // speculative + ); + return Err(err); + } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { + let ident = self.parse_ident().unwrap(); + self.bump(); // `(` + let kw_name = self.recover_first_param(); + self.consume_block(token::Paren, ConsumeClosingDelim::Yes); + let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { + self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); + self.bump(); // `{` + ("fn", kw_name, false) + } else if self.check(&token::OpenDelim(token::Brace)) { + self.bump(); // `{` + ("fn", kw_name, false) + } else if self.check(&token::Colon) { + let kw = "struct"; + (kw, kw, false) + } else { + ("fn` or `struct", "function or struct", true) + }; + + let msg = format!("missing `{}` for {} definition", kw, kw_name); + let mut err = self.struct_span_err(sp, &msg); + if !ambiguous { + self.consume_block(token::Brace, ConsumeClosingDelim::Yes); + let suggestion = + format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name); err.span_suggestion_short( sp, - &msg, - " struct ".into(), - Applicability::MaybeIncorrect, // speculative + &suggestion, + format!(" {} ", kw), + Applicability::MachineApplicable, ); - return Err(err); - } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { - let ident = self.parse_ident().unwrap(); - self.bump(); // `(` - let kw_name = self.recover_first_param(); - self.consume_block(token::Paren, ConsumeClosingDelim::Yes); - let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { - self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); - self.bump(); // `{` - ("fn", kw_name, false) - } else if self.check(&token::OpenDelim(token::Brace)) { - self.bump(); // `{` - ("fn", kw_name, false) - } else if self.check(&token::Colon) { - let kw = "struct"; - (kw, kw, false) - } else { - ("fn` or `struct", "function or struct", true) - }; - - let msg = format!("missing `{}` for {} definition", kw, kw_name); - let mut err = self.struct_span_err(sp, &msg); - if !ambiguous { - self.consume_block(token::Brace, ConsumeClosingDelim::Yes); - let suggestion = - format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name); - err.span_suggestion_short( - sp, - &suggestion, - format!(" {} ", kw), - Applicability::MachineApplicable, + } else { + if let Ok(snippet) = self.span_to_snippet(ident_sp) { + err.span_suggestion( + full_sp, + "if you meant to call a macro, try", + format!("{}!", snippet), + // this is the `ambiguous` conditional branch + Applicability::MaybeIncorrect, ); } else { - if let Ok(snippet) = self.span_to_snippet(ident_sp) { - err.span_suggestion( - full_sp, - "if you meant to call a macro, try", - format!("{}!", snippet), - // this is the `ambiguous` conditional branch - Applicability::MaybeIncorrect, - ); - } else { - err.help( - "if you meant to call a macro, remove the `pub` \ + err.help( + "if you meant to call a macro, remove the `pub` \ and add a trailing `!` after the identifier", - ); - } - } - return Err(err); - } else if self.look_ahead(1, |t| *t == token::Lt) { - let ident = self.parse_ident().unwrap(); - self.eat_to_tokens(&[&token::Gt]); - self.bump(); // `>` - let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { - ("fn", self.recover_first_param(), false) - } else if self.check(&token::OpenDelim(token::Brace)) { - ("struct", "struct", false) - } else { - ("fn` or `struct", "function or struct", true) - }; - let msg = format!("missing `{}` for {} definition", kw, kw_name); - let mut err = self.struct_span_err(sp, &msg); - if !ambiguous { - err.span_suggestion_short( - sp, - &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), - format!(" {} ", kw), - Applicability::MachineApplicable, ); } - return Err(err); } + return Err(err); + } else if self.look_ahead(1, |t| *t == token::Lt) { + let ident = self.parse_ident().unwrap(); + self.eat_to_tokens(&[&token::Gt]); + self.bump(); // `>` + let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { + ("fn", self.recover_first_param(), false) + } else if self.check(&token::OpenDelim(token::Brace)) { + ("struct", "struct", false) + } else { + ("fn` or `struct", "function or struct", true) + }; + let msg = format!("missing `{}` for {} definition", kw, kw_name); + let mut err = self.struct_span_err(sp, &msg); + if !ambiguous { + err.span_suggestion_short( + sp, + &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), + format!(" {} ", kw), + Applicability::MachineApplicable, + ); + } + return Err(err); + } else { + Ok(()) } - self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) } pub(super) fn mk_item_with_info( From 73d5970cdc304c874cd6d7d594f3abb7317f1519 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 08:37:09 +0100 Subject: [PATCH 16/27] parser: introduce `parse_item_kind` as central `ItemInfo` logic. this also extracts macro item parsers. --- src/librustc_parse/parser/item.rs | 348 ++++++++---------- src/test/ui/pub/pub-restricted-error-fn.rs | 3 +- .../ui/pub/pub-restricted-error-fn.stderr | 14 +- 3 files changed, 168 insertions(+), 197 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index acbae7dfd6810..9ba3be041b5e6 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -11,7 +11,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::BytePos; use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind}; -use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, StrLit, Unsafe}; +use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind}; @@ -83,45 +83,60 @@ impl<'a> Parser<'a> { }); let lo = self.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - if self.eat_keyword(kw::Use) { - // USE ITEM - let item_ = ItemKind::Use(P(self.parse_use_tree()?)); - self.expect_semi()?; + if let Some(info) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { + return Ok(Some(self.mk_item_with_info(attrs, lo, vis, info))); + } - let span = lo.to(self.prev_span); - let item = self.mk_item(span, Ident::invalid(), item_, vis, attrs); - return Ok(Some(item)); + // FAILURE TO PARSE ITEM + match vis.node { + VisibilityKind::Inherited => {} + _ => { + self.struct_span_err(vis.span, "unmatched visibility `pub`") + .span_label(vis.span, "the unmatched visibility") + .help("you likely meant to define an item, e.g., `pub fn foo() {}`") + .emit(); + } } - if self.check_fn_front_matter() { - // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(&mut false, &mut attrs, |_| true)?; - let kind = ItemKind::Fn(sig, generics, body); - return self.mk_item_with_info(attrs, lo, vis, (ident, kind, None)); + if !attributes_allowed && !attrs.is_empty() { + self.expected_item_err(&attrs)?; } + Ok(None) + } - if self.eat_keyword(kw::Extern) { + /// Parses one of the items allowed by the flags. + fn parse_item_kind( + &mut self, + attrs: &mut Vec, + macros_allowed: bool, + lo: Span, + vis: &Visibility, + ) -> PResult<'a, Option> { + let info = if self.eat_keyword(kw::Use) { + // USE ITEM + let tree = self.parse_use_tree()?; + self.expect_semi()?; + (Ident::invalid(), ItemKind::Use(P(tree)), None) + } else if self.check_fn_front_matter() { + // FUNCTION ITEM + let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, |_| true)?; + (ident, ItemKind::Fn(sig, generics, body), None) + } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { // EXTERN CRATE - return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); + self.parse_item_extern_crate()? + } else { + // EXTERN BLOCK + self.parse_item_foreign_mod()? } - // EXTERN BLOCK - let abi = self.parse_abi(); - return Ok(Some(self.parse_item_foreign_mod(lo, abi, vis, attrs)?)); - } - - if self.is_static_global() { + } else if self.is_static_global() { // STATIC ITEM - self.bump(); + self.bump(); // `static` let m = self.parse_mutability(); - let info = self.parse_item_const(Some(m))?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if let Const::Yes(const_span) = self.parse_constness() { + self.parse_item_const(Some(m))? + } else if let Const::Yes(const_span) = self.parse_constness() { // CONST ITEM if self.eat_keyword(kw::Mut) { let prev_span = self.prev_span; @@ -136,18 +151,13 @@ impl<'a> Parser<'a> { .emit(); } - let info = self.parse_item_const(None)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) { + self.parse_item_const(None)? + } else if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) + { // UNSAFE TRAIT ITEM let unsafety = self.parse_unsafety(); - let info = self.parse_item_trait(lo, unsafety)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.check_keyword(kw::Impl) + self.parse_item_trait(lo, unsafety)? + } else if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) { @@ -155,58 +165,48 @@ impl<'a> Parser<'a> { let defaultness = self.parse_defaultness(); let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Impl)?; - let info = self.parse_item_impl(unsafety, defaultness)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.eat_keyword(kw::Mod) { + self.parse_item_impl(unsafety, defaultness)? + } else if self.eat_keyword(kw::Mod) { // MODULE ITEM - let info = self.parse_item_mod(&attrs[..])?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.eat_keyword(kw::Type) { + self.parse_item_mod(&attrs[..])? + } else if self.eat_keyword(kw::Type) { // TYPE ITEM let (ident, ty, generics) = self.parse_type_alias()?; - let kind = ItemKind::TyAlias(ty, generics); - return self.mk_item_with_info(attrs, lo, vis, (ident, kind, None)); - } - - if self.eat_keyword(kw::Enum) { + (ident, ItemKind::TyAlias(ty, generics), None) + } else if self.eat_keyword(kw::Enum) { // ENUM ITEM - let info = self.parse_item_enum()?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.check_keyword(kw::Trait) + self.parse_item_enum()? + } else if self.check_keyword(kw::Trait) || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait])) { // TRAIT ITEM - let info = self.parse_item_trait(lo, Unsafe::No)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.eat_keyword(kw::Struct) { + self.parse_item_trait(lo, Unsafe::No)? + } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM - let info = self.parse_item_struct()?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.is_union_item() { + self.parse_item_struct()? + } else if self.is_union_item() { // UNION ITEM - self.bump(); - let info = self.parse_item_union()?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if let Some(macro_def) = self.eat_macro_def(&attrs, &vis, lo)? { - return Ok(Some(macro_def)); - } - - if vis.node.is_pub() && self.check_ident() && self.look_ahead(1, |t| *t != token::Not) { + self.bump(); // `union` + self.parse_item_union()? + } else if self.eat_keyword(kw::Macro) { + // MACROS 2.0 ITEM + self.parse_item_decl_macro(lo)? + } else if self.is_macro_rules_item() { + // MACRO_RULES ITEM + self.parse_item_macro_rules(vis)? + } else if vis.node.is_pub() + && self.check_ident() + && self.look_ahead(1, |t| *t != token::Not) + { self.recover_missing_kw_before_item()?; - } - self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) + return Ok(None); + } else if macros_allowed && self.token.is_path_start() { + // MACRO INVOCATION ITEM + self.parse_item_macro(vis)? + } else { + return Ok(None); + }; + Ok(Some(info)) } /// Recover on encountering a struct or method definition where the user @@ -312,11 +312,11 @@ impl<'a> Parser<'a> { lo: Span, vis: Visibility, info: ItemInfo, - ) -> PResult<'a, Option>> { + ) -> P { let (ident, item, extra_attrs) = info; let span = lo.to(self.prev_span); let attrs = Self::maybe_append(attrs, extra_attrs); - Ok(Some(self.mk_item(span, ident, item, vis, attrs))) + self.mk_item(span, ident, item, vis, attrs) } fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { @@ -326,49 +326,20 @@ impl<'a> Parser<'a> { lhs } - /// This is the fall-through for parsing items. - fn parse_macro_use_or_failure( - &mut self, - attrs: Vec, - macros_allowed: bool, - attributes_allowed: bool, - lo: Span, - visibility: Visibility, - ) -> PResult<'a, Option>> { - if macros_allowed - && self.token.is_path_start() - && !(self.is_async_fn() && self.token.span.rust_2015()) - { - // MACRO INVOCATION ITEM - - let prev_span = self.prev_span; - self.complain_if_pub_macro(&visibility.node, prev_span); - - // Item macro - let path = self.parse_path(PathStyle::Mod)?; - self.expect(&token::Not)?; - let args = self.parse_mac_args()?; - if args.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } - - let hi = self.prev_span; - let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; - let item = - self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs); - return Ok(Some(item)); - } + /// Parses an item macro, e.g., `item!();`. + fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { + self.complain_if_pub_macro(&vis.node, vis.span); - // FAILURE TO PARSE ITEM - match visibility.node { - VisibilityKind::Inherited => {} - _ => return Err(self.struct_span_err(self.prev_span, "unmatched visibility `pub`")), + // Item macro + let path = self.parse_path(PathStyle::Mod)?; + self.expect(&token::Not)?; + let args = self.parse_mac_args()?; + if args.need_semicolon() && !self.eat(&token::Semi) { + self.report_invalid_macro_expansion_item(); } - if !attributes_allowed && !attrs.is_empty() { - self.expected_item_err(&attrs)?; - } - Ok(None) + let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; + Ok((Ident::invalid(), ItemKind::Mac(mac), None)) } /// Emits an expected-item-after-attributes error. @@ -874,12 +845,7 @@ impl<'a> Parser<'a> { /// extern crate foo; /// extern crate bar as foo; /// ``` - fn parse_item_extern_crate( - &mut self, - lo: Span, - visibility: Visibility, - attrs: Vec, - ) -> PResult<'a, P> { + fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemInfo> { // Accept `extern crate name-like-this` for better diagnostics let orig_name = self.parse_crate_name_with_dashes()?; let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? { @@ -888,9 +854,7 @@ impl<'a> Parser<'a> { (orig_name, None) }; self.expect_semi()?; - - let span = lo.to(self.prev_span); - Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs)) + Ok((item_name, ItemKind::ExternCrate(orig_name), None)) } fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> { @@ -933,8 +897,7 @@ impl<'a> Parser<'a> { /// Parses `extern` for foreign ABIs modules. /// - /// `extern` is expected to have been - /// consumed before calling this method. + /// `extern` is expected to have been consumed before calling this method. /// /// # Examples /// @@ -942,18 +905,11 @@ impl<'a> Parser<'a> { /// extern "C" {} /// extern {} /// ``` - fn parse_item_foreign_mod( - &mut self, - lo: Span, - abi: Option, - vis: Visibility, - mut attrs: Vec, - ) -> PResult<'a, P> { - let (items, iattrs) = self.parse_item_list(|p, at_end| p.parse_foreign_item(at_end))?; - attrs.extend(iattrs); - let span = lo.to(self.prev_span); - let m = ast::ForeignMod { abi, items }; - Ok(self.mk_item(span, Ident::invalid(), ItemKind::ForeignMod(m), vis, attrs)) + fn parse_item_foreign_mod(&mut self) -> PResult<'a, ItemInfo> { + let abi = self.parse_abi(); // ABI? + let (items, attrs) = self.parse_item_list(|p, at_end| p.parse_foreign_item(at_end))?; + let module = ast::ForeignMod { abi, items }; + Ok((Ident::invalid(), ItemKind::ForeignMod(module), Some(attrs))) } /// Parses a foreign item (one in an `extern { ... }` block). @@ -1386,64 +1342,72 @@ impl<'a> Parser<'a> { }) } - pub(super) fn eat_macro_def( - &mut self, - attrs: &[Attribute], - vis: &Visibility, - lo: Span, - ) -> PResult<'a, Option>> { - let (ident, def) = if self.eat_keyword(kw::Macro) { - let ident = self.parse_ident()?; + /// Parses a declarative macro 2.0 definition. + /// The `macro` keyword has already been parsed. + fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> { + let ident = self.parse_ident()?; + let body = if self.check(&token::OpenDelim(token::Brace)) { + self.parse_mac_args()? + } else if self.check(&token::OpenDelim(token::Paren)) { + let params = self.parse_token_tree(); + let pspan = params.span(); let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_mac_args()? - } else if self.check(&token::OpenDelim(token::Paren)) { - let params = self.parse_token_tree(); - let pspan = params.span(); - let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_token_tree() - } else { - return self.unexpected(); - }; - let bspan = body.span(); - let tokens = TokenStream::new(vec![ - params.into(), - TokenTree::token(token::FatArrow, pspan.between(bspan)).into(), - body.into(), - ]); - let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); - P(MacArgs::Delimited(dspan, MacDelimiter::Brace, tokens)) + self.parse_token_tree() } else { return self.unexpected(); }; + let bspan = body.span(); + let tokens = TokenStream::new(vec![ + params.into(), + TokenTree::token(token::FatArrow, pspan.between(bspan)).into(), + body.into(), + ]); + let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); + P(MacArgs::Delimited(dspan, MacDelimiter::Brace, tokens)) + } else { + return self.unexpected(); + }; + + self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_span)); + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false }), None)) + } - (ident, ast::MacroDef { body, legacy: false }) - } else if self.check_keyword(sym::macro_rules) + /// Is this unambiguously the start of a `macro_rules! foo` item defnition? + fn is_macro_rules_item(&mut self) -> bool { + self.check_keyword(sym::macro_rules) && self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) - { - let prev_span = self.prev_span; - self.complain_if_pub_macro(&vis.node, prev_span); - self.bump(); - self.bump(); - - let ident = self.parse_ident()?; - let body = self.parse_mac_args()?; - if body.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } - - (ident, ast::MacroDef { body, legacy: true }) - } else { - return Ok(None); - }; + } - let span = lo.to(self.prev_span); + /// Parses a legacy `macro_rules! foo { ... }` declarative macro. + fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { + self.complain_if_pub_macro(&vis.node, vis.span); + self.expect_keyword(sym::macro_rules)?; // `macro_rules` + self.expect(&token::Not)?; // `!` - if !def.legacy { - self.sess.gated_spans.gate(sym::decl_macro, span); + let ident = self.parse_ident()?; + let body = self.parse_mac_args()?; + if body.need_semicolon() && !self.eat(&token::Semi) { + self.report_invalid_macro_expansion_item(); } - Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec()))) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }), None)) + } + + pub(super) fn eat_macro_def( + &mut self, + attrs: &[Attribute], + vis: &Visibility, + lo: Span, + ) -> PResult<'a, Option>> { + let info = if self.eat_keyword(kw::Macro) { + self.parse_item_decl_macro(lo)? + } else if self.is_macro_rules_item() { + self.parse_item_macro_rules(vis)? + } else { + return Ok(None); + }; + Ok(Some(self.mk_item_with_info(attrs.to_vec(), lo, vis.clone(), info))) } fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { diff --git a/src/test/ui/pub/pub-restricted-error-fn.rs b/src/test/ui/pub/pub-restricted-error-fn.rs index 56ee02f517c7b..3f8904fbe79d8 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.rs +++ b/src/test/ui/pub/pub-restricted-error-fn.rs @@ -1,3 +1,2 @@ -#![feature(pub_restricted)] - pub(crate) () fn foo() {} //~ unmatched visibility +//~^ ERROR expected item, found `(` diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index fcff5334890eb..c5acb92dcd436 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -1,8 +1,16 @@ error: unmatched visibility `pub` - --> $DIR/pub-restricted-error-fn.rs:3:10 + --> $DIR/pub-restricted-error-fn.rs:1:1 | LL | pub(crate) () fn foo() {} - | ^ + | ^^^^^^^^^^ the unmatched visibility + | + = help: you likely meant to define an item, e.g., `pub fn foo() {}` + +error: expected item, found `(` + --> $DIR/pub-restricted-error-fn.rs:1:12 + | +LL | pub(crate) () fn foo() {} + | ^ expected item -error: aborting due to previous error +error: aborting due to 2 previous errors From 20ba6875e695dd985ba7f8974cc10c665f687670 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 11:35:36 +0100 Subject: [PATCH 17/27] parser_item_mod: avoid cloning outer attributes --- src/librustc_parse/config.rs | 11 +++-------- src/librustc_parse/parser/item.rs | 2 +- src/librustc_parse/parser/module.rs | 26 ++++++++++++-------------- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 8dec64c579e88..1c479295af3ed 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -562,14 +562,9 @@ fn is_cfg(attr: &Attribute) -> bool { /// Process the potential `cfg` attributes on a module. /// Also determine if the module should be included in this configuration. -pub fn process_configure_mod( - sess: &ParseSess, - cfg_mods: bool, - attrs: &[Attribute], -) -> (bool, Vec) { +pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec) -> bool { // Don't perform gated feature checking. let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - let mut attrs = attrs.to_owned(); - strip_unconfigured.process_cfg_attrs(&mut attrs); - (!cfg_mods || strip_unconfigured.in_cfg(&attrs), attrs) + strip_unconfigured.process_cfg_attrs(attrs); + !cfg_mods || strip_unconfigured.in_cfg(&attrs) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 9ba3be041b5e6..38e87cfbc07e7 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -168,7 +168,7 @@ impl<'a> Parser<'a> { self.parse_item_impl(unsafety, defaultness)? } else if self.eat_keyword(kw::Mod) { // MODULE ITEM - self.parse_item_mod(&attrs[..])? + self.parse_item_mod(attrs)? } else if self.eat_keyword(kw::Type) { // TYPE ITEM let (ident, ty, generics) = self.parse_type_alias()?; diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 0c8fad03d8690..36a1e87956fa6 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -40,36 +40,34 @@ impl<'a> Parser<'a> { } /// Parses a `mod { ... }` or `mod ;` item. - pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> { - let (in_cfg, outer_attrs) = - crate::config::process_configure_mod(self.sess, self.cfg_mods, outer_attrs); + pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs); let id_span = self.token.span; let id = self.parse_ident()?; - if self.eat(&token::Semi) { + let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { // This mod is in an external file. Let's go get it! let ModulePathSuccess { path, directory_ownership } = - self.submod_path(id, &outer_attrs, id_span)?; - let (module, attrs) = - self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?; - Ok((id, ItemKind::Mod(module), Some(attrs))) + self.submod_path(id, &attrs, id_span)?; + self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)? } else { - let placeholder = ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }; - Ok((id, ItemKind::Mod(placeholder), None)) + (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) } } else { let old_directory = self.directory.clone(); - self.push_directory(id, &outer_attrs); + self.push_directory(id, &attrs); self.expect(&token::OpenDelim(token::Brace))?; let mod_inner_lo = self.token.span; - let attrs = self.parse_inner_attributes()?; + let inner_attrs = self.parse_inner_attributes()?; let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; self.directory = old_directory; - Ok((id, ItemKind::Mod(module), Some(attrs))) - } + (module, inner_attrs) + }; + attrs.append(&mut inner_attrs); + Ok((id, ItemKind::Mod(module), None)) } /// Given a termination token, parses all of the items in a module. From c2026030b5d761a83d62c7e198057b119addcfd1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 12:09:21 +0100 Subject: [PATCH 18/27] parser: remove `Option>` in `ItemInfo`. --- src/librustc_parse/parser/item.rs | 107 +++++++++++++--------------- src/librustc_parse/parser/module.rs | 2 +- 2 files changed, 50 insertions(+), 59 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 38e87cfbc07e7..745d125b58c8f 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -22,7 +22,7 @@ use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree}; use log::debug; use std::mem; -pub(super) type ItemInfo = (Ident, ItemKind, Option>); +pub(super) type ItemInfo = (Ident, ItemKind); impl<'a> Parser<'a> { pub fn parse_item(&mut self) -> PResult<'a, Option>> { @@ -85,8 +85,8 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; - if let Some(info) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { - return Ok(Some(self.mk_item_with_info(attrs, lo, vis, info))); + if let Some((ident, kind)) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { + return Ok(Some(self.mk_item(lo.to(self.prev_span), ident, kind, vis, attrs))); } // FAILURE TO PARSE ITEM @@ -118,18 +118,18 @@ impl<'a> Parser<'a> { // USE ITEM let tree = self.parse_use_tree()?; self.expect_semi()?; - (Ident::invalid(), ItemKind::Use(P(tree)), None) + (Ident::invalid(), ItemKind::Use(P(tree))) } else if self.check_fn_front_matter() { // FUNCTION ITEM let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, |_| true)?; - (ident, ItemKind::Fn(sig, generics, body), None) + (ident, ItemKind::Fn(sig, generics, body)) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { // EXTERN CRATE self.parse_item_extern_crate()? } else { // EXTERN BLOCK - self.parse_item_foreign_mod()? + self.parse_item_foreign_mod(attrs)? } } else if self.is_static_global() { // STATIC ITEM @@ -156,7 +156,7 @@ impl<'a> Parser<'a> { { // UNSAFE TRAIT ITEM let unsafety = self.parse_unsafety(); - self.parse_item_trait(lo, unsafety)? + self.parse_item_trait(attrs, lo, unsafety)? } else if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) @@ -165,14 +165,14 @@ impl<'a> Parser<'a> { let defaultness = self.parse_defaultness(); let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Impl)?; - self.parse_item_impl(unsafety, defaultness)? + self.parse_item_impl(attrs, unsafety, defaultness)? } else if self.eat_keyword(kw::Mod) { // MODULE ITEM self.parse_item_mod(attrs)? } else if self.eat_keyword(kw::Type) { // TYPE ITEM let (ident, ty, generics) = self.parse_type_alias()?; - (ident, ItemKind::TyAlias(ty, generics), None) + (ident, ItemKind::TyAlias(ty, generics)) } else if self.eat_keyword(kw::Enum) { // ENUM ITEM self.parse_item_enum()? @@ -180,7 +180,7 @@ impl<'a> Parser<'a> { || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait])) { // TRAIT ITEM - self.parse_item_trait(lo, Unsafe::No)? + self.parse_item_trait(attrs, lo, Unsafe::No)? } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM self.parse_item_struct()? @@ -306,26 +306,6 @@ impl<'a> Parser<'a> { } } - pub(super) fn mk_item_with_info( - &self, - attrs: Vec, - lo: Span, - vis: Visibility, - info: ItemInfo, - ) -> P { - let (ident, item, extra_attrs) = info; - let span = lo.to(self.prev_span); - let attrs = Self::maybe_append(attrs, extra_attrs); - self.mk_item(span, ident, item, vis, attrs) - } - - fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { - if let Some(ref mut rhs) = rhs { - lhs.append(rhs); - } - lhs - } - /// Parses an item macro, e.g., `item!();`. fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { self.complain_if_pub_macro(&vis.node, vis.span); @@ -339,7 +319,7 @@ impl<'a> Parser<'a> { } let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; - Ok((Ident::invalid(), ItemKind::Mac(mac), None)) + Ok((Ident::invalid(), ItemKind::Mac(mac))) } /// Emits an expected-item-after-attributes error. @@ -428,16 +408,21 @@ impl<'a> Parser<'a> { /// Parses an implementation item, `impl` keyword is already parsed. /// - /// impl<'a, T> TYPE { /* impl items */ } - /// impl<'a, T> TRAIT for TYPE { /* impl items */ } - /// impl<'a, T> !TRAIT for TYPE { /* impl items */ } - /// impl<'a, T> const TRAIT for TYPE { /* impl items */ } + /// ``` + /// impl<'a, T> TYPE { /* impl items */ } + /// impl<'a, T> TRAIT for TYPE { /* impl items */ } + /// impl<'a, T> !TRAIT for TYPE { /* impl items */ } + /// impl<'a, T> const TRAIT for TYPE { /* impl items */ } + /// ``` /// /// We actually parse slightly more relaxed grammar for better error reporting and recovery. - /// `impl` GENERICS `const`? `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}` - /// `impl` GENERICS `const`? `!`? TYPE (`where` PREDICATES)? `{` BODY `}` + /// ``` + /// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}" + /// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}" + /// ``` fn parse_item_impl( &mut self, + attrs: &mut Vec, unsafety: Unsafe, defaultness: Defaultness, ) -> PResult<'a, ItemInfo> { @@ -492,7 +477,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; - let (impl_items, attrs) = self.parse_item_list(|p, at_end| p.parse_impl_item(at_end))?; + let impl_items = self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end))?; let item_kind = match ty_second { Some(ty_second) => { @@ -545,15 +530,16 @@ impl<'a> Parser<'a> { } }; - Ok((Ident::invalid(), item_kind, Some(attrs))) + Ok((Ident::invalid(), item_kind)) } fn parse_item_list( &mut self, + attrs: &mut Vec, mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, T>, - ) -> PResult<'a, (Vec, Vec)> { + ) -> PResult<'a, Vec> { self.expect(&token::OpenDelim(token::Brace))?; - let attrs = self.parse_inner_attributes()?; + attrs.append(&mut self.parse_inner_attributes()?); let mut items = Vec::new(); while !self.eat(&token::CloseDelim(token::Brace)) { @@ -572,7 +558,7 @@ impl<'a> Parser<'a> { } } } - Ok((items, attrs)) + Ok(items) } /// Recover on a doc comment before `}`. @@ -624,7 +610,12 @@ impl<'a> Parser<'a> { } /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafe) -> PResult<'a, ItemInfo> { + fn parse_item_trait( + &mut self, + attrs: &mut Vec, + lo: Span, + unsafety: Unsafe, + ) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No }; @@ -662,12 +653,12 @@ impl<'a> Parser<'a> { self.sess.gated_spans.gate(sym::trait_alias, whole_span); - Ok((ident, ItemKind::TraitAlias(tps, bounds), None)) + Ok((ident, ItemKind::TraitAlias(tps, bounds))) } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - let (items, attrs) = self.parse_item_list(|p, at_end| p.parse_trait_item(at_end))?; - Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items), Some(attrs))) + let items = self.parse_item_list(attrs, |p, at_end| p.parse_trait_item(at_end))?; + Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items))) } } @@ -854,7 +845,7 @@ impl<'a> Parser<'a> { (orig_name, None) }; self.expect_semi()?; - Ok((item_name, ItemKind::ExternCrate(orig_name), None)) + Ok((item_name, ItemKind::ExternCrate(orig_name))) } fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> { @@ -905,11 +896,11 @@ impl<'a> Parser<'a> { /// extern "C" {} /// extern {} /// ``` - fn parse_item_foreign_mod(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_foreign_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? - let (items, attrs) = self.parse_item_list(|p, at_end| p.parse_foreign_item(at_end))?; + let items = self.parse_item_list(attrs, |p, at_end| p.parse_foreign_item(at_end))?; let module = ast::ForeignMod { abi, items }; - Ok((Ident::invalid(), ItemKind::ForeignMod(module), Some(attrs))) + Ok((Ident::invalid(), ItemKind::ForeignMod(module))) } /// Parses a foreign item (one in an `extern { ... }` block). @@ -1016,7 +1007,7 @@ impl<'a> Parser<'a> { Some(m) => ItemKind::Static(ty, m, e), None => ItemKind::Const(ty, e), }; - Ok((id, item, None)) + Ok((id, item)) } /// We were supposed to parse `:` but instead, we're already at `=`. @@ -1069,7 +1060,7 @@ impl<'a> Parser<'a> { let enum_definition = EnumDef { variants: variants.into_iter().filter_map(|v| v).collect() }; - Ok((id, ItemKind::Enum(enum_definition, generics), None)) + Ok((id, ItemKind::Enum(enum_definition, generics))) } fn parse_enum_variant(&mut self) -> PResult<'a, Option> { @@ -1163,7 +1154,7 @@ impl<'a> Parser<'a> { return Err(err); }; - Ok((class_name, ItemKind::Struct(vdata, generics), None)) + Ok((class_name, ItemKind::Struct(vdata, generics))) } /// Parses `union Foo { ... }`. @@ -1187,7 +1178,7 @@ impl<'a> Parser<'a> { return Err(err); }; - Ok((class_name, ItemKind::Union(vdata, generics), None)) + Ok((class_name, ItemKind::Union(vdata, generics))) } pub(super) fn is_union_item(&self) -> bool { @@ -1369,7 +1360,7 @@ impl<'a> Parser<'a> { }; self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_span)); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false }), None)) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false }))) } /// Is this unambiguously the start of a `macro_rules! foo` item defnition? @@ -1391,7 +1382,7 @@ impl<'a> Parser<'a> { self.report_invalid_macro_expansion_item(); } - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }), None)) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) } pub(super) fn eat_macro_def( @@ -1400,14 +1391,14 @@ impl<'a> Parser<'a> { vis: &Visibility, lo: Span, ) -> PResult<'a, Option>> { - let info = if self.eat_keyword(kw::Macro) { + let (ident, kind) = if self.eat_keyword(kw::Macro) { self.parse_item_decl_macro(lo)? } else if self.is_macro_rules_item() { self.parse_item_macro_rules(vis)? } else { return Ok(None); }; - Ok(Some(self.mk_item_with_info(attrs.to_vec(), lo, vis.clone(), info))) + Ok(Some(self.mk_item(lo.to(self.prev_span), ident, kind, vis.clone(), attrs.to_vec()))) } fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 36a1e87956fa6..754923ae55e29 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -67,7 +67,7 @@ impl<'a> Parser<'a> { (module, inner_attrs) }; attrs.append(&mut inner_attrs); - Ok((id, ItemKind::Mod(module), None)) + Ok((id, ItemKind::Mod(module))) } /// Given a termination token, parses all of the items in a module. From fd64b3bcdfcc844b9b25318106917937f7b17b94 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 12:31:51 +0100 Subject: [PATCH 19/27] parser: make `eat_macro_def` redundant. --- src/librustc_parse/parser/item.rs | 35 ++++++++----------------------- src/librustc_parse/parser/stmt.rs | 10 +++------ 2 files changed, 12 insertions(+), 33 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 745d125b58c8f..27b3d501751b7 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -86,7 +86,7 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; if let Some((ident, kind)) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { - return Ok(Some(self.mk_item(lo.to(self.prev_span), ident, kind, vis, attrs))); + return Ok(Some(P(self.mk_item(lo, ident, kind, vis, attrs)))); } // FAILURE TO PARSE ITEM @@ -942,9 +942,7 @@ impl<'a> Parser<'a> { } self.unexpected()? }; - - let span = lo.to(self.prev_span); - Ok(P(ast::ForeignItem { ident, attrs, kind, id: DUMMY_NODE_ID, span, vis, tokens: None })) + Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) } /// Parses a static item from a foreign module. @@ -1364,7 +1362,7 @@ impl<'a> Parser<'a> { } /// Is this unambiguously the start of a `macro_rules! foo` item defnition? - fn is_macro_rules_item(&mut self) -> bool { + pub(super) fn is_macro_rules_item(&mut self) -> bool { self.check_keyword(sym::macro_rules) && self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) @@ -1385,22 +1383,6 @@ impl<'a> Parser<'a> { Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) } - pub(super) fn eat_macro_def( - &mut self, - attrs: &[Attribute], - vis: &Visibility, - lo: Span, - ) -> PResult<'a, Option>> { - let (ident, kind) = if self.eat_keyword(kw::Macro) { - self.parse_item_decl_macro(lo)? - } else if self.is_macro_rules_item() { - self.parse_item_macro_rules(vis)? - } else { - return Ok(None); - }; - Ok(Some(self.mk_item(lo.to(self.prev_span), ident, kind, vis.clone(), attrs.to_vec()))) - } - fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { match *vis { VisibilityKind::Inherited => {} @@ -1496,15 +1478,16 @@ impl<'a> Parser<'a> { Ok(true) } - fn mk_item( + fn mk_item( &self, - span: Span, + lo: Span, ident: Ident, - kind: ItemKind, + kind: K, vis: Visibility, attrs: Vec, - ) -> P { - P(Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, span, tokens: None }) + ) -> Item { + let span = lo.to(self.prev_span); + Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, span, tokens: None } } } diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index e97af0dc00c69..b111b45e70990 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -7,10 +7,10 @@ use crate::maybe_whole; use crate::DirectoryOwnership; use rustc_errors::{Applicability, PResult}; -use rustc_span::source_map::{respan, BytePos, Span}; +use rustc_span::source_map::{BytePos, Span}; use rustc_span::symbol::{kw, sym, Symbol}; use syntax::ast; -use syntax::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle, VisibilityKind}; +use syntax::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle}; use syntax::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID}; use syntax::ptr::P; use syntax::token::{self, TokenKind}; @@ -55,11 +55,6 @@ impl<'a> Parser<'a> { return self.recover_stmt_local(lo, attrs.into(), msg, "let"); } - let mac_vis = respan(lo, VisibilityKind::Inherited); - if let Some(macro_def) = self.eat_macro_def(&attrs, &mac_vis, lo)? { - return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Item(macro_def)))); - } - // Starts like a simple path, being careful to avoid contextual keywords // such as a union items, item with `crate` visibility or auto trait items. // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts @@ -70,6 +65,7 @@ impl<'a> Parser<'a> { && !self.is_crate_vis() // `crate::b::c` - path, `crate struct S;` - not a path. && !self.is_auto_trait_item() && !self.is_async_fn() + && !self.is_macro_rules_item() { let path = self.parse_path(PathStyle::Expr)?; From 15e07a6a11bc5ed86e33403eb4b7d718d1636855 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 13:37:23 +0100 Subject: [PATCH 20/27] parser: fuse `trait` parsing & layer with `is_path_start_item` --- src/librustc_parse/parser/item.rs | 46 +++++++++++++++++-------------- src/librustc_parse/parser/stmt.rs | 16 +---------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 27b3d501751b7..6de82d8f9be59 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -152,11 +152,9 @@ impl<'a> Parser<'a> { } self.parse_item_const(None)? - } else if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) - { - // UNSAFE TRAIT ITEM - let unsafety = self.parse_unsafety(); - self.parse_item_trait(attrs, lo, unsafety)? + } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() { + // TRAIT ITEM + self.parse_item_trait(attrs, lo)? } else if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) @@ -176,11 +174,6 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Enum) { // ENUM ITEM self.parse_item_enum()? - } else if self.check_keyword(kw::Trait) - || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait])) - { - // TRAIT ITEM - self.parse_item_trait(attrs, lo, Unsafe::No)? } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM self.parse_item_struct()? @@ -209,6 +202,15 @@ impl<'a> Parser<'a> { Ok(Some(info)) } + /// When parsing a statement, would the start of a path be an item? + pub(super) fn is_path_start_item(&mut self) -> bool { + self.is_crate_vis() // no: `crate::b`, yes: `crate $item` + || self.is_union_item() // no: `union::b`, yes: `union U { .. }` + || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }` + || self.is_async_fn() // no(2015): `async::b`, yes: `async fn` + || self.is_macro_rules_item() // no: `macro_rules::b`, yes: `macro_rules! mac` + } + /// Recover on encountering a struct or method definition where the user /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`. fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> { @@ -338,7 +340,7 @@ impl<'a> Parser<'a> { Err(err) } - pub(super) fn is_async_fn(&self) -> bool { + fn is_async_fn(&self) -> bool { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } @@ -609,13 +611,17 @@ impl<'a> Parser<'a> { } } - /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait( - &mut self, - attrs: &mut Vec, - lo: Span, - unsafety: Unsafe, - ) -> PResult<'a, ItemInfo> { + /// Is this an `(unsafe auto? | auto) trait` item? + fn check_auto_or_unsafe_trait_item(&mut self) -> bool { + // auto trait + self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait]) + // unsafe auto trait + || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) + } + + /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`. + fn parse_item_trait(&mut self, attrs: &mut Vec, lo: Span) -> PResult<'a, ItemInfo> { + let unsafety = self.parse_unsafety(); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No }; @@ -1179,7 +1185,7 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics))) } - pub(super) fn is_union_item(&self) -> bool { + fn is_union_item(&self) -> bool { self.token.is_keyword(kw::Union) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) } @@ -1362,7 +1368,7 @@ impl<'a> Parser<'a> { } /// Is this unambiguously the start of a `macro_rules! foo` item defnition? - pub(super) fn is_macro_rules_item(&mut self) -> bool { + fn is_macro_rules_item(&mut self) -> bool { self.check_keyword(sym::macro_rules) && self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index b111b45e70990..439d0368d0961 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -61,11 +61,7 @@ impl<'a> Parser<'a> { // like a path (1 token), but it fact not a path. if self.token.is_path_start() && !self.token.is_qpath_start() - && !self.is_union_item() // `union::b::c` - path, `union U { ... }` - not a path. - && !self.is_crate_vis() // `crate::b::c` - path, `crate struct S;` - not a path. - && !self.is_auto_trait_item() - && !self.is_async_fn() - && !self.is_macro_rules_item() + && !self.is_path_start_item() // Confirm we don't steal syntax from `parse_item_`. { let path = self.parse_path(PathStyle::Expr)?; @@ -295,16 +291,6 @@ impl<'a> Parser<'a> { } } - fn is_auto_trait_item(&self) -> bool { - // auto trait - (self.token.is_keyword(kw::Auto) && - self.is_keyword_ahead(1, &[kw::Trait])) - || // unsafe auto trait - (self.token.is_keyword(kw::Unsafe) && - self.is_keyword_ahead(1, &[kw::Auto]) && - self.is_keyword_ahead(2, &[kw::Trait])) - } - /// Parses a block. No inner attributes are allowed. pub fn parse_block(&mut self) -> PResult<'a, P> { maybe_whole!(self, NtBlock, |x| x); From 46d3ef58a8a184b5a76098b2ac0e66792a6def25 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 14:23:12 +0100 Subject: [PATCH 21/27] parser: extract `recover_const_mut`. --- src/librustc_parse/parser/item.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 6de82d8f9be59..f13898d702454 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -138,19 +138,7 @@ impl<'a> Parser<'a> { self.parse_item_const(Some(m))? } else if let Const::Yes(const_span) = self.parse_constness() { // CONST ITEM - if self.eat_keyword(kw::Mut) { - let prev_span = self.prev_span; - self.struct_span_err(prev_span, "const globals cannot be mutable") - .span_label(prev_span, "cannot be mutable") - .span_suggestion( - const_span, - "you might want to declare a static instead", - "static".to_owned(), - Applicability::MaybeIncorrect, - ) - .emit(); - } - + self.recover_const_mut(const_span); self.parse_item_const(None)? } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() { // TRAIT ITEM @@ -987,6 +975,22 @@ impl<'a> Parser<'a> { } } + /// Recover on `const mut` with `const` already eaten. + fn recover_const_mut(&mut self, const_span: Span) { + if self.eat_keyword(kw::Mut) { + let span = self.prev_span; + self.struct_span_err(span, "const globals cannot be mutable") + .span_label(span, "cannot be mutable") + .span_suggestion( + const_span, + "you might want to declare a static instead", + "static".to_owned(), + Applicability::MaybeIncorrect, + ) + .emit(); + } + } + /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty = $expr` with /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. /// From aaaf0ba072815d275820d8ac85ece6eeb9182321 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 1 Feb 2020 06:18:10 +0100 Subject: [PATCH 22/27] parser: misc small item related improvements & cleanups. --- src/librustc_parse/parser/item.rs | 258 ++++++++---------- src/librustc_parse/parser/mod.rs | 5 + src/librustc_parse/parser/stmt.rs | 18 +- src/test/ui/issues/issue-58856-2.stderr | 4 +- src/test/ui/issues/issue-60075.stderr | 2 +- src/test/ui/macros/issue-54441.rs | 3 +- src/test/ui/macros/issue-54441.stderr | 16 +- src/test/ui/parser/attr-before-eof.stderr | 4 +- .../ui/parser/attr-dangling-in-mod.stderr | 4 +- .../ui/parser/attrs-after-extern-mod.stderr | 4 +- src/test/ui/parser/default.rs | 3 +- src/test/ui/parser/default.stderr | 6 +- src/test/ui/parser/doc-before-attr.stderr | 6 +- src/test/ui/parser/duplicate-visibility.rs | 3 +- .../ui/parser/duplicate-visibility.stderr | 6 +- src/test/ui/parser/issue-19398.rs | 3 +- src/test/ui/parser/issue-19398.stderr | 13 +- src/test/ui/parser/issue-20711-2.rs | 3 +- src/test/ui/parser/issue-20711-2.stderr | 8 +- src/test/ui/parser/issue-20711.rs | 3 +- src/test/ui/parser/issue-20711.stderr | 8 +- src/test/ui/parser/issue-32446.stderr | 4 +- src/test/ui/parser/issue-41155.stderr | 4 +- ...-58094-missing-right-square-bracket.stderr | 4 +- src/test/ui/parser/macro/pub-item-macro.rs | 11 +- .../ui/parser/macro/pub-item-macro.stderr | 12 +- .../parser/macro/trait-non-item-macros.stderr | 4 +- .../missing-close-brace-in-impl-trait.rs | 6 +- .../missing-close-brace-in-impl-trait.stderr | 25 +- .../missing-close-brace-in-trait.rs | 2 +- .../missing-close-brace-in-trait.stderr | 6 +- src/test/ui/parser/pub-method-macro.rs | 3 +- src/test/ui/parser/pub-method-macro.stderr | 2 +- .../ui/parser/removed-syntax-static-fn.rs | 2 +- .../ui/parser/removed-syntax-static-fn.stderr | 13 +- .../ui/pub/pub-restricted-error-fn.stderr | 4 +- 36 files changed, 233 insertions(+), 249 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index f13898d702454..af9700ee81e55 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -8,8 +8,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey}; use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::BytePos; -use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; +use syntax::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind}; use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; @@ -90,18 +89,18 @@ impl<'a> Parser<'a> { } // FAILURE TO PARSE ITEM - match vis.node { - VisibilityKind::Inherited => {} - _ => { - self.struct_span_err(vis.span, "unmatched visibility `pub`") - .span_label(vis.span, "the unmatched visibility") - .help("you likely meant to define an item, e.g., `pub fn foo() {}`") - .emit(); - } + if let VisibilityKind::Inherited = vis.node { + } else { + let vs = pprust::vis_to_string(&vis); + let vs = vs.trim_end(); + self.struct_span_err(vis.span, &format!("unmatched visibility `{}`", vs)) + .span_label(vis.span, "the unmatched visibility") + .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs)) + .emit(); } - if !attributes_allowed && !attrs.is_empty() { - self.expected_item_err(&attrs)?; + if !attributes_allowed { + self.recover_attrs_no_item(&attrs)?; } Ok(None) } @@ -165,7 +164,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM self.parse_item_struct()? - } else if self.is_union_item() { + } else if self.is_kw_followed_by_ident(kw::Union) { // UNION ITEM self.bump(); // `union` self.parse_item_union()? @@ -175,15 +174,12 @@ impl<'a> Parser<'a> { } else if self.is_macro_rules_item() { // MACRO_RULES ITEM self.parse_item_macro_rules(vis)? - } else if vis.node.is_pub() - && self.check_ident() - && self.look_ahead(1, |t| *t != token::Not) - { + } else if vis.node.is_pub() && self.isnt_macro_invocation() { self.recover_missing_kw_before_item()?; return Ok(None); } else if macros_allowed && self.token.is_path_start() { // MACRO INVOCATION ITEM - self.parse_item_macro(vis)? + (Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?)) } else { return Ok(None); }; @@ -193,12 +189,17 @@ impl<'a> Parser<'a> { /// When parsing a statement, would the start of a path be an item? pub(super) fn is_path_start_item(&mut self) -> bool { self.is_crate_vis() // no: `crate::b`, yes: `crate $item` - || self.is_union_item() // no: `union::b`, yes: `union U { .. }` + || self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }` || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }` || self.is_async_fn() // no(2015): `async::b`, yes: `async fn` || self.is_macro_rules_item() // no: `macro_rules::b`, yes: `macro_rules! mac` } + /// Are we sure this could not possibly be a macro invocation? + fn isnt_macro_invocation(&mut self) -> bool { + self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::ModSep) + } + /// Recover on encountering a struct or method definition where the user /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`. fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> { @@ -297,33 +298,33 @@ impl<'a> Parser<'a> { } /// Parses an item macro, e.g., `item!();`. - fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { - self.complain_if_pub_macro(&vis.node, vis.span); - - // Item macro - let path = self.parse_path(PathStyle::Mod)?; - self.expect(&token::Not)?; - let args = self.parse_mac_args()?; - if args.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } - - let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; - Ok((Ident::invalid(), ItemKind::Mac(mac))) - } - - /// Emits an expected-item-after-attributes error. - fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { - let message = match attrs.last() { - Some(&Attribute { kind: AttrKind::DocComment(_), .. }) => { - "expected item after doc comment" - } - _ => "expected item after attributes", + fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, Mac> { + let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` + self.expect(&token::Not)?; // `!` + let args = self.parse_mac_args()?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. + self.eat_semi_for_macro_if_needed(&args); + self.complain_if_pub_macro(vis, false); + Ok(Mac { path, args, prior_type_ascription: self.last_type_ascription }) + } + + /// Recover if we parsed attributes and expected an item but there was none. + fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { + let (start, end) = match attrs { + [] => return Ok(()), + [x0] => (x0, x0), + [x0, .., xn] => (x0, xn), }; - - let mut err = self.struct_span_err(self.prev_span, message); - if attrs.last().unwrap().is_doc_comment() { - err.span_label(self.prev_span, "this doc comment doesn't document anything"); + let msg = if end.is_doc_comment() { + "expected item after doc comment" + } else { + "expected item after attributes" + }; + let mut err = self.struct_span_err(end.span, msg); + if end.is_doc_comment() { + err.span_label(end.span, "this doc comment doesn't document anything"); + } + if let [.., penultimate, _] = attrs { + err.span_label(start.span.to(penultimate.span), "other attributes here"); } Err(err) } @@ -332,38 +333,19 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - /// Parses a macro invocation inside a `trait`, `impl` or `extern` block. + /// Parses a macro invocation inside a `trait`, `impl`, or `extern` block. fn parse_assoc_macro_invoc( &mut self, item_kind: &str, - vis: Option<&Visibility>, + vis: &Visibility, at_end: &mut bool, ) -> PResult<'a, Option> { - if self.token.is_path_start() && !(self.is_async_fn() && self.token.span.rust_2015()) { - let prev_span = self.prev_span; - let path = self.parse_path(PathStyle::Mod)?; - - if path.segments.len() == 1 { - if !self.eat(&token::Not) { - return Err(self.missing_assoc_item_kind_err(item_kind, prev_span)); - } - } else { - self.expect(&token::Not)?; - } - - if let Some(vis) = vis { - self.complain_if_pub_macro(&vis.node, prev_span); - } - + if self.isnt_macro_invocation() { + Err(self.missing_assoc_item_kind_err(item_kind, self.prev_span)) + } else if self.token.is_path_start() { + let mac = self.parse_item_macro(vis)?; *at_end = true; - - // eat a matched-delimiter token tree: - let args = self.parse_mac_args()?; - if args.need_semicolon() { - self.expect_semi()?; - } - - Ok(Some(Mac { path, args, prior_type_ascription: self.last_type_ascription })) + Ok(Some(mac)) } else { Ok(None) } @@ -389,7 +371,7 @@ impl<'a> Parser<'a> { // | ^ missing `fn`, `type`, or `const` // pub path( // ^^ `sp` below will point to this - let sp = prev_span.between(self.prev_span); + let sp = prev_span.between(self.token.span); let mut err = self .struct_span_err(sp, &format!("{} for {}-item declaration", expected_kinds, item_type)); err.span_label(sp, expected_kinds); @@ -706,10 +688,13 @@ impl<'a> Parser<'a> { } else if self.check_fn_front_matter() { let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?; (ident, AssocItemKind::Fn(sig, body), generics) - } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", Some(&vis), at_end)? { + } else if self.check_keyword(kw::Const) { + self.parse_assoc_const()? + } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", &vis, at_end)? { (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default()) } else { - self.parse_assoc_const()? + self.recover_attrs_no_item(&attrs)?; + self.unexpected()? }; let span = lo.to(self.prev_span); @@ -813,7 +798,7 @@ impl<'a> Parser<'a> { fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { match self.token.kind { - token::Ident(name, false) if name == kw::Underscore => { + token::Ident(name @ kw::Underscore, false) => { let span = self.token.span; self.bump(); Ok(Ident::new(name, span)) @@ -928,12 +913,10 @@ impl<'a> Parser<'a> { ) .emit(); self.parse_item_foreign_static()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), at_end)? { + } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", &vis, at_end)? { (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { - if !attrs.is_empty() { - self.expected_item_err(&attrs)?; - } + self.recover_attrs_no_item(&attrs)?; self.unexpected()? }; Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) @@ -1189,11 +1172,6 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics))) } - fn is_union_item(&self) -> bool { - self.token.is_keyword(kw::Union) - && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) - } - fn parse_record_struct_body( &mut self, ) -> PResult<'a, (Vec, /* recovered */ bool)> { @@ -1343,24 +1321,26 @@ impl<'a> Parser<'a> { /// Parses a declarative macro 2.0 definition. /// The `macro` keyword has already been parsed. + /// ``` + /// MacBody = "{" TOKEN_STREAM "}" ; + /// MacParams = "(" TOKEN_STREAM ")" ; + /// DeclMac = "macro" Ident MacParams? MacBody ; + /// ``` fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> { let ident = self.parse_ident()?; let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_mac_args()? + self.parse_mac_args()? // `MacBody` } else if self.check(&token::OpenDelim(token::Paren)) { - let params = self.parse_token_tree(); + let params = self.parse_token_tree(); // `MacParams` let pspan = params.span(); - let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_token_tree() - } else { + if !self.check(&token::OpenDelim(token::Brace)) { return self.unexpected(); - }; + } + let body = self.parse_token_tree(); // `MacBody` + // Convert `MacParams MacBody` into `{ MacParams => MacBody }`. let bspan = body.span(); - let tokens = TokenStream::new(vec![ - params.into(), - TokenTree::token(token::FatArrow, pspan.between(bspan)).into(), - body.into(), - ]); + let arrow = TokenTree::token(token::FatArrow, pspan.between(bspan)); // `=>` + let tokens = TokenStream::new(vec![params.into(), arrow.into(), body.into()]); let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); P(MacArgs::Delimited(dspan, MacDelimiter::Brace, tokens)) } else { @@ -1380,65 +1360,68 @@ impl<'a> Parser<'a> { /// Parses a legacy `macro_rules! foo { ... }` declarative macro. fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { - self.complain_if_pub_macro(&vis.node, vis.span); self.expect_keyword(sym::macro_rules)?; // `macro_rules` self.expect(&token::Not)?; // `!` let ident = self.parse_ident()?; let body = self.parse_mac_args()?; - if body.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } + self.eat_semi_for_macro_if_needed(&body); + self.complain_if_pub_macro(vis, true); Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) } - fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { - match *vis { - VisibilityKind::Inherited => {} - _ => { - let mut err = if self.token.is_keyword(sym::macro_rules) { - let mut err = - self.struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); - err.span_suggestion( - sp, - "try exporting the macro", - "#[macro_export]".to_owned(), - Applicability::MaybeIncorrect, // speculative - ); - err - } else { - let mut err = - self.struct_span_err(sp, "can't qualify macro invocation with `pub`"); - err.help("try adjusting the macro to put `pub` inside the invocation"); - err - }; - err.emit(); - } + /// Item macro invocations or `macro_rules!` definitions need inherited visibility. + /// If that's not the case, emit an error. + fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) { + if let VisibilityKind::Inherited = vis.node { + return; + } + + let vstr = pprust::vis_to_string(vis); + let vstr = vstr.trim_end(); + if macro_rules { + let msg = format!("can't qualify macro_rules invocation with `{}`", vstr); + self.struct_span_err(vis.span, &msg) + .span_suggestion( + vis.span, + "try exporting the macro", + "#[macro_export]".to_owned(), + Applicability::MaybeIncorrect, // speculative + ) + .emit(); + } else { + self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`") + .span_suggestion( + vis.span, + "remove the visibility", + String::new(), + Applicability::MachineApplicable, + ) + .help(&format!("try adjusting the macro to put `{}` inside the invocation", vstr)) + .emit(); } } - fn report_invalid_macro_expansion_item(&self) { - let has_close_delim = self - .sess - .source_map() - .span_to_snippet(self.prev_span) - .map(|s| s.ends_with(")") || s.ends_with("]")) - .unwrap_or(false); + fn eat_semi_for_macro_if_needed(&mut self, args: &MacArgs) { + if args.need_semicolon() && !self.eat(&token::Semi) { + self.report_invalid_macro_expansion_item(args); + } + } + fn report_invalid_macro_expansion_item(&self, args: &MacArgs) { let mut err = self.struct_span_err( self.prev_span, "macros that expand to items must be delimited with braces or followed by a semicolon", ); - - // To avoid ICE, we shouldn't emit actual suggestions when it hasn't closing delims - if has_close_delim { + if self.unclosed_delims.is_empty() { + let DelimSpan { open, close } = match args { + MacArgs::Empty | MacArgs::Eq(..) => unreachable!(), + MacArgs::Delimited(dspan, ..) => *dspan, + }; err.multipart_suggestion( "change the delimiters to curly braces", - vec![ - (self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), '{'.to_string()), - (self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()), - ], + vec![(open, "{".to_string()), (close, '}'.to_string())], Applicability::MaybeIncorrect, ); } else { @@ -1449,14 +1432,13 @@ impl<'a> Parser<'a> { Applicability::HasPlaceholders, ); } - err.span_suggestion( self.prev_span.shrink_to_hi(), "add a semicolon", ';'.to_string(), Applicability::MaybeIncorrect, - ) - .emit(); + ); + err.emit(); } /// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 4716d722778a6..79944dc35e523 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -572,6 +572,11 @@ impl<'a> Parser<'a> { if !self.eat_keyword(kw) { self.unexpected() } else { Ok(()) } } + /// Is the given keyword `kw` followed by a non-reserved identifier? + fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { + self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) + } + fn check_or_expected(&mut self, ok: bool, typ: TokenType) -> bool { if ok { true diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 439d0368d0961..742fc4802fd9d 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -8,7 +8,7 @@ use crate::DirectoryOwnership; use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::{BytePos, Span}; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{kw, sym}; use syntax::ast; use syntax::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle}; use syntax::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID}; @@ -55,13 +55,11 @@ impl<'a> Parser<'a> { return self.recover_stmt_local(lo, attrs.into(), msg, "let"); } - // Starts like a simple path, being careful to avoid contextual keywords - // such as a union items, item with `crate` visibility or auto trait items. - // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts - // like a path (1 token), but it fact not a path. - if self.token.is_path_start() - && !self.token.is_qpath_start() - && !self.is_path_start_item() // Confirm we don't steal syntax from `parse_item_`. + // Starts like a simple path, being careful to avoid contextual keywords, + // e.g., `union`, items with `crate` visibility, or `auto trait` items. + // We aim to parse an arbitrary path `a::b` but not something that starts like a path + // (1 token), but it fact not a path. Also, we avoid stealing syntax from `parse_item_`. + if self.token.is_path_start() && !self.token.is_qpath_start() && !self.is_path_start_item() { let path = self.parse_path(PathStyle::Expr)?; @@ -191,10 +189,6 @@ impl<'a> Parser<'a> { } } - fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { - self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) - } - fn recover_stmt_local( &mut self, lo: Span, diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr index 01d70d861e2c9..6221b90b31dd7 100644 --- a/src/test/ui/issues/issue-58856-2.stderr +++ b/src/test/ui/issues/issue-58856-2.stderr @@ -7,11 +7,11 @@ LL | fn how_are_you(&self -> Empty { | | help: `)` may belong here | unclosed delimiter -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `)` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `)` --> $DIR/issue-58856-2.rs:11:1 | LL | } - | - expected one of 10 possible tokens + | - expected one of 11 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index 60eb99b46b79f..b2beb73503bb0 100644 --- a/src/test/ui/issues/issue-60075.stderr +++ b/src/test/ui/issues/issue-60075.stderr @@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}` LL | }); | ^ expected one of `.`, `;`, `?`, `else`, or an operator -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `;` --> $DIR/issue-60075.rs:6:11 | LL | fn qux() -> Option { diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs index afdf76b7b580f..a70163df1cb93 100644 --- a/src/test/ui/macros/issue-54441.rs +++ b/src/test/ui/macros/issue-54441.rs @@ -1,6 +1,7 @@ macro_rules! m { + //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration () => { - let //~ ERROR expected + let }; } diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr index c94355f47161c..761e7aec7235a 100644 --- a/src/test/ui/macros/issue-54441.stderr +++ b/src/test/ui/macros/issue-54441.stderr @@ -1,13 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `static`, `type`, or `unsafe`, found keyword `let` - --> $DIR/issue-54441.rs:3:9 +error: missing `fn`, `type`, or `static` for extern-item declaration + --> $DIR/issue-54441.rs:1:1 | -LL | let - | ^^^ expected one of 9 possible tokens -... -LL | m!(); - | ----- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / macro_rules! m { +LL | | +LL | | () => { +LL | | let + | |________^ missing `fn`, `type`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/attr-before-eof.stderr b/src/test/ui/parser/attr-before-eof.stderr index eb5daf849811c..a2acb94372b8c 100644 --- a/src/test/ui/parser/attr-before-eof.stderr +++ b/src/test/ui/parser/attr-before-eof.stderr @@ -1,8 +1,8 @@ error: expected item after attributes - --> $DIR/attr-before-eof.rs:3:16 + --> $DIR/attr-before-eof.rs:3:1 | LL | #[derive(Debug)] - | ^ + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/attr-dangling-in-mod.stderr b/src/test/ui/parser/attr-dangling-in-mod.stderr index d896b61ce49c4..1c892eac08f3b 100644 --- a/src/test/ui/parser/attr-dangling-in-mod.stderr +++ b/src/test/ui/parser/attr-dangling-in-mod.stderr @@ -1,8 +1,8 @@ error: expected item after attributes - --> $DIR/attr-dangling-in-mod.rs:6:14 + --> $DIR/attr-dangling-in-mod.rs:6:1 | LL | #[foo = "bar"] - | ^ + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr index a02e738a2c38e..6060f3afe1e95 100644 --- a/src/test/ui/parser/attrs-after-extern-mod.stderr +++ b/src/test/ui/parser/attrs-after-extern-mod.stderr @@ -1,8 +1,8 @@ error: expected item after attributes - --> $DIR/attrs-after-extern-mod.rs:6:19 + --> $DIR/attrs-after-extern-mod.rs:6:5 | LL | #[cfg(stage37)] - | ^ + | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs index 17cd06864bf1d..65ecb1ebbe919 100644 --- a/src/test/ui/parser/default.rs +++ b/src/test/ui/parser/default.rs @@ -19,7 +19,8 @@ impl Foo for u16 { } impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo` - default pub fn foo() -> T { T::default() } //~ ERROR expected one of + default pub fn foo() -> T { T::default() } + //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration } fn main() {} diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr index dde36cf8ddeed..ede9e47151863 100644 --- a/src/test/ui/parser/default.stderr +++ b/src/test/ui/parser/default.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `pub` - --> $DIR/default.rs:22:13 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/default.rs:22:12 | LL | default pub fn foo() -> T { T::default() } - | ^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe` + | ^ missing `fn`, `type`, or `const` error[E0449]: unnecessary visibility qualifier --> $DIR/default.rs:16:5 diff --git a/src/test/ui/parser/doc-before-attr.stderr b/src/test/ui/parser/doc-before-attr.stderr index 0fae44ce5c806..14fd01af2f98a 100644 --- a/src/test/ui/parser/doc-before-attr.stderr +++ b/src/test/ui/parser/doc-before-attr.stderr @@ -1,8 +1,10 @@ error: expected item after attributes - --> $DIR/doc-before-attr.rs:4:16 + --> $DIR/doc-before-attr.rs:4:1 | +LL | /// hi + | ------ other attributes here LL | #[derive(Debug)] - | ^ + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index edbf508ecdb76..1d271fa64b0ec 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -1,7 +1,6 @@ -// error-pattern: expected one of `(`, `async`, `const`, `extern`, `fn` - fn main() {} extern { pub pub fn foo(); + //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index 92cf348796943..36a3a1ed5a0cc 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,8 +1,8 @@ -error: expected one of `(`, `async`, `const`, `extern`, `fn`, `static`, `type`, or `unsafe`, found keyword `pub` - --> $DIR/duplicate-visibility.rs:6:9 +error: missing `fn`, `type`, or `static` for extern-item declaration + --> $DIR/duplicate-visibility.rs:4:8 | LL | pub pub fn foo(); - | ^^^ expected one of 8 possible tokens + | ^ missing `fn`, `type`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issue-19398.rs index 2158a2fd6c11c..982a6be23ac5f 100644 --- a/src/test/ui/parser/issue-19398.rs +++ b/src/test/ui/parser/issue-19398.rs @@ -1,5 +1,6 @@ trait T { - extern "Rust" unsafe fn foo(); //~ ERROR expected one of `async`, `const` + //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration + extern "Rust" unsafe fn foo(); } fn main() {} diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issue-19398.stderr index 201a6b2d66a7c..2bd6ac3a4b3a4 100644 --- a/src/test/ui/parser/issue-19398.stderr +++ b/src/test/ui/parser/issue-19398.stderr @@ -1,10 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `extern` - --> $DIR/issue-19398.rs:2:5 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/issue-19398.rs:1:10 | -LL | trait T { - | - expected one of 10 possible tokens -LL | extern "Rust" unsafe fn foo(); - | ^^^^^^ unexpected token +LL | trait T { + | __________^ +LL | | +LL | | extern "Rust" unsafe fn foo(); + | |____^ missing `fn`, `type`, or `const` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-20711-2.rs b/src/test/ui/parser/issue-20711-2.rs index 0063a334182f4..168c7e76162bc 100644 --- a/src/test/ui/parser/issue-20711-2.rs +++ b/src/test/ui/parser/issue-20711-2.rs @@ -4,6 +4,7 @@ impl Foo { fn foo() {} #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or + //~^ ERROR expected item after attributes +} fn main() {} diff --git a/src/test/ui/parser/issue-20711-2.stderr b/src/test/ui/parser/issue-20711-2.stderr index ee484890fada8..10ef31584dec1 100644 --- a/src/test/ui/parser/issue-20711-2.stderr +++ b/src/test/ui/parser/issue-20711-2.stderr @@ -1,10 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}` - --> $DIR/issue-20711-2.rs:7:1 +error: expected item after attributes + --> $DIR/issue-20711-2.rs:6:5 | LL | #[stable(feature = "rust1", since = "1.0.0")] - | - expected one of 9 possible tokens -LL | } - | ^ unexpected token + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-20711.rs b/src/test/ui/parser/issue-20711.rs index dc216167b8a4f..020bb79d6e74e 100644 --- a/src/test/ui/parser/issue-20711.rs +++ b/src/test/ui/parser/issue-20711.rs @@ -2,6 +2,7 @@ struct Foo; impl Foo { #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or + //~^ ERROR expected item after attributes +} fn main() {} diff --git a/src/test/ui/parser/issue-20711.stderr b/src/test/ui/parser/issue-20711.stderr index 152c9f1c68975..66768de569418 100644 --- a/src/test/ui/parser/issue-20711.stderr +++ b/src/test/ui/parser/issue-20711.stderr @@ -1,10 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}` - --> $DIR/issue-20711.rs:5:1 +error: expected item after attributes + --> $DIR/issue-20711.rs:4:5 | LL | #[stable(feature = "rust1", since = "1.0.0")] - | - expected one of 9 possible tokens -LL | } - | ^ unexpected token + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr index 1a97f54160b24..25c1efe35ae11 100644 --- a/src/test/ui/parser/issue-32446.stderr +++ b/src/test/ui/parser/issue-32446.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `...` --> $DIR/issue-32446.rs:4:11 | LL | trait T { ... } - | ^^^ expected one of 10 possible tokens + | ^^^ expected one of 11 possible tokens error: aborting due to previous error diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr index 0e191eb7e0a04..327bc65818fa9 100644 --- a/src/test/ui/parser/issue-41155.stderr +++ b/src/test/ui/parser/issue-41155.stderr @@ -1,8 +1,8 @@ -error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found `}` +error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `type`, `unsafe`, or identifier, found `}` --> $DIR/issue-41155.rs:5:1 | LL | pub - | - expected one of 8 possible tokens + | - expected one of 9 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr b/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr index 00f6652b311da..8a44ee761ed67 100644 --- a/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr +++ b/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr @@ -7,10 +7,10 @@ LL | #[Ѕ | unclosed delimiter error: expected item after attributes - --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4 + --> $DIR/issue-58094-missing-right-square-bracket.rs:4:1 | LL | #[Ѕ - | ^ + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/macro/pub-item-macro.rs b/src/test/ui/parser/macro/pub-item-macro.rs index bae90227c62f4..f5f8a01e6a440 100644 --- a/src/test/ui/parser/macro/pub-item-macro.rs +++ b/src/test/ui/parser/macro/pub-item-macro.rs @@ -1,12 +1,15 @@ // Issue #14660 -macro_rules! priv_x { () => { - static x: u32 = 0; -}} +macro_rules! priv_x { + () => { + static x: u32 = 0; + }; +} macro_rules! pub_x { () => { pub priv_x!(); //~ ERROR can't qualify macro invocation with `pub` - //~^ HELP try adjusting the macro to put `pub` inside the invocation + //~^ HELP remove the visibility + //~| HELP try adjusting the macro to put `pub` inside the invocation }} mod foo { diff --git a/src/test/ui/parser/macro/pub-item-macro.stderr b/src/test/ui/parser/macro/pub-item-macro.stderr index 49644cf6a0e64..4ff96532e03a8 100644 --- a/src/test/ui/parser/macro/pub-item-macro.stderr +++ b/src/test/ui/parser/macro/pub-item-macro.stderr @@ -1,8 +1,8 @@ error: can't qualify macro invocation with `pub` - --> $DIR/pub-item-macro.rs:8:5 + --> $DIR/pub-item-macro.rs:10:5 | LL | pub priv_x!(); - | ^^^ + | ^^^ help: remove the visibility ... LL | pub_x!(); | --------- in this macro invocation @@ -11,16 +11,16 @@ LL | pub_x!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0603]: static `x` is private - --> $DIR/pub-item-macro.rs:17:23 + --> $DIR/pub-item-macro.rs:20:23 | LL | let y: u32 = foo::x; | ^ this static is private | note: the static `x` is defined here - --> $DIR/pub-item-macro.rs:4:5 + --> $DIR/pub-item-macro.rs:5:9 | -LL | static x: u32 = 0; - | ^^^^^^^^^^^^^^^^^^ +LL | static x: u32 = 0; + | ^^^^^^^^^^^^^^^^^^ ... LL | pub_x!(); | --------- in this macro invocation diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr index 5a89b5b936f5b..9d05e85bcc00e 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.stderr +++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or identifier, found `2` --> $DIR/trait-non-item-macros.rs:2:19 | LL | ($a:expr) => ($a) - | ^^ expected one of 9 possible tokens + | ^^ expected one of 10 possible tokens ... LL | bah!(2); | -------- in this macro invocation diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs index 9f02a7a997bf2..592215030f552 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs @@ -1,12 +1,14 @@ +fn main() {} + impl T for () { //~ ERROR cannot find trait `T` in this scope fn foo(&self) {} +//~^ ERROR missing `fn`, `type`, or `const` -trait T { //~ ERROR expected one of +trait T { fn foo(&self); } pub(crate) struct Bar(); -fn main() {} //~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr index a23cfeac58f84..1ec54525105f6 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/missing-close-brace-in-impl-trait.rs:12:52 + --> $DIR/missing-close-brace-in-impl-trait.rs:14:52 | LL | impl T for () { | - unclosed delimiter @@ -7,23 +7,18 @@ LL | impl T for () { LL | | ^ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `trait` - --> $DIR/missing-close-brace-in-impl-trait.rs:5:1 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/missing-close-brace-in-impl-trait.rs:5:17 | -LL | impl T for () { - | - unclosed delimiter -LL | -LL | fn foo(&self) {} - | - - | | - | expected one of 10 possible tokens - | help: `}` may belong here -LL | -LL | trait T { - | ^^^^^ unexpected token +LL | fn foo(&self) {} + | _________________^ +LL | | +LL | | +LL | | trait T { + | |_ missing `fn`, `type`, or `const` error[E0405]: cannot find trait `T` in this scope - --> $DIR/missing-close-brace-in-impl-trait.rs:1:6 + --> $DIR/missing-close-brace-in-impl-trait.rs:3:6 | LL | impl T for () { | ^ not found in this scope diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs index 5ec5d45bbe7b2..077e334719427 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs @@ -3,7 +3,7 @@ trait T { fn foo(&self); pub(crate) struct Bar(); -//~^ ERROR expected one of +//~^ ERROR missing `fn`, `type`, or `const` impl T for Bar { fn foo(&self) {} diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index 213640127829c..1bb153c461d90 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,11 +7,11 @@ LL | trait T { LL | fn main() {} | ^ -error: expected one of `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct` - --> $DIR/missing-close-brace-in-trait.rs:5:12 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/missing-close-brace-in-trait.rs:5:11 | LL | pub(crate) struct Bar(); - | ^^^^^^ expected one of 7 possible tokens + | ^ missing `fn`, `type`, or `const` error[E0601]: `main` function not found in crate `missing_close_brace_in_trait` --> $DIR/missing-close-brace-in-trait.rs:1:1 diff --git a/src/test/ui/parser/pub-method-macro.rs b/src/test/ui/parser/pub-method-macro.rs index f04af1a0d65ff..0183bdcf6220b 100644 --- a/src/test/ui/parser/pub-method-macro.rs +++ b/src/test/ui/parser/pub-method-macro.rs @@ -15,7 +15,8 @@ mod bleh { impl S { pub defn!(f); //~ ERROR can't qualify macro invocation with `pub` - //~^ HELP try adjusting the macro to put `pub` inside the invocation + //~^ HELP remove the visibility + //~| HELP try adjusting the macro to put `pub` inside the invocation } } diff --git a/src/test/ui/parser/pub-method-macro.stderr b/src/test/ui/parser/pub-method-macro.stderr index 7b0fe4934610d..7c7a909267a1c 100644 --- a/src/test/ui/parser/pub-method-macro.stderr +++ b/src/test/ui/parser/pub-method-macro.stderr @@ -2,7 +2,7 @@ error: can't qualify macro invocation with `pub` --> $DIR/pub-method-macro.rs:17:9 | LL | pub defn!(f); - | ^^^ + | ^^^ help: remove the visibility | = help: try adjusting the macro to put `pub` inside the invocation diff --git a/src/test/ui/parser/removed-syntax-static-fn.rs b/src/test/ui/parser/removed-syntax-static-fn.rs index 0caddb9855d83..9e12222f3fd8b 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.rs +++ b/src/test/ui/parser/removed-syntax-static-fn.rs @@ -1,8 +1,8 @@ struct S; impl S { + //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration static fn f() {} - //~^ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, } fn main() {} diff --git a/src/test/ui/parser/removed-syntax-static-fn.stderr b/src/test/ui/parser/removed-syntax-static-fn.stderr index dfadefee23c15..5edf88026fbec 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.stderr +++ b/src/test/ui/parser/removed-syntax-static-fn.stderr @@ -1,10 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `static` - --> $DIR/removed-syntax-static-fn.rs:4:5 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/removed-syntax-static-fn.rs:3:9 | -LL | impl S { - | - expected one of 10 possible tokens -LL | static fn f() {} - | ^^^^^^ unexpected token +LL | impl S { + | _________^ +LL | | +LL | | static fn f() {} + | |____^ missing `fn`, `type`, or `const` error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index c5acb92dcd436..c0168b02da607 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -1,10 +1,10 @@ -error: unmatched visibility `pub` +error: unmatched visibility `pub(crate)` --> $DIR/pub-restricted-error-fn.rs:1:1 | LL | pub(crate) () fn foo() {} | ^^^^^^^^^^ the unmatched visibility | - = help: you likely meant to define an item, e.g., `pub fn foo() {}` + = help: you likely meant to define an item, e.g., `pub(crate) fn foo() {}` error: expected item, found `(` --> $DIR/pub-restricted-error-fn.rs:1:12 From ad72c3abb9a7f9746d6ccc381e69ba88fb15b5cd Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 1 Feb 2020 10:26:11 +0100 Subject: [PATCH 23/27] parser: inline parse_assoc_macro_invoc --- src/librustc_parse/parser/item.rs | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index af9700ee81e55..500aaaf43b92a 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -333,24 +333,6 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - /// Parses a macro invocation inside a `trait`, `impl`, or `extern` block. - fn parse_assoc_macro_invoc( - &mut self, - item_kind: &str, - vis: &Visibility, - at_end: &mut bool, - ) -> PResult<'a, Option> { - if self.isnt_macro_invocation() { - Err(self.missing_assoc_item_kind_err(item_kind, self.prev_span)) - } else if self.token.is_path_start() { - let mac = self.parse_item_macro(vis)?; - *at_end = true; - Ok(Some(mac)) - } else { - Ok(None) - } - } - fn missing_assoc_item_kind_err( &self, item_type: &str, @@ -690,7 +672,11 @@ impl<'a> Parser<'a> { (ident, AssocItemKind::Fn(sig, body), generics) } else if self.check_keyword(kw::Const) { self.parse_assoc_const()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", &vis, at_end)? { + } else if self.isnt_macro_invocation() { + return Err(self.missing_assoc_item_kind_err("associated", self.prev_span)); + } else if self.token.is_path_start() { + let mac = self.parse_item_macro(&vis)?; + *at_end = true; (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default()) } else { self.recover_attrs_no_item(&attrs)?; @@ -913,7 +899,11 @@ impl<'a> Parser<'a> { ) .emit(); self.parse_item_foreign_static()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", &vis, at_end)? { + } else if self.isnt_macro_invocation() { + return Err(self.missing_assoc_item_kind_err("extern", self.prev_span)); + } else if self.token.is_path_start() { + let mac = self.parse_item_macro(&vis)?; + *at_end = true; (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { self.recover_attrs_no_item(&attrs)?; From 4706c38e17349793b2713947f81cfa1fd1f75ba3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 12 Feb 2020 19:46:05 +0100 Subject: [PATCH 24/27] Use HirId in TraitCandidate. --- src/librustc/ich/impls_hir.rs | 1 - src/librustc/ty/context.rs | 1 + src/librustc/ty/mod.rs | 20 +++++++++++++++++++- src/librustc_hir/hir.rs | 4 ++-- src/librustc_resolve/late.rs | 2 +- src/librustc_resolve/lib.rs | 4 ++-- src/librustc_typeck/check/method/probe.rs | 15 ++++++--------- 7 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 1a763e43d557d..eadc9ddeee6fc 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -270,7 +270,6 @@ impl<'a> ToStableHashKey> for hir::TraitCandidate { let import_keys = import_ids .iter() - .map(|node_id| hcx.node_to_hir_id(*node_id)) .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), hir_id.local_id)) .collect(); (hcx.def_path_hash(*def_id), import_keys) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2adf708641798..1a071905523ca 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1161,6 +1161,7 @@ impl<'tcx> TyCtxt<'tcx> { for (k, v) in resolutions.trait_map { let hir_id = hir.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); + let v = v.into_iter().map(|tc| tc.node_to_hir_id(&hir.definitions())).collect(); map.insert(hir_id.local_id, StableVec::new(v)); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2bda99e6d20fc..a561d48844b7a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -35,7 +35,7 @@ use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_hir::{Constness, GlobMap, Node, TraitMap}; +use rustc_hir::{Constness, GlobMap, Node}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_serialize::{self, Encodable, Encoder}; @@ -46,6 +46,7 @@ use rustc_target::abi::Align; use syntax::ast::{self, Ident, Name}; use syntax::node_id::{NodeId, NodeMap, NodeSet}; +use smallvec::SmallVec; use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; @@ -122,6 +123,23 @@ mod sty; // Data types +#[derive(Clone, Debug)] +pub struct TraitCandidate { + pub def_id: DefId, + pub import_ids: SmallVec<[NodeId; 1]>, +} + +impl TraitCandidate { + fn node_to_hir_id(self, definitions: &hir_map::Definitions) -> hir::TraitCandidate { + let TraitCandidate { def_id, import_ids } = self; + let import_ids = + import_ids.into_iter().map(|node_id| definitions.node_to_hir_id(node_id)).collect(); + hir::TraitCandidate { def_id, import_ids } + } +} + +pub type TraitMap = NodeMap>; + pub struct ResolverOutputs { pub definitions: hir_map::Definitions, pub cstore: Box, diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index c2ddaf7df316a..0667bd3f4a219 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -16,7 +16,7 @@ use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; -use syntax::ast::{self, AsmDialect, CrateSugar, Ident, Name, NodeId}; +use syntax::ast::{self, AsmDialect, CrateSugar, Ident, Name}; use syntax::ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy}; pub use syntax::ast::{BorrowKind, ImplPolarity, IsAuto}; pub use syntax::ast::{CaptureBy, Movability, Mutability}; @@ -2610,7 +2610,7 @@ pub type CaptureModeMap = NodeMap; #[derive(Clone, Debug)] pub struct TraitCandidate { pub def_id: DefId, - pub import_ids: SmallVec<[NodeId; 1]>, + pub import_ids: SmallVec<[HirId; 1]>, } // Trait method resolution diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 58ff7f447890c..ea865a5590ae7 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -11,13 +11,13 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; +use rustc::ty::TraitCandidate; use rustc::{bug, lint, span_bug}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; -use rustc_hir::TraitCandidate; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2e63c3e170605..cfe100dc588a6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -22,7 +22,7 @@ use rustc::lint; use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc::span_bug; use rustc::ty::query::Providers; -use rustc::ty::{self, DefIdTree, ResolverOutputs}; +use rustc::ty::{self, DefIdTree, ResolverOutputs, TraitMap}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::ptr_key::PtrKey; @@ -32,8 +32,8 @@ use rustc_expand::base::SyntaxExtension; use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::GlobMap; use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint}; -use rustc_hir::{GlobMap, TraitMap}; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 760b6487045d8..8f0fbc2d60c9f 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -902,13 +902,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { for trait_candidate in applicable_traits.iter() { let trait_did = trait_candidate.def_id; if duplicates.insert(trait_did) { - let import_ids = trait_candidate - .import_ids - .iter() - .map(|node_id| self.fcx.tcx.hir().node_to_hir_id(*node_id)) - .collect(); - let result = - self.assemble_extension_candidates_for_trait(import_ids, trait_did); + let result = self.assemble_extension_candidates_for_trait( + &trait_candidate.import_ids, + trait_did, + ); result?; } } @@ -920,7 +917,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let mut duplicates = FxHashSet::default(); for trait_info in suggest::all_traits(self.tcx) { if duplicates.insert(trait_info.def_id) { - self.assemble_extension_candidates_for_trait(smallvec![], trait_info.def_id)?; + self.assemble_extension_candidates_for_trait(&smallvec![], trait_info.def_id)?; } } Ok(()) @@ -959,7 +956,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn assemble_extension_candidates_for_trait( &mut self, - import_ids: SmallVec<[hir::HirId; 1]>, + import_ids: &SmallVec<[hir::HirId; 1]>, trait_def_id: DefId, ) -> Result<(), MethodError<'tcx>> { debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id); From 2a899e2a2f3eb442af7637f3b9fce529f8441978 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 13 Feb 2020 16:47:51 +0100 Subject: [PATCH 25/27] Make TraitCandidate generic. --- src/librustc/ty/context.rs | 5 ++++- src/librustc/ty/mod.rs | 22 ++-------------------- src/librustc_hir/hir.rs | 17 ++++++++++++++--- src/librustc_resolve/late.rs | 6 +++--- src/librustc_resolve/lib.rs | 6 +++--- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 1a071905523ca..b2eb122bfeead 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1161,7 +1161,10 @@ impl<'tcx> TyCtxt<'tcx> { for (k, v) in resolutions.trait_map { let hir_id = hir.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); - let v = v.into_iter().map(|tc| tc.node_to_hir_id(&hir.definitions())).collect(); + let v = v + .into_iter() + .map(|tc| tc.map_import_ids(|id| hir.definitions().node_to_hir_id(id))) + .collect(); map.insert(hir_id.local_id, StableVec::new(v)); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a561d48844b7a..ad51c60ab0178 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -35,7 +35,7 @@ use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_hir::{Constness, GlobMap, Node}; +use rustc_hir::{Constness, GlobMap, Node, TraitMap}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_serialize::{self, Encodable, Encoder}; @@ -46,7 +46,6 @@ use rustc_target::abi::Align; use syntax::ast::{self, Ident, Name}; use syntax::node_id::{NodeId, NodeMap, NodeSet}; -use smallvec::SmallVec; use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; @@ -123,28 +122,11 @@ mod sty; // Data types -#[derive(Clone, Debug)] -pub struct TraitCandidate { - pub def_id: DefId, - pub import_ids: SmallVec<[NodeId; 1]>, -} - -impl TraitCandidate { - fn node_to_hir_id(self, definitions: &hir_map::Definitions) -> hir::TraitCandidate { - let TraitCandidate { def_id, import_ids } = self; - let import_ids = - import_ids.into_iter().map(|node_id| definitions.node_to_hir_id(node_id)).collect(); - hir::TraitCandidate { def_id, import_ids } - } -} - -pub type TraitMap = NodeMap>; - pub struct ResolverOutputs { pub definitions: hir_map::Definitions, pub cstore: Box, pub extern_crate_map: NodeMap, - pub trait_map: TraitMap, + pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, pub export_map: ExportMap, diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 0667bd3f4a219..80b379218a5d5 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -2608,13 +2608,24 @@ pub type CaptureModeMap = NodeMap; // has length > 0 if the trait is found through an chain of imports, starting with the // import/use statement in the scope where the trait is used. #[derive(Clone, Debug)] -pub struct TraitCandidate { +pub struct TraitCandidate { pub def_id: DefId, - pub import_ids: SmallVec<[HirId; 1]>, + pub import_ids: SmallVec<[ID; 1]>, +} + +impl TraitCandidate { + pub fn map_import_ids(self, f: F) -> TraitCandidate + where + F: Fn(ID) -> T, + { + let TraitCandidate { def_id, import_ids } = self; + let import_ids = import_ids.into_iter().map(f).collect(); + TraitCandidate { def_id, import_ids } + } } // Trait method resolution -pub type TraitMap = NodeMap>; +pub type TraitMap = NodeMap>>; // Map from the NodeId of a glob import to a list of items which are actually // imported. diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index ea865a5590ae7..bcf558d1563ed 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -11,13 +11,13 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; -use rustc::ty::TraitCandidate; use rustc::{bug, lint, span_bug}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc_hir::TraitCandidate; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -2078,7 +2078,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &mut self, mut ident: Ident, ns: Namespace, - ) -> Vec { + ) -> Vec> { debug!("(getting traits containing item) looking for '{}'", ident.name); let mut found_traits = Vec::new(); @@ -2123,7 +2123,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ident: Ident, ns: Namespace, module: Module<'a>, - found_traits: &mut Vec, + found_traits: &mut Vec>, ) { assert!(ns == TypeNS || ns == ValueNS); let mut traits = module.traits.borrow_mut(); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index cfe100dc588a6..4278bf867f305 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -22,7 +22,7 @@ use rustc::lint; use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc::span_bug; use rustc::ty::query::Providers; -use rustc::ty::{self, DefIdTree, ResolverOutputs, TraitMap}; +use rustc::ty::{self, DefIdTree, ResolverOutputs}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::ptr_key::PtrKey; @@ -32,8 +32,8 @@ use rustc_expand::base::SyntaxExtension; use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_hir::GlobMap; use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint}; +use rustc_hir::{GlobMap, TraitMap}; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; @@ -865,7 +865,7 @@ pub struct Resolver<'a> { /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: NodeMap, export_map: ExportMap, - trait_map: TraitMap, + trait_map: TraitMap, /// A map from nodes to anonymous modules. /// Anonymous modules are pseudo-modules that are implicitly created around items From 026dec550002356ea52a0800db5de0f361631f56 Mon Sep 17 00:00:00 2001 From: Drew Ripberger Date: Thu, 13 Feb 2020 11:14:21 -0500 Subject: [PATCH 26/27] Spelling error "represening" to "representing" --- src/librustc_lexer/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 969ce9b06e8a8..25334461a113b 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -35,7 +35,7 @@ impl Token { } } -/// Enum represening common lexeme types. +/// Enum representing common lexeme types. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum TokenKind { // Multi-char tokens: From 23cb749bbb5c57e85a89b72a76299df1aef464e7 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 13 Feb 2020 11:53:07 -0600 Subject: [PATCH 27/27] don't error on network failures --- src/tools/rustbook/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 023f5aa1e284b..226779ad0c0ce 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -115,6 +115,8 @@ pub fn linkcheck( eprintln!("Timeout for link `{}`", link.link.uri); } else if err.is_server_error() { eprintln!("Server error for link `{}`", link.link.uri); + } else if !err.is_http() { + eprintln!("Non-HTTP-related error for link: {} {}", link.link.uri, err); } else { is_real_error = true; }