@@ -22,7 +22,7 @@ use trans::adt;
22
22
use trans:: attributes;
23
23
use trans:: base:: * ;
24
24
use trans:: build:: * ;
25
- use trans:: callee;
25
+ use trans:: callee:: { self , Callee } ;
26
26
use trans:: cleanup;
27
27
use trans:: cleanup:: CleanupMethods ;
28
28
use trans:: common:: * ;
@@ -45,6 +45,7 @@ use syntax::ast;
45
45
use syntax:: ptr:: P ;
46
46
use syntax:: parse:: token;
47
47
48
+ use rustc:: lint;
48
49
use rustc:: session:: Session ;
49
50
use syntax:: codemap:: Span ;
50
51
@@ -125,29 +126,41 @@ pub fn check_intrinsics(ccx: &CrateContext) {
125
126
transmute_restriction. substituted_to ) ;
126
127
let from_type_size = machine:: llbitsize_of_real ( ccx, llfromtype) ;
127
128
let to_type_size = machine:: llbitsize_of_real ( ccx, lltotype) ;
129
+
130
+ if let ty:: TyFnDef ( ..) = transmute_restriction. substituted_from . sty {
131
+ if to_type_size == machine:: llbitsize_of_real ( ccx, ccx. int_type ( ) ) {
132
+ // FIXME #19925 Remove this warning after a release cycle.
133
+ lint:: raw_emit_lint ( & ccx. tcx ( ) . sess ,
134
+ & ccx. tcx ( ) . sess . lint_store . borrow ( ) ,
135
+ lint:: builtin:: TRANSMUTE_FROM_FN_ITEM_TYPES ,
136
+ ( lint:: Warn , lint:: LintSource :: Default ) ,
137
+ Some ( transmute_restriction. span ) ,
138
+ & format ! ( "`{}` is now zero-sized and has to be cast \
139
+ to a pointer before transmuting to `{}`",
140
+ transmute_restriction. substituted_from,
141
+ transmute_restriction. substituted_to) ) ;
142
+ continue ;
143
+ }
144
+ }
128
145
if from_type_size != to_type_size {
129
146
last_failing_id = Some ( transmute_restriction. id ) ;
130
147
131
148
if transmute_restriction. original_from != transmute_restriction. substituted_from {
132
149
span_transmute_size_error ( ccx. sess ( ) , transmute_restriction. span ,
133
150
& format ! ( "transmute called with differently sized types: \
134
- {} (could be {} bit{} ) to {} (could be {} bit{} )",
151
+ {} (could be {} bits ) to {} (could be {} bits )",
135
152
transmute_restriction. original_from,
136
- from_type_size as usize ,
137
- if from_type_size == 1 { "" } else { "s" } ,
153
+ from_type_size,
138
154
transmute_restriction. original_to,
139
- to_type_size as usize ,
140
- if to_type_size == 1 { "" } else { "s" } ) ) ;
155
+ to_type_size) ) ;
141
156
} else {
142
157
span_transmute_size_error ( ccx. sess ( ) , transmute_restriction. span ,
143
158
& format ! ( "transmute called with differently sized types: \
144
- {} ({} bit{} ) to {} ({} bit{} )",
159
+ {} ({} bits ) to {} ({} bits )",
145
160
transmute_restriction. original_from,
146
- from_type_size as usize ,
147
- if from_type_size == 1 { "" } else { "s" } ,
161
+ from_type_size,
148
162
transmute_restriction. original_to,
149
- to_type_size as usize ,
150
- if to_type_size == 1 { "" } else { "s" } ) ) ;
163
+ to_type_size) ) ;
151
164
}
152
165
}
153
166
}
@@ -179,6 +192,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
179
192
let foreign_item = tcx. map . expect_foreign_item ( node) ;
180
193
let name = foreign_item. name . as_str ( ) ;
181
194
195
+ let call_debug_location = DebugLoc :: At ( call_info. id , call_info. span ) ;
196
+
182
197
// For `transmute` we can just trans the input expr directly into dest
183
198
if name == "transmute" {
184
199
let llret_ty = type_of:: type_of ( ccx, ret_ty. unwrap ( ) ) ;
@@ -194,6 +209,27 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
194
209
let in_type_size = machine:: llbitsize_of_real ( ccx, llintype) ;
195
210
let out_type_size = machine:: llbitsize_of_real ( ccx, llouttype) ;
196
211
212
+ if let ty:: TyFnDef ( def_id, substs, _) = in_type. sty {
213
+ if out_type_size != 0 {
214
+ // FIXME #19925 Remove this hack after a release cycle.
215
+ let _ = unpack_datum ! ( bcx, expr:: trans( bcx, & arg_exprs[ 0 ] ) ) ;
216
+ let llfn = Callee :: def ( ccx, def_id, substs, in_type) . reify ( ccx) . val ;
217
+ let llfnty = val_ty ( llfn) ;
218
+ let llresult = match dest {
219
+ expr:: SaveIn ( d) => d,
220
+ expr:: Ignore => alloc_ty ( bcx, out_type, "ret" )
221
+ } ;
222
+ Store ( bcx, llfn, PointerCast ( bcx, llresult, llfnty. ptr_to ( ) ) ) ;
223
+ if dest == expr:: Ignore {
224
+ bcx = glue:: drop_ty ( bcx, llresult, out_type,
225
+ call_debug_location) ;
226
+ }
227
+ fcx. scopes . borrow_mut ( ) . last_mut ( ) . unwrap ( ) . drop_non_lifetime_clean ( ) ;
228
+ fcx. pop_and_trans_custom_cleanup_scope ( bcx, cleanup_scope) ;
229
+ return Result :: new ( bcx, llresult) ;
230
+ }
231
+ }
232
+
197
233
// This should be caught by the intrinsicck pass
198
234
assert_eq ! ( in_type_size, out_type_size) ;
199
235
@@ -311,8 +347,6 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
311
347
}
312
348
}
313
349
314
- let call_debug_location = DebugLoc :: At ( call_info. id , call_info. span ) ;
315
-
316
350
// For `try` we need some custom control flow
317
351
if & name[ ..] == "try" {
318
352
if let callee:: ArgExprs ( ref exprs) = args {
0 commit comments