From a1867f04214d1cb42aadcb4824e7c02137634af4 Mon Sep 17 00:00:00 2001 From: Ivan Bondarev Date: Wed, 27 Dec 2023 12:42:58 +0100 Subject: [PATCH] fix #2829 --- TestSuite/where20.pas | 35 +++++++++++++++++++ .../TreeConversion/syntax_tree_visitor.cs | 31 +++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 TestSuite/where20.pas diff --git a/TestSuite/where20.pas b/TestSuite/where20.pas new file mode 100644 index 000000000..9999c6cb0 --- /dev/null +++ b/TestSuite/where20.pas @@ -0,0 +1,35 @@ +type + c1 = class + // Если объявить сначала "where T1" - тоже должно работать + where T2: IComparable; + where T1: T2; + + function f1(o: T1): integer; + begin + //Ошибка: Неизвестное имя 'CompareTo' + Result := o.CompareTo(o); + end; + + end; + + c2 = class + // Если объявить сначала "where T1" - тоже должно работать + where T2: IComparable; + where T1: T2; + + function f1(o: T1): integer; + begin + //Ошибка: Неизвестное имя 'CompareTo' + Result := o.CompareTo(o); + end; + + end; + + +begin + var a := new c1; + assert(a.f1('abc') = 0); + + var b := new c2; + assert(b.f1('abc') = 0); +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index f565d439b..e62da2762 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -4100,7 +4100,18 @@ namespace PascalABCCompiler.TreeConverter (ctn.Scope as SymbolTable.InterfaceScope).TopInterfaceScopeArray = interf_scopes.ToArray(); } - + + private void InitInterfaceScope(common_type_node ctn, List interfaces) + { + List interf_scopes = new List(interfaces.Count); + foreach (type_node tnode in interfaces) + { + interf_scopes.Add(tnode.Scope); + } + (ctn.Scope as SymbolTable.InterfaceScope).TopInterfaceScopeArray = + interf_scopes.ToArray(); + } + private void visit_function_realizations(SyntaxTree.declarations _decls) { foreach (SyntaxTree.declaration sd in _decls.defs) @@ -12969,6 +12980,16 @@ namespace PascalABCCompiler.TreeConverter ind++; } } + foreach (common_type_node ctn in used_types) + { + if (ctn.base_type != null && ctn.base_type.is_generic_parameter && ctn.base_type.ImplementingInterfaces != null && ctn.base_type.ImplementingInterfaces.Count > 0) + { + foreach (type_node tn in ctn.ImplementingInterfaces) + { + type_table.AddInterface(ctn, tn, null); + } + } + } context.EndSkipGenericInstanceChecking(); } @@ -13071,6 +13092,14 @@ namespace PascalABCCompiler.TreeConverter AddError(get_location(specificators[i]), "STATIC_CLASS_CAN_NOT_BE_USED_AS_PARENT_SPECIFICATOR"); check_cycle_inheritance(param, spec_type); param.SetBaseType(spec_type); + if (spec_type.is_generic_parameter && spec_type.ImplementingInterfaces.Count > 0) + { + foreach (type_node tn in spec_type.ImplementingInterfaces) + { + used_interfs.Add(tn, tn); + type_table.AddInterface(param, tn, get_location(specificators[i])); + } + } base_is_enum = spec_type == SystemLibrary.SystemLibrary.enum_base_type; // Чтобы в секции where override метода можно было указать class вместо конкретного типа // Иначе CLR падает с TypeLoadException