Skip to content

Commit 9909ce7

Browse files
committed
---
yaml --- r: 20494 b: refs/heads/snap-stage3 c: e0ea67a h: refs/heads/master v: v3
1 parent f08907d commit 9909ce7

37 files changed

+412
-131
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: e430a699f2c60890d9b86069fd0c68a70ece7120
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: eb0a34c39865d456a776fc8e81ba780dd383f315
4+
refs/heads/snap-stage3: e0ea67a2a60c694a6c3424d99e4692c2725b8506
55
refs/heads/try: ffbe0e0e00374358b789b0037bcb3a577cd218be
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/libcore/task.rs

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -832,10 +832,10 @@ fn spawn_raw(opts: task_opts, +f: fn~()) {
832832
* types; arbitrary type coercion is possible this way. The interface is safe
833833
* as long as all key functions are monomorphic.
834834
*/
835-
type local_data_key<T> = fn@(+@T);
835+
type local_data_key<T: owned> = fn@(+@T);
836836

837837
iface local_data { }
838-
impl<T> of local_data for @T { }
838+
impl<T: owned> of local_data for @T { }
839839

840840
// We use dvec because it's the best data structure in core. If TLS is used
841841
// heavily in future, this could be made more efficient with a proper map.
@@ -852,6 +852,7 @@ extern fn cleanup_task_local_map(map_ptr: *libc::c_void) unsafe {
852852

853853
// Gets the map from the runtime. Lazily initialises if not done so already.
854854
unsafe fn get_task_local_map(task: *rust_task) -> task_local_map {
855+
855856
// Relies on the runtime initialising the pointer to null.
856857
// NOTE: The map's box lives in TLS invisibly referenced once. Each time
857858
// we retrieve it for get/set, we make another reference, which get/set
@@ -872,16 +873,20 @@ unsafe fn get_task_local_map(task: *rust_task) -> task_local_map {
872873
}
873874
}
874875

875-
unsafe fn key_to_key_value<T>(key: local_data_key<T>) -> *libc::c_void {
876+
unsafe fn key_to_key_value<T: owned>(
877+
key: local_data_key<T>) -> *libc::c_void {
878+
876879
// Keys are closures, which are (fnptr,envptr) pairs. Use fnptr.
877880
// Use reintepret_cast -- transmute would leak (forget) the closure.
878881
let pair: (*libc::c_void, *libc::c_void) = unsafe::reinterpret_cast(key);
879882
pair.first()
880883
}
881884

882885
// If returning some(..), returns with @T with the map's reference. Careful!
883-
unsafe fn local_data_lookup<T>(map: task_local_map, key: local_data_key<T>)
884-
-> option<(uint, *libc::c_void)> {
886+
unsafe fn local_data_lookup<T: owned>(
887+
map: task_local_map, key: local_data_key<T>)
888+
-> option<(uint, *libc::c_void)> {
889+
885890
let key_value = key_to_key_value(key);
886891
let map_pos = (*map).position(|entry|
887892
alt entry { some((k,_,_)) { k == key_value } none { false } }
@@ -893,8 +898,10 @@ unsafe fn local_data_lookup<T>(map: task_local_map, key: local_data_key<T>)
893898
}
894899
}
895900

896-
unsafe fn local_get_helper<T>(task: *rust_task, key: local_data_key<T>,
897-
do_pop: bool) -> option<@T> {
901+
unsafe fn local_get_helper<T: owned>(
902+
task: *rust_task, key: local_data_key<T>,
903+
do_pop: bool) -> option<@T> {
904+
898905
let map = get_task_local_map(task);
899906
// Interpret our findings from the map
900907
do local_data_lookup(map, key).map |result| {
@@ -912,17 +919,23 @@ unsafe fn local_get_helper<T>(task: *rust_task, key: local_data_key<T>,
912919
}
913920
}
914921

915-
unsafe fn local_pop<T>(task: *rust_task,
916-
key: local_data_key<T>) -> option<@T> {
922+
unsafe fn local_pop<T: owned>(
923+
task: *rust_task,
924+
key: local_data_key<T>) -> option<@T> {
925+
917926
local_get_helper(task, key, true)
918927
}
919928

920-
unsafe fn local_get<T>(task: *rust_task,
921-
key: local_data_key<T>) -> option<@T> {
929+
unsafe fn local_get<T: owned>(
930+
task: *rust_task,
931+
key: local_data_key<T>) -> option<@T> {
932+
922933
local_get_helper(task, key, false)
923934
}
924935

925-
unsafe fn local_set<T>(task: *rust_task, key: local_data_key<T>, +data: @T) {
936+
unsafe fn local_set<T: owned>(
937+
task: *rust_task, key: local_data_key<T>, +data: @T) {
938+
926939
let map = get_task_local_map(task);
927940
// Store key+data as *voids. Data is invisibly referenced once; key isn't.
928941
let keyval = key_to_key_value(key);
@@ -956,8 +969,10 @@ unsafe fn local_set<T>(task: *rust_task, key: local_data_key<T>, +data: @T) {
956969
}
957970
}
958971

959-
unsafe fn local_modify<T>(task: *rust_task, key: local_data_key<T>,
960-
modify_fn: fn(option<@T>) -> option<@T>) {
972+
unsafe fn local_modify<T: owned>(
973+
task: *rust_task, key: local_data_key<T>,
974+
modify_fn: fn(option<@T>) -> option<@T>) {
975+
961976
// Could be more efficient by doing the lookup work, but this is easy.
962977
let newdata = modify_fn(local_pop(task, key));
963978
if newdata.is_some() {
@@ -970,29 +985,37 @@ unsafe fn local_modify<T>(task: *rust_task, key: local_data_key<T>,
970985
* Remove a task-local data value from the table, returning the
971986
* reference that was originally created to insert it.
972987
*/
973-
unsafe fn local_data_pop<T>(key: local_data_key<T>) -> option<@T> {
988+
unsafe fn local_data_pop<T: owned>(
989+
key: local_data_key<T>) -> option<@T> {
990+
974991
local_pop(rustrt::rust_get_task(), key)
975992
}
976993
/**
977994
* Retrieve a task-local data value. It will also be kept alive in the
978995
* table until explicitly removed.
979996
*/
980-
unsafe fn local_data_get<T>(key: local_data_key<T>) -> option<@T> {
997+
unsafe fn local_data_get<T: owned>(
998+
key: local_data_key<T>) -> option<@T> {
999+
9811000
local_get(rustrt::rust_get_task(), key)
9821001
}
9831002
/**
9841003
* Store a value in task-local data. If this key already has a value,
9851004
* that value is overwritten (and its destructor is run).
9861005
*/
987-
unsafe fn local_data_set<T>(key: local_data_key<T>, +data: @T) {
1006+
unsafe fn local_data_set<T: owned>(
1007+
key: local_data_key<T>, +data: @T) {
1008+
9881009
local_set(rustrt::rust_get_task(), key, data)
9891010
}
9901011
/**
9911012
* Modify a task-local data value. If the function returns 'none', the
9921013
* data is removed (and its reference dropped).
9931014
*/
994-
unsafe fn local_data_modify<T>(key: local_data_key<T>,
995-
modify_fn: fn(option<@T>) -> option<@T>) {
1015+
unsafe fn local_data_modify<T: owned>(
1016+
key: local_data_key<T>,
1017+
modify_fn: fn(option<@T>) -> option<@T>) {
1018+
9961019
local_modify(rustrt::rust_get_task(), key, modify_fn)
9971020
}
9981021

branches/snap-stage3/src/libstd/deque.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,9 @@ mod tests {
193193

194194
type eqfn<T> = fn@(T, T) -> bool;
195195

196-
fn test_parameterized<T: copy>(e: eqfn<T>, a: T, b: T, c: T, d: T) {
196+
fn test_parameterized<T: copy owned>(
197+
e: eqfn<T>, a: T, b: T, c: T, d: T) {
198+
197199
let deq: deque::t<T> = deque::create::<T>();
198200
assert (deq.size() == 0u);
199201
deq.add_front(a);

branches/snap-stage3/src/libsyntax/parse/parser.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,7 @@ class parser {
383383
let name =
384384
alt copy self.token {
385385
token::IDENT(sid, _) => {
386-
if self.look_ahead(1u) == token::DOT || // backwards compat
387-
self.look_ahead(1u) == token::BINOP(token::SLASH) {
386+
if self.look_ahead(1u) == token::BINOP(token::SLASH) {
388387
self.bump(); self.bump();
389388
some(self.get_str(sid))
390389
} else {

branches/snap-stage3/src/libsyntax/print/pprust.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ fn print_type_ex(s: ps, &&ty: @ast::ty, print_colons: bool) {
345345
ast::ty_rptr(region, mt) {
346346
alt region.node {
347347
ast::re_anon { word(s.s, ~"&"); }
348-
_ { print_region(s, region); word(s.s, ~"."); }
348+
_ { print_region(s, region); word(s.s, ~"/"); }
349349
}
350350
print_mt(s, mt);
351351
}

branches/snap-stage3/src/rustc/metadata/tyencode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
272272
w.write_char('I');
273273
w.write_uint(id.to_uint());
274274
}
275-
ty::ty_param(id, did) {
275+
ty::ty_param({idx: id, def_id: did}) {
276276
w.write_char('p');
277277
w.write_str(cx.ds(did));
278278
w.write_char('|');

branches/snap-stage3/src/rustc/middle/kind.rs

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
115115
fn check_for_box(cx: ctx, id: node_id, fv: option<@freevar_entry>,
116116
is_move: bool, var_t: ty::t, sp: span) {
117117
// all captured data must be owned
118-
if !check_owned(cx, var_t, sp) { ret; }
118+
if !check_owned(cx.tcx, var_t, sp) { ret; }
119119
120120
// copied in data must be copyable, but moved in data can be anything
121121
let is_implicit = fv.is_some();
@@ -217,7 +217,13 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
217217
alt e.node {
218218
expr_assign(_, ex) |
219219
expr_unary(box(_), ex) | expr_unary(uniq(_), ex) |
220-
expr_ret(some(ex)) | expr_cast(ex, _) { maybe_copy(cx, ex); }
220+
expr_ret(some(ex)) {
221+
maybe_copy(cx, ex);
222+
}
223+
expr_cast(source, _) {
224+
maybe_copy(cx, source);
225+
check_cast_for_escaping_regions(cx, source, e);
226+
}
221227
expr_copy(expr) { check_copy_ex(cx, expr, false); }
222228
// Vector add copies, but not "implicitly"
223229
expr_assign_op(_, _, ex) { check_copy_ex(cx, ex, false) }
@@ -440,15 +446,92 @@ fn check_send(cx: ctx, ty: ty::t, sp: span) -> bool {
440446
}
441447
}
442448

443-
fn check_owned(cx: ctx, ty: ty::t, sp: span) -> bool {
444-
if !ty::kind_is_owned(ty::type_kind(cx.tcx, ty)) {
445-
cx.tcx.sess.span_err(sp, ~"not an owned value");
449+
// note: also used from middle::typeck::regionck!
450+
fn check_owned(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool {
451+
if !ty::kind_is_owned(ty::type_kind(tcx, ty)) {
452+
alt ty::get(ty).struct {
453+
ty::ty_param(*) {
454+
tcx.sess.span_err(sp, ~"value may contain borrowed \
455+
pointers; use `owned` bound");
456+
}
457+
_ {
458+
tcx.sess.span_err(sp, ~"value may contain borrowed \
459+
pointers");
460+
}
461+
}
446462
false
447463
} else {
448464
true
449465
}
450466
}
451467

468+
/// This is rather subtle. When we are casting a value to a
469+
/// instantiated iface like `a as iface/&r`, regionck already ensures
470+
/// that any borrowed pointers that appear in the type of `a` are
471+
/// bounded by `&r`. However, it is possible that there are *type
472+
/// parameters* in the type of `a`, and those *type parameters* may
473+
/// have borrowed pointers within them. We have to guarantee that the
474+
/// regions which appear in those type parameters are not obscured.
475+
///
476+
/// Therefore, we ensure that one of three conditions holds:
477+
///
478+
/// (1) The iface instance cannot escape the current fn. This is
479+
/// guaranteed if the region bound `&r` is some scope within the fn
480+
/// itself. This case is safe because whatever borrowed pointers are
481+
/// found within the type parameter, they must enclose the fn body
482+
/// itself.
483+
///
484+
/// (2) The type parameter appears in the type of the iface. For
485+
/// example, if the type parameter is `T` and the iface type is
486+
/// `deque<T>`, then whatever borrowed ptrs may appear in `T` also
487+
/// appear in `deque<T>`.
488+
///
489+
/// (3) The type parameter is owned (and therefore does not contain
490+
/// borrowed ptrs).
491+
fn check_cast_for_escaping_regions(
492+
cx: ctx,
493+
source: @expr,
494+
target: @expr) {
495+
496+
// Determine what type we are casting to; if it is not an iface, then no
497+
// worries.
498+
let target_ty = ty::expr_ty(cx.tcx, target);
499+
let target_substs = alt ty::get(target_ty).struct {
500+
ty::ty_trait(_, substs) => {substs}
501+
_ => { ret; /* not a cast to a trait */ }
502+
};
503+
504+
// Check, based on the region associated with the iface, whether it can
505+
// possibly escape the enclosing fn item (note that all type parameters
506+
// must have been declared on the enclosing fn item):
507+
alt target_substs.self_r {
508+
some(ty::re_scope(*)) => { ret; /* case (1) */ }
509+
none | some(ty::re_static) | some(ty::re_free(*)) => {}
510+
some(ty::re_bound(*)) | some(ty::re_var(*)) => {
511+
cx.tcx.sess.span_bug(
512+
source.span,
513+
#fmt["bad region found in kind: %?", target_substs.self_r]);
514+
}
515+
}
516+
517+
// Assuming the iface instance can escape, then ensure that each parameter
518+
// either appears in the iface type or is owned:
519+
let target_params = ty::param_tys_in_type(target_ty);
520+
let source_ty = ty::expr_ty(cx.tcx, source);
521+
do ty::walk_ty(source_ty) |ty| {
522+
alt ty::get(ty).struct {
523+
ty::ty_param(source_param) => {
524+
if target_params.contains(source_param) {
525+
/* case (2) */
526+
} else {
527+
check_owned(cx.tcx, ty, source.span); /* case (3) */
528+
}
529+
}
530+
_ => {}
531+
}
532+
}
533+
}
534+
452535
//
453536
// Local Variables:
454537
// mode: rust

branches/snap-stage3/src/rustc/middle/trans/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,7 @@ enum copy_action { INIT, DROP_EXISTING, }
13171317
fn type_is_structural_or_param(t: ty::t) -> bool {
13181318
if ty::type_is_structural(t) { ret true; }
13191319
alt ty::get(t).struct {
1320-
ty::ty_param(_, _) { ret true; }
1320+
ty::ty_param(*) { ret true; }
13211321
_ { ret false; }
13221322
}
13231323
}

branches/snap-stage3/src/rustc/middle/trans/reflect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ impl methods for reflector {
272272
ty::ty_trait(_, _) { self.leaf(~"trait") }
273273
ty::ty_var(_) { self.leaf(~"var") }
274274
ty::ty_var_integral(_) { self.leaf(~"var_integral") }
275-
ty::ty_param(n, _) { self.visit(~"param", ~[self.c_uint(n)]) }
275+
ty::ty_param(p) { self.visit(~"param", ~[self.c_uint(p.idx)]) }
276276
ty::ty_self { self.leaf(~"self") }
277277
ty::ty_type { self.leaf(~"type") }
278278
ty::ty_opaque_box { self.leaf(~"opaque_box") }

branches/snap-stage3/src/rustc/middle/trans/type_use.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
137137
}
138138
false
139139
}
140-
ty::ty_param(n, _) {
141-
cx.uses[n] |= use;
140+
ty::ty_param(p) {
141+
cx.uses[p.idx] |= use;
142142
false
143143
}
144144
_ { true }

0 commit comments

Comments
 (0)