Skip to content

Commit cde86fa

Browse files
committed
---
yaml --- r: 5583 b: refs/heads/master c: 459353e h: refs/heads/master i: 5581: 83cf2be 5579: bcec70b 5575: 42b7ac6 5567: 5030aad v: v3
1 parent 5f522d1 commit cde86fa

13 files changed

+163
-14
lines changed

[refs]

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 9ba86178efc8c5b733202995427c6345ee80ba1c
2+
refs/heads/master: 459353e1078ad50c9088980104b4e940840a26ae

trunk/src/comp/middle/kind.rs

+67
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,52 @@ fn need_shared_lhs_rhs(tcx: ty::ctxt, a: @ast::expr, b: @ast::expr, op: str) {
142142
need_expr_kind(tcx, b, ast::kind_shared, op + " rhs");
143143
}
144144

145+
/*
146+
This ... is a hack (I find myself writing that too often *sadface*).
147+
148+
We need to be able to put pinned kinds into other types but such operations
149+
are conceptually copies, and pinned kinds can't do that, e.g.
150+
151+
let a = my_resource(x);
152+
let b = @a; // no-go
153+
154+
So this function attempts to make a loophole where resources can be put into
155+
other types as long as it's done in a safe way, specifically like
156+
157+
let b = @my_resource(x);
158+
*/
159+
fn need_shared_or_pinned_ctor(tcx: ty::ctxt, a: @ast::expr, descr: str) {
160+
let tk = type_and_kind(tcx, a);
161+
if tk.kind == ast::kind_pinned && !pinned_ctor(a) {
162+
let err =
163+
#fmt["mismatched kinds for %s: cannot copy pinned type %s",
164+
descr, util::ppaux::ty_to_str(tcx, tk.ty)];
165+
tcx.sess.span_err(a.span, err);
166+
let note =
167+
#fmt["try constructing %s directly into %s",
168+
util::ppaux::ty_to_str(tcx, tk.ty), descr];
169+
tcx.sess.span_note(a.span, note);
170+
} else if tk.kind != ast::kind_pinned {
171+
need_expr_kind(tcx, a, ast::kind_shared, descr);
172+
}
173+
174+
fn pinned_ctor(a: @ast::expr) -> bool {
175+
// FIXME: Technically a lambda block is also a pinned ctor
176+
alt a.node {
177+
ast::expr_call(cexpr, _) {
178+
// Assuming that if it's a call that it's safe to move in, mostly
179+
// because I don't know offhand how to ensure that it's a call
180+
// specifically to a resource constructor
181+
true
182+
}
183+
ast::expr_rec(_, _) {
184+
true
185+
}
186+
_ { false }
187+
}
188+
}
189+
}
190+
145191
fn check_expr(tcx: ty::ctxt, e: @ast::expr) {
146192
alt e.node {
147193

@@ -189,6 +235,27 @@ fn check_expr(tcx: ty::ctxt, e: @ast::expr) {
189235
}
190236
}
191237
}
238+
ast::expr_unary(op, a) {
239+
alt op {
240+
ast::box(_) {
241+
need_shared_or_pinned_ctor(tcx, a, "'@' operand");
242+
}
243+
ast::uniq(_) {
244+
need_shared_or_pinned_ctor(tcx, a, "'~' operand");
245+
}
246+
_ { /* fall through */ }
247+
}
248+
}
249+
ast::expr_rec(fields, _) {
250+
for field in fields {
251+
need_shared_or_pinned_ctor(tcx, field.node.expr, "record field");
252+
}
253+
}
254+
ast::expr_tup(exprs) {
255+
for expr in exprs {
256+
need_shared_or_pinned_ctor(tcx, expr, "tuple parameter");
257+
}
258+
}
192259
_ { }
193260
}
194261
}

trunk/src/fuzzer/fuzzer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap,
230230
check_variants_T(crate, codemap, filename, "ty", stolen.tys, pprust::ty_to_str, replace_ty_in_crate, cx);
231231
}
232232

233-
fn check_variants_T<T>(
233+
fn check_variants_T<@T>(
234234
crate: ast::crate,
235235
codemap: codemap::codemap,
236236
filename: str,

trunk/src/test/compile-fail/copy-res-into-box.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// xfail-test
2-
// error-pattern:mismatched kinds
1+
// error-pattern:mismatched kinds for '@' operand
32
resource r(i: @mutable int) {
43
*i = *i + 1;
54
}
@@ -9,7 +8,7 @@ fn main() {
98
{
109
let j <- r(i);
1110
// No no no no no
12-
let k = @j;
11+
let k <- @j;
1312
}
1413
log_err *i;
1514
assert *i == 2;

trunk/src/test/compile-fail/copy-res-into-rec.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// xfail-test
2-
// error-pattern:mismatched kinds
1+
// error-pattern:mismatched kinds for record field
32
resource r(i: @mutable int) {
43
*i = *i + 1;
54
}

trunk/src/test/compile-fail/copy-res-into-tag.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// xfail-test
2-
// error-pattern:mismatched kinds
2+
// error-pattern:mismatched kinds for tag parameter
33
resource r(i: @mutable int) {
44
*i = *i + 1;
55
}

trunk/src/test/compile-fail/copy-res-into-tup.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// xfail-test
2-
// error-pattern:mismatched kinds
1+
// error-pattern:mismatched kinds for tuple parameter
32
resource r(i: @mutable int) {
43
*i = *i + 1;
54
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// error-pattern:mismatched kinds for '~' operand
2+
resource r(i: @mutable int) {
3+
*i = *i + 1;
4+
}
5+
6+
fn main() {
7+
let i = @mutable 0;
8+
{
9+
let j <- r(i);
10+
// No no no no no
11+
let k <- ~j;
12+
}
13+
log_err *i;
14+
assert *i == 2;
15+
}

trunk/src/test/run-pass/foreach-box-drop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22

3-
obj ob<K>(k: K) {
3+
obj ob<@K>(k: K) {
44
iter foo() -> @{a: K} { put @{a: k}; }
55
}
66

trunk/src/test/run-pass/foreach-unique-drop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
obj ob<K>(k: K) {
2+
obj ob<@K>(k: K) {
33
iter foo() -> ~{a: K} { put ~{a: k}; }
44
}
55

trunk/src/test/run-pass/generic-box.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22

3-
fn box<T>(x: {x: T, y: T, z: T}) -> @{x: T, y: T, z: T} { ret @x; }
3+
fn box<@T>(x: {x: T, y: T, z: T}) -> @{x: T, y: T, z: T} { ret @x; }
44

55
fn main() {
66
let x: @{x: int, y: int, z: int} = box::<int>({x: 1, y: 2, z: 3});

trunk/src/test/run-pass/generic-exterior-box.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
type recbox<T> = {x: @T};
44

5-
fn reclift<T>(t: T) -> recbox<T> { ret {x: @t}; }
5+
fn reclift<@T>(t: T) -> recbox<T> { ret {x: @t}; }
66

77
fn main() {
88
let foo: int = 17;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Resources can't be copied into other types but still need to be able
2+
// to find their way into things.
3+
4+
resource r(i: @mutable int) {
5+
*i = *i + 1;
6+
}
7+
8+
fn test_box() {
9+
let i = @mutable 0;
10+
{
11+
let a <- @r(i);
12+
}
13+
assert *i == 1;
14+
}
15+
16+
fn test_rec() {
17+
let i = @mutable 0;
18+
{
19+
let a <- {x: r(i)};
20+
}
21+
assert *i == 1;
22+
}
23+
24+
fn test_tag() {
25+
tag t {
26+
t0(r);
27+
}
28+
29+
let i = @mutable 0;
30+
{
31+
let a <- t0(r(i));
32+
}
33+
assert *i == 1;
34+
}
35+
36+
fn test_tup() {
37+
let i = @mutable 0;
38+
{
39+
let a <- (r(i), 0);
40+
}
41+
assert *i == 1;
42+
}
43+
44+
fn test_unique() {
45+
let i = @mutable 0;
46+
{
47+
let a <- ~r(i);
48+
}
49+
assert *i == 1;
50+
}
51+
52+
fn test_box_rec() {
53+
let i = @mutable 0;
54+
{
55+
let a <- @{
56+
x: r(i)
57+
};
58+
}
59+
assert *i == 1;
60+
}
61+
62+
fn main() {
63+
test_box();
64+
test_rec();
65+
// FIXME: tag constructors don't optimize their arguments into moves
66+
// test_tag();
67+
test_tup();
68+
test_unique();
69+
test_box_rec();
70+
}

0 commit comments

Comments
 (0)