Ejemplo n.º 1
0
        public override BoundNode VisitConvertedTupleLiteral(BoundConvertedTupleLiteral node)
        {
            if (_inExpressionLambda)
            {
                Error(ErrorCode.ERR_ExpressionTreeContainsTupleLiteral, node);
            }

            return(base.VisitConvertedTupleLiteral(node));
        }
 public override BoundNode VisitConvertedTupleLiteral(BoundConvertedTupleLiteral node)
 {
     return(VisitTupleExpression(node));
 }
Ejemplo n.º 3
0
        protected BoundExpression CreateConversion(
            CSharpSyntaxNode syntax,
            BoundExpression source,
            Conversion conversion,
            bool isCast,
            bool wasCompilerGenerated,
            TypeSymbol destination,
            DiagnosticBag diagnostics)
        {
            Debug.Assert(source != null);
            Debug.Assert((object)destination != null);

            if (conversion.IsIdentity)
            {
                // identity tuple conversions result in a converted tuple
                // to indicate that tuple conversions are no longer applicable.
                // nothing else changes
                if (source.Kind == BoundKind.TupleLiteral)
                {
                    var sourceTuple = (BoundTupleLiteral)source;
                    source = new BoundConvertedTupleLiteral(
                        sourceTuple.Syntax,
                        sourceTuple.Type, 
                        sourceTuple.Arguments, 
                        sourceTuple.Type, // same type to keep original element names 
                        sourceTuple.HasErrors);
                }

                // We need to preserve any conversion that changes the type (even identity conversions, like object->dynamic),
                // or that was explicitly written in code (so that GetSemanticInfo can find the syntax in the bound tree).
                if (!isCast && source.Type == destination)
                {
                    return source;
                }
            }

            ReportDiagnosticsIfObsolete(diagnostics, conversion, syntax, hasBaseReceiver: false);

            if (conversion.IsMethodGroup)
            {
                return CreateMethodGroupConversion(syntax, source, conversion, isCast, destination, diagnostics);
            }

            if (conversion.IsAnonymousFunction && source.Kind == BoundKind.UnboundLambda)
            {
                return CreateAnonymousFunctionConversion(syntax, source, conversion, isCast, destination, diagnostics);
            }

            if (conversion.IsTupleLiteral || 
                (conversion.Kind == ConversionKind.ImplicitNullable && source.Kind == BoundKind.TupleLiteral))
            {
                return CreateTupleLiteralConversion(syntax, (BoundTupleLiteral)source, conversion, isCast, destination, diagnostics);
            }

            if (conversion.IsUserDefined)
            {
                return CreateUserDefinedConversion(syntax, source, conversion, isCast, destination, diagnostics);
            }

            ConstantValue constantValue = this.FoldConstantConversion(syntax, source, conversion, destination, diagnostics);
            return new BoundConversion(
                syntax,
                source,
                conversion,
                IsCheckedConversion(source.Type, destination),
                explicitCastInCode: isCast && !wasCompilerGenerated,
                constantValueOpt: constantValue,
                type: destination)
            { WasCompilerGenerated = wasCompilerGenerated };
        }
Ejemplo n.º 4
0
        private BoundExpression CreateTupleLiteralConversion(CSharpSyntaxNode syntax, BoundTupleLiteral sourceTuple, Conversion conversion, bool isCast, TypeSymbol destination, DiagnosticBag diagnostics)
        {
            // We have a successful tuple conversion; rather than producing a separate conversion node 
            // which is a conversion on top of a tuple literal, tuple conversion is an element-wise conversion of arguments.

            Debug.Assert(conversion.Kind == ConversionKind.ImplicitTupleLiteral || conversion.Kind == ConversionKind.ImplicitNullable);
            Debug.Assert((conversion.Kind == ConversionKind.ImplicitNullable) == destination.IsNullableType());

            TypeSymbol destinationWithoutNullable = conversion.Kind == ConversionKind.ImplicitNullable ?
                                                                           destinationWithoutNullable = destination.GetNullableUnderlyingType() :
                                                                           destination;

            NamedTypeSymbol targetType = (NamedTypeSymbol)destinationWithoutNullable;

            if (targetType.IsTupleType)
            {
                var destTupleType = (TupleTypeSymbol)targetType;
                // do not lose the original element names in the literal if different from names in the target

                // Come back to this, what about locations? (https://github.com/dotnet/roslyn/issues/11013)
                targetType = destTupleType.WithElementNames(sourceTuple.ArgumentNamesOpt);
            }

            var arguments = sourceTuple.Arguments;
            var convertedArguments = ArrayBuilder<BoundExpression>.GetInstance(arguments.Length);

            ImmutableArray<TypeSymbol> targetElementTypes = targetType.GetElementTypesOfTupleOrCompatible();
            Debug.Assert(targetElementTypes.Length == arguments.Length, "converting a tuple literal to incompatible type?");

            for (int i = 0; i < arguments.Length; i++)
            {
                var argument = arguments[i];
                var destType = targetElementTypes[i];

                HashSet<DiagnosticInfo> useSiteDiagnostics = null;
                Conversion elementConversion;
                if (isCast)
                {
                    elementConversion = this.Conversions.ClassifyConversionForCast(argument, destType, ref useSiteDiagnostics);
                }
                else
                {
                    elementConversion = this.Conversions.ClassifyConversionFromExpression(argument, destType, ref useSiteDiagnostics);
                }

                diagnostics.Add(syntax, useSiteDiagnostics);
                convertedArguments.Add(CreateConversion(argument.Syntax, argument, elementConversion, isCast, destType, diagnostics));
            }

            BoundExpression result = new BoundConvertedTupleLiteral(
                sourceTuple.Syntax,
                sourceTuple.Type,
                convertedArguments.ToImmutableAndFree(), 
                targetType);

            // We need to preserve any conversion that changes the type (even identity conversions),
            // or that was explicitly written in code (so that GetSemanticInfo can find the syntax in the bound tree).
            if (!isCast && targetType == destination)
            {
                return result;
            }

            // if we have a nullable cast combined with a name/dynamic cast
            // name/dynamic cast must happen before converting to nullable
            if (conversion.Kind == ConversionKind.ImplicitNullable &&
                destinationWithoutNullable != targetType)
            {
                Debug.Assert(destinationWithoutNullable.Equals(targetType, ignoreDynamic: true));

                result = new BoundConversion(
                    syntax,
                    result,
                    Conversion.Identity,
                    @checked: false,
                    explicitCastInCode: isCast,
                    constantValueOpt: ConstantValue.NotAvailable,
                    type: destinationWithoutNullable)
                { WasCompilerGenerated = sourceTuple.WasCompilerGenerated };
            }
                                  
            return new BoundConversion(
                syntax,
                result,
                conversion,
                @checked: false,
                explicitCastInCode: isCast,
                constantValueOpt: ConstantValue.NotAvailable,
                type: destination)
            { WasCompilerGenerated = sourceTuple.WasCompilerGenerated };
        }
Ejemplo n.º 5
0
        private BoundExpression CreateTupleLiteralConversion(SyntaxNode syntax, BoundTupleLiteral sourceTuple, Conversion conversion, bool isCast, TypeSymbol destination, DiagnosticBag diagnostics)
        {
            // We have a successful tuple conversion; rather than producing a separate conversion node 
            // which is a conversion on top of a tuple literal, tuple conversion is an element-wise conversion of arguments.
            Debug.Assert((conversion.Kind == ConversionKind.ImplicitNullable) == destination.IsNullableType());

            var destinationWithoutNullable = destination;
            var conversionWithoutNullable = conversion;

            if (conversion.Kind == ConversionKind.ImplicitNullable)
            {
                destinationWithoutNullable = destination.GetNullableUnderlyingType();
                conversionWithoutNullable = conversion.UnderlyingConversions[0];
            }

            Debug.Assert(conversionWithoutNullable.IsTupleLiteralConversion);

            NamedTypeSymbol targetType = (NamedTypeSymbol)destinationWithoutNullable;
            if (targetType.IsTupleType)
            {
                var destTupleType = (TupleTypeSymbol)targetType;
                // do not lose the original element names in the literal if different from names in the target

                TupleTypeSymbol.ReportNamesMismatchesIfAny(targetType, sourceTuple, diagnostics);

                // Come back to this, what about locations? (https://github.com/dotnet/roslyn/issues/11013)
                targetType = destTupleType.WithElementNames(sourceTuple.ArgumentNamesOpt);
            }

            var arguments = sourceTuple.Arguments;
            var convertedArguments = ArrayBuilder<BoundExpression>.GetInstance(arguments.Length);

            ImmutableArray<TypeSymbol> targetElementTypes = targetType.GetElementTypesOfTupleOrCompatible();
            Debug.Assert(targetElementTypes.Length == arguments.Length, "converting a tuple literal to incompatible type?");
            var underlyingConversions = conversionWithoutNullable.UnderlyingConversions;

            for (int i = 0; i < arguments.Length; i++)
            {
                var argument = arguments[i];
                var destType = targetElementTypes[i];
                var elementConversion = underlyingConversions[i];

                convertedArguments.Add(CreateConversion(argument.Syntax, argument, elementConversion, isCast, destType, diagnostics));
            }

            BoundExpression result = new BoundConvertedTupleLiteral(
                sourceTuple.Syntax,
                sourceTuple.Type,
                convertedArguments.ToImmutableAndFree(),
                targetType);

            if (sourceTuple.Type != destination)
            {
                // literal cast is applied to the literal 
                result = new BoundConversion(
                    sourceTuple.Syntax,
                    result,
                    conversion,
                    @checked: false,
                    explicitCastInCode: isCast,
                    constantValueOpt: ConstantValue.NotAvailable,
                    type: destination);
            }

            // If we had a cast in the code, keep conversion in the tree.
            // even though the literal is already converted to the target type.
            if (isCast)
            {
                result = new BoundConversion(
                    syntax,
                    result,
                    Conversion.Identity,
                    @checked: false,
                    explicitCastInCode: isCast,
                    constantValueOpt: ConstantValue.NotAvailable,
                    type: destination);
            }

            return result;
        }
 public override BoundNode VisitConvertedTupleLiteral(BoundConvertedTupleLiteral node)
 {
     return VisitTupleExpression(node);
 }
        public override BoundNode VisitConvertedTupleLiteral(BoundConvertedTupleLiteral node)
        {
            if (_inExpressionLambda)
            {
                Error(ErrorCode.ERR_ExpressionTreeContainsTupleLiteral, node);
            }

            return base.VisitConvertedTupleLiteral(node);
        }