diff --git a/vyper/builtins/_signatures.py b/vyper/builtins/_signatures.py index dd428575b2..616dd39a07 100644 --- a/vyper/builtins/_signatures.py +++ b/vyper/builtins/_signatures.py @@ -6,7 +6,7 @@ from vyper.codegen.expr import Expr from vyper.codegen.ir_node import IRnode from vyper.exceptions import CompilerPanic, TypeMismatch, UnfoldableNode, VyperException -from vyper.semantics.analysis.base import VariableConstancy +from vyper.semantics.analysis.base import Modifiability from vyper.semantics.analysis.utils import ( check_variable_constancy, get_exact_type_from_node, @@ -112,7 +112,7 @@ def _validate_arg_types(self, node: vy_ast.Call) -> None: for kwarg in node.keywords: kwarg_settings = self._kwargs[kwarg.arg] if kwarg_settings.require_literal and not check_variable_constancy( - kwarg.value, VariableConstancy.RUNTIME_CONSTANT + kwarg.value, Modifiability.IMMUTABLE ): raise TypeMismatch("Value must be literal or environment variable", kwarg.value) self._validate_single(kwarg.value, kwarg_settings.typ) diff --git a/vyper/semantics/analysis/base.py b/vyper/semantics/analysis/base.py index 1d293dc149..a34552adb7 100644 --- a/vyper/semantics/analysis/base.py +++ b/vyper/semantics/analysis/base.py @@ -97,10 +97,12 @@ def from_abi(cls, abi_dict: Dict) -> "StateMutability": # specifying a state mutability modifier at all. Do the same here. -class VariableConstancy(enum.IntEnum): - MUTABLE = enum.auto() - RUNTIME_CONSTANT = enum.auto() - COMPILE_TIME_CONSTANT = enum.auto() +class Modifiability(enum.IntEnum): + MODIFIABLE = enum.auto() + IMMUTABLE = enum.auto() + NOT_MODIFIABLE = enum.auto() + CONSTANT_IN_CURRENT_TX = enum.auto() + ALWAYS_CONSTANT = enum.auto() class DataPosition: @@ -198,7 +200,7 @@ class VarInfo: typ: VyperType location: DataLocation = DataLocation.UNSET - constancy: VariableConstancy = VariableConstancy.MUTABLE + constancy: Modifiability = Modifiability.MODIFIABLE is_public: bool = False is_immutable: bool = False is_transient: bool = False @@ -231,7 +233,7 @@ class ExprInfo: typ: VyperType var_info: Optional[VarInfo] = None location: DataLocation = DataLocation.UNSET - constancy: VariableConstancy = VariableConstancy.MUTABLE + constancy: Modifiability = Modifiability.MODIFIABLE is_immutable: bool = False def __post_init__(self): @@ -283,7 +285,7 @@ def validate_modification(self, node: vy_ast.VyperNode, mutability: StateMutabil if self.location == DataLocation.CALLDATA: raise ImmutableViolation("Cannot write to calldata", node) - if self.constancy == VariableConstancy.COMPILE_TIME_CONSTANT: + if self.constancy == Modifiability.ALWAYS_CONSTANT: raise ImmutableViolation("Constant value cannot be written to", node) if self.is_immutable: if node.get_ancestor(vy_ast.FunctionDef).get("name") != "__init__": diff --git a/vyper/semantics/analysis/local.py b/vyper/semantics/analysis/local.py index 38a0ef8255..143ab41fd4 100644 --- a/vyper/semantics/analysis/local.py +++ b/vyper/semantics/analysis/local.py @@ -19,7 +19,7 @@ VariableDeclarationException, VyperException, ) -from vyper.semantics.analysis.base import VariableConstancy, VarInfo +from vyper.semantics.analysis.base import Modifiability, VarInfo from vyper.semantics.analysis.common import VyperNodeVisitorBase from vyper.semantics.analysis.utils import ( get_common_types, @@ -192,9 +192,9 @@ def __init__( def analyze(self): # allow internal function params to be mutable location, is_immutable, constancy = ( - (DataLocation.MEMORY, False, VariableConstancy.MUTABLE) + (DataLocation.MEMORY, False, Modifiability.MODIFIABLE) if self.func.is_internal - else (DataLocation.CALLDATA, True, VariableConstancy.RUNTIME_CONSTANT) + else (DataLocation.CALLDATA, True, Modifiability.NOT_MODIFIABLE) ) for arg in self.func.arguments: self.namespace[arg.name] = VarInfo( @@ -494,7 +494,7 @@ def visit_For(self, node): with self.namespace.enter_scope(): self.namespace[iter_name] = VarInfo( - possible_target_type, constancy=VariableConstancy.COMPILE_TIME_CONSTANT + possible_target_type, constancy=Modifiability.ALWAYS_CONSTANT ) try: diff --git a/vyper/semantics/analysis/module.py b/vyper/semantics/analysis/module.py index 0b57d4045f..05cdf7dac6 100644 --- a/vyper/semantics/analysis/module.py +++ b/vyper/semantics/analysis/module.py @@ -20,7 +20,7 @@ VariableDeclarationException, VyperException, ) -from vyper.semantics.analysis.base import ImportInfo, ModuleInfo, VariableConstancy, VarInfo +from vyper.semantics.analysis.base import ImportInfo, Modifiability, ModuleInfo, VarInfo from vyper.semantics.analysis.common import VyperNodeVisitorBase from vyper.semantics.analysis.import_graph import ImportGraph from vyper.semantics.analysis.local import ExprVisitor, validate_functions @@ -263,11 +263,11 @@ def visit_VariableDecl(self, node): ) constancy = ( - VariableConstancy.RUNTIME_CONSTANT + Modifiability.IMMUTABLE if node.is_immutable - else VariableConstancy.COMPILE_TIME_CONSTANT + else Modifiability.ALWAYS_CONSTANT if node.is_constant - else VariableConstancy.MUTABLE + else Modifiability.MODIFIABLE ) type_ = type_from_annotation(node.annotation, data_loc) @@ -317,7 +317,7 @@ def _validate_self_namespace(): ExprVisitor().visit(node.value, type_) - if not check_variable_constancy(node.value, VariableConstancy.COMPILE_TIME_CONSTANT): + if not check_variable_constancy(node.value, Modifiability.ALWAYS_CONSTANT): raise StateAccessViolation("Value must be a literal", node.value) validate_expected_type(node.value, type_) diff --git a/vyper/semantics/analysis/utils.py b/vyper/semantics/analysis/utils.py index d5555f3888..6cb6fb3141 100644 --- a/vyper/semantics/analysis/utils.py +++ b/vyper/semantics/analysis/utils.py @@ -17,7 +17,7 @@ ZeroDivisionException, ) from vyper.semantics import types -from vyper.semantics.analysis.base import ExprInfo, ModuleInfo, VariableConstancy, VarInfo +from vyper.semantics.analysis.base import ExprInfo, Modifiability, ModuleInfo, VarInfo from vyper.semantics.analysis.levenshtein_utils import get_levenshtein_error_suggestions from vyper.semantics.namespace import get_namespace from vyper.semantics.types.base import TYPE_T, VyperType @@ -201,7 +201,7 @@ def _raise_invalid_reference(name, node): if isinstance(s, (VyperType, TYPE_T)): # ex. foo.bar(). bar() is a ContractFunctionT return [s] - if is_self_reference and s.constancy >= VariableConstancy.RUNTIME_CONSTANT: + if is_self_reference and s.constancy >= Modifiability.IMMUTABLE: _raise_invalid_reference(name, node) # general case. s is a VarInfo, e.g. self.foo return [s.typ] @@ -639,7 +639,7 @@ def _check_literal(node: vy_ast.VyperNode) -> bool: return False -def check_variable_constancy(node: vy_ast.VyperNode, constancy: VariableConstancy) -> bool: +def check_variable_constancy(node: vy_ast.VyperNode, constancy: Modifiability) -> bool: """ Check if the given node is a literal or constant value. """ diff --git a/vyper/semantics/environment.py b/vyper/semantics/environment.py index 937237ad0b..fb89d6dab7 100644 --- a/vyper/semantics/environment.py +++ b/vyper/semantics/environment.py @@ -1,6 +1,6 @@ from typing import Dict -from vyper.semantics.analysis.base import VariableConstancy, VarInfo +from vyper.semantics.analysis.base import Modifiability, VarInfo from vyper.semantics.types import AddressT, BytesT, VyperType from vyper.semantics.types.shortcuts import BYTES32_T, UINT256_T @@ -52,7 +52,7 @@ def get_constant_vars() -> Dict: """ result = {} for k, v in CONSTANT_ENVIRONMENT_VARS.items(): - result[k] = VarInfo(v, constancy=VariableConstancy.RUNTIME_CONSTANT) + result[k] = VarInfo(v, constancy=Modifiability.CONSTANT_IN_CURRENT_TX) return result diff --git a/vyper/semantics/types/function.py b/vyper/semantics/types/function.py index 8ca12bc749..e3001c6c91 100644 --- a/vyper/semantics/types/function.py +++ b/vyper/semantics/types/function.py @@ -18,9 +18,9 @@ ) from vyper.semantics.analysis.base import ( FunctionVisibility, + Modifiability, StateMutability, StorageSlot, - VariableConstancy, ) from vyper.semantics.analysis.utils import ( check_variable_constancy, @@ -702,7 +702,7 @@ def _parse_args( positional_args.append(PositionalArg(argname, type_, ast_source=arg)) else: value = funcdef.args.defaults[i - n_positional_args] - if not check_variable_constancy(value, VariableConstancy.RUNTIME_CONSTANT): + if not check_variable_constancy(value, Modifiability.IMMUTABLE): raise StateAccessViolation("Value must be literal or environment variable", value) validate_expected_type(value, type_) keyword_args.append(KeywordArg(argname, type_, value, ast_source=arg))