Разбираясь с
вот этим случаем, нарвался на любопытную функцию в компиляторе — ForceIntType.
Ее смысл заключается в том, что для встроенных операторов (&, +, и т.п.), операндами которых являются типы меньшие нежели int, задается возвращаемый тип int.
По всей видимости поляки пытались реализовать одну из фич C#-а, при этом не особо задумываясь над тем нужно ли это делать или нет.
Поддержка данной фичи приводит к вот таким вот казусам:
def b : byte = 1;
def _ul : ulong = b & 0x7FUL;
данный код не компилируется с сообщением об ошибке "немогу привести int к ulong).
Казалось бы тип второго операнда задан как UL и должна выбраться версия оператора & с типом ulong * ulong -> ulong, но умный код разрешения перегрузки видит что значение второго операнда — это константа которая влезает в byte и выбирает перегрузку byte * byte ->
int.
А вот, выделенный жирным, int появляется в следствии работы ForceIntType.
Данная неопрятность вылезает и во множестве других мест. Это вызывает некоторые проблемы при использовании стандартных операторов над встроенными типами размер которых меньше int.
C# не имеет подобных проблем, так как в нем допускается ряд небезопасных не явных приведений от int.
Я провел смелый научный эксперимент и закоментировал тело тело функции ForceIntType:
protected static ForceIntType (name : string) : void
{
_ = name;
/*
match (special_members [name]) {
| [elem is IMethod] =>
assert (InternalType.Int32 != null);
def hd = elem.GetHeader ();
hd.ReturnType = InternalType.Int32;
| _ => assert (false)
}
*/
}
Никаких проблем это не создало и компилятор вместе с тестами спокойно собрался по двухпроходной схеме.
Собственно вопрос в том есть ли смысл в этом чуде нечеловеческой мысли? Может убрать этот ForceIntType?