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) => {
+ TyObjectSum(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyImplTrait(ref bounds) => {
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),
let expr = self.lower_expr(expr);
hir::TyTypeof(self.record_body(expr, None))
}
- TyKind::PolyTraitRef(ref bounds) => {
- hir::TyPolyTraitRef(self.lower_bounds(bounds))
+ TyKind::ObjectSum(ref bounds) => {
+ hir::TyObjectSum(self.lower_bounds(bounds))
}
TyKind::ImplTrait(ref bounds) => {
hir::TyImplTrait(self.lower_bounds(bounds))
///
/// 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.
+ TyObjectSum(TyParamBounds),
+ /// An `impl Bound1 + Bound2 + Bound3` type
+ /// where `Bound` is a trait or a lifetime.
TyImplTrait(TyParamBounds),
/// Unused for now
TyTypeof(BodyId),
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::TyObjectSum(ref bounds) => {
self.print_bounds("", &bounds[..])?;
}
hir::TyImplTrait(ref bounds) => {
SawTyTup,
SawTyPath,
SawTyObjectSum,
- SawTyPolyTraitRef,
SawTyImplTrait,
SawTyTypeof,
SawTyInfer
TyTup(..) => SawTyTup,
TyPath(_) => SawTyPath,
TyObjectSum(..) => SawTyObjectSum,
- TyPolyTraitRef(..) => SawTyPolyTraitRef,
TyImplTrait(..) => SawTyImplTrait,
TyTypeof(..) => SawTyTypeof,
TyInfer => SawTyInfer
err.emit();
});
}
- TyKind::ObjectSum(_, ref bounds) |
- TyKind::PolyTraitRef(ref bounds) => {
+ TyKind::ObjectSum(ref bounds) => {
self.no_questions_in_bounds(bounds, "trait object types", false);
}
_ => {}
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> {
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>)
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),
}
tcx.mk_fn_ptr(bare_fn_ty)
}
- hir::TyPolyTraitRef(ref bounds) => {
+ hir::TyObjectSum(ref bounds) => {
self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
}
hir::TyImplTrait(ref bounds) => {
```
"##,
-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.
// 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,
// _
Infer,
- // for<'a> Foo(&'a)
- PolyTraitRef(Vec<TyParamBound>),
-
// impl TraitA+TraitB
ImplTrait(Vec<TyParamBound>),
}
trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
}
}
- TyObjectSum(ref lhs, ref bounds) => {
- let lhs_ty = lhs.clean(cx);
+ TyObjectSum(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),
}
}
}
- 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() {
///
/// 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.
+ ObjectSum(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>),
// 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.
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,
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)
});
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::ObjectSum(bounds) => {
+ TyKind::ObjectSum(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)))
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;
Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
.chain(other_bounds.into_vec())
.collect();
- Ok(ast::TyKind::PolyTraitRef(all_bounds))
+ Ok(ast::TyKind::ObjectSum(all_bounds))
}
}
return Ok(lhs);
}
- let bounds = self.parse_ty_param_bounds()?;
+ let mut bounds = self.parse_ty_param_bounds()?.into_vec();
// In type grammar, `+` is treated like a binary operator,
// and hence both L and R side are required.
"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::ObjectSum(bounds.into());
Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}))
}
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::ObjectSum(ref bounds) => {
self.print_bounds("", &bounds[..])?;
}
ast::TyKind::ImplTrait(ref bounds) => {
}
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::ObjectSum(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyKind::ImplTrait(ref bounds) => {
+++ /dev/null
-// 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() {
-}
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() {
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() { }
//~^ 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
}
}
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>;
}