@@ -32,6 +32,7 @@ use rustc_data_structures::fx::FxHashSet;
32
32
use rustc_errors:: codes:: * ;
33
33
use rustc_errors:: { Applicability , Diag , ErrorGuaranteed } ;
34
34
use rustc_hir:: { self as hir, ExprKind } ;
35
+ use rustc_infer:: infer:: DefineOpaqueTypes ;
35
36
use rustc_macros:: { TypeFoldable , TypeVisitable } ;
36
37
use rustc_middle:: mir:: Mutability ;
37
38
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
@@ -152,12 +153,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
152
153
}
153
154
154
155
#[ derive( Copy , Clone , Debug ) ]
155
- pub enum CastError {
156
+ enum CastError < ' tcx > {
156
157
ErrorGuaranteed ( ErrorGuaranteed ) ,
157
158
158
159
CastToBool ,
159
160
CastToChar ,
160
- DifferingKinds ,
161
+ DifferingKinds {
162
+ src_kind : PointerKind < ' tcx > ,
163
+ dst_kind : PointerKind < ' tcx > ,
164
+ } ,
161
165
/// Cast of thin to fat raw ptr (e.g., `*const () as *const [u8]`).
162
166
SizedUnsizedCast ,
163
167
IllegalCast ,
@@ -177,7 +181,7 @@ pub enum CastError {
177
181
ForeignNonExhaustiveAdt ,
178
182
}
179
183
180
- impl From < ErrorGuaranteed > for CastError {
184
+ impl From < ErrorGuaranteed > for CastError < ' _ > {
181
185
fn from ( err : ErrorGuaranteed ) -> Self {
182
186
CastError :: ErrorGuaranteed ( err)
183
187
}
@@ -251,7 +255,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
251
255
}
252
256
}
253
257
254
- fn report_cast_error ( & self , fcx : & FnCtxt < ' a , ' tcx > , e : CastError ) {
258
+ fn report_cast_error ( & self , fcx : & FnCtxt < ' a , ' tcx > , e : CastError < ' tcx > ) {
255
259
match e {
256
260
CastError :: ErrorGuaranteed ( _) => {
257
261
// an error has already been reported
@@ -306,10 +310,52 @@ impl<'a, 'tcx> CastCheck<'tcx> {
306
310
CastError :: IllegalCast => {
307
311
make_invalid_casting_error ( self . span , self . expr_ty , self . cast_ty , fcx) . emit ( ) ;
308
312
}
309
- CastError :: DifferingKinds => {
310
- make_invalid_casting_error ( self . span , self . expr_ty , self . cast_ty , fcx)
311
- . with_note ( "vtable kinds may not match" )
312
- . emit ( ) ;
313
+ CastError :: DifferingKinds { src_kind, dst_kind } => {
314
+ let mut err =
315
+ make_invalid_casting_error ( self . span , self . expr_ty , self . cast_ty , fcx) ;
316
+
317
+ match ( src_kind, dst_kind) {
318
+ ( PointerKind :: VTable ( _) , PointerKind :: VTable ( _) ) => {
319
+ err. note ( "the trait objects may have different vtables" ) ;
320
+ }
321
+ (
322
+ PointerKind :: OfParam ( _) | PointerKind :: OfAlias ( _) ,
323
+ PointerKind :: OfParam ( _)
324
+ | PointerKind :: OfAlias ( _)
325
+ | PointerKind :: VTable ( _)
326
+ | PointerKind :: Length ,
327
+ )
328
+ | (
329
+ PointerKind :: VTable ( _) | PointerKind :: Length ,
330
+ PointerKind :: OfParam ( _) | PointerKind :: OfAlias ( _) ,
331
+ ) => {
332
+ err. note ( "the pointers may have different metadata" ) ;
333
+ }
334
+ ( PointerKind :: VTable ( _) , PointerKind :: Length )
335
+ | ( PointerKind :: Length , PointerKind :: VTable ( _) ) => {
336
+ err. note ( "the pointers have different metadata" ) ;
337
+ }
338
+ (
339
+ PointerKind :: Thin ,
340
+ PointerKind :: Thin
341
+ | PointerKind :: VTable ( _)
342
+ | PointerKind :: Length
343
+ | PointerKind :: OfParam ( _)
344
+ | PointerKind :: OfAlias ( _) ,
345
+ )
346
+ | (
347
+ PointerKind :: VTable ( _)
348
+ | PointerKind :: Length
349
+ | PointerKind :: OfParam ( _)
350
+ | PointerKind :: OfAlias ( _) ,
351
+ PointerKind :: Thin ,
352
+ )
353
+ | ( PointerKind :: Length , PointerKind :: Length ) => {
354
+ span_bug ! ( self . span, "unexpected cast error: {e:?}" )
355
+ }
356
+ }
357
+
358
+ err. emit ( ) ;
313
359
}
314
360
CastError :: CastToBool => {
315
361
let expr_ty = fcx. resolve_vars_if_possible ( self . expr_ty ) ;
@@ -674,7 +720,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
674
720
/// Checks a cast, and report an error if one exists. In some cases, this
675
721
/// can return Ok and create type errors in the fcx rather than returning
676
722
/// directly. coercion-cast is handled in check instead of here.
677
- fn do_check ( & self , fcx : & FnCtxt < ' a , ' tcx > ) -> Result < CastKind , CastError > {
723
+ fn do_check ( & self , fcx : & FnCtxt < ' a , ' tcx > ) -> Result < CastKind , CastError < ' tcx > > {
678
724
use rustc_middle:: ty:: cast:: CastTy :: * ;
679
725
use rustc_middle:: ty:: cast:: IntTy :: * ;
680
726
@@ -802,27 +848,34 @@ impl<'a, 'tcx> CastCheck<'tcx> {
802
848
fcx : & FnCtxt < ' a , ' tcx > ,
803
849
m_src : ty:: TypeAndMut < ' tcx > ,
804
850
m_dst : ty:: TypeAndMut < ' tcx > ,
805
- ) -> Result < CastKind , CastError > {
851
+ ) -> Result < CastKind , CastError < ' tcx > > {
806
852
debug ! ( "check_ptr_ptr_cast m_src={m_src:?} m_dst={m_dst:?}" ) ;
807
- // ptr-ptr cast. vtables must match.
853
+ // ptr-ptr cast. metadata must match.
808
854
809
855
let src_kind = fcx. tcx . erase_regions ( fcx. pointer_kind ( m_src. ty , self . span ) ?) ;
810
856
let dst_kind = fcx. tcx . erase_regions ( fcx. pointer_kind ( m_dst. ty , self . span ) ?) ;
811
857
812
- match ( src_kind, dst_kind) {
813
- // We can't cast if target pointer kind is unknown
814
- ( _, None ) => Err ( CastError :: UnknownCastPtrKind ) ,
815
- // Cast to thin pointer is OK
816
- ( _, Some ( PointerKind :: Thin ) ) => Ok ( CastKind :: PtrPtrCast ) ,
858
+ // We can't cast if target pointer kind is unknown
859
+ let Some ( dst_kind) = dst_kind else {
860
+ return Err ( CastError :: UnknownCastPtrKind ) ;
861
+ } ;
862
+
863
+ // Cast to thin pointer is OK
864
+ if dst_kind == PointerKind :: Thin {
865
+ return Ok ( CastKind :: PtrPtrCast ) ;
866
+ }
817
867
818
- // We can't cast to fat pointer if source pointer kind is unknown
819
- ( None , _) => Err ( CastError :: UnknownExprPtrKind ) ,
868
+ // We can't cast to fat pointer if source pointer kind is unknown
869
+ let Some ( src_kind) = src_kind else {
870
+ return Err ( CastError :: UnknownCastPtrKind ) ;
871
+ } ;
820
872
873
+ match ( src_kind, dst_kind) {
821
874
// thin -> fat? report invalid cast (don't complain about vtable kinds)
822
- ( Some ( PointerKind :: Thin ) , _) => Err ( CastError :: SizedUnsizedCast ) ,
875
+ ( PointerKind :: Thin , _) => Err ( CastError :: SizedUnsizedCast ) ,
823
876
824
877
// trait object -> trait object? need to do additional checks
825
- ( Some ( PointerKind :: VTable ( src_tty) ) , Some ( PointerKind :: VTable ( dst_tty) ) ) => {
878
+ ( PointerKind :: VTable ( src_tty) , PointerKind :: VTable ( dst_tty) ) => {
826
879
match ( src_tty. principal ( ) , dst_tty. principal ( ) ) {
827
880
// A<dyn Src<...> + SrcAuto> -> B<dyn Dst<...> + DstAuto>. need to make sure
828
881
// - `Src` and `Dst` traits are the same
@@ -838,7 +891,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
838
891
// Note that trait upcasting goes through a different mechanism (`coerce_unsized`)
839
892
// and is unaffected by this check.
840
893
if src_principal. def_id ( ) != dst_principal. def_id ( ) {
841
- return Err ( CastError :: DifferingKinds ) ;
894
+ return Err ( CastError :: DifferingKinds { src_kind , dst_kind } ) ;
842
895
}
843
896
844
897
// We need to reconstruct trait object types.
@@ -864,7 +917,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
864
917
) ) ;
865
918
866
919
// `dyn Src = dyn Dst`, this checks for matching traits/generics
867
- fcx. demand_eqtype ( self . span , src_obj, dst_obj) ;
920
+ // This is `demand_eqtype`, but inlined to give a better error.
921
+ let cause = fcx. misc ( self . span ) ;
922
+ if fcx
923
+ . at ( & cause, fcx. param_env )
924
+ . eq ( DefineOpaqueTypes :: Yes , src_obj, dst_obj)
925
+ . map ( |infer_ok| fcx. register_infer_ok_obligations ( infer_ok) )
926
+ . is_err ( )
927
+ {
928
+ return Err ( CastError :: DifferingKinds { src_kind, dst_kind } ) ;
929
+ }
868
930
869
931
// Check that `SrcAuto` (+auto traits implied by `Src`) is a superset of `DstAuto`.
870
932
// Emit an FCW otherwise.
@@ -909,25 +971,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
909
971
910
972
// dyn Trait -> dyn Auto? should be ok, but we used to not allow it.
911
973
// FIXME: allow this
912
- ( Some ( _) , None ) => Err ( CastError :: DifferingKinds ) ,
974
+ ( Some ( _) , None ) => Err ( CastError :: DifferingKinds { src_kind , dst_kind } ) ,
913
975
914
976
// dyn Auto -> dyn Trait? not ok.
915
- ( None , Some ( _) ) => Err ( CastError :: DifferingKinds ) ,
977
+ ( None , Some ( _) ) => Err ( CastError :: DifferingKinds { src_kind , dst_kind } ) ,
916
978
}
917
979
}
918
980
919
981
// fat -> fat? metadata kinds must match
920
- ( Some ( src_kind) , Some ( dst_kind) ) if src_kind == dst_kind => Ok ( CastKind :: PtrPtrCast ) ,
982
+ ( src_kind, dst_kind) if src_kind == dst_kind => Ok ( CastKind :: PtrPtrCast ) ,
921
983
922
- ( _, _) => Err ( CastError :: DifferingKinds ) ,
984
+ ( _, _) => Err ( CastError :: DifferingKinds { src_kind , dst_kind } ) ,
923
985
}
924
986
}
925
987
926
988
fn check_fptr_ptr_cast (
927
989
& self ,
928
990
fcx : & FnCtxt < ' a , ' tcx > ,
929
991
m_cast : ty:: TypeAndMut < ' tcx > ,
930
- ) -> Result < CastKind , CastError > {
992
+ ) -> Result < CastKind , CastError < ' tcx > > {
931
993
// fptr-ptr cast. must be to thin ptr
932
994
933
995
match fcx. pointer_kind ( m_cast. ty , self . span ) ? {
@@ -941,7 +1003,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
941
1003
& self ,
942
1004
fcx : & FnCtxt < ' a , ' tcx > ,
943
1005
m_expr : ty:: TypeAndMut < ' tcx > ,
944
- ) -> Result < CastKind , CastError > {
1006
+ ) -> Result < CastKind , CastError < ' tcx > > {
945
1007
// ptr-addr cast. must be from thin ptr
946
1008
947
1009
match fcx. pointer_kind ( m_expr. ty , self . span ) ? {
@@ -956,7 +1018,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
956
1018
fcx : & FnCtxt < ' a , ' tcx > ,
957
1019
m_expr : ty:: TypeAndMut < ' tcx > ,
958
1020
m_cast : ty:: TypeAndMut < ' tcx > ,
959
- ) -> Result < CastKind , CastError > {
1021
+ ) -> Result < CastKind , CastError < ' tcx > > {
960
1022
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
961
1023
if m_expr. mutbl >= m_cast. mutbl {
962
1024
if let ty:: Array ( ety, _) = m_expr. ty . kind ( ) {
@@ -991,7 +1053,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
991
1053
& self ,
992
1054
fcx : & FnCtxt < ' a , ' tcx > ,
993
1055
m_cast : TypeAndMut < ' tcx > ,
994
- ) -> Result < CastKind , CastError > {
1056
+ ) -> Result < CastKind , CastError < ' tcx > > {
995
1057
// ptr-addr cast. pointer must be thin.
996
1058
match fcx. pointer_kind ( m_cast. ty , self . span ) ? {
997
1059
None => Err ( CastError :: UnknownCastPtrKind ) ,
0 commit comments