@@ -74,6 +74,46 @@ fn name_is(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, expected: &str) -> bool
74
74
false
75
75
}
76
76
77
+ struct ExpectFail ;
78
+ impl < ' tcx > GotocHook < ' tcx > for ExpectFail {
79
+ fn hook_applies ( & self , tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) -> bool {
80
+ let def_path = tcx. def_path ( instance. def . def_id ( ) ) ;
81
+ if let Some ( data) = def_path. data . last ( ) {
82
+ match data. data . name ( ) {
83
+ DefPathDataName :: Named ( name) => {
84
+ return name. to_string ( ) . starts_with ( "__VERIFIER_expect_fail" ) ;
85
+ }
86
+ DefPathDataName :: Anon { .. } => ( ) ,
87
+ }
88
+ }
89
+ false
90
+ }
91
+
92
+ fn handle (
93
+ & self ,
94
+ tcx : & mut GotocCtx < ' tcx > ,
95
+ _instance : Instance < ' tcx > ,
96
+ mut fargs : Vec < Expr > ,
97
+ _assign_to : Option < Place < ' tcx > > ,
98
+ target : Option < BasicBlock > ,
99
+ span : Option < Span > ,
100
+ ) -> Stmt {
101
+ assert_eq ! ( fargs. len( ) , 2 ) ;
102
+ let target = target. unwrap ( ) ;
103
+ let cond = fargs. remove ( 0 ) . cast_to ( Type :: bool ( ) ) ;
104
+ //TODO: actually use the error message passed by the user.
105
+ let msg = "EXPECTED FAIL" ;
106
+ let loc = tcx. codegen_span_option2 ( span) ;
107
+ Stmt :: block (
108
+ vec ! [
109
+ Stmt :: assert( cond, msg, loc. clone( ) ) ,
110
+ Stmt :: goto( tcx. current_fn( ) . find_label( & target) , loc. clone( ) ) ,
111
+ ] ,
112
+ loc,
113
+ )
114
+ }
115
+ }
116
+
77
117
struct Assume ;
78
118
impl < ' tcx > GotocHook < ' tcx > for Assume {
79
119
fn hook_applies ( & self , tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) -> bool {
@@ -616,6 +656,7 @@ pub fn type_and_fn_hooks<'tcx>() -> (GotocTypeHooks<'tcx>, GotocHooks<'tcx>) {
616
656
hooks : vec ! [
617
657
Rc :: new( Panic ) , //Must go first, so it overrides Nevers
618
658
Rc :: new( Assume ) ,
659
+ Rc :: new( ExpectFail ) ,
619
660
Rc :: new( Intrinsic ) ,
620
661
Rc :: new( MemReplace ) ,
621
662
Rc :: new( MemSwap ) ,
0 commit comments