From 058abcc2094f7657063748f038470076b1e73a63 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 15 Nov 2014 16:04:04 -0500 Subject: Place parenthetical notation under the `unboxed_closure` feature-gate. Consolidate the `unboxed_closure_sugar` and `unboxed_closure` feature gates. --- src/libsyntax/feature_gate.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0c31e9ae01d..a36a0fbc826 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -59,7 +59,6 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("linkage", Active), ("struct_inherit", Removed), ("overloaded_calls", Active), - ("unboxed_closure_sugar", Active), ("quad_precision_float", Removed), @@ -381,7 +380,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { fn_decl: &'v ast::FnDecl, block: &'v ast::Block, span: Span, - _: NodeId) { + _node_id: NodeId) { match fn_kind { visit::FkItemFn(_, _, _, abi) if abi == RustIntrinsic => { self.gate_feature("intrinsics", @@ -392,6 +391,19 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } visit::walk_fn(self, fn_kind, fn_decl, block, span); } + + fn visit_path_parameters(&mut self, path_span: Span, parameters: &'v ast::PathParameters) { + match *parameters { + ast::ParenthesizedParameters(..) => { + self.gate_feature("unboxed_closures", + path_span, + "parenthetical parameter notation is subject to change"); + } + ast::AngleBracketedParameters(..) => { } + } + + visit::walk_path_parameters(self, path_span, parameters) + } } pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, Vec) { -- cgit 1.4.1-3-g733a5 From c8a94c5dfaaf5f1dacc110bb81d292c4382554d9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 15 Nov 2014 16:55:27 -0500 Subject: Convert TyPolyTraitRef to accept arbitary bounds, so that things like `Box Foo<&'a T> + 'a>` can be accepted. Also cleanup the visitor/fold in general, exposing more callbacks. --- src/librustc/middle/resolve.rs | 6 +- src/librustc/middle/typeck/astconv.rs | 66 ++++++++++++++++---- src/libsyntax/ast.rs | 2 +- src/libsyntax/ast_util.rs | 8 +-- src/libsyntax/fold.rs | 10 +-- src/libsyntax/parse/parser.rs | 17 +++++- src/libsyntax/print/pprust.rs | 4 +- src/libsyntax/visit.rs | 112 +++++++++++++++++++++------------- 8 files changed, 155 insertions(+), 70 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 94b52532a94..baf53cc34ba 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -5038,10 +5038,10 @@ impl<'a> Resolver<'a> { visit::walk_ty(self, ty); } - TyPolyTraitRef(ref poly_trait_ref) => { - self.resolve_poly_trait_reference( + TyPolyTraitRef(ref bounds) => { + self.resolve_type_parameter_bounds( ty.id, - &**poly_trait_ref, + bounds, TraitObject); visit::walk_ty(self, ty); } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 082b2acd1d8..d85f8eab7cd 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -883,15 +883,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( ty::mk_closure(tcx, fn_decl) } - ast::TyPolyTraitRef(ref data) => { - // FIXME(#18639) this is just a placeholder for code to come - let principal = instantiate_trait_ref(this, rscope, &data.trait_ref, None, None); - let bounds = conv_existential_bounds(this, - rscope, - ast_ty.span, - &[principal.clone()], - &[]); - ty::mk_trait(tcx, (*principal).clone(), bounds) + ast::TyPolyTraitRef(ref bounds) => { + conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice()) } ast::TyPath(ref path, ref bounds, id) => { let a_def = match tcx.def_map.borrow().get(&id) { @@ -1371,15 +1364,66 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>( let ast_bound_refs: Vec<&ast::TyParamBound> = ast_bounds.iter().collect(); + let partitioned_bounds = + partition_bounds(this.tcx(), span, ast_bound_refs.as_slice()); + + conv_existential_bounds_from_partitioned_bounds( + this, rscope, span, main_trait_refs, partitioned_bounds) +} + +fn conv_ty_poly_trait_ref<'tcx, AC, RS>( + this: &AC, + rscope: &RS, + span: Span, + ast_bounds: &[ast::TyParamBound]) + -> ty::t + where AC: AstConv<'tcx>, RS:RegionScope +{ + let ast_bounds: Vec<&ast::TyParamBound> = ast_bounds.iter().collect(); + let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]); + + let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) { + Some(trait_bound) => { + Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None, None)) + } + None => { + this.tcx().sess.span_err( + span, + "at least one non-builtin trait is required for an object type"); + None + } + }; + + let bounds = conv_existential_bounds_from_partitioned_bounds(this, + rscope, + span, + main_trait_bound.as_slice(), + partitioned_bounds); + + match main_trait_bound { + None => ty::mk_err(), + Some(principal) => ty::mk_trait(this.tcx(), (*principal).clone(), bounds) + } +} + +pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>( + this: &AC, + rscope: &RS, + span: Span, + main_trait_refs: &[Rc], + partitioned_bounds: PartitionedBounds) + -> ty::ExistentialBounds + where AC: AstConv<'tcx>, RS:RegionScope +{ let PartitionedBounds { builtin_bounds, trait_bounds, region_bounds } = - partition_bounds(this.tcx(), span, ast_bound_refs.as_slice()); + partitioned_bounds; if !trait_bounds.is_empty() { let b = &trait_bounds[0]; this.tcx().sess.span_err( - b.path.span, + b.trait_ref.path.span, format!("only the builtin traits can be used \ as closure or object bounds").as_slice()); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 0cb80d4c153..15e14902727 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1154,7 +1154,7 @@ pub enum Ty_ { /// Type parameters are stored in the Path itself TyPath(Path, Option, NodeId), // for #7264; see above /// A type like `for<'a> Foo<&'a Bar>` - TyPolyTraitRef(P), + TyPolyTraitRef(TyParamBounds), /// A "qualified path", e.g. ` as SomeTrait>::SomeType` TyQPath(P), /// No-op; kept solely so that we can pretty-print faithfully diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 2e3a15bfd4b..30cdecbc851 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -494,10 +494,10 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { } visit::walk_fn(self, - function_kind, - function_declaration, - block, - span); + function_kind, + function_declaration, + block, + span); if !self.pass_through_items { match function_kind { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 56d91282437..b3137ff5f7e 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -445,10 +445,12 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyFixedLengthVec(ty, e) => { TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e)) } - TyTypeof(expr) => TyTypeof(fld.fold_expr(expr)), - TyPolyTraitRef(poly_trait_ref) => { - TyPolyTraitRef(poly_trait_ref.map(|p| fld.fold_poly_trait_ref(p))) - }, + TyTypeof(expr) => { + TyTypeof(fld.fold_expr(expr)) + } + TyPolyTraitRef(bounds) => { + TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b))) + } }, span: fld.new_span(span) }) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 98479d65cbb..40c4ac9f8c0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1023,10 +1023,21 @@ impl<'a> Parser<'a> { self.parse_ty_bare_fn_or_ty_closure(lifetime_defs) } else if self.token == token::ModSep || self.token.is_ident() || - self.token.is_path() { + self.token.is_path() + { let trait_ref = self.parse_trait_ref(); - TyPolyTraitRef(P(PolyTraitRef { bound_lifetimes: lifetime_defs, - trait_ref: trait_ref })) + let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs, + trait_ref: trait_ref }; + let other_bounds = if self.eat(&token::BinOp(token::Plus)) { + self.parse_ty_param_bounds() + } else { + OwnedSlice::empty() + }; + let all_bounds = + Some(TraitTyParamBound(poly_trait_ref)).into_iter() + .chain(other_bounds.into_vec().into_iter()) + .collect(); + ast::TyPolyTraitRef(all_bounds) } else { self.parse_ty_closure(lifetime_defs) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0543b80f208..e6e0c33a42d 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -739,8 +739,8 @@ impl<'a> State<'a> { ast::TyPath(ref path, ref bounds, _) => { try!(self.print_bounded_path(path, bounds)); } - ast::TyPolyTraitRef(ref poly_trait_ref) => { - try!(self.print_poly_trait_ref(&**poly_trait_ref)); + ast::TyPolyTraitRef(ref bounds) => { + try!(self.print_bounds("", bounds)); } ast::TyQPath(ref qpath) => { try!(word(&mut self.s, "<")); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 2960c28a8b7..efe1e18eda9 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -78,6 +78,9 @@ pub trait Visitor<'v> { fn visit_ty_method(&mut self, t: &'v TypeMethod) { walk_ty_method(self, t) } fn visit_trait_item(&mut self, t: &'v TraitItem) { walk_trait_item(self, t) } fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) } + fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) { + walk_ty_param_bound(self, bounds) + } fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef) { walk_poly_trait_ref(self, t) } @@ -119,6 +122,12 @@ pub trait Visitor<'v> { fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) { walk_path(self, path) } + fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { + walk_path_segment(self, path_span, path_segment) + } + fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) { + walk_path_parameters(self, path_span, path_parameters) + } fn visit_attribute(&mut self, _attr: &'v Attribute) {} } @@ -170,7 +179,7 @@ pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) { ViewPathGlob(ref path, id) => { visitor.visit_path(path, id); } - ViewPathList(ref path, ref list, _) => { + ViewPathList(ref prefix, ref list, _) => { for id in list.iter() { match id.node { PathListIdent { name, .. } => { @@ -179,7 +188,10 @@ pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) { PathListMod { .. } => () } } - walk_path(visitor, path); + + // Note that the `prefix` here is not a complete + // path, so we don't use `visit_path`. + walk_path(visitor, prefix); } } } @@ -212,7 +224,7 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v PolyTraitRef) where V: Visitor<'v> { - walk_lifetime_decls(visitor, &trait_ref.bound_lifetimes); + walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes); visitor.visit_trait_ref(&trait_ref.trait_ref); } @@ -290,7 +302,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { } ItemTrait(ref generics, _, ref bounds, ref methods) => { visitor.visit_generics(generics); - walk_ty_param_bounds(visitor, bounds); + walk_ty_param_bounds_helper(visitor, bounds); for method in methods.iter() { visitor.visit_trait_item(method) } @@ -363,29 +375,29 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { visitor.visit_ty(&*argument.ty) } walk_fn_ret_ty(visitor, &function_declaration.decl.output); - walk_ty_param_bounds(visitor, &function_declaration.bounds); - walk_lifetime_decls(visitor, &function_declaration.lifetimes); + walk_ty_param_bounds_helper(visitor, &function_declaration.bounds); + walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } TyProc(ref function_declaration) => { for argument in function_declaration.decl.inputs.iter() { visitor.visit_ty(&*argument.ty) } walk_fn_ret_ty(visitor, &function_declaration.decl.output); - walk_ty_param_bounds(visitor, &function_declaration.bounds); - walk_lifetime_decls(visitor, &function_declaration.lifetimes); + walk_ty_param_bounds_helper(visitor, &function_declaration.bounds); + walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } TyBareFn(ref function_declaration) => { for argument in function_declaration.decl.inputs.iter() { visitor.visit_ty(&*argument.ty) } walk_fn_ret_ty(visitor, &function_declaration.decl.output); - walk_lifetime_decls(visitor, &function_declaration.lifetimes); + walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } TyPath(ref path, ref opt_bounds, id) => { visitor.visit_path(path, id); match *opt_bounds { Some(ref bounds) => { - walk_ty_param_bounds(visitor, bounds); + walk_ty_param_bounds_helper(visitor, bounds); } None => { } } @@ -399,8 +411,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { visitor.visit_ty(&**ty); visitor.visit_expr(&**expression) } - TyPolyTraitRef(ref poly_trait_ref) => { - visitor.visit_poly_trait_ref(&**poly_trait_ref) + TyPolyTraitRef(ref bounds) => { + walk_ty_param_bounds_helper(visitor, bounds) } TyTypeof(ref expression) => { visitor.visit_expr(&**expression) @@ -409,8 +421,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { } } -fn walk_lifetime_decls<'v, V: Visitor<'v>>(visitor: &mut V, - lifetimes: &'v Vec) { +pub fn walk_lifetime_decls_helper<'v, V: Visitor<'v>>(visitor: &mut V, + lifetimes: &'v Vec) { for l in lifetimes.iter() { visitor.visit_lifetime_decl(l); } @@ -418,24 +430,35 @@ fn walk_lifetime_decls<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { for segment in path.segments.iter() { - visitor.visit_ident(path.span, segment.identifier); + visitor.visit_path_segment(path.span, segment); + } +} - match segment.parameters { - ast::AngleBracketedParameters(ref data) => { - for typ in data.types.iter() { - visitor.visit_ty(&**typ); - } - for lifetime in data.lifetimes.iter() { - visitor.visit_lifetime_ref(lifetime); - } +pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, + path_span: Span, + segment: &'v PathSegment) { + visitor.visit_ident(path_span, segment.identifier); + visitor.visit_path_parameters(path_span, &segment.parameters); +} + +pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V, + _path_span: Span, + path_parameters: &'v PathParameters) { + match *path_parameters { + ast::AngleBracketedParameters(ref data) => { + for typ in data.types.iter() { + visitor.visit_ty(&**typ); } - ast::ParenthesizedParameters(ref data) => { - for typ in data.inputs.iter() { - visitor.visit_ty(&**typ); - } - for typ in data.output.iter() { - visitor.visit_ty(&**typ); - } + for lifetime in data.lifetimes.iter() { + visitor.visit_lifetime_ref(lifetime); + } + } + ast::ParenthesizedParameters(ref data) => { + for typ in data.inputs.iter() { + visitor.visit_ty(&**typ); + } + for typ in data.output.iter() { + visitor.visit_ty(&**typ); } } } @@ -511,32 +534,37 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, } } -pub fn walk_ty_param_bounds<'v, V: Visitor<'v>>(visitor: &mut V, - bounds: &'v OwnedSlice) { +pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V, + bounds: &'v OwnedSlice) { for bound in bounds.iter() { - match *bound { - TraitTyParamBound(ref typ) => { - visitor.visit_poly_trait_ref(typ) - } - RegionTyParamBound(ref lifetime) => { - visitor.visit_lifetime_ref(lifetime); - } + visitor.visit_ty_param_bound(bound) + } +} + +pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, + bound: &'v TyParamBound) { + match *bound { + TraitTyParamBound(ref typ) => { + visitor.visit_poly_trait_ref(typ); + } + RegionTyParamBound(ref lifetime) => { + visitor.visit_lifetime_ref(lifetime); } } } pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { for type_parameter in generics.ty_params.iter() { - walk_ty_param_bounds(visitor, &type_parameter.bounds); + walk_ty_param_bounds_helper(visitor, &type_parameter.bounds); match type_parameter.default { Some(ref ty) => visitor.visit_ty(&**ty), None => {} } } - walk_lifetime_decls(visitor, &generics.lifetimes); + walk_lifetime_decls_helper(visitor, &generics.lifetimes); for predicate in generics.where_clause.predicates.iter() { visitor.visit_ident(predicate.span, predicate.ident); - walk_ty_param_bounds(visitor, &predicate.bounds); + walk_ty_param_bounds_helper(visitor, &predicate.bounds); } } -- cgit 1.4.1-3-g733a5 From 56ba260749bbd30321bcbe755652ef215106719c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 15 Nov 2014 19:10:22 -0500 Subject: Update test for equivalency to include region binders in object types, add new tests relating to HRTB, consolidate the `unboxed_closures` and `overloaded_calls` feature gates. --- src/doc/reference.md | 8 +-- src/librustc/middle/typeck/check/mod.rs | 4 +- src/libsyntax/feature_gate.rs | 7 ++- src/test/auxiliary/issue-18711.rs | 2 +- src/test/auxiliary/unboxed-closures-cross-crate.rs | 2 +- src/test/bench/shootout-reverse-complement.rs | 2 +- src/test/bench/shootout-spectralnorm.rs | 2 +- src/test/compile-fail/borrowck-overloaded-call.rs | 2 +- .../hrtb-higher-ranker-supertraits-transitive.rs | 60 ++++++++++++++++++++++ .../compile-fail/hrtb-higher-ranker-supertraits.rs | 58 +++++++++++++++++++++ src/test/compile-fail/hrtb-identity-fn-borrows.rs | 35 +++++++++++++ src/test/compile-fail/issue-15094.rs | 2 +- src/test/compile-fail/issue-18532.rs | 2 +- src/test/compile-fail/overloaded-calls-bad.rs | 2 +- src/test/compile-fail/overloaded-calls-nontuple.rs | 2 +- .../stage0-clone-contravariant-lifetime.rs | 43 ++++++++++++++++ src/test/compile-fail/stage0-cmp.rs | 40 +++++++++++++++ .../compile-fail/unboxed-closure-sugar-equiv.rs | 26 ++++++++-- src/test/run-pass/bare-fn-implements-fn-mut.rs | 2 +- .../run-pass/capture-clauses-unboxed-closures.rs | 2 +- .../run-pass/hrtb-binder-levels-in-object-types.rs | 34 ++++++++++++ .../hrtb-debruijn-object-types-in-closures.rs | 23 +++++++++ src/test/run-pass/hrtb-fn-like-trait-object.rs | 35 +++++++++++++ src/test/run-pass/hrtb-fn-like-trait.rs | 35 +++++++++++++ src/test/run-pass/hrtb-resolve-lifetime.rs | 20 ++++++++ .../run-pass/hrtb-trait-object-paren-notation.rs | 37 +++++++++++++ .../hrtb-trait-object-passed-to-closure.rs | 31 +++++++++++ src/test/run-pass/hrtb-unboxed-closure-trait.rs | 22 ++++++++ src/test/run-pass/issue-14958.rs | 2 +- src/test/run-pass/issue-14959.rs | 2 +- src/test/run-pass/issue-16774.rs | 2 +- src/test/run-pass/issue-18652.rs | 2 +- src/test/run-pass/issue-18661.rs | 2 +- src/test/run-pass/issue-18685.rs | 2 +- src/test/run-pass/issue-18711.rs | 2 +- .../run-pass/overloaded-calls-param-vtables.rs | 2 +- src/test/run-pass/overloaded-calls-simple.rs | 2 +- src/test/run-pass/overloaded-calls-zero-args.rs | 2 +- src/test/run-pass/unboxed-closures-all-traits.rs | 2 +- src/test/run-pass/unboxed-closures-by-ref.rs | 2 +- .../unboxed-closures-direct-sugary-call.rs | 2 +- src/test/run-pass/unboxed-closures-drop.rs | 2 +- src/test/run-pass/unboxed-closures-extern-fn.rs | 2 +- .../unboxed-closures-fn-as-fnmut-and-fnonce.rs | 2 +- .../run-pass/unboxed-closures-fnmut-as-fnonce.rs | 2 +- .../run-pass/unboxed-closures-single-word-env.rs | 2 +- src/test/run-pass/unboxed-closures-sugar-1.rs | 34 ------------ .../run-pass/unboxed-closures-unique-type-id.rs | 2 +- 48 files changed, 531 insertions(+), 81 deletions(-) create mode 100644 src/test/compile-fail/hrtb-higher-ranker-supertraits-transitive.rs create mode 100644 src/test/compile-fail/hrtb-higher-ranker-supertraits.rs create mode 100644 src/test/compile-fail/hrtb-identity-fn-borrows.rs create mode 100644 src/test/compile-fail/stage0-clone-contravariant-lifetime.rs create mode 100644 src/test/compile-fail/stage0-cmp.rs create mode 100644 src/test/run-pass/hrtb-binder-levels-in-object-types.rs create mode 100644 src/test/run-pass/hrtb-debruijn-object-types-in-closures.rs create mode 100644 src/test/run-pass/hrtb-fn-like-trait-object.rs create mode 100644 src/test/run-pass/hrtb-fn-like-trait.rs create mode 100644 src/test/run-pass/hrtb-resolve-lifetime.rs create mode 100644 src/test/run-pass/hrtb-trait-object-paren-notation.rs create mode 100644 src/test/run-pass/hrtb-trait-object-passed-to-closure.rs create mode 100644 src/test/run-pass/hrtb-unboxed-closure-trait.rs delete mode 100644 src/test/run-pass/unboxed-closures-sugar-1.rs (limited to 'src/libsyntax') diff --git a/src/doc/reference.md b/src/doc/reference.md index dcf3f9826c2..62e0f5e4f1f 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2513,11 +2513,6 @@ The currently implemented features of the reference compiler are: closure as `once` is unlikely to be supported going forward. So they are hidden behind this feature until they are to be removed. -* `overloaded_calls` - Allow implementing the `Fn*` family of traits on user - types, allowing overloading the call operator (`()`). - This feature may still undergo changes before being - stabilized. - * `phase` - Usage of the `#[phase]` attribute allows loading compiler plugins for custom lints or syntax extensions. The implementation is considered unwholesome and in need of overhaul, and it is not clear @@ -2560,7 +2555,8 @@ The currently implemented features of the reference compiler are: * `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty hack that will certainly be removed. -* `unboxed_closures` - A work in progress feature with many known bugs. +* `unboxed_closures` - Rust's new closure design, which is currently a work in + progress feature with many known bugs. * `unsafe_destructor` - Allows use of the `#[unsafe_destructor]` attribute, which is considered wildly unsafe and will be diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index ea6028acf24..8ae5c3a0a95 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2264,11 +2264,11 @@ fn try_overloaded_call<'a>(fcx: &FnCtxt, fcx.inh.method_map.borrow_mut().insert(method_call, method_callee); write_call(fcx, call_expression, output_type); - if !fcx.tcx().sess.features.borrow().overloaded_calls { + if !fcx.tcx().sess.features.borrow().unboxed_closures { span_err!(fcx.tcx().sess, call_expression.span, E0056, "overloaded calls are experimental"); span_help!(fcx.tcx().sess, call_expression.span, - "add `#![feature(overloaded_calls)]` to \ + "add `#![feature(unboxed_closures)]` to \ the crate attributes to enable"); } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a36a0fbc826..ebdcf278934 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -58,7 +58,6 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("quote", Active), ("linkage", Active), ("struct_inherit", Removed), - ("overloaded_calls", Active), ("quad_precision_float", Removed), @@ -101,7 +100,7 @@ enum Status { /// A set of features to be used by later passes. pub struct Features { pub default_type_params: bool, - pub overloaded_calls: bool, + pub unboxed_closures: bool, pub rustc_diagnostic_macros: bool, pub import_shadowing: bool, pub visible_private_types: bool, @@ -112,7 +111,7 @@ impl Features { pub fn new() -> Features { Features { default_type_params: false, - overloaded_calls: false, + unboxed_closures: false, rustc_diagnostic_macros: false, import_shadowing: false, visible_private_types: false, @@ -458,7 +457,7 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, (Features { default_type_params: cx.has_feature("default_type_params"), - overloaded_calls: cx.has_feature("overloaded_calls"), + unboxed_closures: cx.has_feature("unboxed_closures"), rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"), import_shadowing: cx.has_feature("import_shadowing"), visible_private_types: cx.has_feature("visible_private_types"), diff --git a/src/test/auxiliary/issue-18711.rs b/src/test/auxiliary/issue-18711.rs index 454e67b8bd5..54f1595780d 100644 --- a/src/test/auxiliary/issue-18711.rs +++ b/src/test/auxiliary/issue-18711.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures, overloaded_calls)] +#![feature(unboxed_closures)] #![crate_type = "rlib"] pub fn inner(f: F) -> F { diff --git a/src/test/auxiliary/unboxed-closures-cross-crate.rs b/src/test/auxiliary/unboxed-closures-cross-crate.rs index d04829bb808..9a6a2c7495b 100644 --- a/src/test/auxiliary/unboxed-closures-cross-crate.rs +++ b/src/test/auxiliary/unboxed-closures-cross-crate.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures, overloaded_calls)] +#![feature(unboxed_closures)] #[inline] pub fn has_closures() -> uint { diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index d7d8e94c8a7..ffe5739e0bb 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -40,7 +40,7 @@ // ignore-android see #10393 #13206 -#![feature(slicing_syntax, unboxed_closures, overloaded_calls)] +#![feature(slicing_syntax, unboxed_closures)] extern crate libc; diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index c5f2fbb1890..acb289aa3ad 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -41,7 +41,7 @@ // no-pretty-expanded FIXME #15189 #![allow(non_snake_case)] -#![feature(unboxed_closures, overloaded_calls)] +#![feature(unboxed_closures)] use std::iter::AdditiveIterator; use std::mem; diff --git a/src/test/compile-fail/borrowck-overloaded-call.rs b/src/test/compile-fail/borrowck-overloaded-call.rs index f134c2aa09b..938fc53d610 100644 --- a/src/test/compile-fail/borrowck-overloaded-call.rs +++ b/src/test/compile-fail/borrowck-overloaded-call.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::{Fn, FnMut, FnOnce}; diff --git a/src/test/compile-fail/hrtb-higher-ranker-supertraits-transitive.rs b/src/test/compile-fail/hrtb-higher-ranker-supertraits-transitive.rs new file mode 100644 index 00000000000..4199deee7b8 --- /dev/null +++ b/src/test/compile-fail/hrtb-higher-ranker-supertraits-transitive.rs @@ -0,0 +1,60 @@ +// 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. + +// Test HRTB supertraits with several levels of expansion required. + +trait Foo<'tcx> +{ + fn foo(&'tcx self) -> &'tcx int; +} + +trait Bar<'ccx> + : for<'tcx> Foo<'tcx> +{ + fn bar(&'ccx self) -> &'ccx int; +} + +trait Baz + : for<'ccx> Bar<'ccx> +{ + fn dummy(&self); +} + +trait Qux + : Bar<'static> +{ + fn dummy(&self); +} + +fn want_foo_for_any_tcx(f: &F) + where F : for<'tcx> Foo<'tcx> +{ +} + +fn want_bar_for_any_ccx(b: &B) + where B : for<'ccx> Bar<'ccx> +{ +} + +fn want_baz(b: &B) + where B : Baz +{ + want_foo_for_any_tcx(b); + want_bar_for_any_ccx(b); +} + +fn want_qux(b: &B) + where B : Qux +{ + want_foo_for_any_tcx(b); + want_bar_for_any_ccx(b); //~ ERROR not implemented +} + +fn main() {} diff --git a/src/test/compile-fail/hrtb-higher-ranker-supertraits.rs b/src/test/compile-fail/hrtb-higher-ranker-supertraits.rs new file mode 100644 index 00000000000..108ca1b82e0 --- /dev/null +++ b/src/test/compile-fail/hrtb-higher-ranker-supertraits.rs @@ -0,0 +1,58 @@ +// 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. + +// Test a trait (`Bar`) with a higher-ranked supertrait. + +trait Foo<'tcx> +{ + fn foo(&'tcx self) -> &'tcx int; +} + +trait Bar<'ccx> + : for<'tcx> Foo<'tcx> +{ + fn bar(&'ccx self) -> &'ccx int; +} + +fn want_foo_for_some_tcx<'x,F>(f: &'x F) + where F : Foo<'x> +{ + want_foo_for_some_tcx(f); + want_foo_for_any_tcx(f); //~ ERROR not implemented +} + +fn want_foo_for_any_tcx(f: &F) + where F : for<'tcx> Foo<'tcx> +{ + want_foo_for_some_tcx(f); + want_foo_for_any_tcx(f); +} + +fn want_bar_for_some_ccx<'x,B>(b: &B) + where B : Bar<'x> +{ + want_foo_for_some_tcx(b); + want_foo_for_any_tcx(b); + + want_bar_for_some_ccx(b); + want_bar_for_any_ccx(b); //~ ERROR not implemented +} + +fn want_bar_for_any_ccx(b: &B) + where B : for<'ccx> Bar<'ccx> +{ + want_foo_for_some_tcx(b); + want_foo_for_any_tcx(b); + + want_bar_for_some_ccx(b); + want_bar_for_any_ccx(b); +} + +fn main() {} diff --git a/src/test/compile-fail/hrtb-identity-fn-borrows.rs b/src/test/compile-fail/hrtb-identity-fn-borrows.rs new file mode 100644 index 00000000000..733a5b2a85a --- /dev/null +++ b/src/test/compile-fail/hrtb-identity-fn-borrows.rs @@ -0,0 +1,35 @@ +// 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. + +// Test that the `'a` in the where clause correctly links the region +// of the output to the region of the input. + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +fn call_repeatedly(f: F) + where F : for<'a> FnLike<&'a int, &'a int> +{ + // Result is stored: cannot re-assign `x` + let mut x = 3; + let y = f.call(&x); + x = 5; //~ ERROR cannot assign + + // Result is not stored: can re-assign `x` + let mut x = 3; + f.call(&x); + f.call(&x); + f.call(&x); + x = 5; +} + +fn main() { +} diff --git a/src/test/compile-fail/issue-15094.rs b/src/test/compile-fail/issue-15094.rs index c9e47b74d51..dd3c88b8a10 100644 --- a/src/test/compile-fail/issue-15094.rs +++ b/src/test/compile-fail/issue-15094.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::{fmt, ops}; diff --git a/src/test/compile-fail/issue-18532.rs b/src/test/compile-fail/issue-18532.rs index a67f4c851bf..943d326182f 100644 --- a/src/test/compile-fail/issue-18532.rs +++ b/src/test/compile-fail/issue-18532.rs @@ -12,7 +12,7 @@ // when a type error or unconstrained type variable propagates // into it. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] fn main() { (return)((),()); diff --git a/src/test/compile-fail/overloaded-calls-bad.rs b/src/test/compile-fail/overloaded-calls-bad.rs index cc01c0b3c9f..b3a4c312589 100644 --- a/src/test/compile-fail/overloaded-calls-bad.rs +++ b/src/test/compile-fail/overloaded-calls-bad.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::FnMut; diff --git a/src/test/compile-fail/overloaded-calls-nontuple.rs b/src/test/compile-fail/overloaded-calls-nontuple.rs index ee2fe352247..396a809c2e1 100644 --- a/src/test/compile-fail/overloaded-calls-nontuple.rs +++ b/src/test/compile-fail/overloaded-calls-nontuple.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::FnMut; diff --git a/src/test/compile-fail/stage0-clone-contravariant-lifetime.rs b/src/test/compile-fail/stage0-clone-contravariant-lifetime.rs new file mode 100644 index 00000000000..1d1b244ab5a --- /dev/null +++ b/src/test/compile-fail/stage0-clone-contravariant-lifetime.rs @@ -0,0 +1,43 @@ +// 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. + +// A zero-dependency test that covers some basic traits, default +// methods, etc. When mucking about with basic type system stuff I +// often encounter problems in the iterator trait, so it's useful to +// have hanging around. -nmatsakis + +// error-pattern: requires `start` lang_item + +#![no_std] +#![feature(lang_items)] + +#[lang = "sized"] +pub trait Sized for Sized? { + // Empty. +} + +pub mod std { + pub mod clone { + pub trait Clone { + fn clone(&self) -> Self; + } + } +} + +pub struct ContravariantLifetime<'a>; + +impl <'a> ::std::clone::Clone for ContravariantLifetime<'a> { + #[inline] + fn clone(&self) -> ContravariantLifetime<'a> { + match *self { ContravariantLifetime => ContravariantLifetime, } + } +} + +fn main() { } diff --git a/src/test/compile-fail/stage0-cmp.rs b/src/test/compile-fail/stage0-cmp.rs new file mode 100644 index 00000000000..2c0772b1414 --- /dev/null +++ b/src/test/compile-fail/stage0-cmp.rs @@ -0,0 +1,40 @@ +// 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. + + +// A zero-dependency test that covers some basic traits, default +// methods, etc. When mucking about with basic type system stuff I +// often encounter problems in the iterator trait, so it's useful to +// have hanging around. -nmatsakis + +// error-pattern: requires `start` lang_item + +#![no_std] +#![feature(lang_items)] + +#[lang = "sized"] +pub trait Sized for Sized? { + // Empty. +} + +#[unstable = "Definition may change slightly after trait reform"] +pub trait PartialEq for Sized? { + /// This method tests for `self` and `other` values to be equal, and is used by `==`. + fn eq(&self, other: &Self) -> bool; +} + +#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot +#[unstable = "Trait is unstable."] +impl<'a, Sized? T: PartialEq> PartialEq for &'a T { + #[inline] + fn eq(&self, other: & &'a T) -> bool { PartialEq::eq(*self, *other) } +} + +fn main() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs index f858793b9ec..6f875efdef7 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs @@ -16,13 +16,13 @@ #![feature(unboxed_closures)] #![allow(dead_code)] -struct Foo { - t: T, u: U +trait Foo { + fn dummy(&self, t: T, u: U); } -trait Eq { } -impl Eq for X { } -fn eq>() { } +trait Eq for Sized? { } +impl Eq for X { } +fn eq>() { } fn test<'a,'b>() { // No errors expected: @@ -32,6 +32,22 @@ fn test<'a,'b>() { eq::< Foo<(int,uint),uint>, Foo(int,uint) -> uint >(); eq::< Foo<(&'a int,&'b uint),uint>, Foo(&'a int,&'b uint) -> uint >(); + // Test that anonymous regions in `()` form are equivalent + // to fresh bound regions, and that we can intermingle + // named and anonymous as we choose: + eq::< for<'a,'b> Foo<(&'a int,&'b uint),uint>, + for<'a,'b> Foo(&'a int,&'b uint) -> uint >(); + eq::< for<'a,'b> Foo<(&'a int,&'b uint),uint>, + for<'a> Foo(&'a int,&uint) -> uint >(); + eq::< for<'a,'b> Foo<(&'a int,&'b uint),uint>, + for<'b> Foo(&int,&'b uint) -> uint >(); + eq::< for<'a,'b> Foo<(&'a int,&'b uint),uint>, + Foo(&int,&uint) -> uint >(); + + // FIXME(#18992) Test lifetime elision in `()` form: + // eq::< for<'a,'b> Foo<(&'a int,), &'a int>, + // Foo(&int) -> &int >(); + // Errors expected: eq::< Foo<(),()>, Foo(char) >(); //~^ ERROR not implemented diff --git a/src/test/run-pass/bare-fn-implements-fn-mut.rs b/src/test/run-pass/bare-fn-implements-fn-mut.rs index 4962e9d0f22..9d104afd646 100644 --- a/src/test/run-pass/bare-fn-implements-fn-mut.rs +++ b/src/test/run-pass/bare-fn-implements-fn-mut.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::FnMut; diff --git a/src/test/run-pass/capture-clauses-unboxed-closures.rs b/src/test/run-pass/capture-clauses-unboxed-closures.rs index 9f333fd043f..cd40e2a7843 100644 --- a/src/test/run-pass/capture-clauses-unboxed-closures.rs +++ b/src/test/run-pass/capture-clauses-unboxed-closures.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls, unboxed_closures)] +#![feature(unboxed_closures)] fn each<'a,T,F:FnMut(&'a T)>(x: &'a [T], mut f: F) { for val in x.iter() { diff --git a/src/test/run-pass/hrtb-binder-levels-in-object-types.rs b/src/test/run-pass/hrtb-binder-levels-in-object-types.rs new file mode 100644 index 00000000000..5a793f7065a --- /dev/null +++ b/src/test/run-pass/hrtb-binder-levels-in-object-types.rs @@ -0,0 +1,34 @@ +// 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. + +// Test that we handle binder levels in object types correctly. +// Initially, the reference to `'tcx` in the object type +// `&Typer<'tcx>` was getting an incorrect binder level, yielding +// weird compilation ICEs and so forth. + +trait Typer<'tcx> { + fn method(&self, data: &'tcx int) -> &'tcx int { data } +} + +struct Tcx<'tcx> { + fields: &'tcx int +} + +impl<'tcx> Typer<'tcx> for Tcx<'tcx> { +} + +fn g<'tcx>(typer: &Typer<'tcx>) { +} + +fn check_static_type<'x>(tcx: &Tcx<'x>) { + g(tcx) +} + +fn main() { } diff --git a/src/test/run-pass/hrtb-debruijn-object-types-in-closures.rs b/src/test/run-pass/hrtb-debruijn-object-types-in-closures.rs new file mode 100644 index 00000000000..5bdfa3cafd7 --- /dev/null +++ b/src/test/run-pass/hrtb-debruijn-object-types-in-closures.rs @@ -0,0 +1,23 @@ +// 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. + +trait Typer<'tcx> { + fn method(&self, data: &'tcx int) -> &'tcx int { data } + fn dummy(&self) { } +} + +fn g(_: |&Typer|) { +} + +fn h() { + g(|typer| typer.dummy()) +} + +fn main() { } diff --git a/src/test/run-pass/hrtb-fn-like-trait-object.rs b/src/test/run-pass/hrtb-fn-like-trait-object.rs new file mode 100644 index 00000000000..c8992afe36a --- /dev/null +++ b/src/test/run-pass/hrtb-fn-like-trait-object.rs @@ -0,0 +1,35 @@ +// 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. + +// A basic test of using a higher-ranked trait bound. + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +type FnObject<'b> = for<'a> FnLike<&'a int, &'a int> + 'b; + +struct Identity; + +impl<'a, T> FnLike<&'a T, &'a T> for Identity { + fn call(&self, arg: &'a T) -> &'a T { + arg + } +} + +fn call_repeatedly(f: &FnObject) { + let x = 3; + let y = f.call(&x); + assert_eq!(3, *y); +} + +fn main() { + call_repeatedly(&Identity); +} diff --git a/src/test/run-pass/hrtb-fn-like-trait.rs b/src/test/run-pass/hrtb-fn-like-trait.rs new file mode 100644 index 00000000000..4067b922cfd --- /dev/null +++ b/src/test/run-pass/hrtb-fn-like-trait.rs @@ -0,0 +1,35 @@ +// 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. + +// A basic test of using a higher-ranked trait bound. + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +struct Identity; + +impl<'a, T> FnLike<&'a T, &'a T> for Identity { + fn call(&self, arg: &'a T) -> &'a T { + arg + } +} + +fn call_repeatedly(f: F) + where F : for<'a> FnLike<&'a int, &'a int> +{ + let x = 3; + let y = f.call(&x); + assert_eq!(3, *y); +} + +fn main() { + call_repeatedly(Identity); +} diff --git a/src/test/run-pass/hrtb-resolve-lifetime.rs b/src/test/run-pass/hrtb-resolve-lifetime.rs new file mode 100644 index 00000000000..9b37b8e49ef --- /dev/null +++ b/src/test/run-pass/hrtb-resolve-lifetime.rs @@ -0,0 +1,20 @@ +// 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. + +// A basic test of using a higher-ranked trait bound. + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +type FnObject<'b> = for<'a> FnLike<&'a int, &'a int> + 'b; + +fn main() { +} diff --git a/src/test/run-pass/hrtb-trait-object-paren-notation.rs b/src/test/run-pass/hrtb-trait-object-paren-notation.rs new file mode 100644 index 00000000000..e17e0ae2189 --- /dev/null +++ b/src/test/run-pass/hrtb-trait-object-paren-notation.rs @@ -0,0 +1,37 @@ +// 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)] + +// A basic test of using a higher-ranked trait bound. + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +type FnObject<'b> = for<'a> FnLike(&'a int) -> (&'a int) + 'b; + +struct Identity; + +impl<'a, T> FnLike<(&'a T,), &'a T> for Identity { + fn call(&self, (arg,): (&'a T,)) -> &'a T { + arg + } +} + +fn call_repeatedly(f: &FnObject) { + let x = 3; + let y = f.call((&x,)); + assert_eq!(3, *y); +} + +fn main() { + call_repeatedly(&Identity); +} diff --git a/src/test/run-pass/hrtb-trait-object-passed-to-closure.rs b/src/test/run-pass/hrtb-trait-object-passed-to-closure.rs new file mode 100644 index 00000000000..076b9c7684e --- /dev/null +++ b/src/test/run-pass/hrtb-trait-object-passed-to-closure.rs @@ -0,0 +1,31 @@ +// 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. + +// Test that `&PrinterSupport`, which is really short for `&'a +// PrinterSupport<'b>`, gets properly expanded when it appears in a +// closure type. This used to result in messed up De Bruijn indices. + +trait PrinterSupport<'ast> { + fn ast_map(&self) -> Option<&'ast uint> { None } +} + +struct NoAnn<'ast> { + f: Option<&'ast uint> +} + +impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> { +} + +fn foo<'ast> (f: Option<&'ast uint>, g: |&PrinterSupport|) { + let annotation = NoAnn { f: f }; + g(&annotation) +} + +fn main() {} diff --git a/src/test/run-pass/hrtb-unboxed-closure-trait.rs b/src/test/run-pass/hrtb-unboxed-closure-trait.rs new file mode 100644 index 00000000000..fea628177da --- /dev/null +++ b/src/test/run-pass/hrtb-unboxed-closure-trait.rs @@ -0,0 +1,22 @@ +// 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. + +// Test HRTB used with the `Fn` trait. + +#![feature(unboxed_closures)] + +fn foo(f: F) { + let x = 22; + f(&x); +} + +fn main() { + foo(|&: x: &int| println!("{}", *x)); +} diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs index c2bd8c5b3e5..7f3321e0b3e 100644 --- a/src/test/run-pass/issue-14958.rs +++ b/src/test/run-pass/issue-14958.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] trait Foo {} diff --git a/src/test/run-pass/issue-14959.rs b/src/test/run-pass/issue-14959.rs index 5429c519592..6cc5ab4d6cb 100644 --- a/src/test/run-pass/issue-14959.rs +++ b/src/test/run-pass/issue-14959.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::Fn; diff --git a/src/test/run-pass/issue-16774.rs b/src/test/run-pass/issue-16774.rs index f996f9309c1..ebc879d82fb 100644 --- a/src/test/run-pass/issue-16774.rs +++ b/src/test/run-pass/issue-16774.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls, unboxed_closures)] +#![feature(unboxed_closures)] struct X(Box); diff --git a/src/test/run-pass/issue-18652.rs b/src/test/run-pass/issue-18652.rs index 5ca09100060..ef2c15c748c 100644 --- a/src/test/run-pass/issue-18652.rs +++ b/src/test/run-pass/issue-18652.rs @@ -12,7 +12,7 @@ // once closure as an optimization by trans. This used to hit an // incorrect assert. -#![feature(unboxed_closures, overloaded_calls)] +#![feature(unboxed_closures)] fn main() { let x = 2u8; diff --git a/src/test/run-pass/issue-18661.rs b/src/test/run-pass/issue-18661.rs index 6bade86fd3e..6a2f73a787a 100644 --- a/src/test/run-pass/issue-18661.rs +++ b/src/test/run-pass/issue-18661.rs @@ -11,7 +11,7 @@ // Test that param substitutions from the correct environment are // used when translating unboxed closure calls. -#![feature(unboxed_closures, unboxed_closures)] +#![feature(unboxed_closures)] pub fn inside(c: F) { c.call(()); diff --git a/src/test/run-pass/issue-18685.rs b/src/test/run-pass/issue-18685.rs index 1f74e2f8474..be6dd583132 100644 --- a/src/test/run-pass/issue-18685.rs +++ b/src/test/run-pass/issue-18685.rs @@ -11,7 +11,7 @@ // Test that the self param space is not used in a conflicting // manner by unboxed closures within a default method on a trait -#![feature(unboxed_closures, overloaded_calls)] +#![feature(unboxed_closures)] trait Tr { fn foo(&self); diff --git a/src/test/run-pass/issue-18711.rs b/src/test/run-pass/issue-18711.rs index 2d16aa7f0c3..6a04e68af0c 100644 --- a/src/test/run-pass/issue-18711.rs +++ b/src/test/run-pass/issue-18711.rs @@ -11,7 +11,7 @@ // Test that we don't panic on a RefCell borrow conflict in certain // code paths involving unboxed closures. -#![feature(unboxed_closures, overloaded_calls)] +#![feature(unboxed_closures)] // aux-build:issue-18711.rs extern crate "issue-18711" as issue; diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs index 6f870f0afd5..d0dbee39ae0 100644 --- a/src/test/run-pass/overloaded-calls-param-vtables.rs +++ b/src/test/run-pass/overloaded-calls-param-vtables.rs @@ -10,7 +10,7 @@ // Tests that nested vtables work with overloaded calls. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::Fn; diff --git a/src/test/run-pass/overloaded-calls-simple.rs b/src/test/run-pass/overloaded-calls-simple.rs index 76c7e60116f..b0a40f74ff9 100644 --- a/src/test/run-pass/overloaded-calls-simple.rs +++ b/src/test/run-pass/overloaded-calls-simple.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, overloaded_calls)] +#![feature(lang_items, unboxed_closures)] use std::ops::{Fn, FnMut, FnOnce}; diff --git a/src/test/run-pass/overloaded-calls-zero-args.rs b/src/test/run-pass/overloaded-calls-zero-args.rs index b868c8c96b5..809a251fe80 100644 --- a/src/test/run-pass/overloaded-calls-zero-args.rs +++ b/src/test/run-pass/overloaded-calls-zero-args.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::{FnMut}; diff --git a/src/test/run-pass/unboxed-closures-all-traits.rs b/src/test/run-pass/unboxed-closures-all-traits.rs index e8eeab3e4f3..635e1670aad 100644 --- a/src/test/run-pass/unboxed-closures-all-traits.rs +++ b/src/test/run-pass/unboxed-closures-all-traits.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(lang_items, overloaded_calls, unboxed_closures, unboxed_closures)] +#![feature(lang_items, unboxed_closures)] fn a int>(f: F) -> int { f(1, 2) diff --git a/src/test/run-pass/unboxed-closures-by-ref.rs b/src/test/run-pass/unboxed-closures-by-ref.rs index 70d41a5c689..be955486dac 100644 --- a/src/test/run-pass/unboxed-closures-by-ref.rs +++ b/src/test/run-pass/unboxed-closures-by-ref.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(overloaded_calls, unboxed_closures)] +#![feature(unboxed_closures)] // Test by-ref capture of environment in unboxed closure types diff --git a/src/test/run-pass/unboxed-closures-direct-sugary-call.rs b/src/test/run-pass/unboxed-closures-direct-sugary-call.rs index c77ee9914ef..2854d64f663 100644 --- a/src/test/run-pass/unboxed-closures-direct-sugary-call.rs +++ b/src/test/run-pass/unboxed-closures-direct-sugary-call.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(unboxed_closures, overloaded_calls)] +#![feature(unboxed_closures)] fn main() { let mut unboxed = |&mut:| {}; diff --git a/src/test/run-pass/unboxed-closures-drop.rs b/src/test/run-pass/unboxed-closures-drop.rs index 00bf5fac095..8d4d7b4ecb5 100644 --- a/src/test/run-pass/unboxed-closures-drop.rs +++ b/src/test/run-pass/unboxed-closures-drop.rs @@ -11,7 +11,7 @@ // A battery of tests to ensure destructors of unboxed closure environments // run at the right times. -#![feature(overloaded_calls, unboxed_closures)] +#![feature(unboxed_closures)] static mut DROP_COUNT: uint = 0; diff --git a/src/test/run-pass/unboxed-closures-extern-fn.rs b/src/test/run-pass/unboxed-closures-extern-fn.rs index 516787ae570..2628bd90eef 100644 --- a/src/test/run-pass/unboxed-closures-extern-fn.rs +++ b/src/test/run-pass/unboxed-closures-extern-fn.rs @@ -11,7 +11,7 @@ // Checks that extern fn points implement the full range of Fn traits. #![feature(unboxed_closures)] -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::{Fn,FnMut,FnOnce}; diff --git a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs index a62712b3a4e..77d41ae1907 100644 --- a/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs +++ b/src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs @@ -12,7 +12,7 @@ // any Fn trait to be used where Fn is implemented. #![feature(unboxed_closures)] -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::{Fn,FnMut,FnOnce}; diff --git a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs index 8e639d23aeb..02395624cd1 100644 --- a/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs +++ b/src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs @@ -12,7 +12,7 @@ // FnMut or FnOnce to be used where FnMut is implemented. #![feature(unboxed_closures)] -#![feature(overloaded_calls)] +#![feature(unboxed_closures)] use std::ops::{FnMut,FnOnce}; diff --git a/src/test/run-pass/unboxed-closures-single-word-env.rs b/src/test/run-pass/unboxed-closures-single-word-env.rs index 4239cfdd8cf..61ceb5e140e 100644 --- a/src/test/run-pass/unboxed-closures-single-word-env.rs +++ b/src/test/run-pass/unboxed-closures-single-word-env.rs @@ -11,7 +11,7 @@ // Ensures that single-word environments work right in unboxed closures. // These take a different path in codegen. -#![feature(overloaded_calls, unboxed_closures)] +#![feature(unboxed_closures)] fn a int>(f: F) -> int { f(1, 2) diff --git a/src/test/run-pass/unboxed-closures-sugar-1.rs b/src/test/run-pass/unboxed-closures-sugar-1.rs deleted file mode 100644 index edcb85006ca..00000000000 --- a/src/test/run-pass/unboxed-closures-sugar-1.rs +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -// Test that the unboxed closure sugar can be used with an arbitrary -// struct type and that it is equivalent to the same syntax using -// angle brackets. This test covers only simple types and in -// particular doesn't test bound regions. - -#![allow(dead_code)] - -trait Foo { - fn dummy(&self) -> (T,U); -} - -trait Eq { } -impl Eq for X { } -fn eq>() { } - -fn test<'a,'b>() { - eq::< Foo<(),()>, Foo() >(); - eq::< Foo<(int,),()>, Foo(int) >(); - eq::< Foo<(int,uint),()>, Foo(int,uint) >(); - eq::< Foo<(int,uint),uint>, Foo(int,uint) -> uint >(); - eq::< Foo<(&'a int,&'b uint),uint>, Foo(&'a int,&'b uint) -> uint >(); -} - -fn main() { } diff --git a/src/test/run-pass/unboxed-closures-unique-type-id.rs b/src/test/run-pass/unboxed-closures-unique-type-id.rs index 43ab16c106f..4fdfb8cf02a 100644 --- a/src/test/run-pass/unboxed-closures-unique-type-id.rs +++ b/src/test/run-pass/unboxed-closures-unique-type-id.rs @@ -19,7 +19,7 @@ // // compile-flags: -g -#![feature(unboxed_closures, overloaded_calls)] +#![feature(unboxed_closures)] use std::ptr; -- cgit 1.4.1-3-g733a5