From a281e4b8d527363f260dc660c38d1498019246e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=BD=D0=B4=D0=B0=D1=80=D0=B5=D0=B2=20=D0=98?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD?= Date: Sun, 9 Sep 2018 19:10:15 +0200 Subject: [PATCH] fix #1063 --- TestSuite/CompilationSamples/GraphWPFBase.pas | 5 +- TestSuite/errors/err0263.pas | 12 ++++ TestSuite/errors/err0264.pas | 12 ++++ TestSuite/errors/err0265.pas | 12 ++++ TestSuite/errors/err0266.pas | 13 ++++ TestSuite/where4.pas | 13 ++++ TestSuite/where5.pas | 12 ++++ TestSuite/where6.pas | 13 ++++ TestSuite/where7.pas | 13 ++++ .../TreeConversion/syntax_tree_visitor.cs | 59 ++++++++++++++++++- bin/Lng/Eng/SemanticErrors_ib.dat | 1 + bin/Lng/Rus/SemanticErrors_ib.dat | 1 + bin/Lng/Ukr/SemanticErrors_ib.dat | 1 + 13 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 TestSuite/errors/err0263.pas create mode 100644 TestSuite/errors/err0264.pas create mode 100644 TestSuite/errors/err0265.pas create mode 100644 TestSuite/errors/err0266.pas create mode 100644 TestSuite/where4.pas create mode 100644 TestSuite/where5.pas create mode 100644 TestSuite/where6.pas create mode 100644 TestSuite/where7.pas diff --git a/TestSuite/CompilationSamples/GraphWPFBase.pas b/TestSuite/CompilationSamples/GraphWPFBase.pas index f4b09bba9..9c8ee8ffa 100644 --- a/TestSuite/CompilationSamples/GraphWPFBase.pas +++ b/TestSuite/CompilationSamples/GraphWPFBase.pas @@ -216,12 +216,11 @@ function operator implicit(Self: array of (real, real)): array of Point; extensi Self.Select(t->new Point(t[0],t[1])).ToArray; function operator implicit(Self: array of (integer, integer)): array of Point; extensionmethod := Self.Select(t->new Point(t[0],t[1])).ToArray; - -///---- Helpers + procedure SetLeft(Self: UIElement; l: integer); extensionmethod := Canvas.SetLeft(Self,l); procedure SetTop(Self: UIElement; t: integer); extensionmethod := Canvas.SetTop(Self,t); - + var __initialized: boolean; procedure __InitModule; diff --git a/TestSuite/errors/err0263.pas b/TestSuite/errors/err0263.pas new file mode 100644 index 000000000..dbf822a2f --- /dev/null +++ b/TestSuite/errors/err0263.pas @@ -0,0 +1,12 @@ +type + t0=record end; + + t1=class + where T: record; + end; + + t2=class(t1) end; + +begin + //var a := new t2;//не обязательно чтоб вызвать ошибку +end. \ No newline at end of file diff --git a/TestSuite/errors/err0264.pas b/TestSuite/errors/err0264.pas new file mode 100644 index 000000000..74457a2fc --- /dev/null +++ b/TestSuite/errors/err0264.pas @@ -0,0 +1,12 @@ +type + t0=record end; + + t1=class + where T: record; + end; + + t2=class(t1) where T: class; end; + +begin + //var a := new t2;//не обязательно чтоб вызвать ошибку +end. \ No newline at end of file diff --git a/TestSuite/errors/err0265.pas b/TestSuite/errors/err0265.pas new file mode 100644 index 000000000..64c5efbf2 --- /dev/null +++ b/TestSuite/errors/err0265.pas @@ -0,0 +1,12 @@ +type + t0=record end; + + t1=class + where T: t0; + end; + + t2=class(t1) where T: constructor; end; + +begin + //var a := new t2;//не обязательно чтоб вызвать ошибку +end. \ No newline at end of file diff --git a/TestSuite/errors/err0266.pas b/TestSuite/errors/err0266.pas new file mode 100644 index 000000000..1e9c89136 --- /dev/null +++ b/TestSuite/errors/err0266.pas @@ -0,0 +1,13 @@ +type + t0=record end; + + t1=class + where T1: t0; + a: T1; + end; + + t2=class(t1) where T: record; end; + +begin + var a := new t2; +end. \ No newline at end of file diff --git a/TestSuite/where4.pas b/TestSuite/where4.pas new file mode 100644 index 000000000..b5d19c586 --- /dev/null +++ b/TestSuite/where4.pas @@ -0,0 +1,13 @@ +type + t0=record + end; + + t1=class + where T: record; + end; + + t2=class(t1) where T: record; end; + +begin + var a := new t2; +end. \ No newline at end of file diff --git a/TestSuite/where5.pas b/TestSuite/where5.pas new file mode 100644 index 000000000..2253b72f9 --- /dev/null +++ b/TestSuite/where5.pas @@ -0,0 +1,12 @@ +type + t0=record end; + + t1=class + where T1: record; + end; + + t2=class(t1) where T: record; end; + +begin + var a := new t2; +end. \ No newline at end of file diff --git a/TestSuite/where6.pas b/TestSuite/where6.pas new file mode 100644 index 000000000..87651f549 --- /dev/null +++ b/TestSuite/where6.pas @@ -0,0 +1,13 @@ +type + t0=record end; + + t1=class + where T1: record; + a: T1; + end; + + t2=class(Dictionary,T>) where T: record; end; + +begin + var a := new t2; +end. \ No newline at end of file diff --git a/TestSuite/where7.pas b/TestSuite/where7.pas new file mode 100644 index 000000000..3fa20cba2 --- /dev/null +++ b/TestSuite/where7.pas @@ -0,0 +1,13 @@ +type + t0=record end; + + t1=class + where T1: record; + a: T1; + end; + + t2=class(t1) where T: t0; end; + +begin + var a := new t2; +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 6dbeb832e..e962166de 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -3620,6 +3620,7 @@ namespace PascalABCCompiler.TreeConverter { context.converted_type.SetBaseType(SemanticRules.ClassBaseType); } + context.converted_type.is_class = true; if (_class_definition.body == null && (_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0)) @@ -11410,11 +11411,13 @@ namespace PascalABCCompiler.TreeConverter } if (predefined_generic && cl_def.where_section != null && cl_def.where_section.defs.Count > 0) AddError(get_location(cl_def.where_section), "WHERE_SECTION_NOT_ALLOWED"); + visit_where_list(cl_def.where_section); + CheckWaitedRefTypes(ctn); is_direct_type_decl = true; hard_node_test_and_visit(_type_declaration.type_def); - + check_where_from_base_class(ctn); // frninja 28/04/16 - режем мусорные методы хелперы yield { var toRemove = ctn.methods.Where(m => m.is_yield_helper).ToArray(); @@ -11887,6 +11890,60 @@ namespace PascalABCCompiler.TreeConverter } } + private void check_where_from_base_class(common_type_node ctn) + { + if (ctn.base_type != null && ctn.base_type.is_generic_type_instance && ctn.is_generic_type_definition) + { + common_type_node bctn = ctn.base_type.original_generic as common_type_node; + compiled_type_node bctn2 = ctn.base_type.original_generic as compiled_type_node; + Dictionary where_cache = new Dictionary(); + foreach (SemanticTree.ICommonTypeNode t in ctn.generic_params) + { + int ind = ctn.base_type.instance_params.IndexOf(t as type_node); + if (ind != -1) + { + if (bctn != null) + where_cache.Add(bctn.generic_params[ind].name, t); + else + where_cache.Add(bctn2.generic_params[ind].name, t); + } + + } + if (bctn != null && bctn.generic_params != null) + { + foreach (SemanticTree.ICommonTypeNode t in bctn.generic_params) + { + SemanticTree.ICommonTypeNode thist = null; + where_cache.TryGetValue(t.name, out thist); + if (thist == null) + continue; + if (t.is_class || t.is_value_type || t.methods.Length > 0 || t.base_type != SystemLibrary.SystemLibrary.object_type) + { + if (thist.is_class != t.is_class || thist.is_value_type != t.is_value_type && !(t.is_value_type && thist.base_type.is_value_type) + || thist.methods.Length != t.methods.Length || + t.base_type != thist.base_type && !type_table.is_derived(t.base_type as type_node, thist.base_type as type_node)) + AddError(ctn.loc, "WHERE_SPECIFIER_MISMATCH"); + } + } + } + else if (bctn2 != null && bctn2.generic_params != null) + { + foreach (compiled_type_node t in bctn2.generic_params) + { + SemanticTree.ICommonTypeNode thist = null; + where_cache.TryGetValue(t.name, out thist); + if (thist == null) + continue; + if (t.is_value_type || t.base_type != SystemLibrary.SystemLibrary.object_type) + { + if (thist.is_value_type != t.is_value_type && !(t.is_value_type && thist.base_type.is_value_type) || thist.base_type != t.base_type) + AddError(ctn.loc, "WHERE_SPECIFIER_MISMATCH"); + } + } + } + } + } + private void visit_where_list(SyntaxTree.where_definition_list where_list) { if (where_list == null) diff --git a/bin/Lng/Eng/SemanticErrors_ib.dat b/bin/Lng/Eng/SemanticErrors_ib.dat index 778605fd6..35d0a6957 100644 --- a/bin/Lng/Eng/SemanticErrors_ib.dat +++ b/bin/Lng/Eng/SemanticErrors_ib.dat @@ -144,6 +144,7 @@ GENERIC_RECORDS_CANNOT_HAVE_EXPLICIT_LAYOUT=Generic-records can not have attribu ATTRIBUTE_CANNOT_BE_GENERIC=Attributes cannot be generic EXTERNAL_METHOD_CANNOT_BE_DECLARED_IN_GENERIC_TYPE=external-methods can not be declared in generic type EXTERNAL_METHOD_CANNOT_BE_GENERIC=external-methods can not be generic +WHERE_SPECIFIER_MISMATCH=where specifier contradicts with where specifier of base class %PREFIX%=COMPILATIONERROR_ UNIT_MODULE_EXPECTED_LIBRARY_FOUND=Unit expected, library found ASSEMBLY_{0}_READING_ERROR=Error by reading assembly '{0}' diff --git a/bin/Lng/Rus/SemanticErrors_ib.dat b/bin/Lng/Rus/SemanticErrors_ib.dat index fd0230fbf..b6ab65ab2 100644 --- a/bin/Lng/Rus/SemanticErrors_ib.dat +++ b/bin/Lng/Rus/SemanticErrors_ib.dat @@ -139,6 +139,7 @@ GENERIC_RECORDS_CANNOT_HAVE_EXPLICIT_LAYOUT=Генерик-записи не м ATTRIBUTE_CANNOT_BE_GENERIC=Атрибуты не могут быть генерик-классами EXTERNAL_METHOD_CANNOT_BE_DECLARED_IN_GENERIC_TYPE=external-методы нельзя описывать в генерик-классах EXTERNAL_METHOD_CANNOT_BE_GENERIC=external-методы не могут быть генериками +WHERE_SPECIFIER_MISMATCH=Несоответствие спецификатора whеre спецификатору where базового классе​ %PREFIX%=COMPILATIONERROR_ UNIT_MODULE_EXPECTED_LIBRARY_FOUND=Ожидался модуль, а встречена библиотека ASSEMBLY_{0}_READING_ERROR=Ошибка при чтении сборки '{0}' diff --git a/bin/Lng/Ukr/SemanticErrors_ib.dat b/bin/Lng/Ukr/SemanticErrors_ib.dat index 6f03d9f0a..83167652c 100644 --- a/bin/Lng/Ukr/SemanticErrors_ib.dat +++ b/bin/Lng/Ukr/SemanticErrors_ib.dat @@ -137,6 +137,7 @@ GENERIC_RECORDS_CANNOT_HAVE_EXPLICIT_LAYOUT=Генерик-записи не м ATTRIBUTE_CANNOT_BE_GENERIC=Атрибуты не могут быть генерик-классами EXTERNAL_METHOD_CANNOT_BE_DECLARED_IN_GENERIC_TYPE=external-методы нельзя описывать в генерик-классах EXTERNAL_METHOD_CANNOT_BE_GENERIC=external-методы не могут быть генериками +WHERE_SPECIFIER_MISMATCH=Несоответствие спецификатора whеre спецификатору where базового классе​ %PREFIX%=COMPILATIONERROR_ UNIT_MODULE_EXPECTED_LIBRARY_FOUND=Очікувався модуль, а зустріли бібліотеку ASSEMBLY_{0}_READING_ERROR=Помилка при читанні збірки '{0}'