private EXPR BindImplicitConversion(
ArgumentObject[] arguments,
Type returnType,
Dictionary<int, LocalVariableSymbol> dictionary,
bool bIsArrayCreationConversion)
{
if (arguments.Length != 1)
{
throw Error.BindImplicitConversionRequireOneArgument();
}
// Load the conversions on the target.
_symbolTable.AddConversionsForType(returnType);
EXPR argument = CreateArgumentEXPR(arguments[0], dictionary[0]);
CType destinationType = _symbolTable.GetCTypeFromType(returnType);
if (bIsArrayCreationConversion)
{
// If we are converting for an array index, we want to convert to int, uint,
// long, or ulong, depending on what the argument will allow. However, since
// the compiler had to pick a particular type for the return value when it
// made the callsite, we need to make sure that we ultimately return a type
// of that value. So we "mustConvert" to the best type that chooseArrayIndexType
// can find, and then we cast the result of that to the returnType, which is
// incidentally Int32 in the existing compiler. For that cast, we do not consider
// user defined conversions (since the convert is guaranteed to return one of
// the primitive types), and we check for overflow since we don't want truncation.
CType pDestType = _binder.chooseArrayIndexType(argument);
if (null == pDestType)
{
pDestType = SymbolLoader.GetReqPredefType(PredefinedType.PT_INT, true);
}
return _binder.mustCast(
_binder.mustConvert(argument, pDestType),
destinationType,
CONVERTTYPE.CHECKOVERFLOW | CONVERTTYPE.NOUDC);
}
return _binder.mustConvert(argument, destinationType);
}