提交 20e488c5 编写于 作者: V vsadov

Added support for byref local functions.

上级 5f090eb7
......@@ -4552,7 +4552,16 @@ private void ParseVariableDeclarators(TypeSyntax type, VariableFlags flags, Sepa
(parentKind != SyntaxKind.CompilationUnit || IsScript);
LocalFunctionStatementSyntax localFunction;
ParseVariableDeclarators(type, flags, variables, variableDeclarationsExpected, false, default(SyntaxList<SyntaxToken>), out localFunction);
ParseVariableDeclarators(
type,
flags,
variables,
variableDeclarationsExpected,
false,
default(SyntaxList<SyntaxToken>),
default(SyntaxToken),
out localFunction);
Debug.Assert(localFunction == null);
}
......@@ -4563,9 +4572,19 @@ private void ParseVariableDeclarators(TypeSyntax type, VariableFlags flags, Sepa
bool variableDeclarationsExpected,
bool allowLocalFunctions,
SyntaxList<SyntaxToken> mods,
SyntaxToken refTokenOpt,
out LocalFunctionStatementSyntax localFunction)
{
variables.Add(this.ParseVariableDeclarator(type, flags, isFirst: true, allowLocalFunctions: allowLocalFunctions, mods: mods, localFunction: out localFunction));
variables.Add(
this.ParseVariableDeclarator(
type,
flags,
isFirst: true,
allowLocalFunctions: allowLocalFunctions,
mods: mods,
refTokenOpt: refTokenOpt,
localFunction: out localFunction));
if (localFunction != null)
{
// ParseVariableDeclarator returns null, so it is not added to variables
......@@ -4582,7 +4601,15 @@ private void ParseVariableDeclarators(TypeSyntax type, VariableFlags flags, Sepa
else if (this.CurrentToken.Kind == SyntaxKind.CommaToken)
{
variables.AddSeparator(this.EatToken(SyntaxKind.CommaToken));
variables.Add(this.ParseVariableDeclarator(type, flags, isFirst: false, allowLocalFunctions: false, mods: mods, localFunction: out localFunction));
variables.Add(
this.ParseVariableDeclarator(
type,
flags,
isFirst: false,
allowLocalFunctions: false,
mods: mods,
refTokenOpt: refTokenOpt,
localFunction: out localFunction));
}
else if (!variableDeclarationsExpected || this.SkipBadVariableListTokens(variables, SyntaxKind.CommaToken) == PostSkipAction.Abort)
{
......@@ -4700,6 +4727,7 @@ private static bool CanReuseVariableDeclarator(CSharp.Syntax.VariableDeclaratorS
bool isFirst,
bool allowLocalFunctions,
SyntaxList<SyntaxToken> mods,
SyntaxToken refTokenOpt,
out LocalFunctionStatementSyntax localFunction,
bool isExpressionContext = false)
{
......@@ -4835,7 +4863,7 @@ private static bool CanReuseVariableDeclarator(CSharp.Syntax.VariableDeclaratorS
case SyntaxKind.LessThanToken:
if (allowLocalFunctions && isFirst)
{
localFunction = TryParseLocalFunctionStatementBody(mods, parentType, name);
localFunction = TryParseLocalFunctionStatementBody(mods, refTokenOpt, parentType, name);
if (localFunction != null)
{
return null;
......@@ -4846,7 +4874,7 @@ private static bool CanReuseVariableDeclarator(CSharp.Syntax.VariableDeclaratorS
case SyntaxKind.OpenParenToken:
if (allowLocalFunctions && isFirst)
{
localFunction = TryParseLocalFunctionStatementBody(mods, parentType, name);
localFunction = TryParseLocalFunctionStatementBody(mods, refTokenOpt, parentType, name);
if (localFunction != null)
{
return null;
......@@ -8100,7 +8128,7 @@ private StatementSyntax ParseLocalDeclarationStatement()
TypeSyntax type;
LocalFunctionStatementSyntax localFunction;
this.ParseDeclaration(out type, variables, true, mods.ToTokenList(), out localFunction);
this.ParseDeclaration(out type, variables, true, mods.ToTokenList(), refKeyword, out localFunction);
if (localFunction != null)
{
Debug.Assert(variables.Count == 0);
......@@ -8134,7 +8162,7 @@ private StatementSyntax ParseLocalDeclarationStatement()
SeparatedSyntaxListBuilder<VariableDeclaratorSyntax> variables)
{
LocalFunctionStatementSyntax localFunction;
ParseDeclaration(out type, variables, false, default(SyntaxList<SyntaxToken>), out localFunction);
ParseDeclaration(out type, variables, false, default(SyntaxList<SyntaxToken>), default(SyntaxToken), out localFunction);
Debug.Assert(localFunction == null);
}
......@@ -8143,6 +8171,7 @@ private StatementSyntax ParseLocalDeclarationStatement()
SeparatedSyntaxListBuilder<VariableDeclaratorSyntax> variables,
bool allowLocalFunctions,
SyntaxList<SyntaxToken> mods,
SyntaxToken refTokenOpt,
out LocalFunctionStatementSyntax localFunction)
{
type = allowLocalFunctions ? ParseReturnType() : this.ParseType(false);
......@@ -8161,6 +8190,7 @@ private StatementSyntax ParseLocalDeclarationStatement()
variables,
variableDeclarationsExpected: true,
allowLocalFunctions: allowLocalFunctions,
refTokenOpt: refTokenOpt,
mods: mods,
localFunction: out localFunction);
_termState = saveTerm;
......@@ -8259,7 +8289,11 @@ private static bool IsAdditionalLocalFunctionModifier(SyntaxKind kind)
}
}
private LocalFunctionStatementSyntax TryParseLocalFunctionStatementBody(SyntaxList<SyntaxToken> modifiers, TypeSyntax type, SyntaxToken identifier)
private LocalFunctionStatementSyntax TryParseLocalFunctionStatementBody(
SyntaxList<SyntaxToken> modifiers,
SyntaxToken refTokenOpt,
TypeSyntax type,
SyntaxToken identifier)
{
// This may potentially be an ambiguous parse until very far into the token stream, so we may have to backtrack.
// For example, "await x()" is ambiguous at the current point of parsing (right now we're right after the x).
......@@ -8349,6 +8383,7 @@ private LocalFunctionStatementSyntax TryParseLocalFunctionStatementBody(SyntaxLi
var decl = _syntaxFactory.LocalFunctionStatement(
modifiers,
refTokenOpt,
type,
identifier,
typeParameterListOpt,
......
......@@ -14,16 +14,18 @@ Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.ExpressionBody
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.Identifier.get -> Microsoft.CodeAnalysis.SyntaxToken
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.Modifiers.get -> Microsoft.CodeAnalysis.SyntaxTokenList
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.ParameterList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.RefKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.ReturnType.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.SemicolonToken.get -> Microsoft.CodeAnalysis.SyntaxToken
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.TypeParameterList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.Update(Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterConstraintClauseSyntax> constraintClauses, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.Update(Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterConstraintClauseSyntax> constraintClauses, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithBody(Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithConstraintClauses(Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterConstraintClauseSyntax> constraintClauses) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithExpressionBody(Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithIdentifier(Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithModifiers(Microsoft.CodeAnalysis.SyntaxTokenList modifiers) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithParameterList(Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithRefKeyword(Microsoft.CodeAnalysis.SyntaxToken refKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithReturnType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithSemicolonToken(Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax.WithTypeParameterList(Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
......@@ -35,7 +37,7 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.DocumentationComment(params M
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LocalFunctionStatement(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LocalFunctionStatement(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, string identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LocalFunctionStatement(Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterConstraintClauseSyntax> constraintClauses, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LocalFunctionStatement(Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterConstraintClauseSyntax> constraintClauses, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.LocalFunctionStatement(Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax returnType, Microsoft.CodeAnalysis.SyntaxToken identifier, Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterListSyntax typeParameterList, Microsoft.CodeAnalysis.CSharp.Syntax.ParameterListSyntax parameterList, Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.TypeParameterConstraintClauseSyntax> constraintClauses, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.LocalFunctionStatementSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.XmlCrefAttribute(Microsoft.CodeAnalysis.CSharp.Syntax.CrefSyntax cref) -> Microsoft.CodeAnalysis.CSharp.Syntax.XmlCrefAttributeSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.XmlCrefAttribute(Microsoft.CodeAnalysis.CSharp.Syntax.CrefSyntax cref, Microsoft.CodeAnalysis.CSharp.SyntaxKind quoteKind) -> Microsoft.CodeAnalysis.CSharp.Syntax.XmlCrefAttributeSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.XmlElement(Microsoft.CodeAnalysis.CSharp.Syntax.XmlNameSyntax name, Microsoft.CodeAnalysis.SyntaxList<Microsoft.CodeAnalysis.CSharp.Syntax.XmlNodeSyntax> content) -> Microsoft.CodeAnalysis.CSharp.Syntax.XmlElementSyntax
......
......@@ -21,6 +21,7 @@ internal class LocalFunctionSymbol : MethodSymbol
private readonly ImmutableArray<TypeParameterSymbol> _typeParameters;
private ImmutableArray<ParameterSymbol> _parameters;
private ImmutableArray<TypeParameterConstraintClause> _lazyTypeParameterConstraints;
private readonly RefKind _refKind;
private TypeSymbol _returnType;
private bool _isVararg;
private TypeSymbol _iteratorElementType;
......@@ -39,6 +40,7 @@ internal class LocalFunctionSymbol : MethodSymbol
{
_syntax = syntax;
_containingSymbol = containingSymbol;
_refKind = syntax.RefKeyword.Kind().GetRefKind();
_declarationModifiers =
DeclarationModifiers.Private |
......@@ -142,7 +144,7 @@ internal override RefKind RefKind
{
get
{
return RefKind.None;
return _refKind;
}
}
......
......@@ -17,7 +17,7 @@ internal sealed class SourceMemberMethodSymbol : SourceMethodSymbol
private readonly TypeSymbol _explicitInterfaceType;
private readonly string _name;
private readonly bool _isExpressionBodied;
private readonly RefKind refKind;
private readonly RefKind _refKind;
private ImmutableArray<MethodSymbol> _lazyExplicitInterfaceImplementations;
private ImmutableArray<CustomModifier> _lazyReturnTypeCustomModifiers;
......@@ -132,7 +132,7 @@ internal sealed class SourceMemberMethodSymbol : SourceMethodSymbol
CheckModifiersForBody(location, diagnostics);
}
this.refKind = syntax.RefKeyword.Kind().GetRefKind();
_refKind = syntax.RefKeyword.Kind().GetRefKind();
var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);
if (info != null)
......@@ -576,7 +576,7 @@ public override ImmutableArray<ParameterSymbol> Parameters
internal override RefKind RefKind
{
get { return this.refKind; }
get { return _refKind; }
}
public override TypeSymbol ReturnType
......
......@@ -1647,6 +1647,9 @@
<Node Name="LocalFunctionStatementSyntax" Base="StatementSyntax">
<Kind Name="LocalFunctionStatement"/>
<Field Name="Modifiers" Type="SyntaxList&lt;SyntaxToken&gt;"/>
<Field Name="RefKeyword" Type="SyntaxToken" Optional="true">
<Kind Name="RefKeyword"/>
</Field>
<Field Name="ReturnType" Type="TypeSyntax"/>
<Field Name="Identifier" Type="SyntaxToken">
<PropertyComment>
......
......@@ -1486,5 +1486,191 @@ .maxstack 4
IL_00a7: ret
}");
}
[Fact]
public void RefReturnArrayAccessNested()
{
var text = @"
class Program
{
static ref int M()
{
ref int N()
{
return ref (new int[1])[0];
}
return ref N();
}
}
";
CompileAndVerifyExperimental(text).VerifyIL("Program.M()", @"
{
// Code size 6 (0x6)
.maxstack 1
IL_0000: call ""ref int Program.<M>g__N0_0()""
IL_0005: ret
}").VerifyIL("Program.<M>g__N0_0", @"
{
// Code size 13 (0xd)
.maxstack 2
IL_0000: ldc.i4.1
IL_0001: newarr ""int""
IL_0006: ldc.i4.0
IL_0007: ldelema ""int""
IL_000c: ret
}");
}
[Fact]
public void RefReturnArrayAccessNested1()
{
var text = @"
class Program
{
static ref int M()
{
var arr = new int[1]{40};
ref int N()
{
ref int NN(ref int arg) => ref arg;
ref var r = ref NN(ref arr[0]);
r += 2;
return ref r;
}
return ref N();
}
static void Main()
{
System.Console.WriteLine(M());
}
}
";
CompileAndVerifyExperimental(text, expectedOutput: "42", verify: false).VerifyIL("Program.M()", @"
{
// Code size 34 (0x22)
.maxstack 5
.locals init (Program.<>c__DisplayClass0_0 V_0) //CS$<>8__locals0
IL_0000: ldloca.s V_0
IL_0002: initobj ""Program.<>c__DisplayClass0_0""
IL_0008: ldloca.s V_0
IL_000a: ldc.i4.1
IL_000b: newarr ""int""
IL_0010: dup
IL_0011: ldc.i4.0
IL_0012: ldc.i4.s 40
IL_0014: stelem.i4
IL_0015: stfld ""int[] Program.<>c__DisplayClass0_0.arr""
IL_001a: ldloca.s V_0
IL_001c: call ""ref int Program.<M>g__N0_0(ref Program.<>c__DisplayClass0_0)""
IL_0021: ret
}").VerifyIL("Program.<M>g__N0_0", @"
{
// Code size 24 (0x18)
.maxstack 4
IL_0000: ldarg.0
IL_0001: ldfld ""int[] Program.<>c__DisplayClass0_0.arr""
IL_0006: ldc.i4.0
IL_0007: ldelema ""int""
IL_000c: call ""ref int Program.<M>g__NN0_1(ref int)""
IL_0011: dup
IL_0012: dup
IL_0013: ldind.i4
IL_0014: ldc.i4.2
IL_0015: add
IL_0016: stind.i4
IL_0017: ret
}").VerifyIL("Program.<M>g__NN0_1", @"
{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
}
[Fact]
public void RefReturnArrayAccessNested2()
{
var text = @"
class Program
{
delegate ref int D();
static D M()
{
var arr = new int[1]{40};
ref int N()
{
ref int NN(ref int arg) => ref arg;
ref var r = ref NN(ref arr[0]);
r += 2;
return ref r;
}
return N;
}
static void Main()
{
System.Console.WriteLine(M()());
}
}
";
CompileAndVerifyExperimental(text, expectedOutput: "42", verify: false).VerifyIL("Program.M()", @"
{
// Code size 36 (0x24)
.maxstack 5
.locals init (Program.<>c__DisplayClass1_0 V_0) //CS$<>8__locals0
IL_0000: newobj ""Program.<>c__DisplayClass1_0..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldc.i4.1
IL_0008: newarr ""int""
IL_000d: dup
IL_000e: ldc.i4.0
IL_000f: ldc.i4.s 40
IL_0011: stelem.i4
IL_0012: stfld ""int[] Program.<>c__DisplayClass1_0.arr""
IL_0017: ldloc.0
IL_0018: ldftn ""ref int Program.<>c__DisplayClass1_0.<M>g__N0()""
IL_001e: newobj ""Program.D..ctor(object, System.IntPtr)""
IL_0023: ret
}").VerifyIL("Program.<>c__DisplayClass1_0.<M>g__N0()", @"
{
// Code size 24 (0x18)
.maxstack 4
IL_0000: ldarg.0
IL_0001: ldfld ""int[] Program.<>c__DisplayClass1_0.arr""
IL_0006: ldc.i4.0
IL_0007: ldelema ""int""
IL_000c: call ""ref int Program.<M>g__NN1_1(ref int)""
IL_0011: dup
IL_0012: dup
IL_0013: ldind.i4
IL_0014: ldc.i4.2
IL_0015: add
IL_0016: stind.i4
IL_0017: ret
}").VerifyIL("Program.<M>g__NN1_1(ref int)", @"
{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
}
}
}
......@@ -804,5 +804,111 @@ public struct S1
);
}
[Fact]
public void RefReturnNested()
{
var text = @"
public class Test
{
public static void Main()
{
ref char Foo(ref char a, ref char b)
{
// valid
return ref a;
}
char Foo1(ref char a, ref char b)
{
return ref b;
}
ref char Foo2(ref char c, ref char b)
{
return c;
}
}
}";
var comp = CreateExperimentalCompilationWithMscorlib45(text);
comp.VerifyDiagnostics(
// (14,13): error CS8894: By-reference returns may only be used in methods that return by reference
// return ref b;
Diagnostic(ErrorCode.ERR_MustNotHaveRefReturn, "return").WithLocation(14, 13),
// (19,13): error CS8895: By-value returns may only be used in methods that return by value
// return c;
Diagnostic(ErrorCode.ERR_MustHaveRefReturn, "return").WithLocation(19, 13),
// (6,18): warning CS0168: The variable 'Foo' is declared but never used
// ref char Foo(ref char a, ref char b)
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Foo").WithArguments("Foo").WithLocation(6, 18),
// (12,14): warning CS0168: The variable 'Foo1' is declared but never used
// char Foo1(ref char a, ref char b)
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Foo1").WithArguments("Foo1").WithLocation(12, 14),
// (17,18): warning CS0168: The variable 'Foo2' is declared but never used
// ref char Foo2(ref char c, ref char b)
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Foo2").WithArguments("Foo2").WithLocation(17, 18)
);
}
[Fact]
public void RefReturnNestedArrow()
{
var text = @"
public class Test
{
public static void Main()
{
// valid
ref char Foo(ref char a, ref char b) => ref a;
char Foo1(ref char a, ref char b) => ref b;
ref char Foo2(ref char c, ref char b) => c;
var arr = new int[1];
ref var r = ref arr[0];
ref char Moo1(ref char a, ref char b) => ref r;
char Moo3(ref char a, ref char b) => r;
}
}";
var comp = CreateExperimentalCompilationWithMscorlib45(text);
comp.VerifyDiagnostics(
// (9,50): error CS8894: By-reference returns may only be used in methods that return by reference
// char Foo1(ref char a, ref char b) => ref b;
Diagnostic(ErrorCode.ERR_MustNotHaveRefReturn, "b").WithLocation(9, 50),
// (11,50): error CS8895: By-value returns may only be used in methods that return by value
// ref char Foo2(ref char c, ref char b) => c;
Diagnostic(ErrorCode.ERR_MustHaveRefReturn, "c").WithLocation(11, 50),
// (16,54): error CS8940: Cannot use ref local 'r' inside an anonymous method, lambda expression, or query expression
// ref char Moo1(ref char a, ref char b) => ref r;
Diagnostic(ErrorCode.ERR_AnonDelegateCantUseLocal, "r").WithArguments("r").WithLocation(16, 54),
// (16,54): error CS8896: The return expression must be of type 'char' because this method returns by reference
// ref char Moo1(ref char a, ref char b) => ref r;
Diagnostic(ErrorCode.ERR_RefReturnMustHaveIdentityConversion, "r").WithArguments("char").WithLocation(16, 54),
// (17,46): error CS8940: Cannot use ref local 'r' inside an anonymous method, lambda expression, or query expression
// char Moo3(ref char a, ref char b) => r;
Diagnostic(ErrorCode.ERR_AnonDelegateCantUseLocal, "r").WithArguments("r").WithLocation(17, 46),
// (17,46): error CS0266: Cannot implicitly convert type 'int' to 'char'. An explicit conversion exists (are you missing a cast?)
// char Moo3(ref char a, ref char b) => r;
Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "r").WithArguments("int", "char").WithLocation(17, 46),
// (7,18): warning CS0168: The variable 'Foo' is declared but never used
// ref char Foo(ref char a, ref char b) => ref a;
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Foo").WithArguments("Foo").WithLocation(7, 18),
// (9,14): warning CS0168: The variable 'Foo1' is declared but never used
// char Foo1(ref char a, ref char b) => ref b;
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Foo1").WithArguments("Foo1").WithLocation(9, 14),
// (11,18): warning CS0168: The variable 'Foo2' is declared but never used
// ref char Foo2(ref char c, ref char b) => c;
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Foo2").WithArguments("Foo2").WithLocation(11, 18),
// (16,18): warning CS0168: The variable 'Moo1' is declared but never used
// ref char Moo1(ref char a, ref char b) => ref r;
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Moo1").WithArguments("Moo1").WithLocation(16, 18),
// (17,14): warning CS0168: The variable 'Moo3' is declared but never used
// char Moo3(ref char a, ref char b) => r;
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Moo3").WithArguments("Moo3").WithLocation(17, 14)
);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册