提交 eb3563a7 编写于 作者: P Paul Vick

Merge remote-tracking branch 'upstream/master' into merge-master-into-future20160526-150028

......@@ -607,17 +607,17 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
var importChain = methodWithBody.ImportChainOpt;
compilationState.CurrentImportChain = importChain;
var method = methodWithBody.Method;
var lambda = method as SynthesizedLambdaMethod;
var variableSlotAllocatorOpt = ((object)lambda != null) ?
_moduleBeingBuiltOpt.TryCreateVariableSlotAllocator(lambda, lambda.TopLevelMethod) :
_moduleBeingBuiltOpt.TryCreateVariableSlotAllocator(method, method);
// We make sure that an asynchronous mutation to the diagnostic bag does not
// confuse the method body generator by making a fresh bag and then loading
// any diagnostics emitted into it back into the main diagnostic bag.
var diagnosticsThisMethod = DiagnosticBag.GetInstance();
var method = methodWithBody.Method;
var lambda = method as SynthesizedLambdaMethod;
var variableSlotAllocatorOpt = ((object)lambda != null) ?
_moduleBeingBuiltOpt.TryCreateVariableSlotAllocator(lambda, lambda.TopLevelMethod, diagnosticsThisMethod) :
_moduleBeingBuiltOpt.TryCreateVariableSlotAllocator(method, method, diagnosticsThisMethod);
// Synthesized methods have no ordinal stored in custom debug information (only user-defined methods have ordinals).
// In case of async lambdas, which synthesize a state machine type during the following rewrite, the containing method has already been uniquely named,
// so there is no need to produce a unique method ordinal for the corresponding state machine type, whose name includes the (unique) containing method name.
......@@ -1234,7 +1234,7 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol,
if (lazyVariableSlotAllocator == null)
{
lazyVariableSlotAllocator = compilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method);
lazyVariableSlotAllocator = compilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method, diagnostics);
}
BoundStatement bodyWithoutLambdas = loweredBody;
......
......@@ -193,9 +193,9 @@ internal override bool SupportsPrivateImplClass
return anonymousTypes;
}
internal override VariableSlotAllocator TryCreateVariableSlotAllocator(MethodSymbol method, MethodSymbol topLevelMethod)
internal override VariableSlotAllocator TryCreateVariableSlotAllocator(MethodSymbol method, MethodSymbol topLevelMethod, DiagnosticBag diagnostics)
{
return _previousDefinitions.TryCreateVariableSlotAllocator(_previousGeneration, method, topLevelMethod);
return _previousDefinitions.TryCreateVariableSlotAllocator(_previousGeneration, Compilation, method, topLevelMethod, diagnostics);
}
internal override ImmutableArray<AnonymousTypeKey> GetPreviousAnonymousTypes()
......
......@@ -331,7 +331,7 @@ private Location GetSmallestSourceLocationOrNull(Symbol symbol)
/// </summary>
internal virtual NamedTypeSymbol DynamicOperationContextType => null;
internal virtual VariableSlotAllocator TryCreateVariableSlotAllocator(MethodSymbol method, MethodSymbol topLevelMethod)
internal virtual VariableSlotAllocator TryCreateVariableSlotAllocator(MethodSymbol method, MethodSymbol topLevelMethod, DiagnosticBag diagnostics)
{
return null;
}
......
......@@ -1218,10 +1218,9 @@ public virtual MethodSymbol TupleUnderlyingMethod
#region IMethodSymbolInternal
int IMethodSymbolInternal.CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree)
{
return CalculateLocalSyntaxOffset(localPosition, localTree);
}
bool IMethodSymbolInternal.IsIterator => IsIterator;
int IMethodSymbolInternal.CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree) => CalculateLocalSyntaxOffset(localPosition, localTree);
#endregion
......
......@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Symbols;
using System.Reflection.Metadata.Ecma335;
......@@ -152,7 +153,7 @@ private bool TryGetMethodHandle(EmitBaseline baseline, Cci.IMethodDefinition def
protected abstract ImmutableArray<EncLocalInfo> TryGetLocalSlotMapFromMetadata(MethodDefinitionHandle handle, EditAndContinueMethodDebugInformation debugInfo);
protected abstract ITypeSymbol TryGetStateMachineType(EntityHandle methodHandle);
internal VariableSlotAllocator TryCreateVariableSlotAllocator(EmitBaseline baseline, IMethodSymbol method, IMethodSymbol topLevelMethod)
internal VariableSlotAllocator TryCreateVariableSlotAllocator(EmitBaseline baseline, Compilation compilation, IMethodSymbolInternal method, IMethodSymbol topLevelMethod, DiagnosticBag diagnostics)
{
// Top-level methods are always included in the semantic edit list. Lambda methods are not.
MappedMethod mappedMethod;
......@@ -249,6 +250,31 @@ internal VariableSlotAllocator TryCreateVariableSlotAllocator(EmitBaseline basel
}
else
{
// If the current method is async/iterator then either the previous method wasn't declared as async/iterator and it's updated to be one,
// or it was but is not marked by the corresponding state machine attribute because it was missing in the compilation.
// In the later case we need to report an error since we don't known how to map to the previous state machine.
// The IDE already checked that the attribute type is present in the base compilation, but didn't validate that it is well-formed.
// We don't have the base compilation to directly query for the attribute, only the source compilation.
// But since constructor signatures can't be updated during EnC we can just check the current compilation.
if (method.IsAsync)
{
if (compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor) == null)
{
ReportMissingStateMachineAttribute(diagnostics, method, AttributeDescription.AsyncStateMachineAttribute.FullName);
return null;
}
}
else if (method.IsIterator)
{
if (compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor) == null)
{
ReportMissingStateMachineAttribute(diagnostics, method, AttributeDescription.IteratorStateMachineAttribute.FullName);
return null;
}
}
previousLocals = TryGetLocalSlotMapFromMetadata(previousHandle, debugInfo);
if (previousLocals.IsDefault)
{
......@@ -276,6 +302,15 @@ internal VariableSlotAllocator TryCreateVariableSlotAllocator(EmitBaseline basel
awaiterMap);
}
private void ReportMissingStateMachineAttribute(DiagnosticBag diagnostics, IMethodSymbolInternal method, string stateMachineAttributeFullName)
{
diagnostics.Add(MessageProvider.CreateDiagnostic(
MessageProvider.ERR_EncUpdateFailedMissingAttribute,
method.Locations.First(),
MessageProvider.GetErrorDisplayString(method),
stateMachineAttributeFullName));
}
private static void MakeLambdaAndClosureMaps(
ImmutableArray<LambdaDebugInfo> lambdaDebugInfo,
ImmutableArray<ClosureDebugInfo> closureDebugInfo,
......
......@@ -191,11 +191,9 @@ private bool TryGetPreviousLocalId(SyntaxNode currentDeclarator, LocalDebugId cu
DiagnosticBag diagnostics,
out int slotIndex)
{
// Well-formed state machine attribute wasn't found in the baseline (the type is missing or bad).
// Should rarely happen since the IDE reports a rude edit if the attribute type doesn't exist.
// The previous method was not a state machine (it is allowed to change non-state machine to a state machine):
if (_hoistedLocalSlotsOpt == null)
{
ReportMissingStateMachineAttribute(diagnostics);
slotIndex = -1;
return false;
}
......@@ -226,11 +224,9 @@ private bool TryGetPreviousLocalId(SyntaxNode currentDeclarator, LocalDebugId cu
public override bool TryGetPreviousAwaiterSlotIndex(Cci.ITypeReference currentType, DiagnosticBag diagnostics, out int slotIndex)
{
// Well-formed state machine attribute wasn't found in the baseline (the type is missing or bad).
// Should rarely happen since the IDE reports a rude edit if the attribute type doesn't exist.
// The previous method was not a state machine (it is allowed to change non-state machine to a state machine):
if (_awaiterMapOpt == null)
{
ReportMissingStateMachineAttribute(diagnostics);
slotIndex = -1;
return false;
}
......@@ -238,16 +234,6 @@ public override bool TryGetPreviousAwaiterSlotIndex(Cci.ITypeReference currentTy
return _awaiterMapOpt.TryGetValue(_symbolMap.MapReference(currentType), out slotIndex);
}
private void ReportMissingStateMachineAttribute(DiagnosticBag diagnostics)
{
diagnostics.Add(_messageProvider.CreateDiagnostic(
_messageProvider.ERR_EncUpdateFailedMissingAttribute,
NoLocation.Singleton,
_messageProvider.GetErrorDisplayString(_previousTopLevelMethod),
(_previousTopLevelMethod.IsAsync ? AttributeDescription.AsyncStateMachineAttribute : AttributeDescription.IteratorStateMachineAttribute).FullName));
}
private bool TryGetPreviousSyntaxOffset(SyntaxNode currentSyntax, out int previousSyntaxOffset)
{
// no syntax map
......
......@@ -4,6 +4,11 @@ namespace Microsoft.CodeAnalysis.Symbols
{
internal interface IMethodSymbolInternal : IMethodSymbol
{
/// <summary>
/// True if the method is a source method implemented as an iterator.
/// </summary>
bool IsIterator { get; }
int CalculateLocalSyntaxOffset(int declaratorPosition, SyntaxTree declaratorTree);
}
}
......@@ -213,8 +213,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Return anonymousTypes
End Function
Friend Overrides Function TryCreateVariableSlotAllocator(method As MethodSymbol, topLevelMethod As MethodSymbol) As VariableSlotAllocator
Return _previousDefinitions.TryCreateVariableSlotAllocator(_previousGeneration, method, topLevelMethod)
Friend Overrides Function TryCreateVariableSlotAllocator(method As MethodSymbol, topLevelMethod As MethodSymbol, diagnostics As DiagnosticBag) As VariableSlotAllocator
Return _previousDefinitions.TryCreateVariableSlotAllocator(_previousGeneration, Compilation, method, topLevelMethod, diagnostics)
End Function
Friend Overrides Function GetPreviousAnonymousTypes() As ImmutableArray(Of AnonymousTypeKey)
......
......@@ -310,7 +310,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
End Get
End Property
Friend Overridable Function TryCreateVariableSlotAllocator(method As MethodSymbol, topLevelMethod As MethodSymbol) As VariableSlotAllocator
Friend Overridable Function TryCreateVariableSlotAllocator(method As MethodSymbol, topLevelMethod As MethodSymbol, diagnostics As DiagnosticBag) As VariableSlotAllocator
Return Nothing
End Function
......
......@@ -898,7 +898,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' produce a unique method ordinal for the corresponding state machine type, whose name includes the (unique) method name.
Const methodOrdinal As Integer = -1
Dim slotAllocatorOpt = CompilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method.TopLevelMethod)
Dim slotAllocatorOpt = CompilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method.TopLevelMethod, Diagnostics)
Return Rewriter.RewriteIteratorAndAsync(loweredBody, method, methodOrdinal, CompilationState, Diagnostics, slotAllocatorOpt, stateMachineTypeOpt)
End Function
......
......@@ -61,7 +61,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If lazyVariableSlotAllocator Is Nothing Then
' synthesized lambda methods are handled in LambdaRewriter.RewriteLambdaAsMethod
Debug.Assert(TypeOf method IsNot SynthesizedLambdaMethod)
lazyVariableSlotAllocator = compilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method)
lazyVariableSlotAllocator = compilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method, diagnostics)
End If
' Lowers lambda expressions into expressions that construct delegates.
......
......@@ -978,6 +978,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
#End Region
#Region "IMethodSymbolInternal"
Private ReadOnly Property IMethodSymbolInternal_IsIterator As Boolean Implements IMethodSymbolInternal.IsIterator
Get
Return Me.IsIterator
End Get
End Property
Private Function IMethodSymbolInternal_CalculateLocalSyntaxOffset(localPosition As Integer, localTree As SyntaxTree) As Integer Implements IMethodSymbolInternal.CalculateLocalSyntaxOffset
Return CalculateLocalSyntaxOffset(localPosition, localTree)
End Function
......
......@@ -4447,12 +4447,185 @@ End Class
ImmutableArray.Create(New SemanticEdit(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables:=True)))
diff1.EmitResult.Diagnostics.Verify(
Diagnostic(ERRID.ERR_EncUpdateFailedMissingAttribute).WithArguments("Public Function F() As IEnumerable(Of Integer)", "System.Runtime.CompilerServices.IteratorStateMachineAttribute"))
Diagnostic(ERRID.ERR_EncUpdateFailedMissingAttribute, "F").WithArguments("Public Function F() As IEnumerable(Of Integer)", "System.Runtime.CompilerServices.IteratorStateMachineAttribute").WithLocation(6, 30))
End Sub
<Fact, WorkItem(9119, "https://github.com/dotnet/roslyn/issues/9119")>
Public Sub MissingAsyncStateMachineAttribute()
Dim common = "
<Fact>
Public Sub BadIteratorStateMachineAttribute()
Dim source0 = MarkedSource("
Imports System
Imports System.Collections.Generic
Namespace System.Runtime.CompilerServices
Public Class IteratorStateMachineAttribute
Inherits Attribute
End Class
End Namespace
Class C
Public Iterator Function F() As IEnumerable(Of Integer)
Dim <N:0>a</N:0> As Integer = 0
<N:1>Yield 0</N:1>
Console.WriteLine(a)
End Function
End Class
")
Dim source1 = MarkedSource("
Imports System
Imports System.Collections.Generic
Namespace System.Runtime.CompilerServices
Public Class IteratorStateMachineAttribute
Inherits Attribute
End Class
End Namespace
Class C
Public Iterator Function F() As IEnumerable(Of Integer)
Dim <N:0>a</N:0> As Integer = 1
<N:1>Yield 1</N:1>
Console.WriteLine(a)
End Function
End Class
")
Dim compilation0 = CreateCompilationWithMscorlib({source0.Tree}, options:=ComSafeDebugDll)
Dim compilation1 = compilation0.WithSource(source1.Tree)
' the ctor is missing a parameter
Assert.Null(compilation0.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor))
Dim v0 = CompileAndVerify(compilation0, verify:=False)
Dim md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData)
Dim f0 = compilation0.GetMember(Of MethodSymbol)("C.F")
Dim f1 = compilation1.GetMember(Of MethodSymbol)("C.F")
Dim generation0 = EmitBaseline.CreateInitialBaseline(md0, AddressOf v0.CreateSymReader().GetEncMethodDebugInfo)
Dim diff1 = compilation1.EmitDifference(
generation0,
ImmutableArray.Create(New SemanticEdit(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables:=True)))
diff1.EmitResult.Diagnostics.Verify(
Diagnostic(ERRID.ERR_EncUpdateFailedMissingAttribute, "F").WithArguments("Public Function F() As IEnumerable(Of Integer)", "System.Runtime.CompilerServices.IteratorStateMachineAttribute").WithLocation(12, 30))
End Sub
<Fact>
Public Sub AddedIteratorStateMachineAttribute()
Dim source0 = MarkedSource("
Imports System
Imports System.Collections.Generic
Class C
Public Iterator Function F() As IEnumerable(Of Integer)
Dim <N:0>a</N:0> As Integer = 0
<N:1>Yield 0</N:1>
Console.WriteLine(a)
End Function
End Class
")
Dim source1 = MarkedSource("
Imports System
Imports System.Collections.Generic
Namespace System.Runtime.CompilerServices
Public Class IteratorStateMachineAttribute
Inherits Attribute
Sub New(type As Type)
End Sub
End Class
End Namespace
Class C
Public Iterator Function F() As IEnumerable(Of Integer)
Dim <N:0>a</N:0> As Integer = 1
<N:1>Yield 1</N:1>
Console.WriteLine(a)
End Function
End Class
")
Dim compilation0 = CreateCompilationWithMscorlib({source0.Tree}, options:=ComSafeDebugDll)
Dim compilation1 = compilation0.WithSource(source1.Tree)
' older versions of mscorlib don't contain IteratorStateMachineAttribute
Assert.Null(compilation0.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor))
Dim v0 = CompileAndVerify(compilation0, verify:=False)
Dim md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData)
Dim f0 = compilation0.GetMember(Of MethodSymbol)("C.F")
Dim f1 = compilation1.GetMember(Of MethodSymbol)("C.F")
Dim ism1 = compilation1.GetMember(Of TypeSymbol)("System.Runtime.CompilerServices.IteratorStateMachineAttribute")
Dim generation0 = EmitBaseline.CreateInitialBaseline(md0, AddressOf v0.CreateSymReader().GetEncMethodDebugInfo)
Dim diff1 = compilation1.EmitDifference(
generation0,
ImmutableArray.Create(
New SemanticEdit(SemanticEditKind.Insert, Nothing, ism1),
New SemanticEdit(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables:=True)))
diff1.EmitResult.Diagnostics.Verify()
End Sub
<Fact>
Public Sub SourceIteratorStateMachineAttribute()
Dim source0 = MarkedSource("
Imports System
Imports System.Collections.Generic
Namespace System.Runtime.CompilerServices
Public Class IteratorStateMachineAttribute
Inherits Attribute
Sub New(type As Type)
End Sub
End Class
End Namespace
Class C
Public Iterator Function F() As IEnumerable(Of Integer)
Dim <N:0>a</N:0> As Integer = 0
<N:1>Yield 0</N:1>
Console.WriteLine(a)
End Function
End Class
")
Dim source1 = MarkedSource("
Imports System
Imports System.Collections.Generic
Namespace System.Runtime.CompilerServices
Public Class IteratorStateMachineAttribute
Inherits Attribute
Sub New(type As Type)
End Sub
End Class
End Namespace
Class C
Public Iterator Function F() As IEnumerable(Of Integer)
Dim <N:0>a</N:0> As Integer = 1
<N:1>Yield 1</N:1>
Console.WriteLine(a)
End Function
End Class
")
Dim compilation0 = CreateCompilationWithMscorlib({source0.Tree}, options:=ComSafeDebugDll)
Dim compilation1 = compilation0.WithSource(source1.Tree)
Dim v0 = CompileAndVerify(compilation0, verify:=False)
Dim md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData)
Dim f0 = compilation0.GetMember(Of MethodSymbol)("C.F")
Dim f1 = compilation1.GetMember(Of MethodSymbol)("C.F")
Dim generation0 = EmitBaseline.CreateInitialBaseline(md0, AddressOf v0.CreateSymReader().GetEncMethodDebugInfo)
Dim diff1 = compilation1.EmitDifference(
generation0,
ImmutableArray.Create(New SemanticEdit(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables:=True)))
diff1.EmitResult.Diagnostics.Verify()
End Sub
Const AsyncHelpers = "
Imports System
Imports System.Threading.Tasks
......@@ -4466,7 +4639,9 @@ Namespace Microsoft.VisualBasic.CompilerServices
End Class
End Namespace"
Dim source0 = MarkedSource(common & "
<Fact, WorkItem(9119, "https://github.com/dotnet/roslyn/issues/9119")>
Public Sub MissingAsyncStateMachineAttribute()
Dim source0 = MarkedSource(AsyncHelpers & "
Class C
Public Async Function F() As Task(Of Integer)
Dim <N:0>a</N:0> As Integer = 0
......@@ -4475,7 +4650,7 @@ Class C
End Function
End Class
")
Dim source1 = MarkedSource(common & "
Dim source1 = MarkedSource(AsyncHelpers & "
Class C
Public Async Function F() As Task(Of Integer)
Dim <N:0>a</N:0> As Integer = 1
......@@ -4501,8 +4676,123 @@ End Class
ImmutableArray.Create(New SemanticEdit(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables:=True)))
diff1.EmitResult.Diagnostics.Verify(
Diagnostic(ERRID.ERR_EncUpdateFailedMissingAttribute).WithArguments("Public Function F() As Task(Of Integer)", "System.Runtime.CompilerServices.AsyncStateMachineAttribute"),
Diagnostic(ERRID.ERR_EncUpdateFailedMissingAttribute).WithArguments("Public Function F() As Task(Of Integer)", "System.Runtime.CompilerServices.AsyncStateMachineAttribute"))
Diagnostic(ERRID.ERR_EncUpdateFailedMissingAttribute, "F").WithArguments("Public Function F() As Task(Of Integer)", "System.Runtime.CompilerServices.AsyncStateMachineAttribute").WithLocation(15, 27))
End Sub
<Fact, WorkItem(10190, "https://github.com/dotnet/roslyn/issues/10190")>
Public Sub NonAsyncToAsync()
Dim source0 = MarkedSource(AsyncHelpers & "
Class C
Public Function F() As Task(Of Integer)
Dim <N:0>a</N:0> As Integer = 0
<N:1>Return Task.FromResult(a)</N:1>
End Function
End Class
")
Dim source1 = MarkedSource(AsyncHelpers & "
Class C
Public Async Function F() As Task(Of Integer)
Dim <N:0>a</N:0> As Integer = 1
<N:1>Return Await Task.FromResult(a)</N:1>
End Function
End Class
")
Dim compilation0 = CompilationUtils.CreateCompilation({source0.Tree}, {TestReferences.NetFx.v4_0_30316_17626.mscorlib}, options:=ComSafeDebugDll)
Dim compilation1 = compilation0.WithSource(source1.Tree)
Assert.NotNull(compilation0.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor))
Dim v0 = CompileAndVerify(compilation0, verify:=False)
Dim md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData)
Dim f0 = compilation0.GetMember(Of MethodSymbol)("C.F")
Dim f1 = compilation1.GetMember(Of MethodSymbol)("C.F")
Dim generation0 = EmitBaseline.CreateInitialBaseline(md0, AddressOf v0.CreateSymReader().GetEncMethodDebugInfo)
Dim diff1 = compilation1.EmitDifference(
generation0,
ImmutableArray.Create(New SemanticEdit(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables:=True)))
diff1.EmitResult.Diagnostics.Verify()
End Sub
<Fact>
Public Sub NonAsyncToAsync_MissingAttribute()
Dim source0 = MarkedSource(AsyncHelpers & "
Class C
Public Function F() As Task(Of Integer)
Dim <N:0>a</N:0> As Integer = 0
a = a + 1
<N:1>Return New Task(Of Integer)()</N:1>
End Function
End Class
")
Dim source1 = MarkedSource(AsyncHelpers & "
Class C
Public Async Function F() As Task(Of Integer)
Dim <N:0>a</N:0> As Integer = 1
a = a + 1
<N:1>Return Await New Task(Of Integer)()</N:1>
End Function
End Class
")
Dim compilation0 = CompilationUtils.CreateCompilation({source0.Tree}, {TestReferences.NetFx.Minimal.mincorlib, TestReferences.NetFx.Minimal.minasync}, options:=ComSafeDebugDll)
Dim compilation1 = compilation0.WithSource(source1.Tree)
Assert.Null(compilation0.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor))
Dim v0 = CompileAndVerify(compilation0, verify:=False)
Dim md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData)
Dim f0 = compilation0.GetMember(Of MethodSymbol)("C.F")
Dim f1 = compilation1.GetMember(Of MethodSymbol)("C.F")
Dim generation0 = EmitBaseline.CreateInitialBaseline(md0, AddressOf v0.CreateSymReader().GetEncMethodDebugInfo)
Dim diff1 = compilation1.EmitDifference(
generation0,
ImmutableArray.Create(New SemanticEdit(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables:=True)))
diff1.EmitResult.Diagnostics.Verify(
Diagnostic(ERRID.ERR_EncUpdateFailedMissingAttribute, "F").WithArguments("Public Function F() As Task(Of Integer)", "System.Runtime.CompilerServices.AsyncStateMachineAttribute").WithLocation(15, 27))
End Sub
<Fact>
Public Sub NonIteratorToIterator_MissingAttribute()
Dim source0 = MarkedSource("
Imports System.Collections.Generic
Class C
Public Function F() As IEnumerable(Of Integer)
Dim <N:0>a</N:0> As Integer = 0
<N:1>Return { 0 }</N:1>
End Function
End Class
")
Dim source1 = MarkedSource("
Imports System.Collections.Generic
Class C
Public Iterator Function F() As IEnumerable(Of Integer)
Dim <N:0>a</N:0> As Integer = 1
<N:1>Yield a</N:1>
End Function
End Class
")
Dim compilation0 = CreateCompilationWithMscorlib({source0.Tree}, options:=ComSafeDebugDll)
Dim compilation1 = compilation0.WithSource(source1.Tree)
Dim v0 = CompileAndVerify(compilation0, verify:=False)
Dim md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData)
Dim f0 = compilation0.GetMember(Of MethodSymbol)("C.F")
Dim f1 = compilation1.GetMember(Of MethodSymbol)("C.F")
Dim generation0 = EmitBaseline.CreateInitialBaseline(md0, AddressOf v0.CreateSymReader().GetEncMethodDebugInfo)
Dim diff1 = compilation1.EmitDifference(
generation0,
ImmutableArray.Create(New SemanticEdit(SemanticEditKind.Update, f0, f1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables:=True)))
diff1.EmitResult.Diagnostics.Verify(
Diagnostic(ERRID.ERR_EncUpdateFailedMissingAttribute, "F").WithArguments("Public Function F() As IEnumerable(Of Integer)", "System.Runtime.CompilerServices.IteratorStateMachineAttribute").WithLocation(5, 30))
End Sub
End Class
End Namespace
......@@ -71,7 +71,7 @@ protected override IModuleReference TranslateModule(ModuleSymbol symbol, Diagnos
public override int CurrentGenerationOrdinal => 0;
internal override VariableSlotAllocator TryCreateVariableSlotAllocator(MethodSymbol symbol, MethodSymbol topLevelMethod)
internal override VariableSlotAllocator TryCreateVariableSlotAllocator(MethodSymbol symbol, MethodSymbol topLevelMethod, DiagnosticBag diagnostics)
{
var method = symbol as EEMethodSymbol;
if (((object)method != null) && Methods.Contains(method))
......
......@@ -72,7 +72,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
End Get
End Property
Friend Overrides Function TryCreateVariableSlotAllocator(symbol As MethodSymbol, topLevelMethod As MethodSymbol) As VariableSlotAllocator
Friend Overrides Function TryCreateVariableSlotAllocator(symbol As MethodSymbol, topLevelMethod As MethodSymbol, diagnostics As DiagnosticBag) As VariableSlotAllocator
Dim method = TryCast(symbol, EEMethodSymbol)
If method IsNot Nothing AndAlso _methods.Contains(method) Then
Dim defs = GetLocalDefinitions(method.Locals)
......
......@@ -69,6 +69,26 @@ public override SymbolKeyResolution Resolve(Compilation compilation, bool ignore
foreach (var declaringLocation in containingSymbol.DeclaringSyntaxReferences)
{
// This operation can potentially fail. If containingSymbol came from
// a SpeculativeSemanticModel, containingSymbol.ContainingAssembly.Compilation
// may not have been rebuilt to reflect the trees used by the
// SpeculativeSemanticModel to produce containingSymbol. In that case,
// asking the ContainingAssembly's complation for a SemanticModel based
// on trees for containingSymbol with throw an ArgumentException.
// Unfortunately, the best way to avoid this (currently) is to see if
// we're asking for a model for a tree that's part of the compilation.
// (There's no way to get back to a SemanticModel from a symbol).
// TODO (rchande): It might be better to call compilation.GetSemanticModel
// and catch the ArgumentException. The compilation internally has a
// Dictionary<SyntaxTree, ...> that it uses to check if the SyntaxTree
// is applicable wheras the public interface requires us to enumerate
// the entire IEnumerable of trees in the Compilation.
if (!compilation.SyntaxTrees.Contains(declaringLocation.SyntaxTree))
{
continue;
}
var node = declaringLocation.GetSyntax(cancellationToken);
if (node.Language == LanguageNames.VisualBasic)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册