X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconvert.cs;h=a99e3fde628b60061aae8448ab3621c23a7fad9c;hb=d2a26c959578e8d721cfe320f6ac1d8ee8633cf3;hp=3adb909e6f5afc782964f929c325165b6694813d;hpb=bb99b3ef99e38cdbc8fbcab61d62a2943e216b61;p=mono.git diff --git a/mcs/mcs/convert.cs b/mcs/mcs/convert.cs index 3adb909e6f5..a99e3fde628 100644 --- a/mcs/mcs/convert.cs +++ b/mcs/mcs/convert.cs @@ -679,6 +679,80 @@ namespace Mono.CSharp { return null; } + static Expression ImplicitTupleLiteralConversion (ResolveContext rc, Expression source, TypeSpec targetType, Location loc) + { + var targetTypeArgument = targetType.TypeArguments; + if (source.Type.Arity != targetTypeArgument.Length) + return null; + + var namedTarget = targetType as NamedTupleSpec; + var tupleLiteral = source as TupleLiteral; + Expression instance; + + if (tupleLiteral == null && !ExpressionAnalyzer.IsInexpensiveLoad (source)) { + var expr_variable = LocalVariable.CreateCompilerGenerated (source.Type, rc.CurrentBlock, loc); + source = new CompilerAssign (expr_variable.CreateReferenceExpression (rc, loc), source, loc); + instance = expr_variable.CreateReferenceExpression (rc, loc); + } else { + instance = null; + } + + var converted = new List (targetType.Arity); + for (int i = 0; i < targetType.Arity; ++i) { + Expression elementSrc; + if (tupleLiteral != null) { + elementSrc = tupleLiteral.Elements [i].Expr; + + if (namedTarget != null) { + var elementSrcName = tupleLiteral.Elements [i].Name; + if (elementSrcName != null && elementSrcName != namedTarget.Elements [i]) { + rc.Report.Warning (8123, 1, loc, + "The tuple element name `{0}' is ignored because a different name or no name is specified by the target type `{1}'", + elementSrcName, namedTarget.GetSignatureForErrorWithNames ()); + } + } + } else { + elementSrc = new MemberAccess (instance, NamedTupleSpec.GetElementPropertyName (i)).Resolve (rc); + } + + var res = ImplicitConversionStandard (rc, elementSrc, targetTypeArgument [i], loc); + if (res == null) + return null; + + converted.Add (res); + } + + return new TupleLiteralConversion (source, targetType, converted, loc); + } + + static bool ImplicitTupleLiteralConversionExists (Expression source, TypeSpec targetType) + { + if (source.Type.Arity != targetType.Arity) + return false; + + var srcTypeArgument = source.Type.TypeArguments; + var targetTypeArgument = targetType.TypeArguments; + + var tupleLiteralElements = (source as TupleLiteral)?.Elements; + + for (int i = 0; i < targetType.Arity; ++i) { + var elementType = srcTypeArgument [i]; + + if (tupleLiteralElements != null) { + if (!ImplicitStandardConversionExists (tupleLiteralElements[i].Expr, targetTypeArgument [i])) { + return false; + } + } else { + if (!ImplicitStandardConversionExists (new EmptyExpression (srcTypeArgument [i]), targetTypeArgument [i])) { + return false; + } + } + } + + return true; + } + + // // Full version of implicit conversion // @@ -758,7 +832,10 @@ namespace Mono.CSharp { if (ImplicitBoxingConversion (null, expr_type, target_type) != null) return true; - + + if (expr_type.IsTupleType && target_type.IsTupleType) + return ImplicitTupleLiteralConversionExists (expr, target_type); + // // Implicit Constant Expression Conversions // @@ -1420,6 +1497,14 @@ namespace Mono.CSharp { return c; } + if (expr_type.IsTupleType) { + if (target_type.IsTupleType) + return ImplicitTupleLiteralConversion (ec, expr, target_type, loc); + + if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (expr_type)) + return null; + } + e = ImplicitNumericConversion (expr, expr_type, target_type); if (e != null) return e; @@ -1499,14 +1584,15 @@ namespace Mono.CSharp { /// ImplicitConversion. If there is no implicit conversion, then /// an error is signaled /// - static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source, + public static Expression ImplicitConversionRequired (ResolveContext ec, Expression source, TypeSpec target_type, Location loc) { Expression e = ImplicitConversion (ec, source, target_type, loc); if (e != null) return e; - source.Error_ValueCannotBeConverted (ec, target_type, false); + if (target_type != InternalType.ErrorType) + source.Error_ValueCannotBeConverted (ec, target_type, false); return null; }