@@ -42,7 +42,7 @@ use rustc_middle::ty::cast::{CastKind, CastTy};
42
42
use rustc_middle:: ty:: error:: TypeError ;
43
43
use rustc_middle:: ty:: { self , Ty , TypeAndMut , TypeVisitableExt , VariantDef } ;
44
44
use rustc_session:: lint;
45
- use rustc_span:: def_id:: { DefId , LOCAL_CRATE } ;
45
+ use rustc_span:: def_id:: LOCAL_CRATE ;
46
46
use rustc_span:: symbol:: sym;
47
47
use rustc_span:: Span ;
48
48
use rustc_trait_selection:: infer:: InferCtxtExt ;
@@ -72,7 +72,7 @@ enum PointerKind<'tcx> {
72
72
/// No metadata attached, ie pointer to sized type or foreign type
73
73
Thin ,
74
74
/// A trait object
75
- VTable ( Option < DefId > ) ,
75
+ VTable ( Option < ty :: Binder < ' tcx , ty :: ExistentialTraitRef < ' tcx > > > ) ,
76
76
/// Slice
77
77
Length ,
78
78
/// The unsize info of this projection or opaque type
@@ -100,7 +100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
100
100
101
101
Ok ( match * t. kind ( ) {
102
102
ty:: Slice ( _) | ty:: Str => Some ( PointerKind :: Length ) ,
103
- ty:: Dynamic ( tty, _, ty:: Dyn ) => Some ( PointerKind :: VTable ( tty. principal_def_id ( ) ) ) ,
103
+ ty:: Dynamic ( tty, _, ty:: Dyn ) => Some ( PointerKind :: VTable ( tty. principal ( ) ) ) ,
104
104
ty:: Adt ( def, args) if def. is_struct ( ) => match def. non_enum_variant ( ) . tail_opt ( ) {
105
105
None => Some ( PointerKind :: Thin ) ,
106
106
Some ( f) => {
@@ -611,14 +611,39 @@ impl<'a, 'tcx> CastCheck<'tcx> {
611
611
} else {
612
612
match self . try_coercion_cast ( fcx) {
613
613
Ok ( ( ) ) => {
614
- if self . expr_ty . is_unsafe_ptr ( ) && self . cast_ty . is_unsafe_ptr ( ) {
615
- // When casting a raw pointer to another raw pointer, we cannot convert the cast into
616
- // a coercion because the pointee types might only differ in regions, which HIR typeck
617
- // cannot distinguish. This would cause us to erroneously discard a cast which will
618
- // lead to a borrowck error like #113257.
619
- // We still did a coercion above to unify inference variables for `ptr as _` casts.
620
- // This does cause us to miss some trivial casts in the trival cast lint.
621
- debug ! ( " -> PointerCast" ) ;
614
+ if let ty:: RawPtr ( src_pointee) = self . expr_ty . kind ( )
615
+ && let ty:: RawPtr ( tgt_pointee) = self . cast_ty . kind ( )
616
+ {
617
+ if let Ok ( Some ( src_kind) ) = fcx. pointer_kind ( src_pointee. ty , self . expr_span )
618
+ && let Ok ( Some ( tgt_kind) ) =
619
+ fcx. pointer_kind ( tgt_pointee. ty , self . cast_span )
620
+ {
621
+ match ( src_kind, tgt_kind) {
622
+ // When casting a raw pointer to another raw pointer, we cannot convert the cast into
623
+ // a coercion because the pointee types might only differ in regions, which HIR typeck
624
+ // cannot distinguish. This would cause us to erroneously discard a cast which will
625
+ // lead to a borrowck error like #113257.
626
+ // We still did a coercion above to unify inference variables for `ptr as _` casts.
627
+ // This does cause us to miss some trivial casts in the trivial cast lint.
628
+ ( PointerKind :: Thin , PointerKind :: Thin )
629
+ | ( PointerKind :: Length , PointerKind :: Length ) => {
630
+ debug ! ( " -> PointerCast" ) ;
631
+ }
632
+
633
+ // If we are not casting pointers to sized types or slice-ish DSTs
634
+ // (handled above), we need to make a coercion cast. This prevents
635
+ // casts like `*const dyn Trait<'a> -> *const dyn Trait<'b>` which
636
+ // are unsound.
637
+ //
638
+ // See <https://github.com/rust-lang/rust/issues/120217>
639
+ ( _, _) => {
640
+ debug ! ( " -> CoercionCast" ) ;
641
+ fcx. typeck_results
642
+ . borrow_mut ( )
643
+ . set_coercion_cast ( self . expr . hir_id . local_id ) ;
644
+ }
645
+ }
646
+ }
622
647
} else {
623
648
self . trivial_cast_lint ( fcx) ;
624
649
debug ! ( " -> CoercionCast" ) ;
0 commit comments