From 7b5c4f538cc1a1d1bf02b309f1e6286927901d87 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Sun, 30 Jan 2022 18:07:23 +0100 Subject: [PATCH] vala: Improve check of generic type references in static contexts Fixes https://gitlab.gnome.org/GNOME/vala/issues/1284 --- tests/Makefile.am | 4 +++ ...od-parameter-unknown-type-parameter-2.test | 9 +++++ ...thod-parameter-unknown-type-parameter.test | 9 +++++ ...ethod-return-unknown-type-parameter-2.test | 10 ++++++ .../method-return-unknown-type-parameter.test | 10 ++++++ vala/valamethod.vala | 34 +++++++++++++++++++ 6 files changed, 76 insertions(+) create mode 100644 tests/generics/method-parameter-unknown-type-parameter-2.test create mode 100644 tests/generics/method-parameter-unknown-type-parameter.test create mode 100644 tests/generics/method-return-unknown-type-parameter-2.test create mode 100644 tests/generics/method-return-unknown-type-parameter.test diff --git a/tests/Makefile.am b/tests/Makefile.am index cf9bd1e93..a502b3494 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -765,6 +765,10 @@ TESTS = \ generics/parameter-invalid-initializer.test \ generics/parameter-sizeof-initializer.vala \ generics/member-dup-destroy.vala \ + generics/method-parameter-unknown-type-parameter.test \ + generics/method-parameter-unknown-type-parameter-2.test \ + generics/method-return-unknown-type-parameter.test \ + generics/method-return-unknown-type-parameter-2.test \ generics/null-type.vala \ generics/property-gobject-set.vala \ generics/property-int-cast.vala \ diff --git a/tests/generics/method-parameter-unknown-type-parameter-2.test b/tests/generics/method-parameter-unknown-type-parameter-2.test new file mode 100644 index 000000000..afbd77100 --- /dev/null +++ b/tests/generics/method-parameter-unknown-type-parameter-2.test @@ -0,0 +1,9 @@ +Invalid Code + +class Foo { + static void bar (Foo g) { + } +} + +void main () { +} diff --git a/tests/generics/method-parameter-unknown-type-parameter.test b/tests/generics/method-parameter-unknown-type-parameter.test new file mode 100644 index 000000000..f40ae8096 --- /dev/null +++ b/tests/generics/method-parameter-unknown-type-parameter.test @@ -0,0 +1,9 @@ +Invalid Code + +class Foo { + static void bar (G g) { + } +} + +void main () { +} diff --git a/tests/generics/method-return-unknown-type-parameter-2.test b/tests/generics/method-return-unknown-type-parameter-2.test new file mode 100644 index 000000000..aef59eda8 --- /dev/null +++ b/tests/generics/method-return-unknown-type-parameter-2.test @@ -0,0 +1,10 @@ +Invalid Code + +class Foo { + static Foo bar () { + return null; + } +} + +void main () { +} diff --git a/tests/generics/method-return-unknown-type-parameter.test b/tests/generics/method-return-unknown-type-parameter.test new file mode 100644 index 000000000..f25d37183 --- /dev/null +++ b/tests/generics/method-return-unknown-type-parameter.test @@ -0,0 +1,10 @@ +Invalid Code + +class Foo { + static G bar () { + return null; + } +} + +void main () { +} diff --git a/vala/valamethod.vala b/vala/valamethod.vala index fc8491594..2794cd48e 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -890,6 +890,19 @@ public class Vala.Method : Subroutine, Callable { Report.error (source_reference, "[Print] methods must have exactly one parameter of type `string'"); } + // Collect generic type references + // TODO Can this be done in the SymbolResolver? + List referenced_generics = new ArrayList (); + var traverse = new TraverseVisitor (node => { + if (node is GenericType) { + referenced_generics.add ((GenericType) node); + return TraverseStatus.STOP; + } + return TraverseStatus.CONTINUE; + }); + + return_type.accept (traverse); + var optional_param = false; var params_array_param = false; var ellipsis_param = false; @@ -907,6 +920,9 @@ public class Vala.Method : Subroutine, Callable { Report.error (param.source_reference, "Variadic parameters are not supported for async methods"); return false; } + + param.accept_children (traverse); + // TODO: begin and end parameters must be checked separately for coroutines if (coroutine) { continue; @@ -955,6 +971,24 @@ public class Vala.Method : Subroutine, Callable { } } + // Check if referenced type-parameters are present + // TODO Can this be done in the SymbolResolver? + if (binding == MemberBinding.STATIC && parent_symbol is Class && !((Class) parent_symbol).is_compact) { + Iterator ref_generics_it = referenced_generics.iterator (); + while (ref_generics_it.next ()) { + var ref_generics = ref_generics_it.get (); + foreach (var type_param in get_type_parameters ()) { + if (ref_generics.type_parameter.name == type_param.name) { + ref_generics_it.remove (); + } + } + } + foreach (var type in referenced_generics) { + error = true; + Report.error (type.source_reference, "The type name `%s' could not be found", type.type_parameter.name); + } + } + if (coroutine) { // TODO: async methods with out-parameters before in-parameters are not supported bool requires_pointer = false; -- 2.47.2