[vala/wip/issue548: 4/4] vala: Search in all interfaces for an implementation match and don't bail early



commit c2836ca459197f3d16d58da1bf68cd52dcd4f874
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Thu Nov 29 18:44:28 2018 +0100

    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

 tests/Makefile.am                                  |  1 +
 ...lass-missing-implement-interfaces-methods2.test | 18 ++++++++++++++
 vala/valamethod.vala                               | 29 ++++++++++++++++------
 3 files changed, 40 insertions(+), 8 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9fe2ea6bd..a269d528d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -540,6 +540,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 7ec91729d..7cb49297a 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -616,6 +616,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) {
@@ -646,20 +651,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 ()));
                }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]