@@ -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
@@ -303,10 +307,52 @@ impl<'a, 'tcx> CastCheck<'tcx> {
303
307
CastError :: IllegalCast => {
304
308
make_invalid_casting_error ( self . span , self . expr_ty , self . cast_ty , fcx) . emit ( ) ;
305
309
}
306
- CastError :: DifferingKinds => {
307
- make_invalid_casting_error ( self . span , self . expr_ty , self . cast_ty , fcx)
308
- . with_note ( "vtable kinds may not match" )
309
- . emit ( ) ;
310
+ CastError :: DifferingKinds { src_kind, dst_kind } => {
311
+ let mut err =
312
+ make_invalid_casting_error ( self . span , self . expr_ty , self . cast_ty , fcx) ;
313
+
314
+ match ( src_kind, dst_kind) {
315
+ ( PointerKind :: VTable ( _) , PointerKind :: VTable ( _) ) => {
316
+ err. note ( "the trait objects may have different vtables" ) ;
317
+ }
318
+ (
319
+ PointerKind :: OfParam ( _) | PointerKind :: OfAlias ( _) ,
320
+ PointerKind :: OfParam ( _)
321
+ | PointerKind :: OfAlias ( _)
322
+ | PointerKind :: VTable ( _)
323
+ | PointerKind :: Length ,
324
+ )
325
+ | (
326
+ PointerKind :: VTable ( _) | PointerKind :: Length ,
327
+ PointerKind :: OfParam ( _) | PointerKind :: OfAlias ( _) ,
328
+ ) => {
329
+ err. note ( "the pointers may have different metadata" ) ;
330
+ }
331
+ ( PointerKind :: VTable ( _) , PointerKind :: Length )
332
+ | ( PointerKind :: Length , PointerKind :: VTable ( _) ) => {
333
+ err. note ( "the pointers have different metadata" ) ;
334
+ }
335
+ (
336
+ PointerKind :: Thin ,
337
+ PointerKind :: Thin
338
+ | PointerKind :: VTable ( _)
339
+ | PointerKind :: Length
340
+ | PointerKind :: OfParam ( _)
341
+ | PointerKind :: OfAlias ( _) ,
342
+ )
343
+ | (
344
+ PointerKind :: VTable ( _)
345
+ | PointerKind :: Length
346
+ | PointerKind :: OfParam ( _)
347
+ | PointerKind :: OfAlias ( _) ,
348
+ PointerKind :: Thin ,
349
+ )
350
+ | ( PointerKind :: Length , PointerKind :: Length ) => {
351
+ span_bug ! ( self . span, "unexpected cast error: {e:?}" )
352
+ }
353
+ }
354
+
355
+ err. emit ( ) ;
310
356
}
311
357
CastError :: CastToBool => {
312
358
let expr_ty = fcx. resolve_vars_if_possible ( self . expr_ty ) ;
@@ -670,7 +716,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
670
716
/// Checks a cast, and report an error if one exists. In some cases, this
671
717
/// can return Ok and create type errors in the fcx rather than returning
672
718
/// directly. coercion-cast is handled in check instead of here.
673
- fn do_check ( & self , fcx : & FnCtxt < ' a , ' tcx > ) -> Result < CastKind , CastError > {
719
+ fn do_check ( & self , fcx : & FnCtxt < ' a , ' tcx > ) -> Result < CastKind , CastError < ' tcx > > {
674
720
use rustc_middle:: ty:: cast:: CastTy :: * ;
675
721
use rustc_middle:: ty:: cast:: IntTy :: * ;
676
722
@@ -798,27 +844,34 @@ impl<'a, 'tcx> CastCheck<'tcx> {
798
844
fcx : & FnCtxt < ' a , ' tcx > ,
799
845
m_src : ty:: TypeAndMut < ' tcx > ,
800
846
m_dst : ty:: TypeAndMut < ' tcx > ,
801
- ) -> Result < CastKind , CastError > {
847
+ ) -> Result < CastKind , CastError < ' tcx > > {
802
848
debug ! ( "check_ptr_ptr_cast m_src={m_src:?} m_dst={m_dst:?}" ) ;
803
- // ptr-ptr cast. vtables must match.
849
+ // ptr-ptr cast. metadata must match.
804
850
805
851
let src_kind = fcx. tcx . erase_regions ( fcx. pointer_kind ( m_src. ty , self . span ) ?) ;
806
852
let dst_kind = fcx. tcx . erase_regions ( fcx. pointer_kind ( m_dst. ty , self . span ) ?) ;
807
853
808
- match ( src_kind, dst_kind) {
809
- // We can't cast if target pointer kind is unknown
810
- ( _, None ) => Err ( CastError :: UnknownCastPtrKind ) ,
811
- // Cast to thin pointer is OK
812
- ( _, Some ( PointerKind :: Thin ) ) => Ok ( CastKind :: PtrPtrCast ) ,
854
+ // We can't cast if target pointer kind is unknown
855
+ let Some ( dst_kind) = dst_kind else {
856
+ return Err ( CastError :: UnknownCastPtrKind ) ;
857
+ } ;
858
+
859
+ // Cast to thin pointer is OK
860
+ if dst_kind == PointerKind :: Thin {
861
+ return Ok ( CastKind :: PtrPtrCast ) ;
862
+ }
813
863
814
- // We can't cast to fat pointer if source pointer kind is unknown
815
- ( None , _) => Err ( CastError :: UnknownExprPtrKind ) ,
864
+ // We can't cast to fat pointer if source pointer kind is unknown
865
+ let Some ( src_kind) = src_kind else {
866
+ return Err ( CastError :: UnknownCastPtrKind ) ;
867
+ } ;
816
868
869
+ match ( src_kind, dst_kind) {
817
870
// thin -> fat? report invalid cast (don't complain about vtable kinds)
818
- ( Some ( PointerKind :: Thin ) , _) => Err ( CastError :: SizedUnsizedCast ) ,
871
+ ( PointerKind :: Thin , _) => Err ( CastError :: SizedUnsizedCast ) ,
819
872
820
873
// trait object -> trait object? need to do additional checks
821
- ( Some ( PointerKind :: VTable ( src_tty) ) , Some ( PointerKind :: VTable ( dst_tty) ) ) => {
874
+ ( PointerKind :: VTable ( src_tty) , PointerKind :: VTable ( dst_tty) ) => {
822
875
match ( src_tty. principal ( ) , dst_tty. principal ( ) ) {
823
876
// A<dyn Src<...> + SrcAuto> -> B<dyn Dst<...> + DstAuto>. need to make sure
824
877
// - `Src` and `Dst` traits are the same
@@ -834,7 +887,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
834
887
// Note that trait upcasting goes through a different mechanism (`coerce_unsized`)
835
888
// and is unaffected by this check.
836
889
if src_principal. def_id ( ) != dst_principal. def_id ( ) {
837
- return Err ( CastError :: DifferingKinds ) ;
890
+ return Err ( CastError :: DifferingKinds { src_kind , dst_kind } ) ;
838
891
}
839
892
840
893
// We need to reconstruct trait object types.
@@ -860,7 +913,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
860
913
) ) ;
861
914
862
915
// `dyn Src = dyn Dst`, this checks for matching traits/generics
863
- fcx. demand_eqtype ( self . span , src_obj, dst_obj) ;
916
+ // This is `demand_eqtype`, but inlined to give a better error.
917
+ let cause = fcx. misc ( self . span ) ;
918
+ if fcx
919
+ . at ( & cause, fcx. param_env )
920
+ . eq ( DefineOpaqueTypes :: Yes , src_obj, dst_obj)
921
+ . map ( |infer_ok| fcx. register_infer_ok_obligations ( infer_ok) )
922
+ . is_err ( )
923
+ {
924
+ return Err ( CastError :: DifferingKinds { src_kind, dst_kind } ) ;
925
+ }
864
926
865
927
// Check that `SrcAuto` (+auto traits implied by `Src`) is a superset of `DstAuto`.
866
928
// Emit an FCW otherwise.
@@ -905,25 +967,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
905
967
906
968
// dyn Trait -> dyn Auto? should be ok, but we used to not allow it.
907
969
// FIXME: allow this
908
- ( Some ( _) , None ) => Err ( CastError :: DifferingKinds ) ,
970
+ ( Some ( _) , None ) => Err ( CastError :: DifferingKinds { src_kind , dst_kind } ) ,
909
971
910
972
// dyn Auto -> dyn Trait? not ok.
911
- ( None , Some ( _) ) => Err ( CastError :: DifferingKinds ) ,
973
+ ( None , Some ( _) ) => Err ( CastError :: DifferingKinds { src_kind , dst_kind } ) ,
912
974
}
913
975
}
914
976
915
977
// fat -> fat? metadata kinds must match
916
- ( Some ( src_kind) , Some ( dst_kind) ) if src_kind == dst_kind => Ok ( CastKind :: PtrPtrCast ) ,
978
+ ( src_kind, dst_kind) if src_kind == dst_kind => Ok ( CastKind :: PtrPtrCast ) ,
917
979
918
- ( _, _) => Err ( CastError :: DifferingKinds ) ,
980
+ ( _, _) => Err ( CastError :: DifferingKinds { src_kind , dst_kind } ) ,
919
981
}
920
982
}
921
983
922
984
fn check_fptr_ptr_cast (
923
985
& self ,
924
986
fcx : & FnCtxt < ' a , ' tcx > ,
925
987
m_cast : ty:: TypeAndMut < ' tcx > ,
926
- ) -> Result < CastKind , CastError > {
988
+ ) -> Result < CastKind , CastError < ' tcx > > {
927
989
// fptr-ptr cast. must be to thin ptr
928
990
929
991
match fcx. pointer_kind ( m_cast. ty , self . span ) ? {
@@ -937,7 +999,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
937
999
& self ,
938
1000
fcx : & FnCtxt < ' a , ' tcx > ,
939
1001
m_expr : ty:: TypeAndMut < ' tcx > ,
940
- ) -> Result < CastKind , CastError > {
1002
+ ) -> Result < CastKind , CastError < ' tcx > > {
941
1003
// ptr-addr cast. must be from thin ptr
942
1004
943
1005
match fcx. pointer_kind ( m_expr. ty , self . span ) ? {
@@ -952,7 +1014,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
952
1014
fcx : & FnCtxt < ' a , ' tcx > ,
953
1015
m_expr : ty:: TypeAndMut < ' tcx > ,
954
1016
m_cast : ty:: TypeAndMut < ' tcx > ,
955
- ) -> Result < CastKind , CastError > {
1017
+ ) -> Result < CastKind , CastError < ' tcx > > {
956
1018
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
957
1019
if m_expr. mutbl >= m_cast. mutbl {
958
1020
if let ty:: Array ( ety, _) = m_expr. ty . kind ( ) {
@@ -987,7 +1049,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
987
1049
& self ,
988
1050
fcx : & FnCtxt < ' a , ' tcx > ,
989
1051
m_cast : TypeAndMut < ' tcx > ,
990
- ) -> Result < CastKind , CastError > {
1052
+ ) -> Result < CastKind , CastError < ' tcx > > {
991
1053
// ptr-addr cast. pointer must be thin.
992
1054
match fcx. pointer_kind ( m_cast. ty , self . span ) ? {
993
1055
None => Err ( CastError :: UnknownCastPtrKind ) ,
0 commit comments