Why a `stackalloc` expression cannot be assigned to a `Span<T>` parameter?

660 views Asked by At

Consider the following methods (fiddle):

void test(Span<int> param)
{
    //Fail, the stackalloc'ed buffer could be exposed.
    param = stackalloc int[10];
}

void test2(Span<int> param)
{
    //OK
    Span<int> local = stackalloc int[10];
}

I don't understand why param = stackalloc int[10]; produces the error:

A result of a stackalloc expression of type 'Span' cannot be used in this context because it may be exposed outside of the containing method

Span is a ref struct but (despite its name) it is still a value-type so any modification to param won't be reflected on the caller object.

I think of param as a local variable with an initial value and I don't see why test2 compiles while test doesn't.

How can the returned value of stackalloc int[10] in test escape the scope of the method?

1

There are 1 answers

1
Margaret Bloom On

Sinatr posted a link (here the relevant part) in the comments that helped me put the whole code in the context of Span safety.

In the method test the parameter param is safe to return because we can pretend it was like a local variable initialized with a value given by the caller (and thus, being external to the method, safe to return).

When a local is marked safe to return, the compiler will prevent any assignment to it with values that are not safe to return (stackalloc expressions are safe to escape to the top scope of the method but are not safe to return, obviously).

The fact that the method is void doesn't matter (neither to me as an asker, neither to the compiler) as this rule is general (I don't see much benefit from handling these corner cases).

For completeness, this code doesn't compile:

void test2(Span<int> param)
{
    //Fail, because local is marked safe to return
    Span<int> local = param;
    local = stackalloc int[10];
}

This was the missing piece I was looking for.