syntactically allow visibility on trait item & enum variant

This commit is contained in:
Mazdak Farrokhzad 2019-11-07 11:26:36 +01:00
parent e2fa9527d4
commit 9a88364525
25 changed files with 190 additions and 115 deletions

View File

@ -1187,26 +1187,6 @@ impl<'a> Parser<'a> {
}
}
/// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid.
pub(super) fn eat_bad_pub(&mut self) {
// When `unclosed_delims` is populated, it means that the code being parsed is already
// quite malformed, which might mean that, for example, a pub struct definition could be
// parsed as being a trait item, which is invalid and this error would trigger
// unconditionally, resulting in misleading diagnostics. Because of this, we only attempt
// this nice to have recovery for code that is otherwise well formed.
if self.token.is_keyword(kw::Pub) && self.unclosed_delims.is_empty() {
match self.parse_visibility(false) {
Ok(vis) => {
self.diagnostic()
.struct_span_err(vis.span, "unnecessary visibility qualifier")
.span_label(vis.span, "`pub` not permitted here")
.emit();
}
Err(mut err) => err.emit(),
}
}
}
/// Eats tokens until we can be relatively sure we reached the end of the
/// statement. This is something of a best-effort heuristic.
///

View File

@ -1,4 +1,4 @@
use super::{Parser, PathStyle};
use super::{Parser, PathStyle, FollowedByType};
use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim};
use crate::maybe_whole;
@ -93,7 +93,7 @@ impl<'a> Parser<'a> {
let lo = self.token.span;
let vis = self.parse_visibility(false)?;
let vis = self.parse_visibility(FollowedByType::No)?;
if self.eat_keyword(kw::Use) {
// USE ITEM
@ -706,7 +706,7 @@ impl<'a> Parser<'a> {
mut attrs: Vec<Attribute>,
) -> PResult<'a, ImplItem> {
let lo = self.token.span;
let vis = self.parse_visibility(false)?;
let vis = self.parse_visibility(FollowedByType::No)?;
let defaultness = self.parse_defaultness();
let (name, kind, generics) = if let Some(type_) = self.eat_type() {
let (name, alias, generics) = type_?;
@ -896,7 +896,7 @@ impl<'a> Parser<'a> {
mut attrs: Vec<Attribute>,
) -> PResult<'a, TraitItem> {
let lo = self.token.span;
self.eat_bad_pub();
let vis = self.parse_visibility(FollowedByType::No)?;
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
self.parse_trait_item_assoc_ty()?
} else if self.is_const_item() {
@ -912,6 +912,7 @@ impl<'a> Parser<'a> {
id: DUMMY_NODE_ID,
ident: name,
attrs,
vis,
generics,
kind,
span: lo.to(self.prev_span),
@ -1142,7 +1143,7 @@ impl<'a> Parser<'a> {
let attrs = self.parse_outer_attributes()?;
let lo = self.token.span;
let visibility = self.parse_visibility(false)?;
let visibility = self.parse_visibility(FollowedByType::No)?;
// FOREIGN STATIC ITEM
// Treat `const` as `static` for error recovery, but don't add it to expected tokens.
@ -1370,7 +1371,7 @@ impl<'a> Parser<'a> {
let variant_attrs = self.parse_outer_attributes()?;
let vlo = self.token.span;
self.eat_bad_pub();
let vis = self.parse_visibility(FollowedByType::No)?;
let ident = self.parse_ident()?;
let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
@ -1397,6 +1398,7 @@ impl<'a> Parser<'a> {
let vr = ast::Variant {
ident,
vis,
id: DUMMY_NODE_ID,
attrs: variant_attrs,
data: struct_def,
@ -1550,7 +1552,7 @@ impl<'a> Parser<'a> {
self.parse_paren_comma_seq(|p| {
let attrs = p.parse_outer_attributes()?;
let lo = p.token.span;
let vis = p.parse_visibility(true)?;
let vis = p.parse_visibility(FollowedByType::Yes)?;
let ty = p.parse_ty()?;
Ok(StructField {
span: lo.to(ty.span),
@ -1568,7 +1570,7 @@ impl<'a> Parser<'a> {
fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
let attrs = self.parse_outer_attributes()?;
let lo = self.token.span;
let vis = self.parse_visibility(false)?;
let vis = self.parse_visibility(FollowedByType::No)?;
self.parse_single_struct_field(lo, vis, attrs)
}

View File

@ -346,6 +346,8 @@ impl SeqSep {
}
}
pub enum FollowedByType { Yes, No }
impl<'a> Parser<'a> {
pub fn new(
sess: &'a ParseSess,
@ -1116,7 +1118,7 @@ impl<'a> Parser<'a> {
/// If the following element can't be a tuple (i.e., it's a function definition), then
/// it's not a tuple struct field), and the contents within the parentheses isn't valid,
/// so emit a proper diagnostic.
pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> {
pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
maybe_whole!(self, NtVis, |x| x);
self.expected_tokens.push(TokenType::Keyword(kw::Crate));
@ -1171,7 +1173,9 @@ impl<'a> Parser<'a> {
id: ast::DUMMY_NODE_ID,
};
return Ok(respan(lo.to(self.prev_span), vis));
} else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct.
} else if let FollowedByType::No = fbt {
// Provide this diagnostic if a type cannot follow;
// in particular, if this is not a tuple struct.
self.recover_incorrect_vis_restriction()?;
// Emit diagnostic, but continue with public visibility.
}

View File

@ -524,6 +524,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
ItemKind::Enum(ref def, _) => {
for variant in &def.variants {
self.invalid_visibility(&variant.vis, None);
for field in variant.data.fields() {
self.invalid_visibility(&field.vis, None);
}
@ -754,6 +755,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
visit::walk_impl_item(self, ii);
}
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
self.invalid_visibility(&ti.vis, None);
visit::walk_trait_item(self, ti);
}
}
pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {

View File

@ -961,12 +961,12 @@ pub struct Arm {
/// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Field {
pub ident: Ident,
pub expr: P<Expr>,
pub span: Span,
pub is_shorthand: bool,
pub attrs: ThinVec<Attribute>,
pub id: NodeId,
pub span: Span,
pub ident: Ident,
pub expr: P<Expr>,
pub is_shorthand: bool,
pub is_placeholder: bool,
}
@ -1515,12 +1515,14 @@ pub struct FnSig {
/// signature) or provided (meaning it has a default implementation).
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct TraitItem {
pub id: NodeId,
pub ident: Ident,
pub attrs: Vec<Attribute>,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub ident: Ident,
pub generics: Generics,
pub kind: TraitItemKind,
pub span: Span,
/// See `Item::tokens` for what this is.
pub tokens: Option<TokenStream>,
}
@ -1536,14 +1538,15 @@ pub enum TraitItemKind {
/// Represents anything within an `impl` block.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ImplItem {
pub id: NodeId,
pub ident: Ident,
pub vis: Visibility,
pub defaultness: Defaultness,
pub attrs: Vec<Attribute>,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub ident: Ident,
pub defaultness: Defaultness,
pub generics: Generics,
pub kind: ImplItemKind,
pub span: Span,
/// See `Item::tokens` for what this is.
pub tokens: Option<TokenStream>,
}
@ -2101,22 +2104,24 @@ pub struct GlobalAsm {
pub struct EnumDef {
pub variants: Vec<Variant>,
}
/// Enum variant.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Variant {
/// Name of the variant.
pub ident: Ident,
/// Attributes of the variant.
pub attrs: Vec<Attribute>,
/// Id of the variant (not the constructor, see `VariantData::ctor_id()`).
pub id: NodeId,
/// Span
pub span: Span,
/// The visibility of the variant. Syntactically accepted but not semantically.
pub vis: Visibility,
/// Name of the variant.
pub ident: Ident,
/// Fields and constructor id of the variant.
pub data: VariantData,
/// Explicit discriminant, e.g., `Foo = 1`.
pub disr_expr: Option<AnonConst>,
/// Span
pub span: Span,
/// Is a macro placeholder
pub is_placeholder: bool,
}
@ -2295,12 +2300,13 @@ impl VisibilityKind {
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct StructField {
pub span: Span,
pub ident: Option<Ident>,
pub vis: Visibility,
pub id: NodeId,
pub ty: P<Ty>,
pub attrs: Vec<Attribute>,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub ident: Option<Ident>,
pub ty: P<Ty>,
pub is_placeholder: bool,
}
@ -2344,12 +2350,13 @@ impl VariantData {
/// The name might be a dummy name in case of anonymous items.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Item {
pub ident: Ident,
pub attrs: Vec<Attribute>,
pub id: NodeId,
pub kind: ItemKind,
pub vis: Visibility,
pub span: Span,
pub vis: Visibility,
pub ident: Ident,
pub kind: ItemKind,
/// Original tokens this item was parsed from. This isn't necessarily
/// available for all items, although over time more and more items should
@ -2518,12 +2525,13 @@ impl ItemKind {
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ForeignItem {
pub ident: Ident,
pub attrs: Vec<Attribute>,
pub kind: ForeignItemKind,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub ident: Ident,
pub kind: ForeignItemKind,
}
/// An item within an `extern` block.

View File

@ -472,16 +472,17 @@ pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis:
items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
}
pub fn noop_flat_map_variant<T: MutVisitor>(mut variant: Variant, vis: &mut T)
pub fn noop_flat_map_variant<T: MutVisitor>(mut variant: Variant, visitor: &mut T)
-> SmallVec<[Variant; 1]>
{
let Variant { ident, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
vis.visit_ident(ident);
visit_attrs(attrs, vis);
vis.visit_id(id);
vis.visit_variant_data(data);
visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr));
vis.visit_span(span);
let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
visitor.visit_ident(ident);
visitor.visit_vis(vis);
visit_attrs(attrs, visitor);
visitor.visit_id(id);
visitor.visit_variant_data(data);
visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
visitor.visit_span(span);
smallvec![variant]
}
@ -920,32 +921,33 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
}
}
pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, vis: &mut T)
pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, visitor: &mut T)
-> SmallVec<[TraitItem; 1]>
{
let TraitItem { id, ident, attrs, generics, kind, span, tokens: _ } = &mut item;
vis.visit_id(id);
vis.visit_ident(ident);
visit_attrs(attrs, vis);
vis.visit_generics(generics);
let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item;
visitor.visit_id(id);
visitor.visit_ident(ident);
visitor.visit_vis(vis);
visit_attrs(attrs, visitor);
visitor.visit_generics(generics);
match kind {
TraitItemKind::Const(ty, default) => {
vis.visit_ty(ty);
visit_opt(default, |default| vis.visit_expr(default));
visitor.visit_ty(ty);
visit_opt(default, |default| visitor.visit_expr(default));
}
TraitItemKind::Method(sig, body) => {
visit_fn_sig(sig, vis);
visit_opt(body, |body| vis.visit_block(body));
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
TraitItemKind::Type(bounds, default) => {
visit_bounds(bounds, vis);
visit_opt(default, |default| vis.visit_ty(default));
visit_bounds(bounds, visitor);
visit_opt(default, |default| visitor.visit_ty(default));
}
TraitItemKind::Macro(mac) => {
vis.visit_mac(mac);
visitor.visit_mac(mac);
}
}
vis.visit_span(span);
visitor.visit_span(span);
smallvec![item]
}

View File

@ -50,6 +50,7 @@ fn test_variant_to_string() {
let var = ast::Variant {
ident,
vis: source_map::respan(syntax_pos::DUMMY_SP, ast::VisibilityKind::Inherited),
attrs: Vec::new(),
id: ast::DUMMY_NODE_ID,
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),

View File

@ -314,6 +314,7 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant)
where V: Visitor<'a>,
{
visitor.visit_ident(variant.ident);
visitor.visit_vis(&variant.vis);
visitor.visit_variant_data(&variant.data);
walk_list!(visitor, visit_anon_const, &variant.disr_expr);
walk_list!(visitor, visit_attribute, &variant.attrs);
@ -585,6 +586,7 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl
}
pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) {
visitor.visit_vis(&trait_item.vis);
visitor.visit_ident(trait_item.ident);
walk_list!(visitor, visit_attribute, &trait_item.attrs);
visitor.visit_generics(&trait_item.generics);

View File

@ -582,12 +582,13 @@ impl<'a> ExtCtxt<'a> {
}
pub fn variant(&self, span: Span, ident: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant {
let vis_span = span.shrink_to_lo();
let fields: Vec<_> = tys.into_iter().map(|ty| {
ast::StructField {
span: ty.span,
ty,
ident: None,
vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
vis: respan(vis_span, ast::VisibilityKind::Inherited),
attrs: Vec::new(),
id: ast::DUMMY_NODE_ID,
is_placeholder: false,
@ -606,6 +607,7 @@ impl<'a> ExtCtxt<'a> {
disr_expr: None,
id: ast::DUMMY_NODE_ID,
ident,
vis: respan(vis_span, ast::VisibilityKind::Inherited),
span,
is_placeholder: false,
}

View File

@ -77,7 +77,7 @@ use TokenTreeOrTokenTreeSlice::*;
use crate::mbe::{self, TokenTree};
use rustc_parse::Directory;
use rustc_parse::parser::{Parser, PathStyle};
use rustc_parse::parser::{Parser, PathStyle, FollowedByType};
use syntax::ast::{Ident, Name};
use syntax::print::pprust;
use syntax::sess::ParseSess;
@ -933,7 +933,7 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a,
}
sym::path => token::NtPath(p.parse_path(PathStyle::Type)?),
sym::meta => token::NtMeta(p.parse_attr_item()?),
sym::vis => token::NtVis(p.parse_visibility(true)?),
sym::vis => token::NtVis(p.parse_visibility(FollowedByType::Yes)?),
sym::lifetime => if p.check_lifetime() {
token::NtLifetime(p.expect_lifetime().ident)
} else {

View File

@ -53,7 +53,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
tokens: None,
})]),
AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
id, span, ident, attrs, generics,
id, span, ident, vis, attrs, generics,
kind: ast::TraitItemKind::Macro(mac_placeholder()),
tokens: None,
}]),
@ -150,6 +150,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
id,
ident,
span,
vis,
is_placeholder: true,
}
])

View File

@ -1 +1 @@
{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}}
{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}}

View File

@ -1,14 +1,15 @@
error: unnecessary visibility qualifier
error[E0449]: unnecessary visibility qualifier
--> $DIR/issue-28433.rs:2:5
|
LL | pub Duck,
| ^^^ `pub` not permitted here
| ^^^ `pub` not permitted here because it's implied
error: unnecessary visibility qualifier
error[E0449]: unnecessary visibility qualifier
--> $DIR/issue-28433.rs:5:5
|
LL | pub(crate) Dove
| ^^^^^^^^^^ `pub` not permitted here
| ^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0449`.

View File

@ -4,7 +4,7 @@ trait T {
fn qux() -> Option<usize> {
let _ = if true {
});
//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
//~^ ERROR expected one of `async`
//~| ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
//~| ERROR expected identifier, found `;`
Some(4)

View File

@ -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`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;`
--> $DIR/issue-60075.rs:6:11
|
LL | fn qux() -> Option<usize> {

View File

@ -1,8 +1,8 @@
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `...`
error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...`
--> $DIR/issue-32446.rs:4:11
|
LL | trait T { ... }
| ^^^ expected one of 7 possible tokens
| ^^^ expected one of 9 possible tokens
error: aborting due to previous error

View File

@ -0,0 +1,28 @@
// check-pass
// Here we check that a `:vis` macro matcher subsititued for the empty visibility
// (`VisibilityKind::Inherited`) is accepted when used before an enum variant.
fn main() {}
macro_rules! mac_variant {
($vis:vis MARKER) => {
enum Enum {
$vis Unit,
$vis Tuple(u8, u16),
$vis Struct { f: u8 },
}
}
}
mac_variant!(MARKER);
// We also accept visibilities on variants syntactically but not semantically.
#[cfg(FALSE)]
enum E {
pub U,
pub(crate) T(u8),
pub(super) T { f: String }
}

View File

@ -0,0 +1,28 @@
// check-pass
// Here we check that a `:vis` macro matcher subsititued for the empty visibility
// (`VisibilityKind::Inherited`) is accepted when used before an item in a trait.
fn main() {}
macro_rules! mac_in_trait {
($vis:vis MARKER) => {
$vis fn beta() {}
$vis const GAMMA: u8;
$vis type Delta;
}
}
trait Alpha {
mac_in_trait!(MARKER);
}
// We also accept visibilities on items in traits syntactically but not semantically.
#[cfg(FALSE)]
trait Foo {
pub fn bar();
pub(crate) type baz;
pub(super) const QUUX: u8;
}

View File

@ -1,6 +1,6 @@
macro_rules! bah {
($a:expr) => ($a)
//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found `2`
//~^ ERROR expected one of `async`
}
trait bar {

View File

@ -1,8 +1,8 @@
error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found `2`
error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2`
--> $DIR/trait-non-item-macros.rs:2:19
|
LL | ($a:expr) => ($a)
| ^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`
| ^^ expected one of 8 possible tokens
...
LL | bah!(2);
| -------- in this macro invocation

View File

@ -1,7 +1,9 @@
trait T {
//~^ ERROR `main` function not found in crate `missing_close_brace_in_trait`
fn foo(&self);
pub(crate) struct Bar<T>(); //~ ERROR expected one of
pub(crate) struct Bar<T>();
//~^ ERROR expected one of
impl T for Bar<usize> {
fn foo(&self) {}

View File

@ -1,5 +1,5 @@
error: this file contains an un-closed delimiter
--> $DIR/missing-close-brace-in-trait.rs:10:66
--> $DIR/missing-close-brace-in-trait.rs:12:66
|
LL | trait T {
| - un-closed delimiter
@ -7,19 +7,24 @@ LL | trait T {
LL | fn main() {}
| ^
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found keyword `pub`
--> $DIR/missing-close-brace-in-trait.rs:4:1
error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct`
--> $DIR/missing-close-brace-in-trait.rs:5:12
|
LL | trait T {
| - unclosed delimiter
LL | fn foo(&self);
| -
| |
| expected one of 7 possible tokens
| help: `}` may belong here
LL |
LL | pub(crate) struct Bar<T>();
| ^^^ unexpected token
| ^^^^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`
error: aborting due to 2 previous errors
error[E0601]: `main` function not found in crate `missing_close_brace_in_trait`
--> $DIR/missing-close-brace-in-trait.rs:1:1
|
LL | / trait T {
LL | |
LL | | fn foo(&self);
LL | |
... |
LL | |
LL | | fn main() {}
| |_________________________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-trait.rs`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0601`.

View File

@ -1,8 +1,9 @@
error: unnecessary visibility qualifier
error[E0449]: unnecessary visibility qualifier
--> $DIR/trait-pub-assoc-const.rs:2:5
|
LL | pub const Foo: u32;
| ^^^ `pub` not permitted here
| ^^^ `pub` not permitted here because it's implied
error: aborting due to previous error
For more information about this error, try `rustc --explain E0449`.

View File

@ -1,8 +1,9 @@
error: unnecessary visibility qualifier
error[E0449]: unnecessary visibility qualifier
--> $DIR/trait-pub-assoc-ty.rs:2:5
|
LL | pub type Foo;
| ^^^ `pub` not permitted here
| ^^^ `pub` not permitted here because it's implied
error: aborting due to previous error
For more information about this error, try `rustc --explain E0449`.

View File

@ -1,8 +1,9 @@
error: unnecessary visibility qualifier
error[E0449]: unnecessary visibility qualifier
--> $DIR/trait-pub-method.rs:2:5
|
LL | pub fn foo();
| ^^^ `pub` not permitted here
| ^^^ `pub` not permitted here because it's implied
error: aborting due to previous error
For more information about this error, try `rustc --explain E0449`.