提交 05f6d3f5 编写于 作者: J Julien Couvreur 提交者: GitHub

Check for restricted types in deconstruction in async method (#15258)

上级 0d5e74c2
......@@ -745,6 +745,7 @@ private static void FlattenDeconstructVariables(ArrayBuilder<DeconstructionVaria
if (!isVar)
{
CheckRestrictedTypeInAsync(this.ContainingMemberOrLambda, declType, diagnostics, typeSyntax);
return new BoundLocal(designation, localSymbol, constantValueOpt: null, type: declType, hasErrors: hasErrors);
}
......
......@@ -2120,12 +2120,7 @@ private BoundExpression BindOutVariableArgument(DeclarationExpressionSyntax decl
return new OutVariablePendingInference(declarationExpression, localSymbol, null);
}
if (this.ContainingMemberOrLambda.Kind == SymbolKind.Method
&& ((MethodSymbol)this.ContainingMemberOrLambda).IsAsync
&& declType.IsRestrictedType())
{
Error(diagnostics, ErrorCode.ERR_BadSpecialByRefLocal, typeSyntax, declType);
}
CheckRestrictedTypeInAsync(this.ContainingMemberOrLambda, declType, diagnostics, typeSyntax);
return new BoundLocal(declarationExpression, localSymbol, constantValueOpt: null, type: declType);
}
......@@ -2159,6 +2154,21 @@ private BoundExpression BindOutVariableArgument(DeclarationExpressionSyntax decl
expressionVariableField, null, LookupResultKind.Viable, fieldType);
}
/// <summary>
/// Returns true if a bad special by ref local was found.
/// </summary>
internal static bool CheckRestrictedTypeInAsync(Symbol containingSymbol, TypeSymbol type, DiagnosticBag diagnostics, SyntaxNode syntax)
{
if (containingSymbol.Kind == SymbolKind.Method
&& ((MethodSymbol)containingSymbol).IsAsync
&& type.IsRestrictedType())
{
Error(diagnostics, ErrorCode.ERR_BadSpecialByRefLocal, syntax, type);
return true;
}
return false;
}
internal GlobalExpressionVariable LookupDeclaredField(SingleVariableDesignationSyntax variableDesignator)
{
return LookupDeclaredField(variableDesignator, variableDesignator.Identifier.ValueText);
......
......@@ -291,13 +291,9 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy
// Check for variable declaration errors.
hasErrors |= localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
if (this.ContainingMemberOrLambda.Kind == SymbolKind.Method
&& ((MethodSymbol)this.ContainingMemberOrLambda).IsAsync
&& declType.IsRestrictedType()
&& !hasErrors)
if (!hasErrors)
{
Error(diagnostics, ErrorCode.ERR_BadSpecialByRefLocal, typeSyntax, declType);
hasErrors = true;
hasErrors = CheckRestrictedTypeInAsync(this.ContainingMemberOrLambda, declType, diagnostics, typeSyntax);
}
return new BoundDeclarationPattern(node, localSymbol, boundDeclType, isVar, hasErrors);
......
......@@ -882,11 +882,8 @@ private TypeSymbol BindVariableType(CSharpSyntaxNode declarationNode, Diagnostic
}
}
if (this.ContainingMemberOrLambda.Kind == SymbolKind.Method
&& ((MethodSymbol)this.ContainingMemberOrLambda).IsAsync
&& declTypeOpt.IsRestrictedType())
if (CheckRestrictedTypeInAsync(this.ContainingMemberOrLambda, declTypeOpt, localDiagnostics, typeSyntax))
{
Error(localDiagnostics, ErrorCode.ERR_BadSpecialByRefLocal, typeSyntax, declTypeOpt);
hasErrors = true;
}
......
......@@ -29,6 +29,11 @@ public BoundExpression SetInferredType(TypeSymbol type, Binder binderOpt, Diagno
{
ReportInferenceFailure(diagnostics);
}
else
{
Binder.CheckRestrictedTypeInAsync(local.ContainingSymbol, type, diagnostics, this.Syntax);
}
local.SetType(type);
return new BoundLocal(this.Syntax, local, constantValueOpt: null, type: type, hasErrors: this.HasErrors || inferenceFailed);
......
......@@ -39,12 +39,10 @@ private BoundExpression SetInferredType(TypeSymbol type, Binder binderOpt, Diagn
{
ReportInferenceFailure(diagnosticsOpt);
}
else if (localSymbol.ContainingSymbol.Kind == SymbolKind.Method &&
((MethodSymbol)localSymbol.ContainingSymbol).IsAsync &&
type.IsRestrictedType())
else
{
var declaration = (DeclarationExpressionSyntax)this.Syntax;
Binder.Error(diagnosticsOpt, ErrorCode.ERR_BadSpecialByRefLocal, declaration.Type, type);
TypeSyntax typeSyntax = ((DeclarationExpressionSyntax)Syntax).Type;
Binder.CheckRestrictedTypeInAsync(localSymbol.ContainingSymbol, type, diagnosticsOpt, typeSyntax);
}
}
......
......@@ -1163,6 +1163,81 @@ public void Deconstruct(out int a, out int b)
);
}
[Fact]
public void NoArgIteratorTypeInAsync()
{
string source = @"
using System;
class C
{
public async void M()
{
(int x, var (err1, y)) = (0, new C());
(ArgIterator err2, var err3) = M2();
foreach ((ArgIterator err4, var err5) in new[] { M2() })
{
}
}
public static (ArgIterator, ArgIterator) M2()
{
return (default(ArgIterator), default(ArgIterator));
}
public void Deconstruct(out ArgIterator a, out int b)
{
a = default(ArgIterator);
b = 2;
}
public void M3()
{
(int x, var (err1, y)) = (0, new C());
(ArgIterator err2, var err3) = M2();
foreach ((ArgIterator err4, var err5) in new[] { M2() })
{
}
}
}
";
var comp = CreateCompilationWithMscorlib(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef });
comp.VerifyDiagnostics(
// (14,20): error CS0610: Field or property cannot be of type 'ArgIterator'
// public static (ArgIterator, ArgIterator) M2()
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "ArgIterator").WithArguments("System.ArgIterator").WithLocation(14, 20),
// (14,33): error CS0610: Field or property cannot be of type 'ArgIterator'
// public static (ArgIterator, ArgIterator) M2()
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "ArgIterator").WithArguments("System.ArgIterator").WithLocation(14, 33),
// (18,29): error CS1601: Cannot make reference to variable of type 'ArgIterator'
// public void Deconstruct(out ArgIterator a, out int b)
Diagnostic(ErrorCode.ERR_MethodArgCantBeRefAny, "out ArgIterator a").WithArguments("System.ArgIterator").WithLocation(18, 29),
// (7,22): error CS4012: Parameters or locals of type 'ArgIterator' cannot be declared in async methods or lambda expressions.
// (int x, var (err1, y)) = (0, new C());
Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "err1").WithArguments("System.ArgIterator").WithLocation(7, 22),
// (8,10): error CS4012: Parameters or locals of type 'ArgIterator' cannot be declared in async methods or lambda expressions.
// (ArgIterator err2, var err3) = M2();
Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "ArgIterator").WithArguments("System.ArgIterator").WithLocation(8, 10),
// (8,32): error CS4012: Parameters or locals of type 'ArgIterator' cannot be declared in async methods or lambda expressions.
// (ArgIterator err2, var err3) = M2();
Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "err3").WithArguments("System.ArgIterator").WithLocation(8, 32),
// (9,19): error CS4012: Parameters or locals of type 'ArgIterator' cannot be declared in async methods or lambda expressions.
// foreach ((ArgIterator err4, var err5) in new[] { M2() })
Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "ArgIterator").WithArguments("System.ArgIterator").WithLocation(9, 19),
// (9,41): error CS4012: Parameters or locals of type 'ArgIterator' cannot be declared in async methods or lambda expressions.
// foreach ((ArgIterator err4, var err5) in new[] { M2() })
Diagnostic(ErrorCode.ERR_BadSpecialByRefLocal, "err5").WithArguments("System.ArgIterator").WithLocation(9, 41),
// (5,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
// public async void M()
Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "M").WithLocation(5, 23),
// (16,17): error CS0610: Field or property cannot be of type 'ArgIterator'
// return (default(ArgIterator), default(ArgIterator));
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "default(ArgIterator)").WithArguments("System.ArgIterator").WithLocation(16, 17),
// (16,39): error CS0610: Field or property cannot be of type 'ArgIterator'
// return (default(ArgIterator), default(ArgIterator));
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "default(ArgIterator)").WithArguments("System.ArgIterator").WithLocation(16, 39)
);
}
[Fact]
public void MixedDeconstructionCannotBeParsed()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册