syntax: add anonymized type syntax, i.e. impl TraitA+TraitB.

This commit is contained in:
Eduard Burtescu 2016-08-01 04:25:32 +03:00
parent c976e073fd
commit f0baec691f
13 changed files with 68 additions and 4 deletions

View File

@ -375,6 +375,9 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
TyPolyTraitRef(bounds) => {
TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
}
TyImplTrait(bounds) => {
TyImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
}
},
span: fld.new_span(span),
}

View File

@ -427,6 +427,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
TyPolyTraitRef(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyImplTrait(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyTypeof(ref expression) => {
visitor.visit_expr(expression)
}

View File

@ -293,8 +293,10 @@ impl<'a> LoweringContext<'a> {
hir::TyTypeof(self.lower_expr(expr))
}
PolyTraitRef(ref bounds) => {
let bounds = bounds.iter().map(|b| self.lower_ty_param_bound(b)).collect();
hir::TyPolyTraitRef(bounds)
hir::TyPolyTraitRef(self.lower_bounds(bounds))
}
ImplTrait(ref bounds) => {
hir::TyImplTrait(self.lower_bounds(bounds))
}
Mac(_) => panic!("TyMac should have been expanded by now."),
},

View File

@ -1132,6 +1132,8 @@ pub enum Ty_ {
TyObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`
TyPolyTraitRef(TyParamBounds),
/// An `impl TraitA+TraitB` type.
TyImplTrait(TyParamBounds),
/// Unused for now
TyTypeof(P<Expr>),
/// TyInfer means the type should be inferred instead of it having been

View File

@ -536,6 +536,9 @@ impl<'a> State<'a> {
hir::TyPolyTraitRef(ref bounds) => {
self.print_bounds("", &bounds[..])?;
}
hir::TyImplTrait(ref bounds) => {
self.print_bounds("impl ", &bounds[..])?;
}
hir::TyFixedLengthVec(ref ty, ref v) => {
word(&mut self.s, "[")?;
self.print_type(&ty)?;

View File

@ -1492,6 +1492,9 @@ pub enum Type {
// for<'a> Foo(&'a)
PolyTraitRef(Vec<TyParamBound>),
// impl TraitA+TraitB
ImplTrait(Vec<TyParamBound>),
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
@ -1777,6 +1780,7 @@ impl Clean<Type> for hir::Ty {
}
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyPolyTraitRef(ref bounds) => PolyTraitRef(bounds.clean(cx)),
TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
TyInfer => Infer,
TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
}

View File

@ -539,6 +539,16 @@ impl fmt::Display for clean::Type {
}
Ok(())
}
clean::ImplTrait(ref bounds) => {
write!(f, "impl ")?;
for (i, bound) in bounds.iter().enumerate() {
if i != 0 {
write!(f, " + ")?;
}
write!(f, "{}", *bound)?;
}
Ok(())
}
// It's pretty unsightly to look at `<A as B>::C` in output, and
// we've got hyperlinking on our side, so try to avoid longer
// notation as much as possible by making `C` a hyperlink to trait

View File

@ -1368,6 +1368,8 @@ pub enum TyKind {
ObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`
PolyTraitRef(TyParamBounds),
/// An `impl TraitA+TraitB` type.
ImplTrait(TyParamBounds),
/// No-op; kept solely so that we can pretty-print faithfully
Paren(P<Ty>),
/// Unused for now

View File

@ -277,7 +277,10 @@ declare_features! (
(active, cfg_target_has_atomic, "1.9.0", Some(32976)),
// Allows `..` in tuple (struct) patterns
(active, dotdot_in_tuple_patterns, "1.10.0", Some(33627))
(active, dotdot_in_tuple_patterns, "1.10.0", Some(33627)),
// Allows `impl Trait` in function return types.
(active, conservative_impl_trait, "1.12.0", Some(34511))
);
declare_features! (
@ -952,6 +955,10 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
ast::TyKind::BareFn(ref bare_fn_ty) => {
self.check_abi(bare_fn_ty.abi, ty.span);
}
ast::TyKind::ImplTrait(..) => {
gate_feature_post!(&self, conservative_impl_trait, ty.span,
"`impl Trait` is experimental");
}
_ => {}
}
visit::walk_ty(self, ty)

View File

@ -397,6 +397,9 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
TyKind::PolyTraitRef(bounds) => {
TyKind::PolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
}
TyKind::ImplTrait(bounds) => {
TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
}
TyKind::Mac(mac) => {
TyKind::Mac(fld.fold_mac(mac))
}

View File

@ -1051,7 +1051,7 @@ impl<'a> Parser<'a> {
pub fn parse_for_in_type(&mut self) -> PResult<'a, TyKind> {
/*
Parses whatever can come after a `for` keyword in a type.
The `for` has already been consumed.
The `for` hasn't been consumed.
Deprecated:
@ -1091,6 +1091,23 @@ impl<'a> Parser<'a> {
}
}
pub fn parse_impl_trait_type(&mut self) -> PResult<'a, TyKind> {
/*
Parses whatever can come after a `impl` keyword in a type.
The `impl` has already been consumed.
*/
let bounds = self.parse_ty_param_bounds(BoundParsingMode::Modified)?;
if !bounds.iter().any(|b| if let TraitTyParamBound(..) = *b { true } else { false }) {
let last_span = self.last_span;
self.span_err(last_span, "at least one trait must be specified");
}
Ok(ast::TyKind::ImplTrait(bounds))
}
pub fn parse_ty_path(&mut self) -> PResult<'a, TyKind> {
Ok(TyKind::Path(None, self.parse_path(PathStyle::Type)?))
}
@ -1406,6 +1423,8 @@ impl<'a> Parser<'a> {
self.parse_borrowed_pointee()?
} else if self.check_keyword(keywords::For) {
self.parse_for_in_type()?
} else if self.eat_keyword(keywords::Impl) {
self.parse_impl_trait_type()?
} else if self.token_is_bare_fn_keyword() {
// BARE FUNCTION
self.parse_ty_bare_fn(Vec::new())?

View File

@ -1018,6 +1018,9 @@ impl<'a> State<'a> {
ast::TyKind::PolyTraitRef(ref bounds) => {
try!(self.print_bounds("", &bounds[..]));
}
ast::TyKind::ImplTrait(ref bounds) => {
try!(self.print_bounds("impl ", &bounds[..]));
}
ast::TyKind::FixedLengthVec(ref ty, ref v) => {
try!(word(&mut self.s, "["));
try!(self.print_type(&ty));

View File

@ -343,6 +343,9 @@ pub fn walk_ty<V: Visitor>(visitor: &mut V, typ: &Ty) {
TyKind::PolyTraitRef(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyKind::ImplTrait(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyKind::Typeof(ref expression) => {
visitor.visit_expr(expression)
}