@@ -47,6 +47,7 @@ pub enum ReviewRisk {
4747 Effect ,
4848 Boundary ,
4949 Unsafe ,
50+ Guarantee ,
5051}
5152
5253impl ReviewRisk {
@@ -58,6 +59,7 @@ impl ReviewRisk {
5859 Self :: Effect => "effect" ,
5960 Self :: Boundary => "boundary" ,
6061 Self :: Unsafe => "unsafe" ,
62+ Self :: Guarantee => "guarantee" ,
6163 }
6264 }
6365}
@@ -238,6 +240,10 @@ fn review_fixes(code: &str) -> Vec<ReviewFix> {
238240 "review_unsafe_native_boundary" ,
239241 "Review the new unsafe or native boundary and require explicit justification." ,
240242 ) ,
243+ code:: REVIEW_GUARANTEE_REMOVED => (
244+ "review_removed_guarantee" ,
245+ "Review callers that relied on the removed runtime guarantee." ,
246+ ) ,
241247 _ => ( "review_change" , "Review this source-level contract change." ) ,
242248 } ;
243249 vec ! [ ReviewFix {
@@ -414,6 +420,26 @@ fn compare_function(old: &FunctionSig, new: &FunctionSig, findings: &mut Vec<Rev
414420 Some ( effects_contract ( & new_unsafe_native) ) ,
415421 ) ) ;
416422 }
423+ let old_guarantees = guarantee_effects ( & old. effects ) ;
424+ let new_guarantees = guarantee_effects ( & new. effects ) ;
425+ let removed_guarantees: BTreeSet < _ > = old_guarantees
426+ . difference ( & new_guarantees)
427+ . cloned ( )
428+ . collect ( ) ;
429+ if !removed_guarantees. is_empty ( ) {
430+ findings. push ( review_finding (
431+ code:: REVIEW_GUARANTEE_REMOVED ,
432+ ReviewRisk :: Guarantee ,
433+ format ! (
434+ "function `{}` removed guarantee(s): {}." ,
435+ old. name,
436+ effects_contract( & removed_guarantees)
437+ ) ,
438+ paired_spans ( & old. span , & new. span , "old guarantees" , "new guarantees" ) ,
439+ Some ( effects_contract ( & old_guarantees) ) ,
440+ Some ( effects_contract ( & new_guarantees) ) ,
441+ ) ) ;
442+ }
417443 if old. boundary != new. boundary {
418444 findings. push ( review_finding (
419445 code:: REVIEW_BOUNDARY_CHANGED ,
@@ -552,6 +578,19 @@ fn unsafe_native_effects(effects: &BTreeSet<String>) -> BTreeSet<String> {
552578 . collect ( )
553579}
554580
581+ fn guarantee_effects ( effects : & BTreeSet < String > ) -> BTreeSet < String > {
582+ effects
583+ . iter ( )
584+ . filter ( |effect| {
585+ matches ! (
586+ effect. as_str( ) ,
587+ "no_panic" | "noalloc" | "no_block" | "pure"
588+ )
589+ } )
590+ . cloned ( )
591+ . collect ( )
592+ }
593+
555594fn type_contract ( ty : & TypeSig ) -> String {
556595 format ! (
557596 "{} {} {{ {} }}" ,
0 commit comments