fix #2067
This commit is contained in:
parent
41316f86d1
commit
ac3cb68835
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
|||
public const string Major = "3";
|
||||
public const string Minor = "6";
|
||||
public const string Build = "3";
|
||||
public const string Revision = "2500";
|
||||
public const string Revision = "2505";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%COREVERSION%=3
|
||||
%REVISION%=2500
|
||||
%MINOR%=6
|
||||
%REVISION%=2505
|
||||
%COREVERSION%=3
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.6.3.2500
|
||||
3.6.3.2505
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.6.3.2500'
|
||||
!define VERSION '3.6.3.2505'
|
||||
|
|
|
|||
21
TestSuite/2067.pas
Normal file
21
TestSuite/2067.pas
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// #2067
|
||||
type
|
||||
t1<T> = class
|
||||
procedure p1<T2>(f: Func<T,T2>); begin end;
|
||||
end;
|
||||
|
||||
procedure p1<T>;
|
||||
begin
|
||||
var o: t1<byte>;
|
||||
o.p1(b->''); // ok
|
||||
end;
|
||||
|
||||
procedure p2<TSource>;
|
||||
begin
|
||||
var o: t1<TSource>;
|
||||
o.p1((b: TSource): string ->'');
|
||||
end;
|
||||
|
||||
begin
|
||||
Assert(1=1)
|
||||
end.
|
||||
|
|
@ -113,7 +113,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
{
|
||||
// Выводим дженерики по self
|
||||
var nils = new List<int>();
|
||||
var deduceSucceded = generic_convertions.DeduceInstanceTypes(selfParameter.type, patternInstance.type, deducedGenerics, nils);
|
||||
var deduceSucceded = generic_convertions.DeduceInstanceTypes(selfParameter.type, patternInstance.type, deducedGenerics, nils, candidate.get_generic_params_list());
|
||||
if (!deduceSucceded || deducedGenerics.Contains(null))
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
[Serializable]
|
||||
public class expressions_list : extended_collection<expression_node>
|
||||
{
|
||||
public override string ToString() => string.Join(", ", this._elements);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
|
|
|||
|
|
@ -350,6 +350,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
return semantic_node_type.typed_expression;
|
||||
}
|
||||
}
|
||||
public override string ToString() => type.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -661,7 +661,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
public static bool TryToDeduceTypesInLambda(function_lambda_definition lambda_syntax_node,
|
||||
delegate_internal_interface formal_delegate,
|
||||
type_node[] deduced, List<int> nils,
|
||||
out Exception exception_on_body_compilation)
|
||||
out Exception exception_on_body_compilation, List<type_node> generic_params)
|
||||
{
|
||||
var there_are_undeduced_params = false;
|
||||
var param_counter = 0;
|
||||
|
|
@ -744,7 +744,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
}
|
||||
else if (!DeduceInstanceTypes(formal_delegate.return_value_type,
|
||||
(type_node)((lambda_inferred_type)lambda_syntax_node.return_type).real_type,
|
||||
deduced, nils)) //Выводим дженерик-параметры после того как вычислили тип возвращаемого значения
|
||||
deduced, nils, generic_params)) //Выводим дженерик-параметры после того как вычислили тип возвращаемого значения
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
|
@ -761,6 +761,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
int formal_count = formal.Count;
|
||||
int fact_count = fact.Count;
|
||||
int generic_type_params_count = func.generic_parameters_count;
|
||||
List<type_node> generic_params = func.get_generic_params_list();
|
||||
type_node[] deduced = new type_node[generic_type_params_count];
|
||||
List<int> nils = new List<int>();
|
||||
int count_params_to_see = fact_count;
|
||||
|
|
@ -811,11 +812,11 @@ namespace PascalABCCompiler.TreeRealization
|
|||
for (int i = formal_count - 1; i < fact_count; ++i)
|
||||
{
|
||||
//Проверяем фактические, попадающие под params...
|
||||
if (!DeduceInstanceTypes(last_params_type, fact[i].type, deduced, nils))
|
||||
if (!DeduceInstanceTypes(last_params_type, fact[i].type, deduced, nils, generic_params))
|
||||
{
|
||||
if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null)
|
||||
{
|
||||
if (DeduceInstanceTypes(last_params_type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils))
|
||||
if (DeduceInstanceTypes(last_params_type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils, generic_params))
|
||||
continue;
|
||||
}
|
||||
else if (alone)
|
||||
|
|
@ -840,7 +841,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
type_node tn = fact[i].type;
|
||||
if (tn.element_type != null && tn.type_special_kind != SemanticTree.type_special_kind.array_wrapper)
|
||||
tn = tn.element_type;
|
||||
if (!DeduceInstanceTypes(last_params_type, tn, deduced, nils))
|
||||
if (!DeduceInstanceTypes(last_params_type, tn, deduced, nils, generic_params))
|
||||
{
|
||||
if (alone)
|
||||
throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name);
|
||||
|
|
@ -869,14 +870,14 @@ namespace PascalABCCompiler.TreeRealization
|
|||
|
||||
for (int i = 0; i < count_params_to_see; ++i)
|
||||
{
|
||||
if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null && DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils))
|
||||
if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null && DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils, generic_params))
|
||||
continue;
|
||||
else
|
||||
if (!DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils))
|
||||
if (!DeduceInstanceTypes(formal[i].type, fact[i].type, deduced, nils, generic_params))
|
||||
{
|
||||
if (alone && fact[i].type is delegated_methods && (fact[i].type as delegated_methods).empty_param_method != null)
|
||||
{
|
||||
if (DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils))
|
||||
if (DeduceInstanceTypes(formal[i].type, (fact[i].type as delegated_methods).empty_param_method.type, deduced, nils, generic_params))
|
||||
continue;
|
||||
}
|
||||
if (alone)
|
||||
|
|
@ -916,7 +917,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
Exception on_lambda_body_compile_exception;
|
||||
// Исключение которое может возникнуть в результате компиляции тела лямбды если мы выберем неправильные типы параметров
|
||||
var b = TryToDeduceTypesInLambda(lambda_syntax_node, formal_delegate.Value, deduced, nils,
|
||||
out on_lambda_body_compile_exception);
|
||||
out on_lambda_body_compile_exception, generic_params);
|
||||
if (!b)
|
||||
// Пробуем вычислить типы из лямбд
|
||||
{
|
||||
|
|
@ -961,12 +962,12 @@ namespace PascalABCCompiler.TreeRealization
|
|||
type_node[] tmp_deduced = (type_node[])deduced.Clone();
|
||||
List<int> tmp_nils = new List<int>();
|
||||
tmp_nils.AddRange(nils);
|
||||
if (!DeduceInstanceTypes(formal[count_params_to_see].type, fact[count_params_to_see].type, deduced, nils))
|
||||
if (!DeduceInstanceTypes(formal[count_params_to_see].type, fact[count_params_to_see].type, deduced, nils, generic_params))
|
||||
{
|
||||
//Второй шанс. Учитываем слово params.
|
||||
deduced = tmp_deduced;
|
||||
nils = tmp_nils;
|
||||
if (!DeduceInstanceTypes(formal[count_params_to_see].type.element_type, fact[count_params_to_see].type, deduced, nils))
|
||||
if (!DeduceInstanceTypes(formal[count_params_to_see].type.element_type, fact[count_params_to_see].type, deduced, nils, generic_params))
|
||||
{
|
||||
if (alone)
|
||||
throw new SimpleSemanticError(loc, "GENERIC_FUNCTION_{0}_CAN_NOT_BE_CALLED_WITH_THESE_PARAMETERS", func.name);
|
||||
|
|
@ -1010,7 +1011,12 @@ namespace PascalABCCompiler.TreeRealization
|
|||
}
|
||||
|
||||
//Выведение типов
|
||||
public static bool DeduceInstanceTypes(type_node formal_type, type_node fact_type, type_node[] deduced, List<int> nils)
|
||||
//Странно, что для вывода ОДНОГО параметра передаётся весь массив deduced!!!
|
||||
//Непонятно, что делать, если мы сюда заходим, а он уже в том месте заполнен. Это ошибка или нет?
|
||||
//Может ли быть такое, что deduced[par_num] заполнен, а возвращается false?
|
||||
//Не может ли быть, что при рекурсивном вызове deduced начинает перезаполняться вовсе для других параметров?
|
||||
//Где потом используется deduced?
|
||||
public static bool DeduceInstanceTypes(type_node formal_type, type_node fact_type, type_node[] deduced, List<int> nils, List<type_node> generic_params)
|
||||
{
|
||||
if (fact_type == null)//issue #347
|
||||
return false;
|
||||
|
|
@ -1024,6 +1030,11 @@ namespace PascalABCCompiler.TreeRealization
|
|||
//Формальный тип - generic-параметр функции. Выводим.
|
||||
if (formal_type.generic_function_container != null)
|
||||
{
|
||||
// SSM 13/06/20 Если formal_type не входит в generic_params, то вернуть false
|
||||
if (!generic_params.Contains(formal_type)) // SSM 13.06.20 #2067
|
||||
{
|
||||
return true; // т.е. вывод закончен - нечего выводить
|
||||
}
|
||||
int par_num = formal_type.generic_param_index;
|
||||
if (fact_type.semantic_node_type == semantic_node_type.null_type_node)
|
||||
{
|
||||
|
|
@ -1065,7 +1076,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
{
|
||||
goto eq_cmp;
|
||||
}
|
||||
return DeduceInstanceTypes(formal_ref.pointed_type, fact_ref.pointed_type, deduced, nils);
|
||||
return DeduceInstanceTypes(formal_ref.pointed_type, fact_ref.pointed_type, deduced, nils, generic_params);
|
||||
}
|
||||
//безразмерные массивы
|
||||
array_internal_interface formal_ii = formal_type.get_internal_interface(internal_interface_kind.unsized_array_interface) as array_internal_interface;
|
||||
|
|
@ -1076,25 +1087,25 @@ namespace PascalABCCompiler.TreeRealization
|
|||
{
|
||||
goto eq_cmp;
|
||||
}
|
||||
return DeduceInstanceTypes(formal_ii.element_type, fact_ii.element_type, deduced, nils);
|
||||
return DeduceInstanceTypes(formal_ii.element_type, fact_ii.element_type, deduced, nils, generic_params);
|
||||
}
|
||||
//множества
|
||||
//Множества
|
||||
if (formal_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.set_type)
|
||||
{
|
||||
if (fact_type.type_special_kind != PascalABCCompiler.SemanticTree.type_special_kind.set_type)
|
||||
{
|
||||
goto eq_cmp;
|
||||
}
|
||||
return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils);
|
||||
return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils, generic_params);
|
||||
}
|
||||
//множества
|
||||
//Типизированные файлы
|
||||
if (formal_type.type_special_kind == PascalABCCompiler.SemanticTree.type_special_kind.typed_file)
|
||||
{
|
||||
if (fact_type.type_special_kind != PascalABCCompiler.SemanticTree.type_special_kind.typed_file)
|
||||
{
|
||||
goto eq_cmp;
|
||||
}
|
||||
return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils);
|
||||
return DeduceInstanceTypes(formal_type.element_type, fact_type.element_type, deduced, nils, generic_params);
|
||||
}
|
||||
//Делегаты
|
||||
if (formal_type.IsDelegate)
|
||||
|
|
@ -1128,7 +1139,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
continue;
|
||||
}
|
||||
// 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
|
||||
if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils))
|
||||
if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils, generic_params))
|
||||
//if (!DeduceInstanceTypes(fact_func.parameters[i].type, dii.parameters[i].type, deduced, nils))
|
||||
{
|
||||
goto eq_cmp;
|
||||
|
|
@ -1147,7 +1158,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
return true;
|
||||
}
|
||||
// 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
|
||||
else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
|
||||
else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils, generic_params)) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
|
||||
// else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
|
||||
{
|
||||
goto eq_cmp;
|
||||
|
|
@ -1184,7 +1195,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
}
|
||||
for (int i = 0; i < param_count; i++)
|
||||
{
|
||||
if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils)) // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
|
||||
if (!DeduceInstanceTypes(dii.parameters[i].type, fact_func.parameters[i].type, deduced, nils, generic_params)) // 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
|
||||
//if (!DeduceInstanceTypes(fact_func.parameters[i].type, dii.parameters[i].type, deduced, nils))
|
||||
{
|
||||
goto eq_cmp;
|
||||
|
|
@ -1199,7 +1210,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
goto eq_cmp;
|
||||
}
|
||||
// 07.04.15 - SSM поменял местами первые 2 параметра - видимо, была ошибка
|
||||
else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
|
||||
else if (fact_func.return_value_type == null || !DeduceInstanceTypes(dii.return_value_type, fact_func.return_value_type, deduced, nils, generic_params)) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
|
||||
// else if (fact_func.return_value_type == null || !DeduceInstanceTypes(fact_func.return_value_type, dii.return_value_type, deduced, nils)) // SSM 29.05.14 - не выводится если IEnumerable<TResult>
|
||||
{
|
||||
goto eq_cmp;
|
||||
|
|
@ -1248,7 +1259,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
int pcount = formal_type.instance_params.Count;
|
||||
for (int k = 0; k < pcount; ++k)
|
||||
{
|
||||
if (!DeduceInstanceTypes(formal_type.instance_params[k], fact_type_converted.instance_params[k], deduced, nils))
|
||||
if (!DeduceInstanceTypes(formal_type.instance_params[k], fact_type_converted.instance_params[k], deduced, nils, generic_params))
|
||||
{
|
||||
goto eq_cmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -675,6 +675,7 @@ namespace PascalABCCompiler.TreeRealization
|
|||
|
||||
}
|
||||
}
|
||||
public override string ToString() => "λ_anytype";
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
|
@ -4663,15 +4664,15 @@ namespace PascalABCCompiler.TreeRealization
|
|||
case SemanticTree.parameter_type.var : sb.Append("var "); break;
|
||||
}
|
||||
if (prm.is_params) sb.Append("params ");
|
||||
sb.Append(prm.name+": ");
|
||||
sb.Append(prm.type.name);
|
||||
sb.Append((prm.name ?? "_") +": ");
|
||||
sb.Append(prm.type.ToString());
|
||||
if (i<bfc.function.parameters.Length-1)
|
||||
sb.Append(';');
|
||||
}
|
||||
sb.Append(')');
|
||||
}
|
||||
if (bfc.function.return_value_type != null)
|
||||
sb.Append(": "+bfc.function.return_value_type.name);
|
||||
sb.Append(": "+bfc.function.return_value_type.ToString());
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
|
@ -4685,6 +4686,8 @@ namespace PascalABCCompiler.TreeRealization
|
|||
}
|
||||
}
|
||||
|
||||
public override string ToString() => name;
|
||||
|
||||
public override List<SymbolInfo> find(string name, bool no_search_in_extension_methods = false)
|
||||
{
|
||||
return find_in_type(name);
|
||||
|
|
|
|||
Loading…
Reference in a new issue