public override Expression DoResolve(ParseContext ec) { // It's null when lifting non-nullable type if (_unwrap == null) { // S -> T? is wrap only if (TypeManager.IsNullableType(Type)) { return(Wrap.Create(_child, Type)); } // S -> T can be simplified return(_child); } // Wrap target for T? if (TypeManager.IsNullableType(Type)) { _child = Wrap.Create(_child, Type); if (_child == null) { return(null); } } ExpressionClass = ExpressionClass.Value; return(this); }
public static Expression ImplicitNullableConversion(ParseContext ec, Expression expr, Type targetType) { Type exprType = expr.Type; // // From null to any nullable type // if (exprType == TypeManager.CoreTypes.Null) { return(ec == null ? EmptyExpression.Null : LiftedNullExpression.Create(targetType, expr.Span)); } // S -> T? var elementType = targetType.GetGenericArguments()[0]; // S? -> T? if (TypeManager.IsNullableType(exprType)) { exprType = exprType.GetGenericArguments()[0]; } // // Predefined implicit identity or implicit numeric conversion // has to exist between underlying type S and underlying type T // // Handles probing if (ec == null) { if (exprType == elementType) { return(EmptyExpression.Null); } return(MakeImplicitNumericConversion(ec, null, exprType, elementType)); } Expression unwrap; if (exprType != expr.Type) { unwrap = Unwrap.Create(expr); } else { unwrap = expr; } Expression conv = exprType == elementType ? unwrap : MakeImplicitNumericConversion(ec, unwrap, exprType, elementType); if (conv == null) { return(null); } if (exprType != expr.Type) { return(new LiftedExpression(conv, unwrap, targetType).Resolve(ec)); } // Do constant optimization for S -> T? if (unwrap is ConstantExpression) { conv = ((ConstantExpression)unwrap).ConvertImplicitly(elementType); } return(Wrap.Create(conv, targetType)); }