diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 3af1d7ea35b..eee0a48ec67 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -76,7 +76,7 @@ fn kind_to_str(k: Kind) -> ~str { if ty::kind_can_be_sent(k) { kinds.push(~"owned"); } else if ty::kind_is_durable(k) { - kinds.push(~"durable"); + kinds.push(~"&static"); } str::connect(kinds, ~" ") @@ -571,7 +571,7 @@ fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool { match ty::get(ty).sty { ty::ty_param(*) => { tcx.sess.span_err(sp, ~"value may contain borrowed \ - pointers; use `durable` bound"); + pointers; use `&static` bound"); } _ => { tcx.sess.span_err(sp, ~"value may contain borrowed \ diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 3dce81df5f3..e2a5c7ca9f9 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -22,8 +22,8 @@ use middle::pat_util::{pat_bindings}; use core::cmp; use core::str; use core::vec; -use syntax::ast::{_mod, add, arm, binding_mode, bitand, bitor, bitxor, blk}; -use syntax::ast::{capture_clause}; +use syntax::ast::{RegionTyParamBound, TraitTyParamBound, _mod, add, arm}; +use syntax::ast::{binding_mode, bitand, bitor, bitxor, blk, capture_clause}; use syntax::ast::{crate, crate_num, decl_item, def, def_arg, def_binding}; use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label}; use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self}; @@ -4117,8 +4117,11 @@ impl Resolver { fn resolve_type_parameters(type_parameters: ~[ty_param], visitor: ResolveVisitor) { for type_parameters.each |type_parameter| { - for type_parameter.bounds.each |bound| { - self.resolve_type(**bound, visitor); + for type_parameter.bounds.each |&bound| { + match bound { + TraitTyParamBound(ty) => self.resolve_type(ty, visitor), + RegionTyParamBound => {} + } } } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index d29858e1fa4..b4cbc6c3f0e 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1591,7 +1591,7 @@ fn substs_to_str(cx: ctxt, substs: &substs) -> ~str { fn param_bound_to_str(cx: ctxt, pb: ¶m_bound) -> ~str { match *pb { bound_copy => ~"copy", - bound_durable => ~"durable", + bound_durable => ~"&static", bound_owned => ~"owned", bound_const => ~"const", bound_trait(t) => ::util::ppaux::ty_to_str(cx, t) diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index db99689f0ad..3743a5e0129 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -50,6 +50,7 @@ use util::ppaux::bound_to_str; use core::dvec; use core::option; use core::vec; +use syntax::ast::{RegionTyParamBound, TraitTyParamBound}; use syntax::ast; use syntax::ast_map; use syntax::ast_util::{local_def, split_trait_methods}; @@ -908,36 +909,42 @@ fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item) } } -// Translate the AST's notion of ty param bounds (which are just newtyped Tys) -// to ty's notion of ty param bounds, which can either be user-defined traits, -// or one of the four built-in traits (formerly known as kinds): Const, Copy, -// Durable, and Send. +// Translate the AST's notion of ty param bounds (which are an enum consisting +// of a newtyped Ty or a region) to ty's notion of ty param bounds, which can +// either be user-defined traits, or one of the four built-in traits (formerly +// known as kinds): Const, Copy, Durable, and Send. fn compute_bounds(ccx: @crate_ctxt, - ast_bounds: @~[ast::ty_param_bound]) -> ty::param_bounds { + ast_bounds: @~[ast::ty_param_bound]) + -> ty::param_bounds { @do vec::flat_map(*ast_bounds) |b| { - let li = &ccx.tcx.lang_items; - let ity = ast_ty_to_ty(ccx, empty_rscope, **b); - match ty::get(ity).sty { - ty::ty_trait(did, _, _) => { - if did == li.owned_trait() { - ~[ty::bound_owned] - } else if did == li.copy_trait() { - ~[ty::bound_copy] - } else if did == li.const_trait() { - ~[ty::bound_const] - } else if did == li.durable_trait() { - ~[ty::bound_durable] - } else { - // Must be a user-defined trait - ~[ty::bound_trait(ity)] + match b { + &TraitTyParamBound(b) => { + let li = &ccx.tcx.lang_items; + let ity = ast_ty_to_ty(ccx, empty_rscope, b); + match ty::get(ity).sty { + ty::ty_trait(did, _, _) => { + if did == li.owned_trait() { + ~[ty::bound_owned] + } else if did == li.copy_trait() { + ~[ty::bound_copy] + } else if did == li.const_trait() { + ~[ty::bound_const] + } else if did == li.durable_trait() { + ~[ty::bound_durable] + } else { + // Must be a user-defined trait + ~[ty::bound_trait(ity)] + } + } + _ => { + ccx.tcx.sess.span_err( + (*b).span, ~"type parameter bounds must be \ + trait types"); + ~[] + } } } - _ => { - ccx.tcx.sess.span_err( - (*b).span, ~"type parameter bounds must be \ - trait types"); - ~[] - } + &RegionTyParamBound => ~[ty::bound_durable] } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 072a7e94fe9..2cd873414c4 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -110,7 +110,10 @@ const crate_node_id: node_id = 0; // typeck::collect::compute_bounds matches these against // the "special" built-in traits (see middle::lang_items) and // detects Copy, Send, Owned, and Const. -enum ty_param_bound = @Ty; +enum ty_param_bound { + TraitTyParamBound(@Ty), + RegionTyParamBound +} #[auto_encode] #[auto_decode] diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 90df6fde8e3..2b3fefd6e51 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -245,7 +245,7 @@ priv impl ext_ctxt { path: @ast::path, bounds: @~[ast::ty_param_bound] ) -> ast::ty_param { - let bound = ast::ty_param_bound(@{ + let bound = ast::TraitTyParamBound(@{ id: self.next_id(), node: ast::ty_path(path, self.next_id()), span: span, @@ -397,7 +397,7 @@ fn mk_impl( let mut trait_tps = vec::append( ~[ty_param], do tps.map |tp| { - let t_bound = ast::ty_param_bound(@{ + let t_bound = ast::TraitTyParamBound(@{ id: cx.next_id(), node: ast::ty_path(path, cx.next_id()), span: span, diff --git a/src/libsyntax/ext/deriving.rs b/src/libsyntax/ext/deriving.rs index 8e36dc01e2a..afce1edf158 100644 --- a/src/libsyntax/ext/deriving.rs +++ b/src/libsyntax/ext/deriving.rs @@ -13,13 +13,13 @@ use core::prelude::*; -use ast::{Ty, and, bind_by_ref, binop, deref, enum_def, enum_variant_kind}; -use ast::{expr, expr_match, ident, item, item_, item_struct, item_enum}; -use ast::{item_impl, m_imm, meta_item, method, named_field, or, pat}; -use ast::{pat_ident, pat_wild, public, pure_fn, re_anon, spanned, stmt}; -use ast::{struct_def, struct_variant_kind, sty_by_ref, sty_region}; -use ast::{tuple_variant_kind, ty_nil, ty_param, ty_param_bound, ty_path}; -use ast::{ty_rptr, unnamed_field, variant}; +use ast::{TraitTyParamBound, Ty, and, bind_by_ref, binop, deref, enum_def}; +use ast::{enum_variant_kind, expr, expr_match, ident, item, item_}; +use ast::{item_enum, item_impl, item_struct, m_imm, meta_item, method}; +use ast::{named_field, or, pat, pat_ident, pat_wild, public, pure_fn}; +use ast::{re_anon, spanned, stmt, struct_def, struct_variant_kind}; +use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, ty_param}; +use ast::{ty_param_bound, ty_path, ty_rptr, unnamed_field, variant}; use ext::base::ext_ctxt; use ext::build; use codemap::span; @@ -211,7 +211,7 @@ fn create_derived_impl(cx: ext_ctxt, let bound = build::mk_ty_path_global(cx, span, trait_path.map(|x| *x)); - let bounds = @~[ ty_param_bound(bound) ]; + let bounds = @~[ TraitTyParamBound(bound) ]; let impl_ty_param = build::mk_ty_param(cx, ty_param.ident, bounds); impl_ty_params.push(move impl_ty_param); } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 272ad3456e5..bca2336bc8c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -141,7 +141,10 @@ fn fold_fn_decl(decl: ast::fn_decl, fld: ast_fold) -> ast::fn_decl { } fn fold_ty_param_bound(tpb: ty_param_bound, fld: ast_fold) -> ty_param_bound { - ty_param_bound(fld.fold_ty(*tpb)) + match tpb { + TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_ty(ty)), + RegionTyParamBound => RegionTyParamBound + } } fn fold_ty_param(tp: ty_param, fld: ast_fold) -> ty_param { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1a549fc93d5..6974ac508aa 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -10,7 +10,8 @@ use core::prelude::*; -use ast::{ProtoBox, ProtoUniq, provided, public, pure_fn, purity, re_static}; +use ast::{ProtoBox, ProtoUniq, RegionTyParamBound, TraitTyParamBound}; +use ast::{provided, public, pure_fn, purity, re_static}; use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer}; use ast::{bind_by_value, bind_by_move, bitand, bitor, bitxor, blk}; use ast::{blk_check_mode, box, by_copy, by_move, by_ref, by_val}; @@ -2401,8 +2402,16 @@ impl Parser { fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] { let mut bounds = ~[]; if self.eat(token::COLON) { - while is_ident(self.token) { - if is_ident(self.token) { + loop { + if self.eat(token::BINOP(token::AND)) { + if self.eat_keyword(~"static") { + bounds.push(RegionTyParamBound); + } else { + self.span_err(copy self.span, + ~"`&static` is the only permissible \ + region bound here"); + } + } else if is_ident(self.token) { let maybe_bound = match self.token { token::IDENT(copy sid, _) => { match *self.id_to_str(sid) { @@ -2415,7 +2424,7 @@ impl Parser { ObsoleteLowerCaseKindBounds); // Bogus value, but doesn't matter, since // is an error - Some(ty_param_bound(self.mk_ty_path(sid))) + Some(TraitTyParamBound(self.mk_ty_path(sid))) } _ => None @@ -2430,11 +2439,12 @@ impl Parser { bounds.push(bound); } None => { - bounds.push(ty_param_bound(self.parse_ty(false))); + let ty = self.parse_ty(false); + bounds.push(TraitTyParamBound(ty)); } } } else { - bounds.push(ty_param_bound(self.parse_ty(false))); + break; } } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 272c35152bb..f7117cc7043 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -10,7 +10,7 @@ use core::prelude::*; -use ast::{required, provided}; +use ast::{RegionTyParamBound, TraitTyParamBound, required, provided}; use ast; use ast_util; use ast_util::{operator_prec}; @@ -1791,9 +1791,12 @@ fn print_arg_mode(s: ps, m: ast::mode) { fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) { if bounds.is_not_empty() { word(s.s, ~":"); - for vec::each(*bounds) |bound| { + for vec::each(*bounds) |&bound| { nbsp(s); - print_type(s, **bound); + match bound { + TraitTyParamBound(ty) => print_type(s, ty), + RegionTyParamBound => word(s.s, ~"&static"), + } } } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 0da6396253e..25ea76d9b51 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -288,8 +288,11 @@ fn visit_foreign_item(ni: @foreign_item, e: E, v: vt) { } fn visit_ty_param_bounds(bounds: @~[ty_param_bound], e: E, v: vt) { - for vec::each(*bounds) |bound| { - (v.visit_ty)(**bound, e, v) + for bounds.each |&bound| { + match bound { + TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v), + RegionTyParamBound => () + } } } diff --git a/src/test/compile-fail/kindck-owned-trait-scoped.rs b/src/test/compile-fail/kindck-owned-trait-scoped.rs index d1eae60ac9d..b160ffe2ecd 100644 --- a/src/test/compile-fail/kindck-owned-trait-scoped.rs +++ b/src/test/compile-fail/kindck-owned-trait-scoped.rs @@ -35,7 +35,7 @@ fn to_foo_2(t: T) -> foo { {f:t} as foo //~ ERROR value may contain borrowed pointers; use `durable` bound } -fn to_foo_3(t: T) -> foo { +fn to_foo_3(t: T) -> foo { // OK---T may escape as part of the returned foo value, but it is // owned and hence does not contain borrowed ptrs {f:t} as foo diff --git a/src/test/compile-fail/kindck-owned-trait.rs b/src/test/compile-fail/kindck-owned-trait.rs index 35dc066e320..63d8212f41d 100644 --- a/src/test/compile-fail/kindck-owned-trait.rs +++ b/src/test/compile-fail/kindck-owned-trait.rs @@ -14,7 +14,7 @@ fn to_foo(t: T) -> foo { t as foo //~ ERROR value may contain borrowed pointers; use `durable` bound } -fn to_foo2(t: T) -> foo { +fn to_foo2(t: T) -> foo { t as foo } diff --git a/src/test/compile-fail/kindck-owned.rs b/src/test/compile-fail/kindck-owned.rs index 111b621c5a0..9cd7b36095f 100644 --- a/src/test/compile-fail/kindck-owned.rs +++ b/src/test/compile-fail/kindck-owned.rs @@ -12,7 +12,7 @@ fn copy1(t: T) -> fn@() -> T { fn@() -> T { t } //~ ERROR value may contain borrowed pointers } -fn copy2(t: T) -> fn@() -> T { +fn copy2(t: T) -> fn@() -> T { fn@() -> T { t } } diff --git a/src/test/compile-fail/static-region-bound.rs b/src/test/compile-fail/static-region-bound.rs new file mode 100644 index 00000000000..b70b0cdf881 --- /dev/null +++ b/src/test/compile-fail/static-region-bound.rs @@ -0,0 +1,9 @@ +fn f(_: T) {} + +fn main() { + let x = @3; + f(x); + let x = &3; + f(x); //~ ERROR instantiating a type parameter with an incompatible type +} + diff --git a/src/test/run-pass/alignment-gep-tup-like-1.rs b/src/test/run-pass/alignment-gep-tup-like-1.rs index 8acbee4400c..a880b50d628 100644 --- a/src/test/run-pass/alignment-gep-tup-like-1.rs +++ b/src/test/run-pass/alignment-gep-tup-like-1.rs @@ -12,7 +12,7 @@ type pair = { a: A, b: B }; -fn f(a: A, b: u16) -> fn@() -> (A, u16) { +fn f(a: A, b: u16) -> fn@() -> (A, u16) { fn@() -> (A, u16) { (a, b) } } diff --git a/src/test/run-pass/close-over-big-then-small-data.rs b/src/test/run-pass/close-over-big-then-small-data.rs index a0b55a1ea8d..a2a97f531de 100644 --- a/src/test/run-pass/close-over-big-then-small-data.rs +++ b/src/test/run-pass/close-over-big-then-small-data.rs @@ -16,7 +16,7 @@ type pair = { a: A, b: B }; -fn f(a: A, b: u16) -> fn@() -> (A, u16) { +fn f(a: A, b: u16) -> fn@() -> (A, u16) { fn@() -> (A, u16) { (a, b) } } diff --git a/src/test/run-pass/fixed-point-bind-unique.rs b/src/test/run-pass/fixed-point-bind-unique.rs index a00afd8c6d9..f01b2b082d0 100644 --- a/src/test/run-pass/fixed-point-bind-unique.rs +++ b/src/test/run-pass/fixed-point-bind-unique.rs @@ -11,11 +11,11 @@ // xfail-fast #[legacy_modes]; -fn fix_help(f: extern fn(fn@(A) -> B, A) -> B, x: A) -> B { +fn fix_help(f: extern fn(fn@(A) -> B, A) -> B, x: A) -> B { return f({|a|fix_help(f, a)}, x); } -fn fix(f: extern fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B { +fn fix(f: extern fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B { return {|a|fix_help(f, a)}; } diff --git a/src/test/run-pass/issue-2734.rs b/src/test/run-pass/issue-2734.rs index 7156e015473..0ab6c630ac8 100644 --- a/src/test/run-pass/issue-2734.rs +++ b/src/test/run-pass/issue-2734.rs @@ -11,7 +11,7 @@ trait hax { } impl A: hax { } -fn perform_hax(x: @T) -> hax { +fn perform_hax(x: @T) -> hax { x as hax } diff --git a/src/test/run-pass/issue-2735.rs b/src/test/run-pass/issue-2735.rs index 360e7b3c241..675397a0881 100644 --- a/src/test/run-pass/issue-2735.rs +++ b/src/test/run-pass/issue-2735.rs @@ -11,7 +11,7 @@ trait hax { } impl A: hax { } -fn perform_hax(x: @T) -> hax { +fn perform_hax(x: @T) -> hax { x as hax } diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index 33e5e386e39..5e66d2c7c19 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -59,7 +59,7 @@ fn square_from_char(c: char) -> square { } } -fn read_board_grid(+in: rdr) -> ~[~[square]] { +fn read_board_grid(+in: rdr) -> ~[~[square]] { let in = (move in) as io::Reader; let mut grid = ~[]; for in.each_line |line| {