@@ -472,20 +472,71 @@ impl<'tcx> Analyzer<'tcx> {
472472 self . fn_sig_with_body ( def_id, body)
473473 }
474474
475+ fn extract_path_with_attr (
476+ & self ,
477+ local_def_id : LocalDefId ,
478+ attr_path : & [ Symbol ] ,
479+ ) -> Option < DefId > {
480+ let map = self . tcx . hir ( ) ;
481+ let Some ( body_id) = map. maybe_body_owned_by ( local_def_id) else {
482+ return None ;
483+ } ;
484+ let body = map. body ( body_id) ;
485+
486+ let rustc_hir:: ExprKind :: Block ( block, _) = body. value . kind else {
487+ return None ;
488+ } ;
489+ for stmt in block. stmts {
490+ if map
491+ . attrs ( stmt. hir_id )
492+ . iter ( )
493+ . all ( |attr| !attr. path_matches ( attr_path) )
494+ {
495+ continue ;
496+ }
497+ let rustc_hir:: StmtKind :: Semi ( expr) = stmt. kind else {
498+ panic ! (
499+ "annotated path is expected to be a semi statement, but found: {:?}" ,
500+ stmt. kind
501+ ) ;
502+ } ;
503+ let rustc_hir:: ExprKind :: Path ( qpath) = expr. kind else {
504+ panic ! (
505+ "annotated path is expected to be a path expression, but found: {:?}" ,
506+ expr. kind
507+ ) ;
508+ } ;
509+ let rustc_hir:: QPath :: Resolved ( _, path) = qpath else {
510+ panic ! (
511+ "qpath is unexpectedly not resolved in annotated path: {:?}" ,
512+ qpath
513+ ) ;
514+ } ;
515+ let rustc_hir:: def:: Res :: Def ( _, def_id) = path. res else {
516+ panic ! (
517+ "annotated path is expected to refer to a def, but found: {:?}" ,
518+ path. res
519+ ) ;
520+ } ;
521+ return Some ( def_id) ;
522+ }
523+ None
524+ }
525+
475526 fn extract_require_annot < T > (
476527 & self ,
477- def_id : DefId ,
528+ local_def_id : LocalDefId ,
478529 resolver : T ,
479530 self_type_name : Option < String > ,
480531 ) -> Option < AnnotFormula < T :: Output > >
481532 where
482- T : Resolver ,
533+ T : Resolver < Output = rty :: FunctionParamIdx > ,
483534 {
484535 let mut require_annot = None ;
485536 let parser = AnnotParser :: new ( & resolver, self_type_name) ;
486537 for attrs in self
487538 . tcx
488- . get_attrs_by_path ( def_id , & analyze:: annot:: requires_path ( ) )
539+ . get_attrs_by_path ( local_def_id . to_def_id ( ) , & analyze:: annot:: requires_path ( ) )
489540 {
490541 if require_annot. is_some ( ) {
491542 unimplemented ! ( ) ;
@@ -494,23 +545,47 @@ impl<'tcx> Analyzer<'tcx> {
494545 let require = parser. parse_formula ( ts) . unwrap ( ) ;
495546 require_annot = Some ( require) ;
496547 }
548+
549+ if let Some ( formula_def_id) =
550+ self . extract_path_with_attr ( local_def_id, & analyze:: annot:: requires_path ( ) )
551+ {
552+ if require_annot. is_some ( ) {
553+ unimplemented ! ( ) ;
554+ }
555+ let Some ( formula_fn) = self . formula_fns . get ( & formula_def_id) else {
556+ panic ! (
557+ "require annotation {:?} is not a formula function" ,
558+ formula_def_id
559+ ) ;
560+ } ;
561+ let Some ( annot) = formula_fn. to_require_annot ( self . fn_sig ( local_def_id. to_def_id ( ) ) )
562+ else {
563+ panic ! (
564+ "require annotation {:?} has incompatible signature with {:?}" ,
565+ formula_def_id, local_def_id
566+ ) ;
567+ } ;
568+ require_annot = Some ( annot) ;
569+ }
570+
497571 require_annot
498572 }
499573
500574 fn extract_ensure_annot < T > (
501575 & self ,
502- def_id : DefId ,
576+ local_def_id : LocalDefId ,
503577 resolver : T ,
504578 self_type_name : Option < String > ,
505579 ) -> Option < AnnotFormula < T :: Output > >
506580 where
507- T : Resolver ,
581+ T : Resolver < Output = rty :: RefinedTypeVar < rty :: FunctionParamIdx > > ,
508582 {
509583 let mut ensure_annot = None ;
584+
510585 let parser = AnnotParser :: new ( & resolver, self_type_name) ;
511586 for attrs in self
512587 . tcx
513- . get_attrs_by_path ( def_id , & analyze:: annot:: ensures_path ( ) )
588+ . get_attrs_by_path ( local_def_id . to_def_id ( ) , & analyze:: annot:: ensures_path ( ) )
514589 {
515590 if ensure_annot. is_some ( ) {
516591 unimplemented ! ( ) ;
@@ -519,6 +594,29 @@ impl<'tcx> Analyzer<'tcx> {
519594 let ensure = parser. parse_formula ( ts) . unwrap ( ) ;
520595 ensure_annot = Some ( ensure) ;
521596 }
597+
598+ if let Some ( formula_def_id) =
599+ self . extract_path_with_attr ( local_def_id, & analyze:: annot:: ensures_path ( ) )
600+ {
601+ if ensure_annot. is_some ( ) {
602+ unimplemented ! ( ) ;
603+ }
604+ let Some ( formula_fn) = self . formula_fns . get ( & formula_def_id) else {
605+ panic ! (
606+ "ensure annotation {:?} is not a formula function" ,
607+ formula_def_id
608+ ) ;
609+ } ;
610+ let Some ( annot) = formula_fn. to_ensure_annot ( self . fn_sig ( local_def_id. to_def_id ( ) ) )
611+ else {
612+ panic ! (
613+ "ensure annotation {:?} has incompatible signature with {:?}" ,
614+ formula_def_id, local_def_id
615+ ) ;
616+ } ;
617+ ensure_annot = Some ( annot) ;
618+ }
619+
522620 ensure_annot
523621 }
524622
0 commit comments