예제 #1
0
        public override Conversion GetStackAllocConversion(BoundStackAllocArrayCreation sourceExpression, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            if (sourceExpression.Syntax.IsVariableDeclarationInitialization())
            {
                Debug.Assert((object)sourceExpression.Type == null);
                Debug.Assert((object)sourceExpression.ElementType != null);

                var sourceAsPointer   = new PointerTypeSymbol(TypeSymbolWithAnnotations.Create(sourceExpression.ElementType));
                var pointerConversion = ClassifyImplicitConversionFromType(sourceAsPointer, destination, ref useSiteDiagnostics);

                if (pointerConversion.IsValid)
                {
                    return(Conversion.MakeStackAllocToPointerType(pointerConversion));
                }
                else
                {
                    var spanType = _binder.GetWellKnownType(WellKnownType.core_Span_T, ref useSiteDiagnostics);
                    if (spanType.TypeKind == TypeKind.Struct && spanType.IsRefLikeType)
                    {
                        var spanType_T     = spanType.Construct(sourceExpression.ElementType);
                        var spanConversion = ClassifyImplicitConversionFromType(spanType_T, destination, ref useSiteDiagnostics);

                        if (spanConversion.Exists)
                        {
                            return(Conversion.MakeStackAllocToSpanType(spanConversion));
                        }
                    }
                }
            }

            return(Conversion.NoConversion);
        }
예제 #2
0
        public override BoundNode VisitStackAllocArrayCreation(BoundStackAllocArrayCreation stackAllocNode)
        {
            var rewrittenCount = VisitExpression(stackAllocNode.Count);
            var type           = stackAllocNode.Type;

            if (rewrittenCount.ConstantValue?.Int32Value == 0)
            {
                // either default(span) or nullptr
                return(_factory.Default(type));
            }

            var elementType = stackAllocNode.ElementType;

            var initializerOpt = stackAllocNode.InitializerOpt;

            if (initializerOpt != null)
            {
                initializerOpt = initializerOpt.Update(VisitList(initializerOpt.Initializers));
            }

            if (type.IsPointerType())
            {
                var stackSize = RewriteStackAllocCountToSize(rewrittenCount, elementType);
                return(new BoundConvertedStackAllocExpression(stackAllocNode.Syntax, elementType, stackSize, initializerOpt, stackAllocNode.Type));
            }
            else if (TypeSymbol.Equals(type.OriginalDefinition, _compilation.GetWellKnownType(WellKnownType.core_Span_T), TypeCompareKind.ConsiderEverything2))
            {
                var spanType    = (NamedTypeSymbol)stackAllocNode.Type;
                var sideEffects = ArrayBuilder <BoundExpression> .GetInstance();

                var locals = ArrayBuilder <LocalSymbol> .GetInstance();

                var countTemp = CaptureExpressionInTempIfNeeded(rewrittenCount, sideEffects, locals);
                var stackSize = RewriteStackAllocCountToSize(countTemp, elementType);
                stackAllocNode = new BoundConvertedStackAllocExpression(stackAllocNode.Syntax, elementType, stackSize, initializerOpt, spanType);

                BoundExpression constructorCall;
                if (TryGetWellKnownTypeMember(stackAllocNode.Syntax, WellKnownMember.System_Span_T__ctor, out MethodSymbol spanConstructor))
                {
                    constructorCall = _factory.New((MethodSymbol)spanConstructor.SymbolAsMember(spanType), stackAllocNode, countTemp);
                }
                else
                {
                    constructorCall = new BoundBadExpression(
                        syntax: stackAllocNode.Syntax,
                        resultKind: LookupResultKind.NotInvocable,
                        symbols: ImmutableArray <Symbol> .Empty,
                        childBoundNodes: ImmutableArray <BoundExpression> .Empty,
                        type: ErrorTypeSymbol.UnknownResultType);
                }

                return(new BoundSequence(
                           syntax: stackAllocNode.Syntax,
                           locals: locals.ToImmutableAndFree(),
                           sideEffects: sideEffects.ToImmutableAndFree(),
                           value: constructorCall,
                           type: spanType));
            }
            else
            {
                throw ExceptionUtilities.UnexpectedValue(type);
            }
        }
예제 #3
0
 public override Conversion GetStackAllocConversion(BoundStackAllocArrayCreation sourceExpression, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
 {
     // Conversions involving stackalloc expressions require a Binder.
     throw ExceptionUtilities.Unreachable;
 }