提交 1f4b6308 编写于 作者: L leonardo.yvens

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.
上级 06506bb7
......@@ -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 @@ fn visit_item(&mut self, item: &'lcx Item) {
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 @@ fn lower_item_kind(&mut self,
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 @@ fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
}
}
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 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
}
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 @@ pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> {
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 @@ fn hash_stable<W: StableHasherResult>(&self,
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 @@ fn hash_stable<W: StableHasherResult>(&self,
MutImmutable
});
impl_stable_hash_for!(enum hir::IsAuto {
Yes,
No
});
impl_stable_hash_for!(enum hir::Unsafety {
Unsafe,
......
......@@ -332,7 +332,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
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 @@ fn visit_early_late<F>(&mut self,
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 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
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 @@ fn resolve_item(&mut self, item: &Item) {
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 @@ fn visit_item(&mut self, item: &'l ast::Item) {
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 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
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 @@ pub fn has_self(&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,
......@@ -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::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 @@ fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
}
}
}
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 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
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 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
}
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 @@ pub fn print_unsafety(&mut self, s: ast::Unsafety) -> io::Result<()> {
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 @@ fn fresh() -> Self {
(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.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册