}
}
-type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
+type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>);
/// How to parse a path.
#[derive(Copy, Clone, PartialEq)]
};
}
-fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
- -> Vec<Attribute> {
- if let Some(ref attrs) = rhs {
- lhs.extend(attrs.iter().cloned())
+fn maybe_append(mut lhs: Vec<Attribute>, mut rhs: Option<Vec<Attribute>>) -> Vec<Attribute> {
+ if let Some(ref mut rhs) = rhs {
+ lhs.append(rhs);
}
lhs
}
Function Style
*/
- let unsafety = self.parse_unsafety()?;
+ let unsafety = self.parse_unsafety();
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi()?.unwrap_or(Abi::C)
} else {
})))
}
- pub fn parse_unsafety(&mut self) -> PResult<'a, Unsafety> {
+ /// Parse unsafety: `unsafe` or nothing.
+ fn parse_unsafety(&mut self) -> Unsafety {
if self.eat_keyword(keywords::Unsafe) {
- return Ok(Unsafety::Unsafe);
+ Unsafety::Unsafe
} else {
- return Ok(Unsafety::Normal);
+ Unsafety::Normal
}
}
self.look_ahead(2, |t| t.is_keyword(keywords::Trait)))
}
- fn is_defaultness(&self) -> bool {
- // `pub` is included for better error messages
- self.token.is_keyword(keywords::Default) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
- t.is_keyword(keywords::Const) ||
- t.is_keyword(keywords::Fn) ||
- t.is_keyword(keywords::Unsafe) ||
- t.is_keyword(keywords::Extern) ||
- t.is_keyword(keywords::Type) ||
- t.is_keyword(keywords::Pub))
- }
-
- fn eat_defaultness(&mut self) -> bool {
- let is_defaultness = self.is_defaultness();
- if is_defaultness {
- self.bump()
- } else {
- self.expected_tokens.push(TokenType::Keyword(keywords::Default));
- }
- is_defaultness
- }
-
fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
-> PResult<'a, Option<P<Item>>> {
let token_lo = self.span;
fn parse_item_fn(&mut self,
unsafety: Unsafety,
constness: Spanned<Constness>,
- abi: abi::Abi)
+ abi: Abi)
-> PResult<'a, ItemInfo> {
let (ident, mut generics) = self.parse_fn_header()?;
let decl = self.parse_fn_decl(false)?;
/// - `const unsafe fn`
/// - `extern fn`
/// - etc
- pub fn parse_fn_front_matter(&mut self)
- -> PResult<'a, (Spanned<ast::Constness>,
- ast::Unsafety,
- abi::Abi)> {
+ pub fn parse_fn_front_matter(&mut self) -> PResult<'a, (Spanned<Constness>, Unsafety, Abi)> {
let is_const_fn = self.eat_keyword(keywords::Const);
let const_span = self.prev_span;
- let unsafety = self.parse_unsafety()?;
+ let unsafety = self.parse_unsafety();
let (constness, unsafety, abi) = if is_const_fn {
(respan(const_span, Constness::Const), unsafety, Abi::Rust)
} else {
mut attrs: Vec<Attribute>) -> PResult<'a, ImplItem> {
let lo = self.span;
let vis = self.parse_visibility(false)?;
- let defaultness = self.parse_defaultness()?;
+ let defaultness = self.parse_defaultness();
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
// This parses the grammar:
// ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
/// Parse a method or a macro invocation in a trait impl.
fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
- -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::Generics,
+ -> PResult<'a, (Ident, Vec<Attribute>, ast::Generics,
ast::ImplItemKind)> {
// code copied from parse_macro_use_or_failure... abstraction!
if self.token.is_path_start() && !self.is_extern_non_path() {
}
}
- /// Parses items implementations variants
- /// impl<T> Foo { ... }
- /// impl<T> ToString for &'static T { ... }
- fn parse_item_impl(&mut self,
- unsafety: ast::Unsafety,
- defaultness: Defaultness) -> PResult<'a, ItemInfo> {
+ fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
+ self.expect(&token::OpenDelim(token::Brace))?;
+ let attrs = self.parse_inner_attributes()?;
- // First, parse type parameters if necessary.
- let mut generics = self.parse_generics()?;
+ let mut impl_items = Vec::new();
+ while !self.eat(&token::CloseDelim(token::Brace)) {
+ let mut at_end = false;
+ match self.parse_impl_item(&mut at_end) {
+ Ok(impl_item) => impl_items.push(impl_item),
+ Err(mut err) => {
+ err.emit();
+ if !at_end {
+ self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
+ }
+ }
+ }
+ }
+ Ok((impl_items, attrs))
+ }
- // Special case: if the next identifier that follows is '(', don't
- // allow this to be parsed as a trait.
- let could_be_trait = self.token != token::OpenDelim(token::Paren);
+ /// Parses an implementation item, `impl` keyword is already parsed.
+ /// impl<'a, T> TYPE { /* impl items */ }
+ /// impl<'a, T> TRAIT for TYPE { /* impl items */ }
+ /// impl<'a, T> !TRAIT for TYPE { /* impl items */ }
+ /// We actually parse slightly more relaxed grammar for better error reporting and recovery.
+ /// `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}`
+ /// `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}`
+ fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
+ -> PResult<'a, ItemInfo> {
+ // First, parse generic parameters if necessary.
+ // FIXME: Disambiguate generic parameters and qualified paths (`impl <A as B>::C {}`).
+ let mut generics = self.parse_generics()?;
- let neg_span = self.span;
- let polarity = if self.eat(&token::Not) {
+ // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
+ let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) {
+ self.bump(); // `!`
ast::ImplPolarity::Negative
} else {
ast::ImplPolarity::Positive
};
- // Parse the trait.
- let mut ty = self.parse_ty()?;
-
- // Parse traits, if necessary.
- let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
- // New-style trait. Reinterpret the type as a trait.
- match ty.node {
- TyKind::Path(None, ref path) => {
- Some(TraitRef {
- path: (*path).clone(),
- ref_id: ty.id,
- })
- }
- _ => {
- self.span_err(ty.span, "not a trait");
- None
- }
- }
+ // Parse both types and traits as a type, then reinterpret if necessary.
+ let ty_first = self.parse_ty()?;
+
+ // If `for` is missing we try to recover.
+ let has_for = self.eat_keyword(keywords::For);
+ let missing_for_span = self.prev_span.between(self.span);
+
+ let ty_second = if self.token == token::DotDot {
+ // We need to report this error after `cfg` expansion for compatibility reasons
+ self.bump(); // `..`, do not add it to expected tokens
+ Some(P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID }))
+ } else if has_for || self.token.can_begin_type() {
+ Some(self.parse_ty()?)
} else {
- if polarity == ast::ImplPolarity::Negative {
- // This is a negated type implementation
- // `impl !MyType {}`, which is not allowed.
- self.span_err(neg_span, "inherent implementation can't be negated");
- }
None
};
- if opt_trait.is_some() {
- ty = if self.eat(&token::DotDot) {
- P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID })
- } else {
- self.parse_ty()?
- }
- }
generics.where_clause = self.parse_where_clause()?;
- self.expect(&token::OpenDelim(token::Brace))?;
- let attrs = self.parse_inner_attributes()?;
+ let (impl_items, attrs) = self.parse_impl_body()?;
- let mut impl_items = vec![];
- while !self.eat(&token::CloseDelim(token::Brace)) {
- let mut at_end = false;
- match self.parse_impl_item(&mut at_end) {
- Ok(item) => impl_items.push(item),
- Err(mut e) => {
- e.emit();
- if !at_end {
- self.recover_stmt_(SemiColonMode::Break, BlockMode::Break);
- }
+ let item_kind = match ty_second {
+ Some(ty_second) => {
+ // impl Trait for Type
+ if !has_for {
+ self.span_err(missing_for_span, "missing `for` in a trait impl");
}
+
+ let ty_first = ty_first.into_inner();
+ let path = match ty_first.node {
+ // This notably includes paths passed through `ty` macro fragments (#46438).
+ TyKind::Path(None, path) => path,
+ _ => {
+ self.span_err(ty_first.span, "expected a trait, found type");
+ ast::Path::from_ident(ty_first.span, keywords::Invalid.ident())
+ }
+ };
+ let trait_ref = TraitRef { path, ref_id: ty_first.id };
+
+ ItemKind::Impl(unsafety, polarity, defaultness,
+ generics, Some(trait_ref), ty_second, impl_items)
}
- }
+ None => {
+ // impl Type
+ ItemKind::Impl(unsafety, polarity, defaultness,
+ generics, None, ty_first, impl_items)
+ }
+ };
- Ok((keywords::Invalid.ident(),
- ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items),
- Some(attrs)))
+ Ok((keywords::Invalid.ident(), item_kind, Some(attrs)))
}
fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
Ok(Visibility::Public)
}
- /// Parse defaultness: DEFAULT or nothing
- fn parse_defaultness(&mut self) -> PResult<'a, Defaultness> {
- if self.eat_defaultness() {
- Ok(Defaultness::Default)
+ /// Parse defaultness: `default` or nothing.
+ fn parse_defaultness(&mut self) -> Defaultness {
+ // `pub` is included for better error messages
+ if self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl) ||
+ t.is_keyword(keywords::Const) ||
+ t.is_keyword(keywords::Fn) ||
+ t.is_keyword(keywords::Unsafe) ||
+ t.is_keyword(keywords::Extern) ||
+ t.is_keyword(keywords::Type) ||
+ t.is_keyword(keywords::Pub)) {
+ self.bump(); // `default`
+ Defaultness::Default
} else {
- Ok(Defaultness::Final)
+ Defaultness::Final
}
}
let (module, mut attrs) =
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
if warn {
- let attr = ast::Attribute {
+ let attr = Attribute {
id: attr::mk_attr_id(),
style: ast::AttrStyle::Outer,
path: ast::Path::from_ident(syntax_pos::DUMMY_SP,
}
}
- pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> {
+ pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str()))
}
fn submod_path(&mut self,
id: ast::Ident,
- outer_attrs: &[ast::Attribute],
+ outer_attrs: &[Attribute],
id_sp: Span)
-> PResult<'a, ModulePathSuccess> {
if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
directory_ownership: DirectoryOwnership,
name: String,
id_sp: Span)
- -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
+ -> PResult<'a, (ast::ItemKind, Vec<Attribute> )> {
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
let mut err = String::from("circular modules: ");
/// extern {}
fn parse_item_foreign_mod(&mut self,
lo: Span,
- opt_abi: Option<abi::Abi>,
+ opt_abi: Option<Abi>,
visibility: Visibility,
mut attrs: Vec<Attribute>)
-> PResult<'a, P<Item>> {
/// Parses a string as an ABI spec on an extern type or module. Consumes
/// the `extern` keyword, if one is found.
- fn parse_opt_abi(&mut self) -> PResult<'a, Option<abi::Abi>> {
+ fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
match self.token {
token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
let sp = self.span;
|| (self.check_keyword(keywords::Unsafe)
&& self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
// CONST FUNCTION ITEM
- let unsafety = if self.eat_keyword(keywords::Unsafe) {
- Unsafety::Unsafe
- } else {
- Unsafety::Normal
- };
+ let unsafety = self.parse_unsafety();
self.bump();
let (ident, item_, extra_attrs) =
self.parse_item_fn(unsafety,
self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
{
// UNSAFE TRAIT ITEM
- self.expect_keyword(keywords::Unsafe)?;
+ self.bump(); // `unsafe`
let is_auto = if self.eat_keyword(keywords::Trait) {
IsAuto::No
} else {
IsAuto::Yes
};
let (ident, item_, extra_attrs) =
- self.parse_item_trait(is_auto, ast::Unsafety::Unsafe)?;
+ self.parse_item_trait(is_auto, Unsafety::Unsafe)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
- if (self.check_keyword(keywords::Unsafe) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
- (self.check_keyword(keywords::Default) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
- self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
- {
+ if self.check_keyword(keywords::Impl) ||
+ self.check_keyword(keywords::Unsafe) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
+ self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) ||
+ self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) {
// IMPL ITEM
- let defaultness = self.parse_defaultness()?;
- self.expect_keyword(keywords::Unsafe)?;
+ let defaultness = self.parse_defaultness();
+ let unsafety = self.parse_unsafety();
self.expect_keyword(keywords::Impl)?;
- let (ident,
- item_,
- extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe, defaultness)?;
- let prev_span = self.prev_span;
- let item = self.mk_item(lo.to(prev_span),
- ident,
- item_,
- visibility,
- maybe_append(attrs, extra_attrs));
- return Ok(Some(item));
+ let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?;
+ let span = lo.to(self.prev_span);
+ return Ok(Some(self.mk_item(span, ident, item, visibility,
+ maybe_append(attrs, extra_attrs))));
}
if self.check_keyword(keywords::Fn) {
// FUNCTION ITEM
if self.check_keyword(keywords::Unsafe)
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
// UNSAFE FUNCTION ITEM
- self.bump();
+ self.bump(); // `unsafe`
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi()?.unwrap_or(Abi::C)
} else {
};
// TRAIT ITEM
let (ident, item_, extra_attrs) =
- self.parse_item_trait(is_auto, ast::Unsafety::Normal)?;
- let prev_span = self.prev_span;
- let item = self.mk_item(lo.to(prev_span),
- ident,
- item_,
- visibility,
- maybe_append(attrs, extra_attrs));
- return Ok(Some(item));
- }
- if (self.check_keyword(keywords::Impl)) ||
- (self.check_keyword(keywords::Default) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl)))
- {
- // IMPL ITEM
- let defaultness = self.parse_defaultness()?;
- self.expect_keyword(keywords::Impl)?;
- let (ident,
- item_,
- extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal, defaultness)?;
+ self.parse_item_trait(is_auto, Unsafety::Normal)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,