librustc: Implement &static as the replacement for Durable. r=nmatsakis

This commit is contained in:
Patrick Walton 2013-01-10 11:16:54 -08:00
parent 982830c836
commit 2a1b6c4de9
21 changed files with 107 additions and 66 deletions

View File

@ -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 \

View File

@ -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 => {}
}
}
}
}

View File

@ -1591,7 +1591,7 @@ fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
fn param_bound_to_str(cx: ctxt, pb: &param_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)

View File

@ -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]
}
}
}

View File

@ -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]

View File

@ -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,

View File

@ -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);
}

View File

@ -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 {

View File

@ -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;
}
}
}

View File

@ -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"),
}
}
}
}

View File

@ -288,8 +288,11 @@ fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) {
}
fn visit_ty_param_bounds<E>(bounds: @~[ty_param_bound], e: E, v: vt<E>) {
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 => ()
}
}
}

View File

@ -35,7 +35,7 @@ fn to_foo_2<T:Copy>(t: T) -> foo {
{f:t} as foo //~ ERROR value may contain borrowed pointers; use `durable` bound
}
fn to_foo_3<T:Copy Durable>(t: T) -> foo {
fn to_foo_3<T:Copy &static>(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

View File

@ -14,7 +14,7 @@ fn to_foo<T: Copy foo>(t: T) -> foo {
t as foo //~ ERROR value may contain borrowed pointers; use `durable` bound
}
fn to_foo2<T: Copy foo Durable>(t: T) -> foo {
fn to_foo2<T: Copy foo &static>(t: T) -> foo {
t as foo
}

View File

@ -12,7 +12,7 @@ fn copy1<T: Copy>(t: T) -> fn@() -> T {
fn@() -> T { t } //~ ERROR value may contain borrowed pointers
}
fn copy2<T: Copy Durable>(t: T) -> fn@() -> T {
fn copy2<T: Copy &static>(t: T) -> fn@() -> T {
fn@() -> T { t }
}

View File

@ -0,0 +1,9 @@
fn f<T:&static>(_: T) {}
fn main() {
let x = @3;
f(x);
let x = &3;
f(x); //~ ERROR instantiating a type parameter with an incompatible type
}

View File

@ -12,7 +12,7 @@ type pair<A,B> = {
a: A, b: B
};
fn f<A:Copy Durable>(a: A, b: u16) -> fn@() -> (A, u16) {
fn f<A:Copy &static>(a: A, b: u16) -> fn@() -> (A, u16) {
fn@() -> (A, u16) { (a, b) }
}

View File

@ -16,7 +16,7 @@ type pair<A,B> = {
a: A, b: B
};
fn f<A:Copy Durable>(a: A, b: u16) -> fn@() -> (A, u16) {
fn f<A:Copy &static>(a: A, b: u16) -> fn@() -> (A, u16) {
fn@() -> (A, u16) { (a, b) }
}

View File

@ -11,11 +11,11 @@
// xfail-fast
#[legacy_modes];
fn fix_help<A: Durable, B: Owned>(f: extern fn(fn@(A) -> B, A) -> B, x: A) -> B {
fn fix_help<A: &static, B: Owned>(f: extern fn(fn@(A) -> B, A) -> B, x: A) -> B {
return f({|a|fix_help(f, a)}, x);
}
fn fix<A: Durable, B: Owned>(f: extern fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B {
fn fix<A: &static, B: Owned>(f: extern fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B {
return {|a|fix_help(f, a)};
}

View File

@ -11,7 +11,7 @@
trait hax { }
impl <A> A: hax { }
fn perform_hax<T: Durable>(x: @T) -> hax {
fn perform_hax<T: &static>(x: @T) -> hax {
x as hax
}

View File

@ -11,7 +11,7 @@
trait hax { }
impl <A> A: hax { }
fn perform_hax<T: Durable>(x: @T) -> hax {
fn perform_hax<T: &static>(x: @T) -> hax {
x as hax
}

View File

@ -59,7 +59,7 @@ fn square_from_char(c: char) -> square {
}
}
fn read_board_grid<rdr: Durable io::Reader>(+in: rdr) -> ~[~[square]] {
fn read_board_grid<rdr: &static io::Reader>(+in: rdr) -> ~[~[square]] {
let in = (move in) as io::Reader;
let mut grid = ~[];
for in.each_line |line| {