@@ -142,6 +142,52 @@ fn need_shared_lhs_rhs(tcx: ty::ctxt, a: @ast::expr, b: @ast::expr, op: str) {
142
142
need_expr_kind ( tcx, b, ast:: kind_shared, op + " rhs" ) ;
143
143
}
144
144
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
+
145
191
fn check_expr ( tcx : ty:: ctxt , e : @ast:: expr ) {
146
192
alt e. node {
147
193
@@ -189,6 +235,27 @@ fn check_expr(tcx: ty::ctxt, e: @ast::expr) {
189
235
}
190
236
}
191
237
}
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
+ }
192
259
_ { }
193
260
}
194
261
}
0 commit comments