@@ -38,6 +38,7 @@ use rustc_span::def_id::CRATE_DEF_ID;
38
38
use rustc_span:: source_map:: Spanned ;
39
39
use rustc_span:: symbol:: sym;
40
40
use rustc_span:: Span ;
41
+ use rustc_span:: DUMMY_SP ;
41
42
use rustc_target:: abi:: { FieldIdx , FIRST_VARIANT } ;
42
43
use rustc_trait_selection:: traits:: query:: type_op:: custom:: scrape_region_constraints;
43
44
use rustc_trait_selection:: traits:: query:: type_op:: custom:: CustomTypeOp ;
@@ -49,6 +50,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
49
50
use rustc_mir_dataflow:: move_paths:: MoveData ;
50
51
use rustc_mir_dataflow:: ResultsCursor ;
51
52
53
+ use crate :: renumber:: RegionCtxt ;
52
54
use crate :: session_diagnostics:: { MoveUnsized , SimdIntrinsicArgConst } ;
53
55
use crate :: {
54
56
borrow_set:: BorrowSet ,
@@ -1352,7 +1354,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1352
1354
}
1353
1355
// FIXME: check the values
1354
1356
}
1355
- TerminatorKind :: Call { func, args, destination, call_source, target, .. } => {
1357
+ TerminatorKind :: Call { func, args, .. }
1358
+ | TerminatorKind :: TailCall { func, args, .. } => {
1359
+ let call_source = match term. kind {
1360
+ TerminatorKind :: Call { call_source, .. } => call_source,
1361
+ TerminatorKind :: TailCall { .. } => CallSource :: Normal ,
1362
+ _ => unreachable ! ( ) ,
1363
+ } ;
1364
+
1356
1365
self . check_operand ( func, term_location) ;
1357
1366
for arg in args {
1358
1367
self . check_operand ( & arg. node , term_location) ;
@@ -1425,7 +1434,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1425
1434
) ;
1426
1435
}
1427
1436
1428
- self . check_call_dest ( body, term, & sig, * destination, * target, term_location) ;
1437
+ if let TerminatorKind :: Call { destination, target, .. } = term. kind {
1438
+ self . check_call_dest ( body, term, & sig, destination, target, term_location) ;
1439
+ }
1429
1440
1430
1441
// The ordinary liveness rules will ensure that all
1431
1442
// regions in the type of the callee are live here. We
@@ -1443,7 +1454,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1443
1454
. add_location ( region_vid, term_location) ;
1444
1455
}
1445
1456
1446
- self . check_call_inputs ( body, term, func, & sig, args, term_location, * call_source) ;
1457
+ self . check_call_inputs ( body, term, func, & sig, args, term_location, call_source) ;
1447
1458
}
1448
1459
TerminatorKind :: Assert { cond, msg, .. } => {
1449
1460
self . check_operand ( cond, term_location) ;
@@ -1675,6 +1686,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1675
1686
span_mirbug ! ( self , block_data, "return on cleanup block" )
1676
1687
}
1677
1688
}
1689
+ TerminatorKind :: TailCall { .. } => {
1690
+ if is_cleanup {
1691
+ span_mirbug ! ( self , block_data, "tailcall on cleanup block" )
1692
+ }
1693
+ }
1678
1694
TerminatorKind :: CoroutineDrop { .. } => {
1679
1695
if is_cleanup {
1680
1696
span_mirbug ! ( self , block_data, "coroutine_drop in cleanup block" )
@@ -2319,7 +2335,57 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
2319
2335
let cast_ty_from = CastTy :: from_ty ( ty_from) ;
2320
2336
let cast_ty_to = CastTy :: from_ty ( * ty) ;
2321
2337
match ( cast_ty_from, cast_ty_to) {
2322
- ( Some ( CastTy :: Ptr ( _) ) , Some ( CastTy :: Ptr ( _) ) ) => ( ) ,
2338
+ ( Some ( CastTy :: Ptr ( src) ) , Some ( CastTy :: Ptr ( dst) ) ) => {
2339
+ let mut normalize = |t| self . normalize ( t, location) ;
2340
+ let src_tail =
2341
+ tcx. struct_tail_with_normalize ( src. ty , & mut normalize, || ( ) ) ;
2342
+ let dst_tail =
2343
+ tcx. struct_tail_with_normalize ( dst. ty , & mut normalize, || ( ) ) ;
2344
+
2345
+ // This checks (lifetime part of) vtable validity for pointer casts,
2346
+ // which is irrelevant when there are aren't principal traits on both sides (aka only auto traits).
2347
+ //
2348
+ // Note that other checks (such as denying `dyn Send` -> `dyn Debug`) are in `rustc_hir_typeck`.
2349
+ if let ty:: Dynamic ( src_tty, ..) = src_tail. kind ( )
2350
+ && let ty:: Dynamic ( dst_tty, ..) = dst_tail. kind ( )
2351
+ && src_tty. principal ( ) . is_some ( )
2352
+ && dst_tty. principal ( ) . is_some ( )
2353
+ {
2354
+ // Remove auto traits.
2355
+ // Auto trait checks are handled in `rustc_hir_typeck` as FCW.
2356
+ let src_obj = tcx. mk_ty_from_kind ( ty:: Dynamic (
2357
+ tcx. mk_poly_existential_predicates (
2358
+ & src_tty. without_auto_traits ( ) . collect :: < Vec < _ > > ( ) ,
2359
+ ) ,
2360
+ tcx. lifetimes . re_static ,
2361
+ ty:: Dyn ,
2362
+ ) ) ;
2363
+ let dst_obj = tcx. mk_ty_from_kind ( ty:: Dynamic (
2364
+ tcx. mk_poly_existential_predicates (
2365
+ & dst_tty. without_auto_traits ( ) . collect :: < Vec < _ > > ( ) ,
2366
+ ) ,
2367
+ tcx. lifetimes . re_static ,
2368
+ ty:: Dyn ,
2369
+ ) ) ;
2370
+
2371
+ // Replace trait object lifetimes with fresh vars, to allow casts like
2372
+ // `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static`,
2373
+ let src_obj =
2374
+ freshen_single_trait_object_lifetime ( self . infcx , src_obj) ;
2375
+ let dst_obj =
2376
+ freshen_single_trait_object_lifetime ( self . infcx , dst_obj) ;
2377
+
2378
+ debug ! ( ?src_tty, ?dst_tty, ?src_obj, ?dst_obj) ;
2379
+
2380
+ self . eq_types (
2381
+ src_obj,
2382
+ dst_obj,
2383
+ location. to_locations ( ) ,
2384
+ ConstraintCategory :: Cast { unsize_to : None } ,
2385
+ )
2386
+ . unwrap ( ) ;
2387
+ }
2388
+ }
2323
2389
_ => {
2324
2390
span_mirbug ! (
2325
2391
self ,
@@ -2842,3 +2908,16 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
2842
2908
Ok ( output)
2843
2909
}
2844
2910
}
2911
+
2912
+ fn freshen_single_trait_object_lifetime < ' tcx > (
2913
+ infcx : & BorrowckInferCtxt < ' tcx > ,
2914
+ ty : Ty < ' tcx > ,
2915
+ ) -> Ty < ' tcx > {
2916
+ let & ty:: Dynamic ( tty, _, dyn_kind @ ty:: Dyn ) = ty. kind ( ) else { bug ! ( "expected trait object" ) } ;
2917
+
2918
+ let fresh = infcx
2919
+ . next_region_var ( rustc_infer:: infer:: RegionVariableOrigin :: MiscVariable ( DUMMY_SP ) , || {
2920
+ RegionCtxt :: Unknown
2921
+ } ) ;
2922
+ infcx. tcx . mk_ty_from_kind ( ty:: Dynamic ( tty, fresh, dyn_kind) )
2923
+ }
0 commit comments