From: Rico Tzschichholz Date: Thu, 29 Nov 2018 17:44:28 +0000 (+0100) Subject: vala: Search in all interfaces for an implementation match and don't bail early X-Git-Tag: 0.43.4~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3da2f97f02d6dcc359765080bf2f894a0519806d;p=thirdparty%2Fvala.git vala: Search in all interfaces for an implementation match and don't bail early The first imcompatible method match doesn't mean there is no match for another interface. This might mean an implementation is missing which will be covered by the semantic check of the parent class. Fixes https://gitlab.gnome.org/GNOME/vala/issues/548 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 63e62bae7..f62e5f2c3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -552,6 +552,7 @@ TESTS = \ semantic/class-missing-implement-interface-method.test \ semantic/class-missing-implement-interface-property.test \ semantic/class-missing-implement-interfaces-methods.test \ + semantic/class-missing-implement-interfaces-methods2.test \ semantic/class-missing-implement-interfaces-methods3.test \ semantic/class-missing-implement-method.test \ semantic/class-missing-implement-property.test \ diff --git a/tests/semantic/class-missing-implement-interfaces-methods2.test b/tests/semantic/class-missing-implement-interfaces-methods2.test new file mode 100644 index 000000000..a419e682c --- /dev/null +++ b/tests/semantic/class-missing-implement-interfaces-methods2.test @@ -0,0 +1,18 @@ +Invalid Code + +interface IFoo : Object { + public abstract string foo (); +} + +interface IBar : Object { + public abstract int foo (); +} + +class Manam : Object, IFoo, IBar { + public int foo () { + return 23; + } +} + +void main() { +} diff --git a/vala/valamethod.vala b/vala/valamethod.vala index 294f7b397..bd203ab36 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -631,6 +631,11 @@ public class Vala.Method : Subroutine, Callable { } private void find_base_interface_method (Class cl) { + Method? base_match = null; + + string? invalid_error = null; + Method? invalid_base_match = null; + foreach (DataType type in cl.get_base_types ()) { if (type.data_type is Interface) { if (base_interface_type != null && base_interface_type.data_type != type.data_type) { @@ -661,20 +666,28 @@ public class Vala.Method : Subroutine, Callable { string invalid_match = null; if (!compatible (base_method, out invalid_match)) { - error = true; - var base_method_type = new MethodType (base_method); - Report.error (source_reference, "overriding method `%s' is incompatible with base method `%s': %s.".printf (get_full_name (), base_method_type.to_prototype_string (), invalid_match)); - return; + invalid_error = invalid_match; + invalid_base_match = base_method; + } else { + base_match = base_method; + break; } - - _base_interface_method = base_method; - copy_attribute_double (base_method, "CCode", "instance_pos"); - return; } } } } + if (base_match != null) { + _base_interface_method = base_match; + copy_attribute_double (base_match, "CCode", "instance_pos"); + return; + } else if (invalid_base_match != null) { + error = true; + var base_method_type = new MethodType (invalid_base_match); + Report.error (source_reference, "overriding method `%s' is incompatible with base method `%s': %s.".printf (get_full_name (), base_method_type.to_prototype_string (), invalid_error)); + return; + } + if (base_interface_type != null) { Report.error (source_reference, "`%s': no suitable interface method found to implement".printf (get_full_name ())); }