diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 6e77b0a7c7936..d2bf7f1e15ab4 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -85,7 +85,7 @@ pub struct Formatter<'a> { width: Option, precision: Option, - buf: &'a mut FormatWriter+'a, + buf: &'a mut (FormatWriter+'a), curarg: slice::Items<'a, Argument<'a>>, args: &'a [Argument<'a>], } @@ -565,7 +565,7 @@ impl<'a, Sized? T: Show> Show for &'a T { impl<'a, Sized? T: Show> Show for &'a mut T { fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) } } -impl<'a> Show for &'a Show+'a { +impl<'a> Show for &'a (Show+'a) { fn fmt(&self, f: &mut Formatter) -> Result { (*self).fmt(f) } } @@ -724,7 +724,7 @@ macro_rules! tuple ( tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, } -impl<'a> Show for &'a any::Any+'a { +impl<'a> Show for &'a (any::Any+'a) { fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") } } diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index afbb18faa0b9f..1873213fadf1d 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -145,5 +145,7 @@ register_diagnostics!( E0166, E0167, E0168, - E0169 + E0169, + E0170, + E0171 ) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 9fe7a21243f18..1dbd170a0d997 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -421,7 +421,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { match ty.node { - ast::TyPath(_, _, id) => self.check_def(ty.span, ty.id, id), + ast::TyPath(_, id) => self.check_def(ty.span, ty.id, id), _ => (), } visit::walk_ty(self, ty); diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 7e4d2621f1837..8c21e559ec1f8 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1230,10 +1230,9 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_name(rbml_w, item.ident.name); encode_attributes(rbml_w, item.attrs.as_slice()); match ty.node { - ast::TyPath(ref path, ref bounds, _) if path.segments + ast::TyPath(ref path, _) if path.segments .len() == 1 => { let ident = path.segments.last().unwrap().identifier; - assert!(bounds.is_none()); encode_impl_type_basename(rbml_w, ident); } _ => {} diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 656feb51a1d3c..5ab3978b8a8f7 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -295,7 +295,7 @@ impl OverloadedCallType { pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> { typer: &'t TYPER, mc: mc::MemCategorizationContext<'t,TYPER>, - delegate: &'d mut Delegate<'tcx>+'d, + delegate: &'d mut (Delegate<'tcx>+'d), } // If the TYPER results in an error, it's because the type check diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 66c782877f9ca..ec939d19b7240 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -243,7 +243,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // * Private trait impls for private types can be completely ignored ast::ItemImpl(_, _, ref ty, ref impl_items) => { let public_ty = match ty.node { - ast::TyPath(_, _, id) => { + ast::TyPath(_, id) => { match self.tcx.def_map.borrow()[id].clone() { def::DefPrimTy(..) => true, def => { @@ -311,7 +311,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { ast::ItemTy(ref ty, _) if public_first => { match ty.node { - ast::TyPath(_, _, id) => { + ast::TyPath(_, id) => { match self.tcx.def_map.borrow()[id].clone() { def::DefPrimTy(..) | def::DefTyParam(..) => {}, def => { @@ -616,7 +616,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // was private. ast::ItemImpl(_, _, ref ty, _) => { let id = match ty.node { - ast::TyPath(_, _, id) => id, + ast::TyPath(_, id) => id, _ => return Some((err_span, err_msg, None)), }; let def = self.tcx.def_map.borrow()[id].clone(); @@ -1292,7 +1292,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> { fn visit_ty(&mut self, ty: &ast::Ty) { match ty.node { - ast::TyPath(_, _, path_id) => { + ast::TyPath(_, path_id) => { if self.inner.path_is_private_type(path_id) { self.contains_private = true; // found what we're looking for so let's stop @@ -1493,7 +1493,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { fn visit_ty(&mut self, t: &ast::Ty) { match t.node { - ast::TyPath(ref p, _, path_id) => { + ast::TyPath(ref p, path_id) => { if !self.tcx.sess.features.borrow().visible_private_types && self.path_is_private_type(path_id) { self.tcx.sess.span_err(p.span, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 68a31c83ea484..bdb3edef6bdcc 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -63,7 +63,7 @@ use syntax::ast::{PolyTraitRef, PrimTy, Public, SelfExplicit, SelfStatic}; use syntax::ast::{RegionTyParamBound, StmtDecl, StructField}; use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound}; use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32}; -use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt}; +use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum}; use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyProc, TyQPath}; use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint}; use syntax::ast::{TypeImplItem, UnnamedField}; @@ -1396,29 +1396,53 @@ impl<'a> Resolver<'a> { // methods within to a new module, if the type was defined // within this module. - // Create the module and add all methods. - match ty.node { - TyPath(ref path, _, _) if path.segments.len() == 1 => { + let mod_name = match ty.node { + TyPath(ref path, _) if path.segments.len() == 1 => { // FIXME(18446) we should distinguish between the name of // a trait and the name of an impl of that trait. - let mod_name = path.segments.last().unwrap().identifier.name; + Some(path.segments.last().unwrap().identifier.name) + } + TyObjectSum(ref lhs_ty, _) => { + match lhs_ty.node { + TyPath(ref path, _) if path.segments.len() == 1 => { + Some(path.segments.last().unwrap().identifier.name) + } + _ => { + None + } + } + } + _ => { + None + } + }; + match mod_name { + None => { + self.resolve_error(ty.span, + "inherent implementations may \ + only be implemented in the same \ + module as the type they are \ + implemented for") + } + Some(mod_name) => { + // Create the module and add all methods. let parent_opt = parent.module().children.borrow() - .get(&mod_name).cloned(); + .get(&mod_name).cloned(); let new_parent = match parent_opt { // It already exists Some(ref child) if child.get_module_if_available() - .is_some() && - (child.get_module().kind.get() == ImplModuleKind || - child.get_module().kind.get() == TraitModuleKind) => { - ModuleReducedGraphParent(child.get_module()) - } + .is_some() && + (child.get_module().kind.get() == ImplModuleKind || + child.get_module().kind.get() == TraitModuleKind) => { + ModuleReducedGraphParent(child.get_module()) + } Some(ref child) if child.get_module_if_available() - .is_some() && - child.get_module().kind.get() == - EnumModuleKind => { - ModuleReducedGraphParent(child.get_module()) - } + .is_some() && + child.get_module().kind.get() == + EnumModuleKind => { + ModuleReducedGraphParent(child.get_module()) + } // Create the module _ => { let name_bindings = @@ -1433,7 +1457,7 @@ impl<'a> Resolver<'a> { let ns = TypeNS; let is_public = !name_bindings.defined_in_namespace(ns) || - name_bindings.defined_in_public_namespace(ns); + name_bindings.defined_in_public_namespace(ns); name_bindings.define_module(parent_link, Some(def_id), @@ -1459,21 +1483,21 @@ impl<'a> Resolver<'a> { ForbidDuplicateValues, method.span); let def = match method.pe_explicit_self() - .node { - SelfStatic => { - // Static methods become - // `DefStaticMethod`s. - DefStaticMethod(local_def(method.id), - FromImpl(local_def(item.id))) - } - _ => { - // Non-static methods become - // `DefMethod`s. - DefMethod(local_def(method.id), - None, - FromImpl(local_def(item.id))) - } - }; + .node { + SelfStatic => { + // Static methods become + // `DefStaticMethod`s. + DefStaticMethod(local_def(method.id), + FromImpl(local_def(item.id))) + } + _ => { + // Non-static methods become + // `DefMethod`s. + DefMethod(local_def(method.id), + None, + FromImpl(local_def(item.id))) + } + }; // NB: not IMPORTABLE let modifiers = if method.pe_vis() == ast::Public { @@ -1496,7 +1520,7 @@ impl<'a> Resolver<'a> { ForbidDuplicateTypesAndModules, typedef.span); let def = DefAssociatedTy(local_def( - typedef.id)); + typedef.id)); // NB: not IMPORTABLE let modifiers = if typedef.vis == ast::Public { PUBLIC @@ -1511,13 +1535,6 @@ impl<'a> Resolver<'a> { } } } - _ => { - self.resolve_error(ty.span, - "inherent implementations may \ - only be implemented in the same \ - module as the type they are \ - implemented for") - } } parent @@ -4725,7 +4742,7 @@ impl<'a> Resolver<'a> { // type, the result will be that the type name resolves to a module but not // a type (shadowing any imported modules or types with this name), leading // to weird user-visible bugs. So we ward this off here. See #15060. - TyPath(ref path, _, path_id) => { + TyPath(ref path, path_id) => { match self.def_map.borrow().get(&path_id) { // FIXME: should we catch other options and give more precise errors? Some(&DefMod(_)) => { @@ -4891,7 +4908,7 @@ impl<'a> Resolver<'a> { // Like path expressions, the interpretation of path types depends // on whether the path has multiple elements in it or not. - TyPath(ref path, ref bounds, path_id) => { + TyPath(ref path, path_id) => { // This is a path in the type namespace. Walk through scopes // looking for it. let mut result_def = None; @@ -4961,11 +4978,12 @@ impl<'a> Resolver<'a> { self.resolve_error(ty.span, msg.as_slice()); } } + } - bounds.as_ref().map(|bound_vec| { - self.resolve_type_parameter_bounds(ty.id, bound_vec, + TyObjectSum(ref ty, ref bound_vec) => { + self.resolve_type(&**ty); + self.resolve_type_parameter_bounds(ty.id, bound_vec, TraitBoundingTypeParameter); - }); } TyQPath(ref qpath) => { @@ -5602,7 +5620,7 @@ impl<'a> Resolver<'a> { fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks) -> Option<(Path, NodeId, FallbackChecks)> { match t.node { - TyPath(ref path, _, node_id) => Some((path.clone(), node_id, allow)), + TyPath(ref path, node_id) => Some((path.clone(), node_id, allow)), TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics), TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow), // This doesn't handle the remaining `Ty` variants as they are not diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index fae64ff924274..02e353d6b1fdd 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -162,7 +162,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { visit::walk_ty(this, ty); }); } - ast::TyPath(ref path, ref opt_bounds, id) => { + ast::TyPath(ref path, id) => { // if this path references a trait, then this will resolve to // a trait ref, which introduces a binding scope. match self.def_map.borrow().get(&id) { @@ -170,13 +170,6 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { self.with(LateScope(&Vec::new(), self.scope), |this| { this.visit_path(path, id); }); - - match *opt_bounds { - Some(ref bounds) => { - visit::walk_ty_param_bounds_helper(self, bounds); - } - None => { } - } } _ => { visit::walk_ty(self, ty); diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index d1cc851c41f20..8658a5248ccc2 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -43,7 +43,7 @@ use util::ppaux::Repr; pub struct SelectionContext<'cx, 'tcx:'cx> { infcx: &'cx InferCtxt<'cx, 'tcx>, param_env: &'cx ty::ParameterEnvironment<'tcx>, - typer: &'cx Typer<'tcx>+'cx, + typer: &'cx (Typer<'tcx>+'cx), /// Skolemizer used specifically for skolemizing entries on the /// obligation stack. This ensures that all entries on the stack diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index fd5b1bd4793b5..0a5ae10dd0142 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -59,8 +59,9 @@ use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope, ShiftedRscope, BindingRscope}; use middle::typeck::rscope; use middle::typeck::TypeAndSubsts; +use util::common::ErrorReported; use util::nodemap::DefIdMap; -use util::ppaux::{Repr, UserString}; +use util::ppaux::{mod, Repr, UserString}; use std::rc::Rc; use std::iter::AdditiveIterator; @@ -585,7 +586,7 @@ fn check_path_args(tcx: &ty::ctxt, pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty) -> Option> { match ast_ty.node { - ast::TyPath(ref path, _, id) => { + ast::TyPath(ref path, id) => { let a_def = match tcx.def_map.borrow().get(&id) { None => { tcx.sess.span_bug(ast_ty.span, @@ -642,7 +643,7 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( } match ast_ty.node { - ast::TyPath(ref path, _, id) => { + ast::TyPath(ref path, id) => { let a_def = match this.tcx().def_map.borrow().get(&id) { None => { this.tcx() @@ -682,64 +683,92 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( } } -// Handle `~`, `Box`, and `&` being able to mean strs and vecs. -// If a_seq_ty is a str or a vec, make it a str/vec. -// Also handle first-class trait types. -fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( - this: &AC, - rscope: &RS, - a_seq_mutbl: ast::Mutability, - a_seq_ty: &ast::Ty, - region: ty::Region, - constr: |Ty<'tcx>| -> Ty<'tcx>) - -> Ty<'tcx> +fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, + rscope: &RS, + ty: &ast::Ty, + bounds: &[ast::TyParamBound]) + -> Result, ErrorReported> + where AC : AstConv<'tcx>, RS : RegionScope { - let tcx = this.tcx(); - - debug!("mk_pointer(region={}, a_seq_ty={})", - region, - a_seq_ty.repr(tcx)); + /*! + * In a type like `Foo + Send`, we want to wait to collect the + * full set of bounds before we make the object type, because we + * need them to infer a region bound. (For example, if we tried + * made a type from just `Foo`, then it wouldn't be enough to + * infer a 'static bound, and hence the user would get an error.) + * So this function is used when we're dealing with a sum type to + * convert the LHS. It only accepts a type that refers to a trait + * name, and reports an error otherwise. + */ - match a_seq_ty.node { - ast::TyVec(ref ty) => { - let ty = ast_ty_to_ty(this, rscope, &**ty); - return constr(ty::mk_vec(tcx, ty, None)); + match ty.node { + ast::TyPath(ref path, id) => { + match this.tcx().def_map.borrow().get(&id) { + Some(&def::DefTrait(trait_def_id)) => { + return Ok(ast_path_to_trait_ref(this, + rscope, + trait_def_id, + None, + path)); + } + _ => { + span_err!(this.tcx().sess, ty.span, E0170, "expected a reference to a trait"); + Err(ErrorReported) + } + } } - ast::TyPath(ref path, ref opt_bounds, id) => { - // Note that the "bounds must be empty if path is not a trait" - // restriction is enforced in the below case for ty_path, which - // will run after this as long as the path isn't a trait. - match tcx.def_map.borrow().get(&id) { - Some(&def::DefPrimTy(ast::TyStr)) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - return ty::mk_str_slice(tcx, region, a_seq_mutbl); + _ => { + span_err!(this.tcx().sess, ty.span, E0171, + "expected a path on the left-hand side of `+`, not `{}`", + pprust::ty_to_string(ty)); + match ty.node { + ast::TyRptr(None, ref mut_ty) => { + span_note!(this.tcx().sess, ty.span, + "perhaps you meant `&{}({} +{})`? (per RFC 248)", + ppaux::mutability_to_string(mut_ty.mutbl), + pprust::ty_to_string(&*mut_ty.ty), + pprust::bounds_to_string(bounds)); } - Some(&def::DefTrait(trait_def_id)) => { - let result = ast_path_to_trait_ref(this, - rscope, - trait_def_id, - None, - path); - let empty_vec = []; - let bounds = match *opt_bounds { None => empty_vec.as_slice(), - Some(ref bounds) => bounds.as_slice() }; - let existential_bounds = conv_existential_bounds(this, - rscope, - path.span, - &[Rc::new(result.clone())], - bounds); - let tr = ty::mk_trait(tcx, - result, - existential_bounds); - return ty::mk_rptr(tcx, region, ty::mt{mutbl: a_seq_mutbl, ty: tr}); + + ast::TyRptr(Some(ref lt), ref mut_ty) => { + span_note!(this.tcx().sess, ty.span, + "perhaps you meant `&{} {}({} +{})`? (per RFC 248)", + pprust::lifetime_to_string(lt), + ppaux::mutability_to_string(mut_ty.mutbl), + pprust::ty_to_string(&*mut_ty.ty), + pprust::bounds_to_string(bounds)); + } + + _ => { + span_note!(this.tcx().sess, ty.span, + "perhaps you forgot parentheses? (per RFC 248)"); } - _ => {} } + Err(ErrorReported) } - _ => {} } - constr(ast_ty_to_ty(this, rscope, a_seq_ty)) +} + +fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC, + rscope: &RS, + span: Span, + trait_ref: ty::TraitRef<'tcx>, + bounds: &[ast::TyParamBound]) + -> Ty<'tcx> + where AC : AstConv<'tcx>, RS : RegionScope +{ + let existential_bounds = conv_existential_bounds(this, + rscope, + span, + &[Rc::new(trait_ref.clone())], + bounds); + + let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds); + debug!("trait_ref_to_object_type: result={}", + result.repr(this.tcx())); + + result } fn qpath_to_ty<'tcx,AC,RS>(this: &AC, @@ -806,6 +835,17 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ast::TyVec(ref ty) => { ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None) } + ast::TyObjectSum(ref ty, ref bounds) => { + match ast_ty_to_trait_ref(this, rscope, &**ty, bounds.as_slice()) { + Ok(trait_ref) => { + trait_ref_to_object_type(this, rscope, ast_ty.span, + trait_ref, bounds.as_slice()) + } + Err(ErrorReported) => { + ty::mk_err() + } + } + } ast::TyPtr(ref mt) => { ty::mk_ptr(tcx, ty::mt { ty: ast_ty_to_ty(this, rscope, &*mt.ty), @@ -815,8 +855,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ast::TyRptr(ref region, ref mt) => { let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region); debug!("ty_rptr r={}", r.repr(this.tcx())); - mk_pointer(this, rscope, mt.mutbl, &*mt.ty, r, - |ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl})) + let t = ast_ty_to_ty(this, rscope, &*mt.ty); + ty::mk_rptr(tcx, r, ty::mt {ty: t, mutbl: mt.mutbl}) } ast::TyTup(ref fields) => { let flds = fields.iter() @@ -874,7 +914,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ast::TyPolyTraitRef(ref bounds) => { conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice()) } - ast::TyPath(ref path, ref bounds, id) => { + ast::TyPath(ref path, id) => { let a_def = match tcx.def_map.borrow().get(&id) { None => { tcx.sess @@ -884,35 +924,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( } Some(&d) => d }; - // Kind bounds on path types are only supported for traits. - match a_def { - // But don't emit the error if the user meant to do a trait anyway. - def::DefTrait(..) => { }, - _ if bounds.is_some() => - tcx.sess.span_err(ast_ty.span, - "kind bounds can only be used on trait types"), - _ => { }, - } match a_def { def::DefTrait(trait_def_id) => { + // N.B. this case overlaps somewhat with + // TyObjectSum, see that fn for details let result = ast_path_to_trait_ref(this, rscope, trait_def_id, None, path); - let empty_bounds: &[ast::TyParamBound] = &[]; - let ast_bounds = match *bounds { - Some(ref b) => b.as_slice(), - None => empty_bounds - }; - let bounds = conv_existential_bounds(this, - rscope, - ast_ty.span, - &[Rc::new(result.clone())], - ast_bounds); - let result_ty = ty::mk_trait(tcx, result, bounds); - debug!("ast_ty_to_ty: result_ty={}", result_ty.repr(this.tcx())); - result_ty + trait_ref_to_object_type(this, rscope, path.span, result, &[]) } def::DefTy(did, _) | def::DefStruct(did) => { ast_path_to_ty(this, rscope, did, path).ty diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index bc36a2bd801b4..a78977d9fc7f6 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -1249,7 +1249,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { } ty_queue.push(&*mut_ty.ty); } - ast::TyPath(ref path, ref bounds, id) => { + ast::TyPath(ref path, id) => { let a_def = match self.tcx.def_map.borrow().get(&id) { None => { self.tcx @@ -1296,7 +1296,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { let new_path = self.rebuild_path(rebuild_info, lifetime); let to = ast::Ty { id: cur_ty.id, - node: ast::TyPath(new_path, bounds.clone(), id), + node: ast::TyPath(new_path, id), span: cur_ty.span }; new_ty = self.rebuild_ty(new_ty, P(to)); diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index 2f72d3cf50db1..3bca24f479f70 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -139,11 +139,11 @@ impl RegionScope for BindingRscope { /// A scope which simply shifts the Debruijn index of other scopes /// to account for binding levels. pub struct ShiftedRscope<'r> { - base_scope: &'r RegionScope+'r + base_scope: &'r (RegionScope+'r) } impl<'r> ShiftedRscope<'r> { - pub fn new(base_scope: &'r RegionScope+'r) -> ShiftedRscope<'r> { + pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> { ShiftedRscope { base_scope: base_scope } } } diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index ba6292f8975da..f5c732d9adcf1 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -651,7 +651,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { typ: &ast::Ty, impl_items: &Vec) { match typ.node { - ast::TyPath(ref path, _, id) => { + ast::TyPath(ref path, id) => { match self.lookup_type_ref(id) { Some(id) => { let sub_span = self.span.sub_span_for_type_name(path.span); @@ -1256,7 +1256,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } match t.node { - ast::TyPath(ref path, _, id) => { + ast::TyPath(ref path, id) => { match self.lookup_type_ref(id) { Some(id) => { let sub_span = self.span.sub_span_for_type_name(t.span); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5985516a559f3..6c04707b5ec1d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -972,7 +972,7 @@ impl Clean for doctree::Trait { impl Clean for ast::TraitRef { fn clean(&self, cx: &DocContext) -> Type { - resolve_type(cx, self.path.clean(cx), None, self.ref_id) + resolve_type(cx, self.path.clean(cx), self.ref_id) } } @@ -1258,8 +1258,19 @@ impl Clean for ast::Ty { TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx), e.span.to_src(cx)), TyTup(ref tys) => Tuple(tys.clean(cx)), - TyPath(ref p, ref tpbs, id) => { - resolve_type(cx, p.clean(cx), tpbs.clean(cx), id) + TyPath(ref p, id) => { + resolve_type(cx, p.clean(cx), id) + } + TyObjectSum(ref lhs, ref bounds) => { + let lhs_ty = lhs.clean(cx); + match lhs_ty { + ResolvedPath { path, typarams: None, did } => { + ResolvedPath { path: path, typarams: Some(bounds.clean(cx)), did: did} + } + _ => { + lhs_ty // shouldn't happen + } + } } TyClosure(ref c) => Closure(box c.clean(cx)), TyProc(ref c) => Proc(box c.clean(cx)), @@ -2110,8 +2121,8 @@ fn name_from_pat(p: &ast::Pat) -> String { } /// Given a Type, resolve it using the def_map -fn resolve_type(cx: &DocContext, path: Path, - tpbs: Option>, +fn resolve_type(cx: &DocContext, + path: Path, id: ast::NodeId) -> Type { let tcx = match cx.tcx_opt() { Some(tcx) => tcx, @@ -2148,7 +2159,7 @@ fn resolve_type(cx: &DocContext, path: Path, _ => {} }; let did = register_def(&*cx, def); - ResolvedPath { path: path, typarams: tpbs, did: did } + ResolvedPath { path: path, typarams: None, did: did } } fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId { diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs index 7544b93ce522a..697ee95df4c0f 100644 --- a/src/librustrt/unwind.rs +++ b/src/librustrt/unwind.rs @@ -86,7 +86,7 @@ struct Exception { cause: Option>, } -pub type Callback = fn(msg: &Any + Send, file: &'static str, line: uint); +pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint); // Variables used for invoking callbacks when a task starts to unwind. // diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 4a2ca58fc9269..19d23265b01ad 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -398,7 +398,7 @@ fn fmt_number_or_null(v: f64) -> string::String { /// A structure for implementing serialization to JSON. pub struct Encoder<'a> { - writer: &'a mut io::Writer+'a, + writer: &'a mut (io::Writer+'a), } impl<'a> Encoder<'a> { @@ -602,7 +602,7 @@ impl<'a> ::Encoder for Encoder<'a> { /// Another encoder for JSON, but prints out human-readable JSON instead of /// compact data pub struct PrettyEncoder<'a> { - writer: &'a mut io::Writer+'a, + writer: &'a mut (io::Writer+'a), curr_indent: uint, indent: uint, } diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index 621556f75ce3f..3191519815ae4 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/comm/select.rs @@ -84,7 +84,7 @@ pub struct Handle<'rx, T:'rx> { next: *mut Handle<'static, ()>, prev: *mut Handle<'static, ()>, added: bool, - packet: &'rx Packet+'rx, + packet: &'rx (Packet+'rx), // due to our fun transmutes, we be sure to place this at the end. (nothing // previous relies on T) diff --git a/src/libstd/failure.rs b/src/libstd/failure.rs index 32a8be2290297..d839c1484e562 100644 --- a/src/libstd/failure.rs +++ b/src/libstd/failure.rs @@ -40,7 +40,7 @@ impl Writer for Stdio { } } -pub fn on_fail(obj: &Any + Send, file: &'static str, line: uint) { +pub fn on_fail(obj: &(Any+Send), file: &'static str, line: uint) { let msg = match obj.downcast_ref::<&'static str>() { Some(s) => *s, None => match obj.downcast_ref::() { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 681400e9db581..311cbe6ece852 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -911,7 +911,7 @@ impl<'a> Reader for Box { } } -impl<'a> Reader for &'a mut Reader+'a { +impl<'a> Reader for &'a mut (Reader+'a) { fn read(&mut self, buf: &mut [u8]) -> IoResult { (*self).read(buf) } } @@ -1279,7 +1279,7 @@ impl<'a> Writer for Box { } } -impl<'a> Writer for &'a mut Writer+'a { +impl<'a> Writer for &'a mut (Writer+'a) { #[inline] fn write(&mut self, buf: &[u8]) -> IoResult<()> { (**self).write(buf) } diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 8102299438749..d47256b1d1890 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -288,7 +288,7 @@ mod imp { struct Context<'a> { idx: int, - writer: &'a mut Writer+'a, + writer: &'a mut (Writer+'a), last_error: Option, } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3d33774aa55e1..14f164ff23b82 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1151,7 +1151,9 @@ pub enum Ty_ { /// A path (`module::module::...::Type`) or primitive /// /// Type parameters are stored in the Path itself - TyPath(Path, Option, NodeId), // for #7264; see above + TyPath(Path, NodeId), + /// Something like `A+B`. Note that `B` must always be a path. + TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` TyPolyTraitRef(TyParamBounds), /// A "qualified path", e.g. ` as SomeTrait>::SomeType` diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 043e79bffd9e9..4d6ac4f343096 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -454,7 +454,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { fn visit_ty(&mut self, typ: &Ty) { self.operation.visit_id(typ.id); match typ.node { - TyPath(_, _, id) => self.operation.visit_id(id), + TyPath(_, id) => self.operation.visit_id(id), _ => {} } visit::walk_ty(self, typ) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 2c7f9e889f8b2..bd01e5e643020 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -44,7 +44,8 @@ pub trait AstBuilder { fn ty_mt(&self, ty: P, mutbl: ast::Mutability) -> ast::MutTy; fn ty(&self, span: Span, ty: ast::Ty_) -> P; - fn ty_path(&self, ast::Path, Option>) -> P; + fn ty_path(&self, ast::Path) -> P; + fn ty_sum(&self, ast::Path, OwnedSlice) -> P; fn ty_ident(&self, span: Span, idents: ast::Ident) -> P; fn ty_rptr(&self, span: Span, @@ -344,17 +345,21 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }) } - fn ty_path(&self, path: ast::Path, bounds: Option>) - -> P { + fn ty_path(&self, path: ast::Path) -> P { + self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID)) + } + + fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice) -> P { self.ty(path.span, - ast::TyPath(path, bounds, ast::DUMMY_NODE_ID)) + ast::TyObjectSum(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) -> P { - self.ty_path(self.path_ident(span, ident), None) + self.ty_path(self.path_ident(span, ident)) } fn ty_rptr(&self, @@ -386,7 +391,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.ident_of("Option") ), Vec::new(), - vec!( ty )), None) + vec!( ty ))) } fn ty_field_imm(&self, span: Span, name: Ident, ty: P) -> ast::TypeField { @@ -425,8 +430,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn ty_vars_global(&self, ty_params: &OwnedSlice) -> Vec> { - ty_params.iter().map(|p| self.ty_path( - self.path_global(DUMMY_SP, vec!(p.ident)), None)).collect() + 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 { diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index fcd4966683d3b..d5f472bd82710 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -444,7 +444,7 @@ impl<'a> TraitDef<'a> { // Create the type of `self`. let self_type = cx.ty_path( cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes, - self_ty_params.into_vec()), None); + self_ty_params.into_vec())); let attr = cx.attribute( self.span, diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index 700ada8b4ad8f..6614ab50f1e45 100644 --- a/src/libsyntax/ext/deriving/generic/ty.rs +++ b/src/libsyntax/ext/deriving/generic/ty.rs @@ -70,7 +70,7 @@ impl<'a> Path<'a> { self_ty: Ident, self_generics: &Generics) -> P { - cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None) + cx.ty_path(self.to_path(cx, span, self_ty, self_generics)) } pub fn to_path(&self, cx: &ExtCtxt, @@ -152,7 +152,7 @@ impl<'a> Ty<'a> { } Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) } Self => { - cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None) + cx.ty_path(self.to_path(cx, span, self_ty, self_generics)) } Tuple(ref fields) => { let ty = ast::TyTup(fields.iter() diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index b04a800a32d2a..6ec12b4d603c1 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -531,7 +531,7 @@ impl<'a, 'b> Context<'a, 'b> { true, Context::rtpath(self.ecx, "Argument"), vec![static_lifetime], vec![] - ), None); + )); lets.push(Context::item_static_array(self.ecx, static_args_name, piece_ty, diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index b4cd9779ae251..4785fe37293c0 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -514,7 +514,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { "stmt" => token::NtStmt(p.parse_stmt(Vec::new())), "pat" => token::NtPat(p.parse_pat()), "expr" => token::NtExpr(p.parse_expr()), - "ty" => token::NtTy(p.parse_ty(false /* no need to disambiguate*/)), + "ty" => token::NtTy(p.parse_ty()), // this could be handled like a token, since it is one "ident" => match p.token { token::Ident(sn,b) => { p.bump(); token::NtIdent(box sn,b) } @@ -525,7 +525,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { } }, "path" => { - token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons).path) + token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons)) } "meta" => token::NtMeta(p.parse_meta_item()), "tt" => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6941c0e9c1800..122f99cabb3f6 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -433,11 +433,13 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { } TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyParen(ty) => TyParen(fld.fold_ty(ty)), - TyPath(path, bounds, id) => { + TyPath(path, id) => { let id = fld.new_id(id); - TyPath(fld.fold_path(path), - fld.fold_opt_bounds(bounds), - id) + TyPath(fld.fold_path(path), id) + } + TyObjectSum(ty, bounds) => { + TyObjectSum(fld.fold_ty(ty), + fld.fold_bounds(bounds)) } TyQPath(qpath) => { TyQPath(fld.fold_qpath(qpath)) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 96659031e6a37..b46f7cdfe22ad 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1029,7 +1029,7 @@ mod test { parameters: ast::PathParameters::none(), } ), - }, None, ast::DUMMY_NODE_ID), + }, ast::DUMMY_NODE_ID), span:sp(10,13) }), pat: P(ast::Pat { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c731a0005f884..35187ebb52210 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -111,16 +111,6 @@ pub enum PathParsingMode { /// A path with a lifetime and type parameters with double colons before /// the type parameters; e.g. `foo::bar::<'a>::Baz::` LifetimeAndTypesWithColons, - /// A path with a lifetime and type parameters with bounds before the last - /// set of type parameters only; e.g. `foo::bar<'a>::Baz+X+Y` This - /// form does not use extra double colons. - LifetimeAndTypesAndBounds, -} - -/// A path paired with optional type bounds. -pub struct PathAndBounds { - pub path: ast::Path, - pub bounds: Option, } enum ItemOrViewItem { @@ -1053,17 +1043,9 @@ impl<'a> Parser<'a> { } } - pub fn parse_ty_path(&mut self, plus_allowed: bool) -> Ty_ { - let mode = if plus_allowed { - LifetimeAndTypesAndBounds - } else { - LifetimeAndTypesWithoutColons - }; - let PathAndBounds { - path, - bounds - } = self.parse_path(mode); - TyPath(path, bounds, ast::DUMMY_NODE_ID) + pub fn parse_ty_path(&mut self) -> Ty_ { + let path = self.parse_path(LifetimeAndTypesWithoutColons); + TyPath(path, ast::DUMMY_NODE_ID) } /// parse a TyBareFn type: @@ -1286,7 +1268,7 @@ impl<'a> Parser<'a> { let lo = self.span.lo; let ident = self.parse_ident(); self.expect(&token::Eq); - let typ = self.parse_ty(true); + let typ = self.parse_ty_sum(); let hi = self.span.hi; self.expect(&token::Semi); Typedef { @@ -1385,7 +1367,7 @@ impl<'a> Parser<'a> { /// Parse a possibly mutable type pub fn parse_mt(&mut self) -> MutTy { let mutbl = self.parse_mutability(); - let t = self.parse_ty(true); + let t = self.parse_ty(); MutTy { ty: t, mutbl: mutbl } } @@ -1396,7 +1378,7 @@ impl<'a> Parser<'a> { let mutbl = self.parse_mutability(); let id = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); let hi = ty.span.hi; ast::TypeField { ident: id, @@ -1411,7 +1393,19 @@ impl<'a> Parser<'a> { if self.eat(&token::Not) { NoReturn(self.span) } else { - Return(self.parse_ty(true)) + let t = self.parse_ty(); + + // We used to allow `fn foo() -> &T + U`, but don't + // anymore. If we see it, report a useful error. This + // only makes sense because `parse_ret_ty` is only + // used in fn *declarations*, not fn types or where + // clauses (i.e., not when parsing something like + // `FnMut() -> T + Send`, where the `+` is legal). + if self.token == token::BinOp(token::Plus) { + self.warn("deprecated syntax: `()` are required, see RFC 248 for details"); + } + + Return(t) } } else { let pos = self.span.lo; @@ -1423,11 +1417,36 @@ impl<'a> Parser<'a> { } } + /// Parse a type in a context where `T1+T2` is allowed. + pub fn parse_ty_sum(&mut self) -> P { + let lo = self.span.lo; + let lhs = self.parse_ty(); + + if !self.eat(&token::BinOp(token::Plus)) { + return lhs; + } + + let bounds = self.parse_ty_param_bounds(); + + // In type grammar, `+` is treated like a binary operator, + // and hence both L and R side are required. + if bounds.len() == 0 { + let last_span = self.last_span; + self.span_err(last_span, + "at least one type parameter bound \ + must be specified"); + } + + let sp = mk_sp(lo, self.last_span.hi); + let sum = ast::TyObjectSum(lhs, bounds); + P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}) + } + /// Parse a type. /// /// The second parameter specifies whether the `+` binary operator is /// allowed in the type grammar. - pub fn parse_ty(&mut self, plus_allowed: bool) -> P { + pub fn parse_ty(&mut self) -> P { maybe_whole!(no_clone self, NtTy); let lo = self.span.lo; @@ -1441,7 +1460,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(true)); + ts.push(self.parse_ty_sum()); if self.token == token::Comma { last_comma = true; self.bump(); @@ -1465,7 +1484,7 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector), _ => self.obsolete(last_span, ObsoleteOwnedType) } - TyTup(vec![self.parse_ty(false)]) + TyTup(vec![self.parse_ty()]) } else if self.token == token::BinOp(token::Star) { // STAR POINTER (bare pointer?) self.bump(); @@ -1473,7 +1492,7 @@ impl<'a> Parser<'a> { } else if self.token == token::OpenDelim(token::Bracket) { // VECTOR self.expect(&token::OpenDelim(token::Bracket)); - let t = self.parse_ty(true); + let t = self.parse_ty_sum(); // Parse the `, ..e` in `[ int, ..e ]` // where `e` is a const expression @@ -1514,7 +1533,7 @@ impl<'a> Parser<'a> { } else if self.token == token::Lt { // QUALIFIED PATH `::item` self.bump(); - let self_type = self.parse_ty(true); + let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); let trait_ref = self.parse_trait_ref(); self.expect(&token::Gt); @@ -1529,7 +1548,7 @@ impl<'a> Parser<'a> { self.token.is_ident() || self.token.is_path() { // NAMED TYPE - self.parse_ty_path(plus_allowed) + self.parse_ty_path() } else if self.eat(&token::Underscore) { // TYPE TO BE INFERRED TyInfer @@ -1563,7 +1582,7 @@ impl<'a> Parser<'a> { known as `*const T`"); MutImmutable }; - let t = self.parse_ty(true); + let t = self.parse_ty(); MutTy { ty: t, mutbl: mutbl } } @@ -1603,7 +1622,7 @@ impl<'a> Parser<'a> { special_idents::invalid) }; - let t = self.parse_ty(true); + let t = self.parse_ty_sum(); Arg { ty: t, @@ -1621,7 +1640,7 @@ impl<'a> Parser<'a> { pub fn parse_fn_block_arg(&mut self) -> Arg { let pat = self.parse_pat(); let t = if self.eat(&token::Colon) { - self.parse_ty(true) + self.parse_ty_sum() } else { P(Ty { id: ast::DUMMY_NODE_ID, @@ -1739,7 +1758,7 @@ impl<'a> Parser<'a> { /// mode. The `mode` parameter determines whether lifetimes, types, and/or /// bounds are permitted and whether `::` must precede type parameter /// groups. - pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds { + pub fn parse_path(&mut self, mode: PathParsingMode) -> ast::Path { // Check for a whole path... let found = match self.token { token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()), @@ -1747,10 +1766,7 @@ impl<'a> Parser<'a> { }; match found { Some(token::Interpolated(token::NtPath(box path))) => { - return PathAndBounds { - path: path, - bounds: None - } + return path; } _ => {} } @@ -1762,8 +1778,7 @@ impl<'a> Parser<'a> { // identifier followed by an optional lifetime and a set of types. // A bound set is a set of type parameter bounds. let segments = match mode { - LifetimeAndTypesWithoutColons | - LifetimeAndTypesAndBounds => { + LifetimeAndTypesWithoutColons => { self.parse_path_segments_without_colons() } LifetimeAndTypesWithColons => { @@ -1774,44 +1789,14 @@ impl<'a> Parser<'a> { } }; - // Next, parse a plus and bounded type parameters, if - // applicable. We need to remember whether the separate was - // present for later, because in some contexts it's a parse - // error. - let opt_bounds = { - if mode == LifetimeAndTypesAndBounds && - self.eat(&token::BinOp(token::Plus)) - { - let bounds = self.parse_ty_param_bounds(); - - // For some reason that I do not fully understand, we - // do not permit an empty list in the case where it is - // introduced by a `+`, but we do for `:` and other - // separators. -nmatsakis - if bounds.len() == 0 { - let last_span = self.last_span; - self.span_err(last_span, - "at least one type parameter bound \ - must be specified"); - } - - Some(bounds) - } else { - None - } - }; - // Assemble the span. let span = mk_sp(lo, self.last_span.hi); // Assemble the result. - PathAndBounds { - path: ast::Path { - span: span, - global: is_global, - segments: segments, - }, - bounds: opt_bounds, + ast::Path { + span: span, + global: is_global, + segments: segments, } } @@ -1837,10 +1822,10 @@ impl<'a> Parser<'a> { let inputs = self.parse_seq_to_end( &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), - |p| p.parse_ty(true)); + |p| p.parse_ty_sum()); let output_ty = if self.eat(&token::RArrow) { - Some(self.parse_ty(true)) + Some(self.parse_ty()) } else { None }; @@ -2327,7 +2312,7 @@ impl<'a> Parser<'a> { !self.token.is_keyword(keywords::True) && !self.token.is_keyword(keywords::False) { let pth = - self.parse_path(LifetimeAndTypesWithColons).path; + self.parse_path(LifetimeAndTypesWithColons); // `!`, as an operator, is prefix, so we know this isn't that if self.token == token::Not { @@ -2898,7 +2883,7 @@ impl<'a> Parser<'a> { } None => { if as_prec > min_prec && self.eat_keyword(keywords::As) { - let rhs = self.parse_ty(false); + let rhs = self.parse_ty(); let _as = self.mk_expr(lhs.span.lo, rhs.span.hi, ExprCast(lhs, rhs)); @@ -3362,8 +3347,7 @@ impl<'a> Parser<'a> { }) { self.bump(); let end = if self.token.is_ident() || self.token.is_path() { - let path = self.parse_path(LifetimeAndTypesWithColons) - .path; + let path = self.parse_path(LifetimeAndTypesWithColons); let hi = self.span.hi; self.mk_expr(lo, hi, ExprPath(path)) } else { @@ -3433,8 +3417,7 @@ impl<'a> Parser<'a> { } } else { // parse an enum pat - let enum_path = self.parse_path(LifetimeAndTypesWithColons) - .path; + let enum_path = self.parse_path(LifetimeAndTypesWithColons); match self.token { token::OpenDelim(token::Brace) => { self.bump(); @@ -3548,7 +3531,7 @@ impl<'a> Parser<'a> { span: mk_sp(lo, lo), }); if self.eat(&token::Colon) { - ty = self.parse_ty(true); + ty = self.parse_ty_sum(); } let init = self.parse_initializer(); P(ast::Local { @@ -3577,7 +3560,7 @@ impl<'a> Parser<'a> { } let name = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); spanned(lo, self.last_span.hi, ast::StructField_ { kind: NamedField(name, pr), id: ast::DUMMY_NODE_ID, @@ -3624,7 +3607,7 @@ impl<'a> Parser<'a> { // Potential trouble: if we allow macros with paths instead of // idents, we'd need to look ahead past the whole path here... - let pth = self.parse_path(NoTypesAllowed).path; + let pth = self.parse_path(NoTypesAllowed); self.bump(); let id = match self.token { @@ -3976,7 +3959,7 @@ impl<'a> Parser<'a> { let default = if self.token == token::Eq { self.bump(); - Some(self.parse_ty(true)) + Some(self.parse_ty_sum()) } else { None }; @@ -4032,7 +4015,7 @@ impl<'a> Parser<'a> { Some(token::Comma), |p| { p.forbid_lifetime(); - p.parse_ty(true) + p.parse_ty_sum() } ); (lifetimes, result.into_vec()) @@ -4265,7 +4248,7 @@ impl<'a> Parser<'a> { // Determine whether this is the fully explicit form, `self: // TYPE`. if self.eat(&token::Colon) { - SelfExplicit(self.parse_ty(false), self_ident) + SelfExplicit(self.parse_ty_sum(), self_ident) } else { SelfValue(self_ident) } @@ -4277,7 +4260,7 @@ impl<'a> Parser<'a> { // Determine whether this is the fully explicit form, // `self: TYPE`. if self.eat(&token::Colon) { - SelfExplicit(self.parse_ty(false), self_ident) + SelfExplicit(self.parse_ty_sum(), self_ident) } else { SelfValue(self_ident) } @@ -4466,7 +4449,7 @@ impl<'a> Parser<'a> { && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { // method macro. - let pth = self.parse_path(NoTypesAllowed).path; + let pth = self.parse_path(NoTypesAllowed); self.expect(&token::Not); // eat a matched-delimiter token tree: @@ -4564,30 +4547,25 @@ impl<'a> Parser<'a> { let could_be_trait = self.token != token::OpenDelim(token::Paren); // Parse the trait. - let mut ty = self.parse_ty(true); + let mut ty = self.parse_ty_sum(); // Parse traits, if necessary. let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. let opt_trait_ref = match ty.node { - TyPath(ref path, None, node_id) => { + TyPath(ref path, node_id) => { Some(TraitRef { path: (*path).clone(), ref_id: node_id, }) } - TyPath(_, Some(_), _) => { - self.span_err(ty.span, - "bounded traits are only valid in type position"); - None - } _ => { self.span_err(ty.span, "not a trait"); None } }; - ty = self.parse_ty(true); + ty = self.parse_ty_sum(); opt_trait_ref } else { None @@ -4606,7 +4584,7 @@ impl<'a> Parser<'a> { /// Parse a::B fn parse_trait_ref(&mut self) -> TraitRef { ast::TraitRef { - path: self.parse_path(LifetimeAndTypesWithoutColons).path, + path: self.parse_path(LifetimeAndTypesWithoutColons), ref_id: ast::DUMMY_NODE_ID, } } @@ -4638,7 +4616,7 @@ impl<'a> Parser<'a> { let mut generics = self.parse_generics(); if self.eat(&token::Colon) { - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); self.span_err(ty.span, "`virtual` structs have been removed from the language"); } @@ -4673,7 +4651,7 @@ impl<'a> Parser<'a> { let struct_field_ = ast::StructField_ { kind: UnnamedField(p.parse_visibility()), id: ast::DUMMY_NODE_ID, - ty: p.parse_ty(true), + ty: p.parse_ty_sum(), attrs: attrs, }; spanned(lo, p.span.hi, struct_field_) @@ -4830,7 +4808,7 @@ impl<'a> Parser<'a> { fn parse_item_const(&mut self, m: Option) -> ItemInfo { let id = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); self.expect(&token::Eq); let e = self.parse_expr(); self.commit_expr_expecting(&*e, token::Semi); @@ -5023,7 +5001,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); let hi = self.span.hi; self.expect(&token::Semi); P(ForeignItem { @@ -5181,7 +5159,7 @@ impl<'a> Parser<'a> { let mut tps = self.parse_generics(); self.parse_where_clause(&mut tps); self.expect(&token::Eq); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); self.expect(&token::Semi); (ident, ItemTy(ty, tps), None) } @@ -5235,7 +5213,7 @@ impl<'a> Parser<'a> { &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), - |p| p.parse_ty(true) + |p| p.parse_ty_sum() ); for ty in arg_tys.into_iter() { args.push(ast::VariantArg { @@ -5593,7 +5571,7 @@ impl<'a> Parser<'a> { // MACRO INVOCATION ITEM // item macro. - let pth = self.parse_path(NoTypesAllowed).path; + let pth = self.parse_path(NoTypesAllowed); self.expect(&token::Not); // a 'special' identifier (like what `macro_rules!` uses) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6960337c3e2c9..ab78d5ecbfdce 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -61,7 +61,7 @@ pub struct State<'a> { literals: Option >, cur_cmnt_and_lit: CurrentCommentAndLiteral, boxes: Vec, - ann: &'a PpAnn+'a, + ann: &'a (PpAnn+'a), encode_idents_with_hygiene: bool, } @@ -293,6 +293,10 @@ pub fn ty_to_string(ty: &ast::Ty) -> String { $to_string(|s| s.print_type(ty)) } +pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String { + $to_string(|s| s.print_bounds("", bounds)) +} + pub fn pat_to_string(pat: &ast::Pat) -> String { $to_string(|s| s.print_pat(pat)) } @@ -739,11 +743,15 @@ impl<'a> State<'a> { Some(&generics), None)); } - ast::TyPath(ref path, ref bounds, _) => { - try!(self.print_bounded_path(path, bounds)); + ast::TyPath(ref path, _) => { + try!(self.print_path(path, false)); + } + ast::TyObjectSum(ref ty, ref bounds) => { + try!(self.print_type(&**ty)); + try!(self.print_bounds("+", bounds.as_slice())); } ast::TyPolyTraitRef(ref bounds) => { - try!(self.print_bounds("", bounds)); + try!(self.print_bounds("", bounds.as_slice())); } ast::TyQPath(ref qpath) => { try!(word(&mut self.s, "<")); @@ -970,7 +978,7 @@ impl<'a> State<'a> { } _ => {} } - try!(self.print_bounds(":", bounds)); + try!(self.print_bounds(":", bounds.as_slice())); try!(self.print_where_clause(generics)); try!(word(&mut self.s, " ")); try!(self.bopen()); @@ -1908,11 +1916,11 @@ impl<'a> State<'a> { self.print_expr(coll) } - fn print_path_(&mut self, - path: &ast::Path, - colons_before_params: bool, - opt_bounds: &Option>) - -> IoResult<()> { + fn print_path(&mut self, + path: &ast::Path, + colons_before_params: bool) + -> IoResult<()> + { try!(self.maybe_print_comment(path.span.lo)); if path.global { try!(word(&mut self.s, "::")); @@ -1931,10 +1939,7 @@ impl<'a> State<'a> { try!(self.print_path_parameters(&segment.parameters, colons_before_params)); } - match *opt_bounds { - None => Ok(()), - Some(ref bounds) => self.print_bounds("+", bounds) - } + Ok(()) } fn print_path_parameters(&mut self, @@ -1997,17 +2002,6 @@ impl<'a> State<'a> { Ok(()) } - fn print_path(&mut self, path: &ast::Path, - colons_before_params: bool) -> IoResult<()> { - self.print_path_(path, colons_before_params, &None) - } - - fn print_bounded_path(&mut self, path: &ast::Path, - bounds: &Option>) - -> IoResult<()> { - self.print_path_(path, false, bounds) - } - pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> { try!(self.maybe_print_comment(pat.span.lo)); try!(self.ann.pre(self, NodePat(pat))); @@ -2329,7 +2323,7 @@ impl<'a> State<'a> { pub fn print_bounds(&mut self, prefix: &str, - bounds: &OwnedSlice) + bounds: &[ast::TyParamBound]) -> IoResult<()> { if !bounds.is_empty() { try!(word(&mut self.s, prefix)); @@ -2418,7 +2412,7 @@ impl<'a> State<'a> { _ => {} } try!(self.print_ident(param.ident)); - try!(self.print_bounds(":", ¶m.bounds)); + try!(self.print_bounds(":", param.bounds.as_slice())); match param.default { Some(ref default) => { try!(space(&mut self.s)); @@ -2447,7 +2441,7 @@ impl<'a> State<'a> { } try!(self.print_ident(predicate.ident)); - try!(self.print_bounds(":", &predicate.bounds)); + try!(self.print_bounds(":", predicate.bounds.as_slice())); } Ok(()) @@ -2664,7 +2658,7 @@ impl<'a> State<'a> { try!(self.pclose()); } - try!(self.print_bounds(":", bounds)); + try!(self.print_bounds(":", bounds.as_slice())); try!(self.print_fn_output(decl)); diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index f21a3185d6d3e..05828fc05f8c6 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -482,8 +482,7 @@ fn mk_tests(cx: &TestCtxt) -> P { let ecx = &cx.ext_cx; let struct_type = ecx.ty_path(ecx.path(sp, vec![ecx.ident_of("self"), ecx.ident_of("test"), - ecx.ident_of("TestDescAndFn")]), - None); + ecx.ident_of("TestDescAndFn")])); let static_lt = ecx.lifetime(sp, token::special_idents::static_lifetime.name); // &'static [self::test::TestDescAndFn] let static_type = ecx.ty_rptr(sp, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 3f87dbc0740ec..95679bc6bf0d1 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -404,14 +404,12 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_fn_ret_ty(visitor, &function_declaration.decl.output); walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } - TyPath(ref path, ref opt_bounds, id) => { + TyPath(ref path, id) => { visitor.visit_path(path, id); - match *opt_bounds { - Some(ref bounds) => { - walk_ty_param_bounds_helper(visitor, bounds); - } - None => { } - } + } + TyObjectSum(ref ty, ref bounds) => { + visitor.visit_ty(&**ty); + walk_ty_param_bounds_helper(visitor, bounds); } TyQPath(ref qpath) => { visitor.visit_ty(&*qpath.self_type); diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 151a388a13335..611c10ea71a09 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -115,7 +115,7 @@ pub fn stdout() -> Option + Send>> { #[cfg(not(windows))] /// Return a Terminal wrapping stderr, or None if a terminal couldn't be /// opened. -pub fn stderr() -> Option + Send> + Send> { +pub fn stderr() -> Option + Send>> { TerminfoTerminal::new(WriterWrapper { wrapped: box std::io::stderr() as Box, }) diff --git a/src/test/compile-fail/dst-index.rs b/src/test/compile-fail/dst-index.rs index 542562b69e6a7..f6511d68662ee 100644 --- a/src/test/compile-fail/dst-index.rs +++ b/src/test/compile-fail/dst-index.rs @@ -25,7 +25,7 @@ impl Index for S { struct T; impl Index for T { - fn index<'a>(&'a self, idx: &uint) -> &'a Show + 'static { + fn index<'a>(&'a self, idx: &uint) -> &'a (Show + 'static) { static x: uint = 42; &x } diff --git a/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs b/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs new file mode 100644 index 0000000000000..ff3512ad8e72a --- /dev/null +++ b/src/test/compile-fail/hrtb-precedence-of-plus-error-message.rs @@ -0,0 +1,36 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures)] + +// Test that we suggest the correct parentheses + +trait Bar { + fn dummy(&self) { } +} + +struct Foo<'a> { + a: &'a Bar+'a, + //~^ ERROR E0171 + //~^^ NOTE perhaps you meant `&'a (Bar + 'a)`? + + b: &'a mut Bar+'a, + //~^ ERROR E0171 + //~^^ NOTE perhaps you meant `&'a mut (Bar + 'a)`? + + c: Box, // OK, no paren needed in this context + + d: fn() -> Bar+'a, + //~^ ERROR E0171 + //~^^ NOTE perhaps you forgot parentheses + //~^^^ WARN deprecated syntax +} + +fn main() { } diff --git a/src/test/compile-fail/issue-12470.rs b/src/test/compile-fail/issue-12470.rs index aa7e3cd3739b2..0202d538cf650 100644 --- a/src/test/compile-fail/issue-12470.rs +++ b/src/test/compile-fail/issue-12470.rs @@ -24,7 +24,7 @@ impl X for B { } struct A<'a> { - p: &'a X+'a + p: &'a (X+'a) } fn make_a<'a>(p: &'a X) -> A<'a> { diff --git a/src/test/compile-fail/issue-14285.rs b/src/test/compile-fail/issue-14285.rs index 624ddf0c8bbdc..cbf4412a81df2 100644 --- a/src/test/compile-fail/issue-14285.rs +++ b/src/test/compile-fail/issue-14285.rs @@ -14,7 +14,7 @@ struct A; impl Foo for A {} -struct B<'a>(&'a Foo+'a); +struct B<'a>(&'a (Foo+'a)); fn foo<'a>(a: &Foo) -> B<'a> { B(a) //~ ERROR cannot infer an appropriate lifetime diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs index 499144698fb81..202529c30b3e6 100644 --- a/src/test/compile-fail/kindck-copy.rs +++ b/src/test/compile-fail/kindck-copy.rs @@ -44,15 +44,15 @@ fn test<'a,T,U:Copy>(_: &'a int) { // borrowed object types are generally ok assert_copy::<&'a Dummy>(); - assert_copy::<&'a Dummy+Copy>(); - assert_copy::<&'static Dummy+Copy>(); + assert_copy::<&'a (Dummy+Copy)>(); + assert_copy::<&'static (Dummy+Copy)>(); // owned object types are not ok assert_copy::>(); //~ ERROR `core::kinds::Copy` is not implemented assert_copy::>(); //~ ERROR `core::kinds::Copy` is not implemented // mutable object types are not ok - assert_copy::<&'a mut Dummy+Copy>(); //~ ERROR `core::kinds::Copy` is not implemented + assert_copy::<&'a mut (Dummy+Copy)>(); //~ ERROR `core::kinds::Copy` is not implemented // closures are like an `&mut` object assert_copy::<||>(); //~ ERROR `core::kinds::Copy` is not implemented diff --git a/src/test/compile-fail/kindck-send-object.rs b/src/test/compile-fail/kindck-send-object.rs index 9217d05002d88..4fbb3eab8c416 100644 --- a/src/test/compile-fail/kindck-send-object.rs +++ b/src/test/compile-fail/kindck-send-object.rs @@ -19,7 +19,7 @@ trait Message : Send { } // careful with object types, who knows what they close over... fn object_ref_with_static_bound_not_ok() { - assert_send::<&'static Dummy+'static>(); + assert_send::<&'static (Dummy+'static)>(); //~^ ERROR the trait `core::kinds::Send` is not implemented } @@ -36,7 +36,7 @@ fn closure_with_no_bound_not_ok<'a>() { } fn object_with_send_bound_ok() { - assert_send::<&'static Dummy+Send>(); + assert_send::<&'static (Dummy+Send)>(); assert_send::>(); assert_send::; assert_send::<||:Send>; diff --git a/src/test/compile-fail/kindck-send-object1.rs b/src/test/compile-fail/kindck-send-object1.rs index ff8daa045c66d..a551975364329 100644 --- a/src/test/compile-fail/kindck-send-object1.rs +++ b/src/test/compile-fail/kindck-send-object1.rs @@ -21,13 +21,13 @@ fn test51<'a>() { //~^ ERROR the trait `core::kinds::Send` is not implemented } fn test52<'a>() { - assert_send::<&'a Dummy+Send>(); + assert_send::<&'a (Dummy+Send)>(); //~^ ERROR does not fulfill the required lifetime } // ...unless they are properly bounded fn test60() { - assert_send::<&'static Dummy+Send>(); + assert_send::<&'static (Dummy+Send)>(); } fn test61() { assert_send::>(); diff --git a/src/test/compile-fail/kindck-send-object2.rs b/src/test/compile-fail/kindck-send-object2.rs index d46c6e68c05c2..ea8c262830633 100644 --- a/src/test/compile-fail/kindck-send-object2.rs +++ b/src/test/compile-fail/kindck-send-object2.rs @@ -23,7 +23,7 @@ fn test53() { // ...unless they are properly bounded fn test60() { - assert_send::<&'static Dummy+Send>(); + assert_send::<&'static (Dummy+Send)>(); } fn test61() { assert_send::>(); diff --git a/src/test/compile-fail/region-object-lifetime-1.rs b/src/test/compile-fail/region-object-lifetime-1.rs index 01daeb628ef57..4758ce71ffff5 100644 --- a/src/test/compile-fail/region-object-lifetime-1.rs +++ b/src/test/compile-fail/region-object-lifetime-1.rs @@ -28,14 +28,14 @@ fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () { // Borrowed receiver with two distinct lifetimes, but we know that // 'b:'a, hence &'a () is permitted. -fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a Foo+'b) -> &'a () { +fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () { x.borrowed() } // Here we have two distinct lifetimes, but we try to return a pointer // with the longer lifetime when (from the signature) we only know // that it lives as long as the shorter lifetime. Therefore, error. -fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a Foo+'b) -> &'b () { +fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () { x.borrowed() //~ ERROR cannot infer } diff --git a/src/test/compile-fail/regions-bounded-by-send.rs b/src/test/compile-fail/regions-bounded-by-send.rs index 182b40ceaae03..660a9be4f63c5 100644 --- a/src/test/compile-fail/regions-bounded-by-send.rs +++ b/src/test/compile-fail/regions-bounded-by-send.rs @@ -57,12 +57,12 @@ fn box_with_region_not_ok<'a>() { // objects with insufficient bounds no ok fn object_with_random_bound_not_ok<'a>() { - assert_send::<&'a Dummy+'a>(); + assert_send::<&'a (Dummy+'a)>(); //~^ ERROR not implemented } fn object_with_send_bound_not_ok<'a>() { - assert_send::<&'a Dummy+Send>(); + assert_send::<&'a (Dummy+Send)>(); //~^ ERROR does not fulfill } diff --git a/src/test/compile-fail/regions-close-object-into-object.rs b/src/test/compile-fail/regions-close-object-into-object.rs index 835c55c9bd17a..48945868bd355 100644 --- a/src/test/compile-fail/regions-close-object-into-object.rs +++ b/src/test/compile-fail/regions-close-object-into-object.rs @@ -10,7 +10,7 @@ trait A {} -struct B<'a, T>(&'a A+'a); +struct B<'a, T>(&'a (A+'a)); trait X {} impl<'a, T> X for B<'a, T> {} diff --git a/src/test/compile-fail/regions-trait-variance.rs b/src/test/compile-fail/regions-trait-variance.rs index 3ceb4e3fef6df..4e31a41c4e074 100644 --- a/src/test/compile-fail/regions-trait-variance.rs +++ b/src/test/compile-fail/regions-trait-variance.rs @@ -31,7 +31,7 @@ impl Drop for B { } struct A<'r> { - p: &'r X+'r + p: &'r (X+'r) } fn make_a(p:&X) -> A { diff --git a/src/test/compile-fail/trait-bounds-not-on-impl.rs b/src/test/compile-fail/trait-bounds-not-on-impl.rs index 38c7814460147..a034352c4a694 100644 --- a/src/test/compile-fail/trait-bounds-not-on-impl.rs +++ b/src/test/compile-fail/trait-bounds-not-on-impl.rs @@ -13,7 +13,7 @@ trait Foo { struct Bar; -impl Foo + Owned for Bar { //~ ERROR bounded traits are only valid in type position +impl Foo + Owned for Bar { //~ ERROR not a trait } fn main() { } diff --git a/src/test/compile-fail/trait-bounds-not-on-struct.rs b/src/test/compile-fail/trait-bounds-not-on-struct.rs index 0a5909ff2efbe..081efa429c3e4 100644 --- a/src/test/compile-fail/trait-bounds-not-on-struct.rs +++ b/src/test/compile-fail/trait-bounds-not-on-struct.rs @@ -11,6 +11,6 @@ struct Foo; -fn foo(_x: Box) { } //~ ERROR kind bounds can only be used on trait types +fn foo(_x: Box) { } //~ ERROR expected a reference to a trait fn main() { } diff --git a/src/test/compile-fail/trait-bounds-sugar.rs b/src/test/compile-fail/trait-bounds-sugar.rs index 7ed8db4fcd291..4da496621d1c9 100644 --- a/src/test/compile-fail/trait-bounds-sugar.rs +++ b/src/test/compile-fail/trait-bounds-sugar.rs @@ -16,14 +16,14 @@ trait Foo {} fn a(_x: Box) { } -fn b(_x: &'static Foo+'static) { +fn b(_x: &'static (Foo+'static)) { } fn c(x: Box) { a(x); //~ ERROR mismatched types } -fn d(x: &'static Foo+Sync) { +fn d(x: &'static (Foo+Sync)) { b(x); //~ ERROR cannot infer //~^ ERROR mismatched types } diff --git a/src/test/run-pass/colorful-write-macros.rs b/src/test/run-pass/colorful-write-macros.rs index 75b8e39133105..bbb049eb96033 100644 --- a/src/test/run-pass/colorful-write-macros.rs +++ b/src/test/run-pass/colorful-write-macros.rs @@ -18,7 +18,7 @@ use std::fmt; use std::fmt::FormatWriter; struct Foo<'a> { - writer: &'a mut Writer+'a, + writer: &'a mut (Writer+'a), other: &'a str, } diff --git a/src/test/run-pass/dst-index.rs b/src/test/run-pass/dst-index.rs index 266f9bcba5f92..eaf7131e1d878 100644 --- a/src/test/run-pass/dst-index.rs +++ b/src/test/run-pass/dst-index.rs @@ -25,7 +25,7 @@ impl Index for S { struct T; impl Index for T { - fn index<'a>(&'a self, idx: &uint) -> &'a Show + 'static { + fn index<'a>(&'a self, idx: &uint) -> &'a (Show + 'static) { static x: uint = 42; &x } diff --git a/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs new file mode 100644 index 0000000000000..f942abe55c366 --- /dev/null +++ b/src/test/run-pass/hrtb-precedence-of-plus-where-clause.rs @@ -0,0 +1,27 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures)] + +// Test that `F : Fn(int) -> int + Send` is interpreted as two +// distinct bounds on `F`. + +fn foo(f: F) + where F : FnOnce(int) -> int + Send +{ + bar(&f); + baz(&f); +} + +fn bar(f: &F) { } + +fn baz int>(f: &F) { } + +fn main() {} diff --git a/src/test/run-pass/hrtb-precedence-of-plus.rs b/src/test/run-pass/hrtb-precedence-of-plus.rs new file mode 100644 index 0000000000000..9a43b5b711eb5 --- /dev/null +++ b/src/test/run-pass/hrtb-precedence-of-plus.rs @@ -0,0 +1,21 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(unboxed_closures)] + +// Test that `Fn(int) -> int + 'static` parses as `(Fn(int) -> int) + +// 'static` and not `Fn(int) -> (int + 'static)`. The latter would +// cause a compilation error. Issue #18772. + +fn adder(y: int) -> Box int + 'static> { + box move |&: x| y + x +} + +fn main() {} diff --git a/src/test/run-pass/issue-10902.rs b/src/test/run-pass/issue-10902.rs index 84d71e1ef5de6..324a1701b2feb 100644 --- a/src/test/run-pass/issue-10902.rs +++ b/src/test/run-pass/issue-10902.rs @@ -10,7 +10,7 @@ pub mod two_tuple { pub trait T {} - pub struct P<'a>(&'a T + 'a, &'a T + 'a); + pub struct P<'a>(&'a (T + 'a), &'a (T + 'a)); pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> { P(car, cdr) } @@ -18,7 +18,7 @@ pub mod two_tuple { pub mod two_fields { pub trait T {} - pub struct P<'a> { car: &'a T + 'a, cdr: &'a T + 'a } + pub struct P<'a> { car: &'a (T + 'a), cdr: &'a (T + 'a) } pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> { P{ car: car, cdr: cdr } } diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs index 89224e1fb12c4..ea138311f19b3 100644 --- a/src/test/run-pass/issue-11205.rs +++ b/src/test/run-pass/issue-11205.rs @@ -49,7 +49,7 @@ fn main() { foog(x, &[box 1i]); struct T<'a> { - t: [&'a Foo+'a, ..2] + t: [&'a (Foo+'a), ..2] } let _n = T { t: [&1i, &2i] @@ -64,7 +64,7 @@ fn main() { }; struct F<'b> { - t: &'b [&'b Foo+'b] + t: &'b [&'b (Foo+'b)] } let _n = F { t: &[&1i, &2i] diff --git a/src/test/run-pass/issue-14901.rs b/src/test/run-pass/issue-14901.rs index 647bbfbd65da0..e41754fd1b998 100644 --- a/src/test/run-pass/issue-14901.rs +++ b/src/test/run-pass/issue-14901.rs @@ -11,7 +11,7 @@ use std::io::Reader; enum Wrapper<'a> { - WrapReader(&'a Reader + 'a) + WrapReader(&'a (Reader + 'a)) } trait Wrap<'a> { diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs index 7f3321e0b3eed..1ffd349a65385 100644 --- a/src/test/run-pass/issue-14958.rs +++ b/src/test/run-pass/issue-14958.rs @@ -14,7 +14,7 @@ trait Foo {} struct Bar; -impl<'a> std::ops::Fn<(&'a Foo+'a,), ()> for Bar { +impl<'a> std::ops::Fn<(&'a (Foo+'a),), ()> for Bar { extern "rust-call" fn call(&self, _: (&'a Foo,)) {} } diff --git a/src/test/run-pass/issue-14959.rs b/src/test/run-pass/issue-14959.rs index 6cc5ab4d6cbaa..99472bb3610f8 100644 --- a/src/test/run-pass/issue-14959.rs +++ b/src/test/run-pass/issue-14959.rs @@ -33,8 +33,8 @@ impl Alloy { } } -impl<'a, 'b> Fn<(&'b mut Response+'b,),()> for SendFile<'a> { - extern "rust-call" fn call(&self, (_res,): (&'b mut Response+'b,)) {} +impl<'a, 'b> Fn<(&'b mut (Response+'b),),()> for SendFile<'a> { + extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {} } impl Ingot for HelloWorld { diff --git a/src/test/run-pass/issue-5708.rs b/src/test/run-pass/issue-5708.rs index 9c728005b6fb7..61ae273aef50b 100644 --- a/src/test/run-pass/issue-5708.rs +++ b/src/test/run-pass/issue-5708.rs @@ -29,7 +29,7 @@ impl Inner for int { } struct Outer<'a> { - inner: &'a Inner+'a + inner: &'a (Inner+'a) } impl<'a> Outer<'a> { @@ -51,7 +51,7 @@ pub fn main() { pub trait MyTrait { } pub struct MyContainer<'a, T> { - foos: Vec<&'a MyTrait+'a> , + foos: Vec<&'a (MyTrait+'a)> , } impl<'a, T> MyContainer<'a, T> { diff --git a/src/test/run-pass/issue-8249.rs b/src/test/run-pass/issue-8249.rs index dae5db11b0a80..44f07def531bc 100644 --- a/src/test/run-pass/issue-8249.rs +++ b/src/test/run-pass/issue-8249.rs @@ -13,7 +13,7 @@ struct B; impl A for B {} struct C<'a> { - foo: &'a mut A+'a, + foo: &'a mut (A+'a), } fn foo(a: &mut A) { diff --git a/src/test/run-pass/issue-9719.rs b/src/test/run-pass/issue-9719.rs index ebb9b20ec25fe..4c6b9a3aaa0e4 100644 --- a/src/test/run-pass/issue-9719.rs +++ b/src/test/run-pass/issue-9719.rs @@ -16,7 +16,7 @@ mod a { pub trait X {} impl X for int {} - pub struct Z<'a>(Enum<&'a X+'a>); + pub struct Z<'a>(Enum<&'a (X+'a)>); fn foo() { let x = 42i; let z = Z(Enum::A(&x as &X)); let _ = z; } } @@ -24,7 +24,7 @@ mod b { trait X {} impl X for int {} struct Y<'a>{ - x:Option<&'a X+'a>, + x:Option<&'a (X+'a)>, } fn bar() { @@ -36,7 +36,7 @@ mod b { mod c { pub trait X { fn f(&self); } impl X for int { fn f(&self) {} } - pub struct Z<'a>(Option<&'a X+'a>); + pub struct Z<'a>(Option<&'a (X+'a)>); fn main() { let x = 42i; let z = Z(Some(&x as &X)); let _ = z; } } diff --git a/src/test/run-pass/parameterized-trait-with-bounds.rs b/src/test/run-pass/parameterized-trait-with-bounds.rs index 339c9e3c490c7..840e58848a742 100644 --- a/src/test/run-pass/parameterized-trait-with-bounds.rs +++ b/src/test/run-pass/parameterized-trait-with-bounds.rs @@ -19,7 +19,7 @@ mod foo { pub trait D<'a, T> {} } -fn foo1(_: &A + Send) {} +fn foo1(_: &(A + Send)) {} fn foo2(_: Box + Send + Sync>) {} fn foo3(_: Box + 'static>) {} fn foo4<'a, T>(_: Box + 'static + Send>) {} diff --git a/src/test/run-pass/regions-early-bound-trait-param.rs b/src/test/run-pass/regions-early-bound-trait-param.rs index faf371e8826b2..907f610ff25db 100644 --- a/src/test/run-pass/regions-early-bound-trait-param.rs +++ b/src/test/run-pass/regions-early-bound-trait-param.rs @@ -30,7 +30,7 @@ fn object_invoke1<'d>(x: &'d Trait<'d>) -> (int, int) { } struct Struct1<'e> { - f: &'e Trait<'e>+'e + f: &'e (Trait<'e>+'e) } fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (int,int) { @@ -40,7 +40,7 @@ fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (int,int) { } struct Struct2<'h, 'i> { - f: &'h Trait<'i>+'h + f: &'h (Trait<'i>+'h) } fn object_invoke2<'j, 'k>(x: &'k Trait<'j>) -> int {