44use std:: cmp;
55
66use chalk_ir:: TyKind ;
7- use hir_def:: resolver:: HasResolver ;
7+ use hir_def:: {
8+ builtin_type:: { BuiltinInt , BuiltinUint } ,
9+ resolver:: HasResolver ,
10+ } ;
811use hir_expand:: mod_path:: ModPath ;
912
1013use super :: * ;
@@ -300,21 +303,36 @@ impl Evaluator<'_> {
300303 BeginPanic => Err ( MirEvalError :: Panic ( "<unknown-panic-payload>" . to_string ( ) ) ) ,
301304 PanicFmt => {
302305 let message = ( || {
303- let resolver = self . db . crate_def_map ( self . crate_id ) . crate_root ( ) . resolver ( self . db . upcast ( ) ) ;
306+ let resolver = self
307+ . db
308+ . crate_def_map ( self . crate_id )
309+ . crate_root ( )
310+ . resolver ( self . db . upcast ( ) ) ;
304311 let Some ( format_fn) = resolver. resolve_path_in_value_ns_fully (
305312 self . db . upcast ( ) ,
306- & hir_def:: path:: Path :: from_known_path_with_no_generic ( ModPath :: from_segments (
307- hir_expand:: mod_path:: PathKind :: Abs ,
308- [ name ! [ std] , name ! [ fmt] , name ! [ format] ] . into_iter ( ) ,
309- ) ) ,
313+ & hir_def:: path:: Path :: from_known_path_with_no_generic (
314+ ModPath :: from_segments (
315+ hir_expand:: mod_path:: PathKind :: Abs ,
316+ [ name ! [ std] , name ! [ fmt] , name ! [ format] ] . into_iter ( ) ,
317+ ) ,
318+ ) ,
310319 ) else {
311320 not_supported ! ( "std::fmt::format not found" ) ;
312321 } ;
313- let hir_def:: resolver:: ValueNs :: FunctionId ( format_fn) = format_fn else { not_supported ! ( "std::fmt::format is not a function" ) } ;
314- let message_string = self . interpret_mir ( self . db . mir_body ( format_fn. into ( ) ) . map_err ( |e| MirEvalError :: MirLowerError ( format_fn, e) ) ?, args. map ( |x| IntervalOrOwned :: Owned ( x. clone ( ) ) ) ) ?;
315- let addr = Address :: from_bytes ( & message_string[ self . ptr_size ( ) ..2 * self . ptr_size ( ) ] ) ?;
322+ let hir_def:: resolver:: ValueNs :: FunctionId ( format_fn) = format_fn else {
323+ not_supported ! ( "std::fmt::format is not a function" )
324+ } ;
325+ let message_string = self . interpret_mir (
326+ self . db
327+ . mir_body ( format_fn. into ( ) )
328+ . map_err ( |e| MirEvalError :: MirLowerError ( format_fn, e) ) ?,
329+ args. map ( |x| IntervalOrOwned :: Owned ( x. clone ( ) ) ) ,
330+ ) ?;
331+ let addr =
332+ Address :: from_bytes ( & message_string[ self . ptr_size ( ) ..2 * self . ptr_size ( ) ] ) ?;
316333 let size = from_bytes ! ( usize , message_string[ 2 * self . ptr_size( ) ..] ) ;
317- Ok ( std:: string:: String :: from_utf8_lossy ( self . read_memory ( addr, size) ?) . into_owned ( ) )
334+ Ok ( std:: string:: String :: from_utf8_lossy ( self . read_memory ( addr, size) ?)
335+ . into_owned ( ) )
318336 } ) ( )
319337 . unwrap_or_else ( |e| format ! ( "Failed to render panic format args: {e:?}" ) ) ;
320338 Err ( MirEvalError :: Panic ( message) )
@@ -483,9 +501,7 @@ impl Evaluator<'_> {
483501 }
484502 "syscall" => {
485503 let Some ( ( id, rest) ) = args. split_first ( ) else {
486- return Err ( MirEvalError :: TypeError (
487- "syscall arg1 is not provided" ,
488- ) ) ;
504+ return Err ( MirEvalError :: TypeError ( "syscall arg1 is not provided" ) ) ;
489505 } ;
490506 let id = from_bytes ! ( i64 , id. get( self ) ?) ;
491507 self . exec_syscall ( id, rest, destination, locals, span)
@@ -710,22 +726,26 @@ impl Evaluator<'_> {
710726 }
711727 match name {
712728 "size_of" => {
713- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
729+ let Some ( ty) =
730+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
714731 else {
715732 return Err ( MirEvalError :: TypeError ( "size_of generic arg is not provided" ) ) ;
716733 } ;
717734 let size = self . size_of_sized ( ty, locals, "size_of arg" ) ?;
718735 destination. write_from_bytes ( self , & size. to_le_bytes ( ) [ 0 ..destination. size ] )
719736 }
720737 "min_align_of" | "pref_align_of" => {
721- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) ) else {
738+ let Some ( ty) =
739+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
740+ else {
722741 return Err ( MirEvalError :: TypeError ( "align_of generic arg is not provided" ) ) ;
723742 } ;
724743 let align = self . layout ( ty) ?. align . abi . bytes ( ) ;
725744 destination. write_from_bytes ( self , & align. to_le_bytes ( ) [ 0 ..destination. size ] )
726745 }
727746 "size_of_val" => {
728- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
747+ let Some ( ty) =
748+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
729749 else {
730750 return Err ( MirEvalError :: TypeError ( "size_of_val generic arg is not provided" ) ) ;
731751 } ;
@@ -741,8 +761,12 @@ impl Evaluator<'_> {
741761 }
742762 }
743763 "min_align_of_val" => {
744- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) ) else {
745- return Err ( MirEvalError :: TypeError ( "min_align_of_val generic arg is not provided" ) ) ;
764+ let Some ( ty) =
765+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
766+ else {
767+ return Err ( MirEvalError :: TypeError (
768+ "min_align_of_val generic arg is not provided" ,
769+ ) ) ;
746770 } ;
747771 let [ arg] = args else {
748772 return Err ( MirEvalError :: TypeError ( "min_align_of_val args are not provided" ) ) ;
@@ -756,7 +780,8 @@ impl Evaluator<'_> {
756780 }
757781 }
758782 "type_name" => {
759- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
783+ let Some ( ty) =
784+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
760785 else {
761786 return Err ( MirEvalError :: TypeError ( "type_name generic arg is not provided" ) ) ;
762787 } ;
@@ -779,7 +804,8 @@ impl Evaluator<'_> {
779804 . write_from_bytes ( self , & len. to_le_bytes ( ) )
780805 }
781806 "needs_drop" => {
782- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
807+ let Some ( ty) =
808+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
783809 else {
784810 return Err ( MirEvalError :: TypeError ( "size_of generic arg is not provided" ) ) ;
785811 } ;
@@ -831,9 +857,12 @@ impl Evaluator<'_> {
831857 let lhs = i128:: from_le_bytes ( pad16 ( lhs. get ( self ) ?, false ) ) ;
832858 let rhs = i128:: from_le_bytes ( pad16 ( rhs. get ( self ) ?, false ) ) ;
833859 let ans = lhs. wrapping_sub ( rhs) ;
834- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
860+ let Some ( ty) =
861+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
835862 else {
836- return Err ( MirEvalError :: TypeError ( "ptr_offset_from generic arg is not provided" ) ) ;
863+ return Err ( MirEvalError :: TypeError (
864+ "ptr_offset_from generic arg is not provided" ,
865+ ) ) ;
837866 } ;
838867 let size = self . size_of_sized ( ty, locals, "ptr_offset_from arg" ) ? as i128 ;
839868 let ans = ans / size;
@@ -940,7 +969,8 @@ impl Evaluator<'_> {
940969 "copy_nonoverlapping args are not provided" ,
941970 ) ) ;
942971 } ;
943- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
972+ let Some ( ty) =
973+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
944974 else {
945975 return Err ( MirEvalError :: TypeError (
946976 "copy_nonoverlapping generic arg is not provided" ,
@@ -959,9 +989,45 @@ impl Evaluator<'_> {
959989 let [ ptr, offset] = args else {
960990 return Err ( MirEvalError :: TypeError ( "offset args are not provided" ) ) ;
961991 } ;
962- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
963- else {
964- return Err ( MirEvalError :: TypeError ( "offset generic arg is not provided" ) ) ;
992+ let ty = if name == "offset" {
993+ let Some ( ty0) =
994+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
995+ else {
996+ return Err ( MirEvalError :: TypeError ( "offset generic arg is not provided" ) ) ;
997+ } ;
998+ let Some ( ty1) =
999+ generic_args. as_slice ( Interner ) . get ( 1 ) . and_then ( |it| it. ty ( Interner ) )
1000+ else {
1001+ return Err ( MirEvalError :: TypeError ( "offset generic arg is not provided" ) ) ;
1002+ } ;
1003+ if !matches ! (
1004+ ty1. as_builtin( ) ,
1005+ Some (
1006+ BuiltinType :: Int ( BuiltinInt :: Isize )
1007+ | BuiltinType :: Uint ( BuiltinUint :: Usize )
1008+ )
1009+ ) {
1010+ return Err ( MirEvalError :: TypeError (
1011+ "offset generic arg is not usize or isize" ,
1012+ ) ) ;
1013+ }
1014+ match ty0. as_raw_ptr ( ) {
1015+ Some ( ( ty, _) ) => ty,
1016+ None => {
1017+ return Err ( MirEvalError :: TypeError (
1018+ "offset generic arg is not a raw pointer" ,
1019+ ) ) ;
1020+ }
1021+ }
1022+ } else {
1023+ let Some ( ty) =
1024+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
1025+ else {
1026+ return Err ( MirEvalError :: TypeError (
1027+ "arith_offset generic arg is not provided" ,
1028+ ) ) ;
1029+ } ;
1030+ ty
9651031 } ;
9661032 let ptr = u128:: from_le_bytes ( pad16 ( ptr. get ( self ) ?, false ) ) ;
9671033 let offset = u128:: from_le_bytes ( pad16 ( offset. get ( self ) ?, false ) ) ;
@@ -1079,7 +1145,8 @@ impl Evaluator<'_> {
10791145 let [ arg] = args else {
10801146 return Err ( MirEvalError :: TypeError ( "discriminant_value arg is not provided" ) ) ;
10811147 } ;
1082- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
1148+ let Some ( ty) =
1149+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
10831150 else {
10841151 return Err ( MirEvalError :: TypeError (
10851152 "discriminant_value generic arg is not provided" ,
@@ -1139,11 +1206,10 @@ impl Evaluator<'_> {
11391206 } ;
11401207 let count = from_bytes ! ( usize , count. get( self ) ?) ;
11411208 let val = from_bytes ! ( u8 , val. get( self ) ?) ;
1142- let Some ( ty) = generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
1209+ let Some ( ty) =
1210+ generic_args. as_slice ( Interner ) . get ( 0 ) . and_then ( |it| it. ty ( Interner ) )
11431211 else {
1144- return Err ( MirEvalError :: TypeError (
1145- "write_bytes generic arg is not provided" ,
1146- ) ) ;
1212+ return Err ( MirEvalError :: TypeError ( "write_bytes generic arg is not provided" ) ) ;
11471213 } ;
11481214 let dst = Address :: from_bytes ( dst. get ( self ) ?) ?;
11491215 let size = self . size_of_sized ( ty, locals, "copy_nonoverlapping ptr type" ) ?;
0 commit comments