diff --git a/src/librustc/hir/fold.rs b/src/librustc/hir/fold.rs index 5e0e6622185f8b50336cc4409b033a5be0f4793b..dd79e14f077e831c5949797dd4b62c4fc08c7bef 100644 --- a/src/librustc/hir/fold.rs +++ b/src/librustc/hir/fold.rs @@ -375,6 +375,9 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyPolyTraitRef(bounds) => { TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b))) } + TyImplTrait(bounds) => { + TyImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b))) + } }, span: fld.new_span(span), } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index aded220c0cdfe6893c854a8c734a560606cd6bff..1162c290f9cfca675f63b14bb52fef53e050e59e 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -427,6 +427,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { TyPolyTraitRef(ref bounds) => { walk_list!(visitor, visit_ty_param_bound, bounds); } + TyImplTrait(ref bounds) => { + walk_list!(visitor, visit_ty_param_bound, bounds); + } TyTypeof(ref expression) => { visitor.visit_expr(expression) } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 789b70ccfa412998157b36c220c0715baafc33e3..eb98ed77da703df241719e57999b9c37a460930d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -293,8 +293,10 @@ fn lower_ty(&mut self, t: &Ty) -> P { hir::TyTypeof(self.lower_expr(expr)) } PolyTraitRef(ref bounds) => { - let bounds = bounds.iter().map(|b| self.lower_ty_param_bound(b)).collect(); - hir::TyPolyTraitRef(bounds) + hir::TyPolyTraitRef(self.lower_bounds(bounds)) + } + ImplTrait(ref bounds) => { + hir::TyImplTrait(self.lower_bounds(bounds)) } Mac(_) => panic!("TyMac should have been expanded by now."), }, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 9212fda6502532e1ab5fc75e466fac752334ad14..707ef987c2c06e1518c466bccad774f5a9765732 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1132,6 +1132,8 @@ pub enum Ty_ { TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` TyPolyTraitRef(TyParamBounds), + /// An `impl TraitA+TraitB` type. + TyImplTrait(TyParamBounds), /// Unused for now TyTypeof(P), /// TyInfer means the type should be inferred instead of it having been diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 5f2fac5c01b30df8b719ef301e13cafde1a1cbbd..6dedae5ccd75d2761321976ae5a260c343ab7315 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -536,6 +536,9 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> { hir::TyPolyTraitRef(ref bounds) => { self.print_bounds("", &bounds[..])?; } + hir::TyImplTrait(ref bounds) => { + self.print_bounds("impl ", &bounds[..])?; + } hir::TyFixedLengthVec(ref ty, ref v) => { word(&mut self.s, "[")?; self.print_type(&ty)?; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 26ea4890b30bf1ef52339e66f118d9ba023a7375..37af778d5556876b5e599488ea01ca8b554b30a8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1492,6 +1492,9 @@ pub enum Type { // for<'a> Foo(&'a) PolyTraitRef(Vec), + + // impl TraitA+TraitB + ImplTrait(Vec), } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)] @@ -1777,6 +1780,7 @@ fn clean(&self, cx: &DocContext) -> Type { } 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), } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index eed2615175b27a62ce77ce4debd5a2de1aff430e..854ca57e8556c72a606a0f4e49c2de298c3e9c22 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -539,6 +539,16 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } Ok(()) } + clean::ImplTrait(ref bounds) => { + write!(f, "impl ")?; + for (i, bound) in bounds.iter().enumerate() { + if i != 0 { + write!(f, " + ")?; + } + write!(f, "{}", *bound)?; + } + Ok(()) + } // It's pretty unsightly to look at `::C` in output, and // we've got hyperlinking on our side, so try to avoid longer // notation as much as possible by making `C` a hyperlink to trait diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a8bb255fba4a4d4b099c936239dee1abdc7fee7c..3f929e6d23aea0cedcd5eda3d8aa9256e7a3ae5e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1368,6 +1368,8 @@ pub enum TyKind { ObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` PolyTraitRef(TyParamBounds), + /// An `impl TraitA+TraitB` type. + ImplTrait(TyParamBounds), /// No-op; kept solely so that we can pretty-print faithfully Paren(P), /// Unused for now diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 29da0fb1a2735aa14c4ac71633ac9be97f9b9ebb..f550e7d2a0515e1f2da1f7599a1746d9a0bebd93 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -277,7 +277,10 @@ pub fn new() -> Features { (active, cfg_target_has_atomic, "1.9.0", Some(32976)), // Allows `..` in tuple (struct) patterns - (active, dotdot_in_tuple_patterns, "1.10.0", Some(33627)) + (active, dotdot_in_tuple_patterns, "1.10.0", Some(33627)), + + // Allows `impl Trait` in function return types. + (active, conservative_impl_trait, "1.12.0", Some(34511)) ); declare_features! ( @@ -952,6 +955,10 @@ fn visit_ty(&mut self, ty: &ast::Ty) { ast::TyKind::BareFn(ref bare_fn_ty) => { self.check_abi(bare_fn_ty.abi, ty.span); } + ast::TyKind::ImplTrait(..) => { + gate_feature_post!(&self, conservative_impl_trait, ty.span, + "`impl Trait` is experimental"); + } _ => {} } visit::walk_ty(self, ty) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index ac3d643b185cac725fd7139d14ae4541970a3be6..afc990f498e6f824d5502292a77a80f1ec18f778 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -397,6 +397,9 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyKind::PolyTraitRef(bounds) => { TyKind::PolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b))) } + TyKind::ImplTrait(bounds) => { + TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b))) + } TyKind::Mac(mac) => { TyKind::Mac(fld.fold_mac(mac)) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c143e190c6fc16ce814c785d88aab8e0d5889974..1b32632a06f4e2b2997df194f7029387231fffa0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1051,7 +1051,7 @@ pub fn get_lifetime(&mut self) -> ast::Ident { pub fn parse_for_in_type(&mut self) -> PResult<'a, TyKind> { /* Parses whatever can come after a `for` keyword in a type. - The `for` has already been consumed. + The `for` hasn't been consumed. Deprecated: @@ -1091,6 +1091,23 @@ pub fn parse_for_in_type(&mut self) -> PResult<'a, TyKind> { } } + pub fn parse_impl_trait_type(&mut self) -> PResult<'a, TyKind> { + /* + Parses whatever can come after a `impl` keyword in a type. + The `impl` has already been consumed. + */ + + let bounds = self.parse_ty_param_bounds(BoundParsingMode::Modified)?; + + if !bounds.iter().any(|b| if let TraitTyParamBound(..) = *b { true } else { false }) { + let last_span = self.last_span; + self.span_err(last_span, "at least one trait must be specified"); + } + + Ok(ast::TyKind::ImplTrait(bounds)) + } + + pub fn parse_ty_path(&mut self) -> PResult<'a, TyKind> { Ok(TyKind::Path(None, self.parse_path(PathStyle::Type)?)) } @@ -1406,6 +1423,8 @@ pub fn parse_ty(&mut self) -> PResult<'a, P> { self.parse_borrowed_pointee()? } else if self.check_keyword(keywords::For) { self.parse_for_in_type()? + } else if self.eat_keyword(keywords::Impl) { + self.parse_impl_trait_type()? } else if self.token_is_bare_fn_keyword() { // BARE FUNCTION self.parse_ty_bare_fn(Vec::new())? diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a619da84b2d510529d679312641bf89b257b50e0..62e55eb78b72383eda8accaa5bbbec407af72564 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1018,6 +1018,9 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> { ast::TyKind::PolyTraitRef(ref bounds) => { try!(self.print_bounds("", &bounds[..])); } + ast::TyKind::ImplTrait(ref bounds) => { + try!(self.print_bounds("impl ", &bounds[..])); + } ast::TyKind::FixedLengthVec(ref ty, ref v) => { try!(word(&mut self.s, "[")); try!(self.print_type(&ty)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 1fc4e54d21807c26145f6d10e98e7d85f34eed15..6d3cdbdc6da7cc414e63de5ef5bcf4f0023ee849 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -343,6 +343,9 @@ pub fn walk_ty(visitor: &mut V, typ: &Ty) { TyKind::PolyTraitRef(ref bounds) => { walk_list!(visitor, visit_ty_param_bound, bounds); } + TyKind::ImplTrait(ref bounds) => { + walk_list!(visitor, visit_ty_param_bound, bounds); + } TyKind::Typeof(ref expression) => { visitor.visit_expr(expression) }