提交 4770b753 编写于 作者: V vsadov

Removed ReturnableReference value kind. The returnability will be computed and...

Removed ReturnableReference value kind. The returnability will be computed and validated separately from value kinds now.
上级 5531aaf5
......@@ -54,14 +54,6 @@ internal enum BindValueKind : byte
/// </summary>
RefersToLocation = 4 << ValueKindInsignificantBits,
/// <summary>
/// Expression is free from references to the local frame.
///
/// As long as there are no types that can embed references,
/// this bit is meaningful only to byref variables.
/// </summary>
ReturnableReference = 8 << ValueKindInsignificantBits,
///////////////////
// The rest are just combinations of the above.
//
......@@ -134,11 +126,6 @@ private static bool RequiresReferenceToLocation(BindValueKind kind)
return (kind & BindValueKind.RefersToLocation) != 0;
}
private static bool RequiresReturnableReference(BindValueKind kind)
{
return (kind & BindValueKind.ReturnableReference) != 0;
}
private static bool RequiresAssignableVariable(BindValueKind kind)
{
return (kind & BindValueKind.Assignable) != 0;
......@@ -360,24 +347,13 @@ internal bool CheckValueKind(SyntaxNode node, BoundExpression expr, BindValueKin
case BoundKind.RefValueOperator:
// The undocumented __refvalue(tr, T) expression results in a variable of type T.
// it is a readwrite variable, but could refer to local data
if (!RequiresReturnableReference(valueKind))
{
return true;
}
break;
// it is a readwrite variable.
return true;
case BoundKind.DynamicMemberAccess:
case BoundKind.DynamicIndexerAccess:
// dynamic expressions can be read and written to
// can even be passed by reference (which is implemented via a temp)
// it is not valid to return them by reference though.
if (RequiresReturnableReference(valueKind))
{
Error(diagnostics, ErrorCode.ERR_RefReturnLvalueExpected, expr.Syntax);
return false;
}
return true;
case BoundKind.Parameter:
......@@ -410,12 +386,6 @@ internal bool CheckValueKind(SyntaxNode node, BoundExpression expr, BindValueKin
return false;
}
//"this" is not returnable by reference in a struct.
if(RequiresReturnableReference(valueKind))
{
Error(diagnostics, ErrorCode.ERR_RefReturnStructThis, node, ThisParameterSymbol.SymbolName);
}
return true;
case BoundKind.Call:
......@@ -468,35 +438,6 @@ private bool CheckLocalValueKind(SyntaxNode node, BoundLocal local, BindValueKin
// or declared in a foreach.
LocalSymbol localSymbol = local.LocalSymbol;
if (RequiresReturnableReference(valueKind))
{
if (localSymbol.RefKind == RefKind.None)
{
if (checkingReceiver)
{
Error(diagnostics, ErrorCode.ERR_RefReturnLocal2, local.Syntax, localSymbol);
}
else
{
Error(diagnostics, ErrorCode.ERR_RefReturnLocal, node, localSymbol);
}
return false;
}
if (!localSymbol.IsReturnable)
{
if (checkingReceiver)
{
Error(diagnostics, ErrorCode.ERR_RefReturnNonreturnableLocal2, local.Syntax, localSymbol);
}
else
{
Error(diagnostics, ErrorCode.ERR_RefReturnNonreturnableLocal, node, localSymbol);
}
return false;
}
}
if (RequiresAssignableVariable(valueKind))
{
if (this.LockedOrDisposedVariables.Contains(localSymbol))
......@@ -555,20 +496,6 @@ private bool CheckParameterValueKind(SyntaxNode node, BoundParameter parameter,
ParameterSymbol parameterSymbol = parameter.ParameterSymbol;
var paramKind = parameterSymbol.RefKind;
// byval parameters are not ref-returnable
if (RequiresReturnableReference(valueKind) && parameterSymbol.RefKind == RefKind.None)
{
if (checkingReceiver)
{
Error(diagnostics, ErrorCode.ERR_RefReturnParameter2, parameter.Syntax, parameterSymbol.Name);
}
else
{
Error(diagnostics, ErrorCode.ERR_RefReturnParameter, node, parameterSymbol.Name);
}
return false;
}
// all parameters can be passed by ref/out or assigned to
// except "in" parameters, which are readonly
if (paramKind == RefKind.RefReadOnly && RequiresAssignableVariable(valueKind))
......@@ -746,11 +673,7 @@ private bool CheckEventValueKind(BoundEventAccess boundEvent, BindValueKind valu
}
else if (ReportUseSiteDiagnostics(eventSymbol, diagnostics, eventSyntax))
{
if (RequiresReturnableReference(valueKind) && !CheckIsValidReceiverForVariable(eventSyntax, receiver, valueKind, diagnostics))
{
return false;
}
else if (!CheckIsValidReceiverForVariable(eventSyntax, receiver, BindValueKind.Assignable, diagnostics))
if (!CheckIsValidReceiverForVariable(eventSyntax, receiver, BindValueKind.Assignable, diagnostics))
{
return false;
}
......@@ -1189,11 +1112,6 @@ static private ErrorCode GetStandardLvalueError(BindValueKind kind)
return ErrorCode.ERR_RefReturnLvalueExpected;
}
if (RequiresReturnableReference(kind))
{
return ErrorCode.ERR_RefReturnLvalueExpected;
}
if (RequiresReferenceToLocation(kind))
{
return ErrorCode.ERR_RefLvalueExpected;
......@@ -1229,20 +1147,20 @@ private static void ReportReadOnlyFieldError(FieldSymbol field, SyntaxNode node,
ErrorCode[] ReadOnlyErrors =
{
ErrorCode.ERR_RefReadonly,
ErrorCode.ERR_RefReturnReadonly,
ErrorCode.ERR_RefReadonly,
ErrorCode.ERR_AssgReadonly,
ErrorCode.ERR_RefReadonlyStatic,
ErrorCode.ERR_RefReturnReadonlyStatic,
ErrorCode.ERR_RefReadonlyStatic,
ErrorCode.ERR_AssgReadonlyStatic,
ErrorCode.ERR_RefReadonly2,
ErrorCode.ERR_RefReturnReadonly2,
ErrorCode.ERR_RefReadonly2,
ErrorCode.ERR_AssgReadonly2,
ErrorCode.ERR_RefReadonlyStatic2,
ErrorCode.ERR_RefReturnReadonlyStatic2,
ErrorCode.ERR_RefReadonlyStatic2,
ErrorCode.ERR_AssgReadonlyStatic2
};
int index = (checkingReceiver ? 6 : 0) + (field.IsStatic ? 3 : 0) + (RequiresRefOrOut(kind) ? 0 : (RequiresReturnableReference(kind) ? 1 : 2));
int index = (checkingReceiver ? 6 : 0) + (field.IsStatic ? 3 : 0) + (kind == BindValueKind.RefReturn ? 0 : (RequiresRefOrOut(kind) ? 1 : 2));
if (checkingReceiver)
{
Error(diagnostics, ReadOnlyErrors[index], node, field);
......@@ -1270,15 +1188,15 @@ private static void ReportReadOnlyError(Symbol symbol, SyntaxNode node, BindValu
ErrorCode[] ReadOnlyErrors =
{
ErrorCode.ERR_RefReadonlyNotField,
ErrorCode.ERR_RefReturnReadonlyNotField,
ErrorCode.ERR_RefReadonlyNotField,
ErrorCode.ERR_AssignReadonlyNotField,
ErrorCode.ERR_RefReadonlyNotField2,
ErrorCode.ERR_RefReturnReadonlyNotField2,
ErrorCode.ERR_RefReadonlyNotField2,
ErrorCode.ERR_AssignReadonlyNotField2,
};
int index = (checkingReceiver ? 3 : 0) + (RequiresRefOrOut(kind) ? 0 : (RequiresReturnableReference(kind) ? 1 : 2));
int index = (checkingReceiver ? 3 : 0) + (kind == BindValueKind.RefReturn ? 0 : (RequiresRefOrOut(kind) ? 1 : 2));
Error(diagnostics, ReadOnlyErrors[index], node, symbolKind, symbol);
}
......
......@@ -8459,7 +8459,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to A readonly field cannot be returned by reference.
/// Looks up a localized string similar to A readonly field cannot be returned by writeable reference.
/// </summary>
internal static string ERR_RefReturnReadonly {
get {
......@@ -8468,7 +8468,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to Members of readonly field &apos;{0}&apos; cannot be returned by reference.
/// Looks up a localized string similar to Members of readonly field &apos;{0}&apos; cannot be returned by writeable reference.
/// </summary>
internal static string ERR_RefReturnReadonly2 {
get {
......@@ -8504,7 +8504,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to Cannot return {0} &apos;{1}&apos; by reference because it is a readonly variable.
/// Looks up a localized string similar to Cannot return {0} &apos;{1}&apos; by writeable reference because it is a readonly variable.
/// </summary>
internal static string ERR_RefReturnReadonlyNotField {
get {
......@@ -8513,7 +8513,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to Members of {0} &apos;{1}&apos; cannot be returned by reference because it is a readonly variable.
/// Looks up a localized string similar to Members of {0} &apos;{1}&apos; cannot be returned by writeable reference because it is a readonly variable.
/// </summary>
internal static string ERR_RefReturnReadonlyNotField2 {
get {
......@@ -8522,7 +8522,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to A static readonly field cannot be returned by reference.
/// Looks up a localized string similar to A static readonly field cannot be returned by writeable reference.
/// </summary>
internal static string ERR_RefReturnReadonlyStatic {
get {
......@@ -8531,7 +8531,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to Fields of static readonly field &apos;{0}&apos; cannot be returned by reference.
/// Looks up a localized string similar to Fields of static readonly field &apos;{0}&apos; cannot be returned by writeable reference.
/// </summary>
internal static string ERR_RefReturnReadonlyStatic2 {
get {
......
......@@ -2825,10 +2825,10 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep
<value>Cannot assign to a member of {0} '{1}' because it is a readonly variable</value>
</data>
<data name="ERR_RefReturnReadonlyNotField" xml:space="preserve">
<value>Cannot return {0} '{1}' by reference because it is a readonly variable</value>
<value>Cannot return {0} '{1}' by writeable reference because it is a readonly variable</value>
</data>
<data name="ERR_RefReturnReadonlyNotField2" xml:space="preserve">
<value>Members of {0} '{1}' cannot be returned by reference because it is a readonly variable</value>
<value>Members of {0} '{1}' cannot be returned by writeable reference because it is a readonly variable</value>
</data>
<data name="ERR_AssgReadonlyStatic2" xml:space="preserve">
<value>Fields of static readonly field '{0}' cannot be assigned to (except in a static constructor or a variable initializer)</value>
......@@ -4827,16 +4827,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<value>Cannot return fields of '{0}' by reference because it is a '{1}'</value>
</data>
<data name="ERR_RefReturnReadonly" xml:space="preserve">
<value>A readonly field cannot be returned by reference</value>
<value>A readonly field cannot be returned by writeable reference</value>
</data>
<data name="ERR_RefReturnReadonlyStatic" xml:space="preserve">
<value>A static readonly field cannot be returned by reference</value>
<value>A static readonly field cannot be returned by writeable reference</value>
</data>
<data name="ERR_RefReturnReadonly2" xml:space="preserve">
<value>Members of readonly field '{0}' cannot be returned by reference</value>
<value>Members of readonly field '{0}' cannot be returned by writeable reference</value>
</data>
<data name="ERR_RefReturnReadonlyStatic2" xml:space="preserve">
<value>Fields of static readonly field '{0}' cannot be returned by reference</value>
<value>Fields of static readonly field '{0}' cannot be returned by writeable reference</value>
</data>
<data name="ERR_RefReturnCall" xml:space="preserve">
<value>Cannot return by reference a result of '{0}' because the argument passed to parameter '{1}' cannot be returned by reference</value>
......
......@@ -435,6 +435,47 @@ static void M(in int arg1, in (int Alice, int Bob) arg2)
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "arg2.Alice").WithArguments("variable", "in (int Alice, int Bob)"));
}
[Fact]
public void ReadonlyParamCannotRefReturn()
{
var text = @"
class Program
{
static ref readonly int M1_baseline(in int arg1, in (int Alice, int Bob) arg2)
{
// valid
return ref arg1;
}
static ref readonly int M2_baseline(in int arg1, in (int Alice, int Bob) arg2)
{
// valid
return ref arg2.Alice;
}
static ref int M1(in int arg1, in (int Alice, int Bob) arg2)
{
return ref arg1;
}
static ref int M2(in int arg1, in (int Alice, int Bob) arg2)
{
return ref arg2.Alice;
}
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (18,20): error CS8410: Cannot return variable 'in int' by writeable reference because it is a readonly variable
// return ref arg1;
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "arg1").WithArguments("variable", "in int").WithLocation(18, 20),
// (23,20): error CS8411: Members of variable 'in (int Alice, int Bob)' cannot be returned by writeable reference because it is a readonly variable
// return ref arg2.Alice;
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField2, "arg2.Alice").WithArguments("variable", "in (int Alice, int Bob)").WithLocation(23, 20)
);
}
[Fact]
public void ReadonlyParamCannotAssignByref()
{
......@@ -522,12 +563,13 @@ class Program
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (10,24): error CS8406: Cannot use variable 'in int' as a ref or out value because it is a readonly variable
// (10,24): error CS8410: Cannot return variable 'in int' by writeable reference because it is a readonly variable
// return ref arg1;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "arg1").WithArguments("variable", "in int"),
// (14,24): error CS8407: Members of variable 'in (int Alice, int Bob)' cannot be used as a ref or out value because it is a readonly variable
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "arg1").WithArguments("variable", "in int").WithLocation(10, 24),
// (14,24): error CS8411: Members of variable 'in (int Alice, int Bob)' cannot be returned by writeable reference because it is a readonly variable
// return ref arg2.Alice;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField2, "arg2.Alice").WithArguments("variable", "in (int Alice, int Bob)"));
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField2, "arg2.Alice").WithArguments("variable", "in (int Alice, int Bob)").WithLocation(14, 24)
);
}
[Fact]
......@@ -640,12 +682,12 @@ class Program
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (12,28): error CS8406: Cannot use variable 'in int' as a ref or out value because it is a readonly variable
// (12,28): error CS8410: Cannot return variable 'in int' by writeable reference because it is a readonly variable
// return ref arg11;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "arg11").WithArguments("variable", "in int").WithLocation(12, 28),
// (16,28): error CS8407: Members of variable 'in (int Alice, int Bob)' cannot be used as a ref or out value because it is a readonly variable
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "arg11").WithArguments("variable", "in int").WithLocation(12, 28),
// (16,28): error CS8411: Members of variable 'in (int Alice, int Bob)' cannot be returned by writeable reference because it is a readonly variable
// return ref arg21.Alice;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField2, "arg21.Alice").WithArguments("variable", "in (int Alice, int Bob)").WithLocation(16, 28)
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField2, "arg21.Alice").WithArguments("variable", "in (int Alice, int Bob)").WithLocation(16, 28)
);
}
......
......@@ -322,18 +322,18 @@ class Program
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (12,28): error CS8406: Cannot use method 'Program.M()' as a ref or out value because it is a readonly variable
// (12,28): error CS8410: Cannot return method 'Program.M()' by writeable reference because it is a readonly variable
// return ref M();
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "M()").WithArguments("method", "Program.M()").WithLocation(12, 28),
// (16,28): error CS8407: Members of method 'Program.M1()' cannot be used as a ref or out value because it is a readonly variable
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "M()").WithArguments("method", "Program.M()").WithLocation(12, 28),
// (16,28): error CS8411: Members of method 'Program.M1()' cannot be returned by writeable reference because it is a readonly variable
// return ref M1().Alice;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField2, "M1().Alice").WithArguments("method", "Program.M1()").WithLocation(16, 28),
// (23,28): error CS8406: Cannot use property 'Program.P' as a ref or out value because it is a readonly variable
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField2, "M1().Alice").WithArguments("method", "Program.M1()").WithLocation(16, 28),
// (23,28): error CS8410: Cannot return property 'Program.P' by writeable reference because it is a readonly variable
// return ref P;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "P").WithArguments("property", "Program.P").WithLocation(23, 28),
// (27,28): error CS8407: Members of property 'Program.P1' cannot be used as a ref or out value because it is a readonly variable
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "P").WithArguments("property", "Program.P").WithLocation(23, 28),
// (27,28): error CS8411: Members of property 'Program.P1' cannot be returned by writeable reference because it is a readonly variable
// return ref P1.Alice;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField2, "P1.Alice").WithArguments("property", "Program.P1").WithLocation(27, 28)
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField2, "P1.Alice").WithArguments("property", "Program.P1").WithLocation(27, 28)
);
}
......
......@@ -515,27 +515,27 @@ static Test()
// (65,33): error CS0192: A readonly field cannot be used as a ref or out value (except in a constructor)
// ref char temp = ref i1;
Diagnostic(ErrorCode.ERR_RefReadonly, "i1").WithLocation(65, 33),
// (68,24): error CS0192: A readonly field cannot be used as a ref or out value (except in a constructor)
// (68,24): error CS8160: A readonly field cannot be returned by writeable reference
// return ref i1;
Diagnostic(ErrorCode.ERR_RefReadonly, "i1").WithLocation(68, 24),
Diagnostic(ErrorCode.ERR_RefReturnReadonly, "i1").WithLocation(68, 24),
// (72,33): error CS1649: Members of readonly field 'Test.i2' cannot be used as a ref or out value (except in a constructor)
// ref char temp = ref i2.x;
Diagnostic(ErrorCode.ERR_RefReadonly2, "i2.x").WithArguments("Test.i2").WithLocation(72, 33),
// (75,24): error CS1649: Members of readonly field 'Test.i2' cannot be used as a ref or out value (except in a constructor)
// (75,24): error CS8162: Members of readonly field 'Test.i2' cannot be returned by writeable reference
// return ref i2.x;
Diagnostic(ErrorCode.ERR_RefReadonly2, "i2.x").WithArguments("Test.i2").WithLocation(75, 24),
Diagnostic(ErrorCode.ERR_RefReturnReadonly2, "i2.x").WithArguments("Test.i2").WithLocation(75, 24),
// (83,33): error CS0199: A static readonly field cannot be used as a ref or out value (except in a static constructor)
// ref char temp = ref s1;
Diagnostic(ErrorCode.ERR_RefReadonlyStatic, "s1").WithLocation(83, 33),
// (86,24): error CS0199: A static readonly field cannot be used as a ref or out value (except in a static constructor)
// (86,24): error CS8161: A static readonly field cannot be returned by writeable reference
// return ref s1;
Diagnostic(ErrorCode.ERR_RefReadonlyStatic, "s1").WithLocation(86, 24),
Diagnostic(ErrorCode.ERR_RefReturnReadonlyStatic, "s1").WithLocation(86, 24),
// (90,33): error CS1651: Fields of static readonly field 'Test.s2' cannot be used as a ref or out value (except in a static constructor)
// ref char temp = ref s2.x;
Diagnostic(ErrorCode.ERR_RefReadonlyStatic2, "s2.x").WithArguments("Test.s2").WithLocation(90, 33),
// (93,24): error CS1651: Fields of static readonly field 'Test.s2' cannot be used as a ref or out value (except in a static constructor)
// (93,24): error CS8163: Fields of static readonly field 'Test.s2' cannot be returned by writeable reference
// return ref s2.x;
Diagnostic(ErrorCode.ERR_RefReadonlyStatic2, "s2.x").WithArguments("Test.s2").WithLocation(93, 24)
Diagnostic(ErrorCode.ERR_RefReturnReadonlyStatic2, "s2.x").WithArguments("Test.s2").WithLocation(93, 24)
);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册