add auto
keyword, parse auto trait
, lower to HIR
Adds an `IsAuto` field to `ItemTrait` which flags if the trait was declared as an `auto trait`. Auto traits cannot have generics nor super traits.
This commit is contained in:
parent
06506bb751
commit
1f4b630899
@ -520,7 +520,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
||||
visitor.visit_id(item.id);
|
||||
visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
|
||||
}
|
||||
ItemTrait(_, ref generics, ref bounds, ref trait_item_refs) => {
|
||||
ItemTrait(.., ref generics, ref bounds, ref trait_item_refs) => {
|
||||
visitor.visit_id(item.id);
|
||||
visitor.visit_generics(generics);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
|
@ -198,7 +198,7 @@ impl<'a> LoweringContext<'a> {
|
||||
ItemKind::Union(_, ref generics) |
|
||||
ItemKind::Enum(_, ref generics) |
|
||||
ItemKind::Ty(_, ref generics) |
|
||||
ItemKind::Trait(_, ref generics, ..) => {
|
||||
ItemKind::Trait(_, _, ref generics, ..) => {
|
||||
let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
|
||||
let count = generics.lifetimes.len();
|
||||
self.lctx.type_def_lifetime_params.insert(def_id, count);
|
||||
@ -1515,10 +1515,11 @@ impl<'a> LoweringContext<'a> {
|
||||
self.lower_ty(ty),
|
||||
new_impl_items)
|
||||
}
|
||||
ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
|
||||
ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
|
||||
let bounds = self.lower_bounds(bounds);
|
||||
let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
|
||||
hir::ItemTrait(self.lower_unsafety(unsafety),
|
||||
hir::ItemTrait(self.lower_is_auto(is_auto),
|
||||
self.lower_unsafety(unsafety),
|
||||
self.lower_generics(generics),
|
||||
bounds,
|
||||
items)
|
||||
@ -1741,6 +1742,13 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_is_auto(&mut self, u: IsAuto) -> hir::IsAuto {
|
||||
match u {
|
||||
IsAuto::Yes => hir::IsAuto::Yes,
|
||||
IsAuto::No => hir::IsAuto::No,
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
|
||||
match u {
|
||||
Unsafety::Unsafe => hir::Unsafety::Unsafe,
|
||||
|
@ -1500,6 +1500,13 @@ pub struct FnDecl {
|
||||
pub has_implicit_self: bool,
|
||||
}
|
||||
|
||||
/// Is the trait definition an auto trait?
|
||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum IsAuto {
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum Unsafety {
|
||||
Unsafe,
|
||||
@ -1811,7 +1818,7 @@ pub enum Item_ {
|
||||
/// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
|
||||
ItemUnion(VariantData, Generics),
|
||||
/// Represents a Trait Declaration
|
||||
ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
|
||||
ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
|
||||
|
||||
/// Auto trait implementations
|
||||
///
|
||||
|
@ -717,9 +717,10 @@ impl<'a> State<'a> {
|
||||
}
|
||||
self.bclose(item.span)?;
|
||||
}
|
||||
hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => {
|
||||
hir::ItemTrait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
|
||||
self.head("")?;
|
||||
self.print_visibility(&item.vis)?;
|
||||
self.print_is_auto(is_auto)?;
|
||||
self.print_unsafety(unsafety)?;
|
||||
self.word_nbsp("trait")?;
|
||||
self.print_name(item.name)?;
|
||||
@ -2274,6 +2275,13 @@ impl<'a> State<'a> {
|
||||
hir::Unsafety::Unsafe => self.word_nbsp("unsafe"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_is_auto(&mut self, s: hir::IsAuto) -> io::Result<()> {
|
||||
match s {
|
||||
hir::IsAuto::Yes => self.word_nbsp("auto"),
|
||||
hir::IsAuto::No => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dup'ed from parse::classify, but adapted for the HIR.
|
||||
|
@ -944,7 +944,7 @@ impl_stable_hash_for!(enum hir::Item_ {
|
||||
ItemEnum(enum_def, generics),
|
||||
ItemStruct(variant_data, generics),
|
||||
ItemUnion(variant_data, generics),
|
||||
ItemTrait(unsafety, generics, bounds, item_refs),
|
||||
ItemTrait(is_auto, unsafety, generics, bounds, item_refs),
|
||||
ItemAutoImpl(unsafety, trait_ref),
|
||||
ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
|
||||
});
|
||||
@ -1126,6 +1126,10 @@ impl_stable_hash_for!(enum hir::Mutability {
|
||||
MutImmutable
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum hir::IsAuto {
|
||||
Yes,
|
||||
No
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum hir::Unsafety {
|
||||
Unsafe,
|
||||
|
@ -332,7 +332,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
hir::ItemEnum(_, ref generics) |
|
||||
hir::ItemStruct(_, ref generics) |
|
||||
hir::ItemUnion(_, ref generics) |
|
||||
hir::ItemTrait(_, ref generics, ..) |
|
||||
hir::ItemTrait(_, _, ref generics, ..) |
|
||||
hir::ItemImpl(_, _, _, ref generics, ..) => {
|
||||
// These kinds of items have only early bound lifetime parameters.
|
||||
let mut index = if let hir::ItemTrait(..) = item.node {
|
||||
@ -688,7 +688,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
|
||||
hir::ItemUnion(_, ref generics) |
|
||||
hir::ItemEnum(_, ref generics) |
|
||||
hir::ItemTy(_, ref generics) |
|
||||
hir::ItemTrait(_, ref generics, ..) => {
|
||||
hir::ItemTrait(_, _, ref generics, ..) => {
|
||||
let result = object_lifetime_defaults_for_item(hir_map, generics);
|
||||
|
||||
// Debugging aid.
|
||||
@ -844,7 +844,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
index += 1; // Self comes first.
|
||||
}
|
||||
match parent.node {
|
||||
hir::ItemTrait(_, ref generics, ..) |
|
||||
hir::ItemTrait(_, _, ref generics, ..) |
|
||||
hir::ItemImpl(_, _, _, ref generics, ..) => {
|
||||
index += (generics.lifetimes.len() + generics.ty_params.len()) as u32;
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
|
||||
|
||||
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
||||
match it.node {
|
||||
hir::ItemTrait(hir::Unsafety::Unsafe, ..) => {
|
||||
hir::ItemTrait(_, hir::Unsafety::Unsafe, ..) => {
|
||||
self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait")
|
||||
}
|
||||
|
||||
|
@ -1854,7 +1854,7 @@ impl<'a> Resolver<'a> {
|
||||
item.id,
|
||||
impl_items),
|
||||
|
||||
ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
|
||||
ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
|
||||
// Create a new rib for the trait-wide type parameters.
|
||||
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
|
||||
let local_def_id = this.definitions.local_def_id(item.id);
|
||||
|
@ -1232,7 +1232,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
|
||||
ref impl_items) => {
|
||||
self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
|
||||
}
|
||||
Trait(_, ref generics, ref trait_refs, ref methods) =>
|
||||
Trait(_, _, ref generics, ref trait_refs, ref methods) =>
|
||||
self.process_trait(item, generics, trait_refs, methods),
|
||||
Mod(ref m) => {
|
||||
self.process_mod(item);
|
||||
|
@ -477,8 +477,13 @@ impl Sig for ast::Item {
|
||||
sig.text.push_str(" {}");
|
||||
Ok(sig)
|
||||
}
|
||||
ast::ItemKind::Trait(unsafety, ref generics, ref bounds, _) => {
|
||||
ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, _) => {
|
||||
let mut text = String::new();
|
||||
|
||||
if is_auto == ast::IsAuto::Yes {
|
||||
text.push_str("auto ");
|
||||
}
|
||||
|
||||
if unsafety == ast::Unsafety::Unsafe {
|
||||
text.push_str("unsafe ");
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ItemEnum(_, ref generics) |
|
||||
ItemStruct(_, ref generics) |
|
||||
ItemUnion(_, ref generics) => generics,
|
||||
ItemTrait(_, ref generics, ..) => {
|
||||
ItemTrait(_, _, ref generics, ..) => {
|
||||
// Implied `Self: Trait` and supertrait bounds.
|
||||
if param_id == item_node_id {
|
||||
result.predicates.push(ty::TraitRef {
|
||||
@ -670,7 +670,7 @@ fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
};
|
||||
|
||||
let (generics, bounds) = match item.node {
|
||||
hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
|
||||
hir::ItemTrait(.., ref generics, ref supertraits, _) => (generics, supertraits),
|
||||
_ => span_bug!(item.span,
|
||||
"super_predicates invoked on non-trait"),
|
||||
};
|
||||
@ -713,7 +713,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let item = tcx.hir.expect_item(node_id);
|
||||
|
||||
let unsafety = match item.node {
|
||||
hir::ItemTrait(unsafety, ..) => unsafety,
|
||||
hir::ItemTrait(_, unsafety, ..) => unsafety,
|
||||
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
|
||||
};
|
||||
|
||||
@ -888,7 +888,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
generics
|
||||
}
|
||||
|
||||
ItemTrait(_, ref generics, ..) => {
|
||||
ItemTrait(_, _, ref generics, ..) => {
|
||||
// Add in the self type parameter.
|
||||
//
|
||||
// Something of a hack: use the node id for the trait, also as
|
||||
@ -1350,7 +1350,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
generics
|
||||
}
|
||||
|
||||
ItemTrait(_, ref generics, .., ref items) => {
|
||||
ItemTrait(_, _, ref generics, .., ref items) => {
|
||||
is_trait = Some((ty::TraitRef {
|
||||
def_id,
|
||||
substs: Substs::identity_for_item(tcx, def_id)
|
||||
|
@ -1581,6 +1581,13 @@ impl FnDecl {
|
||||
}
|
||||
}
|
||||
|
||||
/// Is the trait definition an auto trait?
|
||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum IsAuto {
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum Unsafety {
|
||||
Unsafe,
|
||||
@ -1942,8 +1949,8 @@ pub enum ItemKind {
|
||||
Union(VariantData, Generics),
|
||||
/// A Trait declaration (`trait` or `pub trait`).
|
||||
///
|
||||
/// E.g. `trait Foo { .. }` or `trait Foo<T> { .. }`
|
||||
Trait(Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
|
||||
/// E.g. `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`
|
||||
Trait(IsAuto, Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
|
||||
/// Auto trait implementation.
|
||||
///
|
||||
/// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
|
||||
|
@ -926,7 +926,8 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
|
||||
folder.fold_ty(ty),
|
||||
impl_items.move_flat_map(|item| folder.fold_impl_item(item)),
|
||||
),
|
||||
ItemKind::Trait(unsafety, generics, bounds, items) => ItemKind::Trait(
|
||||
ItemKind::Trait(is_auto, unsafety, generics, bounds, items) => ItemKind::Trait(
|
||||
is_auto,
|
||||
unsafety,
|
||||
folder.fold_generics(generics),
|
||||
folder.fold_bounds(bounds),
|
||||
|
@ -16,12 +16,13 @@ use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind};
|
||||
use ast::Block;
|
||||
use ast::{BlockCheckMode, CaptureBy};
|
||||
use ast::{Constness, Crate};
|
||||
use ast::Generics;
|
||||
use ast::Defaultness;
|
||||
use ast::EnumDef;
|
||||
use ast::{Expr, ExprKind, RangeLimits};
|
||||
use ast::{Field, FnDecl};
|
||||
use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
|
||||
use ast::{Ident, ImplItem, Item, ItemKind};
|
||||
use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
|
||||
use ast::{Lifetime, LifetimeDef, Lit, LitKind, UintTy};
|
||||
use ast::Local;
|
||||
use ast::MacStmtStyle;
|
||||
@ -5078,7 +5079,17 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok((ident, ItemKind::Trait(unsafety, tps, bounds, trait_items), None))
|
||||
Ok((ident, ItemKind::Trait(IsAuto::No, unsafety, tps, bounds, trait_items), None))
|
||||
}
|
||||
|
||||
fn parse_item_auto_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
|
||||
let ident = self.parse_ident()?;
|
||||
self.expect(&token::OpenDelim(token::Brace))?;
|
||||
self.expect(&token::CloseDelim(token::Brace))?;
|
||||
// Auto traits cannot have generics, super traits nor contain items.
|
||||
Ok((ident,
|
||||
ItemKind::Trait(IsAuto::Yes, unsafety, Generics::default(), Vec::new(), Vec::new()),
|
||||
None))
|
||||
}
|
||||
|
||||
/// Parses items implementations variants
|
||||
@ -6127,6 +6138,37 @@ impl<'a> Parser<'a> {
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(Some(item));
|
||||
}
|
||||
if self.eat_keyword(keywords::Auto) {
|
||||
self.expect_keyword(keywords::Trait)?;
|
||||
// AUTO TRAIT ITEM
|
||||
let (ident,
|
||||
item_,
|
||||
extra_attrs) = self.parse_item_auto_trait(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::Unsafe) &&
|
||||
self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) {
|
||||
self.expect_keyword(keywords::Unsafe)?;
|
||||
self.expect_keyword(keywords::Auto)?;
|
||||
self.expect_keyword(keywords::Trait)?;
|
||||
// UNSAFE AUTO TRAIT ITEM
|
||||
let (ident,
|
||||
item_,
|
||||
extra_attrs) = self.parse_item_auto_trait(ast::Unsafety::Unsafe)?;
|
||||
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.eat_keyword(keywords::Struct) {
|
||||
// STRUCT ITEM
|
||||
let (ident, item_, extra_attrs) = self.parse_item_struct()?;
|
||||
|
@ -1338,9 +1338,10 @@ impl<'a> State<'a> {
|
||||
}
|
||||
self.bclose(item.span)?;
|
||||
}
|
||||
ast::ItemKind::Trait(unsafety, ref generics, ref bounds, ref trait_items) => {
|
||||
ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
|
||||
self.head("")?;
|
||||
self.print_visibility(&item.vis)?;
|
||||
self.print_is_auto(is_auto)?;
|
||||
self.print_unsafety(unsafety)?;
|
||||
self.word_nbsp("trait")?;
|
||||
self.print_ident(item.ident)?;
|
||||
@ -3123,6 +3124,13 @@ impl<'a> State<'a> {
|
||||
ast::Unsafety::Unsafe => self.word_nbsp("unsafe"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_is_auto(&mut self, s: ast::IsAuto) -> io::Result<()> {
|
||||
match s {
|
||||
ast::IsAuto::Yes => self.word_nbsp("auto"),
|
||||
ast::IsAuto::No => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() }
|
||||
|
@ -300,7 +300,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
||||
visitor.visit_variant_data(struct_definition, item.ident,
|
||||
generics, item.id, item.span);
|
||||
}
|
||||
ItemKind::Trait(_, ref generics, ref bounds, ref methods) => {
|
||||
ItemKind::Trait(.., ref generics, ref bounds, ref methods) => {
|
||||
visitor.visit_generics(generics);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_trait_item, methods);
|
||||
|
@ -309,11 +309,12 @@ declare_keywords! {
|
||||
(54, Yield, "yield")
|
||||
|
||||
// Weak keywords, have special meaning only in specific contexts.
|
||||
(55, Catch, "catch")
|
||||
(56, Default, "default")
|
||||
(57, Dyn, "dyn")
|
||||
(58, StaticLifetime, "'static")
|
||||
(59, Union, "union")
|
||||
(55, Auto, "auto")
|
||||
(56, Catch, "catch")
|
||||
(57, Default, "default")
|
||||
(58, Dyn, "dyn")
|
||||
(59, StaticLifetime, "'static")
|
||||
(60, Union, "union")
|
||||
}
|
||||
|
||||
// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
|
||||
|
Loading…
x
Reference in New Issue
Block a user