diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 356e655b3cb8..746fe3ba29da 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -599,7 +599,7 @@ def update_project_options(self, project_options: 'MutableKeyedOptionDictType', oldval = self.optstore.get_value_object(key) if type(oldval) is not type(value): self.optstore.set_value(key, value.value) - elif oldval.printable_choices() != value.printable_choices(): + elif options.choices_are_different(oldval, value): # If the choices have changed, use the new value, but attempt # to keep the old options. If they are not valid keep the new # defaults but warn. diff --git a/mesonbuild/options.py b/mesonbuild/options.py index ed01bc12e933..3de001b1dca6 100644 --- a/mesonbuild/options.py +++ b/mesonbuild/options.py @@ -483,7 +483,31 @@ def is_auto(self) -> bool: return self.value == 'auto' -@dataclasses.dataclass(init=False) +_U = T.TypeVar('_U', bound=UserOption) + + +def choices_are_different(a: _U, b: _U) -> bool: + """Are the choices between two options the same? + + :param a: A UserOption[T] + :param b: A second UserOption[T] + :return: True if the choices have changed, otherwise False + """ + if isinstance(a, EnumeratedUserOption): + # We expect `a` and `b` to be of the same type, but can't really annotate it that way. + assert isinstance(b, EnumeratedUserOption), 'for mypy' + return a.choices != b.choices + elif isinstance(a, UserArrayOption): + # We expect `a` and `b` to be of the same type, but can't really annotate it that way. + assert isinstance(b, UserArrayOption), 'for mypy' + return a.choices != b.choices + elif isinstance(a, _UserIntegerBase): + assert isinstance(b, _UserIntegerBase), 'for mypy' + return a.max_value != b.max_value or a.min_value != b.min_value + + return False + + class UserStdOption(UserComboOption): ''' UserOption specific to c_std and cpp_std options. User can set a list of