Consider changing the inferred type of stackalloc to a Span<T> instead of a T* if using a safe context #8813
Replies: 15 comments
-
This is a language proposal, not a framework/runtime proposal. Language changes should be proposed at dotnet/csharplang. But on top of that, I don't see this being considered because it changes meaning of the code depending on whether the current block is |
Beta Was this translation helpful? Give feedback.
-
As @Joe4evr said, we likely can't do this. If we had Span when stackalloc was added to the language, it probably would never have returned a pointer array. But it did, and having the result type of an expression change based on the unsafe context does not sound like a good idea to me. |
Beta Was this translation helpful? Give feedback.
-
I'm personally intrigued by this idea. Namely, while it would technically be a breaking change , I wonder if we could justsay that the type of stackalloc was |
Beta Was this translation helpful? Give feedback.
-
The above comments make sense and I agree that returning different types between unsafe and safe probably isn't the best idea, however, as mentioned by @CyrusNajmabadi, maybe changing stackalloc to always return a |
Beta Was this translation helpful? Give feedback.
-
Converting a
I also think it adds more confusion for relatively little benefit. Checked/unchecked operations are bad enough and I wouldn't want to remember that |
Beta Was this translation helpful? Give feedback.
-
or this var span = (stackalloc T[size]);
|
Beta Was this translation helpful? Give feedback.
-
@tannergooding I agree with what you are saying, however, I still don't find it great to have a type infer to a pointer in a safe context. From my understanding, unsafe code was always supposed to be an explicit opt-in feature and whilst I understand that |
Beta Was this translation helpful? Give feedback.
-
Why would this be a breaking change? int Foo() { var s = stackalloc int[5]; } does not currently compile. int Foo() { Span<int> s = stackalloc int[5]; } does. unsafe int Foo() { var s = stackalloc int[5]; } Compiles of course, and would still (if this is accepted) infere int*. So the meaning of existing code would not change. I agree it's kind of weird that the return type changes based on unsafe context, but why is it a "breaking" change? All it does it allow code that currently does not compile to do so, no? |
Beta Was this translation helpful? Give feedback.
-
I don't think it's technically a breaking change. It would be a very odd language semantic, but it's not technically a break. |
Beta Was this translation helpful? Give feedback.
-
@chrisaut It's not about it being a breaking change to allow this; it's that doing this makes the simple act of changing a block to struct S
{
// 50 lines down....
int M()
{
var span = stackalloc int[8]; // not unsafe, inferred as Span<int>
return span.Length; // valid
}
} And then you add an unsafe struct S
{
// 50 lines down....
int M()
{
var span = stackalloc int[8]; // unsafe context, inferred as int*
return span.Length; // oops! cant do .Length on int*
}
} |
Beta Was this translation helpful? Give feedback.
-
@Joe4evr that's why I don't think we'd do this, but that doesn't make this a breaking change. A breaking change changes the meaning of existing, compiling code. |
Beta Was this translation helpful? Give feedback.
-
Right. And I probably agree that the gain here would be small compared to the weird semantics. I was just trying to understand why this would be breaking. It would still be nice to just use var in safe contexts, but yeah.... |
Beta Was this translation helpful? Give feedback.
-
@Joe4evr does it not make more sense then to return a This is obviously a breaking change though |
Beta Was this translation helpful? Give feedback.
-
I don't think it is worth a breaking change for an edge case scenario around saving 5 characters when typing 😄. |
Beta Was this translation helpful? Give feedback.
-
Can we legalize |
Beta Was this translation helpful? Give feedback.
-
Currently, if you want to use stackalloc to allocate a Span you need to do one of the following because the inferred type when using the var keyword is a T* (which you cannot access in a safe context.
or
It would be nice if this so that you could do something like the following and get a Span as the inferred type if you were not using an unsafe context
Beta Was this translation helpful? Give feedback.
All reactions