提交 f1525a89 编写于 作者: V Vladimir Sadov 提交者: GitHub

Merge pull request #17737 from VSadov/inRoReb

Implementing safety rules for the "ref readonly" parameters and returns
......@@ -644,70 +644,6 @@ internal static ThreeState ReportDiagnosticsIfObsoleteInternal(DiagnosticBag dia
return AccessCheck.IsSymbolAccessible(symbol, within, throughTypeOpt, out failedThroughTypeCheck, ref useSiteDiagnostics, basesBeingResolved);
}
/// <summary>
/// Expression lvalue and rvalue requirements.
/// </summary>
internal enum BindValueKind : byte
{
/// <summary>
/// Expression is the RHS of an assignment operation.
/// </summary>
/// <remarks>
/// The following are rvalues: values, variables, null literals, properties
/// and indexers with getters, events. The following are not rvalues:
/// namespaces, types, method groups, anonymous functions.
/// </remarks>
RValue,
/// <summary>
/// Expression is the RHS of an assignment operation
/// and may be a method group.
/// </summary>
RValueOrMethodGroup,
/// <summary>
/// Expression is the LHS of a simple assignment operation.
/// </summary>
Assignment,
/// <summary>
/// Expression is the operand of an increment
/// or decrement operation.
/// </summary>
IncrementDecrement,
/// <summary>
/// Expression is the LHS of a compound assignment
/// operation (such as +=).
/// </summary>
CompoundAssignment,
/// <summary>
/// Expression is passed as a ref or out parameter or assigned to a byref variable.
/// </summary>
RefOrOut,
/// <summary>
/// Expression is the operand of an address-of operation (&amp;).
/// </summary>
AddressOf,
/// <summary>
/// Expression is the receiver of a fixed buffer field access
/// </summary>
FixedReceiver,
/// <summary>
/// Expression is assigned by reference.
/// </summary>
RefAssign,
/// <summary>
/// Expression is returned by reference.
/// </summary>
RefReturn,
}
/// <summary>
/// Report diagnostics that should be reported when using a synthesized attribute.
/// </summary>
......
......@@ -664,7 +664,7 @@ private BoundTupleLiteral DeconstructionVariablesAsTuple(CSharpSyntaxNode syntax
}
default:
var boundVariable = BindExpression(node, diagnostics, invoked: false, indexed: false);
var checkedVariable = CheckValue(boundVariable, BindValueKind.Assignment, diagnostics);
var checkedVariable = CheckValue(boundVariable, BindValueKind.Assignable, diagnostics);
if (expression == null && checkedVariable.Kind != BoundKind.DiscardExpression)
{
expression = node;
......
......@@ -230,69 +230,6 @@ internal TypeSymbol CreateErrorType(string name = "")
return new ExtendedErrorTypeSymbol(this.Compilation, name, arity: 0, errorInfo: null, unreported: false);
}
private static bool RequiresGettingValue(BindValueKind kind)
{
switch (kind)
{
case BindValueKind.RValue:
case BindValueKind.RValueOrMethodGroup:
case BindValueKind.CompoundAssignment:
case BindValueKind.IncrementDecrement:
return true;
case BindValueKind.RefOrOut:
case BindValueKind.AddressOf:
case BindValueKind.Assignment:
case BindValueKind.RefReturn:
return false;
default:
throw ExceptionUtilities.UnexpectedValue(kind);
}
}
private static bool RequiresSettingValue(BindValueKind kind)
{
switch (kind)
{
case BindValueKind.RValue:
case BindValueKind.RValueOrMethodGroup:
return false;
case BindValueKind.CompoundAssignment:
case BindValueKind.IncrementDecrement:
case BindValueKind.RefOrOut:
case BindValueKind.AddressOf:
case BindValueKind.Assignment:
case BindValueKind.RefReturn:
return true;
default:
throw ExceptionUtilities.UnexpectedValue(kind);
}
}
private static bool RequiresAddressableValue(BindValueKind kind)
{
switch (kind)
{
case BindValueKind.RValue:
case BindValueKind.RValueOrMethodGroup:
case BindValueKind.CompoundAssignment:
case BindValueKind.IncrementDecrement:
case BindValueKind.Assignment:
return false;
case BindValueKind.RefOrOut:
case BindValueKind.AddressOf:
case BindValueKind.RefReturn:
return true;
default:
throw ExceptionUtilities.UnexpectedValue(kind);
}
}
/// <summary>
/// Bind the expression and verify the expression matches the combination of lvalue and
/// rvalue requirements given by valueKind. If the expression was bound successfully, but
......@@ -2147,7 +2084,7 @@ private bool RefMustBeObeyed(bool isDelegateCreation, ArgumentSyntax argumentSyn
{
case BoundKind.PropertyAccess:
case BoundKind.IndexerAccess:
return CheckIsVariable(argumentSyntax, arg, BindValueKind.RefOrOut, false, diagnostics);
return CheckValueKind(argumentSyntax, arg, BindValueKind.RefOrOut, false, diagnostics);
}
}
......@@ -3746,7 +3683,7 @@ private BoundExpression MakeBadExpressionForObjectCreation(ObjectCreationExpress
BoundKind boundMemberKind = boundMember.Kind;
SyntaxKind rhsKind = namedAssignment.Right.Kind();
bool isRhsNestedInitializer = rhsKind == SyntaxKind.ObjectInitializerExpression || rhsKind == SyntaxKind.CollectionInitializerExpression;
BindValueKind valueKind = isRhsNestedInitializer ? BindValueKind.RValue : BindValueKind.Assignment;
BindValueKind valueKind = isRhsNestedInitializer ? BindValueKind.RValue : BindValueKind.Assignable;
ImmutableArray<BoundExpression> arguments = ImmutableArray<BoundExpression>.Empty;
ImmutableArray<string> argumentNamesOpt = default(ImmutableArray<string>);
......@@ -3818,7 +3755,7 @@ private BoundExpression MakeBadExpressionForObjectCreation(ObjectCreationExpress
// 2) CS0200 (ERR_AssgReadonlyProp)
Debug.Assert(Flags.Includes(CSharp.BinderFlags.ObjectInitializerMember));
if (!CheckValueKind(boundMember, valueKind, diagnostics))
if (!CheckValueKind(boundMember.Syntax, boundMember, valueKind, checkingReceiver: false, diagnostics: diagnostics))
{
hasErrors = true;
resultKind = isRhsNestedInitializer ? LookupResultKind.NotAValue : LookupResultKind.NotAVariable;
......@@ -5802,11 +5739,10 @@ private static void CombineExtensionMethodArguments(BoundExpression receiver, An
if (!hasError && fieldSymbol.IsFixed && EnclosingNameofArgument == null)
{
TypeSymbol receiverType = receiver.Type;
hasError =
// Reflect errors that have been reported elsewhere...
(object)receiverType == null || !receiverType.IsValueType ||
// ...and errors that are reported here.
!CheckIsVariable(node, receiver, BindValueKind.FixedReceiver, checkingReceiver: false, diagnostics: diagnostics);
// Reflect errors that have been reported elsewhere...
hasError = (object)receiverType == null || !receiverType.IsValueType;
if (!hasError)
{
var isFixedStatementExpression = SyntaxFacts.IsFixedStatementExpression(node);
......@@ -5815,9 +5751,14 @@ private static void CombineExtensionMethodArguments(BoundExpression receiver, An
if (IsNonMoveableVariable(receiver, out accessedLocalOrParameterOpt) == isFixedStatementExpression && !isInsideNameof)
{
Error(diagnostics, isFixedStatementExpression ? ErrorCode.ERR_FixedNotNeeded : ErrorCode.ERR_FixedBufferNotFixed, node);
hasErrors = true;
hasErrors = hasError = true;
}
}
if (!hasError)
{
hasError = !CheckValueKind(node, receiver, BindValueKind.FixedReceiver, checkingReceiver: false, diagnostics: diagnostics);
}
}
ConstantValue constantValueOpt = null;
......
......@@ -75,7 +75,7 @@ private BoundExpression BindCompoundAssignment(AssignmentExpressionSyntax node,
}
}
if (left.Kind == BoundKind.EventAccess && !CheckEventValueKind((BoundEventAccess)left, BindValueKind.Assignment, diagnostics))
if (left.Kind == BoundKind.EventAccess && !CheckEventValueKind((BoundEventAccess)left, BindValueKind.Assignable, diagnostics))
{
// If we're in a place where the event can be assigned, then continue so that we give errors
// about the types and operator not lining up. Otherwise, just report that the event can't
......@@ -2102,7 +2102,7 @@ internal bool IsNonMoveableVariable(BoundExpression expr, out Symbol accessedLoc
}
var unusedDiagnostics = DiagnosticBag.GetInstance();
bool receiverIsLValue = CheckValueKind(receiver, BindValueKind.AddressOf, unusedDiagnostics);
bool receiverIsLValue = CheckValueKind(receiver.Syntax, receiver, BindValueKind.AddressOf, checkingReceiver: false, diagnostics: unusedDiagnostics);
unusedDiagnostics.Free();
if (!receiverIsLValue)
......@@ -2437,7 +2437,7 @@ private static BindValueKind GetBinaryAssignmentKind(SyntaxKind kind)
switch (kind)
{
case SyntaxKind.SimpleAssignmentExpression:
return BindValueKind.Assignment;
return BindValueKind.Assignable;
case SyntaxKind.AddAssignmentExpression:
case SyntaxKind.AndAssignmentExpression:
case SyntaxKind.DivideAssignmentExpression:
......@@ -3439,7 +3439,11 @@ private BoundExpression BindConditionalOperator(ConditionalExpressionSyntax node
BoundExpression condition = BindBooleanExpression(node.Condition, diagnostics);
var valKind = isRef ? BindValueKind.RefOrOut : BindValueKind.RValue;
var valKind = BindValueKind.RValue;
if (isRef)
{
valKind |= BindValueKind.RefersToLocation;
}
BoundExpression trueExpr = BindValue(whenTrue, diagnostics, valKind);
BoundExpression falseExpr = BindValue(whenFalse, diagnostics, valKind);
......
......@@ -39,6 +39,7 @@
<Compile Include="Binder\AliasAndExternAliasDirective.cs" />
<Compile Include="Binder\AliasAndUsingDirective.cs" />
<Compile Include="Binder\Binder.cs" />
<Compile Include="Binder\Binder.ValueChecks.cs" />
<Compile Include="Binder\Binder.OverflowChecks.cs" />
<Compile Include="Binder\Binder.QueryTranslationState.cs" />
<Compile Include="Binder\Binder.QueryUnboundLambdaState.cs" />
......
......@@ -646,6 +646,24 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Cannot assign to {0} &apos;{1}&apos; because it is a readonly variable.
/// </summary>
internal static string ERR_AssignReadonlyNotField {
get {
return ResourceManager.GetString("ERR_AssignReadonlyNotField", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot assign to a member of {0} &apos;{1}&apos; because it is a readonly variable.
/// </summary>
internal static string ERR_AssignReadonlyNotField2 {
get {
return ResourceManager.GetString("ERR_AssignReadonlyNotField2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The type parameter &apos;{0}&apos; cannot be used with the &apos;as&apos; operator because it does not have a class type constraint nor a &apos;class&apos; constraint.
/// </summary>
......@@ -8062,6 +8080,24 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Cannot use {0} &apos;{1}&apos; as a ref or out value because it is a readonly variable.
/// </summary>
internal static string ERR_RefReadonlyNotField {
get {
return ResourceManager.GetString("ERR_RefReadonlyNotField", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Members of {0} &apos;{1}&apos; cannot be used as a ref or out value because it is a readonly variable.
/// </summary>
internal static string ERR_RefReadonlyNotField2 {
get {
return ResourceManager.GetString("ERR_RefReadonlyNotField2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A static readonly field cannot be used as a ref or out value (except in a static constructor).
/// </summary>
......@@ -8180,7 +8216,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to Cannot return or a member of parameter &apos;{0}&apos; by reference because it is not a ref or out parameter.
/// Looks up a localized string similar to Cannot return by reference a member of parameter &apos;{0}&apos; by reference because it is not a ref or out parameter.
/// </summary>
internal static string ERR_RefReturnParameter2 {
get {
......@@ -8242,6 +8278,24 @@ 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.
/// </summary>
internal static string ERR_RefReturnReadonlyNotField {
get {
return ResourceManager.GetString("ERR_RefReturnReadonlyNotField", resourceCulture);
}
}
/// <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.
/// </summary>
internal static string ERR_RefReturnReadonlyNotField2 {
get {
return ResourceManager.GetString("ERR_RefReturnReadonlyNotField2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A static readonly field cannot be returned by reference.
/// </summary>
......
......@@ -855,12 +855,6 @@
<data name="ERR_ArgsInvalid" xml:space="preserve">
<value>The __arglist construct is valid only within a variable argument method</value>
</data>
<data name="ERR_AssgReadonly" xml:space="preserve">
<value>A readonly field cannot be assigned to (except in a constructor or a variable initializer)</value>
</data>
<data name="ERR_RefReadonly" xml:space="preserve">
<value>A readonly field cannot be used as a ref or out value (except in a constructor)</value>
</data>
<data name="ERR_PtrExpected" xml:space="preserve">
<value>The * or -&gt; operator must be applied to a pointer</value>
</data>
......@@ -2779,12 +2773,36 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep
<data name="ERR_ExpectedVerbatimLiteral" xml:space="preserve">
<value>Keyword, identifier, or string expected after verbatim specifier: @</value>
</data>
<data name="ERR_AssgReadonly2" xml:space="preserve">
<value>Members of readonly field '{0}' cannot be modified (except in a constructor or a variable initializer)</value>
<data name="ERR_RefReadonly" xml:space="preserve">
<value>A readonly field cannot be used as a ref or out value (except in a constructor)</value>
</data>
<data name="ERR_RefReadonly2" xml:space="preserve">
<value>Members of readonly field '{0}' cannot be used as a ref or out value (except in a constructor)</value>
</data>
<data name="ERR_AssgReadonly" xml:space="preserve">
<value>A readonly field cannot be assigned to (except in a constructor or a variable initializer)</value>
</data>
<data name="ERR_AssgReadonly2" xml:space="preserve">
<value>Members of readonly field '{0}' cannot be modified (except in a constructor or a variable initializer)</value>
</data>
<data name="ERR_RefReadonlyNotField" xml:space="preserve">
<value>Cannot use {0} '{1}' as a ref or out value because it is a readonly variable</value>
</data>
<data name="ERR_RefReadonlyNotField2" xml:space="preserve">
<value>Members of {0} '{1}' cannot be used as a ref or out value because it is a readonly variable</value>
</data>
<data name="ERR_AssignReadonlyNotField" xml:space="preserve">
<value>Cannot assign to {0} '{1}' because it is a readonly variable</value>
</data>
<data name="ERR_AssignReadonlyNotField2" xml:space="preserve">
<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>
</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>
</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>
</data>
......@@ -4796,7 +4814,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<value>Cannot return a parameter by reference '{0}' because it is not a ref or out parameter</value>
</data>
<data name="ERR_RefReturnParameter2" xml:space="preserve">
<value>Cannot return or a member of parameter '{0}' by reference because it is not a ref or out parameter</value>
<value>Cannot return by reference a member of parameter '{0}' by reference because it is not a ref or out parameter</value>
</data>
<data name="ERR_RefReturnLocal" xml:space="preserve">
<value>Cannot return local '{0}' by reference because it is not a ref local</value>
......
......@@ -582,7 +582,9 @@ private void EmitArgument(BoundExpression argument, RefKind refKind)
else
{
var temp = EmitAddress(argument, AddressKind.Writeable);
Debug.Assert(temp == null, "passing args byref should not clone them into temps");
// Dynamic is allowed to be passed by reference, via a temp.
Debug.Assert(temp == null || argument.Type.IsDynamic(), "passing args byref should not clone them into temps");
}
}
......
......@@ -1468,5 +1468,12 @@ internal enum ErrorCode
ERR_RefConditionalNeedsTwoRefs = 8402,
ERR_RefConditionalDifferentTypes = 8403,
ERR_BadParameterModifiers = 8404,
ERR_RefReadonlyNotField = 8406,
ERR_RefReadonlyNotField2 = 8407,
ERR_AssignReadonlyNotField = 8408,
ERR_AssignReadonlyNotField2 = 8409,
ERR_RefReturnReadonlyNotField = 8410,
ERR_RefReturnReadonlyNotField2 = 8411,
}
}
\ No newline at end of file
......@@ -805,34 +805,34 @@ public struct S
}";
var comp = CreateCompilationWithMscorlib(text, references: s_attributeRefs);
comp.VerifyDiagnostics(
// (31,2): error CS8208: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// (31,2): error CS8408: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// [TupleElementNames(new[] { "a", "b" })]
Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""a"", ""b"" })").WithLocation(31, 2),
// (5,2): error CS8208: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// (5,2): error CS8408: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// [TupleElementNames(new[] { "a", "b" })]
Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""a"", ""b"" })").WithLocation(5, 2),
// (18,10): error CS8208: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// (18,10): error CS8408: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// [TupleElementNames(new[] { "x" })]ValueTuple<T> args);
Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""x"" })").WithLocation(18, 10),
// (11,6): error CS8208: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// (11,6): error CS8408: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// [TupleElementNames(new[] { "x", "y" })]
Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""x"", ""y"" })").WithLocation(11, 6),
// (14,14): error CS8208: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// (14,14): error CS8408: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// [return: TupleElementNames(new string[] { null, null })]
Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, "TupleElementNames(new string[] { null, null })").WithLocation(14, 14),
// (15,36): error CS8208: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// (15,36): error CS8408: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// public ValueTuple<int, int> M([TupleElementNames(new string[] { null})] ValueTuple x) => (0, 0);
Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, "TupleElementNames(new string[] { null})").WithLocation(15, 36),
// (20,6): error CS0592: Attribute 'TupleElementNames' is not valid on this declaration type. It is only valid on 'class, struct, property, indexer, field, parameter, return' declarations.
// [TupleElementNames(new[] { "y" })]
Diagnostic(ErrorCode.ERR_AttributeOnBadSymbolType, "TupleElementNames").WithArguments("TupleElementNames", "class, struct, property, indexer, field, parameter, return").WithLocation(20, 6),
// (27,6): error CS8208: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// (27,6): error CS8408: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// [TupleElementNames(new[] { "a", "b" })]
Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, @"TupleElementNames(new[] { ""a"", ""b"" })").WithLocation(27, 6),
// (28,33): error CS8208: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// (28,33): error CS8408: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// public (int x, int y) this[[TupleElementNames](int a, int b) t] => t;
Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, "TupleElementNames").WithLocation(28, 33),
// (8,6): error CS8208: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// (8,6): error CS8408: Cannot reference 'System.Runtime.CompilerServices.TupleElementNamesAttribute' explicitly. Use the tuple syntax to define tuple names.
// [TupleElementNames(new string[] { null, null })]
Diagnostic(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, "TupleElementNames(new string[] { null, null })").WithLocation(8, 6));
}
......
......@@ -98,5 +98,183 @@ class Program
Diagnostic(ErrorCode.ERR_BadParameterModifiers, "in").WithArguments("in", "ref").WithLocation(13, 37)
);
}
[Fact]
public void ReadonlyParamCannotAssign()
{
var text = @"
class Program
{
static void M(in int arg1, in (int Alice, int Bob) arg2)
{
arg1 = 1;
arg2.Alice = 2;
arg1 ++;
arg2.Alice --;
arg1 += 1;
arg2.Alice -= 2;
}
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (6,9): error CS8408: Cannot assign to variable 'ref readonly int' because it is a readonly variable
// arg1 = 1;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "arg1").WithArguments("variable", "ref readonly int").WithLocation(6, 9),
// (7,9): error CS8409: Cannot assign to a member of variable 'ref readonly (int Alice, int Bob)' because it is a readonly variable
// arg2.Alice = 2;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "arg2.Alice").WithArguments("variable", "ref readonly (int Alice, int Bob)").WithLocation(7, 9),
// (9,9): error CS8408: Cannot assign to variable 'ref readonly int' because it is a readonly variable
// arg1 ++;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "arg1").WithArguments("variable", "ref readonly int").WithLocation(9, 9),
// (10,9): error CS8409: Cannot assign to a member of variable 'ref readonly (int Alice, int Bob)' because it is a readonly variable
// arg2.Alice --;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "arg2.Alice").WithArguments("variable", "ref readonly (int Alice, int Bob)").WithLocation(10, 9),
// (12,9): error CS8408: Cannot assign to variable 'ref readonly int' because it is a readonly variable
// arg1 += 1;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "arg1").WithArguments("variable", "ref readonly int").WithLocation(12, 9),
// (13,9): error CS8409: Cannot assign to a member of variable 'ref readonly (int Alice, int Bob)' because it is a readonly variable
// arg2.Alice -= 2;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "arg2.Alice").WithArguments("variable", "ref readonly (int Alice, int Bob)").WithLocation(13, 9)
);
}
[Fact]
public void ReadonlyParamCannotAssignByref()
{
var text = @"
class Program
{
static void M(in int arg1, in (int Alice, int Bob) arg2)
{
ref var y = ref arg1;
ref int a = ref arg2.Alice;
}
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (6,25): error CS8406: Cannot use variable 'ref readonly int' as a ref or out value because it is a readonly variable
// ref var y = ref arg1;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "arg1").WithArguments("variable", "ref readonly int").WithLocation(6, 25),
// (7,25): error CS8407: Members of variable 'ref readonly (int Alice, int Bob)' cannot be used as a ref or out value because it is a readonly variable
// ref int a = ref arg2.Alice;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField2, "arg2.Alice").WithArguments("variable", "ref readonly (int Alice, int Bob)").WithLocation(7, 25)
);
}
[Fact]
public void ReadonlyParamCannotTakePtr()
{
var text = @"
class Program
{
unsafe static void M(in int arg1, in (int Alice, int Bob) arg2)
{
int* a = & arg1;
int* b = & arg2.Alice;
fixed(int* c = & arg1)
{
}
fixed(int* d = & arg2.Alice)
{
}
}
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.UnsafeReleaseDll);
comp.VerifyDiagnostics(
// (6,20): error CS0211: Cannot take the address of the given expression
// int* a = & arg1;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "arg1").WithLocation(6, 20),
// (7,20): error CS0211: Cannot take the address of the given expression
// int* b = & arg2.Alice;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "arg2.Alice").WithLocation(7, 20),
// (9,26): error CS0211: Cannot take the address of the given expression
// fixed(int* c = & arg1)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "arg1").WithLocation(9, 26),
// (13,26): error CS0211: Cannot take the address of the given expression
// fixed(int* d = & arg2.Alice)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "arg2.Alice").WithLocation(13, 26)
);
}
[Fact]
public void ReadonlyParamCannotReturnByOrdinaryRef()
{
var text = @"
class Program
{
static ref int M(in int arg1, in (int Alice, int Bob) arg2)
{
bool b = true;
if (b)
{
return ref arg1;
}
else
{
return ref arg2.Alice;
}
}
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (10,24): error CS8406: Cannot use variable 'ref readonly int' as a ref or out value because it is a readonly variable
// return ref arg1;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "arg1").WithArguments("variable", "ref readonly int").WithLocation(10, 24),
// (14,24): error CS8407: Members of variable 'ref readonly (int Alice, int Bob)' cannot be used as a ref or out value because it is a readonly variable
// return ref arg2.Alice;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField2, "arg2.Alice").WithArguments("variable", "ref readonly (int Alice, int Bob)").WithLocation(14, 24)
);
}
[Fact]
public void ReadonlyParamCanReturnByRefReadonly()
{
var text = @"
class Program
{
static ref readonly int M(in int arg1, in (int Alice, int Bob) arg2)
{
bool b = true;
if (b)
{
return ref arg1;
}
else
{
return ref arg2.Alice;
}
}
}
";
var comp = CompileAndVerify(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular, verify: false);
comp.VerifyIL("Program.M", @"
{
// Code size 12 (0xc)
.maxstack 1
IL_0000: ldc.i4.1
IL_0001: brfalse.s IL_0005
IL_0003: ldarg.0
IL_0004: ret
IL_0005: ldarg.1
IL_0006: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_000b: ret
}");
}
}
}
......@@ -663,8 +663,10 @@ static void Main()
Diagnostic(ErrorCode.ERR_RefReturnLocal, "local1").WithArguments("local1").WithLocation(15, 27),
// (15,39): error CS8168: Cannot return local 'local2' by reference because it is not a ref local
// return ref b? ref local1: ref local2;
Diagnostic(ErrorCode.ERR_RefReturnLocal, "local2").WithArguments("local2").WithLocation(15, 39)
Diagnostic(ErrorCode.ERR_RefReturnLocal, "local2").WithArguments("local2").WithLocation(15, 39),
// (15,20): error CS8156: An expression cannot be used in this context because it may not be returned by reference
// return ref b? ref local1: ref local2;
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "b? ref local1: ref local2").WithLocation(15, 20)
);
}
......@@ -695,7 +697,10 @@ static void Main()
comp.VerifyEmitDiagnostics(
// (14,37): error CS8168: Cannot return local 'local2' by reference because it is not a ref local
// return ref b? ref val1: ref local2;
Diagnostic(ErrorCode.ERR_RefReturnLocal, "local2").WithArguments("local2").WithLocation(14, 37)
Diagnostic(ErrorCode.ERR_RefReturnLocal, "local2").WithArguments("local2").WithLocation(14, 37),
// (14,20): error CS8156: An expression cannot be used in this context because it may not be returned by reference
// return ref b? ref val1: ref local2;
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "b? ref val1: ref local2").WithLocation(14, 20)
);
}
......@@ -731,7 +736,47 @@ struct S1
comp.VerifyEmitDiagnostics(
// (14,38): error CS8168: Cannot return local 'local2' by reference because it is not a ref local
// return ref (b? ref val1: ref local2).x;
Diagnostic(ErrorCode.ERR_RefReturnLocal, "local2").WithArguments("local2").WithLocation(14, 38)
Diagnostic(ErrorCode.ERR_RefReturnLocal, "local2").WithArguments("local2").WithLocation(14, 38),
// (14,20): error CS8156: An expression cannot be used in this context because it may not be returned by reference
// return ref (b? ref val1: ref local2).x;
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "(b? ref val1: ref local2).x").WithLocation(14, 20)
);
}
[Fact]
public void TestRefConditionalUnsafeToReturn4()
{
var source = @"
class C
{
static void Main()
{
}
ref int Test()
{
S1 local2 = default(S1);
bool b = true;
ref var temp = ref (b? ref val1: ref local2).x;
return ref temp;
}
static S1 val1;
struct S1
{
public int x;
}
}
";
var comp = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe);
comp.VerifyEmitDiagnostics(
// (15,20): error CS8157: Cannot return 'temp' by reference because it was initialized to a value that cannot be returned by reference
// return ref temp;
Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "temp").WithArguments("temp").WithLocation(15, 20)
);
}
......
......@@ -42,5 +42,508 @@ .maxstack 2
IL_000c: ret
}");
}
[Fact]
public void BindingInvalidRefRoCombination()
{
var text = @"
class Program
{
// should be a syntax error
// just make sure binder is ok with this
static ref readonly ref int M(int x)
{
return ref M(x);
}
// should be a syntax error
// just make sure binder is ok with this
static readonly int M1(int x)
{
return ref M(x);
}
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (6,25): error CS1031: Type expected
// static ref readonly ref int M(int x)
Diagnostic(ErrorCode.ERR_TypeExpected, "ref").WithLocation(6, 25),
// (13,25): error CS0106: The modifier 'readonly' is not valid for this item
// static readonly int M1(int x)
Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("readonly").WithLocation(13, 25),
// (15,20): error CS0120: An object reference is required for the non-static field, method, or property 'Program.M(int)'
// return ref M(x);
Diagnostic(ErrorCode.ERR_ObjectRequired, "M").WithArguments("Program.M(int)").WithLocation(15, 20),
// (15,9): error CS8149: By-reference returns may only be used in methods that return by reference
// return ref M(x);
Diagnostic(ErrorCode.ERR_MustNotHaveRefReturn, "return").WithLocation(15, 9)
);
}
[Fact]
public void ReadonlyReturnCannotAssign()
{
var text = @"
class Program
{
static void Test()
{
M() = 1;
M1().Alice = 2;
M() ++;
M1().Alice --;
M() += 1;
M1().Alice -= 2;
}
static ref readonly int M() => throw null;
static ref readonly (int Alice, int Bob) M1() => throw null;
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (6,9): error CS8408: Cannot assign to method 'Program.M()' because it is a readonly variable
// M() = 1;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "M()").WithArguments("method", "Program.M()").WithLocation(6, 9),
// (7,9): error CS8409: Cannot assign to a member of method 'Program.M1()' because it is a readonly variable
// M1().Alice = 2;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "M1().Alice").WithArguments("method", "Program.M1()").WithLocation(7, 9),
// (9,9): error CS8408: Cannot assign to method 'Program.M()' because it is a readonly variable
// M() ++;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "M()").WithArguments("method", "Program.M()").WithLocation(9, 9),
// (10,9): error CS8409: Cannot assign to a member of method 'Program.M1()' because it is a readonly variable
// M1().Alice --;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "M1().Alice").WithArguments("method", "Program.M1()").WithLocation(10, 9),
// (12,9): error CS8408: Cannot assign to method 'Program.M()' because it is a readonly variable
// M() += 1;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "M()").WithArguments("method", "Program.M()").WithLocation(12, 9),
// (13,9): error CS8409: Cannot assign to a member of method 'Program.M1()' because it is a readonly variable
// M1().Alice -= 2;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "M1().Alice").WithArguments("method", "Program.M1()").WithLocation(13, 9)
);
}
[Fact]
public void ReadonlyReturnCannotAssign1()
{
var text = @"
class Program
{
static void Test()
{
P = 1;
P1.Alice = 2;
P ++;
P1.Alice --;
P += 1;
P1.Alice -= 2;
}
static ref readonly int P => throw null;
static ref readonly (int Alice, int Bob) P1 => throw null;
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (6,9): error CS8408: Cannot assign to property 'Program.P' because it is a readonly variable
// P = 1;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "P").WithArguments("property", "Program.P").WithLocation(6, 9),
// (7,9): error CS8409: Cannot assign to a member of property 'Program.P1' because it is a readonly variable
// P1.Alice = 2;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "P1.Alice").WithArguments("property", "Program.P1").WithLocation(7, 9),
// (9,9): error CS8408: Cannot assign to property 'Program.P' because it is a readonly variable
// P ++;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "P").WithArguments("property", "Program.P").WithLocation(9, 9),
// (10,9): error CS8409: Cannot assign to a member of property 'Program.P1' because it is a readonly variable
// P1.Alice --;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "P1.Alice").WithArguments("property", "Program.P1").WithLocation(10, 9),
// (12,9): error CS8408: Cannot assign to property 'Program.P' because it is a readonly variable
// P += 1;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "P").WithArguments("property", "Program.P").WithLocation(12, 9),
// (13,9): error CS8409: Cannot assign to a member of property 'Program.P1' because it is a readonly variable
// P1.Alice -= 2;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "P1.Alice").WithArguments("property", "Program.P1").WithLocation(13, 9)
);
}
[Fact]
public void ReadonlyReturnCannotAssignByref()
{
var text = @"
class Program
{
static void Test()
{
ref var y = ref M();
ref int a = ref M1.Alice;
ref var y1 = ref P;
ref int a1 = ref P1.Alice;
}
static ref readonly int M() => throw null;
static ref readonly (int Alice, int Bob) M1() => throw null;
static ref readonly int P => throw null;
static ref readonly (int Alice, int Bob) P1 => throw null;
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (6,25): error CS8406: Cannot use method 'Program.M()' as a ref or out value because it is a readonly variable
// ref var y = ref M();
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "M()").WithArguments("method", "Program.M()").WithLocation(6, 25),
// (7,25): error CS0119: 'Program.M1()' is a method, which is not valid in the given context
// ref int a = ref M1.Alice;
Diagnostic(ErrorCode.ERR_BadSKunknown, "M1").WithArguments("Program.M1()", "method").WithLocation(7, 25),
// (8,26): error CS8406: Cannot use property 'Program.P' as a ref or out value because it is a readonly variable
// ref var y1 = ref P;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "P").WithArguments("property", "Program.P").WithLocation(8, 26),
// (9,26): error CS8407: Members of property 'Program.P1' cannot be used as a ref or out value because it is a readonly variable
// ref int a1 = ref P1.Alice;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField2, "P1.Alice").WithArguments("property", "Program.P1").WithLocation(9, 26)
);
}
[Fact]
public void ReadonlyReturnCannotTakePtr()
{
var text = @"
class Program
{
unsafe static void Test()
{
int* a = & M();
int* b = & M1().Alice;
int* a1 = & P;
int* b2 = & P1.Alice;
fixed(int* c = & M())
{
}
fixed(int* d = & M1().Alice)
{
}
fixed(int* c = & P)
{
}
fixed(int* d = & P1.Alice)
{
}
}
static ref readonly int M() => throw null;
static ref readonly (int Alice, int Bob) M1() => throw null;
static ref readonly int P => throw null;
static ref readonly (int Alice, int Bob) P1 => throw null;
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.UnsafeReleaseDll);
comp.VerifyDiagnostics(
// (6,20): error CS0211: Cannot take the address of the given expression
// int* a = & M();
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M()").WithLocation(6, 20),
// (7,20): error CS0211: Cannot take the address of the given expression
// int* b = & M1().Alice;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M1().Alice").WithLocation(7, 20),
// (9,21): error CS0211: Cannot take the address of the given expression
// int* a1 = & P;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P").WithLocation(9, 21),
// (10,21): error CS0211: Cannot take the address of the given expression
// int* b2 = & P1.Alice;
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P1.Alice").WithLocation(10, 21),
// (12,26): error CS0211: Cannot take the address of the given expression
// fixed(int* c = & M())
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M()").WithLocation(12, 26),
// (16,26): error CS0211: Cannot take the address of the given expression
// fixed(int* d = & M1().Alice)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "M1().Alice").WithLocation(16, 26),
// (20,26): error CS0211: Cannot take the address of the given expression
// fixed(int* c = & P)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P").WithLocation(20, 26),
// (24,26): error CS0211: Cannot take the address of the given expression
// fixed(int* d = & P1.Alice)
Diagnostic(ErrorCode.ERR_InvalidAddrOp, "P1.Alice").WithLocation(24, 26)
);
}
[Fact]
public void ReadonlyReturnCannotReturnByOrdinaryRef()
{
var text = @"
class Program
{
static ref int Test()
{
bool b = true;
if (b)
{
if (b)
{
return ref M();
}
else
{
return ref M1().Alice;
}
}
else
{
if (b)
{
return ref P;
}
else
{
return ref P1.Alice;
}
}
}
static ref readonly int M() => throw null;
static ref readonly (int Alice, int Bob) M1() => throw null;
static ref readonly int P => throw null;
static ref readonly (int Alice, int Bob) P1 => throw null;
}
";
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
// 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
// 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
// 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
// return ref P1.Alice;
Diagnostic(ErrorCode.ERR_RefReadonlyNotField2, "P1.Alice").WithArguments("property", "Program.P1").WithLocation(27, 28)
);
}
[Fact]
public void ReadonlyReturnCanReturnByRefReadonly()
{
var text = @"
class Program
{
static ref readonly int Test()
{
bool b = true;
if (b)
{
if (b)
{
return ref M();
}
else
{
return ref M1().Alice;
}
}
else
{
if (b)
{
return ref P;
}
else
{
return ref P1.Alice;
}
}
}
static ref readonly int M() => throw null;
static ref readonly (int Alice, int Bob) M1() => throw null;
static ref readonly int P => throw null;
static ref readonly (int Alice, int Bob) P1 => throw null;
}
";
var comp = CompileAndVerify(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular, verify: false);
comp.VerifyIL("Program.Test", @"
{
// Code size 45 (0x2d)
.maxstack 1
.locals init (bool V_0) //b
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: brfalse.s IL_0019
IL_0005: ldloc.0
IL_0006: brfalse.s IL_000e
IL_0008: call ""ref readonly int Program.M()""
IL_000d: ret
IL_000e: call ""ref readonly (int Alice, int Bob) Program.M1()""
IL_0013: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_0018: ret
IL_0019: ldloc.0
IL_001a: brfalse.s IL_0022
IL_001c: call ""ref readonly int Program.P.get""
IL_0021: ret
IL_0022: call ""ref readonly (int Alice, int Bob) Program.P1.get""
IL_0027: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_002c: ret
}");
}
[Fact]
public void ReadonlyFieldCanReturnByRefReadonly()
{
var text = @"
class Program
{
ref readonly int Test()
{
bool b = true;
if (b)
{
if (b)
{
return ref F;
}
else
{
return ref F1.Alice;
}
}
else
{
if (b)
{
return ref S1.F;
}
else
{
return ref S2.F1.Alice;
}
}
}
readonly int F = 1;
static readonly (int Alice, int Bob) F1 = (2,3);
readonly S S1 = new S();
static readonly S S2 = new S();
struct S
{
public readonly int F;
public readonly (int Alice, int Bob) F1;
}
}
";
var comp = CompileAndVerify(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular, verify: false);
//PROTOTYPE(readonlyRef): correct emit is NYI. We should not make copies when returning r/o fields
comp.VerifyIL("Program.Test", @"
{
// Code size 70 (0x46)
.maxstack 1
.locals init (bool V_0, //b
int V_1,
System.ValueTuple<int, int> V_2,
int V_3,
System.ValueTuple<int, int> V_4)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: brfalse.s IL_0020
IL_0005: ldloc.0
IL_0006: brfalse.s IL_0012
IL_0008: ldarg.0
IL_0009: ldfld ""int Program.F""
IL_000e: stloc.1
IL_000f: ldloca.s V_1
IL_0011: ret
IL_0012: ldsfld ""(int Alice, int Bob) Program.F1""
IL_0017: stloc.2
IL_0018: ldloca.s V_2
IL_001a: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_001f: ret
IL_0020: ldloc.0
IL_0021: brfalse.s IL_0032
IL_0023: ldarg.0
IL_0024: ldfld ""Program.S Program.S1""
IL_0029: ldfld ""int Program.S.F""
IL_002e: stloc.3
IL_002f: ldloca.s V_3
IL_0031: ret
IL_0032: ldsfld ""Program.S Program.S2""
IL_0037: ldfld ""(int Alice, int Bob) Program.S.F1""
IL_003c: stloc.s V_4
IL_003e: ldloca.s V_4
IL_0040: ldflda ""int System.ValueTuple<int, int>.Item1""
IL_0045: ret
}");
}
[Fact]
public void ReadonlyReturnByRefReadonlyLocalSafety()
{
var text = @"
class Program
{
ref readonly int Test()
{
bool b = true;
int local = 42;
if (b)
{
return ref M(ref local);
}
else
{
return ref M1(out local).Alice;
}
}
static ref readonly int M(ref int x) => throw null;
static ref readonly (int Alice, int Bob) M1(out int x) => throw null;
}
";
var comp = CreateCompilationWithMscorlib45(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (11,30): error CS8168: Cannot return local 'local' by reference because it is not a ref local
// return ref M(ref local);
Diagnostic(ErrorCode.ERR_RefReturnLocal, "local").WithArguments("local").WithLocation(11, 30),
// (11,24): error CS8164: Cannot return by reference a result of 'Program.M(ref int)' because the argument passed to parameter 'x' cannot be returned by reference
// return ref M(ref local);
Diagnostic(ErrorCode.ERR_RefReturnCall, "M(ref local)").WithArguments("Program.M(ref int)", "x").WithLocation(11, 24),
// (15,31): error CS8168: Cannot return local 'local' by reference because it is not a ref local
// return ref M1(out local).Alice;
Diagnostic(ErrorCode.ERR_RefReturnLocal, "local").WithArguments("local").WithLocation(15, 31),
// (15,24): error CS8165: Cannot return by reference a member of result of 'Program.M1(out int)' because the argument passed to parameter 'x' cannot be returned by reference
// return ref M1(out local).Alice;
Diagnostic(ErrorCode.ERR_RefReturnCall2, "M1(out local)").WithArguments("Program.M1(out int)", "x").WithLocation(15, 24)
);
}
}
}
......@@ -2836,6 +2836,7 @@ static void Main()
);
}
[Fact]
[WorkItem(16947, "https://github.com/dotnet/roslyn/issues/16947")]
public void Dynamic001()
{
......@@ -2853,18 +2854,28 @@ public void M()
public static ref dynamic F(ref dynamic d)
{
// this is ok
F1(ref d.Length);
// this is an error
return ref d.Length;
}
public static void F1(ref dynamic d)
{
}
}
";
CreateCompilationWithMscorlib45AndCSruntime(source).VerifyEmitDiagnostics(
// (14,20): error CS8156: An expression cannot be used in this context because it may not be returned by reference
// (18,20): error CS8156: An expression cannot be used in this context because it may not be returned by reference
// return ref d.Length;
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "d.Length").WithLocation(14, 20)
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "d.Length").WithLocation(18, 20)
);
}
[Fact]
[WorkItem(16947, "https://github.com/dotnet/roslyn/issues/16947")]
public void Dynamic002()
{
......@@ -2882,19 +2893,27 @@ public void M()
public static ref dynamic F(ref dynamic d)
{
// this is ok
F1(ref d[0]);
return ref d[0];
}
public static void F1(ref dynamic d)
{
}
}
";
CreateCompilationWithMscorlib45AndCSruntime(source).VerifyEmitDiagnostics(
// (14,20): error CS8156: An expression cannot be used in this context because it may not be returned by reference
// (17,20): error CS8156: An expression cannot be used in this context because it may not be returned by reference
// return ref d[0];
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "d[0]").WithLocation(14, 20)
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "d[0]").WithLocation(17, 20)
);
}
[Fact]
[WorkItem(16947, "https://github.com/dotnet/roslyn/issues/16947")]
public void Dynamic003()
{
......@@ -2924,13 +2943,12 @@ public void M()
";
CreateCompilationWithMscorlib45AndCSruntime(source).VerifyEmitDiagnostics(
// (14,28): error CS8156: An expression cannot be used in this context because it may not be returned by reference
// (14,26): error CS8156: An expression cannot be used in this context because it may not be returned by reference
// return ref G(ref d.Length);
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "d.Length").WithLocation(14, 28),
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "d.Length").WithLocation(14, 26),
// (14,20): error CS8164: Cannot return by reference a result of 'C.G(ref dynamic)' because the argument passed to parameter 'd' cannot be returned by reference
// return ref G(ref d.Length);
Diagnostic(ErrorCode.ERR_RefReturnCall, "G(ref d.Length)").WithArguments("C.G(ref dynamic)", "d").WithLocation(14, 20)
Diagnostic(ErrorCode.ERR_RefReturnCall, "G(ref d.Length)").WithArguments("C.G(ref dynamic)", "d")
);
}
......
......@@ -3896,7 +3896,7 @@ public ValueTuple(T1 item1, T2 item2)
";
var comp = CreateCompilationWithMscorlib(source, assemblyName: "comp");
comp.VerifyDiagnostics(
// (11,13): error CS8207: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference?
// (11,13): error CS8407: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference?
// void M2((int a, int b) y)
Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(int a, int b)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(11, 13),
// (7,39): error CS8128: Member 'Item1' was not found on type 'ValueTuple<T1, T2>' from assembly 'comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
......@@ -14242,7 +14242,7 @@ public TestAttribute((int, string) val)
// (6,38): error CS8129: Type of the tuple element cannot be infered from '<null>'.
// var x0 = new {tuple = (null, null)};
Diagnostic(ErrorCode.Unknown, "null").WithArguments("<null>").WithLocation(6, 38),
// (8,31): error CS8207: Cannot implicitly convert tuple expression to 'ValueType'
// (8,31): error CS8407: Cannot implicitly convert tuple expression to 'ValueType'
// System.ValueType x1 = (null, "1");
Diagnostic(ErrorCode.Unknown, @"(null, ""1"")").WithArguments("System.ValueType").WithLocation(8, 31),
// (11,20): error CS1503: Argument 1: cannot convert from '<tuple>' to '(int, string)'
......@@ -14278,25 +14278,25 @@ public TestAttribute((int, string) val)
// (29,20): error CS0655: 'Val' is not a valid named attribute argument because it is not a valid attribute parameter type
// [TestAttribute(Val = ("12", "12"))]
Diagnostic(ErrorCode.ERR_BadNamedAttributeArgumentType, "Val").WithArguments("Val").WithLocation(29, 20),
// (34,14): error CS8207: Cannot implicitly convert tuple expression to 'int'
// (34,14): error CS8407: Cannot implicitly convert tuple expression to 'int'
// V1 = (13, null),
Diagnostic(ErrorCode.Unknown, "(13, null)").WithArguments("int").WithLocation(34, 14),
// (35,14): error CS8207: Cannot implicitly convert tuple expression to 'int'
// (35,14): error CS8407: Cannot implicitly convert tuple expression to 'int'
// V2 = (14, "14"),
Diagnostic(ErrorCode.Unknown, @"(14, ""14"")").WithArguments("int").WithLocation(35, 14),
// (36,14): error CS8207: Cannot implicitly convert tuple expression to 'int'
// (36,14): error CS8407: Cannot implicitly convert tuple expression to 'int'
// V3 = ("15", "15"),
Diagnostic(ErrorCode.Unknown, @"(""15"", ""15"")").WithArguments("int").WithLocation(36, 14),
// (41,28): error CS8129: Type of the tuple element cannot be infered from '<null>'.
// var x = (16, (16 , null));
Diagnostic(ErrorCode.Unknown, "null").WithArguments("<null>").WithLocation(41, 28),
// (44,17): error CS8207: Cannot implicitly convert tuple expression to 'TypedReference'
// (44,17): error CS8407: Cannot implicitly convert tuple expression to 'TypedReference'
// var u = __refvalue((17, null), (int, string));
Diagnostic(ErrorCode.Unknown, "__refvalue((17, null), (int, string))").WithArguments("System.TypedReference").WithLocation(44, 17),
// (45,17): error CS8207: Cannot implicitly convert tuple expression to 'TypedReference'
// (45,17): error CS8407: Cannot implicitly convert tuple expression to 'TypedReference'
// var v = __refvalue((18, "18"), (int, string));
Diagnostic(ErrorCode.Unknown, @"__refvalue((18, ""18""), (int, string))").WithArguments("System.TypedReference").WithLocation(45, 17),
// (46,17): error CS8207: Cannot implicitly convert tuple expression to 'TypedReference'
// (46,17): error CS8407: Cannot implicitly convert tuple expression to 'TypedReference'
// var w = __refvalue(("19", "19"), (int, string));
Diagnostic(ErrorCode.Unknown, @"__refvalue((""19"", ""19""), (int, string))").WithArguments("System.TypedReference").WithLocation(46, 17)
);
......
......@@ -258,13 +258,21 @@ unsafe struct S
{
fixed int F[G];
fixed int G[1];
fixed int F1[(new S()).G];
}
";
// CONSIDER: Dev11 reports CS1666 (ERR_FixedBufferNotFixed), but that's no more helpful.
CreateCompilationWithMscorlib(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (6,18): error CS1666: You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.
// fixed int F1[(new S()).G];
Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "(new S()).G").WithLocation(6, 18),
// (4,17): error CS0120: An object reference is required for the non-static field, method, or property 'S.G'
// fixed int F[G];
Diagnostic(ErrorCode.ERR_ObjectRequired, "G").WithArguments("S.G"));
Diagnostic(ErrorCode.ERR_ObjectRequired, "G").WithArguments("S.G").WithLocation(4, 17),
// (4,17): error CS1666: You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.
// fixed int F[G];
Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "G").WithLocation(4, 17)
);
}
[Fact]
......@@ -275,15 +283,23 @@ public void FixedSizeBufferInFixedSizeBufferSize_Cycle()
unsafe struct S
{
fixed int F[F];
fixed int G[default(S).G];
}
";
// CONSIDER: Dev11 also reports CS0110 (ERR_CircConstValue), but Roslyn doesn't regard this as a cycle:
// F has no initializer, so it has no constant value, so the constant value of F is "null" - not "the
// constant value of F" (i.e. cyclic).
CreateCompilationWithMscorlib(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (5,17): error CS1666: You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.
// fixed int G[default(S).G];
Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "default(S).G").WithLocation(5, 17),
// (4,17): error CS0120: An object reference is required for the non-static field, method, or property 'S.F'
// fixed int F[F];
Diagnostic(ErrorCode.ERR_ObjectRequired, "F").WithArguments("S.F"));
Diagnostic(ErrorCode.ERR_ObjectRequired, "F").WithArguments("S.F").WithLocation(4, 17),
// (4,17): error CS1666: You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.
// fixed int F[F];
Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "F").WithLocation(4, 17)
);
}
[Fact]
......
......@@ -378,31 +378,35 @@ public IEnumerable<int> B(int C, int D)
CreateCompilationWithMscorlib(source).VerifyDiagnostics(
// (9,26): error CS1026: ) expected
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.ERR_CloseParenExpected, "return"),
Diagnostic(ErrorCode.ERR_CloseParenExpected, "return").WithLocation(9, 26),
// (9,26): error CS1026: ) expected
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.ERR_CloseParenExpected, "return"),
Diagnostic(ErrorCode.ERR_CloseParenExpected, "return").WithLocation(9, 26),
// (9,35): error CS1002: ; expected
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.ERR_SemicolonExpected, ")"),
Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(9, 35),
// (9,35): error CS1513: } expected
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.ERR_RbraceExpected, ")"),
Diagnostic(ErrorCode.ERR_RbraceExpected, ")").WithLocation(9, 35),
// (9,47): error CS1002: ; expected
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.ERR_SemicolonExpected, ")"),
Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(9, 47),
// (9,47): error CS1513: } expected
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.ERR_RbraceExpected, ")"),
Diagnostic(ErrorCode.ERR_RbraceExpected, ")").WithLocation(9, 47),
// (9,20): error CS0103: The name 'yield' does not exist in the current context
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.ERR_NameNotInContext, "yield").WithArguments("yield"),
Diagnostic(ErrorCode.ERR_NameNotInContext, "yield").WithArguments("yield").WithLocation(9, 20),
// (9,26): error CS1622: Cannot return a value from an iterator. Use the yield return statement to return a value, or yield break to end the iteration.
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.ERR_ReturnInIterator, "return"),
Diagnostic(ErrorCode.ERR_ReturnInIterator, "return").WithLocation(9, 26),
// (9,33): error CS0029: Cannot implicitly convert type 'int' to 'System.Collections.Generic.IEnumerable<int>'
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.ERR_NoImplicitConv, "+D").WithArguments("int", "System.Collections.Generic.IEnumerable<int>").WithLocation(9, 33),
// (9,37): warning CS0162: Unreachable code detected
// lock ((C + yield return +D).ToString())
Diagnostic(ErrorCode.WRN_UnreachableCode, "ToString"));
Diagnostic(ErrorCode.WRN_UnreachableCode, "ToString").WithLocation(9, 37)
);
}
[Fact]
......
......@@ -2783,10 +2783,10 @@ static void Main()
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe);
compilation.VerifyDiagnostics(
// (9,18): error CS8207: It is not legal to use the type 'dynamic' in a pattern.
// (9,18): error CS8407: It is not legal to use the type 'dynamic' in a pattern.
// case dynamic x: // error 1
Diagnostic(ErrorCode.ERR_PatternDynamicType, "dynamic"),
// (12,18): error CS8207: It is not legal to use the type 'dynamic' in a pattern.
// (12,18): error CS8407: It is not legal to use the type 'dynamic' in a pattern.
// if (d is dynamic y) {} // error 2
Diagnostic(ErrorCode.ERR_PatternDynamicType, "dynamic").WithLocation(12, 18)
);
......
......@@ -236,22 +236,21 @@ public struct S1
}";
var comp = CreateCompilationRef(text);
comp.VerifyDiagnostics(
// (18,24): error CS8168: Cannot return local 'l' by reference because it is not a ref local
// return ref l;
Diagnostic(ErrorCode.ERR_RefReturnLocal, "l").WithArguments("l").WithLocation(18, 24),
// (28,24): error CS8169: Cannot return a member of local 'l' by reference because it is not a ref local
// return ref l.x;
Diagnostic(ErrorCode.ERR_RefReturnLocal2, "l").WithArguments("l").WithLocation(28, 24),
// (37,24): error CS8166: Cannot return a parameter by reference 'arg1' because it is not a ref or out parameter
// return ref arg1;
Diagnostic(ErrorCode.ERR_RefReturnParameter, "arg1").WithArguments("arg1").WithLocation(37, 24),
// (46,24): error CS8167: Cannot return or a member of parameter 'arg2' by reference because it is not a ref or out parameter
// return ref arg2.x;
Diagnostic(ErrorCode.ERR_RefReturnParameter2, "arg2").WithArguments("arg2").WithLocation(46, 24)
// (18,24): error CS8168: Cannot return local 'l' by reference because it is not a ref local
// return ref l;
Diagnostic(ErrorCode.ERR_RefReturnLocal, "l").WithArguments("l").WithLocation(18, 24),
// (28,24): error CS8169: Cannot return a member of local 'l' by reference because it is not a ref local
// return ref l.x;
Diagnostic(ErrorCode.ERR_RefReturnLocal2, "l").WithArguments("l").WithLocation(28, 24),
// (37,24): error CS8166: Cannot return a parameter by reference 'arg1' because it is not a ref or out parameter
// return ref arg1;
Diagnostic(ErrorCode.ERR_RefReturnParameter, "arg1").WithArguments("arg1").WithLocation(37, 24),
// (46,24): error CS8167: Cannot return by reference a member of parameter 'arg2' by reference because it is not a ref or out parameter
// return ref arg2.x;
Diagnostic(ErrorCode.ERR_RefReturnParameter2, "arg2").WithArguments("arg2").WithLocation(46, 24)
);
}
[Fact]
public void RefReadonlyLocal()
{
......@@ -507,36 +506,36 @@ static Test()
}";
var comp = CreateCompilationRef(text);
comp.VerifyDiagnostics(
// (33,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(33, 33),
// (39,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(39, 33),
// (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 CS8160: A readonly field cannot be returned by reference
// return ref i1;
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 CS8162: Members of readonly field 'Test.i2' cannot be returned by reference
// return ref i2.x;
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 CS8161: A static readonly field cannot be returned by reference
// return ref s1;
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 CS8163: Fields of static readonly field 'Test.s2' cannot be returned by reference
// return ref s2.x;
Diagnostic(ErrorCode.ERR_RefReturnReadonlyStatic2, "s2.x").WithArguments("Test.s2").WithLocation(93, 24)
// (33,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(33, 33),
// (39,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(39, 33),
// (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)
// return ref i1;
Diagnostic(ErrorCode.ERR_RefReadonly, "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)
// return ref i2.x;
Diagnostic(ErrorCode.ERR_RefReadonly2, "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)
// return ref s1;
Diagnostic(ErrorCode.ERR_RefReadonlyStatic, "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)
// return ref s2.x;
Diagnostic(ErrorCode.ERR_RefReadonlyStatic2, "s2.x").WithArguments("Test.s2").WithLocation(93, 24)
);
}
......@@ -788,31 +787,30 @@ public struct S1
}";
var comp = CreateCompilationRef(text);
comp.VerifyDiagnostics(
// (19,24): error CS8157: Cannot return 'r' by reference because it was initialized to a value that cannot be returned by reference
// return ref r; //1
Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "r").WithArguments("r").WithLocation(19, 24),
// (25,24): error CS8158: Cannot return by reference a member of 'r' because it was initialized to a value that cannot be returned by reference
// return ref r.x; //2
Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal2, "r").WithArguments("r").WithLocation(25, 24),
// (34,24): error CS0103: The name 'r' does not exist in the current context
// return ref r;
Diagnostic(ErrorCode.ERR_NameNotInContext, "r").WithArguments("r").WithLocation(34, 24),
// (43,24): error CS8157: Cannot return 'valid' by reference because it was initialized to a value that cannot be returned by reference
// return ref valid; //4
Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "valid").WithArguments("valid").WithLocation(43, 24),
// (52,24): error CS8157: Cannot return 'r' by reference because it was initialized to a value that cannot be returned by reference
// return ref r; //5
Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "r").WithArguments("r").WithLocation(52, 24),
// (18,30): error CS0165: Use of unassigned local variable 'r'
// ref char r = ref r;
Diagnostic(ErrorCode.ERR_UseDefViolation, "r").WithArguments("r").WithLocation(18, 30),
// (24,28): error CS0165: Use of unassigned local variable 'r'
// ref S1 r = ref r;
Diagnostic(ErrorCode.ERR_UseDefViolation, "r").WithArguments("r").WithLocation(24, 28),
// (49,45): error CS0165: Use of unassigned local variable 'r'
// ref char r = ref Foo(ref a, ref r);
Diagnostic(ErrorCode.ERR_UseDefViolation, "r").WithArguments("r").WithLocation(49, 45)
// (19,24): error CS8157: Cannot return 'r' by reference because it was initialized to a value that cannot be returned by reference
// return ref r; //1
Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "r").WithArguments("r").WithLocation(19, 24),
// (25,24): error CS8158: Cannot return by reference a member of 'r' because it was initialized to a value that cannot be returned by reference
// return ref r.x; //2
Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal2, "r").WithArguments("r").WithLocation(25, 24),
// (34,24): error CS0103: The name 'r' does not exist in the current context
// return ref r;
Diagnostic(ErrorCode.ERR_NameNotInContext, "r").WithArguments("r").WithLocation(34, 24),
// (43,24): error CS8157: Cannot return 'valid' by reference because it was initialized to a value that cannot be returned by reference
// return ref valid; //4
Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "valid").WithArguments("valid").WithLocation(43, 24),
// (52,24): error CS8157: Cannot return 'r' by reference because it was initialized to a value that cannot be returned by reference
// return ref r; //5
Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "r").WithArguments("r").WithLocation(52, 24),
// (18,30): error CS0165: Use of unassigned local variable 'r'
// ref char r = ref r;
Diagnostic(ErrorCode.ERR_UseDefViolation, "r").WithArguments("r").WithLocation(18, 30),
// (24,28): error CS0165: Use of unassigned local variable 'r'
// ref S1 r = ref r;
Diagnostic(ErrorCode.ERR_UseDefViolation, "r").WithArguments("r").WithLocation(24, 28),
// (49,45): error CS0165: Use of unassigned local variable 'r'
// ref char r = ref Foo(ref a, ref r);
Diagnostic(ErrorCode.ERR_UseDefViolation, "r").WithArguments("r").WithLocation(49, 45)
);
}
......
......@@ -15484,22 +15484,15 @@ static void Main()
public readonly S _s2;
}";
CreateCompilationWithMscorlib(text, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (18,9): error CS1708: Fixed size buffers can only be accessed through locals or fields
// (18,9): error CS1666: You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.
// myC.UnsafeMethod().name[3] = 'a'; // CS1708
Diagnostic(ErrorCode.ERR_FixedNeedsLvalue, "myC.UnsafeMethod().name"),
// (19,9): error CS0198: A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)
// C._s1.name[3] = 'a'; // CS1708
Diagnostic(ErrorCode.ERR_AssgReadonlyStatic, "C._s1.name"),
Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "myC.UnsafeMethod().name").WithLocation(18, 9),
// (19,9): error CS1666: You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.
// C._s1.name[3] = 'a'; // CS1708
Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "C._s1.name"),
// (20,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
// myC._s2.name[3] = 'a'; // CS1708
Diagnostic(ErrorCode.ERR_AssgReadonly, "myC._s2.name"),
Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "C._s1.name").WithLocation(19, 9),
// (20,9): error CS1666: You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.
// myC._s2.name[3] = 'a'; // CS1708
Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "myC._s2.name")
);
Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "myC._s2.name").WithLocation(20, 9));
}
[Fact, WorkItem(543995, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543995"), WorkItem(544258, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544258")]
......
......@@ -19524,7 +19524,7 @@ .module ForwarderModule.dll
var compilation = CreateCompilationWithCustomILSource(userCode, forwardingIL, appendDefaultHeader: false);
compilation.VerifyDiagnostics(
// (8,29): error CS8206: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Destination.TestClass' to multiple assemblies: 'Destination1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' and 'Destination2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
// (8,29): error CS8406: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Destination.TestClass' to multiple assemblies: 'Destination1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' and 'Destination2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
// new Destination.TestClass();
Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "TestClass").WithArguments("ForwarderModule.dll", "Forwarder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Destination.TestClass", "Destination1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Destination2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(8, 29),
// (8,29): error CS0234: The type or namespace name 'TestClass' does not exist in the namespace 'Destination' (are you missing an assembly reference?)
......@@ -19587,7 +19587,7 @@ .module ForwarderModule.dll
var compilation = CreateCompilationWithCustomILSource(userCode, forwardingIL, appendDefaultHeader: false);
compilation.VerifyDiagnostics(
// (8,29): error CS8206: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Destination.TestClass' to multiple assemblies: 'Destination1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'Destination2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// (8,29): error CS8406: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Destination.TestClass' to multiple assemblies: 'Destination1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'Destination2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// new Destination.TestClass();
Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "TestClass").WithArguments("ForwarderModule.dll", "Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Destination.TestClass", "Destination1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Destination2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(8, 29),
// (8,29): error CS0234: The type or namespace name 'TestClass' does not exist in the namespace 'Destination' (are you missing an assembly reference?)
......@@ -19657,7 +19657,7 @@ .module CModule.dll
var referenceC2 = CompileIL(codeC2, appendDefaultHeader: false);
CreateCompilationWithMscorlib(codeA, references: new MetadataReference[] { referenceB, referenceC2 }, assemblyName: "A").VerifyDiagnostics(
// (10,13): error CS8206: Module 'CModule.dll' in assembly 'C, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'C.ClassC' to multiple assemblies: 'D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// (10,13): error CS8406: Module 'CModule.dll' in assembly 'C, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'C.ClassC' to multiple assemblies: 'D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// ClassB.MethodB(null);
Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "ClassB.MethodB").WithArguments("CModule.dll", "C, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "C.ClassC", "D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"));
}
......@@ -19759,7 +19759,7 @@ .module ForwarderModule.dll
var ilModule = GetILModuleReference(ilSource, appendDefaultHeader: false);
CreateCompilationWithMscorlib(string.Empty, references: new MetadataReference[] { ilModule }, assemblyName: "Forwarder").VerifyDiagnostics(
// error CS8206: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Testspace.TestType' to multiple assemblies: 'D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// error CS8406: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Testspace.TestType' to multiple assemblies: 'D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies).WithArguments("ForwarderModule.dll", "Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Testspace.TestType", "D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 1));
}
......@@ -19836,7 +19836,7 @@ public static void Main()
assemblyName: "UserAssembly");
userCompilation.VerifyDiagnostics(
// (8,37): error CS8206: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Testspace.TestType' to multiple assemblies: 'D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// (8,37): error CS8406: Module 'ForwarderModule.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Testspace.TestType' to multiple assemblies: 'D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// var obj = new Testspace.TestType();
Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "TestType").WithArguments("ForwarderModule.dll", "Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Testspace.TestType", "D1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "D2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(8, 37),
// (8,37): error CS0234: The type or namespace name 'TestType' does not exist in the namespace 'Testspace' (are you missing an assembly reference?)
......@@ -19901,7 +19901,7 @@ public static void Main()
assemblyName: "UserAssembly");
userCompilation.VerifyDiagnostics(
// (8,37): error CS8206: Module 'module12L.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Testspace.TestType' to multiple assemblies: 'D3, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D4, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// (8,37): error CS8406: Module 'module12L.dll' in assembly 'Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'Testspace.TestType' to multiple assemblies: 'D3, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'D4, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// var obj = new Testspace.TestType();
Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "TestType").WithArguments("module12L.dll", "Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Testspace.TestType", "D3, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "D4, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"),
// (8,37): error CS0234: The type or namespace name 'TestType' does not exist in the namespace 'Testspace' (are you missing an assembly reference?)
......@@ -19981,7 +19981,7 @@ public void MethodA(ClassC obj)
}";
CreateCompilationWithMscorlib(codeA, references: new MetadataReference[] { referenceB, referenceC2, referenceD, referenceE }, assemblyName: "A").VerifyDiagnostics(
// (11,13): error CS8206: Module 'C.dll' in assembly 'C, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'C.ClassC' to multiple assemblies: 'D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'E, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// (11,13): error CS8406: Module 'C.dll' in assembly 'C, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is forwarding the type 'C.ClassC' to multiple assemblies: 'D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' and 'E, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// ClassB.MethodB(obj);
Diagnostic(ErrorCode.ERR_TypeForwardedToMultipleAssemblies, "ClassB.MethodB").WithArguments("C.dll", "C, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "C.ClassC", "D, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "E, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(11, 13));
}
......
......@@ -610,12 +610,13 @@ private static BoundStatement BindStatement(Binder binder, StatementSyntax synta
private static bool IsAssignableExpression(Binder binder, BoundExpression expression)
{
//PROTOTYPE(readonlyRefs): is this comment still valid?
// NOTE: Surprisingly, binder.CheckValueKind will return true (!) for readonly fields
// in contexts where they cannot be assigned - it simply reports a diagnostic.
// Presumably, this is done to avoid producing a confusing error message about the
// field not being an lvalue.
var diagnostics = DiagnosticBag.GetInstance();
var result = binder.CheckValueKind(expression, Binder.BindValueKind.Assignment, diagnostics) &&
var result = binder.CheckValueKind(expression.Syntax, expression, Binder.BindValueKind.Assignable, checkingReceiver: false, diagnostics: diagnostics) &&
!diagnostics.HasAnyErrors();
diagnostics.Free();
return result;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册