Replies: 11 comments
-
One possible solution could be using underbar " _ " as RHS. ref int x = ref _ ;
// same as the following, but variable is not ref-returnable from the current scope
ref int x ;
Span<int> s = _ ;
// same as the following, but variable is not val-returnable from the current scope
Span<int> s; It seems a bit too subtle though. |
Beta Was this translation helpful? Give feedback.
-
Real-world example where I had to work around this with unsafe code: |
Beta Was this translation helpful? Give feedback.
-
If I understand this, the If so, couldn't we move the "lifetime" of RHS ( Span<byte> s;
// fine.
// but `s` is no longer returnable because `stackalloc` is not
s = stackalloc byte[10]; Basically, what we do with |
Beta Was this translation helpful? Give feedback.
-
We already do something similar for refs (and later for ref re-assignments) ref int M() {
var local = 42;
ref var r1 = ref local;
ref var r2 = ref r1;
ref var r3 = ref r2
return ref r3; // error
} returnability flows through all assignments. |
Beta Was this translation helpful? Give feedback.
-
The problem is that ref-like variables do not need to be assigned at declaration. The issue is that two levels can be "guessed" and later enforced - outermost/external and innermost/current. But whichever is chosen, there are cases where it would be a wrong guess. |
Beta Was this translation helpful? Give feedback.
-
There is no guess, whenever you assign |
Beta Was this translation helpful? Give feedback.
-
I assume the following is how ref reassignment is going to work, ref int M() {
var local = 42;
ref var r1 = ref local;
return ref r1; // ERROR
r1 = ref field;
return ref r1; // OK
} If that's correct, we could do something similar with stackalloc here, Span<byte> s;
s = stackalloc byte[10];
return s; // ERROR
s = new byte[10];
return s; // OK |
Beta Was this translation helpful? Give feedback.
-
That is not how it works though. The escape level of a variable, just like its type when it is Span<byte> s; // Is "s" returnable or not returnable? By default it is.
s = stackalloc byte[10]; // <-- error here, since s is returnable |
Beta Was this translation helpful? Give feedback.
-
That's not how it works right now. Why it couldn't be inferred from the value that it has been assigned from, instead of just the "initializer"?
Yes that the current situation. But a variable that is not assigned anywhere, cannot be used anyways, right? couldn't we just infer the escape level once it is actually holding a value? (because that's where it actually makes sense and we know that what the escape level should be) |
Beta Was this translation helpful? Give feedback.
-
Another suggestion for a work-around for working with a public static class SpanExt {
public static ref T ToRef<T>(this Span<T> src, out int length) {
length = src.Length;
return ref MemoryMarshal.GetReference(src);
}
}
public static class RefExt {
public static Span<T> ToSpan<T>(this ref T reference, int length) where T : struct =>
MemoryMarshal.CreateSpan(ref reference, length);
} Usage: Span<byte> bytesOnStack = stackalloc byte[100].ToRef(out len).ToSpan(len); ...now the compiler does not realize that Be warned that circumventing the compiler is at your own peril! |
Beta Was this translation helpful? Give feedback.
-
We have Span<byte> s;
// error.
// s is returnable and stackalloc is not
s = stackalloc byte[10];
scoped Span<byte> t;
// no error.
t = stackalloc byte[10]; |
Beta Was this translation helpful? Give feedback.
-
Local references are much less common than returnable ones, so majority of users are ok with the current state.
However when you do need a ref/ref-like variable marked as nonreturnable, or generally bound to current scope, we do not have a good solution.
The default escape of references is the outermost scope ("optimized" for the most common case).
I.E.
is the same as
except the "s" is not definitely assigned.
It becomes a problem in cases when you need to create a variable suitable to accept a local reference with a particular escape scope, but not just yet.
Current half-solutions
===== Span
For
Span<T>
and types that it converts to implicitly, the following can be used.But it is only a half-solution.
===== ref locals
For
ref
locals, it is possible to do something like:But it is again a half-solution.
Beta Was this translation helpful? Give feedback.
All reactions