]> git.lizzy.rs Git - rust.git/commitdiff
AST/HIR: Merge ObjectSum and PolyTraitRef
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Mon, 16 Jan 2017 20:33:45 +0000 (23:33 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Mon, 16 Jan 2017 22:52:47 +0000 (01:52 +0300)
22 files changed:
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_passes/ast_validation.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/diagnostics.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/libsyntax/ast.rs
src/libsyntax/diagnostic_list.rs
src/libsyntax/ext/build.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/test/compile-fail/E0172.rs [deleted file]
src/test/compile-fail/E0178.rs
src/test/compile-fail/trait-bounds-not-on-struct.rs
src/test/compile-fail/trait-object-reference-without-parens-suggestion.rs
src/test/pretty/path-type-bounds.rs

index c244c33728c7a7a863faea743f16ca4d5de2dc47..001a5f6e586125e6423dcef5102144cf5276d644 100644 (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) => {
+        TyObjectSum(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
         TyImplTrait(ref bounds) => {
index bdd54c547e3e8c5e2bd9382dcfd440c660cac648..9a0ef6537ce3a30ca14e9bf1bddeed840bdb0d64 100644 (file)
@@ -308,9 +308,6 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
                         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 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::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))
index 075358c576ceff0314beb8d124208680a25197b5..c3ae0e3f276c4ba25b77b215e66df9e399e19c27 100644 (file)
@@ -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.
+    TyObjectSum(TyParamBounds),
+    /// An `impl Bound1 + Bound2 + Bound3` type
+    /// where `Bound` is a trait or a lifetime.
     TyImplTrait(TyParamBounds),
     /// Unused for now
     TyTypeof(BodyId),
index b84a33083156653f9be6a1b515d8008e9f26b7fa..c314145721f1081c76a22237cf83924ef417212c 100644 (file)
@@ -418,11 +418,7 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
             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) => {
index 4bb12667bbc147f861ed2583909c9758c89fcef0..c2abba5cce3f8e54391594df37e6f2fb470b1ada 100644 (file)
@@ -441,7 +441,6 @@ enum SawTyComponent {
     SawTyTup,
     SawTyPath,
     SawTyObjectSum,
-    SawTyPolyTraitRef,
     SawTyImplTrait,
     SawTyTypeof,
     SawTyInfer
@@ -458,7 +457,6 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
       TyTup(..) => SawTyTup,
       TyPath(_) => SawTyPath,
       TyObjectSum(..) => SawTyObjectSum,
-      TyPolyTraitRef(..) => SawTyPolyTraitRef,
       TyImplTrait(..) => SawTyImplTrait,
       TyTypeof(..) => SawTyTypeof,
       TyInfer => SawTyInfer
index 52bdd014933b8d6438949a179e1afe5cbe041d7a..e38fcbb5f6b05892ea248732906c0696e4a90617 100644 (file)
@@ -143,8 +143,7 @@ fn visit_ty(&mut self, ty: &'a Ty) {
                     err.emit();
                 });
             }
-            TyKind::ObjectSum(_, ref bounds) |
-            TyKind::PolyTraitRef(ref bounds) => {
+            TyKind::ObjectSum(ref bounds) => {
                 self.no_questions_in_bounds(bounds, "trait object types", false);
             }
             _ => {}
index bc984949fc69d0438432a85c38151a60c47dfa7b..bcb82c85f2485b4c67c5a6e1db3974e89c6e5cfb 100644 (file)
@@ -73,7 +73,7 @@
 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 @@ fn ast_path_to_ty(&self,
         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>)
@@ -1534,9 +1453,6 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'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),
@@ -1609,7 +1525,7 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 }
                 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) => {
index 1a971be64d81923d528313df3b01b0d892c7f251..3617b1f0a7de97722230bcfe6f18496f3559d072 100644 (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 @@ fn main() {
 //  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,
index 71165cd3f40c36817fe00f045576688e8827f8d0..77ca6ef34b875f51ecf0867ca1da76fd1c26afea 100644 (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 @@ fn clean(&self, cx: &DocContext) -> Type {
                     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),
index 716ad05401d03036a459da76f97ccdcc89ab4f3b..d25c4184f3cf9f816d58ae4960355d2eecf8687d 100644 (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() {
index 52f9ec30aec066532e5ee2897ffd42dff751449a..6c69aa14bcf96dcefccd615eae84e1d4747e054c 100644 (file)
@@ -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.
+    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>),
index 9110e989a8a1491f6d1f884a78d79e06790c1241..2b4d13375046e851c7910765114ce16d38a32f4c 100644 (file)
 // 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.
 
index 688df96ffa32fcfde245a767a0aa69001b243acc..fc3cbf20fb955f88613a38274ab8ad7c9346a381 100644 (file)
@@ -54,7 +54,6 @@ fn qpath_all(&self, self_type: P<ast::Ty>,
 
     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,
@@ -403,12 +402,6 @@ fn ty_path(&self, path: ast::Path) -> P<ast::Ty> {
         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)
index 1d9abebc7b81f169c1c321bb95c0ec5645b9ea02..8b045f1b53002cd93a8c6282b816453144749715 100644 (file)
@@ -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::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)))
index 167fa78d7e07500fdd861d6d7b03caff5a4ac486..bae08da0a640c5ab24a064bebe943c5375f1379a 100644 (file)
@@ -40,7 +40,7 @@
 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;
@@ -1045,7 +1045,7 @@ pub fn parse_for_in_type(&mut self) -> PResult<'a, TyKind> {
                 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))
         }
     }
 
@@ -1267,7 +1267,7 @@ pub fn parse_ty_sum(&mut self) -> PResult<'a, P<Ty>> {
             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.
@@ -1277,9 +1277,57 @@ pub fn parse_ty_sum(&mut self) -> PResult<'a, P<Ty>> {
                           "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}))
     }
 
index f6ed2350105a93272f4f5439157fe239ee0bc280..31e6f25559dec47b954b50a3e2ae6d8ab1e53c7d 100644 (file)
@@ -1028,11 +1028,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
             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) => {
index cc6ba7adf1a6a9661ca921b86871e0278dd4a2de..b0d7a2518036fccff1cdd2df296550b7e875fc2e 100644 (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::ObjectSum(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
         TyKind::ImplTrait(ref bounds) => {
diff --git a/src/test/compile-fail/E0172.rs b/src/test/compile-fail/E0172.rs
deleted file mode 100644 (file)
index 485a31d..0000000
+++ /dev/null
@@ -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() {
-}
index 6527465e0b7f74631c17a159fe5ca41f289b9cbb..ffc5940c95c98c8bae7412b955d0c06545f08b3d 100644 (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() {
index 081efa429c3e43c1d233de5f61ebd53fd5209be3..cabe0fd48edf99d0124ef40e19b45060f8ec4cf0 100644 (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() { }
index fc2ed83b2724d0a2d0be5e9b2b04ab1ca592fb28..c009644c5619fe09447ba5067d2934b960ee658e 100644 (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
 }
index 06d57b261e6864c3e4e78ea7b2a9077574f14c59..651d2b67941cb9ffbdd442d9e035b528948cb0d7 100644 (file)
@@ -16,10 +16,10 @@ fn dummy(&self) { }
 }
 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>;
 }