E0166,
E0167,
E0168,
- E0169
+ E0169,
+ E0170,
+ E0171
)
// methods within to a new module, if the type was defined
// within this module.
- // Create the module and add all methods.
- match ty.node {
- TyPath(ref path, _, _) if path.segments.len() == 1 => {
+ let mod_name = match ty.node {
+ TyPath(ref path, _) if path.segments.len() == 1 => {
// FIXME(18446) we should distinguish between the name of
// a trait and the name of an impl of that trait.
- let mod_name = path.segments.last().unwrap().identifier.name;
+ Some(path.segments.last().unwrap().identifier.name)
+ }
+ TyObjectSum(ref lhs_ty, _) => {
+ match lhs_ty.node {
+ TyPath(ref path, _) if path.segments.len() == 1 => {
+ Some(path.segments.last().unwrap().identifier.name)
+ }
+ _ => {
+ None
+ }
+ }
+ }
+ _ => {
+ None
+ }
+ };
+ match mod_name {
+ None => {
+ self.resolve_error(ty.span,
+ "inherent implementations may \
+ only be implemented in the same \
+ module as the type they are \
+ implemented for")
+ }
+ Some(mod_name) => {
+ // Create the module and add all methods.
let parent_opt = parent.module().children.borrow()
- .get(&mod_name).cloned();
+ .get(&mod_name).cloned();
let new_parent = match parent_opt {
// It already exists
Some(ref child) if child.get_module_if_available()
- .is_some() &&
- (child.get_module().kind.get() == ImplModuleKind ||
- child.get_module().kind.get() == TraitModuleKind) => {
- ModuleReducedGraphParent(child.get_module())
- }
+ .is_some() &&
+ (child.get_module().kind.get() == ImplModuleKind ||
+ child.get_module().kind.get() == TraitModuleKind) => {
+ ModuleReducedGraphParent(child.get_module())
+ }
Some(ref child) if child.get_module_if_available()
- .is_some() &&
- child.get_module().kind.get() ==
- EnumModuleKind => {
- ModuleReducedGraphParent(child.get_module())
- }
+ .is_some() &&
+ child.get_module().kind.get() ==
+ EnumModuleKind => {
+ ModuleReducedGraphParent(child.get_module())
+ }
// Create the module
_ => {
let name_bindings =
let ns = TypeNS;
let is_public =
!name_bindings.defined_in_namespace(ns) ||
- name_bindings.defined_in_public_namespace(ns);
+ name_bindings.defined_in_public_namespace(ns);
name_bindings.define_module(parent_link,
Some(def_id),
ForbidDuplicateValues,
method.span);
let def = match method.pe_explicit_self()
- .node {
- SelfStatic => {
- // Static methods become
- // `DefStaticMethod`s.
- DefStaticMethod(local_def(method.id),
- FromImpl(local_def(item.id)))
- }
- _ => {
- // Non-static methods become
- // `DefMethod`s.
- DefMethod(local_def(method.id),
- None,
- FromImpl(local_def(item.id)))
- }
- };
+ .node {
+ SelfStatic => {
+ // Static methods become
+ // `DefStaticMethod`s.
+ DefStaticMethod(local_def(method.id),
+ FromImpl(local_def(item.id)))
+ }
+ _ => {
+ // Non-static methods become
+ // `DefMethod`s.
+ DefMethod(local_def(method.id),
+ None,
+ FromImpl(local_def(item.id)))
+ }
+ };
// NB: not IMPORTABLE
let modifiers = if method.pe_vis() == ast::Public {
ForbidDuplicateTypesAndModules,
typedef.span);
let def = DefAssociatedTy(local_def(
- typedef.id));
+ typedef.id));
// NB: not IMPORTABLE
let modifiers = if typedef.vis == ast::Public {
PUBLIC
}
}
}
- _ => {
- self.resolve_error(ty.span,
- "inherent implementations may \
- only be implemented in the same \
- module as the type they are \
- implemented for")
- }
}
parent
ShiftedRscope, BindingRscope};
use middle::typeck::rscope;
use middle::typeck::TypeAndSubsts;
+use util::common::ErrorReported;
use util::nodemap::DefIdMap;
-use util::ppaux::{Repr, UserString};
+use util::ppaux::{mod, Repr, UserString};
use std::rc::Rc;
use std::iter::AdditiveIterator;
pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
-> Option<Ty<'tcx>> {
match ast_ty.node {
- ast::TyPath(ref path, _, id) => {
+ ast::TyPath(ref path, id) => {
let a_def = match tcx.def_map.borrow().get(&id) {
None => {
tcx.sess.span_bug(ast_ty.span,
}
match ast_ty.node {
- ast::TyPath(ref path, _, id) => {
+ ast::TyPath(ref path, id) => {
let a_def = match this.tcx().def_map.borrow().get(&id) {
None => {
this.tcx()
}
}
-// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
-// If a_seq_ty is a str or a vec, make it a str/vec.
-// Also handle first-class trait types.
-fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
- this: &AC,
- rscope: &RS,
- a_seq_mutbl: ast::Mutability,
- a_seq_ty: &ast::Ty,
- region: ty::Region,
- constr: |Ty<'tcx>| -> Ty<'tcx>)
- -> Ty<'tcx>
+fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
+ rscope: &RS,
+ ty: &ast::Ty,
+ bounds: &[ast::TyParamBound])
+ -> Result<ty::TraitRef<'tcx>, ErrorReported>
+ where AC : AstConv<'tcx>, RS : RegionScope
{
- let tcx = this.tcx();
-
- debug!("mk_pointer(region={}, a_seq_ty={})",
- region,
- a_seq_ty.repr(tcx));
+ /*!
+ * In a type like `Foo + Send`, we want to wait to collect the
+ * full set of bounds before we make the object type, because we
+ * need them to infer a region bound. (For example, if we tried
+ * made a type from just `Foo`, then it wouldn't be enough to
+ * infer a 'static bound, and hence the user would get an error.)
+ * So this function is used when we're dealing with a sum type to
+ * convert the LHS. It only accepts a type that refers to a trait
+ * name, and reports an error otherwise.
+ */
- match a_seq_ty.node {
- ast::TyVec(ref ty) => {
- let ty = ast_ty_to_ty(this, rscope, &**ty);
- return constr(ty::mk_vec(tcx, ty, None));
+ match ty.node {
+ ast::TyPath(ref path, id) => {
+ match this.tcx().def_map.borrow().get(&id) {
+ Some(&def::DefTrait(trait_def_id)) => {
+ return Ok(ast_path_to_trait_ref(this,
+ rscope,
+ trait_def_id,
+ None,
+ path));
+ }
+ _ => {
+ span_err!(this.tcx().sess, ty.span, E0170, "expected a reference to a trait");
+ Err(ErrorReported)
+ }
+ }
}
- ast::TyPath(ref path, ref opt_bounds, id) => {
- // Note that the "bounds must be empty if path is not a trait"
- // restriction is enforced in the below case for ty_path, which
- // will run after this as long as the path isn't a trait.
- match tcx.def_map.borrow().get(&id) {
- Some(&def::DefPrimTy(ast::TyStr)) => {
- check_path_args(tcx, path, NO_TPS | NO_REGIONS);
- return ty::mk_str_slice(tcx, region, a_seq_mutbl);
+ _ => {
+ span_err!(this.tcx().sess, ty.span, E0171,
+ "expected a path on the left-hand side of `+`, not `{}`",
+ pprust::ty_to_string(ty));
+ match ty.node {
+ ast::TyRptr(None, ref mut_ty) => {
+ span_note!(this.tcx().sess, ty.span,
+ "perhaps you meant `&{}({} +{})`? (per RFC 248)",
+ ppaux::mutability_to_string(mut_ty.mutbl),
+ pprust::ty_to_string(&*mut_ty.ty),
+ pprust::bounds_to_string(bounds));
}
- Some(&def::DefTrait(trait_def_id)) => {
- let result = ast_path_to_trait_ref(this,
- rscope,
- trait_def_id,
- None,
- path);
- let empty_vec = [];
- let bounds = match *opt_bounds { None => empty_vec.as_slice(),
- Some(ref bounds) => bounds.as_slice() };
- let existential_bounds = conv_existential_bounds(this,
- rscope,
- path.span,
- &[Rc::new(result.clone())],
- bounds);
- let tr = ty::mk_trait(tcx,
- result,
- existential_bounds);
- return ty::mk_rptr(tcx, region, ty::mt{mutbl: a_seq_mutbl, ty: tr});
+
+ ast::TyRptr(Some(ref lt), ref mut_ty) => {
+ span_note!(this.tcx().sess, ty.span,
+ "perhaps you meant `&{} {}({} +{})`? (per RFC 248)",
+ pprust::lifetime_to_string(lt),
+ ppaux::mutability_to_string(mut_ty.mutbl),
+ pprust::ty_to_string(&*mut_ty.ty),
+ pprust::bounds_to_string(bounds));
+ }
+
+ _ => {
+ span_note!(this.tcx().sess, ty.span,
+ "perhaps you forget parentheses? (per RFC 248)");
}
- _ => {}
}
+ Err(ErrorReported)
}
- _ => {}
}
- constr(ast_ty_to_ty(this, rscope, a_seq_ty))
+}
+
+fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
+ rscope: &RS,
+ span: Span,
+ trait_ref: ty::TraitRef<'tcx>,
+ bounds: &[ast::TyParamBound])
+ -> Ty<'tcx>
+ where AC : AstConv<'tcx>, RS : RegionScope
+{
+ let existential_bounds = conv_existential_bounds(this,
+ rscope,
+ span,
+ &[Rc::new(trait_ref.clone())],
+ bounds);
+
+ let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
+ debug!("trait_ref_to_object_type: result={}",
+ result.repr(this.tcx()));
+
+ result
}
fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
ast::TyVec(ref ty) => {
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
}
+ ast::TyObjectSum(ref ty, ref bounds) => {
+ match ast_ty_to_trait_ref(this, rscope, &**ty, bounds.as_slice()) {
+ Ok(trait_ref) => {
+ trait_ref_to_object_type(this, rscope, ast_ty.span,
+ trait_ref, bounds.as_slice())
+ }
+ Err(ErrorReported) => {
+ ty::mk_err()
+ }
+ }
+ }
ast::TyPtr(ref mt) => {
ty::mk_ptr(tcx, ty::mt {
ty: ast_ty_to_ty(this, rscope, &*mt.ty),
ast::TyRptr(ref region, ref mt) => {
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
debug!("ty_rptr r={}", r.repr(this.tcx()));
- mk_pointer(this, rscope, mt.mutbl, &*mt.ty, r,
- |ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
+ let t = ast_ty_to_ty(this, rscope, &*mt.ty);
+ ty::mk_rptr(tcx, r, ty::mt {ty: t, mutbl: mt.mutbl})
}
ast::TyTup(ref fields) => {
let flds = fields.iter()
ast::TyPolyTraitRef(ref bounds) => {
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
}
- ast::TyPath(ref path, ref bounds, id) => {
+ ast::TyPath(ref path, id) => {
let a_def = match tcx.def_map.borrow().get(&id) {
None => {
tcx.sess
}
Some(&d) => d
};
- // Kind bounds on path types are only supported for traits.
- match a_def {
- // But don't emit the error if the user meant to do a trait anyway.
- def::DefTrait(..) => { },
- _ if bounds.is_some() =>
- tcx.sess.span_err(ast_ty.span,
- "kind bounds can only be used on trait types"),
- _ => { },
- }
match a_def {
def::DefTrait(trait_def_id) => {
+ // N.B. this case overlaps somewhat with
+ // TyObjectSum, see that fn for details
let result = ast_path_to_trait_ref(this,
rscope,
trait_def_id,
None,
path);
- let empty_bounds: &[ast::TyParamBound] = &[];
- let ast_bounds = match *bounds {
- Some(ref b) => b.as_slice(),
- None => empty_bounds
- };
- let bounds = conv_existential_bounds(this,
- rscope,
- ast_ty.span,
- &[Rc::new(result.clone())],
- ast_bounds);
- let result_ty = ty::mk_trait(tcx, result, bounds);
- debug!("ast_ty_to_ty: result_ty={}", result_ty.repr(this.tcx()));
- result_ty
+ trait_ref_to_object_type(this, rscope, path.span, result, &[])
}
def::DefTy(did, _) | def::DefStruct(did) => {
ast_path_to_ty(this, rscope, did, path).ty
/// A path (`module::module::...::Type`) or primitive
///
/// Type parameters are stored in the Path itself
- TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
+ TyPath(Path, NodeId),
+ /// Something like `A+B`. Note that `B` must always be a path.
+ TyObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`
TyPolyTraitRef(TyParamBounds),
/// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
parameters: ast::PathParameters::none(),
}
),
- }, None, ast::DUMMY_NODE_ID),
+ }, ast::DUMMY_NODE_ID),
span:sp(10,13)
}),
pat: P(ast::Pat {
/// A path with a lifetime and type parameters with double colons before
/// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
LifetimeAndTypesWithColons,
- /// A path with a lifetime and type parameters with bounds before the last
- /// set of type parameters only; e.g. `foo::bar<'a>::Baz+X+Y<T>` This
- /// form does not use extra double colons.
- LifetimeAndTypesAndBounds,
-}
-
-/// A path paired with optional type bounds.
-pub struct PathAndBounds {
- pub path: ast::Path,
- pub bounds: Option<ast::TyParamBounds>,
}
enum ItemOrViewItem {
}
}
- pub fn parse_ty_path(&mut self, plus_allowed: bool) -> Ty_ {
- let mode = if plus_allowed {
- LifetimeAndTypesAndBounds
- } else {
- LifetimeAndTypesWithoutColons
- };
- let PathAndBounds {
- path,
- bounds
- } = self.parse_path(mode);
- TyPath(path, bounds, ast::DUMMY_NODE_ID)
+ pub fn parse_ty_path(&mut self) -> Ty_ {
+ let path = self.parse_path(LifetimeAndTypesWithoutColons);
+ TyPath(path, ast::DUMMY_NODE_ID)
}
/// parse a TyBareFn type:
let lo = self.span.lo;
let ident = self.parse_ident();
self.expect(&token::Eq);
- let typ = self.parse_ty(true);
+ let typ = self.parse_ty_sum();
let hi = self.span.hi;
self.expect(&token::Semi);
Typedef {
/// Parse a possibly mutable type
pub fn parse_mt(&mut self) -> MutTy {
let mutbl = self.parse_mutability();
- let t = self.parse_ty(true);
+ let t = self.parse_ty();
MutTy { ty: t, mutbl: mutbl }
}
let mutbl = self.parse_mutability();
let id = self.parse_ident();
self.expect(&token::Colon);
- let ty = self.parse_ty(true);
+ let ty = self.parse_ty_sum();
let hi = ty.span.hi;
ast::TypeField {
ident: id,
if self.eat(&token::Not) {
NoReturn(self.span)
} else {
- Return(self.parse_ty(true))
+ let t = self.parse_ty();
+
+ // We used to allow `fn foo() -> &T + U`, but don't
+ // anymore. If we see it, report a useful error. This
+ // only makes sense because `parse_ret_ty` is only
+ // used in fn *declarations*, not fn types or where
+ // clauses (i.e., not when parsing something like
+ // `FnMut() -> T + Send`, where the `+` is legal).
+ if self.token == token::BinOp(token::Plus) {
+ self.warn("deprecated syntax: `()` are required, see RFC 248 for details");
+ }
+
+ Return(t)
}
} else {
let pos = self.span.lo;
}
}
+ /// Parse a type in a context where `T1+T2` is allowed.
+ pub fn parse_ty_sum(&mut self) -> P<Ty> {
+ let lo = self.span.lo;
+ let lhs = self.parse_ty();
+
+ if !self.eat(&token::BinOp(token::Plus)) {
+ return lhs;
+ }
+
+ let bounds = self.parse_ty_param_bounds();
+
+ // In type grammar, `+` is treated like a binary operator,
+ // and hence both L and R side are required.
+ if bounds.len() == 0 {
+ let last_span = self.last_span;
+ self.span_err(last_span,
+ "at least one type parameter bound \
+ must be specified");
+ }
+
+ let sp = mk_sp(lo, self.last_span.hi);
+ let sum = ast::TyObjectSum(lhs, bounds);
+ P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp})
+ }
+
/// Parse a type.
///
/// The second parameter specifies whether the `+` binary operator is
/// allowed in the type grammar.
- pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> {
+ pub fn parse_ty(&mut self) -> P<Ty> {
maybe_whole!(no_clone self, NtTy);
let lo = self.span.lo;
let mut ts = vec![];
let mut last_comma = false;
while self.token != token::CloseDelim(token::Paren) {
- ts.push(self.parse_ty(true));
+ ts.push(self.parse_ty_sum());
if self.token == token::Comma {
last_comma = true;
self.bump();
token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector),
_ => self.obsolete(last_span, ObsoleteOwnedType)
}
- TyTup(vec![self.parse_ty(false)])
+ TyTup(vec![self.parse_ty()])
} else if self.token == token::BinOp(token::Star) {
// STAR POINTER (bare pointer?)
self.bump();
} else if self.token == token::OpenDelim(token::Bracket) {
// VECTOR
self.expect(&token::OpenDelim(token::Bracket));
- let t = self.parse_ty(true);
+ let t = self.parse_ty_sum();
// Parse the `, ..e` in `[ int, ..e ]`
// where `e` is a const expression
} else if self.token == token::Lt {
// QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
self.bump();
- let self_type = self.parse_ty(true);
+ let self_type = self.parse_ty_sum();
self.expect_keyword(keywords::As);
let trait_ref = self.parse_trait_ref();
self.expect(&token::Gt);
self.token.is_ident() ||
self.token.is_path() {
// NAMED TYPE
- self.parse_ty_path(plus_allowed)
+ self.parse_ty_path()
} else if self.eat(&token::Underscore) {
// TYPE TO BE INFERRED
TyInfer
known as `*const T`");
MutImmutable
};
- let t = self.parse_ty(true);
+ let t = self.parse_ty();
MutTy { ty: t, mutbl: mutbl }
}
special_idents::invalid)
};
- let t = self.parse_ty(true);
+ let t = self.parse_ty_sum();
Arg {
ty: t,
pub fn parse_fn_block_arg(&mut self) -> Arg {
let pat = self.parse_pat();
let t = if self.eat(&token::Colon) {
- self.parse_ty(true)
+ self.parse_ty_sum()
} else {
P(Ty {
id: ast::DUMMY_NODE_ID,
/// mode. The `mode` parameter determines whether lifetimes, types, and/or
/// bounds are permitted and whether `::` must precede type parameter
/// groups.
- pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds {
+ pub fn parse_path(&mut self, mode: PathParsingMode) -> ast::Path {
// Check for a whole path...
let found = match self.token {
token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()),
};
match found {
Some(token::Interpolated(token::NtPath(box path))) => {
- return PathAndBounds {
- path: path,
- bounds: None
- }
+ return path;
}
_ => {}
}
// identifier followed by an optional lifetime and a set of types.
// A bound set is a set of type parameter bounds.
let segments = match mode {
- LifetimeAndTypesWithoutColons |
- LifetimeAndTypesAndBounds => {
+ LifetimeAndTypesWithoutColons => {
self.parse_path_segments_without_colons()
}
LifetimeAndTypesWithColons => {
}
};
- // Next, parse a plus and bounded type parameters, if
- // applicable. We need to remember whether the separate was
- // present for later, because in some contexts it's a parse
- // error.
- let opt_bounds = {
- if mode == LifetimeAndTypesAndBounds &&
- self.eat(&token::BinOp(token::Plus))
- {
- let bounds = self.parse_ty_param_bounds();
-
- // For some reason that I do not fully understand, we
- // do not permit an empty list in the case where it is
- // introduced by a `+`, but we do for `:` and other
- // separators. -nmatsakis
- if bounds.len() == 0 {
- let last_span = self.last_span;
- self.span_err(last_span,
- "at least one type parameter bound \
- must be specified");
- }
-
- Some(bounds)
- } else {
- None
- }
- };
-
// Assemble the span.
let span = mk_sp(lo, self.last_span.hi);
// Assemble the result.
- PathAndBounds {
- path: ast::Path {
- span: span,
- global: is_global,
- segments: segments,
- },
- bounds: opt_bounds,
+ ast::Path {
+ span: span,
+ global: is_global,
+ segments: segments,
}
}
let inputs = self.parse_seq_to_end(
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
- |p| p.parse_ty(true));
+ |p| p.parse_ty_sum());
let output_ty = if self.eat(&token::RArrow) {
- Some(self.parse_ty(true))
+ Some(self.parse_ty())
} else {
None
};
!self.token.is_keyword(keywords::True) &&
!self.token.is_keyword(keywords::False) {
let pth =
- self.parse_path(LifetimeAndTypesWithColons).path;
+ self.parse_path(LifetimeAndTypesWithColons);
// `!`, as an operator, is prefix, so we know this isn't that
if self.token == token::Not {
}
None => {
if as_prec > min_prec && self.eat_keyword(keywords::As) {
- let rhs = self.parse_ty(false);
+ let rhs = self.parse_ty();
let _as = self.mk_expr(lhs.span.lo,
rhs.span.hi,
ExprCast(lhs, rhs));
}) {
self.bump();
let end = if self.token.is_ident() || self.token.is_path() {
- let path = self.parse_path(LifetimeAndTypesWithColons)
- .path;
+ let path = self.parse_path(LifetimeAndTypesWithColons);
let hi = self.span.hi;
self.mk_expr(lo, hi, ExprPath(path))
} else {
}
} else {
// parse an enum pat
- let enum_path = self.parse_path(LifetimeAndTypesWithColons)
- .path;
+ let enum_path = self.parse_path(LifetimeAndTypesWithColons);
match self.token {
token::OpenDelim(token::Brace) => {
self.bump();
span: mk_sp(lo, lo),
});
if self.eat(&token::Colon) {
- ty = self.parse_ty(true);
+ ty = self.parse_ty_sum();
}
let init = self.parse_initializer();
P(ast::Local {
}
let name = self.parse_ident();
self.expect(&token::Colon);
- let ty = self.parse_ty(true);
+ let ty = self.parse_ty_sum();
spanned(lo, self.last_span.hi, ast::StructField_ {
kind: NamedField(name, pr),
id: ast::DUMMY_NODE_ID,
// Potential trouble: if we allow macros with paths instead of
// idents, we'd need to look ahead past the whole path here...
- let pth = self.parse_path(NoTypesAllowed).path;
+ let pth = self.parse_path(NoTypesAllowed);
self.bump();
let id = match self.token {
let default = if self.token == token::Eq {
self.bump();
- Some(self.parse_ty(true))
+ Some(self.parse_ty_sum())
}
else { None };
Some(token::Comma),
|p| {
p.forbid_lifetime();
- p.parse_ty(true)
+ p.parse_ty_sum()
}
);
(lifetimes, result.into_vec())
// Determine whether this is the fully explicit form, `self:
// TYPE`.
if self.eat(&token::Colon) {
- SelfExplicit(self.parse_ty(false), self_ident)
+ SelfExplicit(self.parse_ty_sum(), self_ident)
} else {
SelfValue(self_ident)
}
// Determine whether this is the fully explicit form,
// `self: TYPE`.
if self.eat(&token::Colon) {
- SelfExplicit(self.parse_ty(false), self_ident)
+ SelfExplicit(self.parse_ty_sum(), self_ident)
} else {
SelfValue(self_ident)
}
&& (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren))
|| self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) {
// method macro.
- let pth = self.parse_path(NoTypesAllowed).path;
+ let pth = self.parse_path(NoTypesAllowed);
self.expect(&token::Not);
// eat a matched-delimiter token tree:
let could_be_trait = self.token != token::OpenDelim(token::Paren);
// Parse the trait.
- let mut ty = self.parse_ty(true);
+ let mut ty = self.parse_ty_sum();
// 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.
let opt_trait_ref = match ty.node {
- TyPath(ref path, None, node_id) => {
+ TyPath(ref path, node_id) => {
Some(TraitRef {
path: (*path).clone(),
ref_id: node_id,
})
}
- TyPath(_, Some(_), _) => {
- self.span_err(ty.span,
- "bounded traits are only valid in type position");
- None
- }
_ => {
self.span_err(ty.span, "not a trait");
None
}
};
- ty = self.parse_ty(true);
+ ty = self.parse_ty_sum();
opt_trait_ref
} else {
None
/// Parse a::B<String,int>
fn parse_trait_ref(&mut self) -> TraitRef {
ast::TraitRef {
- path: self.parse_path(LifetimeAndTypesWithoutColons).path,
+ path: self.parse_path(LifetimeAndTypesWithoutColons),
ref_id: ast::DUMMY_NODE_ID,
}
}
let mut generics = self.parse_generics();
if self.eat(&token::Colon) {
- let ty = self.parse_ty(true);
+ let ty = self.parse_ty_sum();
self.span_err(ty.span, "`virtual` structs have been removed from the language");
}
let struct_field_ = ast::StructField_ {
kind: UnnamedField(p.parse_visibility()),
id: ast::DUMMY_NODE_ID,
- ty: p.parse_ty(true),
+ ty: p.parse_ty_sum(),
attrs: attrs,
};
spanned(lo, p.span.hi, struct_field_)
fn parse_item_const(&mut self, m: Option<Mutability>) -> ItemInfo {
let id = self.parse_ident();
self.expect(&token::Colon);
- let ty = self.parse_ty(true);
+ let ty = self.parse_ty_sum();
self.expect(&token::Eq);
let e = self.parse_expr();
self.commit_expr_expecting(&*e, token::Semi);
let ident = self.parse_ident();
self.expect(&token::Colon);
- let ty = self.parse_ty(true);
+ let ty = self.parse_ty_sum();
let hi = self.span.hi;
self.expect(&token::Semi);
P(ForeignItem {
let mut tps = self.parse_generics();
self.parse_where_clause(&mut tps);
self.expect(&token::Eq);
- let ty = self.parse_ty(true);
+ let ty = self.parse_ty_sum();
self.expect(&token::Semi);
(ident, ItemTy(ty, tps), None)
}
&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
- |p| p.parse_ty(true)
+ |p| p.parse_ty_sum()
);
for ty in arg_tys.into_iter() {
args.push(ast::VariantArg {
// MACRO INVOCATION ITEM
// item macro.
- let pth = self.parse_path(NoTypesAllowed).path;
+ let pth = self.parse_path(NoTypesAllowed);
self.expect(&token::Not);
// a 'special' identifier (like what `macro_rules!` uses)
$to_string(|s| s.print_type(ty))
}
+pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String {
+ $to_string(|s| s.print_bounds("", bounds))
+}
+
pub fn pat_to_string(pat: &ast::Pat) -> String {
$to_string(|s| s.print_pat(pat))
}
Some(&generics),
None));
}
- ast::TyPath(ref path, ref bounds, _) => {
- try!(self.print_bounded_path(path, bounds));
+ ast::TyPath(ref path, _) => {
+ try!(self.print_path(path, false));
+ }
+ ast::TyObjectSum(ref ty, ref bounds) => {
+ try!(self.print_type(&**ty));
+ try!(self.print_bounds("+", bounds.as_slice()));
}
ast::TyPolyTraitRef(ref bounds) => {
- try!(self.print_bounds("", bounds));
+ try!(self.print_bounds("", bounds.as_slice()));
}
ast::TyQPath(ref qpath) => {
try!(word(&mut self.s, "<"));
}
_ => {}
}
- try!(self.print_bounds(":", bounds));
+ try!(self.print_bounds(":", bounds.as_slice()));
try!(self.print_where_clause(generics));
try!(word(&mut self.s, " "));
try!(self.bopen());
pub fn print_bounds(&mut self,
prefix: &str,
- bounds: &OwnedSlice<ast::TyParamBound>)
+ bounds: &[ast::TyParamBound])
-> IoResult<()> {
if !bounds.is_empty() {
try!(word(&mut self.s, prefix));
_ => {}
}
try!(self.print_ident(param.ident));
- try!(self.print_bounds(":", ¶m.bounds));
+ try!(self.print_bounds(":", param.bounds.as_slice()));
match param.default {
Some(ref default) => {
try!(space(&mut self.s));
}
try!(self.print_ident(predicate.ident));
- try!(self.print_bounds(":", &predicate.bounds));
+ try!(self.print_bounds(":", predicate.bounds.as_slice()));
}
Ok(())
try!(self.pclose());
}
- try!(self.print_bounds(":", bounds));
+ try!(self.print_bounds(":", bounds.as_slice()));
try!(self.print_fn_output(decl));