@@ -330,7 +330,23 @@ def from_vyi(cls, funcdef: vy_ast.FunctionDef) -> "ContractFunctionT":
330
330
function_visibility , state_mutability , nonreentrant = _parse_decorators (funcdef )
331
331
332
332
if nonreentrant :
333
- raise FunctionDeclarationException ("`@nonreentrant` not allowed in interfaces" , funcdef )
333
+ # TODO: refactor so parse_decorators returns the AST location
334
+ decorator = next (d for d in funcdef .decorator_list if d .id == "nonreentrant" )
335
+ raise FunctionDeclarationException (
336
+ "`@nonreentrant` not allowed in interfaces" , decorator
337
+ )
338
+
339
+ # it's redundant to specify visibility in vyi - always should be external
340
+ if function_visibility is None :
341
+ function_visibility = FunctionVisibility .EXTERNAL
342
+
343
+ if function_visibility != FunctionVisibility .EXTERNAL :
344
+ nonexternal = next (
345
+ d for d in funcdef .decorator_list if d .id in FunctionVisibility .values ()
346
+ )
347
+ raise FunctionDeclarationException (
348
+ "Interface functions can only be marked as `@external`" , nonexternal
349
+ )
334
350
335
351
if funcdef .name == "__init__" :
336
352
raise FunctionDeclarationException ("Constructors cannot appear in interfaces" , funcdef )
@@ -381,6 +397,10 @@ def from_FunctionDef(cls, funcdef: vy_ast.FunctionDef) -> "ContractFunctionT":
381
397
"""
382
398
function_visibility , state_mutability , nonreentrant = _parse_decorators (funcdef )
383
399
400
+ # it's redundant to specify internal visibility - it's implied by not being external
401
+ if function_visibility is None :
402
+ function_visibility = FunctionVisibility .INTERNAL
403
+
384
404
positional_args , keyword_args = _parse_args (funcdef )
385
405
386
406
return_type = _parse_return_type (funcdef )
@@ -419,6 +439,10 @@ def from_FunctionDef(cls, funcdef: vy_ast.FunctionDef) -> "ContractFunctionT":
419
439
raise FunctionDeclarationException (
420
440
"Constructor may not use default arguments" , funcdef .args .defaults [0 ]
421
441
)
442
+ if nonreentrant :
443
+ decorator = next (d for d in funcdef .decorator_list if d .id == "nonreentrant" )
444
+ msg = "`@nonreentrant` decorator disallowed on `__init__`"
445
+ raise FunctionDeclarationException (msg , decorator )
422
446
423
447
return cls (
424
448
funcdef .name ,
@@ -495,6 +519,8 @@ def implements(self, other: "ContractFunctionT") -> bool:
495
519
if not self .is_external : # pragma: nocover
496
520
raise CompilerPanic ("unreachable!" )
497
521
522
+ assert self .visibility == other .visibility
523
+
498
524
arguments , return_type = self ._iface_sig
499
525
other_arguments , other_return_type = other ._iface_sig
500
526
@@ -700,7 +726,7 @@ def _parse_return_type(funcdef: vy_ast.FunctionDef) -> Optional[VyperType]:
700
726
701
727
def _parse_decorators (
702
728
funcdef : vy_ast .FunctionDef ,
703
- ) -> tuple [FunctionVisibility , StateMutability , bool ]:
729
+ ) -> tuple [Optional [ FunctionVisibility ] , StateMutability , bool ]:
704
730
function_visibility = None
705
731
state_mutability = None
706
732
nonreentrant_node = None
@@ -719,10 +745,6 @@ def _parse_decorators(
719
745
if nonreentrant_node is not None :
720
746
raise StructureException ("nonreentrant decorator is already set" , nonreentrant_node )
721
747
722
- if funcdef .name == "__init__" :
723
- msg = "`@nonreentrant` decorator disallowed on `__init__`"
724
- raise FunctionDeclarationException (msg , decorator )
725
-
726
748
nonreentrant_node = decorator
727
749
728
750
elif isinstance (decorator , vy_ast .Name ):
@@ -733,6 +755,7 @@ def _parse_decorators(
733
755
decorator ,
734
756
hint = "only one visibility decorator is allowed per function" ,
735
757
)
758
+
736
759
function_visibility = FunctionVisibility (decorator .id )
737
760
738
761
elif StateMutability .is_valid_value (decorator .id ):
@@ -755,9 +778,6 @@ def _parse_decorators(
755
778
else :
756
779
raise StructureException ("Bad decorator syntax" , decorator )
757
780
758
- if function_visibility is None :
759
- function_visibility = FunctionVisibility .INTERNAL
760
-
761
781
if state_mutability is None :
762
782
# default to nonpayable
763
783
state_mutability = StateMutability .NONPAYABLE
0 commit comments