Version Used:
master 7 July 2018 on https://sharplab.io
Steps to Reproduce:
Compile the following program:
unsafe struct S
{
void M(in S x)
{
ref readonly var y = ref x;
fixed (S* p = &x) {}
fixed (S* p = &y) {}
}
}
Expected Behavior:
Compiler emits diagnostics "error CS0211: Cannot take the address of the given expression" on both address-of operators, because according to specification:
A compile-time error occurs if E is not classified as a variable, if E is classified as a read-only local variable, or if E denotes a moveable variable.
Actual Behavior:
Code compiles without errors.
/cc @VSadov
BTW I see the same behavior with any variables classified as read-only.
For instance, with foreach-loop variables:
foreach (int x in new int[0])
{
int* ptr = &x; // no error currently, but error with old compiler
}
or with readonly fields:
struct S1 {}
struct S2
{
public readonly S1 Inner;
unsafe void M(S2 arg)
{
S1* ptr = &arg.Inner; // no error currently, but error with old compiler
}
}
Is it a bug or at some point the rules regarding the taking addresses have been relaxed?
/cc @jcouv (I'm sorry for cc'ing you directly, but the issue bothers me and Vladimir is moved to JS/Chakra AFAIK)
Will take a look. Thanks for the ping.
Tagging @agocke who I think was looking at another fixed issue recently, in case there is any relation.
My rule change was very narrowly tailored, so I'd be surprised if this issue was caused by that change.
But, it definitely looks like a violation of the spec. See here: https://sharplab.io/#v2:EYLgtghgzgLgpgJwDQBMQGoA+ABADAAmwEYAWAbgFgAoagVwDsoIAzOfWBWgYxnwGVqAb3wjqI7CXwBZABTEAzAB4+APnxwAlGPyDtIkcwD2COBC4ALfDL7t8AS3rqtVfft0vXnvgCp8AB3wAXnwAMihKD1cAX20YqiigA==
foreach iteration variables should be read-only, so the spec should not consider them legal targets for &, but there's no error. Either this was intentional and we didn't note a spec relaxation, or we have a bug.
FWIW, I'm not sure what we want to do for ref-readonly. I could definitely see wanting to take a pointer to a ReadOnlySpan, which would probably be prohibited by these rules.
Btw a reasonable addition here would be... readonly pointers 馃榿
Probably a result of https://github.com/dotnet/roslyn/pull/22400
Pointers are commonly used to get around the type system entirely.
From that perspective respecting readonlyness seems strange. It would not make things safer or faster or serve any other purpose, just cause inconveniences.
@VSadov Thank you for explanation! Then it totally makes sense.
Apparently both @jcouv and I both reviewed this and totally forgot about it.
I'm going to now treat this issue as tracking a spec change, probably for C# 7.2.