]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Search in all interfaces for an implementation match and don't bail early
authorRico Tzschichholz <ricotz@ubuntu.com>
Thu, 29 Nov 2018 17:44:28 +0000 (18:44 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 19 Dec 2018 23:51:37 +0000 (00:51 +0100)
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

tests/Makefile.am
tests/semantic/class-missing-implement-interfaces-methods2.test [new file with mode: 0644]
vala/valamethod.vala

index 63e62bae7b3583f08fc8b40301b0ca83c6fd69eb..f62e5f2c30b74afcb2fc3344eec205ba64b4e2f1 100644 (file)
@@ -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 (file)
index 0000000..a419e68
--- /dev/null
@@ -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() {
+}
index 294f7b397a5a9a2dad2d2418178698f5381af85f..bd203ab363aa065e69e56f7e221de64c1a3b96c2 100644 (file)
@@ -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 ()));
                }