diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 426659fd92452..e0db8606bc203 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -269,26 +269,12 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs) } ItemKind::Static(ref t, m, ref e) => { - let ty = self.lower_ty( - t, - if self.sess.features_untracked().impl_trait_in_bindings { - ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc) - } else { - ImplTraitContext::Disallowed(ImplTraitPosition::Binding) - }, - ); - hir::ItemKind::Static(ty, m, self.lower_const_body(span, Some(e))) + let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); + hir::ItemKind::Static(ty, m, body_id) } ItemKind::Const(ref t, ref e) => { - let ty = self.lower_ty( - t, - if self.sess.features_untracked().impl_trait_in_bindings { - ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc) - } else { - ImplTraitContext::Disallowed(ImplTraitPosition::Binding) - }, - ); - hir::ItemKind::Const(ty, self.lower_const_body(span, Some(e))) + let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); + hir::ItemKind::Const(ty, body_id) } ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => { let fn_def_id = self.resolver.definitions().local_def_id(id); @@ -457,6 +443,21 @@ impl<'hir> LoweringContext<'_, 'hir> { // not cause an assertion failure inside the `lower_defaultness` function. } + fn lower_const_item( + &mut self, + ty: &Ty, + span: Span, + body: Option<&Expr>, + ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { + let itctx = if self.sess.features_untracked().impl_trait_in_bindings { + ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc) + } else { + ImplTraitContext::Disallowed(ImplTraitPosition::Binding) + }; + let ty = self.lower_ty(ty, itctx); + (ty, self.lower_const_body(span, body)) + } + fn lower_use_tree( &mut self, tree: &UseTree, @@ -678,11 +679,16 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } - ForeignItemKind::Static(ref t, m) => { + ForeignItemKind::Static(ref t, m, _) => { let ty = self.lower_ty(t, ImplTraitContext::disallowed()); hir::ForeignItemKind::Static(ty, m) } - ForeignItemKind::Ty => hir::ForeignItemKind::Type, + ForeignItemKind::Const(ref t, _) => { + // For recovery purposes. + let ty = self.lower_ty(t, ImplTraitContext::disallowed()); + hir::ForeignItemKind::Static(ty, Mutability::Not) + } + ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"), }, vis: self.lower_visibility(&i.vis, None), @@ -759,32 +765,27 @@ impl<'hir> LoweringContext<'_, 'hir> { let trait_item_def_id = self.resolver.definitions().local_def_id(i.id); let (generics, kind) = match i.kind { - AssocItemKind::Const(ref ty, ref default) => { - let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); + AssocItemKind::Static(ref ty, _, ref default) // Let's pretend this is a `const`. + | AssocItemKind::Const(ref ty, ref default) => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); - ( - generics, - hir::TraitItemKind::Const( - ty, - default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))), - ), - ) + let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); + (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body)) } - AssocItemKind::Fn(ref sig, None) => { + AssocItemKind::Fn(ref sig, ref generics, None) => { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = - self.lower_method_sig(&i.generics, sig, trait_item_def_id, false, None); + self.lower_method_sig(generics, sig, trait_item_def_id, false, None); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } - AssocItemKind::Fn(ref sig, Some(ref body)) => { + AssocItemKind::Fn(ref sig, ref generics, Some(ref body)) => { let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = - self.lower_method_sig(&i.generics, sig, trait_item_def_id, false, None); + self.lower_method_sig(generics, sig, trait_item_def_id, false, None); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) } - AssocItemKind::TyAlias(ref bounds, ref default) => { + AssocItemKind::TyAlias(ref generics, ref bounds, ref default) => { let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed())); - let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); + let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); let kind = hir::TraitItemKind::Type( self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), ty, @@ -806,10 +807,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { - let (kind, has_default) = match i.kind { - AssocItemKind::Const(_, ref default) => (hir::AssocItemKind::Const, default.is_some()), - AssocItemKind::TyAlias(_, ref default) => (hir::AssocItemKind::Type, default.is_some()), - AssocItemKind::Fn(ref sig, ref default) => { + let (kind, has_default) = match &i.kind { + AssocItemKind::Static(_, _, default) // Let's pretend this is a `const` for recovery. + | AssocItemKind::Const(_, default) => { + (hir::AssocItemKind::Const, default.is_some()) + } + AssocItemKind::TyAlias(_, _, default) => (hir::AssocItemKind::Type, default.is_some()), + AssocItemKind::Fn(sig, _, default) => { (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some()) } AssocItemKind::Macro(..) => unimplemented!(), @@ -832,22 +836,21 @@ impl<'hir> LoweringContext<'_, 'hir> { let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); let (generics, kind) = match i.kind { - AssocItemKind::Const(ref ty, ref expr) => { - let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); + AssocItemKind::Static(ref ty, _, ref expr) | AssocItemKind::Const(ref ty, ref expr) => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); ( - generics, + hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), ) } - AssocItemKind::Fn(ref sig, ref body) => { + AssocItemKind::Fn(ref sig, ref generics, ref body) => { self.current_item = Some(i.span); let asyncness = sig.header.asyncness; let body_id = self.lower_maybe_async_body(i.span, &sig.decl, asyncness, body.as_deref()); let impl_trait_return_allow = !self.is_in_trait_impl; let (generics, sig) = self.lower_method_sig( - &i.generics, + generics, sig, impl_item_def_id, impl_trait_return_allow, @@ -856,8 +859,8 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, hir::ImplItemKind::Method(sig, body_id)) } - AssocItemKind::TyAlias(_, ref ty) => { - let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); + AssocItemKind::TyAlias(ref generics, _, ref ty) => { + let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); let kind = match ty { None => { let ty = self.arena.alloc(self.ty(i.span, hir::TyKind::Err)); @@ -901,14 +904,15 @@ impl<'hir> LoweringContext<'_, 'hir> { vis: self.lower_visibility(&i.vis, Some(i.id)), defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), kind: match &i.kind { - AssocItemKind::Const(..) => hir::AssocItemKind::Const, - AssocItemKind::TyAlias(_, ty) => { + AssocItemKind::Static(..) // Let's pretend this is a `const` for recovery. + | AssocItemKind::Const(..) => hir::AssocItemKind::Const, + AssocItemKind::TyAlias(_, _, ty) => { match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) { None => hir::AssocItemKind::Type, Some(_) => hir::AssocItemKind::OpaqueTy, } } - AssocItemKind::Fn(sig, _) => { + AssocItemKind::Fn(sig, _, _) => { hir::AssocItemKind::Method { has_self: sig.decl.has_self() } } AssocItemKind::Macro(..) => unimplemented!(), diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 99de4b88fd3c4..56d789b7a6a8b 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -490,7 +490,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lctx.allocate_hir_id_counter(item.id); let owner = match (&item.kind, ctxt) { // Ignore patterns in trait methods without bodies. - (AssocItemKind::Fn(_, None), AssocCtxt::Trait) => None, + (AssocItemKind::Fn(_, _, None), AssocCtxt::Trait) => None, _ => Some(item.id), }; self.with_hir_id_owner(owner, |this| visit::walk_assoc_item(this, item, ctxt)); diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 2f0495b8b5a48..d3fcb589fd0ff 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -22,6 +22,9 @@ use syntax::expand::is_proc_macro_attr; use syntax::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use syntax::walk_list; +const MORE_EXTERN: &str = + "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; + /// Is `self` allowed semantically as the first parameter in an `FnDecl`? enum SelfSemantic { Yes, @@ -423,14 +426,62 @@ impl<'a> AstValidator<'a> { } } - fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) { + fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) { let span = match bounds { [] => return, [b0] => b0.span(), [b0, .., bl] => b0.span().to(bl.span()), }; self.err_handler() - .struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect") + .struct_span_err(span, &format!("bounds on `type`s in {} have no effect", ctx)) + .emit(); + } + + fn check_foreign_ty_genericless(&self, generics: &Generics) { + let cannot_have = |span, descr, remove_descr| { + self.err_handler() + .struct_span_err( + span, + &format!("`type`s inside `extern` blocks cannot have {}", descr), + ) + .span_suggestion( + span, + &format!("remove the {}", remove_descr), + String::new(), + Applicability::MaybeIncorrect, + ) + .span_label(self.current_extern_span(), "`extern` block begins here") + .note(MORE_EXTERN) + .emit(); + }; + + if !generics.params.is_empty() { + cannot_have(generics.span, "generic parameters", "generic parameters"); + } + + if !generics.where_clause.predicates.is_empty() { + cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause"); + } + } + + fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) { + let body = match body { + None => return, + Some(body) => body, + }; + self.err_handler() + .struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind)) + .span_label(ident.span, "cannot have a body") + .span_label(body, "the invalid body") + .span_label( + self.current_extern_span(), + format!( + "`extern` blocks define existing foreign {0}s and {0}s \ + inside of them cannot have a body", + kind + ), + ) + .note(MORE_EXTERN) .emit(); } @@ -458,7 +509,7 @@ impl<'a> AstValidator<'a> { "`extern` blocks define existing foreign functions and functions \ inside of them cannot have a body", ) - .note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html") + .note(MORE_EXTERN) .emit(); } @@ -531,6 +582,16 @@ impl<'a> AstValidator<'a> { } } } + + fn check_item_named(&self, ident: Ident, kind: &str) { + if ident.name != kw::Underscore { + return; + } + self.err_handler() + .struct_span_err(ident.span, &format!("`{}` items in this context need a name", kind)) + .span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind)) + .emit(); + } } enum GenericPosition { @@ -900,6 +961,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.err_handler().span_err(item.span, "unions cannot have zero fields"); } } + ItemKind::Const(.., None) => { + let msg = "free constant item without body"; + self.error_item_without_body(item.span, "constant", msg, " = <expr>;"); + } + ItemKind::Static(.., None) => { + let msg = "free static item without body"; + self.error_item_without_body(item.span, "static", msg, " = <expr>;"); + } _ => {} } @@ -912,7 +981,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_fn_bodyless(fi.ident, body.as_deref()); self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header); } - ForeignItemKind::Static(..) | ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {} + ForeignItemKind::TyAlias(generics, bounds, body) => { + self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span)); + self.check_type_no_bounds(bounds, "`extern` blocks"); + self.check_foreign_ty_genericless(generics); + } + ForeignItemKind::Static(_, _, body) => { + self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); + } + ForeignItemKind::Const(..) | ForeignItemKind::Macro(..) => {} } visit::walk_foreign_item(self, fi) @@ -1154,12 +1231,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { AssocItemKind::Const(_, body) => { self.check_impl_item_provided(item.span, body, "constant", " = <expr>;"); } - AssocItemKind::Fn(_, body) => { + AssocItemKind::Fn(_, _, body) => { self.check_impl_item_provided(item.span, body, "function", " { <body> }"); } - AssocItemKind::TyAlias(bounds, body) => { + AssocItemKind::TyAlias(_, bounds, body) => { self.check_impl_item_provided(item.span, body, "type", " = <type>;"); - self.check_impl_assoc_type_no_bounds(bounds); + self.check_type_no_bounds(bounds, "`impl`s"); } _ => {} } @@ -1167,12 +1244,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if ctxt == AssocCtxt::Trait || self.in_trait_impl { self.invalid_visibility(&item.vis, None); - if let AssocItemKind::Fn(sig, _) = &item.kind { + if let AssocItemKind::Fn(sig, _, _) = &item.kind { self.check_trait_fn_not_const(sig.header.constness); self.check_trait_fn_not_async(item.span, sig.header.asyncness); } } + if let AssocItemKind::Const(..) = item.kind { + self.check_item_named(item.ident, "const"); + } + self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt)); } } diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 0b21de4d78b41..d4de2c937583d 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -397,10 +397,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } } - ast::ForeignItemKind::Ty => { + ast::ForeignItemKind::TyAlias(..) => { gate_feature_post!(&self, extern_types, i.span, "extern types are experimental"); } - ast::ForeignItemKind::Macro(..) => {} + ast::ForeignItemKind::Macro(..) | ast::ForeignItemKind::Const(..) => {} } visit::walk_foreign_item(self, i) @@ -548,12 +548,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } match i.kind { - ast::AssocItemKind::Fn(ref sig, _) => { + ast::AssocItemKind::Fn(ref sig, _, _) => { if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) { gate_feature_post!(&self, const_fn, i.span, "const fn is unstable"); } } - ast::AssocItemKind::TyAlias(_, ref ty) => { + ast::AssocItemKind::TyAlias(ref generics, _, ref ty) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { gate_feature_post!( &self, @@ -565,7 +565,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if let Some(ty) = ty { self.check_impl_trait(ty); } - self.check_gat(&i.generics, i.span); + self.check_gat(generics, i.span); } _ => {} } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 75938470b6fca..2f712964a84cb 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -912,7 +912,7 @@ impl<'a> State<'a> { } } - crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) { + crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[Attribute]) { self.print_inner_attributes(attrs); for item in &nmod.items { self.print_foreign_item(item); @@ -1016,59 +1016,73 @@ impl<'a> State<'a> { } crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) { + let ast::ForeignItem { id, span, ident, attrs, kind, vis, tokens: _ } = item; + self.print_nested_item_kind(*id, *span, *ident, attrs, ast::Defaultness::Final, kind, vis); + } + + fn print_nested_item_kind( + &mut self, + id: ast::NodeId, + span: Span, + ident: ast::Ident, + attrs: &[Attribute], + defaultness: ast::Defaultness, + kind: &ast::AssocItemKind, + vis: &ast::Visibility, + ) { + self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); - self.maybe_print_comment(item.span.lo()); - self.print_outer_attributes(&item.attrs); - match item.kind { - ast::ForeignItemKind::Fn(ref sig, ref gen, ref body) => { - self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs); + self.maybe_print_comment(span.lo()); + self.print_outer_attributes(attrs); + self.print_defaultness(defaultness); + match kind { + ast::ForeignItemKind::Fn(sig, gen, body) => { + self.print_fn_full(sig, ident, gen, vis, body.as_deref(), attrs); } - ast::ForeignItemKind::Static(ref t, m) => { - self.head(visibility_qualified(&item.vis, "static")); - if m == ast::Mutability::Mut { - self.word_space("mut"); - } - self.print_ident(item.ident); - self.word_space(":"); - self.print_type(t); - self.s.word(";"); - self.end(); // end the head-ibox - self.end(); // end the outer cbox + ast::ForeignItemKind::Const(ty, body) => { + self.print_item_const(ident, None, ty, body.as_deref(), vis); } - ast::ForeignItemKind::Ty => { - self.head(visibility_qualified(&item.vis, "type")); - self.print_ident(item.ident); - self.s.word(";"); - self.end(); // end the head-ibox - self.end(); // end the outer cbox + ast::ForeignItemKind::Static(ty, mutbl, body) => { + self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis); + } + ast::ForeignItemKind::TyAlias(generics, bounds, ty) => { + self.print_associated_type(ident, generics, bounds, ty.as_deref()); } - ast::ForeignItemKind::Macro(ref m) => { + ast::ForeignItemKind::Macro(m) => { self.print_mac(m); if m.args.need_semicolon() { self.s.word(";"); } } } + self.ann.post(self, AnnNode::SubItem(id)) } - fn print_associated_const( + fn print_item_const( &mut self, ident: ast::Ident, + mutbl: Option<ast::Mutability>, ty: &ast::Ty, - default: Option<&ast::Expr>, + body: Option<&ast::Expr>, vis: &ast::Visibility, ) { - self.s.word(visibility_qualified(vis, "")); - self.word_space("const"); + let leading = match mutbl { + None => "const", + Some(ast::Mutability::Not) => "static", + Some(ast::Mutability::Mut) => "static mut", + }; + self.head(visibility_qualified(vis, leading)); self.print_ident(ident); self.word_space(":"); self.print_type(ty); - if let Some(expr) = default { - self.s.space(); + self.s.space(); + self.end(); // end the head-ibox + if let Some(body) = body { self.word_space("="); - self.print_expr(expr); + self.print_expr(body); } - self.s.word(";") + self.s.word(";"); + self.end(); // end the outer cbox } fn print_associated_type( @@ -1118,34 +1132,11 @@ impl<'a> State<'a> { self.end(); // end inner head-block self.end(); // end outer head-block } - ast::ItemKind::Static(ref ty, m, ref expr) => { - self.head(visibility_qualified(&item.vis, "static")); - if m == ast::Mutability::Mut { - self.word_space("mut"); - } - self.print_ident(item.ident); - self.word_space(":"); - self.print_type(ty); - self.s.space(); - self.end(); // end the head-ibox - - self.word_space("="); - self.print_expr(expr); - self.s.word(";"); - self.end(); // end the outer cbox + ast::ItemKind::Static(ref ty, mutbl, ref body) => { + self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis); } - ast::ItemKind::Const(ref ty, ref expr) => { - self.head(visibility_qualified(&item.vis, "const")); - self.print_ident(item.ident); - self.word_space(":"); - self.print_type(ty); - self.s.space(); - self.end(); // end the head-ibox - - self.word_space("="); - self.print_expr(expr); - self.s.word(";"); - self.end(); // end the outer cbox + ast::ItemKind::Const(ref ty, ref body) => { + self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis); } ast::ItemKind::Fn(ref sig, ref gen, ref body) => { self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs); @@ -1464,30 +1455,8 @@ impl<'a> State<'a> { } crate fn print_assoc_item(&mut self, item: &ast::AssocItem) { - self.ann.pre(self, AnnNode::SubItem(item.id)); - self.hardbreak_if_not_bol(); - self.maybe_print_comment(item.span.lo()); - self.print_outer_attributes(&item.attrs); - self.print_defaultness(item.defaultness); - match &item.kind { - ast::AssocItemKind::Const(ty, expr) => { - self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis); - } - ast::AssocItemKind::Fn(sig, body) => { - let body = body.as_deref(); - self.print_fn_full(sig, item.ident, &item.generics, &item.vis, body, &item.attrs); - } - ast::AssocItemKind::TyAlias(bounds, ty) => { - self.print_associated_type(item.ident, &item.generics, bounds, ty.as_deref()); - } - ast::AssocItemKind::Macro(mac) => { - self.print_mac(mac); - if mac.args.need_semicolon() { - self.s.word(";"); - } - } - } - self.ann.post(self, AnnNode::SubItem(item.id)) + let ast::AssocItem { id, span, ident, attrs, defaultness, kind, vis, tokens: _ } = item; + self.print_nested_item_kind(*id, *span, *ident, attrs, *defaultness, kind, vis); } crate fn print_stmt(&mut self, st: &ast::Stmt) { diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 5cf233e222e7c..2e4cbd708a9f6 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -544,8 +544,8 @@ impl<'a> TraitDef<'a> { vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, attrs: Vec::new(), - generics: Generics::default(), kind: ast::AssocItemKind::TyAlias( + Generics::default(), Vec::new(), Some(type_def.to_ty(cx, self.span, type_ident, generics)), ), @@ -973,12 +973,11 @@ impl<'a> MethodDef<'a> { P(ast::AssocItem { id: ast::DUMMY_NODE_ID, attrs: self.attributes.clone(), - generics: fn_generics, span: trait_.span, vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, ident: method_ident, - kind: ast::AssocItemKind::Fn(sig, Some(body_block)), + kind: ast::AssocItemKind::Fn(sig, fn_generics, Some(body_block)), tokens: None, }) } diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs index 02a0bc00c1169..b6837c0703aed 100644 --- a/src/librustc_builtin_macros/test.rs +++ b/src/librustc_builtin_macros/test.rs @@ -186,81 +186,85 @@ pub fn expand_test_or_bench( ast::ItemKind::Const( cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), // test::TestDescAndFn { - cx.expr_struct( - sp, - test_path("TestDescAndFn"), - vec![ - // desc: test::TestDesc { - field( - "desc", - cx.expr_struct( - sp, - test_path("TestDesc"), - vec![ - // name: "path::to::test" - field( - "name", - cx.expr_call( - sp, - cx.expr_path(test_path("StaticTestName")), - vec![cx.expr_str( - sp, - Symbol::intern(&item_path( - // skip the name of the root module - &cx.current_expansion.module.mod_path[1..], - &item.ident, - )), - )], - ), - ), - // ignore: true | false - field("ignore", cx.expr_bool(sp, should_ignore(&item))), - // allow_fail: true | false - field("allow_fail", cx.expr_bool(sp, should_fail(&item))), - // should_panic: ... - field( - "should_panic", - match should_panic(cx, &item) { - // test::ShouldPanic::No - ShouldPanic::No => cx.expr_path(should_panic_path("No")), - // test::ShouldPanic::Yes - ShouldPanic::Yes(None) => { - cx.expr_path(should_panic_path("Yes")) - } - // test::ShouldPanic::YesWithMessage("...") - ShouldPanic::Yes(Some(sym)) => cx.expr_call( + Some( + cx.expr_struct( + sp, + test_path("TestDescAndFn"), + vec![ + // desc: test::TestDesc { + field( + "desc", + cx.expr_struct( + sp, + test_path("TestDesc"), + vec![ + // name: "path::to::test" + field( + "name", + cx.expr_call( sp, - cx.expr_path(should_panic_path("YesWithMessage")), - vec![cx.expr_str(sp, sym)], + cx.expr_path(test_path("StaticTestName")), + vec![cx.expr_str( + sp, + Symbol::intern(&item_path( + // skip the name of the root module + &cx.current_expansion.module.mod_path[1..], + &item.ident, + )), + )], ), - }, - ), - // test_type: ... - field( - "test_type", - match test_type(cx) { - // test::TestType::UnitTest - TestType::UnitTest => { - cx.expr_path(test_type_path("UnitTest")) - } - // test::TestType::IntegrationTest - TestType::IntegrationTest => { - cx.expr_path(test_type_path("IntegrationTest")) - } - // test::TestPath::Unknown - TestType::Unknown => { - cx.expr_path(test_type_path("Unknown")) - } - }, - ), - // }, - ], + ), + // ignore: true | false + field("ignore", cx.expr_bool(sp, should_ignore(&item))), + // allow_fail: true | false + field("allow_fail", cx.expr_bool(sp, should_fail(&item))), + // should_panic: ... + field( + "should_panic", + match should_panic(cx, &item) { + // test::ShouldPanic::No + ShouldPanic::No => { + cx.expr_path(should_panic_path("No")) + } + // test::ShouldPanic::Yes + ShouldPanic::Yes(None) => { + cx.expr_path(should_panic_path("Yes")) + } + // test::ShouldPanic::YesWithMessage("...") + ShouldPanic::Yes(Some(sym)) => cx.expr_call( + sp, + cx.expr_path(should_panic_path("YesWithMessage")), + vec![cx.expr_str(sp, sym)], + ), + }, + ), + // test_type: ... + field( + "test_type", + match test_type(cx) { + // test::TestType::UnitTest + TestType::UnitTest => { + cx.expr_path(test_type_path("UnitTest")) + } + // test::TestType::IntegrationTest + TestType::IntegrationTest => { + cx.expr_path(test_type_path("IntegrationTest")) + } + // test::TestPath::Unknown + TestType::Unknown => { + cx.expr_path(test_type_path("Unknown")) + } + }, + ), + // }, + ], + ), ), - ), - // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...) - field("testfn", test_fn), // } - ], - ), // } + // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...) + field("testfn", test_fn), // } + ], + ), // } + ), ), ); test_const = test_const.map(|mut tc| { diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs index af22e46eb6afa..0882151063098 100644 --- a/src/librustc_expand/build.rs +++ b/src/librustc_expand/build.rs @@ -634,7 +634,7 @@ impl<'a> ExtCtxt<'a> { mutbl: ast::Mutability, expr: P<ast::Expr>, ) -> P<ast::Item> { - self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, expr)) + self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr))) } pub fn item_const( @@ -644,7 +644,7 @@ impl<'a> ExtCtxt<'a> { ty: P<ast::Ty>, expr: P<ast::Expr>, ) -> P<ast::Item> { - self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, expr)) + self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, Some(expr))) } pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute { diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs index 6bcb8f45f001e..c96b394c7b5e2 100644 --- a/src/librustc_expand/placeholders.rs +++ b/src/librustc_expand/placeholders.rs @@ -25,7 +25,6 @@ pub fn placeholder( let ident = ast::Ident::invalid(); let attrs = Vec::new(); - let generics = ast::Generics::default(); let vis = vis.unwrap_or_else(|| dummy_spanned(ast::VisibilityKind::Inherited)); let span = DUMMY_SP; let expr_placeholder = || { @@ -57,7 +56,6 @@ pub fn placeholder( ident, vis, attrs, - generics, kind: ast::AssocItemKind::Macro(mac_placeholder()), defaultness: ast::Defaultness::Final, tokens: None, @@ -68,7 +66,6 @@ pub fn placeholder( ident, vis, attrs, - generics, kind: ast::AssocItemKind::Macro(mac_placeholder()), defaultness: ast::Defaultness::Final, tokens: None, diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 659323d1c2555..df50fc5d3ed24 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -686,7 +686,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn flat_map_trait_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> { let is_const = match i.kind { ast::AssocItemKind::Const(..) => true, - ast::AssocItemKind::Fn(ref sig, _) => Self::is_sig_const(sig), + ast::AssocItemKind::Fn(ref sig, _, _) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 93fca43d67c1f..207defa96a3e6 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -640,7 +640,7 @@ declare_lint_pass!( impl EarlyLintPass for AnonymousParameters { fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { match it.kind { - ast::AssocItemKind::Fn(ref sig, _) => { + ast::AssocItemKind::Fn(ref sig, _, _) => { for arg in sig.decl.inputs.iter() { match arg.pat.kind { ast::PatKind::Ident(_, ident, None) => { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 480df99a01eed..7870b9da4cb70 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -603,7 +603,7 @@ impl EarlyLintPass for UnusedParens { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - if let Const(.., ref expr) | Static(.., ref expr) = item.kind { + if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind { self.check_unused_parens_expr(cx, expr, "assigned value", false, None, None); } } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 500aaaf43b92a..da72da043650c 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -13,7 +13,7 @@ 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}; use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; -use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind}; +use syntax::ast::{FnHeader, ForeignItem, Mutability, Visibility, VisibilityKind}; use syntax::ptr::P; use syntax::token; use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree}; @@ -333,29 +333,19 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - fn missing_assoc_item_kind_err( - &self, - item_type: &str, - prev_span: Span, - ) -> DiagnosticBuilder<'a> { - let expected_kinds = if item_type == "extern" { - "missing `fn`, `type`, or `static`" - } else { - "missing `fn`, `type`, or `const`" - }; - - // Given this code `path(`, it seems like this is not - // setting the visibility of a macro invocation, but rather - // a mistyped method declaration. - // Create a diagnostic pointing out that `fn` is missing. - // - // x | pub path(&self) { - // | ^ missing `fn`, `type`, or `const` - // pub path( - // ^^ `sp` below will point to this + /// Given this code `path(`, it seems like this is not + /// setting the visibility of a macro invocation, + /// but rather a mistyped method declaration. + /// Create a diagnostic pointing out that `fn` is missing. + /// + /// ``` + /// x | pub path(&self) { + /// | ^ missing `fn`, `type`, `const`, or `static` + /// ``` + fn missing_nested_item_kind_err(&self, prev_span: Span) -> DiagnosticBuilder<'a> { let sp = prev_span.between(self.token.span); - let mut err = self - .struct_span_err(sp, &format!("{} for {}-item declaration", expected_kinds, item_type)); + let expected_kinds = "missing `fn`, `type`, `const`, or `static`"; + let mut err = self.struct_span_err(sp, &format!("{} for item declaration", expected_kinds)); err.span_label(sp, expected_kinds); err } @@ -546,6 +536,7 @@ impl<'a> Parser<'a> { 1, &[ kw::Impl, + kw::Static, kw::Const, kw::Async, kw::Fn, @@ -638,7 +629,7 @@ impl<'a> Parser<'a> { fn parse_assoc_item( &mut self, at_end: &mut bool, - req_name: fn(&token::Token) -> bool, + req_name: ReqName, ) -> PResult<'a, P<AssocItem>> { let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; @@ -652,59 +643,67 @@ impl<'a> Parser<'a> { if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { item.tokens = Some(tokens); } + self.error_on_assoc_static(&item); Ok(P(item)) } + fn error_on_assoc_static(&self, item: &AssocItem) { + if let AssocItemKind::Static(..) = item.kind { + self.struct_span_err(item.span, "associated `static` items are not allowed").emit(); + } + } + fn parse_assoc_item_( &mut self, at_end: &mut bool, mut attrs: Vec<Attribute>, - req_name: fn(&token::Token) -> bool, + req_name: ReqName, ) -> PResult<'a, AssocItem> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); + let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, req_name, &vis)?; + let span = lo.to(self.prev_span); + let id = DUMMY_NODE_ID; + Ok(AssocItem { id, span, ident, attrs, vis, defaultness, kind, tokens: None }) + } - let (ident, kind, generics) = if self.eat_keyword(kw::Type) { - self.parse_assoc_ty()? + fn parse_assoc_item_kind( + &mut self, + at_end: &mut bool, + attrs: &mut Vec<Attribute>, + req_name: ReqName, + vis: &Visibility, + ) -> PResult<'a, (Ident, AssocItemKind)> { + 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)?; - (ident, AssocItemKind::Fn(sig, body), generics) - } else if self.check_keyword(kw::Const) { - self.parse_assoc_const()? + let (ident, sig, generics, body) = self.parse_fn(at_end, attrs, req_name)?; + Ok((ident, AssocItemKind::Fn(sig, generics, body))) + } else if self.is_static_global() { + self.bump(); // `static` + let mutbl = self.parse_mutability(); + let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; + Ok((ident, AssocItemKind::Static(ty, mutbl, expr))) + } else if self.eat_keyword(kw::Const) { + let (ident, ty, expr) = self.parse_item_const_common(None)?; + Ok((ident, AssocItemKind::Const(ty, expr))) } else if self.isnt_macro_invocation() { - return Err(self.missing_assoc_item_kind_err("associated", self.prev_span)); + Err(self.missing_nested_item_kind_err(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()) + Ok((Ident::invalid(), AssocItemKind::Macro(mac))) } else { - self.recover_attrs_no_item(&attrs)?; - self.unexpected()? - }; - - 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: - /// - /// AssocConst = "const" Ident ":" Ty "=" Expr ";" - fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> { - self.expect_keyword(kw::Const)?; - let ident = self.parse_ident()?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; - let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; - self.expect_semi()?; - Ok((ident, AssocItemKind::Const(ty, expr), Generics::default())) + self.recover_attrs_no_item(attrs)?; + self.unexpected() + } } /// Parses the following grammar: /// /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] - fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> { + fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -716,7 +715,7 @@ impl<'a> Parser<'a> { let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; self.expect_semi()?; - Ok((ident, AssocItemKind::TyAlias(bounds, default), generics)) + Ok((ident, AssocItemKind::TyAlias(generics, bounds, default))) } /// Parses a `UseTree`. @@ -875,60 +874,26 @@ impl<'a> Parser<'a> { let mut attrs = self.parse_outer_attributes()?; let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; + let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, |_| true, &vis)?; + let item = self.mk_item(lo, ident, kind, vis, attrs); + self.error_on_foreign_const(&item); + Ok(P(item)) + } - let (ident, kind) = if self.check_keyword(kw::Type) { - // FOREIGN TYPE ITEM - self.parse_item_foreign_type()? - } else if self.check_fn_front_matter() { - // FOREIGN FUNCTION ITEM - 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 - self.bump(); // `static` - 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` - self.struct_span_err(self.prev_span, "extern items cannot be `const`") + fn error_on_foreign_const(&self, item: &ForeignItem) { + if let AssocItemKind::Const(..) = item.kind { + self.struct_span_err(item.ident.span, "extern items cannot be `const`") .span_suggestion( - self.prev_span, + item.span.with_hi(item.ident.span.lo()), "try using a static value", - "static".to_owned(), + "static ".to_string(), Applicability::MachineApplicable, ) + .note( + "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html", + ) .emit(); - self.parse_item_foreign_static()? - } 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)?; - self.unexpected()? - }; - Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) - } - - /// Parses a static item from a foreign module. - /// Assumes that the `static` keyword is already parsed. - 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()?; - self.expect_semi()?; - Ok((ident, ForeignItemKind::Static(ty, mutbl))) - } - - /// Parses a type from a foreign module. - fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { - self.expect_keyword(kw::Type)?; - let ident = self.parse_ident()?; - self.expect_semi()?; - Ok((ident, ForeignItemKind::Ty)) + } } fn is_static_global(&mut self) -> bool { @@ -964,34 +929,43 @@ impl<'a> Parser<'a> { } } - /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty = $expr` with + /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. /// /// When `m` is `"const"`, `$ident` may also be `"_"`. fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> { + let (id, ty, expr) = self.parse_item_const_common(m)?; + let item = match m { + Some(m) => ItemKind::Static(ty, m, expr), + None => ItemKind::Const(ty, expr), + }; + Ok((id, item)) + } + + /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with + /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. + /// + /// When `m` is `"const"`, `$ident` may also be `"_"`. + fn parse_item_const_common( + &mut self, + m: Option<Mutability>, + ) -> PResult<'a, (Ident, P<Ty>, Option<P<ast::Expr>>)> { let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?; // Parse the type of a `const` or `static mut?` item. // That is, the `":" $ty` fragment. - let ty = if self.token == token::Eq { - self.recover_missing_const_type(id, m) - } else { - // Not `=` so expect `":"" $ty` as usual. - self.expect(&token::Colon)?; + let ty = if self.eat(&token::Colon) { self.parse_ty()? + } else { + self.recover_missing_const_type(id, m) }; - self.expect(&token::Eq)?; - let e = self.parse_expr()?; + let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; - let item = match m { - Some(m) => ItemKind::Static(ty, m, e), - None => ItemKind::Const(ty, e), - }; - Ok((id, item)) + Ok((id, ty, expr)) } - /// We were supposed to parse `:` but instead, we're already at `=`. + /// We were supposed to parse `:` but the `:` was missing. /// This means that the type is missing. fn recover_missing_const_type(&mut self, id: Ident, m: Option<Mutability>) -> P<Ty> { // Construct the error and stash it away with the hope diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index d6ea737385cdd..1f622b80e8e2e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -826,10 +826,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ForeignItemKind::Fn(..) => { (Res::Def(DefKind::Fn, self.r.definitions.local_def_id(item.id)), ValueNS) } - ForeignItemKind::Static(..) => { + ForeignItemKind::Static(..) | ForeignItemKind::Const(..) => { (Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id)), ValueNS) } - ForeignItemKind::Ty => { + ForeignItemKind::TyAlias(..) => { (Res::Def(DefKind::ForeignTy, self.r.definitions.local_def_id(item.id)), TypeNS) } ForeignItemKind::Macro(_) => unreachable!(), @@ -1251,8 +1251,9 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { // Add the item to the trait info. let item_def_id = self.r.definitions.local_def_id(item.id); let (res, ns) = match item.kind { - AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), - AssocItemKind::Fn(ref sig, _) => { + AssocItemKind::Static(..) // Let's pretend it's a `const` for recovery. + | AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), + AssocItemKind::Fn(ref sig, _, _) => { if sig.decl.has_self() { self.r.has_self.insert(item_def_id); } diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index fe80dec513cfe..60cba55512193 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -215,18 +215,22 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { let def_data = match &i.kind { - AssocItemKind::Fn(FnSig { header, decl }, body) if header.asyncness.is_async() => { + AssocItemKind::Fn(FnSig { header, decl }, generics, body) + if header.asyncness.is_async() => + { return self.visit_async_fn( i.id, i.ident.name, i.span, header, - &i.generics, + generics, decl, body.as_deref(), ); } - AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name), + AssocItemKind::Fn(..) | AssocItemKind::Const(..) | AssocItemKind::Static(..) => { + DefPathData::ValueNs(i.ident.name) + } AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), AssocItemKind::Macro(..) => return self.visit_macro_invoc(i.id), }; diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index bcf558d1563ed..68559c0446aed 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -437,17 +437,18 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { match foreign_item.kind { - ForeignItemKind::Fn(_, ref generics, _) => { + ForeignItemKind::Fn(_, ref generics, _) + | ForeignItemKind::TyAlias(ref generics, ..) => { self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { visit::walk_foreign_item(this, foreign_item); }); } - ForeignItemKind::Static(..) => { + ForeignItemKind::Const(..) | ForeignItemKind::Static(..) => { self.with_item_rib(HasGenericParams::No, |this| { visit::walk_foreign_item(this, foreign_item); }); } - ForeignItemKind::Ty | ForeignItemKind::Macro(..) => { + ForeignItemKind::Macro(..) => { visit::walk_foreign_item(self, foreign_item); } } @@ -826,41 +827,34 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds); - for trait_item in trait_items { + let walk_assoc_item = |this: &mut Self, generics, item| { + this.with_generic_param_rib(generics, AssocItemRibKind, |this| { + visit::walk_assoc_item(this, item, AssocCtxt::Trait) + }); + }; + + for item in trait_items { this.with_trait_items(trait_items, |this| { - this.with_generic_param_rib( - &trait_item.generics, - AssocItemRibKind, - |this| { - match trait_item.kind { - AssocItemKind::Const(ref ty, ref default) => { - this.visit_ty(ty); - - // Only impose the restrictions of - // ConstRibKind for an actual constant - // expression in a provided default. - if let Some(ref expr) = *default { - this.with_constant_rib(|this| { - this.visit_expr(expr); - }); - } - } - AssocItemKind::Fn(_, _) => visit::walk_assoc_item( - this, - trait_item, - AssocCtxt::Trait, - ), - AssocItemKind::TyAlias(..) => visit::walk_assoc_item( - this, - trait_item, - AssocCtxt::Trait, - ), - AssocItemKind::Macro(_) => { - panic!("unexpanded macro in resolve!") - } - }; - }, - ); + match &item.kind { + AssocItemKind::Static(ty, _, default) + | AssocItemKind::Const(ty, default) => { + this.visit_ty(ty); + // Only impose the restrictions of `ConstRibKind` for an + // actual constant expression in a provided default. + if let Some(expr) = default { + this.with_constant_rib(|this| this.visit_expr(expr)); + } + } + AssocItemKind::Fn(_, generics, _) => { + walk_assoc_item(this, generics, item); + } + AssocItemKind::TyAlias(generics, _, _) => { + walk_assoc_item(this, generics, item); + } + AssocItemKind::Macro(_) => { + panic!("unexpanded macro in resolve!") + } + }; }); } }); @@ -888,9 +882,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { debug!("resolve_item ItemKind::Const"); self.with_item_rib(HasGenericParams::No, |this| { this.visit_ty(ty); - this.with_constant_rib(|this| { - this.visit_expr(expr); - }); + if let Some(expr) = expr { + this.with_constant_rib(|this| this.visit_expr(expr)); + } }); } @@ -1021,7 +1015,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { trait_items .iter() .filter_map(|item| match &item.kind { - AssocItemKind::TyAlias(bounds, _) if bounds.len() == 0 => Some(item.ident), + AssocItemKind::TyAlias(_, bounds, _) if bounds.len() == 0 => Some(item.ident), _ => None, }) .collect(), @@ -1113,66 +1107,74 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_current_self_type(self_type, |this| { this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); - for impl_item in impl_items { - // We also need a new scope for the impl item type parameters. - this.with_generic_param_rib(&impl_item.generics, - AssocItemRibKind, - |this| { - use crate::ResolutionError::*; - match impl_item.kind { - AssocItemKind::Const(..) => { - debug!( - "resolve_implementation AssocItemKind::Const", - ); - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item( - impl_item.ident, - ValueNS, - impl_item.span, - |n, s| ConstNotMemberOfTrait(n, s), - ); - - this.with_constant_rib(|this| { + for item in impl_items { + use crate::ResolutionError::*; + match &item.kind { + AssocItemKind::Static(..) | AssocItemKind::Const(..) => { + debug!("resolve_implementation AssocItemKind::Const",); + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item( + item.ident, + ValueNS, + item.span, + |n, s| ConstNotMemberOfTrait(n, s), + ); + + this.with_constant_rib(|this| { + visit::walk_assoc_item(this, item, AssocCtxt::Impl) + }); + } + AssocItemKind::Fn(_, generics, _) => { + // We also need a new scope for the impl item type parameters. + this.with_generic_param_rib( + generics, + AssocItemRibKind, + |this| { + // If this is a trait impl, ensure the method + // exists in trait + this.check_trait_item( + item.ident, + ValueNS, + item.span, + |n, s| MethodNotMemberOfTrait(n, s), + ); + + visit::walk_assoc_item( + this, + item, + AssocCtxt::Impl, + ) + }, + ); + } + AssocItemKind::TyAlias(generics, _, _) => { + // We also need a new scope for the impl item type parameters. + this.with_generic_param_rib( + generics, + AssocItemRibKind, + |this| { + // If this is a trait impl, ensure the type + // exists in trait + this.check_trait_item( + item.ident, + TypeNS, + item.span, + |n, s| TypeNotMemberOfTrait(n, s), + ); + visit::walk_assoc_item( this, - impl_item, + item, AssocCtxt::Impl, ) - }); - } - AssocItemKind::Fn(..) => { - // If this is a trait impl, ensure the method - // exists in trait - this.check_trait_item(impl_item.ident, - ValueNS, - impl_item.span, - |n, s| MethodNotMemberOfTrait(n, s)); - - visit::walk_assoc_item( - this, - impl_item, - AssocCtxt::Impl, - ) - } - AssocItemKind::TyAlias(_, _) => { - // If this is a trait impl, ensure the type - // exists in trait - this.check_trait_item(impl_item.ident, - TypeNS, - impl_item.span, - |n, s| TypeNotMemberOfTrait(n, s)); - - visit::walk_assoc_item( - this, - impl_item, - AssocCtxt::Impl, - ) - } - AssocItemKind::Macro(_) => - panic!("unexpanded macro in resolve!"), + }, + ); + } + AssocItemKind::Macro(_) => { + panic!("unexpanded macro in resolve!") } - }); + } } }); }); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 01e3e3f368529..6a3abf4fbf5f3 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -400,7 +400,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &mut self, item: &'l ast::Item, typ: &'l ast::Ty, - expr: &'l ast::Expr, + expr: Option<&'l ast::Expr>, ) { let hir_id = self.tcx.hir().node_to_hir_id(item.id); self.nest_tables(item.id, |v| { @@ -409,7 +409,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), var_data); } v.visit_ty(&typ); - v.visit_expr(expr); + walk_list!(v, visit_expr, expr); }); } @@ -1004,7 +1004,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { self.process_macro_use(trait_item.span); let vis_span = trait_item.span.shrink_to_lo(); match trait_item.kind { - ast::AssocItemKind::Const(ref ty, ref expr) => { + ast::AssocItemKind::Static(ref ty, _, ref expr) + | ast::AssocItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( trait_item.id, trait_item.ident, @@ -1015,18 +1016,18 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &trait_item.attrs, ); } - ast::AssocItemKind::Fn(ref sig, ref body) => { + ast::AssocItemKind::Fn(ref sig, ref generics, ref body) => { self.process_method( sig, body.as_ref().map(|x| &**x), trait_item.id, trait_item.ident, - &trait_item.generics, + generics, respan(vis_span, ast::VisibilityKind::Public), trait_item.span, ); } - ast::AssocItemKind::TyAlias(ref bounds, ref default_ty) => { + ast::AssocItemKind::TyAlias(_, ref bounds, ref default_ty) => { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!( @@ -1074,7 +1075,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) { self.process_macro_use(impl_item.span); match impl_item.kind { - ast::AssocItemKind::Const(ref ty, ref expr) => { + ast::AssocItemKind::Static(ref ty, _, ref expr) + | ast::AssocItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( impl_item.id, impl_item.ident, @@ -1085,19 +1087,19 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &impl_item.attrs, ); } - ast::AssocItemKind::Fn(ref sig, ref body) => { + ast::AssocItemKind::Fn(ref sig, ref generics, ref body) => { self.process_method( sig, body.as_deref(), impl_item.id, impl_item.ident, - &impl_item.generics, + generics, impl_item.vis.clone(), impl_item.span, ); } - ast::AssocItemKind::TyAlias(_, None) => {} - ast::AssocItemKind::TyAlias(_, Some(ref ty)) => { + ast::AssocItemKind::TyAlias(_, _, None) => {} + ast::AssocItemKind::TyAlias(_, _, Some(ref ty)) => { // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. @@ -1293,8 +1295,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { Fn(ref sig, ref ty_params, ref body) => { self.process_fn(item, &sig.decl, &sig.header, ty_params, body.as_deref()) } - Static(ref typ, _, ref expr) => self.process_static_or_const_item(item, typ, expr), - Const(ref typ, ref expr) => self.process_static_or_const_item(item, &typ, &expr), + Static(ref typ, _, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()), + Const(ref typ, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()), Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => { self.process_struct(item, def, ty_params) } @@ -1532,7 +1534,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&ret_ty); } } - ast::ForeignItemKind::Static(ref ty, _) => { + ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(var_data, DefData, item.span); self.dumper.dump_def(&access, var_data); @@ -1540,7 +1542,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(ty); } - ast::ForeignItemKind::Ty => { + ast::ForeignItemKind::TyAlias(..) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(var_data, DefData, item.span); self.dumper.dump_def(&access, var_data); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 401e172275113..d244370ae2c11 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -151,7 +151,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ForeignItemKind::Static(ref ty, _) => { + ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => { filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); @@ -173,7 +173,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { })) } // FIXME(plietar): needs a new DefKind in rls-data - ast::ForeignItemKind::Ty => None, + ast::ForeignItemKind::TyAlias(..) => None, ast::ForeignItemKind::Macro(..) => None, } } diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index d3c4d6d5723b9..3c68124ad40f7 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -334,10 +334,13 @@ impl Sig for ast::Item { let ty = ty.make(offset + text.len(), id, scx)?; text.push_str(&ty.text); - text.push_str(" = "); - let expr = pprust::expr_to_string(expr).replace('\n', " "); - text.push_str(&expr); + if let Some(expr) = expr { + text.push_str(" = "); + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + } + text.push(';'); Ok(extend_sig(ty, text, defs, vec![])) @@ -355,10 +358,13 @@ impl Sig for ast::Item { let ty = ty.make(offset + text.len(), id, scx)?; text.push_str(&ty.text); - text.push_str(" = "); - let expr = pprust::expr_to_string(expr).replace('\n', " "); - text.push_str(&expr); + if let Some(expr) = expr { + text.push_str(" = "); + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + } + text.push(';'); Ok(extend_sig(ty, text, defs, vec![])) @@ -754,7 +760,7 @@ impl Sig for ast::ForeignItem { Ok(sig) } - ast::ForeignItemKind::Static(ref ty, m) => { + ast::ForeignItemKind::Static(ref ty, m, _) => { let mut text = "static ".to_owned(); if m == ast::Mutability::Mut { text.push_str("mut "); @@ -773,7 +779,7 @@ impl Sig for ast::ForeignItem { Ok(extend_sig(ty_sig, text, defs, vec![])) } - ast::ForeignItemKind::Ty => { + ast::ForeignItemKind::TyAlias(..) => { let mut text = "type ".to_owned(); let name = self.ident.to_string(); let defs = vec![SigElement { @@ -786,6 +792,7 @@ impl Sig for ast::ForeignItem { Ok(Signature { text: text, defs: defs, refs: vec![] }) } + ast::ForeignItemKind::Const(..) => Err("foreign const"), ast::ForeignItemKind::Macro(..) => Err("macro"), } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 72430fa9c17e4..a73142406153a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1605,46 +1605,6 @@ pub struct FnSig { pub decl: P<FnDecl>, } -/// Represents associated items. -/// These include items in `impl` and `trait` definitions. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct AssocItem { - pub attrs: Vec<Attribute>, - pub id: NodeId, - pub span: Span, - pub vis: Visibility, - pub ident: Ident, - - pub defaultness: Defaultness, - pub generics: Generics, - pub kind: AssocItemKind, - /// See `Item::tokens` for what this is. - pub tokens: Option<TokenStream>, -} - -/// Represents various kinds of content within an `impl`. -/// -/// The term "provided" in the variants below refers to the item having a default -/// definition / body. Meanwhile, a "required" item lacks a definition / body. -/// In an implementation, all items must be provided. -/// The `Option`s below denote the bodies, where `Some(_)` -/// means "provided" and conversely `None` means "required". -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum AssocItemKind { - /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. - /// If `def` is parsed, then the associated constant is provided, and otherwise required. - Const(P<Ty>, Option<P<Expr>>), - - /// An associated function. - Fn(FnSig, Option<P<Block>>), - - /// An associated type. - TyAlias(GenericBounds, Option<P<Ty>>), - - /// A macro expanding to an associated item. - Macro(Mac), -} - #[derive( Clone, Copy, @@ -2536,11 +2496,11 @@ pub enum ItemKind { /// A static item (`static`). /// /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. - Static(P<Ty>, Mutability, P<Expr>), + Static(P<Ty>, Mutability, Option<P<Expr>>), /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. - Const(P<Ty>, P<Expr>), + Const(P<Ty>, Option<P<Expr>>), /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. @@ -2640,28 +2600,45 @@ impl ItemKind { } } -pub type ForeignItem = Item<ForeignItemKind>; +// FIXME(Centril): These definitions should be unmerged; +// see https://github.com/rust-lang/rust/pull/69194#discussion_r379899975 +pub type ForeignItem = Item<AssocItemKind>; +pub type ForeignItemKind = AssocItemKind; -/// An item within an `extern` block. +/// Represents associated items. +/// These include items in `impl` and `trait` definitions. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ForeignItemKind { - /// A foreign function. - Fn(FnSig, Generics, Option<P<Block>>), - /// A foreign static item (`static ext: u8`). - Static(P<Ty>, Mutability), - /// A foreign type. - Ty, - /// A macro invocation. - Macro(Mac), +pub struct AssocItem { + pub attrs: Vec<Attribute>, + pub id: NodeId, + pub span: Span, + pub vis: Visibility, + pub ident: Ident, + + pub defaultness: Defaultness, + pub kind: AssocItemKind, + /// See `Item::tokens` for what this is. + pub tokens: Option<TokenStream>, } -impl ForeignItemKind { - pub fn descriptive_variant(&self) -> &str { - match *self { - ForeignItemKind::Fn(..) => "foreign function", - ForeignItemKind::Static(..) => "foreign static item", - ForeignItemKind::Ty => "foreign type", - ForeignItemKind::Macro(..) => "macro in foreign module", - } - } +/// Represents non-free item kinds. +/// +/// The term "provided" in the variants below refers to the item having a default +/// definition / body. Meanwhile, a "required" item lacks a definition / body. +/// In an implementation, all items must be provided. +/// The `Option`s below denote the bodies, where `Some(_)` +/// means "provided" and conversely `None` means "required". +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum AssocItemKind { + /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. + /// If `def` is parsed, then the constant is provided, and otherwise required. + Const(P<Ty>, Option<P<Expr>>), + /// A static item (`static FOO: u8`). + Static(P<Ty>, Mutability, Option<P<Expr>>), + /// A function. + Fn(FnSig, Generics, Option<P<Block>>), + /// A type. + TyAlias(Generics, GenericBounds, Option<P<Ty>>), + /// A macro expanding to items. + Macro(Mac), } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index e0180d451936f..1fa6cce2c6284 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -890,13 +890,9 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) { match kind { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(ty, _mut, expr) => { + ItemKind::Static(ty, _, expr) | ItemKind::Const(ty, expr) => { vis.visit_ty(ty); - vis.visit_expr(expr); - } - ItemKind::Const(ty, expr) => { - vis.visit_ty(ty); - vis.visit_expr(expr); + visit_opt(expr, |expr| vis.visit_expr(expr)); } ItemKind::Fn(sig, generics, body) => { visit_fn_sig(sig, vis); @@ -951,31 +947,43 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>( mut item: P<AssocItem>, visitor: &mut T, ) -> SmallVec<[P<AssocItem>; 1]> { - let AssocItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } = + let AssocItem { id, ident, vis, defaultness: _, attrs, kind, span, tokens: _ } = item.deref_mut(); + walk_nested_item(visitor, id, span, ident, vis, attrs, kind); + smallvec![item] +} + +pub fn walk_nested_item( + visitor: &mut impl MutVisitor, + id: &mut NodeId, + span: &mut Span, + ident: &mut Ident, + vis: &mut Visibility, + attrs: &mut Vec<Attribute>, + kind: &mut AssocItemKind, +) { visitor.visit_id(id); visitor.visit_ident(ident); visitor.visit_vis(vis); visit_attrs(attrs, visitor); - visitor.visit_generics(generics); match kind { - AssocItemKind::Const(ty, expr) => { + AssocItemKind::Const(ty, expr) | AssocItemKind::Static(ty, _, expr) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } - AssocItemKind::Fn(sig, body) => { + AssocItemKind::Fn(sig, generics, body) => { + visitor.visit_generics(generics); visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - AssocItemKind::TyAlias(bounds, ty) => { + AssocItemKind::TyAlias(generics, bounds, ty) => { + visitor.visit_generics(generics); visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); } AssocItemKind::Macro(mac) => visitor.visit_mac(mac), } visitor.visit_span(span); - - smallvec![item] } pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) { @@ -1041,22 +1049,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>( visitor: &mut T, ) -> SmallVec<[P<ForeignItem>; 1]> { let ForeignItem { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut(); - visitor.visit_ident(ident); - visit_attrs(attrs, visitor); - match kind { - ForeignItemKind::Fn(sig, generics, body) => { - visit_fn_sig(sig, visitor); - visitor.visit_generics(generics); - visit_opt(body, |body| visitor.visit_block(body)); - } - ForeignItemKind::Static(t, _m) => visitor.visit_ty(t), - ForeignItemKind::Ty => {} - ForeignItemKind::Macro(mac) => visitor.visit_mac(mac), - } - visitor.visit_id(id); - visitor.visit_span(span); - visitor.visit_vis(vis); - + walk_nested_item(visitor, id, span, ident, vis, attrs, kind); smallvec![item] } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 73e731397c329..448ed0ba3de57 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -300,7 +300,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { ItemKind::Use(ref use_tree) => visitor.visit_use_tree(use_tree, item.id, false), ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(ref typ, ref expr) => { visitor.visit_ty(typ); - visitor.visit_expr(expr); + walk_list!(visitor, visit_expr, expr); } ItemKind::Fn(ref sig, ref generics, ref body) => { visitor.visit_generics(generics); @@ -525,21 +525,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { } pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) { - visitor.visit_vis(&item.vis); - visitor.visit_ident(item.ident); - - match item.kind { - ForeignItemKind::Fn(ref sig, ref generics, ref body) => { - visitor.visit_generics(generics); - let kind = FnKind::Fn(FnCtxt::Foreign, item.ident, sig, &item.vis, body.as_deref()); - visitor.visit_fn(kind, item.span, item.id); - } - ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), - ForeignItemKind::Ty => (), - ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac), - } - - walk_list!(visitor, visit_attribute, &item.attrs); + let ForeignItem { id, span, ident, vis, attrs, kind, tokens: _ } = item; + walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Foreign); } pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) { @@ -622,24 +609,39 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa } pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) { - visitor.visit_vis(&item.vis); - visitor.visit_ident(item.ident); - walk_list!(visitor, visit_attribute, &item.attrs); - visitor.visit_generics(&item.generics); - match item.kind { - AssocItemKind::Const(ref ty, ref expr) => { + let AssocItem { id, span, ident, vis, attrs, kind, tokens: _, defaultness: _ } = item; + walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Assoc(ctxt)); +} + +fn walk_nested_item<'a, V: Visitor<'a>>( + visitor: &mut V, + id: NodeId, + span: Span, + ident: Ident, + vis: &'a Visibility, + attrs: &'a [Attribute], + kind: &'a AssocItemKind, + ctxt: FnCtxt, +) { + visitor.visit_vis(vis); + visitor.visit_ident(ident); + walk_list!(visitor, visit_attribute, attrs); + match kind { + AssocItemKind::Const(ty, expr) | AssocItemKind::Static(ty, _, expr) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - AssocItemKind::Fn(ref sig, ref body) => { - let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref()); - visitor.visit_fn(kind, item.span, item.id); + AssocItemKind::Fn(sig, generics, body) => { + visitor.visit_generics(generics); + let kind = FnKind::Fn(ctxt, ident, sig, vis, body.as_deref()); + visitor.visit_fn(kind, span, id); } - AssocItemKind::TyAlias(ref bounds, ref ty) => { + AssocItemKind::TyAlias(generics, bounds, ty) => { + visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); } - AssocItemKind::Macro(ref mac) => { + AssocItemKind::Macro(mac) => { visitor.visit_mac(mac); } } diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs index 60633c6930cdf..2ed682cea9503 100644 --- a/src/test/ui/did_you_mean/issue-40006.rs +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -18,10 +18,10 @@ trait A { //~ ERROR missing trait B { fn xxx() { ### } //~ ERROR expected } -trait C { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration +trait C { //~ ERROR missing `fn`, `type`, `const`, or `static` for item declaration L = M; } -trait D { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration +trait D { //~ ERROR missing `fn`, `type`, `const`, or `static` for item declaration Z = { 2 + 3 }; } trait E { diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 072e61f6a3cd1..119e30a3e0f57 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,26 +1,26 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:1:13 | LL | impl dyn A { | _____________^ LL | | Y - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:7:10 | LL | trait X { | __________^ LL | | X() {} - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:15:10 | LL | trait A { | __________^ LL | | X() {} - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` error: expected `[`, found `#` --> $DIR/issue-40006.rs:19:17 @@ -28,21 +28,21 @@ error: expected `[`, found `#` LL | fn xxx() { ### } | ^ expected `[` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:21:10 | LL | trait C { | __________^ LL | | L = M; - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:24:10 | LL | trait D { | __________^ LL | | Z = { 2 + 3 }; - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` error: expected one of `!` or `::`, found `(` --> $DIR/issue-40006.rs:28:9 @@ -50,11 +50,11 @@ error: expected one of `!` or `::`, found `(` LL | ::Y (); | ^ expected one of `!` or `::` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:32:8 | LL | pub hello_method(&self) { - | ^ missing `fn`, `type`, or `const` + | ^ missing `fn`, `type`, `const`, or `static` error[E0599]: no method named `hello_method` found for struct `S` in the current scope --> $DIR/issue-40006.rs:38:7 diff --git a/src/test/ui/extern/extern-const.stderr b/src/test/ui/extern/extern-const.stderr index 258202b6903d3..7f67adbdb19c7 100644 --- a/src/test/ui/extern/extern-const.stderr +++ b/src/test/ui/extern/extern-const.stderr @@ -1,8 +1,12 @@ error: extern items cannot be `const` - --> $DIR/extern-const.rs:16:5 + --> $DIR/extern-const.rs:16:11 | LL | const rust_dbg_static_mut: libc::c_int; - | ^^^^^ help: try using a static value: `static` + | ------^^^^^^^^^^^^^^^^^^^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html error: aborting due to previous error diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr index 6221b90b31dd7..f4ca3c46ea28a 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 identifier, found `)` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `)` --> $DIR/issue-58856-2.rs:11:1 | LL | } - | - expected one of 11 possible tokens + | - expected one of 12 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index b2beb73503bb0..bab50a53b1ae4 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 identifier, found `;` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `;` --> $DIR/issue-60075.rs:6:11 | LL | fn qux() -> Option<usize> { diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs index a70163df1cb93..5570f081b157d 100644 --- a/src/test/ui/macros/issue-54441.rs +++ b/src/test/ui/macros/issue-54441.rs @@ -1,5 +1,5 @@ macro_rules! m { - //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration () => { let }; diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr index 761e7aec7235a..5857aacb43176 100644 --- a/src/test/ui/macros/issue-54441.stderr +++ b/src/test/ui/macros/issue-54441.stderr @@ -1,11 +1,11 @@ -error: missing `fn`, `type`, or `static` for extern-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-54441.rs:1:1 | LL | / macro_rules! m { LL | | LL | | () => { LL | | let - | |________^ missing `fn`, `type`, or `static` + | |________^ missing `fn`, `type`, `const`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/assoc-const-underscore-semantic-fail.rs b/src/test/ui/parser/assoc-const-underscore-semantic-fail.rs new file mode 100644 index 0000000000000..d37ce06c555bf --- /dev/null +++ b/src/test/ui/parser/assoc-const-underscore-semantic-fail.rs @@ -0,0 +1,17 @@ +// Semantically, an associated constant cannot use `_` as a name. + +fn main() {} + +const _: () = { + pub trait A { + const _: () = (); //~ ERROR `const` items in this context need a name + } + impl A for () { + const _: () = (); //~ ERROR `const` items in this context need a name + //~^ ERROR const `_` is not a member of trait `A` + } + struct B; + impl B { + const _: () = (); //~ ERROR `const` items in this context need a name + } +}; diff --git a/src/test/ui/parser/assoc-const-underscore-semantic-fail.stderr b/src/test/ui/parser/assoc-const-underscore-semantic-fail.stderr new file mode 100644 index 0000000000000..538bf0ec100dc --- /dev/null +++ b/src/test/ui/parser/assoc-const-underscore-semantic-fail.stderr @@ -0,0 +1,27 @@ +error: `const` items in this context need a name + --> $DIR/assoc-const-underscore-semantic-fail.rs:7:15 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error: `const` items in this context need a name + --> $DIR/assoc-const-underscore-semantic-fail.rs:10:15 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error: `const` items in this context need a name + --> $DIR/assoc-const-underscore-semantic-fail.rs:15:15 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error[E0438]: const `_` is not a member of trait `A` + --> $DIR/assoc-const-underscore-semantic-fail.rs:10:9 + | +LL | const _: () = (); + | ^^^^^^^^^^^^^^^^^ not a member of trait `A` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0438`. diff --git a/src/test/ui/parser/assoc-const-underscore-syntactic-pass.rs b/src/test/ui/parser/assoc-const-underscore-syntactic-pass.rs new file mode 100644 index 0000000000000..60da408c81153 --- /dev/null +++ b/src/test/ui/parser/assoc-const-underscore-syntactic-pass.rs @@ -0,0 +1,18 @@ +// All constant items (associated or otherwise) may syntactically use `_` as a name. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +const _: () = { + pub trait A { + const _: () = (); + } + impl A for () { + const _: () = (); + } + impl dyn A { + const _: () = (); + } +}; diff --git a/src/test/ui/parser/assoc-static-semantic-fail.rs b/src/test/ui/parser/assoc-static-semantic-fail.rs new file mode 100644 index 0000000000000..cf3debd77cbfd --- /dev/null +++ b/src/test/ui/parser/assoc-static-semantic-fail.rs @@ -0,0 +1,43 @@ +// Semantically, we do not allow e.g., `static X: u8 = 0;` as an associated item. + +#![feature(specialization)] + +fn main() {} + +struct S; +impl S { + static IA: u8 = 0; + //~^ ERROR associated `static` items are not allowed + static IB: u8; + //~^ ERROR associated `static` items are not allowed + default static IC: u8 = 0; + //~^ ERROR associated `static` items are not allowed + pub(crate) default static ID: u8; + //~^ ERROR associated `static` items are not allowed +} + +trait T { + static TA: u8 = 0; + //~^ ERROR associated `static` items are not allowed + static TB: u8; + //~^ ERROR associated `static` items are not allowed + default static TC: u8 = 0; + //~^ ERROR associated `static` items are not allowed + //~| ERROR `default` is only allowed on items in + pub(crate) default static TD: u8; + //~^ ERROR associated `static` items are not allowed + //~| ERROR `default` is only allowed on items in + //~| ERROR unnecessary visibility qualifier +} + +impl T for S { + static TA: u8 = 0; + //~^ ERROR associated `static` items are not allowed + static TB: u8; + //~^ ERROR associated `static` items are not allowed + default static TC: u8 = 0; + //~^ ERROR associated `static` items are not allowed + pub default static TD: u8; + //~^ ERROR associated `static` items are not allowed + //~| ERROR unnecessary visibility qualifier +} diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr new file mode 100644 index 0000000000000..d02e2855c7e62 --- /dev/null +++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr @@ -0,0 +1,99 @@ +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:9:5 + | +LL | static IA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:11:5 + | +LL | static IB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:13:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:15:5 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:20:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:22:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:24:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:27:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:34:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:36:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:38:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:40:5 + | +LL | pub default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/assoc-static-semantic-fail.rs:24:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/assoc-static-semantic-fail.rs:27:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0449]: unnecessary visibility qualifier + --> $DIR/assoc-static-semantic-fail.rs:27:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^ + +error[E0449]: unnecessary visibility qualifier + --> $DIR/assoc-static-semantic-fail.rs:40:5 + | +LL | pub default static TD: u8; + | ^^^ `pub` not permitted here because it's implied + +error: aborting due to 16 previous errors + +For more information about this error, try `rustc --explain E0449`. diff --git a/src/test/ui/parser/assoc-static-syntactic-fail.rs b/src/test/ui/parser/assoc-static-syntactic-fail.rs new file mode 100644 index 0000000000000..8f042767e5503 --- /dev/null +++ b/src/test/ui/parser/assoc-static-syntactic-fail.rs @@ -0,0 +1,27 @@ +// Syntactically, we do allow e.g., `static X: u8 = 0;` as an associated item. + +fn main() {} + +#[cfg(FALSE)] +impl S { + static IA: u8 = 0; //~ ERROR associated `static` items are not allowed + static IB: u8; //~ ERROR associated `static` items are not allowed + default static IC: u8 = 0; //~ ERROR associated `static` items are not allowed + pub(crate) default static ID: u8; //~ ERROR associated `static` items are not allowed +} + +#[cfg(FALSE)] +trait T { + static TA: u8 = 0; //~ ERROR associated `static` items are not allowed + static TB: u8; //~ ERROR associated `static` items are not allowed + default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed + pub(crate) default static TD: u8; //~ ERROR associated `static` items are not allowed +} + +#[cfg(FALSE)] +impl T for S { + static TA: u8 = 0; //~ ERROR associated `static` items are not allowed + static TB: u8; //~ ERROR associated `static` items are not allowed + default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed + pub default static TD: u8; //~ ERROR associated `static` items are not allowed +} diff --git a/src/test/ui/parser/assoc-static-syntactic-fail.stderr b/src/test/ui/parser/assoc-static-syntactic-fail.stderr new file mode 100644 index 0000000000000..bb1e5c4be2e9c --- /dev/null +++ b/src/test/ui/parser/assoc-static-syntactic-fail.stderr @@ -0,0 +1,74 @@ +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:7:5 + | +LL | static IA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:8:5 + | +LL | static IB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:9:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:10:5 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:15:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:16:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:17:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:18:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:23:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:24:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:25:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:26:5 + | +LL | pub default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs index 65ecb1ebbe919..50952eef22f5c 100644 --- a/src/test/ui/parser/default.rs +++ b/src/test/ui/parser/default.rs @@ -20,7 +20,7 @@ impl Foo for u16 { impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo` default pub fn foo<T: Default>() -> T { T::default() } - //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration } fn main() {} diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr index ede9e47151863..07b051ece2b5d 100644 --- a/src/test/ui/parser/default.stderr +++ b/src/test/ui/parser/default.stderr @@ -1,8 +1,8 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/default.rs:22:12 | LL | default pub fn foo<T: Default>() -> T { T::default() } - | ^ missing `fn`, `type`, or `const` + | ^ missing `fn`, `type`, `const`, or `static` error[E0449]: unnecessary visibility qualifier --> $DIR/default.rs:16:5 diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index 1d271fa64b0ec..f6e7f7e6abe8f 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -2,5 +2,5 @@ fn main() {} extern { pub pub fn foo(); - //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index 36a3a1ed5a0cc..398ba65c9e1d8 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,8 +1,8 @@ -error: missing `fn`, `type`, or `static` for extern-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/duplicate-visibility.rs:4:8 | LL | pub pub fn foo(); - | ^ missing `fn`, `type`, or `static` + | ^ missing `fn`, `type`, `const`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/extern-no-fn.rs b/src/test/ui/parser/extern-no-fn.rs index c37ddd69ce53c..dc47f7410730c 100644 --- a/src/test/ui/parser/extern-no-fn.rs +++ b/src/test/ui/parser/extern-no-fn.rs @@ -1,4 +1,5 @@ -extern { //~ ERROR missing `fn`, `type`, or `static` for extern-item declaration +extern { +//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration f(); } diff --git a/src/test/ui/parser/extern-no-fn.stderr b/src/test/ui/parser/extern-no-fn.stderr index d2d5e3c46874a..8d55eefc8d0ec 100644 --- a/src/test/ui/parser/extern-no-fn.stderr +++ b/src/test/ui/parser/extern-no-fn.stderr @@ -1,10 +1,11 @@ -error: missing `fn`, `type`, or `static` for extern-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/extern-no-fn.rs:1:9 | LL | extern { | _________^ +LL | | LL | | f(); - | |____^ missing `fn`, `type`, or `static` + | |____^ missing `fn`, `type`, `const`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/foreign-const-semantic-fail.rs b/src/test/ui/parser/foreign-const-semantic-fail.rs new file mode 100644 index 0000000000000..d28b64142826c --- /dev/null +++ b/src/test/ui/parser/foreign-const-semantic-fail.rs @@ -0,0 +1,8 @@ +fn main() {} + +extern { + const A: isize; + //~^ ERROR extern items cannot be `const` + const B: isize = 42; + //~^ ERROR extern items cannot be `const` +} diff --git a/src/test/ui/parser/foreign-const-semantic-fail.stderr b/src/test/ui/parser/foreign-const-semantic-fail.stderr new file mode 100644 index 0000000000000..f364f11bb038d --- /dev/null +++ b/src/test/ui/parser/foreign-const-semantic-fail.stderr @@ -0,0 +1,22 @@ +error: extern items cannot be `const` + --> $DIR/foreign-const-semantic-fail.rs:4:11 + | +LL | const A: isize; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: extern items cannot be `const` + --> $DIR/foreign-const-semantic-fail.rs:6:11 + | +LL | const B: isize = 42; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/foreign-const-syntactic-fail.rs b/src/test/ui/parser/foreign-const-syntactic-fail.rs new file mode 100644 index 0000000000000..a78f8b1623a80 --- /dev/null +++ b/src/test/ui/parser/foreign-const-syntactic-fail.rs @@ -0,0 +1,9 @@ +// Syntactically, a `const` item inside an `extern { ... }` block is not allowed. + +fn main() {} + +#[cfg(FALSE)] +extern { + const A: isize; //~ ERROR extern items cannot be `const` + const B: isize = 42; //~ ERROR extern items cannot be `const` +} diff --git a/src/test/ui/parser/foreign-const-syntactic-fail.stderr b/src/test/ui/parser/foreign-const-syntactic-fail.stderr new file mode 100644 index 0000000000000..9cf58fa95fb2d --- /dev/null +++ b/src/test/ui/parser/foreign-const-syntactic-fail.stderr @@ -0,0 +1,22 @@ +error: extern items cannot be `const` + --> $DIR/foreign-const-syntactic-fail.rs:7:11 + | +LL | const A: isize; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: extern items cannot be `const` + --> $DIR/foreign-const-syntactic-fail.rs:8:11 + | +LL | const B: isize = 42; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/foreign-static-semantic-fail.rs b/src/test/ui/parser/foreign-static-semantic-fail.rs new file mode 100644 index 0000000000000..9abdf33df9c46 --- /dev/null +++ b/src/test/ui/parser/foreign-static-semantic-fail.rs @@ -0,0 +1,8 @@ +// Syntactically, a foreign static may not have a body. + +fn main() {} + +extern { + static X: u8 = 0; //~ ERROR incorrect `static` inside `extern` block + static mut Y: u8 = 0; //~ ERROR incorrect `static` inside `extern` block +} diff --git a/src/test/ui/parser/foreign-static-semantic-fail.stderr b/src/test/ui/parser/foreign-static-semantic-fail.stderr new file mode 100644 index 0000000000000..5942e3a94497b --- /dev/null +++ b/src/test/ui/parser/foreign-static-semantic-fail.stderr @@ -0,0 +1,27 @@ +error: incorrect `static` inside `extern` block + --> $DIR/foreign-static-semantic-fail.rs:6:12 + | +LL | extern { + | ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body +LL | static X: u8 = 0; + | ^ - the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect `static` inside `extern` block + --> $DIR/foreign-static-semantic-fail.rs:7:16 + | +LL | extern { + | ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body +LL | static X: u8 = 0; +LL | static mut Y: u8 = 0; + | ^ - the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/foreign-static-syntactic-pass.rs b/src/test/ui/parser/foreign-static-syntactic-pass.rs new file mode 100644 index 0000000000000..2c805e8a0b700 --- /dev/null +++ b/src/test/ui/parser/foreign-static-syntactic-pass.rs @@ -0,0 +1,11 @@ +// Syntactically, a foreign static may have a body. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +extern { + static X: u8 = 0; + static mut Y: u8 = 0; +} diff --git a/src/test/ui/parser/foreign-ty-semantic-fail.rs b/src/test/ui/parser/foreign-ty-semantic-fail.rs new file mode 100644 index 0000000000000..96b15232b10d0 --- /dev/null +++ b/src/test/ui/parser/foreign-ty-semantic-fail.rs @@ -0,0 +1,18 @@ +#![feature(extern_types)] + +fn main() {} + +extern "C" { + type A: Ord; + //~^ ERROR bounds on `type`s in `extern` blocks have no effect + type B<'a> where 'a: 'static; + //~^ ERROR `type`s inside `extern` blocks cannot have generic parameters + //~| ERROR `type`s inside `extern` blocks cannot have `where` clauses + type C<T: Ord> where T: 'static; + //~^ ERROR `type`s inside `extern` blocks cannot have generic parameters + //~| ERROR `type`s inside `extern` blocks cannot have `where` clauses + type D = u8; + //~^ ERROR incorrect `type` inside `extern` block + + type E: where; +} diff --git a/src/test/ui/parser/foreign-ty-semantic-fail.stderr b/src/test/ui/parser/foreign-ty-semantic-fail.stderr new file mode 100644 index 0000000000000..588e4966aaeb5 --- /dev/null +++ b/src/test/ui/parser/foreign-ty-semantic-fail.stderr @@ -0,0 +1,65 @@ +error: bounds on `type`s in `extern` blocks have no effect + --> $DIR/foreign-ty-semantic-fail.rs:6:13 + | +LL | type A: Ord; + | ^^^ + +error: `type`s inside `extern` blocks cannot have generic parameters + --> $DIR/foreign-ty-semantic-fail.rs:8:11 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type B<'a> where 'a: 'static; + | ^^^^ help: remove the generic parameters + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have `where` clauses + --> $DIR/foreign-ty-semantic-fail.rs:8:16 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type B<'a> where 'a: 'static; + | ^^^^^^^^^^^^^^^^^ help: remove the `where` clause + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have generic parameters + --> $DIR/foreign-ty-semantic-fail.rs:11:11 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type C<T: Ord> where T: 'static; + | ^^^^^^^^ help: remove the generic parameters + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have `where` clauses + --> $DIR/foreign-ty-semantic-fail.rs:11:20 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type C<T: Ord> where T: 'static; + | ^^^^^^^^^^^^^^^^ help: remove the `where` clause + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect `type` inside `extern` block + --> $DIR/foreign-ty-semantic-fail.rs:14:10 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign types and types inside of them cannot have a body +... +LL | type D = u8; + | ^ -- the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/foreign-ty-syntactic-pass.rs b/src/test/ui/parser/foreign-ty-syntactic-pass.rs new file mode 100644 index 0000000000000..a746de1f14f4d --- /dev/null +++ b/src/test/ui/parser/foreign-ty-syntactic-pass.rs @@ -0,0 +1,12 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +extern "C" { + type A: Ord; + type A<'a> where 'a: 'static; + type A<T: Ord> where T: 'static; + type A = u8; + type A<'a: 'static, T: Ord + 'static>: Eq + PartialEq where T: 'static + Copy = Vec<u8>; +} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs index 9c321c4bd0d74..fa9c7ababcf9e 100644 --- a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs @@ -11,11 +11,11 @@ impl X { //~| ERROR associated types are not yet supported in inherent impls type Z: Ord; //~^ ERROR associated type in `impl` without body - //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR bounds on `type`s in `impl`s have no effect //~| ERROR associated types are not yet supported in inherent impls type W: Ord where Self: Eq; //~^ ERROR associated type in `impl` without body - //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR bounds on `type`s in `impl`s have no effect //~| ERROR associated types are not yet supported in inherent impls type W where Self: Eq; //~^ ERROR associated type in `impl` without body diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr index 65e1981e3ac78..541d9317c79d0 100644 --- a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -14,7 +14,7 @@ LL | type Z: Ord; | | | help: provide a definition for the type: `= <type>;` -error: bounds on associated `type`s in `impl`s have no effect +error: bounds on `type`s in `impl`s have no effect --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13 | LL | type Z: Ord; @@ -28,7 +28,7 @@ LL | type W: Ord where Self: Eq; | | | help: provide a definition for the type: `= <type>;` -error: bounds on associated `type`s in `impl`s have no effect +error: bounds on `type`s in `impl`s have no effect --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:13 | LL | type W: Ord where Self: Eq; diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issue-19398.rs index 982a6be23ac5f..014c930ef8205 100644 --- a/src/test/ui/parser/issue-19398.rs +++ b/src/test/ui/parser/issue-19398.rs @@ -1,5 +1,5 @@ trait T { - //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration extern "Rust" unsafe fn foo(); } diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issue-19398.stderr index 2bd6ac3a4b3a4..b38b39f9bd99f 100644 --- a/src/test/ui/parser/issue-19398.stderr +++ b/src/test/ui/parser/issue-19398.stderr @@ -1,11 +1,11 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-19398.rs:1:10 | LL | trait T { | __________^ LL | | LL | | extern "Rust" unsafe fn foo(); - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-21153.rs b/src/test/ui/parser/issue-21153.rs index 46cd45f28b43d..4fe05e6f04155 100644 --- a/src/test/ui/parser/issue-21153.rs +++ b/src/test/ui/parser/issue-21153.rs @@ -1,4 +1,5 @@ -trait MyTrait<T>: Iterator { //~ ERROR missing `fn`, `type`, or `const` +trait MyTrait<T>: Iterator { + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration Item = T; } diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr index 6e20a9ce3c432..e9824bd729081 100644 --- a/src/test/ui/parser/issue-21153.stderr +++ b/src/test/ui/parser/issue-21153.stderr @@ -1,10 +1,11 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-21153.rs:1:29 | LL | trait MyTrait<T>: Iterator { | _____________________________^ +LL | | LL | | Item = T; - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` 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 25c1efe35ae11..d25828da0b979 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 identifier, found `...` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `...` --> $DIR/issue-32446.rs:4:11 | LL | trait T { ... } - | ^^^ expected one of 11 possible tokens + | ^^^ expected one of 12 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 327bc65818fa9..a91ef6c67e89e 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`, `unsafe`, or identifier, found `}` +error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `static`, `type`, `unsafe`, or identifier, found `}` --> $DIR/issue-41155.rs:5:1 | LL | pub - | - expected one of 9 possible tokens + | - expected one of 10 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs b/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs new file mode 100644 index 0000000000000..613b3c9856171 --- /dev/null +++ b/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs @@ -0,0 +1,7 @@ +// Semantically, a free `const` item cannot omit its body. + +fn main() {} + +const A: u8; //~ ERROR free constant item without body +const B; //~ ERROR free constant item without body +//~^ ERROR missing type for `const` item diff --git a/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr new file mode 100644 index 0000000000000..4e97229fa1a41 --- /dev/null +++ b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr @@ -0,0 +1,24 @@ +error: free constant item without body + --> $DIR/item-free-const-no-body-semantic-fail.rs:5:1 + | +LL | const A: u8; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= <expr>;` + +error: free constant item without body + --> $DIR/item-free-const-no-body-semantic-fail.rs:6:1 + | +LL | const B; + | ^^^^^^^- + | | + | help: provide a definition for the constant: `= <expr>;` + +error: missing type for `const` item + --> $DIR/item-free-const-no-body-semantic-fail.rs:6:7 + | +LL | const B; + | ^ help: provide a type for the item: `B: [type error]` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/item-free-const-no-body-syntactic-pass.rs b/src/test/ui/parser/item-free-const-no-body-syntactic-pass.rs new file mode 100644 index 0000000000000..acfdd3c363f25 --- /dev/null +++ b/src/test/ui/parser/item-free-const-no-body-syntactic-pass.rs @@ -0,0 +1,8 @@ +// Syntactically, a free `const` item can omit its body. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +const X: u8; diff --git a/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs b/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs new file mode 100644 index 0000000000000..780479e3d26ac --- /dev/null +++ b/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs @@ -0,0 +1,11 @@ +// Semantically, a free `static` item cannot omit its body. + +fn main() {} + +static A: u8; //~ ERROR free static item without body +static B; //~ ERROR free static item without body +//~^ ERROR missing type for `static` item + +static mut C: u8; //~ ERROR free static item without body +static mut D; //~ ERROR free static item without body +//~^ ERROR missing type for `static mut` item diff --git a/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr new file mode 100644 index 0000000000000..60b7bb34c698b --- /dev/null +++ b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr @@ -0,0 +1,46 @@ +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:5:1 + | +LL | static A: u8; + | ^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= <expr>;` + +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:6:1 + | +LL | static B; + | ^^^^^^^^- + | | + | help: provide a definition for the static: `= <expr>;` + +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:9:1 + | +LL | static mut C: u8; + | ^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= <expr>;` + +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:10:1 + | +LL | static mut D; + | ^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= <expr>;` + +error: missing type for `static` item + --> $DIR/item-free-static-no-body-semantic-fail.rs:6:8 + | +LL | static B; + | ^ help: provide a type for the item: `B: [type error]` + +error: missing type for `static mut` item + --> $DIR/item-free-static-no-body-semantic-fail.rs:10:12 + | +LL | static mut D; + | ^ help: provide a type for the item: `D: [type error]` + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/item-free-static-no-body-syntactic-pass.rs b/src/test/ui/parser/item-free-static-no-body-syntactic-pass.rs new file mode 100644 index 0000000000000..db0039204d870 --- /dev/null +++ b/src/test/ui/parser/item-free-static-no-body-syntactic-pass.rs @@ -0,0 +1,8 @@ +// Syntactically, a free `const` item can omit its body. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +static X: u8; 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 9d05e85bcc00e..c76b096a1ebf4 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`, `unsafe`, or identifier, found `2` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, or identifier, found `2` --> $DIR/trait-non-item-macros.rs:2:19 | LL | ($a:expr) => ($a) - | ^^ expected one of 10 possible tokens + | ^^ expected one of 11 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 592215030f552..748db8983b595 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 @@ -3,7 +3,7 @@ fn main() {} impl T for () { //~ ERROR cannot find trait `T` in this scope fn foo(&self) {} -//~^ ERROR missing `fn`, `type`, or `const` +//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration trait T { fn foo(&self); 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 1ec54525105f6..240be39eacef4 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 @@ -7,7 +7,7 @@ LL | impl T for () { LL | | ^ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/missing-close-brace-in-impl-trait.rs:5:17 | LL | fn foo(&self) {} @@ -15,7 +15,7 @@ LL | fn foo(&self) {} LL | | LL | | LL | | trait T { - | |_ missing `fn`, `type`, or `const` + | |_ missing `fn`, `type`, `const`, or `static` error[E0405]: cannot find trait `T` in this scope --> $DIR/missing-close-brace-in-impl-trait.rs:3:6 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 077e334719427..4e8cc6489bc64 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<T>(); -//~^ ERROR missing `fn`, `type`, or `const` +//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration impl T for Bar<usize> { 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 1bb153c461d90..54afad5755b15 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: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/missing-close-brace-in-trait.rs:5:11 | LL | pub(crate) struct Bar<T>(); - | ^ missing `fn`, `type`, or `const` + | ^ missing `fn`, `type`, `const`, or `static` 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/removed-syntax-extern-const.rs b/src/test/ui/parser/removed-syntax-extern-const.rs deleted file mode 100644 index 71c22e62f8e4b..0000000000000 --- a/src/test/ui/parser/removed-syntax-extern-const.rs +++ /dev/null @@ -1,6 +0,0 @@ -extern { - const i: isize; - //~^ ERROR extern items cannot be `const` -} - -fn main() {} diff --git a/src/test/ui/parser/removed-syntax-extern-const.stderr b/src/test/ui/parser/removed-syntax-extern-const.stderr deleted file mode 100644 index 2bccbd91452f6..0000000000000 --- a/src/test/ui/parser/removed-syntax-extern-const.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: extern items cannot be `const` - --> $DIR/removed-syntax-extern-const.rs:2:5 - | -LL | const i: isize; - | ^^^^^ help: try using a static value: `static` - -error: aborting due to previous error - diff --git a/src/test/ui/parser/removed-syntax-static-fn.rs b/src/test/ui/parser/removed-syntax-static-fn.rs index 9e12222f3fd8b..cd643b874dbda 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.rs +++ b/src/test/ui/parser/removed-syntax-static-fn.rs @@ -1,8 +1,10 @@ struct S; impl S { - //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration static fn f() {} + //~^ ERROR expected identifier, found keyword `fn` + //~| ERROR expected one of `:`, `;`, or `=` + //~| ERROR missing type for `static` item } 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 5edf88026fbec..dc5625bdadea3 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.stderr +++ b/src/test/ui/parser/removed-syntax-static-fn.stderr @@ -1,11 +1,20 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration - --> $DIR/removed-syntax-static-fn.rs:3:9 +error: expected identifier, found keyword `fn` + --> $DIR/removed-syntax-static-fn.rs:4:12 | -LL | impl S { - | _________^ -LL | | -LL | | static fn f() {} - | |____^ missing `fn`, `type`, or `const` +LL | static fn f() {} + | ^^ expected identifier, found keyword -error: aborting due to previous error +error: expected one of `:`, `;`, or `=`, found `f` + --> $DIR/removed-syntax-static-fn.rs:4:15 + | +LL | static fn f() {} + | ^ expected one of `:`, `;`, or `=` + +error: missing type for `static` item + --> $DIR/removed-syntax-static-fn.rs:4:12 + | +LL | static fn f() {} + | ^^ help: provide a type for the item: `r#fn: <type>` + +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/underscore_item_not_const.rs b/src/test/ui/parser/underscore_item_not_const.rs index 7b0d128f06f8a..c01ac4752e075 100644 --- a/src/test/ui/parser/underscore_item_not_const.rs +++ b/src/test/ui/parser/underscore_item_not_const.rs @@ -1,18 +1,4 @@ -// Test that various non-const items and associated consts do not permit `_` as a name. - -// Associated `const`s: - -pub trait A { - const _: () = (); //~ ERROR expected identifier, found reserved identifier `_` -} -impl A for () { - const _: () = (); //~ ERROR expected identifier, found reserved identifier `_` -} -impl dyn A { - const _: () = (); //~ ERROR expected identifier, found reserved identifier `_` -} - -// Other kinds of items: +// Test that various non-const items do not syntactically permit `_` as a name. static _: () = (); //~ ERROR expected identifier, found reserved identifier `_` struct _(); //~ ERROR expected identifier, found reserved identifier `_` diff --git a/src/test/ui/parser/underscore_item_not_const.stderr b/src/test/ui/parser/underscore_item_not_const.stderr index ebf1ff9ff1ea3..0bc7642dd1964 100644 --- a/src/test/ui/parser/underscore_item_not_const.stderr +++ b/src/test/ui/parser/underscore_item_not_const.stderr @@ -1,92 +1,74 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:6:11 - | -LL | const _: () = (); - | ^ expected identifier, found reserved identifier - -error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:9:11 - | -LL | const _: () = (); - | ^ expected identifier, found reserved identifier - -error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:12:11 - | -LL | const _: () = (); - | ^ expected identifier, found reserved identifier - -error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:17:8 + --> $DIR/underscore_item_not_const.rs:3:8 | LL | static _: () = (); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:18:8 + --> $DIR/underscore_item_not_const.rs:4:8 | LL | struct _(); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:19:6 + --> $DIR/underscore_item_not_const.rs:5:6 | LL | enum _ {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:20:4 + --> $DIR/underscore_item_not_const.rs:6:4 | LL | fn _() {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:21:5 + --> $DIR/underscore_item_not_const.rs:7:5 | LL | mod _ {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:22:6 + --> $DIR/underscore_item_not_const.rs:8:6 | LL | type _ = (); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:23:5 + --> $DIR/underscore_item_not_const.rs:9:5 | LL | use _; | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:24:5 + --> $DIR/underscore_item_not_const.rs:10:5 | LL | use _ as g; | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:25:7 + --> $DIR/underscore_item_not_const.rs:11:7 | LL | trait _ {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:26:7 + --> $DIR/underscore_item_not_const.rs:12:7 | LL | trait _ = Copy; | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:27:14 + --> $DIR/underscore_item_not_const.rs:13:14 | LL | macro_rules! _ { () => {} } | ^ expected identifier, found reserved identifier error: expected one of `!` or `::`, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:28:7 + --> $DIR/underscore_item_not_const.rs:14:7 | LL | union _ { f: u8 } | ^ expected one of `!` or `::` -error: aborting due to 15 previous errors +error: aborting due to 12 previous errors