Auto merge of #39110 - petrochenkov:sum, r=eddyb

Merge ObjectSum and PolyTraitRef in AST/HIR + some other refactoring

`ObjectSum` and `PolyTraitRef` are the same thing (list of bounds), they exist separately only due to parser quirks. The second commit merges them.

The first commit replaces `Path` with `Ty` in (not yet supported) equality predicates. They are parsed as types anyway and arbitrary types can always be disguised as paths using aliases, so this doesn't add any new functionality.

The third commit uses `Vec` instead of `P<[T]>` in AST. AST is not immutable like HIR and `Vec`s are more convenient for it, unnecessary conversions are also avoided.

The last commit renames `parse_ty_sum` (which is used for parsing types in general) into `parse_ty`, and renames `parse_ty` (which is used restricted contexts where `+` is not permitted due to operator priorities or other reasons) into `parse_ty_no_plus`.

This is the first part of https://github.com/rust-lang/rust/issues/39085#issuecomment-272743755 and https://github.com/rust-lang/rust/issues/39080 focused on data changes and mechanical renaming, I'll submit a PR with parser changes a bit later.

r? @eddyb
This commit is contained in:
bors 2017-01-17 12:31:15 +00:00
commit a167c042ab
30 changed files with 239 additions and 373 deletions

View File

@ -562,15 +562,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
TyPath(ref qpath) => {
visitor.visit_qpath(qpath, typ.id, typ.span);
}
TyObjectSum(ref ty, ref bounds) => {
visitor.visit_ty(ty);
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyArray(ref ty, length) => {
visitor.visit_ty(ty);
visitor.visit_nested_body(length)
}
TyPolyTraitRef(ref bounds) => {
TyTraitObject(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyImplTrait(ref bounds) => {
@ -740,12 +736,12 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
walk_list!(visitor, visit_lifetime, bounds);
}
&WherePredicate::EqPredicate(WhereEqPredicate{id,
ref path,
ref ty,
ref lhs_ty,
ref rhs_ty,
..}) => {
visitor.visit_id(id);
visitor.visit_path(path, id);
visitor.visit_ty(ty);
visitor.visit_ty(lhs_ty);
visitor.visit_ty(rhs_ty);
}
}
}

View File

@ -308,9 +308,6 @@ impl<'a> LoweringContext<'a> {
span: t.span,
})))
}
TyKind::ObjectSum(ref ty, ref bounds) => {
hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
}
TyKind::Array(ref ty, ref length) => {
let length = self.lower_expr(length);
hir::TyArray(self.lower_ty(ty),
@ -320,8 +317,8 @@ impl<'a> LoweringContext<'a> {
let expr = self.lower_expr(expr);
hir::TyTypeof(self.record_body(expr, None))
}
TyKind::PolyTraitRef(ref bounds) => {
hir::TyPolyTraitRef(self.lower_bounds(bounds))
TyKind::TraitObject(ref bounds) => {
hir::TyTraitObject(self.lower_bounds(bounds))
}
TyKind::ImplTrait(ref bounds) => {
hir::TyImplTrait(self.lower_bounds(bounds))
@ -599,7 +596,7 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_ty_params(&mut self, tps: &P<[TyParam]>, add_bounds: &NodeMap<Vec<TyParamBound>>)
fn lower_ty_params(&mut self, tps: &Vec<TyParam>, add_bounds: &NodeMap<Vec<TyParamBound>>)
-> hir::HirVec<hir::TyParam> {
tps.iter().map(|tp| {
self.lower_ty_param(tp, add_bounds.get(&tp.id).map_or(&[][..], |x| &x))
@ -719,13 +716,13 @@ impl<'a> LoweringContext<'a> {
})
}
WherePredicate::EqPredicate(WhereEqPredicate{ id,
ref path,
ref ty,
ref lhs_ty,
ref rhs_ty,
span}) => {
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
id: id,
path: self.lower_path(id, path, ParamMode::Explicit, false),
ty: self.lower_ty(ty),
lhs_ty: self.lower_ty(lhs_ty),
rhs_ty: self.lower_ty(rhs_ty),
span: span,
})
}

View File

@ -403,8 +403,8 @@ pub struct WhereRegionPredicate {
pub struct WhereEqPredicate {
pub id: NodeId,
pub span: Span,
pub path: Path,
pub ty: P<Ty>,
pub lhs_ty: P<Ty>,
pub rhs_ty: P<Ty>,
}
pub type CrateConfig = HirVec<P<MetaItem>>;
@ -1214,12 +1214,11 @@ pub enum Ty_ {
///
/// Type parameters may be stored in each `PathSegment`.
TyPath(QPath),
/// 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),
/// An `impl TraitA+TraitB` type.
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TyTraitObject(TyParamBounds),
/// An `impl Bound1 + Bound2 + Bound3` type
/// where `Bound` is a trait or a lifetime.
TyImplTrait(TyParamBounds),
/// Unused for now
TyTypeof(BodyId),

View File

@ -418,11 +418,7 @@ impl<'a> State<'a> {
hir::TyPath(ref qpath) => {
self.print_qpath(qpath, false)?
}
hir::TyObjectSum(ref ty, ref bounds) => {
self.print_type(&ty)?;
self.print_bounds("+", &bounds[..])?;
}
hir::TyPolyTraitRef(ref bounds) => {
hir::TyTraitObject(ref bounds) => {
self.print_bounds("", &bounds[..])?;
}
hir::TyImplTrait(ref bounds) => {
@ -2023,11 +2019,13 @@ impl<'a> State<'a> {
}
}
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => {
self.print_path(path, false)?;
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
..}) => {
self.print_type(lhs_ty)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(&ty)?;
self.print_type(rhs_ty)?;
}
}
}

View File

@ -323,12 +323,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.visit_lifetime(bound);
}
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ id,
ref path,
ref ty,
.. }) => {
self.visit_path(path, id);
self.visit_ty(&ty);
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
.. }) => {
self.visit_ty(lhs_ty);
self.visit_ty(rhs_ty);
}
}
}

View File

@ -441,7 +441,6 @@ enum SawTyComponent {
SawTyTup,
SawTyPath,
SawTyObjectSum,
SawTyPolyTraitRef,
SawTyImplTrait,
SawTyTypeof,
SawTyInfer
@ -457,8 +456,7 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
TyNever => SawTyNever,
TyTup(..) => SawTyTup,
TyPath(_) => SawTyPath,
TyObjectSum(..) => SawTyObjectSum,
TyPolyTraitRef(..) => SawTyPolyTraitRef,
TyTraitObject(..) => SawTyObjectSum,
TyImplTrait(..) => SawTyImplTrait,
TyTypeof(..) => SawTyTypeof,
TyInfer => SawTyInfer

View File

@ -143,8 +143,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
err.emit();
});
}
TyKind::ObjectSum(_, ref bounds) |
TyKind::PolyTraitRef(ref bounds) => {
TyKind::TraitObject(ref bounds) => {
self.no_questions_in_bounds(bounds, "trait object types", false);
}
_ => {}

View File

@ -853,7 +853,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
&hir::WherePredicate::RegionPredicate(_) => {}
&hir::WherePredicate::EqPredicate(ref eq_pred) => {
self.visit_ty(&eq_pred.ty);
self.visit_ty(&eq_pred.rhs_ty);
}
}
}

View File

@ -73,7 +73,7 @@ use std::iter;
use syntax::{abi, ast};
use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax::symbol::{Symbol, keywords};
use syntax_pos::{Span, Pos};
use syntax_pos::Span;
use errors::DiagnosticBuilder;
pub trait AstConv<'gcx, 'tcx> {
@ -930,87 +930,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
decl_ty.subst(self.tcx(), substs)
}
fn ast_ty_to_object_trait_ref(&self,
rscope: &RegionScope,
span: Span,
ty: &hir::Ty,
bounds: &[hir::TyParamBound])
-> Ty<'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.
*/
let tcx = self.tcx();
match ty.node {
hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
if let Def::Trait(trait_def_id) = path.def {
self.trait_path_to_object_type(rscope,
path.span,
trait_def_id,
ty.id,
path.segments.last().unwrap(),
span,
partition_bounds(bounds))
} else {
struct_span_err!(tcx.sess, ty.span, E0172,
"expected a reference to a trait")
.span_label(ty.span, &format!("expected a trait"))
.emit();
tcx.types.err
}
}
_ => {
let mut err = struct_span_err!(tcx.sess, ty.span, E0178,
"expected a path on the left-hand side \
of `+`, not `{}`",
tcx.map.node_to_pretty_string(ty.id));
err.span_label(ty.span, &format!("expected a path"));
let hi = bounds.iter().map(|x| match *x {
hir::TraitTyParamBound(ref tr, _) => tr.span.hi,
hir::RegionTyParamBound(ref r) => r.span.hi,
}).max_by_key(|x| x.to_usize());
let full_span = hi.map(|hi| Span {
lo: ty.span.lo,
hi: hi,
expn_id: ty.span.expn_id,
});
match (&ty.node, full_span) {
(&hir::TyRptr(ref lifetime, ref mut_ty), Some(full_span)) => {
let ty_str = hir::print::to_string(&tcx.map, |s| {
use syntax::print::pp::word;
use syntax::print::pprust::PrintState;
word(&mut s.s, "&")?;
s.print_opt_lifetime(lifetime)?;
s.print_mutability(mut_ty.mutbl)?;
s.popen()?;
s.print_type(&mut_ty.ty)?;
s.print_bounds(" +", bounds)?;
s.pclose()
});
err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
ty_str);
}
_ => {
help!(&mut err,
"perhaps you forgot parentheses? (per RFC 438)");
}
}
err.emit();
tcx.types.err
}
}
}
/// Transform a PolyTraitRef into a PolyExistentialTraitRef by
/// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF).
fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
@ -1428,7 +1347,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
match path.def {
Def::Trait(trait_def_id) => {
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
// TyTraitObject, see that fn for details
assert_eq!(opt_self_ty, None);
tcx.prohibit_type_params(path.segments.split_last().unwrap().1);
@ -1534,9 +1453,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
hir::TySlice(ref ty) => {
tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty))
}
hir::TyObjectSum(ref ty, ref bounds) => {
self.ast_ty_to_object_trait_ref(rscope, ast_ty.span, ty, bounds)
}
hir::TyPtr(ref mt) => {
tcx.mk_ptr(ty::TypeAndMut {
ty: self.ast_ty_to_ty(rscope, &mt.ty),
@ -1609,7 +1525,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
tcx.mk_fn_ptr(bare_fn_ty)
}
hir::TyPolyTraitRef(ref bounds) => {
hir::TyTraitObject(ref bounds) => {
self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
}
hir::TyImplTrait(ref bounds) => {

View File

@ -1864,55 +1864,6 @@ fn bar(foo: Foo) -> u32 {
```
"##,
E0172: r##"
This error means that an attempt was made to specify the type of a variable with
a combination of a concrete type and a trait. Consider the following example:
```compile_fail,E0172
fn foo(bar: i32+std::fmt::Display) {}
```
The code is trying to specify that we want to receive a signed 32-bit integer
which also implements `Display`. This doesn't make sense: when we pass `i32`, a
concrete type, it implicitly includes all of the traits that it implements.
This includes `Display`, `Debug`, `Clone`, and a host of others.
If `i32` implements the trait we desire, there's no need to specify the trait
separately. If it does not, then we need to `impl` the trait for `i32` before
passing it into `foo`. Either way, a fixed definition for `foo` will look like
the following:
```
fn foo(bar: i32) {}
```
To learn more about traits, take a look at the Book:
https://doc.rust-lang.org/book/traits.html
"##,
E0178: r##"
In types, the `+` type operator has low precedence, so it is often necessary
to use parentheses.
For example:
```compile_fail,E0178
trait Foo {}
struct Bar<'a> {
w: &'a Foo + Copy, // error, use &'a (Foo + Copy)
x: &'a Foo + 'a, // error, use &'a (Foo + 'a)
y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
}
```
More details can be found in [RFC 438].
[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
"##,
E0182: r##"
You bound an associated type in an expression path which is not
allowed.
@ -4152,6 +4103,7 @@ register_diagnostics! {
// E0163, // merged into E0071
// E0167,
// E0168,
// E0172, // non-trait found in a type sum, moved to resolve
// E0173, // manual implementations of unboxed closure traits are experimental
// E0174,
E0183,

View File

@ -1504,9 +1504,6 @@ pub enum Type {
// _
Infer,
// for<'a> Foo(&'a)
PolyTraitRef(Vec<TyParamBound>),
// impl TraitA+TraitB
ImplTrait(Vec<TyParamBound>),
}
@ -1768,24 +1765,26 @@ impl Clean<Type> for hir::Ty {
trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
}
}
TyObjectSum(ref lhs, ref bounds) => {
let lhs_ty = lhs.clean(cx);
TyTraitObject(ref bounds) => {
let lhs_ty = bounds[0].clean(cx);
match lhs_ty {
ResolvedPath { path, typarams: None, did, is_generic } => {
ResolvedPath {
path: path,
typarams: Some(bounds.clean(cx)),
did: did,
is_generic: is_generic,
TraitBound(poly_trait, ..) => {
match poly_trait.trait_ {
ResolvedPath { path, typarams: None, did, is_generic } => {
ResolvedPath {
path: path,
typarams: Some(bounds[1..].clean(cx)),
did: did,
is_generic: is_generic,
}
}
_ => Infer // shouldn't happen
}
}
_ => {
lhs_ty // shouldn't happen
}
_ => Infer // shouldn't happen
}
}
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

@ -679,19 +679,6 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
}
}
}
clean::PolyTraitRef(ref bounds) => {
for (i, bound) in bounds.iter().enumerate() {
if i != 0 {
write!(f, " + ")?;
}
if f.alternate() {
write!(f, "{:#}", *bound)?;
} else {
write!(f, "{}", *bound)?;
}
}
Ok(())
}
clean::ImplTrait(ref bounds) => {
write!(f, "impl ")?;
for (i, bound) in bounds.iter().enumerate() {

View File

@ -204,11 +204,11 @@ pub struct AngleBracketedParameterData {
/// The lifetime parameters for this path segment.
pub lifetimes: Vec<Lifetime>,
/// The type parameters for this path segment, if present.
pub types: P<[P<Ty>]>,
pub types: Vec<P<Ty>>,
/// Bindings (equality constraints) on associated types, if present.
///
/// E.g., `Foo<A=Bar>`.
pub bindings: P<[TypeBinding]>,
pub bindings: Vec<TypeBinding>,
}
impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
@ -297,7 +297,7 @@ pub enum TraitBoundModifier {
Maybe,
}
pub type TyParamBounds = P<[TyParamBound]>;
pub type TyParamBounds = Vec<TyParamBound>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct TyParam {
@ -314,7 +314,7 @@ pub struct TyParam {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct Generics {
pub lifetimes: Vec<LifetimeDef>,
pub ty_params: P<[TyParam]>,
pub ty_params: Vec<TyParam>,
pub where_clause: WhereClause,
pub span: Span,
}
@ -344,7 +344,7 @@ impl Default for Generics {
fn default() -> Generics {
Generics {
lifetimes: Vec::new(),
ty_params: P::new(),
ty_params: Vec::new(),
where_clause: WhereClause {
id: DUMMY_NODE_ID,
predicates: Vec::new(),
@ -403,8 +403,8 @@ pub struct WhereRegionPredicate {
pub struct WhereEqPredicate {
pub id: NodeId,
pub span: Span,
pub path: Path,
pub ty: P<Ty>,
pub lhs_ty: P<Ty>,
pub rhs_ty: P<Ty>,
}
/// The set of MetaItems that define the compilation environment of the crate,
@ -1357,11 +1357,11 @@ pub enum TyKind {
///
/// Type parameters are stored in the Path itself
Path(Option<QSelf>, Path),
/// Something like `A+B`. Note that `B` must always be a path.
ObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`
PolyTraitRef(TyParamBounds),
/// An `impl TraitA+TraitB` type.
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TraitObject(TyParamBounds),
/// An `impl Bound1 + Bound2 + Bound3` type
/// where `Bound` is a trait or a lifetime.
ImplTrait(TyParamBounds),
/// No-op; kept solely so that we can pretty-print faithfully
Paren(P<Ty>),

View File

@ -15,6 +15,28 @@
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics! {
E0178: r##"
In types, the `+` type operator has low precedence, so it is often necessary
to use parentheses.
For example:
```compile_fail,E0178
trait Foo {}
struct Bar<'a> {
w: &'a Foo + Copy, // error, use &'a (Foo + Copy)
x: &'a Foo + 'a, // error, use &'a (Foo + 'a)
y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
}
```
More details can be found in [RFC 438].
[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
"##,
E0534: r##"
The `inline` attribute was malformed.

View File

@ -54,7 +54,6 @@ pub trait AstBuilder {
fn ty(&self, span: Span, ty: ast::TyKind) -> P<ast::Ty>;
fn ty_path(&self, ast::Path) -> P<ast::Ty>;
fn ty_sum(&self, ast::Path, ast::TyParamBounds) -> P<ast::Ty>;
fn ty_ident(&self, span: Span, idents: ast::Ident) -> P<ast::Ty>;
fn ty_rptr(&self, span: Span,
@ -68,9 +67,6 @@ pub trait AstBuilder {
fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty>;
fn ty_infer(&self, sp: Span) -> P<ast::Ty>;
fn ty_vars(&self, ty_params: &P<[ast::TyParam]>) -> Vec<P<ast::Ty>> ;
fn ty_vars_global(&self, ty_params: &P<[ast::TyParam]>) -> Vec<P<ast::Ty>> ;
fn typaram(&self,
span: Span,
id: ast::Ident,
@ -334,8 +330,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
} else {
Some(P(ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
types: types,
bindings: bindings,
})))
};
segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
@ -370,8 +366,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
let mut path = trait_path;
let parameters = ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
types: types,
bindings: bindings,
};
path.segments.push(ast::PathSegment {
identifier: ident,
@ -403,12 +399,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
self.ty(path.span, ast::TyKind::Path(None, path))
}
fn ty_sum(&self, path: ast::Path, bounds: ast::TyParamBounds) -> P<ast::Ty> {
self.ty(path.span,
ast::TyKind::ObjectSum(self.ty_path(path),
bounds))
}
// Might need to take bounds as an argument in the future, if you ever want
// to generate a bounded existential trait type.
fn ty_ident(&self, span: Span, ident: ast::Ident)
@ -465,20 +455,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
}
}
// these are strange, and probably shouldn't be used outside of
// pipes. Specifically, the global version possible generates
// incorrect code.
fn ty_vars(&self, ty_params: &P<[ast::TyParam]>) -> Vec<P<ast::Ty>> {
ty_params.iter().map(|p| self.ty_ident(DUMMY_SP, p.ident)).collect()
}
fn ty_vars_global(&self, ty_params: &P<[ast::TyParam]>) -> Vec<P<ast::Ty>> {
ty_params
.iter()
.map(|p| self.ty_path(self.path_global(DUMMY_SP, vec![p.ident])))
.collect()
}
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
ast::TraitRef {
path: path,

View File

@ -540,7 +540,7 @@ impl<'a> Parser<'a> {
}
ExpansionKind::Expr => Expansion::Expr(self.parse_expr()?),
ExpansionKind::OptExpr => Expansion::OptExpr(Some(self.parse_expr()?)),
ExpansionKind::Ty => Expansion::Ty(self.parse_ty()?),
ExpansionKind::Ty => Expansion::Ty(self.parse_ty_no_plus()?),
ExpansionKind::Pat => Expansion::Pat(self.parse_pat()?),
})
}

View File

@ -388,7 +388,7 @@ pub fn parse_arm_panic(parser: &mut Parser) -> Arm {
}
pub fn parse_ty_panic(parser: &mut Parser) -> P<Ty> {
panictry!(parser.parse_ty())
panictry!(parser.parse_ty_no_plus())
}
pub fn parse_stmt_panic(parser: &mut Parser) -> Option<Stmt> {

View File

@ -522,7 +522,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
},
"pat" => token::NtPat(panictry!(p.parse_pat())),
"expr" => token::NtExpr(panictry!(p.parse_expr())),
"ty" => token::NtTy(panictry!(p.parse_ty())),
"ty" => token::NtTy(panictry!(p.parse_ty_no_plus())),
// this could be handled like a token, since it is one
"ident" => match p.token {
token::Ident(sn) => {

View File

@ -225,7 +225,7 @@ pub trait Folder : Sized {
noop_fold_ty_param(tp, self)
}
fn fold_ty_params(&mut self, tps: P<[TyParam]>) -> P<[TyParam]> {
fn fold_ty_params(&mut self, tps: Vec<TyParam>) -> Vec<TyParam> {
noop_fold_ty_params(tps, self)
}
@ -380,18 +380,14 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
});
TyKind::Path(qself, fld.fold_path(path))
}
TyKind::ObjectSum(ty, bounds) => {
TyKind::ObjectSum(fld.fold_ty(ty),
fld.fold_bounds(bounds))
}
TyKind::Array(ty, e) => {
TyKind::Array(fld.fold_ty(ty), fld.fold_expr(e))
}
TyKind::Typeof(expr) => {
TyKind::Typeof(fld.fold_expr(expr))
}
TyKind::PolyTraitRef(bounds) => {
TyKind::PolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
TyKind::TraitObject(bounds) => {
TyKind::TraitObject(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)))
@ -678,8 +674,7 @@ pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
}
}
pub fn noop_fold_ty_params<T: Folder>(tps: P<[TyParam]>, fld: &mut T)
-> P<[TyParam]> {
pub fn noop_fold_ty_params<T: Folder>(tps: Vec<TyParam>, fld: &mut T) -> Vec<TyParam> {
tps.move_map(|tp| fld.fold_ty_param(tp))
}
@ -766,13 +761,13 @@ pub fn noop_fold_where_predicate<T: Folder>(
})
}
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
path,
ty,
lhs_ty,
rhs_ty,
span}) => {
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{
id: fld.new_id(id),
path: fld.fold_path(path),
ty:fld.fold_ty(ty),
lhs_ty: fld.fold_ty(lhs_ty),
rhs_ty: fld.fold_ty(rhs_ty),
span: fld.new_span(span)
})
}

View File

@ -847,7 +847,7 @@ mod tests {
Abi::Rust,
ast::Generics{ // no idea on either of these:
lifetimes: Vec::new(),
ty_params: P::new(),
ty_params: Vec::new(),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),

View File

@ -40,7 +40,7 @@ use ast::{Visibility, WhereClause};
use ast::{BinOpKind, UnOp};
use {ast, attr};
use codemap::{self, CodeMap, Spanned, spanned, respan};
use syntax_pos::{self, Span, BytePos, mk_sp};
use syntax_pos::{self, Span, Pos, BytePos, mk_sp};
use errors::{self, DiagnosticBuilder};
use ext::tt::macro_parser;
use parse;
@ -685,7 +685,7 @@ impl<'a> Parser<'a> {
pub fn parse_seq_to_before_gt_or_return<T, F>(&mut self,
sep: Option<token::Token>,
mut f: F)
-> PResult<'a, (P<[T]>, bool)>
-> PResult<'a, (Vec<T>, bool)>
where F: FnMut(&mut Parser<'a>) -> PResult<'a, Option<T>>,
{
let mut v = Vec::new();
@ -706,7 +706,7 @@ impl<'a> Parser<'a> {
if i % 2 == 0 {
match f(self)? {
Some(result) => v.push(result),
None => return Ok((P::from_vec(v), true))
None => return Ok((v, true))
}
} else {
if let Some(t) = sep.as_ref() {
@ -715,7 +715,7 @@ impl<'a> Parser<'a> {
}
}
return Ok((P::from_vec(v), false));
return Ok((v, false));
}
/// Parse a sequence bracketed by '<' and '>', stopping
@ -723,7 +723,7 @@ impl<'a> Parser<'a> {
pub fn parse_seq_to_before_gt<T, F>(&mut self,
sep: Option<token::Token>,
mut f: F)
-> PResult<'a, P<[T]>> where
-> PResult<'a, Vec<T>> where
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
let (result, returned) = self.parse_seq_to_before_gt_or_return(sep,
@ -735,7 +735,7 @@ impl<'a> Parser<'a> {
pub fn parse_seq_to_gt<T, F>(&mut self,
sep: Option<token::Token>,
f: F)
-> PResult<'a, P<[T]>> where
-> PResult<'a, Vec<T>> where
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
let v = self.parse_seq_to_before_gt(sep, f)?;
@ -746,7 +746,7 @@ impl<'a> Parser<'a> {
pub fn parse_seq_to_gt_or_return<T, F>(&mut self,
sep: Option<token::Token>,
f: F)
-> PResult<'a, (P<[T]>, bool)> where
-> PResult<'a, (Vec<T>, bool)> where
F: FnMut(&mut Parser<'a>) -> PResult<'a, Option<T>>,
{
let (v, returned) = self.parse_seq_to_before_gt_or_return(sep, f)?;
@ -1039,13 +1039,13 @@ impl<'a> Parser<'a> {
let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
self.parse_ty_param_bounds()?
} else {
P::new()
Vec::new()
};
let all_bounds =
Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
.chain(other_bounds.into_vec())
.chain(other_bounds)
.collect();
Ok(ast::TyKind::PolyTraitRef(all_bounds))
Ok(ast::TyKind::TraitObject(all_bounds))
}
}
@ -1128,7 +1128,7 @@ impl<'a> Parser<'a> {
self.expect_keyword(keywords::Const)?;
let ident = self.parse_ident()?;
self.expect(&token::Colon)?;
let ty = self.parse_ty_sum()?;
let ty = self.parse_ty()?;
let default = if self.check(&token::Eq) {
self.bump();
let expr = self.parse_expr()?;
@ -1244,30 +1244,30 @@ impl<'a> Parser<'a> {
/// Parse a possibly mutable type
pub fn parse_mt(&mut self) -> PResult<'a, MutTy> {
let mutbl = self.parse_mutability()?;
let t = self.parse_ty()?;
let t = self.parse_ty_no_plus()?;
Ok(MutTy { ty: t, mutbl: mutbl })
}
/// Parse optional return type [ -> TY ] in function decl
pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> {
if self.eat(&token::RArrow) {
Ok(FunctionRetTy::Ty(self.parse_ty()?))
Ok(FunctionRetTy::Ty(self.parse_ty_no_plus()?))
} else {
let pos = self.span.lo;
Ok(FunctionRetTy::Default(mk_sp(pos, pos)))
}
}
/// Parse a type in a context where `T1+T2` is allowed.
pub fn parse_ty_sum(&mut self) -> PResult<'a, P<Ty>> {
/// Parse a type.
pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
let lo = self.span.lo;
let lhs = self.parse_ty()?;
let lhs = self.parse_ty_no_plus()?;
if !self.eat(&token::BinOp(token::Plus)) {
return Ok(lhs);
}
let bounds = self.parse_ty_param_bounds()?;
let mut bounds = self.parse_ty_param_bounds()?;
// In type grammar, `+` is treated like a binary operator,
// and hence both L and R side are required.
@ -1277,14 +1277,66 @@ impl<'a> Parser<'a> {
"at least one type parameter bound \
must be specified");
}
if let TyKind::Path(None, ref path) = lhs.node {
let poly_trait_ref = PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: TraitRef { path: path.clone(), ref_id: lhs.id },
span: lhs.span,
};
let poly_trait_ref = TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None);
bounds.insert(0, poly_trait_ref);
} else {
let mut err = struct_span_err!(self.sess.span_diagnostic, lhs.span, E0178,
"expected a path on the left-hand side \
of `+`, not `{}`",
pprust::ty_to_string(&lhs));
err.span_label(lhs.span, &format!("expected a path"));
let hi = bounds.iter().map(|x| match *x {
ast::TraitTyParamBound(ref tr, _) => tr.span.hi,
ast::RegionTyParamBound(ref r) => r.span.hi,
}).max_by_key(|x| x.to_usize());
let full_span = hi.map(|hi| Span {
lo: lhs.span.lo,
hi: hi,
expn_id: lhs.span.expn_id,
});
match (&lhs.node, full_span) {
(&TyKind::Rptr(ref lifetime, ref mut_ty), Some(full_span)) => {
let ty_str = pprust::to_string(|s| {
use print::pp::word;
use print::pprust::PrintState;
word(&mut s.s, "&")?;
s.print_opt_lifetime(lifetime)?;
s.print_mutability(mut_ty.mutbl)?;
s.popen()?;
s.print_type(&mut_ty.ty)?;
s.print_bounds(" +", &bounds)?;
s.pclose()
});
err.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
ty_str);
}
_ => {
help!(&mut err,
"perhaps you forgot parentheses? (per RFC 438)");
}
}
err.emit();
}
let sp = mk_sp(lo, self.prev_span.hi);
let sum = ast::TyKind::ObjectSum(lhs, bounds);
let sum = TyKind::TraitObject(bounds);
Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}))
}
/// Parse a type.
pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
/// Parse a type in restricted contexts where `+` is not permitted.
/// Example 1: `&'a TYPE`
/// `+` is prohibited to maintain operator priority (P(+) < P(&)).
/// Example 2: `value1 as TYPE + value2`
/// `+` is prohibited to avoid interactions with expression grammar.
pub fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
maybe_whole!(self, NtTy, |x| x);
let lo = self.span.lo;
@ -1298,7 +1350,7 @@ impl<'a> Parser<'a> {
let mut ts = vec![];
let mut last_comma = false;
while self.token != token::CloseDelim(token::Paren) {
ts.push(self.parse_ty_sum()?);
ts.push(self.parse_ty()?);
if self.check(&token::Comma) {
last_comma = true;
self.bump();
@ -1323,7 +1375,7 @@ impl<'a> Parser<'a> {
} else if self.check(&token::OpenDelim(token::Bracket)) {
// VECTOR
self.expect(&token::OpenDelim(token::Bracket))?;
let t = self.parse_ty_sum()?;
let t = self.parse_ty()?;
// Parse the `; e` in `[ i32; e ]`
// where `e` is a const expression
@ -1404,7 +1456,7 @@ impl<'a> Parser<'a> {
`*mut T` or `*const T` as appropriate)");
Mutability::Immutable
};
let t = self.parse_ty()?;
let t = self.parse_ty_no_plus()?;
Ok(MutTy { ty: t, mutbl: mutbl })
}
@ -1451,7 +1503,7 @@ impl<'a> Parser<'a> {
})
};
let t = self.parse_ty_sum()?;
let t = self.parse_ty()?;
Ok(Arg {
ty: t,
@ -1469,7 +1521,7 @@ impl<'a> Parser<'a> {
pub fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
let pat = self.parse_pat()?;
let t = if self.eat(&token::Colon) {
self.parse_ty_sum()?
self.parse_ty()?
} else {
P(Ty {
id: ast::DUMMY_NODE_ID,
@ -1610,7 +1662,7 @@ impl<'a> Parser<'a> {
pub fn parse_qualified_path(&mut self, mode: PathStyle)
-> PResult<'a, (QSelf, ast::Path)> {
let span = self.prev_span;
let self_type = self.parse_ty_sum()?;
let self_type = self.parse_ty()?;
let mut path = if self.eat_keyword(keywords::As) {
self.parse_path(PathStyle::Type)?
} else {
@ -1711,8 +1763,8 @@ impl<'a> Parser<'a> {
let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?;
ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
types: types,
bindings: bindings,
}.into()
} else if self.eat(&token::OpenDelim(token::Paren)) {
let lo = self.prev_span.lo;
@ -1720,10 +1772,10 @@ impl<'a> Parser<'a> {
let inputs = self.parse_seq_to_end(
&token::CloseDelim(token::Paren),
SeqSep::trailing_allowed(token::Comma),
|p| p.parse_ty_sum())?;
|p| p.parse_ty())?;
let output_ty = if self.eat(&token::RArrow) {
Some(self.parse_ty()?)
Some(self.parse_ty_no_plus()?)
} else {
None
};
@ -1771,8 +1823,8 @@ impl<'a> Parser<'a> {
identifier: identifier,
parameters: ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
types: types,
bindings: bindings,
}.into(),
});
@ -2933,12 +2985,12 @@ impl<'a> Parser<'a> {
}
// Special cases:
if op == AssocOp::As {
let rhs = self.parse_ty()?;
let rhs = self.parse_ty_no_plus()?;
let (lo, hi) = (lhs_span.lo, rhs.span.hi);
lhs = self.mk_expr(lo, hi, ExprKind::Cast(lhs, rhs), ThinVec::new());
continue
} else if op == AssocOp::Colon {
let rhs = self.parse_ty()?;
let rhs = self.parse_ty_no_plus()?;
let (lo, hi) = (lhs_span.lo, rhs.span.hi);
lhs = self.mk_expr(lo, hi, ExprKind::Type(lhs, rhs), ThinVec::new());
continue
@ -3706,7 +3758,7 @@ impl<'a> Parser<'a> {
let mut ty = None;
if self.eat(&token::Colon) {
ty = Some(self.parse_ty_sum()?);
ty = Some(self.parse_ty()?);
}
let init = self.parse_initializer()?;
Ok(P(ast::Local {
@ -3727,7 +3779,7 @@ impl<'a> Parser<'a> {
-> PResult<'a, StructField> {
let name = self.parse_ident()?;
self.expect(&token::Colon)?;
let ty = self.parse_ty_sum()?;
let ty = self.parse_ty()?;
Ok(StructField {
span: mk_sp(lo, self.prev_span.hi),
ident: Some(name),
@ -4144,7 +4196,7 @@ impl<'a> Parser<'a> {
fn parse_colon_then_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds>
{
if !self.eat(&token::Colon) {
Ok(P::new())
Ok(Vec::new())
} else {
self.parse_ty_param_bounds()
}
@ -4190,7 +4242,7 @@ impl<'a> Parser<'a> {
}
}
return Ok(P::from_vec(result));
return Ok(result);
}
/// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?
@ -4202,7 +4254,7 @@ impl<'a> Parser<'a> {
let default = if self.check(&token::Eq) {
self.bump();
Some(self.parse_ty_sum()?)
Some(self.parse_ty()?)
} else {
None
};
@ -4297,7 +4349,7 @@ impl<'a> Parser<'a> {
let mut err = self.diagnostic().struct_span_err(self.span, &msg);
let span_hi = self.span.hi;
let span_hi = match self.parse_ty() {
let span_hi = match self.parse_ty_no_plus() {
Ok(..) => self.span.hi,
Err(ref mut err) => {
self.cancel(err);
@ -4320,14 +4372,14 @@ impl<'a> Parser<'a> {
if p.look_ahead(1, |t| t == &token::Eq) {
Ok(None)
} else {
Ok(Some(p.parse_ty_sum()?))
Ok(Some(p.parse_ty()?))
}
}
)?;
// If we found the `>`, don't continue.
if !returned {
return Ok((lifetimes, types.into_vec(), Vec::new()));
return Ok((lifetimes, types, Vec::new()));
}
// Then parse type bindings.
@ -4338,7 +4390,7 @@ impl<'a> Parser<'a> {
let lo = p.span.lo;
let ident = p.parse_ident()?;
p.expect(&token::Eq)?;
let ty = p.parse_ty()?;
let ty = p.parse_ty_no_plus()?;
let hi = ty.span.hi;
let span = mk_sp(lo, hi);
return Ok(TypeBinding{id: ast::DUMMY_NODE_ID,
@ -4348,7 +4400,7 @@ impl<'a> Parser<'a> {
});
}
)?;
Ok((lifetimes, types.into_vec(), bindings.into_vec()))
Ok((lifetimes, types, bindings))
}
fn forbid_lifetime(&mut self) -> PResult<'a, ()> {
@ -4436,7 +4488,7 @@ impl<'a> Parser<'a> {
vec![]
};
let bounded_ty = self.parse_ty()?;
let bounded_ty = self.parse_ty_no_plus()?;
if self.eat(&token::Colon) {
let bounds = self.parse_ty_param_bounds()?;
@ -4459,7 +4511,7 @@ impl<'a> Parser<'a> {
parsed_something = true;
} else if self.eat(&token::Eq) {
// let ty = try!(self.parse_ty());
// let ty = try!(self.parse_ty_no_plus());
let hi = self.prev_span.hi;
let span = mk_sp(lo, hi);
// where_clause.predicates.push(
@ -4631,7 +4683,7 @@ impl<'a> Parser<'a> {
// self: TYPE
let eself_ident = expect_ident(self);
if self.eat(&token::Colon) {
let ty = self.parse_ty_sum()?;
let ty = self.parse_ty()?;
(SelfKind::Explicit(ty, Mutability::Immutable), eself_ident)
} else {
(SelfKind::Value(Mutability::Immutable), eself_ident)
@ -4643,7 +4695,7 @@ impl<'a> Parser<'a> {
self.bump();
let eself_ident = expect_ident(self);
if self.eat(&token::Colon) {
let ty = self.parse_ty_sum()?;
let ty = self.parse_ty()?;
(SelfKind::Explicit(ty, Mutability::Mutable), eself_ident)
} else {
(SelfKind::Value(Mutability::Mutable), eself_ident)
@ -4800,14 +4852,14 @@ impl<'a> Parser<'a> {
let (name, node) = if self.eat_keyword(keywords::Type) {
let name = self.parse_ident()?;
self.expect(&token::Eq)?;
let typ = self.parse_ty_sum()?;
let typ = self.parse_ty()?;
self.expect(&token::Semi)?;
(name, ast::ImplItemKind::Type(typ))
} else if self.is_const_item() {
self.expect_keyword(keywords::Const)?;
let name = self.parse_ident()?;
self.expect(&token::Colon)?;
let typ = self.parse_ty_sum()?;
let typ = self.parse_ty()?;
self.expect(&token::Eq)?;
let expr = self.parse_expr()?;
self.expect(&token::Semi)?;
@ -4931,7 +4983,7 @@ impl<'a> Parser<'a> {
};
// Parse the trait.
let mut ty = self.parse_ty_sum()?;
let mut ty = self.parse_ty()?;
// Parse traits, if necessary.
let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
@ -4972,7 +5024,7 @@ impl<'a> Parser<'a> {
ItemKind::DefaultImpl(unsafety, opt_trait.unwrap()), None))
} else {
if opt_trait.is_some() {
ty = self.parse_ty_sum()?;
ty = self.parse_ty()?;
}
generics.where_clause = self.parse_where_clause()?;
@ -5124,7 +5176,7 @@ impl<'a> Parser<'a> {
let mut vis = p.parse_visibility(false)?;
let ty_is_interpolated =
p.token.is_interpolated() || p.look_ahead(1, |t| t.is_interpolated());
let mut ty = p.parse_ty_sum()?;
let mut ty = p.parse_ty()?;
// Handle `pub(path) type`, in which `vis` will be `pub` and `ty` will be `(path)`.
if vis == Visibility::Public && !ty_is_interpolated &&
@ -5132,7 +5184,7 @@ impl<'a> Parser<'a> {
ty = if let TyKind::Paren(ref path_ty) = ty.node {
if let TyKind::Path(None, ref path) = path_ty.node {
vis = Visibility::Restricted { path: P(path.clone()), id: path_ty.id };
Some(p.parse_ty_sum()?)
Some(p.parse_ty()?)
} else {
None
}
@ -5250,7 +5302,7 @@ impl<'a> Parser<'a> {
fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
let id = self.parse_ident()?;
self.expect(&token::Colon)?;
let ty = self.parse_ty_sum()?;
let ty = self.parse_ty()?;
self.expect(&token::Eq)?;
let e = self.parse_expr()?;
self.expect(&token::Semi)?;
@ -5491,7 +5543,7 @@ impl<'a> Parser<'a> {
let ident = self.parse_ident()?;
self.expect(&token::Colon)?;
let ty = self.parse_ty_sum()?;
let ty = self.parse_ty()?;
let hi = self.span.hi;
self.expect(&token::Semi)?;
Ok(ForeignItem {
@ -5580,7 +5632,7 @@ impl<'a> Parser<'a> {
let mut tps = self.parse_generics()?;
tps.where_clause = self.parse_where_clause()?;
self.expect(&token::Eq)?;
let ty = self.parse_ty_sum()?;
let ty = self.parse_ty()?;
self.expect(&token::Semi)?;
Ok((ident, ItemKind::Ty(ty, tps), None))
}

View File

@ -1009,7 +1009,7 @@ impl<'a> State<'a> {
ast::TyKind::BareFn(ref f) => {
let generics = ast::Generics {
lifetimes: f.lifetimes.clone(),
ty_params: P::new(),
ty_params: Vec::new(),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),
@ -1028,11 +1028,7 @@ impl<'a> State<'a> {
ast::TyKind::Path(Some(ref qself), ref path) => {
self.print_qpath(path, qself, false)?
}
ast::TyKind::ObjectSum(ref ty, ref bounds) => {
self.print_type(&ty)?;
self.print_bounds("+", &bounds[..])?;
}
ast::TyKind::PolyTraitRef(ref bounds) => {
ast::TyKind::TraitObject(ref bounds) => {
self.print_bounds("", &bounds[..])?;
}
ast::TyKind::ImplTrait(ref bounds) => {
@ -2849,11 +2845,13 @@ impl<'a> State<'a> {
..}) => {
self.print_lifetime_bounds(lifetime, bounds)?;
}
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
self.print_path(path, false, 0, false)?;
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
..}) => {
self.print_type(lhs_ty)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(&ty)?;
self.print_type(rhs_ty)?;
}
}
}
@ -2975,7 +2973,7 @@ impl<'a> State<'a> {
}
let generics = ast::Generics {
lifetimes: Vec::new(),
ty_params: P::new(),
ty_params: Vec::new(),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),

View File

@ -342,15 +342,11 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
}
visitor.visit_path(path, typ.id);
}
TyKind::ObjectSum(ref ty, ref bounds) => {
visitor.visit_ty(ty);
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyKind::Array(ref ty, ref expression) => {
visitor.visit_ty(ty);
visitor.visit_expr(expression)
}
TyKind::PolyTraitRef(ref bounds) => {
TyKind::TraitObject(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyKind::ImplTrait(ref bounds) => {
@ -508,12 +504,11 @@ pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics
visitor.visit_lifetime(lifetime);
walk_list!(visitor, visit_lifetime, bounds);
}
WherePredicate::EqPredicate(WhereEqPredicate{id,
ref path,
ref ty,
WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
ref rhs_ty,
..}) => {
visitor.visit_path(path, id);
visitor.visit_ty(ty);
visitor.visit_ty(lhs_ty);
visitor.visit_ty(rhs_ty);
}
}
}

View File

@ -507,9 +507,8 @@ impl<'a> TraitDef<'a> {
}
});
let Generics { mut lifetimes, ty_params, mut where_clause, span } = self.generics
let Generics { mut lifetimes, mut ty_params, mut where_clause, span } = self.generics
.to_generics(cx, self.span, type_ident, generics);
let mut ty_params = ty_params.into_vec();
// Copy the lifetimes
lifetimes.extend(generics.lifetimes.iter().cloned());
@ -533,7 +532,7 @@ impl<'a> TraitDef<'a> {
bounds.push((*declared_bound).clone());
}
cx.typaram(self.span, ty_param.ident, vec![], P::from_vec(bounds), None)
cx.typaram(self.span, ty_param.ident, vec![], bounds, None)
}));
// and similarly for where clauses
@ -558,8 +557,8 @@ impl<'a> TraitDef<'a> {
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
id: ast::DUMMY_NODE_ID,
span: self.span,
path: we.path.clone(),
ty: we.ty.clone(),
lhs_ty: we.lhs_ty.clone(),
rhs_ty: we.rhs_ty.clone(),
})
}
}
@ -596,7 +595,7 @@ impl<'a> TraitDef<'a> {
span: self.span,
bound_lifetimes: vec![],
bounded_ty: ty,
bounds: P::from_vec(bounds),
bounds: bounds,
};
let predicate = ast::WherePredicate::BoundPredicate(predicate);
@ -607,7 +606,7 @@ impl<'a> TraitDef<'a> {
let trait_generics = Generics {
lifetimes: lifetimes,
ty_params: P::from_vec(ty_params),
ty_params: ty_params,
where_clause: where_clause,
span: span,
};

View File

@ -212,7 +212,7 @@ fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>, s
-> Generics {
Generics {
lifetimes: lifetimes,
ty_params: P::from_vec(ty_params),
ty_params: ty_params,
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),

View File

@ -1,16 +0,0 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn foo(bar: i32+std::fmt::Display) {}
//~^ ERROR E0172
//~| NOTE expected a trait
fn main() {
}

View File

@ -17,12 +17,15 @@ struct Bar<'a> {
x: &'a Foo + 'a,
//~^ ERROR E0178
//~| NOTE expected a path
//~| ERROR at least one non-builtin trait is required for an object type
y: &'a mut Foo + 'a,
//~^ ERROR E0178
//~| NOTE expected a path
//~| ERROR at least one non-builtin trait is required for an object type
z: fn() -> Foo + 'a,
//~^ ERROR E0178
//~| NOTE expected a path
//~| ERROR at least one non-builtin trait is required for an object type
}
fn main() {

View File

@ -11,6 +11,6 @@
struct Foo;
fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected a reference to a trait
fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected trait, found struct `Foo`
fn main() { }

View File

@ -13,8 +13,10 @@ fn main() {
//~^ ERROR expected a path
//~| HELP try adding parentheses
//~| SUGGESTION let _: &(Copy + 'static);
//~| ERROR at least one non-builtin trait is required for an object type
let _: &'static Copy + 'static;
//~^ ERROR expected a path
//~| HELP try adding parentheses
//~| SUGGESTION let _: &'static (Copy + 'static);
//~| ERROR at least one non-builtin trait is required for an object type
}

View File

@ -16,10 +16,10 @@ trait Tr {
}
impl Tr for isize { }
fn foo<'a>(x: Box<Tr+ Sync + 'a>) -> Box<Tr+ Sync + 'a> { x }
fn foo<'a>(x: Box< Tr + Sync + 'a>) -> Box< Tr + Sync + 'a> { x }
fn main() {
let x: Box<Tr+ Sync>;
let x: Box< Tr + Sync>;
Box::new(1isize) as Box<Tr+ Sync>;
Box::new(1isize) as Box< Tr + Sync>;
}