Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -357,11 +357,12 @@ internal bool IsRuntimeAsyncEnabledIn(Symbol? symbol)

Debug.Assert(ReferenceEquals(method.ContainingAssembly, Assembly));
Debug.Assert(method.IsDefinition);
Debug.Assert(method is not Symbols.Metadata.PE.PEMethodSymbol);

var runtimeAsyncEnabledInMethod = symbol switch
var runtimeAsyncEnabledInMethod = method.RuntimeAsyncMethodGenerationAttributeSetting switch
{
SourceMethodSymbol { IsRuntimeAsyncEnabledInMethod: ThreeState.True } => true,
SourceMethodSymbol { IsRuntimeAsyncEnabledInMethod: ThreeState.False } => false,
ThreeState.True => true,
ThreeState.False => false,
_ => Feature(CodeAnalysis.Feature.RuntimeAsync) == "on"
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,9 @@ public sealed override bool IsImplicitlyDeclared
get { return true; }
}

internal sealed override ThreeState IsRuntimeAsyncEnabledInMethod =>
InheritsBaseMethodAttributes && BaseMethod is SourceMethodSymbol { IsRuntimeAsyncEnabledInMethod: var value }
? value
internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting =>
InheritsBaseMethodAttributes
? BaseMethod.RuntimeAsyncMethodGenerationAttributeSetting
: ThreeState.Unknown;
}
}
2 changes: 2 additions & 0 deletions src/Compilers/CSharp/Portable/Symbols/ErrorMethodSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ public override bool ReturnsVoid

public override FlowAnalysisAnnotations FlowAnalysisAnnotations => FlowAnalysisAnnotations.None;

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => ThreeState.Unknown;

public override bool IsVararg
{
get { return false; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ internal override bool IsIterator
get { return _originalMethod.IsIterator; }
}

public sealed override bool IsAsync => _originalMethod.IsAsync;

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => _originalMethod.RuntimeAsyncMethodGenerationAttributeSetting;

internal sealed override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree)
{
return _originalMethod.CalculateLocalSyntaxOffset(localPosition, localTree);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,7 @@ public override bool IsVararg
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
public override ImmutableHashSet<string> ReturnNotNullIfParameterNotNull => ImmutableHashSet<string>.Empty;
public override FlowAnalysisAnnotations FlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => throw ExceptionUtilities.Unreachable();
internal override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false) => false;
internal override bool IsMetadataVirtual(IsMetadataVirtualOption option = IsMetadataVirtualOption.None) => false;
internal sealed override UnmanagedCallersOnlyAttributeData? GetUnmanagedCallersOnlyAttributeData(bool forceComplete) => null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,15 @@ public override FlowAnalysisAnnotations FlowAnalysisAnnotations
}
}

internal override ThreeState RuntimeAsyncMethodGenerationAttributeSetting
{
get
{
Debug.Fail("Not expecting to get here; if we end up here through ENC, add tests to verify");
return ThreeState.Unknown;
}
}

internal override ImmutableArray<string> NotNullMembers
{
get
Expand Down
7 changes: 7 additions & 0 deletions src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ public virtual bool IsGenericMethod

internal abstract bool HasSpecialNameAttribute { get; }

/// <summary>
/// Returns the method-level runtime async setting from
/// <c>RuntimeAsyncMethodGenerationAttribute</c>, or <see cref="ThreeState.Unknown"/>
/// if no setting was specified.
/// </summary>
internal abstract ThreeState RuntimeAsyncMethodGenerationAttributeSetting { get; }

/// <summary>
/// If a method is annotated with `[MemberNotNull(...)]` attributes, returns the list of members
/// listed in those attributes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@ internal NativeIntegerMethodSymbol(NativeIntegerTypeSymbol container, MethodSymb

public override ImmutableArray<TypeParameterSymbol> TypeParameters => ImmutableArray<TypeParameterSymbol>.Empty;

public override bool IsAsync => UnderlyingMethod.IsAsync;

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => throw ExceptionUtilities.Unreachable();

public override ImmutableArray<ParameterSymbol> Parameters
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations

public override FlowAnalysisAnnotations FlowAnalysisAnnotations => _reducedFrom.FlowAnalysisAnnotations;

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => throw ExceptionUtilities.Unreachable();

public override ImmutableArray<CustomModifier> RefCustomModifiers
{
get { return _typeMap.SubstituteCustomModifiers(_reducedFrom.RefCustomModifiers); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
}
}

public override bool IsAsync => _underlyingMethod.IsAsync;

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => throw ExceptionUtilities.Unreachable();

public override TypeWithAnnotations ReturnTypeWithAnnotations
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ internal override bool IsMetadataFinal

internal sealed override int TryGetOverloadResolutionPriority() => throw ExceptionUtilities.Unreachable();

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => throw ExceptionUtilities.Unreachable();

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ private void DecodeWellKnownAttributeAppliedToMethod(ref DecodeWellKnownAttribut
}
}

internal virtual ThreeState IsRuntimeAsyncEnabledInMethod
internal override ThreeState RuntimeAsyncMethodGenerationAttributeSetting
=> GetDecodedWellKnownAttributeData()?.RuntimeAsyncMethodGenerationSetting ?? ThreeState.Unknown;

internal override ImmutableArray<string> NotNullMembers =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ public override TypeSymbol ReceiverType
}
}

public override bool IsAsync => OriginalDefinition.IsAsync;

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => throw ExceptionUtilities.Unreachable();

public override TypeWithAnnotations GetTypeInferredDuringReduction(TypeParameterSymbol reducedFromTypeParameter)
{
// This will throw if API shouldn't be supported or there is a problem with the argument.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ public override ImmutableArray<CSharpAttributeData> GetAttributes()
=> this.UnderlyingMethod.GetAttributes();

public override Symbol ContainingSymbol => this.UnderlyingMethod.ContainingSymbol;
public override bool IsAsync => this.UnderlyingMethod.IsAsync;
public override ImmutableArray<CustomModifier> RefCustomModifiers => this.UnderlyingMethod.RefCustomModifiers;
public override TypeWithAnnotations ReturnTypeWithAnnotations => this.UnderlyingMethod.ReturnTypeWithAnnotations;
internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => throw ExceptionUtilities.Unreachable();

/// <summary>
/// The projection method itself is intentionally not obsolete. We don't want to report obsoletion errors when
Expand Down Expand Up @@ -139,4 +141,3 @@ private sealed class SynthesizedCollectionBuilderProjectedParameterSymbol(
internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder<CSharpAttributeData> attributes) => throw ExceptionUtilities.Unreachable();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ public override bool ReturnsVoid

public sealed override FlowAnalysisAnnotations FlowAnalysisAnnotations => FlowAnalysisAnnotations.None;

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => ThreeState.Unknown;

public override MethodKind MethodKind
{
get { return MethodKind.Ordinary; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ public sealed override FlowAnalysisAnnotations FlowAnalysisAnnotations
get { return FlowAnalysisAnnotations.None; }
}

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => ThreeState.Unknown;

public override ImmutableArray<CustomModifier> RefCustomModifiers
{
get { return ImmutableArray<CustomModifier>.Empty; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations

public override FlowAnalysisAnnotations FlowAnalysisAnnotations => FlowAnalysisAnnotations.None;

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => ThreeState.Unknown;

public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree l

public sealed override FlowAnalysisAnnotations FlowAnalysisAnnotations => FlowAnalysisAnnotations.None;

internal override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => ThreeState.Unknown;

internal override bool IsNullableAnalysisEnabled() => false;

internal sealed override bool HasUnscopedRefAttribute => false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ public override TypeWithAnnotations ReturnTypeWithAnnotations

public override FlowAnalysisAnnotations FlowAnalysisAnnotations => FlowAnalysisAnnotations.None;

internal sealed override ThreeState RuntimeAsyncMethodGenerationAttributeSetting => ThreeState.Unknown;

public override ImmutableArray<CustomModifier> RefCustomModifiers
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,6 @@ public override bool IsVirtual
}
}

public override bool IsAsync
{
get
{
return UnderlyingMethod.IsAsync;
}
}

public override bool IsOverride
{
get
Expand Down
46 changes: 28 additions & 18 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8514,10 +8514,11 @@ .locals init (S V_0)
""");
}

[Fact]
public void SpillAssignmentToThisStruct_02()
[Theory]
[CombinatorialData]
public void SpillAssignmentToThisStruct_02(bool disableRuntimeAsync)
{
var source = """
var source = $$"""
using System;
using System.Threading.Tasks;
struct S : I
Expand All @@ -8543,6 +8544,7 @@ static class Extensions
{
extension<T>(T t) where T : I
{
{{(disableRuntimeAsync ? "[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(false)]" : "")}}
public async Task M()
{
t.P = 1;
Expand All @@ -8553,30 +8555,38 @@ public async Task M()
""";

var expectedOutput = "0";
CompileAndVerify(source, expectedOutput: expectedOutput, options: TestOptions.ReleaseExe);
CompileAndVerify(source, expectedOutput: expectedOutput, options: TestOptions.DebugExe);
CompileAndVerify([source, RuntimeAsyncMethodGenerationAttributeDefinition], expectedOutput: expectedOutput, options: TestOptions.ReleaseExe);
CompileAndVerify([source, RuntimeAsyncMethodGenerationAttributeDefinition], expectedOutput: expectedOutput, options: TestOptions.DebugExe);

var comp = CreateRuntimeAsyncCompilation(source, TestOptions.ReleaseExe);
var comp = CreateRuntimeAsyncCompilation([source, RuntimeAsyncMethodGenerationAttributeDefinition], TestOptions.ReleaseExe);
var verifier = CompileAndVerify(comp, expectedOutput: RuntimeAsyncTestHelpers.ExpectedOutput(expectedOutput), verify: Verification.Fails with
{
ILVerifyMessage = """
ILVerifyMessage = disableRuntimeAsync
? """
[Main]: Return value missing on the stack. { Offset = 0x1f }
"""
: """
[Main]: Return value missing on the stack. { Offset = 0x1f }
[M]: Return value missing on the stack. { Offset = 0xe }
"""
});

verifier.VerifyDiagnostics();
verifier.VerifyIL("Extensions.M<T>(this T)", """
{
// Code size 15 (0xf)
.maxstack 2
IL_0000: ldarga.s V_0
IL_0002: ldc.i4.1
IL_0003: constrained. "T"
IL_0009: callvirt "void I.P.set"
IL_000e: ret
}
""");
if (!disableRuntimeAsync)
{

verifier.VerifyIL("Extensions.M<T>(this T)", """
{
// Code size 15 (0xf)
.maxstack 2
IL_0000: ldarga.s V_0
IL_0002: ldc.i4.1
IL_0003: constrained. "T"
IL_0009: callvirt "void I.P.set"
IL_000e: ret
}
""");
}
}

[Fact]
Expand Down
Loading