From 3e874d0c448306f8f5cee37ccfbfdd6835e1709f Mon Sep 17 00:00:00 2001
From: "dotnet-maestro[bot]"
<42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date: Mon, 15 Sep 2025 07:41:18 +0000
Subject: [PATCH 1/6] [release/10.0.1xx] Source code updates from dotnet/razor
(#2422)
[release/10.0.1xx] Source code updates from dotnet/razor
---
.../src/SourceGenerators/RazorCohostingOptions.cs | 2 +-
.../RazorSourceGeneratorTests.cs | 5 -----
src/source-manifest.json | 4 ++--
3 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/src/razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorCohostingOptions.cs b/src/razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorCohostingOptions.cs
index 21db8554f0a..fc1a8a78f1e 100644
--- a/src/razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorCohostingOptions.cs
+++ b/src/razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorCohostingOptions.cs
@@ -5,5 +5,5 @@ internal static class RazorCohostingOptions
///
/// True if razor is running in the cohosting mode
///
- internal static bool UseRazorCohostServer { get; set; } = true;
+ internal static bool UseRazorCohostServer { get; set; } = false;
}
diff --git a/src/razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs b/src/razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs
index 8c78aaec0db..20e5cba815c 100644
--- a/src/razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs
+++ b/src/razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs
@@ -10,7 +10,6 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Razor.Language.Syntax;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Test.Utilities;
@@ -2616,9 +2615,6 @@ public async Task SourceGenerator_DoesNotUpdateSources_WhenSourceGeneratorIsSupp
// start with the generator suppressed (this is the default state in VS)
driver = SetSuppressionState(true);
- // Disable co-hosting, this test only applies to non-cohosting scenarios
- RazorCohostingOptions.UseRazorCohostServer = false;
-
// results should be empty, and no recorded steps should have run
using var eventListener = new RazorEventListener();
var result = RunGenerator(compilation!, ref driver).VerifyPageOutput();
@@ -3461,7 +3457,6 @@ public async Task UseRazorCohostServer_CanOverride_Suppression()
["Component.Razor"] = "
Hello world
",
});
var compilation = await project.GetCompilationAsync();
- RazorCohostingOptions.UseRazorCohostServer = false;
// Start with the generator suppressed
var (driver, additionalTexts, optionsProvider) = await GetDriverWithAdditionalTextAndProviderAsync(project, configureGlobalOptions: (o) =>
diff --git a/src/source-manifest.json b/src/source-manifest.json
index 0c9c5aae0e9..70a1b9c7245 100644
--- a/src/source-manifest.json
+++ b/src/source-manifest.json
@@ -67,10 +67,10 @@
"commitSha": "28aa7988271232f1feec583cd7e0144ac8f42ee4"
},
{
- "barId": 282857,
+ "barId": 283108,
"path": "razor",
"remoteUri": "https://github.com/dotnet/razor",
- "commitSha": "34bcb6b4b58087a7f0f54293b5bdab30284eb66b"
+ "commitSha": "bde4f70c9560811a7f25023b9d8ac42fd7d0e99f"
},
{
"barId": 281892,
From 76c90b64fb9d5277e43ec470223bf0892b823886 Mon Sep 17 00:00:00 2001
From: "dotnet-maestro[bot]"
<42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date: Mon, 15 Sep 2025 08:11:59 +0000
Subject: [PATCH 2/6] [release/10.0.1xx] Update dependencies from
dotnet/arcade-services (#2424)
[release/10.0.1xx] Update dependencies from dotnet/arcade-services
---
.config/dotnet-tools.json | 2 +-
eng/Version.Details.xml | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 8d1ac163534..1460435f520 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"microsoft.dotnet.darc": {
- "version": "1.1.0-beta.25454.3",
+ "version": "1.1.0-beta.25461.2",
"commands": [
"darc"
]
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index ff26f6b94ea..eeedaa8ddd0 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -10,9 +10,9 @@
https://github.com/dotnet/dotnet
2db1f5ee2bdda2e8d873769325fabede32e420e0
-
+
https://github.com/dotnet/arcade-services
- 8a799cfe36a94b864726b9b9aa673bd65753e238
+ 4aa8e8c35aaf3cbdfc387d28af3366fcd9125bc8
From b067b59875bd4e4764cf04360970b3dea36bb47e Mon Sep 17 00:00:00 2001
From: "dotnet-maestro[bot]"
<42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date: Mon, 15 Sep 2025 14:09:17 +0000
Subject: [PATCH 3/6] [release/10.0.1xx] Source code updates from dotnet/roslyn
(#2420)
[release/10.0.1xx] Source code updates from dotnet/roslyn
- Temporarily re-add ITypeSymbol extension APIs
---
src/roslyn/azure-pipelines-official.yml | 5 +-
src/roslyn/azure-pipelines.yml | 27 +-
.../Compiler Breaking Changes - DotNet 10.md | 2 +-
.../docs/contributing/Compiler Test Plan.md | 8 +
src/roslyn/eng/Directory.Packages.props | 10 +-
src/roslyn/eng/Version.Details.props | 8 +-
src/roslyn/eng/Version.Details.xml | 18 +-
src/roslyn/eng/Versions.props | 11 +
src/roslyn/eng/build.sh | 1 +
.../job/publish-build-assets.yml | 9 +-
.../eng/common/core-templates/jobs/jobs.yml | 2 +
.../core-templates/steps/generate-sbom.yml | 2 +-
.../steps/source-index-stage1-publish.yml | 4 +-
src/roslyn/global.json | 8 +-
...dAnonymousTypeMemberNameCodeFixProvider.cs | 3 +-
.../MakeLocalFunctionStaticCodeFixHelper.cs | 3 +-
.../UseExplicitTypeCodeFixProvider.cs | 2 +-
.../GenerateConstructorTests.cs | 2 +-
...plementAbstractClassTests_ThroughMember.cs | 2 +-
.../CSharpDeclareAsNullableCodeFixTests.cs | 2 +-
.../SimplifyInterpolationTests.cs | 304 +-
.../IDEDiagnosticIdToOptionMappingHelper.cs | 6 +-
...AttributeSuppressionsDiagnosticAnalyzer.cs | 2 +-
...SimplifyInterpolationDiagnosticAnalyzer.cs | 15 +-
.../AbstractSimplifyInterpolationHelpers.cs | 65 +-
...bstractGenerateConstructorService.State.cs | 2 +-
...actGenerateEnumMemberService.CodeAction.cs | 3 +-
...arameterizedMemberService.SignatureInfo.cs | 4 +-
...enerateParameterizedMemberService.State.cs | 2 +-
...tractGenerateParameterizedMemberService.cs | 5 +-
...actSimplifyInterpolationCodeFixProvider.cs | 6 +-
...erBasedUserDiagnosticTest_OptionHelpers.cs | 12 +-
...tLanguageServices.MefHostExportProvider.cs | 8 +-
src/roslyn/src/CodeStyle/Tools/Program.cs | 4 +-
.../CSharp/Portable/Binder/Binder_Crefs.cs | 35 +-
.../Portable/Binder/Binder_Invocation.cs | 17 +-
.../Portable/Binder/ForEachLoopBinder.cs | 10 +-
.../Portable/Binder/RefSafetyAnalysis.cs | 2 +-
.../Binder/WithCrefTypeParametersBinder.cs | 1 +
.../Portable/BoundTree/UnboundLambda.cs | 25 +-
.../Portable/Compiler/ClsComplianceChecker.cs | 2 +-
.../FlowAnalysis/DefiniteAssignment.cs | 2 +
.../Portable/FlowAnalysis/NullableWalker.cs | 42 +-
.../AsyncRewriter/RuntimeAsyncRewriter.cs | 183 +-
...TreeToDifferentEnclosingContextRewriter.cs | 35 +-
.../Lowering/ExtensionMethodBodyRewriter.cs | 12 -
.../LocalRewriter/LocalRewriter_Call.cs | 67 +-
.../LocalRewriter_ForEachStatement.cs | 21 +-
.../Lowering/MethodToClassRewriter.cs | 43 +-
.../StateMachineRewriter/CapturedSymbol.cs | 9 +-
.../MethodToStateMachineRewriter.cs | 290 +-
.../RefInitializationHoister.cs | 304 +
.../CSharp/Portable/Parser/LanguageParser.cs | 57 +-
.../CSharp/Portable/Symbols/AssemblySymbol.cs | 15 +-
.../Symbols/PublicModel/MethodSymbol.cs | 15 +
.../Symbols/PublicModel/NamedTypeSymbol.cs | 6 +
.../Symbols/Source/SourceConstructorSymbol.cs | 12 +-
.../Source/SourceMemberContainerSymbol.cs | 5 +-
.../SynthesizedBackingFieldSymbol.cs | 10 +-
.../Portable/Syntax/SyntaxNormalizer.cs | 2 +-
.../Test/Emit/CodeGen/CodeGenAsyncEHTests.cs | 1 +
.../Emit/CodeGen/CodeGenAsyncIteratorTests.cs | 2 +-
.../Emit/CodeGen/CodeGenAsyncLocalsTests.cs | 1 +
.../Emit/CodeGen/CodeGenAsyncMainTests.cs | 2 +-
.../CodeGenAsyncMethodBuilderOverrideTests.cs | 1 +
.../Emit/CodeGen/CodeGenAsyncSpillTests.cs | 5497 +++++++++++------
.../Test/Emit/CodeGen/CodeGenAsyncTests.cs | 23 +
.../Emit/CodeGen/CodeGenAwaitForeachTests.cs | 316 +-
.../Emit/CodeGen/CodeGenAwaitUsingTests.cs | 2 +-
.../CodeGenRefConditionalOperatorTests.cs | 37 +-
.../Test/Emit/CodeGen/CodeGenRefLocalTests.cs | 70 +
.../Test/Emit2/CodeGen/CodeGenCallTests.cs | 886 ++-
...CodeAnalysis.CSharp.Emit2.UnitTests.csproj | 3 +-
.../Diagnostics/DiagnosticAnalyzerTests.cs | 199 +
.../CSharp/Test/Emit3/FieldKeywordTests.cs | 124 +
...CodeAnalysis.CSharp.Emit3.UnitTests.csproj | 1 +
.../Test/Emit3/RefStructInterfacesTests.cs | 398 ++
.../Test/Emit3/Semantics/ExtensionTests2.cs | 1415 ++++-
.../Test/Emit3/Semantics/InlineArrayTests.cs | 149 +-
.../Semantic/Semantics/InterpolationTests.cs | 131 +
.../Compilation/GetSemanticInfoTests.cs | 36 +
.../SemanticModelGetSemanticInfoTests.cs | 14 +-
...larationParsingTests_MissingIdentifiers.cs | 2811 +++++++++
.../Syntax/Parsing/ExtensionsParsingTests.cs | 563 +-
.../Syntax/Syntax/SyntaxNormalizerTests.cs | 41 +
.../Compilers/CSharp/csc/AnyCpu/csc.csproj | 2 +-
.../DiagnosticLocalizationTests.cs | 20 +-
.../Core/MSBuildTask/InteractiveCompiler.cs | 2 -
.../Core/MSBuildTask/ManagedCompiler.cs | 1 -
.../Core/MSBuildTask/ManagedToolTask.cs | 65 +-
.../Core/MSBuildTaskTests/CscTests.cs | 6 +-
.../Core/MSBuildTaskTests/IntegrationTests.cs | 22 +-
.../MSBuildManagedToolTests.cs | 5 +-
....Build.Tasks.CodeAnalysis.UnitTests.csproj | 3 +-
.../TestUtilities/IntegrationTestBase.cs | 106 +-
.../TestUtilities/TaskTestUtil.cs | 4 +-
.../DiagnosticAnalyzer/AnalysisScope.cs | 11 +-
.../DiagnosticAnalyzer/AnalyzerDriver.cs | 59 +-
...yzerExecutor.AnalyzerDiagnosticReporter.cs | 22 +-
.../DiagnosticAnalyzer/AnalyzerExecutor.cs | 243 +-
.../DiagnosticAnalyzer/AnalyzerOptions.cs | 5 +
.../AnalyzerOptionsExtensions.cs | 4 +
.../CompilationWithAnalyzers.cs | 4 +-
.../CompilationWithAnalyzersOptions.cs | 25 +
.../DiagnosticStartAnalysisScope.cs | 10 +
.../InternalUtilities/PlatformInformation.cs | 2 +
.../InternalUtilities/StringExtensions.cs | 11 +-
.../Core/Portable/PublicAPI.Unshipped.txt | 4 +
.../Core/Portable/Symbols/IFieldSymbol.cs | 5 +
.../Core/Portable/Symbols/IMethodSymbol.cs | 22 +-
.../Core/Portable/Symbols/INamedTypeSymbol.cs | 11 +
.../Core/Portable/Symbols/ITypeSymbol.cs | 9 +-
...ld.Tasks.CodeAnalysis.Sdk.UnitTests.csproj | 1 +
.../Core/SdkTaskTests/SdkManagedToolTests.cs | 12 +-
.../VBCSCompiler/AnyCpu/VBCSCompiler.csproj | 2 +-
.../CompilerServerApiTest.cs | 5 +-
.../Compilers/Shared/BuildServerConnection.cs | 143 +-
.../src/Compilers/Shared/RuntimeHostInfo.cs | 41 +-
.../Compilation/VisualBasicCompilation.vb | 4 +-
.../Portable/Symbols/MethodSymbol.vb | 6 +
.../Portable/Symbols/NamedTypeSymbol.vb | 11 +
.../Portable/Symbols/TypeSymbol.vb | 6 +-
.../SymbolDisplay/SymbolDisplayTests.vb | 4 +-
.../VisualBasic/vbc/AnyCpu/vbc.csproj | 2 +-
...EventHookupCommandHandler_TabKeyCommand.cs | 2 +-
.../SemanticClassifierTests_Regex.cs | 28 +
.../AddUsingTests_ExtensionMethods.cs | 62 +-
...ateEqualsAndGetHashCodeFromMembersTests.cs | 4 +-
.../InitializeMemberFromParameterTests.cs | 6 +-
...berFromPrimaryConstructorParameterTests.cs | 6 +-
.../CSharpMoveStaticMembersTests.cs | 47 +
.../CodeActions/PreviewExceptionTests.cs | 6 +-
.../DiagnosticAnalyzerDriverTests.cs | 4 +-
.../MockDiagnosticAnalyzerTests.cs | 2 +-
.../EventHookupCommandHandlerTests.cs | 4 +-
.../EventHookup/EventHookupTestState.cs | 2 +-
.../Formatting/CodeCleanupTests.TestFixers.cs | 14 +-
.../NavigateTo/InteractiveNavigateToTests.cs | 10 +-
.../DiagnosticAnalyzerQuickInfoSourceTests.cs | 17 +-
.../AttributeSignatureHelpProviderTests.cs | 70 +-
...orInitializerSignatureHelpProviderTests.cs | 62 +-
...essExpressionSignatureHelpProviderTests.cs | 48 +-
...tiallyWrittenSignatureHelpProviderTests.cs | 32 +-
.../GenericNameSignatureHelpProviderTests.cs | 58 +-
...ionExpressionSignatureHelpProviderTests.cs | 4 +-
.../EditAndContinueLanguageService.cs | 9 +-
.../EditAndContinueLanguageServiceBridge.cs | 9 +-
.../Editor/EditorLayerExtensionManager.cs | 4 +-
.../Api/IVSTypeScriptFindUsagesContext.cs | 2 +-
.../VSTypeScriptDebugLocationInfoWrapper.cs | 2 +-
.../Core/Host/IPreviewPaneService.cs | 2 +-
.../AbstractInlineRenameUndoManager.cs | 4 +-
.../HighlightTags/RenameConflictTag.cs | 2 +-
.../RenameFieldBackgroundAndBorderTag.cs | 2 +-
.../HighlightTags/RenameFixupTag.cs | 2 +-
...lineRenameSession.OpenTextBufferManager.cs | 6 +-
.../UI/InlineRenameAdornmentManager.cs | 3 +-
.../IntelliSense/AsyncCompletion/FilterSet.cs | 2 +-
.../AsyncCompletion/ItemManagerProvider.cs | 2 +-
.../Interactive/InertClassifierProvider.cs | 2 +-
.../DefaultNavigateToPreviewServiceFactory.cs | 2 +-
.../Core/NavigateTo/NavigateToItemDisplay.cs | 4 +-
.../NavigationBar/NavigationBarController.cs | 2 +-
.../EditorNotificationServiceFactory.cs | 2 +-
...ameTrackingTaggerProvider.UndoPrimitive.cs | 2 +-
.../HostWorkspaceServicesExtensions.cs | 8 +-
.../SignatureHelp/Presentation/Signature.cs | 2 +-
.../SplitCommentOptionsStorage.cs | 2 +-
.../Copilot/FlavoredSuggestedAction.cs | 50 -
.../FixAll/FixMultipleOccurrencesService.cs | 7 +-
.../PreviewChangesCodeAction.cs | 81 +-
.../PreviewChangesSuggestedAction.cs | 45 -
.../RefineUsingCopilotCodeAction.cs | 151 +-
.../RefineUsingCopilotSuggestedAction.cs | 70 -
.../SuggestedActionPriorityProvider.cs | 51 -
.../CodeFixSuggestedAction.cs | 52 -
.../CodeRefactoringSuggestedAction.cs | 36 -
...rSuggestedAction.CaretPositionRestorer.cs} | 2 +-
...stedAction.cs => EditorSuggestedAction.cs} | 85 +-
...itorSuggestedActionForRefactorOrFixAll.cs} | 48 +-
...EditorSuggestedActionWithNestedActions.cs} | 48 +-
...EditorSuggestedActionWithNestedFlavors.cs} | 124 +-
...CodeFixSuggestedAction.FixAllCodeAction.cs | 19 -
.../FixAllCodeFixSuggestedAction.cs | 46 -
.../FixAllCodeRefactoringSuggestedAction.cs | 38 -
.../Suggestions/SuggestedActionsSource.cs | 11 +-
.../SuggestedActionsSourceProvider.cs | 6 +-
.../SuggestedActionsSource_Async.cs | 125 +-
.../Core/Utilities/NativeMethods.cs | 2 +-
.../AbstractChangeSignatureTests.cs | 4 +-
.../CodeActions/AbstractCodeActionTest.cs | 14 +-
.../Diagnostics/AbstractUserDiagnosticTest.cs | 4 +-
.../Test/CodeFixes/CodeFixServiceTests.cs | 38 +-
.../DiagnosticAnalyzerServiceTests.cs | 164 +-
.../DocCommentFormattingTests.cs | 4 +-
.../EditAndContinueLanguageServiceTests.cs | 6 +
.../DocCommentFormatterTests.cs | 4 +-
.../RenameTracking/RenameTrackingTestState.cs | 2 +-
.../Test/Utilities/BloomFilterTests.cs | 18 +-
.../SymbolEquivalenceComparerTests.cs | 2 +-
.../Test2/CodeFixes/CodeFixServiceTests.vb | 2 +-
...stractCrossLanguageUserDiagnosticTests.vb} | 6 +-
...ImportCrossLanguageUserDiagnosticTests.vb} | 4 +-
...erenceCrossLanguageUserDiagnosticTests.vb} | 4 +-
...alFileCrossLanguageUserDiagnosticTests.vb} | 4 +-
.../Diagnostics/DiagnosticProviderTests.vb | 2 +-
.../Diagnostics/DiagnosticServiceTests.vb | 16 +-
...eEventCrossLanguageUserDiagnosticTests.vb} | 4 +-
...ructorCrossLanguageUserDiagnosticTests.vb} | 4 +-
...MethodCrossLanguageUserDiagnosticTests.vb} | 4 +-
...riableCrossLanguageUserDiagnosticTests.vb} | 4 +-
...erfaceCrossLanguageUserDiagnosticTests.vb} | 4 +-
...opertyCrossLanguageUserDiagnosticTests.vb} | 4 +-
.../FindReferences/FindReferencesTests.vb | 2 +-
...seTests.vb => VisualBasicGoToBaseTests.vb} | 0
...arpCompletionCommandHandlerTests_Await.vb} | 0
... => CompletionServiceTests_Exclusivity.vb} | 0
...sicCompletionCommandHandlerTests_Await.vb} | 0
...onTests.vb => ModuleNameSimplifierTest.vb} | 0
...icationTests.vb => SimplificationTests.vb} | 0
.../TestUtilities/Async/Checkpoint.cs | 2 +-
.../TestUtilities/BlindAggregatorFactory.cs | 8 +-
.../FormattedClassifications.Operators.cs | 2 +-
...ttedClassifications.OverloadedOperators.cs | 2 +-
.../FormattedClassifications.Punctuation.cs | 2 +-
.../FormattedClassifications.cs | 2 +-
.../IDiagnosticServiceExtensions.cs | 20 -
.../NavigateTo/AbstractNavigateToTests.cs | 38 +-
.../NavigateToTestAggregator.Callback.cs | 3 +-
.../Semantics/SpeculationAnalyzerTestsBase.cs | 2 +-
.../TextEditorFactoryExtensions.cs | 2 +-
.../AbstractTextStructureNavigationTests.cs | 2 +-
.../Threading/WpfTestSharedData.cs | 4 +-
.../Utilities/TestCommandExecutionContext.cs | 2 +-
...NoCompilationDocumentDiagnosticAnalyzer.cs | 2 +-
.../Text/Extensions.TextBufferContainer.cs | 2 +-
.../Extensions/ITextSnapshotExtensions.cs | 8 +-
.../Shared/Extensions/TextSpanExtensions.cs | 4 +-
.../DiagnosticAnalyzerDriverTests.vb | 2 +-
.../Formatting/CodeCleanUpTests.vb | 1 -
.../CSharpAddImportFeatureService.cs | 1 -
...eCodeRefactoringProvider.FixAllProvider.cs | 19 +-
...ecursivePatternsCodeRefactoringProvider.cs | 4 +-
...ConvertNamespaceCodeRefactoringProvider.cs | 6 +-
...nvertToExtensionCodeRefactoringProvider.cs | 4 +-
.../ConvertToExtensionFixAllProvider.cs | 16 +-
...tringToRawStringCodeRefactoringProvider.cs | 4 +-
.../EditAndContinue/SyntaxComparer.cs | 4 +-
.../CSharpEncapsulateFieldService.cs | 9 +-
.../Api/PythiaSignatureHelpItemWrapper.cs | 4 +-
.../CSharpSyntaxTriviaService.cs | 2 +-
...harpDiagnosticAnalyzerQuickInfoProvider.cs | 31 +-
.../AbstractCSharpSignatureHelpProvider.cs | 12 +-
.../AttributeSignatureHelpProvider.cs | 2 +-
...seExpressionBodyCodeRefactoringProvider.cs | 4 +-
...oPropertyToFullPropertyTests_OptionSets.cs | 18 +-
.../ConvertForEachToForTests.cs | 2 +-
.../ConvertForToForEachTests.cs | 4 +-
.../AllAnalyzersSeverityConfigurationTests.cs | 2 +-
...CategoryBasedSeverityConfigurationTests.cs | 2 +-
...SeverityBasedSeverityConfigurationTests.cs | 2 +-
.../Suppression/RemoveSuppressionTests.cs | 2 +-
...emoveUnnecessaryPragmaSuppressionsTests.cs | 6 +-
.../Suppression/SuppressionAllCodeTests.cs | 2 +-
.../SuppressionTest_FixMultipleTests.cs | 4 +-
.../Suppression/SuppressionTests.cs | 12 +-
.../EditAndContinue/StatementMatchingTests.cs | 2 +-
.../IntroduceVariableTests.cs | 2 +-
.../UseExpressionBodyFixAllTests.cs | 2 +-
...ressionBodyForAccessorsRefactoringTests.cs | 16 +-
...essionBodyForPropertiesRefactoringTests.cs | 14 +-
...actAddFileBannerCodeRefactoringProvider.cs | 6 +-
.../AbstractAddImportFeatureService.cs | 14 +-
.../AddImport/SymbolReferenceFinder.cs | 20 +-
.../Core/Portable/AddImport/SymbolResult.cs | 6 +-
.../Portable/CodeFixes/CodeFixCollection.cs | 15 +-
...ConfigureCodeStyleOptionCodeFixProvider.cs | 2 +-
.../ConfigureSeverityLevelCodeFixProvider.cs | 4 +-
.../AbstractFixAllCodeFixCodeAction.cs | 58 -
.../FixMultipleCodeAction.cs | 17 -
...CodeFixService.FixAllDiagnosticProvider.cs | 13 +-
.../CodeFixes/Service/CodeFixService.cs | 139 +-
.../CodeFixes/Service/ICodeFixService.cs | 10 +-
.../AbstractSuppressionCodeFixProvider.cs | 6 +-
.../AbstractFixAllCodeAction.cs | 89 +-
.../AbstractFixAllGetFixesService.cs | 10 +-
.../CodeActionRequestPriorityProvider.cs | 159 -
.../IFixAllGetFixesService.cs | 4 +-
.../CodeLens/CodeLensFindReferenceProgress.cs | 2 +-
.../CodeRefactoringService.cs | 2 +-
.../FixAllCodeRefactoringCodeAction.cs | 21 -
.../AbstractDocCommentCompletionProvider.cs | 2 +-
...tensionMethodImportCompletionCacheEntry.cs | 2 +-
...onvertIfToSwitchCodeRefactoringProvider.cs | 4 +-
...ToInterpolatedStringRefactoringProvider.cs | 4 +-
.../Copilot/ICopilotChangeAnalysisService.cs | 6 +-
.../CodeAnalysisDiagnosticAnalyzerService.cs | 99 +-
.../DiagnosticAnalyzerExtensions.cs | 3 -
.../Diagnostics/IDiagnosticAnalyzerService.cs | 98 +-
.../Options/DiagnosticOptionsStorage.cs | 3 -
...gnosticAnalyzerService.HostAnalyzerInfo.cs | 10 +-
...DiagnosticAnalyzerService.ProjectStates.cs | 2 +-
.../Service/DiagnosticAnalyzerService.cs | 98 +-
...zerService_CompilationWithAnalyzersPair.cs | 2 +-
...lyzerService_DeprioritizationCandidates.cs | 70 +-
...zerService_ForceCodeAnalysisDiagnostics.cs | 102 +
...icAnalyzerService_GetDiagnosticsForSpan.cs | 148 +-
...alyzerService_ProduceProjectDiagnostics.cs | 102 +-
...AnalyzerService_RemoteOrLocalDispatcher.cs | 168 +-
.../RudeEditDiagnosticsBuilder.cs | 4 +-
.../DateAndTimeLanguageDetector.cs | 2 +-
.../EmbeddedLanguageDetector.cs | 9 +-
...ordinator.UnitTestingAsyncWorkItemQueue.cs | 2 +-
.../ExtractMethod/MethodExtractor.Analyzer.cs | 2 +-
.../AbstractGenerateTypeService.Editor.cs | 2 +-
...AbstractInlineParameterNameHintsService.cs | 11 +-
.../AbstractInlineTypeHintsService.cs | 2 +-
.../Portable/InlineHints/InlineHintHelpers.cs | 9 +-
.../Portable/Intents/IntentDataProvider.cs | 2 +-
...dataAsSourceService.WrappedMethodSymbol.cs | 2 +
.../MoveStaticMembersWithDialogCodeAction.cs | 76 +
.../NavigateTo/INavigateToSearcherHost.cs | 2 +-
.../OrganizeImportsCodeRefactoringProvider.cs | 4 +-
.../ImplementationAssemblyLookupService.cs | 2 +-
.../RQName/Nodes/RQConstructedType.cs | 2 +-
.../RQName/Nodes/RQMethodOrProperty.cs | 2 +-
.../RQName/Nodes/RQUnconstructedType.cs | 2 +-
.../AbstractSignatureHelpProvider.cs | 2 +-
.../Structure/BlockStructureContext.cs | 2 +-
.../SymbolSearchUpdateEngine.Update.cs | 4 +-
...CodeActionOrUserDiagnosticTest_NoEditor.cs | 2 +-
...erDiagnosticTest_NoEditor_OptionHelpers.cs | 12 +-
.../AbstractCodeActionTest_NoEditor.cs | 16 +-
.../AbstractSuppressionAllCodeTests.cs | 2 +-
.../AbstractUserDiagnosticTest_NoEditor.cs | 2 +-
.../Diagnostics/ParenthesesOptionsProvider.cs | 6 +-
.../NamingStylesTestOptionSets.cs | 44 +-
.../AspNetCoreVirtualCharSequence.cs | 2 +-
.../EditAndContinueWorkspaceTestBase.cs | 2 +-
.../Features/TestUtilities/Utils/Options.cs | 4 +-
.../VisualBasicAddImportFeatureService.vb | 11 +-
.../VisualDiagnosticsServiceFactory.cs | 4 +-
.../LspFileChangeWatcherTests.cs | 2 +-
.../BrokeredServices/ServiceBrokerFactory.cs | 2 +-
.../BrokeredServiceBridgeManifestService.cs | 2 +-
.../FileWatching/LspFileChangeWatcher.cs | 4 +-
.../StarredCompletionsAssemblyHelper.cs | 2 +-
.../TestExampleLanguageServer.cs | 4 +-
.../RequestExecutionQueue.cs | 2 +-
.../TestDiagnosticAnalyzerDriver.cs | 4 +-
.../AbstractLanguageServerProtocolTests.cs | 82 +-
.../Protocol/Extensions/Extensions.cs | 2 +-
.../Extensions/ProtocolConversions.cs | 8 +-
.../CodeCleanup/AbstractCodeCleanupService.cs | 9 +-
...nguageServerProjectSystemOptionsStorage.cs | 6 +-
.../Features/Suggestions/SuggestedAction.cs | 123 +
.../Suggestions/SuggestedActionFlavors.cs | 11 +
.../Suggestions/SuggestedActionSet.cs | 27 +
...dPredefinedSuggestedActionCategoryNames.cs | 2 +-
.../UnifiedSuggestedActionSetComparer.cs | 6 +-
.../UnifiedSuggestedActionsSource.cs | 329 +-
.../UnifiedSuggestedActionSet.cs | 44 -
.../ICodeFixSuggestedAction.cs | 16 -
.../ICodeRefactoringSuggestedAction.cs | 16 -
.../IFixAllCodeFixSuggestedAction.cs | 21 -
.../IFixAllCodeRefactoringSuggestedAction.cs | 19 -
.../IUnifiedSuggestedAction.cs | 19 -
.../UnifiedCodeFixSuggestedAction.cs | 36 -
.../UnifiedCodeRefactoringSuggestedAction.cs | 32 -
.../UnifiedFixAllCodeFixSuggestedAction.cs | 32 -
...iedFixAllCodeRefactoringSuggestedAction.cs | 28 -
.../UnifiedSuggestedAction.cs | 20 -
...UnifiedSuggestedActionWithNestedActions.cs | 31 -
.../Protocol/Handler/BufferedProgress.cs | 2 +-
.../CodeActionFixAllResolveHandler.cs | 3 +-
.../Handler/CodeActions/CodeActionHelpers.cs | 104 +-
.../Handler/CodeActions/FixAllCodeAction.cs | 29 -
.../BuildOnlyDiagnosticIdsHandler.cs | 44 +-
...mentsAndProjectDiagnosticSourceProvider.cs | 12 +-
.../AbstractProjectDiagnosticSource.cs | 9 +-
...stractWorkspaceDocumentDiagnosticSource.cs | 10 +-
.../NonLocalDocumentDiagnosticSource.cs | 5 +-
...ocumentNonLocalDiagnosticSourceProvider.cs | 4 +-
.../DocumentChanges/DidChangeHandler.cs | 4 +-
.../Handler/DocumentChanges/DidOpenHandler.cs | 2 +-
.../Formatting/FormatDocumentOnTypeHandler.cs | 58 +-
.../Handler/IDocumentChangeTracker.cs | 8 +-
.../InlineCompletions/XmlSnippetParser.cs | 2 +-
.../OnAutoInsert/OnAutoInsertHandler.cs | 15 +-
.../GetTextDocumentWithContextHandler.cs | 2 +-
.../Protocol/Handler/RequestContext.cs | 16 +-
.../Protocol/LanguageInfoProvider.cs | 2 +-
.../LanguageServer/Protocol/NoOpLspLogger.cs | 2 +-
.../Protocol/Converters/SumConverter.cs | 2 +-
.../Protocol/Protocol/Extensions/VSMethods.cs | 2 +-
.../OptimizedVSCompletionListJsonConverter.cs | 2 +-
.../Protocol/Internal/VSInternalMethods.cs | 20 +-
.../Protocol/Protocol/SumType.cs | 18 +-
.../Workspaces/LspWorkspaceManager.cs | 28 +-
.../Workspaces/TrackedDocumentInfo.cs | 16 +
.../CodeActions/CodeActionResolveTests.cs | 6 +-
.../CodeActions/CodeActionsTests.cs | 2 +-
.../AbstractPullDiagnosticTestsBase.cs | 6 +-
.../AdditionalFileDiagnosticsTests.cs | 2 +-
.../DocumentChanges/DocumentChangesTests.cs | 75 +-
.../FoldingRanges/FoldingRangesTests.cs | 2 +-
.../Formatting/FormatDocumentOnTypeTests.cs | 67 +-
.../Formatting/FormatDocumentRangeTests.cs | 2 +-
.../Formatting/FormatDocumentTests.cs | 2 +-
.../Highlights/DocumentHighlightTests.cs | 2 +-
.../ProtocolUnitTests/MapCode/MapCodeTests.cs | 2 +-
.../OnAutoInsert/OnAutoInsertTests.cs | 140 +-
.../GetTextDocumentWithContextHandlerTests.cs | 2 +-
.../FindAllReferencesHandlerTests.cs | 2 +-
.../Rename/PrepareRenameTests.cs | 2 +-
.../ProtocolUnitTests/Rename/RenameTests.cs | 2 +-
.../AbstractSemanticTokensTests.cs | 6 +-
.../SignatureHelp/SignatureHelpTests.cs | 4 +-
.../SimplifyMethod/SimplifyMethodTests.cs | 2 +-
.../Microsoft.Net.Compilers.Toolset.props | 3 +
...Net.Compilers.Toolset.Framework.Core.props | 1 +
...icrosoft.Net.Compilers.Toolset.Arm64.props | 1 +
...rosoft.CodeAnalysis.Metrics.Package.csproj | 2 +
.../Metrics.Legacy/Metrics.Legacy.csproj | 2 +
.../Tools/Metrics/Metrics.csproj | 2 +
.../DisposeAnalysis/DisposeAnalysisHelper.cs | 3 +-
.../Framework/DataFlow/DataFlowAnalysis.cs | 3 +-
.../DataFlow/LValueFlowCapturesProvider.cs | 3 +-
.../BuildBoss/CompilerNuGetCheckerUtil.cs | 5 +-
.../AbstractRazorCohostLifecycleService.cs | 17 -
.../Razor/Features/Cohost/Constants.cs | 2 -
.../Features/Cohost/Handlers/OnAutoInsert.cs | 2 +-
.../Features/Cohost/ICohostStartupService.cs | 1 -
.../Cohost/RazorStartupServiceFactory.cs | 60 +-
.../src/Tools/PrepareTests/MinimizeUtil.cs | 51 +-
src/roslyn/src/Tools/Replay/Replay.cs | 91 +-
src/roslyn/src/Tools/Replay/Replay.csproj | 2 +-
.../Apis/Microsoft.CodeAnalysis.txt | 4 +
.../Impl/Options/Formatting/StyleViewModel.cs | 36 +-
.../CSharpSnippetExpansionLanguageHelper.cs | 2 +-
.../AbstractPersistentStorageTests.cs | 38 +-
.../ChangeSignatureDialogViewModel.cs | 4 +-
.../IVisualStudioDiagnosticAnalyzerService.cs | 2 +-
.../VisualStudioDiagnosticAnalyzerService.cs | 18 +-
.../DocumentSymbolDataViewModel.cs | 4 +-
...StudioDiagnosticAnalyzerServiceAccessor.cs | 8 +-
...tudioGlobalOperationNotificationService.cs | 4 +-
...per.LSPContainedDocumentServiceProvider.cs | 4 +-
...ualStudioExtractInterfaceOptionsService.cs | 2 +-
.../GenerateTypeDialogViewModel.cs | 2 +-
...geService`2.IVsContainedLanguageFactory.cs | 2 +-
...vice`2.IVsImmediateStatementCompletion2.cs | 10 +-
...tractLanguageService`2.IVsLanguageBlock.cs | 5 +-
...ageService`2.IVsLanguageContextProvider.cs | 4 +-
...tLanguageService`2.IVsLanguageDebugInfo.cs | 14 +-
...actLanguageService`2.IVsLanguageTextOps.cs | 9 +-
...ctLanguageService`2.VsCodeWindowManager.cs | 8 +-
...ctLanguageService`2.VsLanguageDebugInfo.cs | 16 +-
.../AbstractLanguageService`2.cs | 90 +-
.../Def/LanguageService/AbstractPackage`2.cs | 36 +-
.../Def/Options/VisualStudioOptionStorage.cs | 1 -
.../PdbSourceDocumentOutputWindowLogger.cs | 2 +-
.../VisualStudioPickMembersService.cs | 4 +-
.../Legacy/AbstractLegacyProject.cs | 4 -
.../Legacy/SolutionEventsBatchScopeCreator.cs | 273 +-
.../Def/Snippets/SnippetExpansionClient.cs | 2 +-
.../VisualStudioSuppressionFixService.cs | 4 +-
.../Core/Def/Telemetry/CodeMarkerLogger.cs | 6 +-
.../Core/Def/Utilities/ClipboardHelpers.cs | 2 +-
.../CodeModel/AbstractCodeModelService.cs | 3 +-
.../Impl/CodeModel/CodeModelExtensions.cs | 2 +-
.../Impl/CodeModel/CodeModelProjectCache.cs | 4 +-
.../CodeModel/InternalElements/CodeClass.cs | 2 +-
.../AbstractMethodXmlBuilder.AttributeInfo.cs | 2 +-
.../MethodXml/AbstractMethodXmlBuilder.cs | 4 +-
.../Core/Impl/CodeModel/ProjectCodeModel.cs | 2 +-
.../Options/AbstractOptionPreviewViewModel.cs | 4 +-
.../Options/CodeStyleNoticeTextBlock.xaml.cs | 2 +-
.../Options/GridOptionPreviewControl.xaml.cs | 2 +-
.../NamingStyleOptionPageViewModel.cs | 7 +-
.../SymbolSpecificationViewModel.cs | 6 +-
.../Venus/DocumentService_IntegrationTests.vb | 2 +-
.../FSharpBreakpointResolutionResult.cs | 4 +-
.../FSharpSimplifyNameDiagnosticAnalyzer.cs | 2 +-
.../FSharpUnusedDeclarationsAnalyzer.cs | 2 +-
.../FSharpUnusedOpensDiagnosticAnalyzer.cs | 2 +-
.../InProcess/EditorInProcess.cs | 24 +-
.../InProcess/SolutionExplorerInProcess.cs | 4 +-
...nguageServices.New.IntegrationTests.csproj | 1 +
.../Client/RemoteLanguageServiceWorkspace.cs | 2 +-
.../RemoteLanguageServiceWorkspaceHost.cs | 2 +-
.../CustomProtocol/LspRequestExtensions.cs | 2 +-
.../Impl/LiveShareInitializeHandler.cs | 2 +-
.../LiveShare/Test/ProjectsHandlerTests.cs | 2 +-
.../TestUtilities2/MockServiceProvider.vb | 21 +-
.../Framework/TestEnvironment.vb | 44 +-
.../Guids.cs | 2 +-
.../Loggers/OutputWindowLogger.cs | 4 +-
.../OptionPages/ForceLowMemoryMode.cs | 2 +-
.../PerfMargin/StatusIndicator.xaml.cs | 4 +-
.../VenusMargin/ProjectionSpanTag.cs | 2 +-
.../VenusMargin/VenusMargin.cs | 2 +-
.../Handler/Completion/CompletionHandler.cs | 2 +-
.../DocumentPullDiagnosticHandler.cs | 2 +-
.../WorkspacePullDiagnosticHandler.cs | 2 +-
.../Impl/Implementation/XamlProjectService.cs | 2 +-
.../XamlTextViewCreationListener.cs | 2 +-
.../CodeGeneration/CSharpSyntaxGenerator.cs | 14 +-
.../CSharpCommandLineParserServiceTests.cs | 2 +-
.../CodeGeneration/SyntaxGeneratorTests.cs | 352 ++
.../Workspace/Host/Mef/MefV1HostServices.cs | 2 +-
.../Core/Portable/CodeFixes/CodeFix.cs | 57 +-
.../Portable/CodeFixes/CodeFixProvider.cs | 3 +-
.../DocumentBasedFixAllProvider.cs | 1 -
.../FixAllOccurrences/FixAllContext.cs | 10 +-
.../FixAllOccurrences/FixAllProvider.cs | 6 +-
.../FixAllOccurrences/FixAllScope.cs | 8 +-
.../CommonFixAllState.cs | 14 +-
.../DefaultFixAllProviderHelpers.cs | 8 +-
.../DocumentBasedFixAllProviderHelpers.cs | 2 +-
.../CodeFixesAndRefactorings/FixAllKind.cs | 2 +-
.../CodeFixesAndRefactorings/FixAllLogger.cs | 2 +-
.../FixAllProviderInfo.cs | 33 +-
...Context.cs => IRefactorOrFixAllContext.cs} | 13 +-
...ovider.cs => IRefactorOrFixAllProvider.cs} | 16 +-
...xAllState.cs => IRefactorOrFixAllState.cs} | 13 +-
.../IRefactorOrFixProvider.cs | 9 +
.../CodeRefactoringProvider.cs | 11 +-
.../DocumentBasedFixAllProvider.cs | 102 -
.../DocumentBasedRefactorAllProvider.cs | 104 +
.../FixAllOccurences/FixAllProvider.cs | 106 -
...FixAllContext.cs => RefactorAllContext.cs} | 75 +-
.../FixAllOccurences/RefactorAllProvider.cs | 107 +
.../FixAllOccurences/RefactorAllScope.cs | 92 +
.../{FixAllState.cs => RefactorAllState.cs} | 71 +-
...yntaxEditorBasedCodeRefactoringProvider.cs | 47 +-
.../Portable/Diagnostics/AnalyzerFilter.cs | 30 +
.../CodeAnalysisEventSource.Workspaces.cs | 2 +-
.../DiagnosticAnalyzerInfoCache.cs | 25 +-
.../Portable/Diagnostics/DiagnosticData.cs | 22 +-
.../Diagnostics/DiagnosticIdFilter.cs | 65 +
.../Portable/Diagnostics/DiagnosticKind.cs | 0
.../Core/Portable/Diagnostics/Extensions.cs | 20 -
.../Diagnostics/HostDiagnosticAnalyzers.cs | 21 +-
.../IRemoteDiagnosticAnalyzerService.cs | 48 +-
.../Core/Portable/Editing/SyntaxGenerator.cs | 67 +-
.../Pythia/Api/PythiaEditDistanceWrapper.cs | 2 +-
.../PatternMatcher.PatternSegment.cs | 2 +-
.../Core/Portable/PublicAPI.Unshipped.txt | 26 +-
.../ConflictingIdentifierTracker.cs | 2 +-
.../Core/Portable/Rename/RenameUtilities.cs | 2 +-
.../Extensions/ILanguageMetadataExtensions.cs | 4 +-
.../DocumentationProviderServiceFactory.cs | 3 +-
.../Host/Metadata/MetadataServiceFactory.cs | 2 +-
...pilationState.RegularCompilationTracker.cs | 2 +-
.../Workspace/Solution/SolutionState.cs | 2 +-
.../Portable/Workspace/WorkspaceEventMap.cs | 4 +-
.../CoreTest/BatchFixAllProviderTests.cs | 2 +-
.../LongestCommonSubsequenceTests.cs | 2 +-
.../CoreTest/Differencing/TestTreeComparer.cs | 4 +-
.../CoreTest/Editing/SyntaxEditorTests.cs | 2 +-
.../CoreTest/ExtensionOrdererTests.cs | 2 +-
.../MEF/ExportProviderCache.cs | 4 +-
.../CoreTestUtilities/MEF/TestComposition.cs | 2 +-
.../Options/OptionsTestHelpers.cs | 2 +-
.../Workspaces/TestHostProject`1.cs | 2 +-
.../Workspaces/TestWorkspace_XmlCreation.cs | 2 +-
.../Workspaces/MSBuild/BuildHost/BuildHost.cs | 34 +-
.../Workspaces/MSBuild/BuildHost/Program.cs | 19 +-
.../BuildHost/Rpc/Contracts/IBuildHost.cs | 7 +
.../BuildHost/Rpc/Contracts/JsonSettings.cs | 2 +-
.../MSBuild/BuildHost/Rpc/RpcServer.cs | 4 +-
.../Core/MSBuild/BuildHostProcessManager.cs | 30 +-
.../MSBuild/Core/Rpc/RemoteBuildHost.cs | 7 +-
.../Workspaces/MSBuild/Core/Rpc/RpcClient.cs | 4 +-
.../Test/BuildHostProcessManagerTests.cs | 79 +-
.../Test/NewlyCreatedProjectsFromDotNetNew.cs | 10 +-
.../Remote/Core/ExportProviderBuilder.cs | 6 +-
.../Serialization/MessagePackFormatters.cs | 2 +-
.../ServiceHub/Host/RemoteWorkspaceManager.cs | 2 +-
.../DiagnosticAnalyzer/DiagnosticComputer.cs | 493 --
.../DiagnosticAnalyzer/PerformanceQueue.cs | 2 +-
.../PerformanceTrackerService.cs | 2 +-
.../RemoteDiagnosticAnalyzerService.cs | 151 +-
.../EditAndContinueLogReporter.cs | 4 +-
.../Services/SyntaxFacts/CSharpSyntaxKinds.cs | 1 +
.../Core/CompilerExtensions.projitems | 1 -
....DataFlowAnalyzer.FlowGraphAnalysisData.cs | 2 +-
.../SymbolUsageAnalysis/SymbolUsageResult.cs | 4 +-
.../SyntaxFacts/ISyntaxFactsExtensions.cs | 159 +-
.../Core/Services/SyntaxFacts/ISyntaxKinds.cs | 1 +
.../Compiler/Core/Utilities/EditDistance.cs | 2 +-
.../Compilation/CompilationExtensions.cs | 3 +
.../Extensions/Symbols/ISymbolExtensions.cs | 32 +-
.../SyntaxFacts/VisualBasicSyntaxKinds.vb | 1 +
.../SyntaxEditorBasedCodeFixProvider.cs | 16 +-
.../IFixAllSpanMappingService.cs | 2 +-
.../Core/CodeGeneration/CodeGenerator.cs | 25 +-
.../CodeGenerationAbstractMethodSymbol.cs | 2 +
.../CodeGenerationAbstractNamedTypeSymbol.cs | 6 +
.../Symbols/CodeGenerationTypeSymbol.cs | 4 +-
.../Core/Extensions/ISolutionExtensions.cs | 20 +
.../Core/Extensions/ProjectExtensions.cs | 23 +-
.../VisualBasicSyntaxGenerator.vb | 5 +
.../CodeGeneration/SyntaxGeneratorTests.vb | 17 +
src/source-manifest.json | 4 +-
606 files changed, 17015 insertions(+), 8087 deletions(-)
create mode 100644 src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/RefInitializationHoister.cs
delete mode 100644 src/roslyn/src/EditorFeatures/Core/Suggestions/Copilot/FlavoredSuggestedAction.cs
delete mode 100644 src/roslyn/src/EditorFeatures/Core/Suggestions/PreviewChanges/PreviewChangesSuggestedAction.cs
delete mode 100644 src/roslyn/src/EditorFeatures/Core/Suggestions/RefineUsingCopilot/RefineUsingCopilotSuggestedAction.cs
delete mode 100644 src/roslyn/src/EditorFeatures/Core/Suggestions/SuggestedActionPriorityProvider.cs
delete mode 100644 src/roslyn/src/EditorFeatures/Core/Suggestions/SuggestedActions/CodeFixSuggestedAction.cs
delete mode 100644 src/roslyn/src/EditorFeatures/Core/Suggestions/SuggestedActions/CodeRefactoringSuggestedAction.cs
rename src/roslyn/src/EditorFeatures/Core/Suggestions/SuggestedActions/{SuggestedAction.CaretPositionRestorer.cs => EditorSuggestedAction.CaretPositionRestorer.cs} (98%)
rename src/roslyn/src/EditorFeatures/Core/Suggestions/SuggestedActions/{SuggestedAction.cs => EditorSuggestedAction.cs} (82%)
rename src/roslyn/src/EditorFeatures/Core/Suggestions/SuggestedActions/{AbstractFixAllSuggestedAction.cs => EditorSuggestedActionForRefactorOrFixAll.cs} (62%)
rename src/roslyn/src/EditorFeatures/Core/Suggestions/{SuggestedActionWithNestedActions.cs => SuggestedActions/EditorSuggestedActionWithNestedActions.cs} (50%)
rename src/roslyn/src/EditorFeatures/Core/Suggestions/{SuggestedActionWithNestedFlavors.cs => SuggestedActions/EditorSuggestedActionWithNestedFlavors.cs} (60%)
delete mode 100644 src/roslyn/src/EditorFeatures/Core/Suggestions/SuggestedActions/FixAllCodeFixSuggestedAction.FixAllCodeAction.cs
delete mode 100644 src/roslyn/src/EditorFeatures/Core/Suggestions/SuggestedActions/FixAllCodeFixSuggestedAction.cs
delete mode 100644 src/roslyn/src/EditorFeatures/Core/Suggestions/SuggestedActions/FixAllCodeRefactoringSuggestedAction.cs
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/{AbstractCrossLanguageUserDiagnosticTest.vb => AbstractCrossLanguageUserDiagnosticTests.vb} (98%)
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/AddImport/{AddImportCrossLanguageTests.vb => AddImportCrossLanguageUserDiagnosticTests.vb} (99%)
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/AddMissingReference/{AddMissingReferenceTests.vb => AddMissingReferenceCrossLanguageUserDiagnosticTests.vb} (98%)
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/{AdditionalFileDiagnosticsTests.vb => AdditionalFileCrossLanguageUserDiagnosticTests.vb} (97%)
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/GenerateEvent/{GenerateEventCrossLanguageTests.vb => GenerateEventCrossLanguageUserDiagnosticTests.vb} (97%)
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/GenerateFromUsage/{GenerateConstructorCrossLanguageTests.vb => GenerateConstructorCrossLanguageUserDiagnosticTests.vb} (94%)
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/GenerateFromUsage/{GenerateMethodCrossLanguageTests.vb => GenerateMethodCrossLanguageUserDiagnosticTests.vb} (99%)
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/GenerateFromUsage/{GenerateVariableCrossLanguageTests.vb => GenerateVariableCrossLanguageUserDiagnosticTests.vb} (95%)
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/ImplementInterface/{ImplementInterfaceCrossLanguageTests.vb => ImplementInterfaceCrossLanguageUserDiagnosticTests.vb} (98%)
rename src/roslyn/src/EditorFeatures/Test2/Diagnostics/UseAutoProperty/{UseAutoPropertyTests.vb => UseAutoPropertyCrossLanguageUserDiagnosticTests.vb} (98%)
rename src/roslyn/src/EditorFeatures/Test2/GoToBase/{VisuaBasicGoToBaseTests.vb => VisualBasicGoToBaseTests.vb} (100%)
rename src/roslyn/src/EditorFeatures/Test2/IntelliSense/{CSharpCompletionCommandHandlerTests_AwaitCompletion.vb => CSharpCompletionCommandHandlerTests_Await.vb} (100%)
rename src/roslyn/src/EditorFeatures/Test2/IntelliSense/{CompletionServiceTests_Exclusivitiy.vb => CompletionServiceTests_Exclusivity.vb} (100%)
rename src/roslyn/src/EditorFeatures/Test2/IntelliSense/{VisualBasicCompletionCommandHandlerTests_AwaitCompletion.vb => VisualBasicCompletionCommandHandlerTests_Await.vb} (100%)
rename src/roslyn/src/EditorFeatures/Test2/Simplification/{ModuleNameSimplificationTests.vb => ModuleNameSimplifierTest.vb} (100%)
rename src/roslyn/src/EditorFeatures/Test2/Simplification/{BlockSimplificationTests.vb => SimplificationTests.vb} (100%)
delete mode 100644 src/roslyn/src/EditorFeatures/TestUtilities/Extensions/IDiagnosticServiceExtensions.cs
delete mode 100644 src/roslyn/src/Features/Core/Portable/CodeFixes/FixAllOccurrences/AbstractFixAllCodeFixCodeAction.cs
delete mode 100644 src/roslyn/src/Features/Core/Portable/CodeFixes/FixAllOccurrences/FixMultipleCodeAction.cs
delete mode 100644 src/roslyn/src/Features/Core/Portable/CodeFixesAndRefactorings/CodeActionRequestPriorityProvider.cs
delete mode 100644 src/roslyn/src/Features/Core/Portable/CodeRefactorings/FixAllOccurences/FixAllCodeRefactoringCodeAction.cs
create mode 100644 src/roslyn/src/Features/Core/Portable/Diagnostics/Service/DiagnosticAnalyzerService_ForceCodeAnalysisDiagnostics.cs
create mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/Suggestions/SuggestedAction.cs
create mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/Suggestions/SuggestedActionFlavors.cs
create mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/Suggestions/SuggestedActionSet.cs
rename src/roslyn/src/LanguageServer/Protocol/Features/{UnifiedSuggestions => Suggestions}/UnifiedPredefinedSuggestedActionCategoryNames.cs (92%)
rename src/roslyn/src/LanguageServer/Protocol/Features/{UnifiedSuggestions => Suggestions}/UnifiedSuggestedActionSetComparer.cs (92%)
rename src/roslyn/src/LanguageServer/Protocol/Features/{UnifiedSuggestions => Suggestions}/UnifiedSuggestedActionsSource.cs (65%)
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActionSet.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/ICodeFixSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/ICodeRefactoringSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/IFixAllCodeFixSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/IFixAllCodeRefactoringSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/IUnifiedSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/UnifiedCodeFixSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/UnifiedCodeRefactoringSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/UnifiedFixAllCodeFixSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/UnifiedFixAllCodeRefactoringSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/UnifiedSuggestedAction.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Features/UnifiedSuggestions/UnifiedSuggestedActions/UnifiedSuggestedActionWithNestedActions.cs
delete mode 100644 src/roslyn/src/LanguageServer/Protocol/Handler/CodeActions/FixAllCodeAction.cs
create mode 100644 src/roslyn/src/LanguageServer/Protocol/Workspaces/TrackedDocumentInfo.cs
delete mode 100644 src/roslyn/src/Tools/ExternalAccess/Razor/Features/Cohost/AbstractRazorCohostLifecycleService.cs
rename src/roslyn/src/Workspaces/Core/Portable/CodeFixesAndRefactorings/{IFixAllContext.cs => IRefactorOrFixAllContext.cs} (69%)
rename src/roslyn/src/Workspaces/Core/Portable/CodeFixesAndRefactorings/{IFixAllProvider.cs => IRefactorOrFixAllProvider.cs} (55%)
rename src/roslyn/src/Workspaces/Core/Portable/CodeFixesAndRefactorings/{IFixAllState.cs => IRefactorOrFixAllState.cs} (71%)
create mode 100644 src/roslyn/src/Workspaces/Core/Portable/CodeFixesAndRefactorings/IRefactorOrFixProvider.cs
delete mode 100644 src/roslyn/src/Workspaces/Core/Portable/CodeRefactorings/FixAllOccurences/DocumentBasedFixAllProvider.cs
create mode 100644 src/roslyn/src/Workspaces/Core/Portable/CodeRefactorings/FixAllOccurences/DocumentBasedRefactorAllProvider.cs
delete mode 100644 src/roslyn/src/Workspaces/Core/Portable/CodeRefactorings/FixAllOccurences/FixAllProvider.cs
rename src/roslyn/src/Workspaces/Core/Portable/CodeRefactorings/FixAllOccurences/{FixAllContext.cs => RefactorAllContext.cs} (50%)
create mode 100644 src/roslyn/src/Workspaces/Core/Portable/CodeRefactorings/FixAllOccurences/RefactorAllProvider.cs
create mode 100644 src/roslyn/src/Workspaces/Core/Portable/CodeRefactorings/FixAllOccurences/RefactorAllScope.cs
rename src/roslyn/src/Workspaces/Core/Portable/CodeRefactorings/FixAllOccurences/{FixAllState.cs => RefactorAllState.cs} (51%)
create mode 100644 src/roslyn/src/Workspaces/Core/Portable/Diagnostics/AnalyzerFilter.cs
create mode 100644 src/roslyn/src/Workspaces/Core/Portable/Diagnostics/DiagnosticIdFilter.cs
rename src/roslyn/src/{Features => Workspaces}/Core/Portable/Diagnostics/DiagnosticKind.cs (100%)
delete mode 100644 src/roslyn/src/Workspaces/Remote/ServiceHub/Services/DiagnosticAnalyzer/DiagnosticComputer.cs
diff --git a/src/roslyn/azure-pipelines-official.yml b/src/roslyn/azure-pipelines-official.yml
index b3869f8e8ae..e8c7a44edcc 100644
--- a/src/roslyn/azure-pipelines-official.yml
+++ b/src/roslyn/azure-pipelines-official.yml
@@ -112,6 +112,8 @@ extends:
parameters:
featureFlags:
autoBaseline: true
+ autoEnablePREfastWithNewRuleset: false
+ autoEnableRoslynWithNewRuleset: false
sdl:
sourceAnalysisPool:
name: NetCore1ESPool-Svc-Internal
@@ -410,9 +412,6 @@ extends:
- template: /eng/common/templates-official/post-build/post-build.yml@self
parameters:
publishingInfraVersion: 3
- # Symbol validation is not entirely reliable as of yet, so should be turned off until
- # https://github.com/dotnet/arcade/issues/2871 is resolved.
- enableSymbolValidation: false
enableSourceLinkValidation: false
# Enable SDL validation, passing through values from the 'DotNet-Roslyn-SDLValidation-Params' group.
SDLValidationParameters:
diff --git a/src/roslyn/azure-pipelines.yml b/src/roslyn/azure-pipelines.yml
index d2d30e15a4a..079ad3505d3 100644
--- a/src/roslyn/azure-pipelines.yml
+++ b/src/roslyn/azure-pipelines.yml
@@ -125,6 +125,10 @@ parameters:
default:
name: $(PoolName)
demands: ImageOverride -equals $(WindowsQueueName)
+ - name: macOSPool
+ type: object
+ default:
+ vmImage: macOS-15
- name: vs2022PreviewPool
type: object
default:
@@ -170,6 +174,16 @@ stages:
testArtifactName: Transport_Artifacts_Unix_Debug
poolParameters: ${{ parameters.ubuntuPool }}
+- ${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
+ - stage: MacOS_Build
+ dependsOn: []
+ jobs:
+ - template: eng/pipelines/build-unix-job.yml
+ parameters:
+ jobName: Build_macOS_Debug
+ testArtifactName: Transport_Artifacts_macOS_Debug
+ poolParameters: ${{ parameters.macOSPool }}
+
- stage: Source_Build
dependsOn: []
jobs:
@@ -370,14 +384,19 @@ stages:
testArguments: --testCoreClr
poolParameters: ${{ parameters.ubuntuPool }}
- # https://github.com/dotnet/runtime/issues/97186
- # Disabled until runtime can track down the crash
- - ${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
+- ${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
+ - stage: MacOS_Debug_CoreClr
+ dependsOn: MacOS_Build
+ variables:
+ - ${{ if ne(variables['System.TeamProject'], 'public') }}:
+ - group: DotNet-HelixApi-Access
+ jobs:
+ # https://github.com/dotnet/runtime/issues/97186
- template: eng/pipelines/test-unix-job.yml
parameters:
testRunName: 'Test macOS Debug'
jobName: Test_macOS_Debug
- testArtifactName: Transport_Artifacts_Unix_Debug
+ testArtifactName: Transport_Artifacts_macOS_Debug
configuration: Debug
testArguments: --testCoreClr
helixQueueName: $(HelixMacOsQueueName)
diff --git a/src/roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md b/src/roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md
index 816c2435e2a..a79569ad0a3 100644
--- a/src/roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md
+++ b/src/roslyn/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md
@@ -7,7 +7,7 @@ This document lists known breaking changes in Roslyn after .NET 9 general releas
***Introduced in Visual Studio 2022 version 17.13***
C# 14 introduces the ability to write a lambda with parameter modifiers, without having to specify a parameter type:
-https://github.com/dotnet/csharplang/blob/main/proposals/simple-lambda-parameters-with-modifiers.md
+[Simple lambda parameters with modifiers](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-14.0/simple-lambda-parameters-with-modifiers.md)
As part of this work, a breaking change was accepted where `scoped` will always be treated as a modifier
in a lambda parameter, even where it might have been accepted as a type name in the past. For example:
diff --git a/src/roslyn/docs/contributing/Compiler Test Plan.md b/src/roslyn/docs/contributing/Compiler Test Plan.md
index bc9d292891d..f17dddeb8ba 100644
--- a/src/roslyn/docs/contributing/Compiler Test Plan.md
+++ b/src/roslyn/docs/contributing/Compiler Test Plan.md
@@ -35,6 +35,14 @@ This document provides guidance for thinking about language interactions and tes
- Can build VS
- Check that `Obsolete` is honored for members used in binding/lowering
- LangVersion
+
+- Does the feature use cryptographic hashes in any way? (examples: metadata names of file-local types, extension types, assembly strong naming, PDB document table, etc.)
+ - Consider using non-cryptographic hash such as `XxHash128` instead.
+ - If you must use a cryptographic hash in the feature implementation, then use `SourceHashAlgorithms.Default`, and not any specific hash.
+ - A cryptographic hash must never be included in a public API name. Taking a change to the default crypto algorithm would then change public API surface, which would be enormously breaking.
+ - **DO NOT** allow using the value of a crypto hash in a field, method or type name
+ - **DO** allow using the value of a crypto hash in attribute or field values
+ - Any time the compiler reads in metadata containing crypto hashes, even if it's an attribute value, ensure the crypto hash algorithm name is included in the metadata (e.g. prefixing it to the hash value), so that it can be changed over time and the compiler can continue to read both metadata using both the old and new algorithms.
# Type and members
- Access modifiers (public, protected, internal, protected internal, private protected, private), static, ref
diff --git a/src/roslyn/eng/Directory.Packages.props b/src/roslyn/eng/Directory.Packages.props
index 1e8a1d46394..37ee560eb8a 100644
--- a/src/roslyn/eng/Directory.Packages.props
+++ b/src/roslyn/eng/Directory.Packages.props
@@ -38,10 +38,10 @@
-
-
-
-
+
+
+
+
@@ -75,6 +75,7 @@
+
@@ -117,6 +118,7 @@
+
- 2.0.0-rc.2.25427.104
+ 2.0.0-rc.2.25462.117
9.0.0
9.0.0
@@ -38,9 +38,9 @@ This file should be imported by eng/Versions.props
9.0.0
9.0.0
- 10.0.0-beta.25427.2
- 10.0.0-beta.25427.2
- 10.0.0-beta.25427.2
+ 11.0.0-beta.25462.2
+ 11.0.0-beta.25462.2
+ 11.0.0-beta.25462.2
2.0.0
diff --git a/src/roslyn/eng/Version.Details.xml b/src/roslyn/eng/Version.Details.xml
index 6792bd1be72..b854fa39af2 100644
--- a/src/roslyn/eng/Version.Details.xml
+++ b/src/roslyn/eng/Version.Details.xml
@@ -1,15 +1,15 @@
-
+
https://github.com/dotnet/roslyn
ae1fff344d46976624e68ae17164e0607ab68b10
-
+
https://github.com/dotnet/dotnet
- 7ac1ca67bb1fb8a381c1c94a9f82a97725f0ccf3
+ ee760c42a6df115208fe2262d358be6d4003e55f
@@ -115,13 +115,13 @@
-
+
https://github.com/dotnet/arcade
- ee3cae9ed3ef1990505e891831163ef34220d4e0
+ c32cd132a730a7b9f947498b2ae75dbdc6785456
-
+
https://github.com/dotnet/arcade
- ee3cae9ed3ef1990505e891831163ef34220d4e0
+ c32cd132a730a7b9f947498b2ae75dbdc6785456
https://github.com/dotnet/symreader
@@ -131,9 +131,9 @@
https://github.com/dotnet/roslyn
5d10d428050c0d6afef30a072c4ae68776621877
-
+
https://github.com/dotnet/arcade
- ee3cae9ed3ef1990505e891831163ef34220d4e0
+ c32cd132a730a7b9f947498b2ae75dbdc6785456
https://github.com/dotnet/roslyn-analyzers
diff --git a/src/roslyn/eng/Versions.props b/src/roslyn/eng/Versions.props
index aec4f310cca..25a52871980 100644
--- a/src/roslyn/eng/Versions.props
+++ b/src/roslyn/eng/Versions.props
@@ -100,6 +100,17 @@
+
+
+ 17.10.29
+ 8.0.5
+
true
false
diff --git a/src/roslyn/eng/build.sh b/src/roslyn/eng/build.sh
index caf46e4825c..a87e4b2a131 100755
--- a/src/roslyn/eng/build.sh
+++ b/src/roslyn/eng/build.sh
@@ -341,6 +341,7 @@ function GetCompilerTestAssembliesIncludePaths {
assemblies+=" --include '^Microsoft\.CodeAnalysis\.VisualBasic\.Emit\.UnitTests$'"
assemblies+=" --include '^Roslyn\.Compilers\.VisualBasic\.IOperation\.UnitTests$'"
assemblies+=" --include '^Microsoft\.CodeAnalysis\.VisualBasic\.CommandLine\.UnitTests$'"
+ assemblies+=" --include '^Microsoft\.Build\.Tasks\.CodeAnalysis\.UnitTests$'"
echo "$assemblies"
}
diff --git a/src/roslyn/eng/common/core-templates/job/publish-build-assets.yml b/src/roslyn/eng/common/core-templates/job/publish-build-assets.yml
index 348cd16376f..37dff559fc1 100644
--- a/src/roslyn/eng/common/core-templates/job/publish-build-assets.yml
+++ b/src/roslyn/eng/common/core-templates/job/publish-build-assets.yml
@@ -40,6 +40,8 @@ parameters:
repositoryAlias: self
+ officialBuildId: ''
+
jobs:
- job: Asset_Registry_Publish
@@ -62,6 +64,11 @@ jobs:
value: false
# unconditional - needed for logs publishing (redactor tool version)
- template: /eng/common/core-templates/post-build/common-variables.yml
+ - name: OfficialBuildId
+ ${{ if ne(parameters.officialBuildId, '') }}:
+ value: ${{ parameters.officialBuildId }}
+ ${{ else }}:
+ value: $(Build.BuildNumber)
pool:
# We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com)
@@ -124,7 +131,7 @@ jobs:
/p:ManifestsPath='$(Build.StagingDirectory)/AssetManifests'
/p:IsAssetlessBuild=${{ parameters.isAssetlessBuild }}
/p:MaestroApiEndpoint=https://maestro.dot.net
- /p:OfficialBuildId=$(Build.BuildNumber)
+ /p:OfficialBuildId=$(OfficialBuildId)
condition: ${{ parameters.condition }}
continueOnError: ${{ parameters.continueOnError }}
diff --git a/src/roslyn/eng/common/core-templates/jobs/jobs.yml b/src/roslyn/eng/common/core-templates/jobs/jobs.yml
index b637cb6e948..01ada747665 100644
--- a/src/roslyn/eng/common/core-templates/jobs/jobs.yml
+++ b/src/roslyn/eng/common/core-templates/jobs/jobs.yml
@@ -44,6 +44,7 @@ parameters:
artifacts: {}
is1ESPipeline: ''
repositoryAlias: self
+ officialBuildId: ''
# Internal resources (telemetry, microbuild) can only be accessed from non-public projects,
# and some (Microbuild) should only be applied to non-PR cases for internal builds.
@@ -116,3 +117,4 @@ jobs:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
signingValidationAdditionalParameters: ${{ parameters.signingValidationAdditionalParameters }}
repositoryAlias: ${{ parameters.repositoryAlias }}
+ officialBuildId: ${{ parameters.officialBuildId }}
diff --git a/src/roslyn/eng/common/core-templates/steps/generate-sbom.yml b/src/roslyn/eng/common/core-templates/steps/generate-sbom.yml
index c05f6502797..003f7eae0fa 100644
--- a/src/roslyn/eng/common/core-templates/steps/generate-sbom.yml
+++ b/src/roslyn/eng/common/core-templates/steps/generate-sbom.yml
@@ -5,7 +5,7 @@
# IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector.
parameters:
- PackageVersion: 10.0.0
+ PackageVersion: 11.0.0
BuildDropPath: '$(System.DefaultWorkingDirectory)/artifacts'
PackageName: '.NET'
ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom
diff --git a/src/roslyn/eng/common/core-templates/steps/source-index-stage1-publish.yml b/src/roslyn/eng/common/core-templates/steps/source-index-stage1-publish.yml
index e9a694afa58..eff4573c6e5 100644
--- a/src/roslyn/eng/common/core-templates/steps/source-index-stage1-publish.yml
+++ b/src/roslyn/eng/common/core-templates/steps/source-index-stage1-publish.yml
@@ -1,6 +1,6 @@
parameters:
- sourceIndexUploadPackageVersion: 2.0.0-20250818.1
- sourceIndexProcessBinlogPackageVersion: 1.0.1-20250818.1
+ sourceIndexUploadPackageVersion: 2.0.0-20250906.1
+ sourceIndexProcessBinlogPackageVersion: 1.0.1-20250906.1
sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json
binlogPath: artifacts/log/Debug/Build.binlog
diff --git a/src/roslyn/global.json b/src/roslyn/global.json
index ed08b2111bd..228f656cf87 100644
--- a/src/roslyn/global.json
+++ b/src/roslyn/global.json
@@ -1,19 +1,19 @@
{
"sdk": {
- "version": "10.0.100-preview.7.25380.108",
+ "version": "10.0.100-rc.1.25451.107",
"allowPrerelease": false,
"rollForward": "patch"
},
"tools": {
- "dotnet": "10.0.100-preview.7.25380.108",
+ "dotnet": "10.0.100-rc.1.25451.107",
"vs": {
"version": "17.14.0"
},
"vswhere": "3.1.7"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25427.2",
- "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25427.2",
+ "Microsoft.DotNet.Arcade.Sdk": "11.0.0-beta.25462.2",
+ "Microsoft.DotNet.Helix.Sdk": "11.0.0-beta.25462.2",
"Microsoft.Build.Traversal": "3.4.0"
}
}
diff --git a/src/roslyn/src/Analyzers/CSharp/CodeFixes/AddAnonymousTypeMemberName/CSharpAddAnonymousTypeMemberNameCodeFixProvider.cs b/src/roslyn/src/Analyzers/CSharp/CodeFixes/AddAnonymousTypeMemberName/CSharpAddAnonymousTypeMemberNameCodeFixProvider.cs
index 35252af110f..1ff979d1bff 100644
--- a/src/roslyn/src/Analyzers/CSharp/CodeFixes/AddAnonymousTypeMemberName/CSharpAddAnonymousTypeMemberNameCodeFixProvider.cs
+++ b/src/roslyn/src/Analyzers/CSharp/CodeFixes/AddAnonymousTypeMemberName/CSharpAddAnonymousTypeMemberNameCodeFixProvider.cs
@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.AddAnonymousTypeMemberName;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.AddAnonymousTypeMemberName;
@@ -39,5 +40,5 @@ protected override AnonymousObjectMemberDeclaratorSyntax WithName(AnonymousObjec
SyntaxFactory.IdentifierName(name)));
protected override IEnumerable GetAnonymousObjectMemberNames(AnonymousObjectCreationExpressionSyntax initializer)
- => initializer.Initializers.Where(i => i.NameEquals != null).Select(i => i.NameEquals!.Name.Identifier.ValueText);
+ => initializer.Initializers.SelectAsArray(i => i.NameEquals != null, i => i.NameEquals!.Name.Identifier.ValueText);
}
diff --git a/src/roslyn/src/Analyzers/CSharp/CodeFixes/MakeLocalFunctionStatic/MakeLocalFunctionStaticCodeFixHelper.cs b/src/roslyn/src/Analyzers/CSharp/CodeFixes/MakeLocalFunctionStatic/MakeLocalFunctionStaticCodeFixHelper.cs
index 0be3c5fc586..9027b048348 100644
--- a/src/roslyn/src/Analyzers/CSharp/CodeFixes/MakeLocalFunctionStatic/MakeLocalFunctionStaticCodeFixHelper.cs
+++ b/src/roslyn/src/Analyzers/CSharp/CodeFixes/MakeLocalFunctionStatic/MakeLocalFunctionStaticCodeFixHelper.cs
@@ -98,7 +98,8 @@ public static async Task MakeLocalFunctionStaticAsync(
var seenDefaultArgumentValue = currentInvocation.ArgumentList.Arguments.Count < localFunction.ParameterList.Parameters.Count;
// Add all the non-this parameters to the end. If there is a 'this' parameter, add it to the start.
- var newArguments = parameterAndCapturedSymbols.Where(p => !p.symbol.IsThisParameter()).Select(
+ var newArguments = parameterAndCapturedSymbols.SelectAsArray(
+ p => !p.symbol.IsThisParameter(),
symbolAndCapture => (ArgumentSyntax)generator.Argument(
seenNamedArgument || seenDefaultArgumentValue ? symbolAndCapture.symbol.Name : null,
symbolAndCapture.symbol.RefKind,
diff --git a/src/roslyn/src/Analyzers/CSharp/CodeFixes/UseImplicitOrExplicitType/UseExplicitTypeCodeFixProvider.cs b/src/roslyn/src/Analyzers/CSharp/CodeFixes/UseImplicitOrExplicitType/UseExplicitTypeCodeFixProvider.cs
index fd0d0c27082..82929bb87be 100644
--- a/src/roslyn/src/Analyzers/CSharp/CodeFixes/UseImplicitOrExplicitType/UseExplicitTypeCodeFixProvider.cs
+++ b/src/roslyn/src/Analyzers/CSharp/CodeFixes/UseImplicitOrExplicitType/UseExplicitTypeCodeFixProvider.cs
@@ -95,7 +95,7 @@ private static async Task HandleDeclarationExpressionAsync(Document document, Sy
var tupleTypeSymbol = GetConvertedType(semanticModel, typeSyntax.Parent, cancellationToken);
var leadingTrivia = declarationExpression.GetLeadingTrivia()
- .Concat(variableDesignation.GetAllPrecedingTriviaToPreviousToken().Where(t => !t.IsWhitespace()).Select(t => t.WithoutAnnotations(SyntaxAnnotation.ElasticAnnotation)));
+ .Concat(variableDesignation.GetAllPrecedingTriviaToPreviousToken().SelectAsArray(t => !t.IsWhitespace(), t => t.WithoutAnnotations(SyntaxAnnotation.ElasticAnnotation)));
var tupleDeclaration = GenerateTupleDeclaration(
semanticModel, tupleTypeSymbol, variableDesignation, cancellationToken).WithLeadingTrivia(leadingTrivia);
diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/GenerateConstructor/GenerateConstructorTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/GenerateConstructor/GenerateConstructorTests.cs
index 5ddc54f833a..2a4674e2160 100644
--- a/src/roslyn/src/Analyzers/CSharp/Tests/GenerateConstructor/GenerateConstructorTests.cs
+++ b/src/roslyn/src/Analyzers/CSharp/Tests/GenerateConstructor/GenerateConstructorTests.cs
@@ -25,7 +25,7 @@ public sealed class GenerateConstructorTests(ITestOutputHelper logger)
internal override (DiagnosticAnalyzer?, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (null, new GenerateConstructorCodeFixProvider());
- private readonly NamingStylesTestOptionSets options = new NamingStylesTestOptionSets(LanguageNames.CSharp);
+ private readonly NamingStylesTestOptionSets options = new(LanguageNames.CSharp);
[Fact]
public Task TestWithSimpleArgument()
diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs b/src/roslyn/src/Analyzers/CSharp/Tests/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs
index 37a1d66bd08..dd8c167d88a 100644
--- a/src/roslyn/src/Analyzers/CSharp/Tests/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs
+++ b/src/roslyn/src/Analyzers/CSharp/Tests/ImplementAbstractClass/ImplementAbstractClassTests_ThroughMember.cs
@@ -24,7 +24,7 @@ internal override (DiagnosticAnalyzer?, CodeFixProvider) CreateDiagnosticProvide
=> (null, new CSharpImplementAbstractClassCodeFixProvider());
private OptionsCollection AllOptionsOff
- => new OptionsCollection(GetLanguage())
+ => new(GetLanguage())
{
{ CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.NeverWithSilentEnforcement },
{ CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.NeverWithSilentEnforcement },
diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/Nullable/CSharpDeclareAsNullableCodeFixTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/Nullable/CSharpDeclareAsNullableCodeFixTests.cs
index a93373e0cdc..f65576cce4a 100644
--- a/src/roslyn/src/Analyzers/CSharp/Tests/Nullable/CSharpDeclareAsNullableCodeFixTests.cs
+++ b/src/roslyn/src/Analyzers/CSharp/Tests/Nullable/CSharpDeclareAsNullableCodeFixTests.cs
@@ -21,7 +21,7 @@ public sealed class CSharpDeclareAsNullableCodeFixTests(ITestOutputHelper logger
internal override (DiagnosticAnalyzer?, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (null, new CSharpDeclareAsNullableCodeFixProvider());
- private static readonly TestParameters s_nullableFeature = new TestParameters(parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8));
+ private static readonly TestParameters s_nullableFeature = new(parseOptions: new CSharpParseOptions(LanguageVersion.CSharp8));
[Fact]
public Task FixAll()
diff --git a/src/roslyn/src/Analyzers/CSharp/Tests/SimplifyInterpolation/SimplifyInterpolationTests.cs b/src/roslyn/src/Analyzers/CSharp/Tests/SimplifyInterpolation/SimplifyInterpolationTests.cs
index e0e67a008e3..3cbecc86a5d 100644
--- a/src/roslyn/src/Analyzers/CSharp/Tests/SimplifyInterpolation/SimplifyInterpolationTests.cs
+++ b/src/roslyn/src/Analyzers/CSharp/Tests/SimplifyInterpolation/SimplifyInterpolationTests.cs
@@ -1056,10 +1056,65 @@ struct TypeNotImplementingIFormattable
}
""");
- [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/42936")]
- public Task ToStringSimplificationIsNotOfferedOnRefStruct()
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnRefStructIfInterpolatedStringHandlersUnavailable()
+ => TestMissingInRegularAndScriptAsync(
+ """
+ class C
+ {
+ string M(RefStruct someValue) => $"Test: {someValue[||].ToString()}";
+ }
+
+ ref struct RefStruct
+ {
+ public override string ToString() => "A";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnReadOnlySpanIfInterpolatedStringHandlersUnavailable()
+ => TestMissingInRegularAndScriptAsync(
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct ReadOnlySpan { }
+ }
+
+ class C
+ {
+ string M(ReadOnlySpan span) => $"Test: {span[||].ToString()}";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnSpanIfInterpolatedStringHandlersUnavailable()
=> TestMissingInRegularAndScriptAsync(
"""
+ using System;
+
+ namespace System
+ {
+ public ref struct Span { }
+ public ref struct ReadOnlySpan { }
+ }
+
+ class C
+ {
+ string M(Span span) => $"Test: {span[||].ToString()}";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnRefStructIfInterpolatedStringHandlersAvailable()
+ => TestMissingInRegularAndScriptAsync(
+ """
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
class C
{
string M(RefStruct someValue) => $"Test: {someValue[||].ToString()}";
@@ -1071,6 +1126,223 @@ ref struct RefStruct
}
""");
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsOfferedOnReadOnlySpanOfCharIfInterpolatedStringHandlersAvailable()
+ => TestInRegularAndScriptAsync(
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ string M(ReadOnlySpan span) => $"Test: {span[||].ToString()}";
+ }
+ """,
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ string M(ReadOnlySpan span) => $"Test: {span}";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsOfferedOnSpanOfCharIfInterpolatedStringHandlersAvailable()
+ => TestInRegularAndScriptAsync(
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct Span { }
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ string M(Span span) => $"Test: {span[||].ToString()}";
+ }
+ """,
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct Span { }
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ string M(Span span) => $"Test: {span}";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnReadOnlySpanOfIntIfInterpolatedStringHandlersAvailable()
+ => TestMissingInRegularAndScriptAsync(
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ string M(ReadOnlySpan span) => $"Test: {span[||].ToString()}";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnSpanOfIntIfInterpolatedStringHandlersAvailable()
+ => TestMissingInRegularAndScriptAsync(
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct Span { }
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ string M(Span span) => $"Test: {span[||].ToString()}";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnReadOnlySpanIfTargetsFormattableStringAndInterpolatedStringHandlersAvailable()
+ => TestMissingInRegularAndScriptAsync(
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ FormattableString M(ReadOnlySpan span) => $"Test: {span[||].ToString()}";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnSpanIfTargetsFormattableStringAndInterpolatedStringHandlersAvailable()
+ => TestMissingInRegularAndScriptAsync(
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct Span { }
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ FormattableString M(Span span) => $"Test: {span[||].ToString()}";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnReadOnlySpanIfTargetsIFormattableAndInterpolatedStringHandlersAvailable()
+ => TestMissingInRegularAndScriptAsync(
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ IFormattable M(ReadOnlySpan span) => $"Test: {span[||].ToString()}";
+ }
+ """);
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/80132")]
+ public Task ToStringSimplificationIsNotOfferedOnSpanIfTargetsIFormattableAndInterpolatedStringHandlersAvailable()
+ => TestMissingInRegularAndScriptAsync(
+ """
+ using System;
+
+ namespace System
+ {
+ public ref struct Span { }
+ public ref struct ReadOnlySpan { }
+ }
+
+ namespace System.Runtime.CompilerServices
+ {
+ public class InterpolatedStringHandlerAttribute { }
+ }
+
+ class C
+ {
+ IFormattable M(Span span) => $"Test: {span[||].ToString()}";
+ }
+ """);
+
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/42936")]
public Task PadLeftSimplificationIsStillOfferedOnRefStruct()
=> TestInRegularAndScriptAsync(
@@ -1232,7 +1504,7 @@ public Task TestNotPassedToFormattableString1()
"""
class C
{
- void B() => M($"{args[||].Length.ToString()}");
+ void B(string[] args) => M($"{args[||].Length.ToString()}");
void M(FormattableString fs)
{
@@ -1242,6 +1514,32 @@ void M(FormattableString fs)
}
""");
+ [Fact]
+ public Task TestNotPassedToIFormattable()
+ => TestMissingAsync(
+ """
+ class C : ICustomFormatter, IFormatProvider
+ {
+ void B(string[] args) => M($"{args[||].Length.ToString()}");
+
+ void M(IFormattable fs)
+ {
+ fs.ToString(null, formatProvider: this);
+ }
+
+ object? IFormatProvider.GetFormat(Type? formatType)
+ {
+ return formatType == typeof(ICustomFormatter) ? this : null;
+ }
+
+ string ICustomFormatter.Format(string? format, object? arg, IFormatProvider? formatProvider)
+ {
+ Console.WriteLine(arg?.GetType());
+ return "";
+ }
+ }
+ """);
+
[Theory]
[InlineData("DateTime", "ToLongDateString", "D")]
[InlineData("DateTime", "ToShortDateString", "d")]
diff --git a/src/roslyn/src/Analyzers/Core/Analyzers/IDEDiagnosticIdToOptionMappingHelper.cs b/src/roslyn/src/Analyzers/Core/Analyzers/IDEDiagnosticIdToOptionMappingHelper.cs
index e3ae127f772..ab070b6da8c 100644
--- a/src/roslyn/src/Analyzers/Core/Analyzers/IDEDiagnosticIdToOptionMappingHelper.cs
+++ b/src/roslyn/src/Analyzers/Core/Analyzers/IDEDiagnosticIdToOptionMappingHelper.cs
@@ -31,9 +31,9 @@ public static bool TryGetMappedOptions(string diagnosticId, string language, [No
public static bool TryGetMappedFadingOption(string diagnosticId, [NotNullWhen(true)] out PerLanguageOption2? fadingOption)
=> s_diagnosticIdToFadingOptionMap.TryGetValue(diagnosticId, out fadingOption);
- public static bool IsKnownIDEDiagnosticId(string diagnosticId)
- => s_diagnosticIdToOptionMap.ContainsKey(diagnosticId) ||
- s_diagnosticIdToLanguageSpecificOptionsMap.Values.Any(map => map.ContainsKey(diagnosticId));
+ public static ImmutableHashSet KnownIDEDiagnosticIds
+ => [.. s_diagnosticIdToOptionMap.Keys,
+ .. s_diagnosticIdToLanguageSpecificOptionsMap.Values.SelectMany(map => map.Keys)];
public static void AddOptionMapping(string diagnosticId, ImmutableHashSet options)
{
diff --git a/src/roslyn/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/AbstractRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer.cs b/src/roslyn/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/AbstractRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer.cs
index e8555ba286a..e968035ca61 100644
--- a/src/roslyn/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/AbstractRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer.cs
+++ b/src/roslyn/src/Analyzers/Core/Analyzers/RemoveUnnecessarySuppressions/AbstractRemoveUnnecessaryAttributeSuppressionsDiagnosticAnalyzer.cs
@@ -68,7 +68,7 @@ protected sealed override void InitializeWorker(AnalysisContext context)
protected sealed class CompilationAnalyzer(Compilation compilation, INamedTypeSymbol suppressMessageAttributeType)
{
- private readonly SuppressMessageAttributeState _state = new SuppressMessageAttributeState(compilation, suppressMessageAttributeType);
+ private readonly SuppressMessageAttributeState _state = new(compilation, suppressMessageAttributeType);
public void AnalyzeAssemblyOrModuleAttribute(SyntaxNode attributeSyntax, SemanticModel model, Action reportDiagnostic, CancellationToken cancellationToken)
{
diff --git a/src/roslyn/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationDiagnosticAnalyzer.cs b/src/roslyn/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationDiagnosticAnalyzer.cs
index feae0e74b51..b24f3b83f33 100644
--- a/src/roslyn/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationDiagnosticAnalyzer.cs
+++ b/src/roslyn/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationDiagnosticAnalyzer.cs
@@ -36,13 +36,20 @@ protected override void InitializeWorker(AnalysisContext context)
{
var compilation = context.Compilation;
var knownToStringFormats = Helpers.BuildKnownToStringFormatsLookupTable(compilation);
- context.RegisterOperationAction(context => AnalyzeInterpolation(context, compilation.FormattableStringType(), knownToStringFormats), OperationKind.Interpolation);
+
+ var readOnlySpanOfCharType = compilation.ReadOnlySpanOfTType()?.Construct(compilation.GetSpecialType(SpecialType.System_Char));
+ var handlersAvailable = compilation.InterpolatedStringHandlerAttributeType() != null;
+
+ context.RegisterOperationAction(context => AnalyzeInterpolation(context, compilation.FormattableStringType(), compilation.IFormattableType(), readOnlySpanOfCharType, knownToStringFormats, handlersAvailable), OperationKind.Interpolation);
});
private void AnalyzeInterpolation(
OperationAnalysisContext context,
INamedTypeSymbol? formattableStringType,
- ImmutableDictionary knownToStringFormats)
+ INamedTypeSymbol? iFormattableType,
+ INamedTypeSymbol? readOnlySpanOfCharType,
+ ImmutableDictionary knownToStringFormats,
+ bool handlersAvailable)
{
var option = context.GetAnalyzerOptions().PreferSimplifiedInterpolation;
@@ -55,7 +62,7 @@ private void AnalyzeInterpolation(
// Formattable strings can observe the inner types of the arguments passed to them. So we can't safely change
// to drop ToString in that.
if (interpolation.Parent is IInterpolatedStringOperation { Parent: IConversionOperation { Type: { } convertedType } conversion } &&
- convertedType.Equals(formattableStringType))
+ (convertedType.Equals(formattableStringType) || convertedType.Equals(iFormattableType)))
{
// One exception to this is calling directly into FormattableString.Invariant. That method has known good
// behavior that is fine to continue calling into.
@@ -68,7 +75,7 @@ private void AnalyzeInterpolation(
}
this.Helpers.UnwrapInterpolation(
- this.VirtualCharService, this.SyntaxFacts, interpolation, knownToStringFormats, out _, out var alignment, out _,
+ this.VirtualCharService, this.SyntaxFacts, interpolation, knownToStringFormats, readOnlySpanOfCharType, handlersAvailable, out _, out var alignment, out _,
out var formatString, out var unnecessaryLocations);
if (alignment == null && formatString == null)
diff --git a/src/roslyn/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationHelpers.cs b/src/roslyn/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationHelpers.cs
index dfe238707ed..a66b3581257 100644
--- a/src/roslyn/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationHelpers.cs
+++ b/src/roslyn/src/Analyzers/Core/Analyzers/SimplifyInterpolation/AbstractSimplifyInterpolationHelpers.cs
@@ -65,6 +65,8 @@ public void UnwrapInterpolation(
ISyntaxFacts syntaxFacts,
IInterpolationOperation interpolation,
ImmutableDictionary knownToStringFormats,
+ INamedTypeSymbol? readOnlySpanOfCharType,
+ bool handlersAvailable,
out TExpressionSyntax? unwrapped,
out TExpressionSyntax? alignment,
out bool negate,
@@ -82,7 +84,7 @@ public void UnwrapInterpolation(
UnwrapAlignmentPadding(expression, out expression, out alignment, out negate, unnecessarySpans);
if (interpolation.FormatString == null)
- UnwrapFormatString(virtualCharService, syntaxFacts, expression, knownToStringFormats, out expression, out formatString, unnecessarySpans);
+ UnwrapFormatString(virtualCharService, syntaxFacts, expression, knownToStringFormats, readOnlySpanOfCharType, handlersAvailable, out expression, out formatString, unnecessarySpans);
unwrapped = GetPreservedInterpolationExpressionSyntax(expression) as TExpressionSyntax;
@@ -118,6 +120,8 @@ private void UnwrapFormatString(
ISyntaxFacts syntaxFacts,
IOperation expression,
ImmutableDictionary knownToStringFormats,
+ INamedTypeSymbol? readOnlySpanOfCharType,
+ bool handlersAvailable,
out IOperation unwrapped,
out string? formatString,
ArrayBuilder unnecessarySpans)
@@ -128,41 +132,43 @@ private void UnwrapFormatString(
HasNonImplicitInstance(invocation, out var instance) &&
!syntaxFacts.IsBaseExpression(instance.Syntax))
{
- if (targetMethod.Name == nameof(ToString) &&
- instance.Type is { IsRefLikeType: false })
+ if (targetMethod.Name == nameof(ToString))
{
- if (invocation.Arguments.Length == 1
- || (invocation.Arguments.Length == 2 && UsesInvariantCultureReferenceInsideFormattableStringInvariant(invocation, formatProviderArgumentIndex: 1)))
+ // If type of instance is not ref-like type or is {ReadOnly}Span that is allowed in interpolated strings in .NET 6+
+ if (instance.Type is { IsRefLikeType: false } || IsRefLikeTypeAllowed(instance.Type))
{
- if (invocation.Arguments[0].Value is ILiteralOperation { ConstantValue: { HasValue: true, Value: string value } } literal &&
- FindType(expression.SemanticModel) is { } systemIFormattable &&
- instance.Type.Implements(systemIFormattable))
+ if (invocation.Arguments.Length == 1
+ || (invocation.Arguments.Length == 2 && UsesInvariantCultureReferenceInsideFormattableStringInvariant(invocation, formatProviderArgumentIndex: 1)))
{
+ if (invocation.Arguments[0].Value is ILiteralOperation { ConstantValue: { HasValue: true, Value: string value } } literal &&
+ FindType(expression.SemanticModel) is { } systemIFormattable &&
+ instance.Type.Implements(systemIFormattable))
+ {
+ unwrapped = instance;
+ formatString = value;
+
+ unnecessarySpans.AddRange(invocation.Syntax.Span
+ .Subtract(GetPreservedInterpolationExpressionSyntax(instance).FullSpan)
+ .Subtract(GetSpanWithinLiteralQuotes(virtualCharService, literal.Syntax.GetFirstToken())));
+ return;
+ }
+ }
+
+ if (IsObjectToStringOverride(invocation.TargetMethod)
+ || (invocation.Arguments.Length == 1 && UsesInvariantCultureReferenceInsideFormattableStringInvariant(invocation, formatProviderArgumentIndex: 0)))
+ {
+ // A call to `.ToString()` at the end of the interpolation. This is unnecessary.
+ // Just remove entirely.
unwrapped = instance;
- formatString = value;
+ formatString = "";
unnecessarySpans.AddRange(invocation.Syntax.Span
- .Subtract(GetPreservedInterpolationExpressionSyntax(instance).FullSpan)
- .Subtract(GetSpanWithinLiteralQuotes(virtualCharService, literal.Syntax.GetFirstToken())));
+ .Subtract(GetPreservedInterpolationExpressionSyntax(instance).FullSpan));
return;
}
}
-
- if (IsObjectToStringOverride(invocation.TargetMethod)
- || (invocation.Arguments.Length == 1 && UsesInvariantCultureReferenceInsideFormattableStringInvariant(invocation, formatProviderArgumentIndex: 0)))
- {
- // A call to `.ToString()` at the end of the interpolation. This is unnecessary.
- // Just remove entirely.
- unwrapped = instance;
- formatString = "";
-
- unnecessarySpans.AddRange(invocation.Syntax.Span
- .Subtract(GetPreservedInterpolationExpressionSyntax(instance).FullSpan));
- return;
- }
}
-
- if (knownToStringFormats.TryGetValue(targetMethod, out var format))
+ else if (knownToStringFormats.TryGetValue(targetMethod, out var format))
{
// A call to a known ToString-like method, e.g. `DateTime.ToLongDateString()`
// We replace this call with predefined format specifier
@@ -177,6 +183,13 @@ private void UnwrapFormatString(
unwrapped = expression;
formatString = null;
+
+ bool IsRefLikeTypeAllowed([NotNullWhen(true)] ITypeSymbol? type)
+ {
+ var compilation = expression.SemanticModel.Compilation;
+ // {ReadOnly}Span is allowed if interpolated string handlers are available in the compilation (.NET 6+)
+ return handlersAvailable && compilation.HasImplicitConversion(type, readOnlySpanOfCharType);
+ }
}
private static bool IsObjectToStringOverride(IMethodSymbol method)
diff --git a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateConstructor/AbstractGenerateConstructorService.State.cs b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateConstructor/AbstractGenerateConstructorService.State.cs
index dedd78ae4df..9e120dbee99 100644
--- a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateConstructor/AbstractGenerateConstructorService.State.cs
+++ b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateConstructor/AbstractGenerateConstructorService.State.cs
@@ -234,7 +234,7 @@ await GetParametersAsync(
}
private TLanguageService GetRequiredLanguageService(string language) where TLanguageService : ILanguageService
- => _document.Project.Solution.Workspace.Services.GetExtendedLanguageServices(language).GetRequiredService();
+ => _document.Project.Solution.GetRequiredLanguageService(language);
private bool ClashesWithExistingConstructor()
{
diff --git a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateEnumMember/AbstractGenerateEnumMemberService.CodeAction.cs b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateEnumMember/AbstractGenerateEnumMemberService.CodeAction.cs
index 51855dbec33..c008fab550a 100644
--- a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateEnumMember/AbstractGenerateEnumMemberService.CodeAction.cs
+++ b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateEnumMember/AbstractGenerateEnumMemberService.CodeAction.cs
@@ -8,6 +8,7 @@
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.LanguageService;
+using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
namespace Microsoft.CodeAnalysis.GenerateMember.GenerateEnumMember;
@@ -21,7 +22,7 @@ private sealed partial class GenerateEnumMemberCodeAction(Document document, Sta
protected override async Task GetChangedDocumentAsync(CancellationToken cancellationToken)
{
- var languageServices = _document.Project.Solution.Workspace.Services.GetExtendedLanguageServices(_state.TypeToGenerateIn.Language);
+ var languageServices = _document.Project.Solution.GetExtendedLanguageServices(_state.TypeToGenerateIn.Language);
var codeGenerator = languageServices.GetRequiredService();
var semanticFacts = languageServices.GetRequiredService();
diff --git a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.SignatureInfo.cs b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.SignatureInfo.cs
index 3a0fca8de4c..efe083d293c 100644
--- a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.SignatureInfo.cs
+++ b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.SignatureInfo.cs
@@ -118,9 +118,7 @@ public async ValueTask GenerateMethodAsync(
methodKind: State.MethodKind);
// Ensure no conflicts between type parameter names and parameter names.
- var languageServiceProvider = Document.Project.Solution.Workspace.Services.GetExtendedLanguageServices(State.TypeToGenerateIn.Language);
-
- var syntaxFacts = languageServiceProvider.GetService();
+ var syntaxFacts = Document.Project.Solution.GetLanguageService(State.TypeToGenerateIn.Language);
var equalityComparer = syntaxFacts.StringComparer;
var reservedParameterNames = DetermineParameterNames(cancellationToken)
diff --git a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.State.cs b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.State.cs
index ce6a1619e54..24c4323b4a1 100644
--- a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.State.cs
+++ b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.State.cs
@@ -82,7 +82,7 @@ protected async Task TryFinishInitializingStateAsync(TService service, Sem
.GetMembers(IdentifierToken.ValueText)
.OfType();
- var destinationProvider = document.Project.Solution.Workspace.Services.GetExtendedLanguageServices(TypeToGenerateIn.Language);
+ var destinationProvider = document.Project.Solution.GetExtendedLanguageServices(TypeToGenerateIn.Language);
var syntaxFacts = destinationProvider.GetService();
var syntaxFactory = destinationProvider.GetService();
diff --git a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.cs b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.cs
index 2d502a68a92..378e204090f 100644
--- a/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.cs
+++ b/src/roslyn/src/Analyzers/Core/CodeFixes/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.cs
@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.PooledObjects;
+using Microsoft.CodeAnalysis.Shared.Extensions;
namespace Microsoft.CodeAnalysis.GenerateMember.GenerateParameterizedMember;
@@ -48,9 +49,7 @@ protected async ValueTask> GetActionsAsync(Document d
if (canGenerateAbstractly)
result.Add(new GenerateParameterizedMemberCodeAction((TService)this, document, state, isAbstract: true, generateProperty: false));
- var semanticFacts = document.Project.Solution.Workspace.Services
- .GetExtendedLanguageServices(state.TypeToGenerateIn.Language)
- .GetRequiredService();
+ var semanticFacts = document.Project.Solution.GetRequiredLanguageService(state.TypeToGenerateIn.Language);
if (semanticFacts.SupportsParameterizedProperties &&
state.InvocationExpressionOpt != null)
diff --git a/src/roslyn/src/Analyzers/Core/CodeFixes/SimplifyInterpolation/AbstractSimplifyInterpolationCodeFixProvider.cs b/src/roslyn/src/Analyzers/Core/CodeFixes/SimplifyInterpolation/AbstractSimplifyInterpolationCodeFixProvider.cs
index b5911cb66c3..88f5603c5e8 100644
--- a/src/roslyn/src/Analyzers/Core/CodeFixes/SimplifyInterpolation/AbstractSimplifyInterpolationCodeFixProvider.cs
+++ b/src/roslyn/src/Analyzers/Core/CodeFixes/SimplifyInterpolation/AbstractSimplifyInterpolationCodeFixProvider.cs
@@ -48,12 +48,16 @@ protected override async Task FixAllAsync(
SyntaxEditor editor, CancellationToken cancellationToken)
{
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
+ var compilation = semanticModel.Compilation;
var generator = editor.Generator;
var generatorInternal = document.GetRequiredLanguageService();
var helpers = this.Helpers;
var knownToStringFormats = helpers.BuildKnownToStringFormatsLookupTable(semanticModel.Compilation);
+ var readOnlySpanOfCharType = compilation.ReadOnlySpanOfTType()?.Construct(compilation.GetSpecialType(SpecialType.System_Char));
+ var handlersAvailable = compilation.InterpolatedStringHandlerAttributeType() != null;
+
foreach (var diagnostic in diagnostics)
{
var node = diagnostic.AdditionalLocations[0].FindNode(getInnermostNodeForTie: true, cancellationToken);
@@ -64,7 +68,7 @@ protected override async Task FixAllAsync(
helpers.UnwrapInterpolation(
document.GetRequiredLanguageService(),
document.GetRequiredLanguageService(),
- interpolation, knownToStringFormats, out var unwrapped, out var alignment, out var negate, out var formatString, out _);
+ interpolation, knownToStringFormats, readOnlySpanOfCharType, handlersAvailable, out var unwrapped, out var alignment, out var negate, out var formatString, out _);
if (unwrapped == null)
continue;
diff --git a/src/roslyn/src/CodeStyle/CSharp/Tests/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_OptionHelpers.cs b/src/roslyn/src/CodeStyle/CSharp/Tests/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_OptionHelpers.cs
index bb91cf3e508..efad3c25d9e 100644
--- a/src/roslyn/src/CodeStyle/CSharp/Tests/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_OptionHelpers.cs
+++ b/src/roslyn/src/CodeStyle/CSharp/Tests/AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_OptionHelpers.cs
@@ -34,20 +34,20 @@ internal static (OptionKey2, object) SingleOption(PerLanguageOption2 (new OptionKey2(option, language), codeStyle);
internal OptionsCollection Option(Option2> option, T enabled, NotificationOption2 notification)
- => new OptionsCollection(GetLanguage()) { { option, enabled, notification } };
+ => new(GetLanguage()) { { option, enabled, notification } };
internal OptionsCollection Option(Option2> option, CodeStyleOption2 codeStyle)
- => new OptionsCollection(GetLanguage()) { { option, codeStyle } };
+ => new(GetLanguage()) { { option, codeStyle } };
internal OptionsCollection Option(PerLanguageOption2> option, T enabled, NotificationOption2 notification)
- => new OptionsCollection(GetLanguage()) { { option, enabled, notification } };
+ => new(GetLanguage()) { { option, enabled, notification } };
internal OptionsCollection Option(PerLanguageOption2> option, CodeStyleOption2 codeStyle)
- => new OptionsCollection(GetLanguage()) { { option, codeStyle } };
+ => new(GetLanguage()) { { option, codeStyle } };
internal OptionsCollection Option(Option2 option, T value)
- => new OptionsCollection(GetLanguage()) { { option, value } };
+ => new(GetLanguage()) { { option, value } };
internal OptionsCollection Option(PerLanguageOption2 option, T value)
- => new OptionsCollection(GetLanguage()) { { option, value } };
+ => new(GetLanguage()) { { option, value } };
}
diff --git a/src/roslyn/src/CodeStyle/Core/CodeFixes/Host/Mef/CodeStyleHostLanguageServices.MefHostExportProvider.cs b/src/roslyn/src/CodeStyle/Core/CodeFixes/Host/Mef/CodeStyleHostLanguageServices.MefHostExportProvider.cs
index a62af922ab2..d5b5649ba4f 100644
--- a/src/roslyn/src/CodeStyle/Core/CodeFixes/Host/Mef/CodeStyleHostLanguageServices.MefHostExportProvider.cs
+++ b/src/roslyn/src/CodeStyle/Core/CodeFixes/Host/Mef/CodeStyleHostLanguageServices.MefHostExportProvider.cs
@@ -10,10 +10,8 @@ namespace Microsoft.CodeAnalysis.Host;
internal sealed partial class CodeStyleHostLanguageServices : HostLanguageServices
{
- private static readonly ConditionalWeakTable s_mappedLanguageServices =
- new ConditionalWeakTable();
- private static readonly ConditionalWeakTable s_exportProvidersByLanguageCache =
- new ConditionalWeakTable();
+ private static readonly ConditionalWeakTable s_mappedLanguageServices = new();
+ private static readonly ConditionalWeakTable s_exportProvidersByLanguageCache = new();
private readonly HostLanguageServices _hostLanguageServices;
private readonly HostLanguageServices _codeStyleLanguageServices;
@@ -35,7 +33,7 @@ public static CodeStyleHostLanguageServices GetRequiredMappedCodeStyleLanguageSe
=> s_mappedLanguageServices.GetValue(hostLanguageServices, Create);
private static CodeStyleHostLanguageServices Create(HostLanguageServices hostLanguageServices)
- => new CodeStyleHostLanguageServices(hostLanguageServices);
+ => new(hostLanguageServices);
public override HostWorkspaceServices WorkspaceServices => _hostLanguageServices.WorkspaceServices;
diff --git a/src/roslyn/src/CodeStyle/Tools/Program.cs b/src/roslyn/src/CodeStyle/Tools/Program.cs
index 19979aa8d9c..ef1992aaf70 100644
--- a/src/roslyn/src/CodeStyle/Tools/Program.cs
+++ b/src/roslyn/src/CodeStyle/Tools/Program.cs
@@ -255,9 +255,9 @@ and an implied numerical option (such as '4') -->
<_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysis{language}CodeStyle Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysis{language}CodeStyle)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysis{language}CodeStyle)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysis{language}CodeStyle)
-
+
+ ('$(AnalysisLevelStyle)' != '$(AnalysisLevel)' or '$(AnalysisModeStyle)' != '$(AnalysisMode)' or ('$(EffectiveAnalysisLevelStyle)' != '' and $([MSBuild]::VersionGreaterThanOrEquals('$(EffectiveAnalysisLevelStyle)', '11.0'))))">
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs b/src/roslyn/src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs
index bc1173c91df..148146b5054 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Binder/Binder_Crefs.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
@@ -224,12 +225,6 @@ private ImmutableArray BindExtensionMemberCref(ExtensionMemberCrefSyntax
{
CheckFeatureAvailability(syntax, MessageID.IDS_FeatureExtensions, diagnostics);
- if (containerOpt is not NamedTypeSymbol namedContainer)
- {
- ambiguityWinner = null;
- return ImmutableArray.Empty;
- }
-
int arity = 0;
TypeArgumentListSyntax? typeArgumentListSyntax = null;
CrefParameterListSyntax? parameters = null;
@@ -256,7 +251,7 @@ private ImmutableArray BindExtensionMemberCref(ExtensionMemberCrefSyntax
TypeArgumentListSyntax? extensionTypeArguments = syntax.TypeArgumentList;
int extensionArity = extensionTypeArguments?.Arguments.Count ?? 0;
- ImmutableArray sortedSymbols = computeSortedAndFilteredCrefExtensionMembers(namedContainer, memberName, extensionArity, arity, extensionTypeArguments, diagnostics, syntax);
+ ImmutableArray sortedSymbols = computeSortedAndFilteredCrefExtensionMembers(containerOpt, memberName, extensionArity, arity, extensionTypeArguments, diagnostics, syntax);
if (sortedSymbols.IsDefaultOrEmpty)
{
@@ -268,7 +263,7 @@ private ImmutableArray BindExtensionMemberCref(ExtensionMemberCrefSyntax
return ProcessCrefMemberLookupResults(sortedSymbols, arity, syntax, typeArgumentListSyntax, parameters, out ambiguityWinner, diagnostics);
- ImmutableArray computeSortedAndFilteredCrefExtensionMembers(NamedTypeSymbol container, string name, int extensionArity, int arity, TypeArgumentListSyntax? extensionTypeArguments, BindingDiagnosticBag diagnostics, ExtensionMemberCrefSyntax syntax)
+ ImmutableArray computeSortedAndFilteredCrefExtensionMembers(NamespaceOrTypeSymbol? containerOpt, string name, int extensionArity, int arity, TypeArgumentListSyntax? extensionTypeArguments, BindingDiagnosticBag diagnostics, ExtensionMemberCrefSyntax syntax)
{
Debug.Assert(name is not null);
@@ -295,9 +290,12 @@ ImmutableArray computeSortedAndFilteredCrefExtensionMembers(NamedTypeSym
CompoundUseSiteInfo useSiteInfo = this.GetNewCompoundUseSiteInfo(diagnostics);
ArrayBuilder? sortedSymbolsBuilder = null;
- foreach (var nested in container.GetTypeMembers())
+ foreach (var nested in candidateTypes(containerOpt))
{
- if (!nested.IsExtension || nested.Arity != extensionArity || nested.ExtensionParameter is null)
+ if (!nested.IsExtension
+ || nested.Arity != extensionArity
+ || nested.ExtensionParameter is null
+ || nested is not { ContainingType: { ContainingType: null } }) // only consider extension blocks in top-level types
{
continue;
}
@@ -364,6 +362,23 @@ ImmutableArray computeSortedAndFilteredCrefExtensionMembers(NamedTypeSym
}
return sortedSymbolsBuilder.ToImmutableAndFree();
+
+ ImmutableArray candidateTypes(NamespaceOrTypeSymbol? containerOpt)
+ {
+ if (containerOpt is NamedTypeSymbol namedType)
+ {
+ return namedType.GetTypeMembers("");
+ }
+
+ NamedTypeSymbol? containingType = ContainingType;
+ if (containingType is null)
+ {
+ return [];
+ }
+
+ NamedTypeSymbol? enclosingType = containingType.IsExtension ? containingType.ContainingType : containingType;
+ return enclosingType?.GetTypeMembers("") ?? [];
+ }
}
}
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/roslyn/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
index edc5a1bdea0..79c30426737 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
@@ -748,6 +748,8 @@ private BoundExpression BindMethodGroupInvocation(
ImmutableArray originalMethods;
LookupResultKind resultKind;
ImmutableArray typeArguments;
+ BoundExpression receiverOpt = methodGroup.ReceiverOpt;
+
if (resolution.OverloadResolutionResult != null)
{
originalMethods = GetOriginalMethods(resolution.OverloadResolutionResult);
@@ -759,12 +761,25 @@ private BoundExpression BindMethodGroupInvocation(
originalMethods = methodGroup.Methods;
resultKind = methodGroup.ResultKind;
typeArguments = methodGroup.TypeArgumentsOpt;
+
+ if (originalMethods.IsEmpty && methodGroup.LookupSymbolOpt is { })
+ {
+ Debug.Assert(methodGroup.LookupSymbolOpt is not MethodSymbol);
+
+ // Create receiver as BindMemberAccessBadResult does
+ receiverOpt = new BoundBadExpression(
+ methodGroup.Syntax,
+ methodGroup.ResultKind,
+ [methodGroup.LookupSymbolOpt],
+ receiverOpt == null ? [] : [receiverOpt],
+ GetNonMethodMemberType(methodGroup.LookupSymbolOpt));
+ }
}
result = CreateBadCall(
syntax,
methodName,
- methodGroup.ReceiverOpt,
+ receiverOpt,
originalMethods,
resultKind,
typeArguments,
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/roslyn/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
index 1f3ac35d1a2..574d0704b02 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
@@ -1261,7 +1261,7 @@ private void GetDisposalInfoForEnumerator(SyntaxNode syntax, ref ForEachEnumerat
}
}
- if (implementsInterface(enumeratorType, isAsync, diagnostics))
+ if (implementsInterface(builder.CollectionType, enumeratorType, isAsync, diagnostics))
{
builder.NeedsDisposal = true;
return;
@@ -1281,7 +1281,7 @@ private void GetDisposalInfoForEnumerator(SyntaxNode syntax, ref ForEachEnumerat
}
}
- bool implementsInterface(TypeSymbol enumeratorType, bool isAsync, BindingDiagnosticBag diagnostics)
+ bool implementsInterface(TypeSymbol collectionType, TypeSymbol enumeratorType, bool isAsync, BindingDiagnosticBag diagnostics)
{
CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
@@ -1295,7 +1295,8 @@ bool implementsInterface(TypeSymbol enumeratorType, bool isAsync, BindingDiagnos
diagnostics.Add(syntax, useSiteInfo);
if (needSupportForRefStructInterfaces &&
- enumeratorType.ContainingModule != Compilation.SourceModule)
+ enumeratorType.ContainingModule != Compilation.SourceModule &&
+ !LocalRewriter.CanRewriteForEachAsFor(Compilation, syntax, collectionType, out _, out _, BindingDiagnosticBag.Discarded))
{
CheckFeatureAvailability(syntax, MessageID.IDS_FeatureRefStructInterfaces, diagnostics);
}
@@ -1824,7 +1825,8 @@ private bool AllInterfacesContainsIEnumerable(
}
}
- if (implementedIEnumerable is not null && needSupportForRefStructInterfaces && type.ContainingModule != Compilation.SourceModule)
+ if (implementedIEnumerable is not null && needSupportForRefStructInterfaces && type.ContainingModule != Compilation.SourceModule &&
+ !LocalRewriter.CanRewriteForEachAsFor(Compilation, collectionSyntax, type, out _, out _, BindingDiagnosticBag.Discarded))
{
CheckFeatureAvailability(collectionSyntax, MessageID.IDS_FeatureRefStructInterfaces, diagnostics);
}
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs b/src/roslyn/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs
index d34dc9c50ac..0e6feb2437f 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Binder/RefSafetyAnalysis.cs
@@ -1147,7 +1147,7 @@ private void VisitDeconstructionArguments(ArrayBuilder v
{
var (placeholder, placeholderConversion) = conversion.DeconstructConversionInfo[i];
var underlyingConversion = BoundNode.GetConversion(placeholderConversion, placeholder);
- VisitDeconstructionArguments(nestedVariables, syntax, underlyingConversion, right: invocation.Arguments[i + offset]);
+ VisitDeconstructionArguments(nestedVariables, syntax, underlyingConversion, right: methodInvocationInfo.ArgsOpt[i + offset]);
}
}
}
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Binder/WithCrefTypeParametersBinder.cs b/src/roslyn/src/Compilers/CSharp/Portable/Binder/WithCrefTypeParametersBinder.cs
index 556e32c5621..fa09e8f2d01 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Binder/WithCrefTypeParametersBinder.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Binder/WithCrefTypeParametersBinder.cs
@@ -63,6 +63,7 @@ private MultiDictionary CreateTypeParameterMap()
case SyntaxKind.IndexerMemberCref:
case SyntaxKind.OperatorMemberCref:
case SyntaxKind.ConversionOperatorMemberCref:
+ case SyntaxKind.ExtensionMemberCref:
{
AddTypeParameters((MemberCrefSyntax)_crefSyntax, map);
break;
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/roslyn/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
index b1fba6ed796..e3e34c54dcf 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
@@ -106,16 +106,22 @@ internal BoundLambda WithInAnonymousFunctionConversion()
public TypeWithAnnotations GetInferredReturnType(ref CompoundUseSiteInfo useSiteInfo, out bool inferredFromFunctionType)
{
// Nullability (and conversions) are ignored.
- return GetInferredReturnType(conversions: null, nullableState: null, ref useSiteInfo, out inferredFromFunctionType);
+ return GetInferredReturnType(conversions: null, nullableState: null, getterNullResilienceData: null, ref useSiteInfo, out inferredFromFunctionType);
}
///
/// Infer return type. If `nullableState` is non-null, nullability is also inferred and `NullableWalker.Analyze`
/// uses that state to set the inferred nullability of variables in the enclosing scope. `conversions` is
/// only needed when nullability is inferred.
+ ///
+ /// If 'getterNullResilienceData' is non-null, it is propagated down to the child analysis pass,
+ /// so that it does not attempt to infer the field's nullable annotation, while a parent pass is also attempting to infer that.
///
- public TypeWithAnnotations GetInferredReturnType(ConversionsBase? conversions, NullableWalker.VariableState? nullableState, ref CompoundUseSiteInfo useSiteInfo, out bool inferredFromFunctionType)
+ public TypeWithAnnotations GetInferredReturnType(ConversionsBase? conversions, NullableWalker.VariableState? nullableState, NullableWalker.GetterNullResilienceData? getterNullResilienceData, ref CompoundUseSiteInfo useSiteInfo, out bool inferredFromFunctionType)
{
+ // Cannot pass 'getterNullResilienceData' without also passing 'nullableState'.
+ Debug.Assert(getterNullResilienceData is null || nullableState is not null);
+
if (!InferredReturnType.UseSiteDiagnostics.IsEmpty)
{
useSiteInfo.AddDiagnostics(InferredReturnType.UseSiteDiagnostics);
@@ -151,7 +157,8 @@ public TypeWithAnnotations GetInferredReturnType(ConversionsBase? conversions, N
diagnostics,
delegateInvokeMethodOpt: delegateType?.DelegateInvokeMethod,
initialState: nullableState,
- returnTypes);
+ returnTypes,
+ getterNullResilienceData);
diagnostics.Free();
inferredReturnType = InferReturnType(returnTypes, node: this, Binder, delegateType, Symbol.IsAsync, conversions);
returnTypes.Free();
@@ -386,6 +393,7 @@ protected override BoundNode VisitExpressionOrPatternWithoutStackGuard(BoundNode
internal partial class UnboundLambda
{
private readonly NullableWalker.VariableState? _nullableState;
+ private readonly NullableWalker.GetterNullResilienceData? _getterNullResilienceData;
public static UnboundLambda Create(
CSharpSyntaxNode syntax,
@@ -417,16 +425,17 @@ public static UnboundLambda Create(
return lambda;
}
- private UnboundLambda(SyntaxNode syntax, UnboundLambdaState state, FunctionTypeSymbol? functionType, bool withDependencies, NullableWalker.VariableState? nullableState, bool hasErrors) :
+ private UnboundLambda(SyntaxNode syntax, UnboundLambdaState state, FunctionTypeSymbol? functionType, bool withDependencies, NullableWalker.VariableState? nullableState, NullableWalker.GetterNullResilienceData? getterNullResilienceData, bool hasErrors) :
this(syntax, state, functionType, withDependencies, hasErrors)
{
this._nullableState = nullableState;
+ this._getterNullResilienceData = getterNullResilienceData;
}
- internal UnboundLambda WithNullableState(NullableWalker.VariableState nullableState)
+ internal UnboundLambda WithNullabilityInfo(NullableWalker.VariableState nullableState, NullableWalker.GetterNullResilienceData? getterNullResilienceData)
{
var data = Data.WithCaching(true);
- var lambda = new UnboundLambda(Syntax, data, FunctionType, WithDependencies, nullableState, HasErrors);
+ var lambda = new UnboundLambda(Syntax, data, FunctionType, WithDependencies, nullableState, getterNullResilienceData, HasErrors);
data.SetUnboundLambda(lambda);
return lambda;
}
@@ -439,7 +448,7 @@ internal UnboundLambda WithNoCache()
return this;
}
- var lambda = new UnboundLambda(Syntax, data, FunctionType, WithDependencies, _nullableState, HasErrors);
+ var lambda = new UnboundLambda(Syntax, data, FunctionType, WithDependencies, _nullableState, _getterNullResilienceData, HasErrors);
data.SetUnboundLambda(lambda);
return lambda;
}
@@ -482,7 +491,7 @@ public Binder GetWithParametersBinder(LambdaSymbol lambdaSymbol, Binder binder)
public int ParameterCount { get { return Data.ParameterCount; } }
public TypeWithAnnotations InferReturnType(ConversionsBase conversions, NamedTypeSymbol delegateType, ref CompoundUseSiteInfo useSiteInfo, out bool inferredFromFunctionType)
- => BindForReturnTypeInference(delegateType).GetInferredReturnType(conversions, _nullableState, ref useSiteInfo, out inferredFromFunctionType);
+ => BindForReturnTypeInference(delegateType).GetInferredReturnType(conversions, _nullableState, _getterNullResilienceData, ref useSiteInfo, out inferredFromFunctionType);
public RefKind RefKind(int index) { return Data.RefKind(index); }
public ScopedKind DeclaredScope(int index) { return Data.DeclaredScope(index); }
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Compiler/ClsComplianceChecker.cs b/src/roslyn/src/Compilers/CSharp/Portable/Compiler/ClsComplianceChecker.cs
index ee26ea798f7..7ff548c3126 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Compiler/ClsComplianceChecker.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Compiler/ClsComplianceChecker.cs
@@ -529,7 +529,7 @@ private void CheckBaseTypeCompliance(NamedTypeSymbol symbol)
else
{
NamedTypeSymbol baseType = symbol.EnumUnderlyingType ?? symbol.BaseTypeNoUseSiteDiagnostics; // null for interfaces
- System.Diagnostics.Debug.Assert((object)baseType != null || symbol.SpecialType == SpecialType.System_Object, "Only object has no base.");
+ System.Diagnostics.Debug.Assert((object)baseType != null || symbol.SpecialType == SpecialType.System_Object || symbol.IsExtension, "Only object or extension has no base.");
if ((object)baseType != null && !IsCompliantType(baseType, symbol))
{
// TODO: it would be nice to report this on the base type clause.
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs b/src/roslyn/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs
index e6e11d2093a..3eff3de5721 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs
@@ -2634,6 +2634,8 @@ protected void CheckAssigned(BoundExpression expr, SyntaxNode node)
#nullable enable
private void MarkFieldsUsed(TypeSymbol type)
{
+ type = type.OriginalDefinition;
+
switch (type.TypeKind)
{
case TypeKind.Array:
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/roslyn/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
index 91ff699e3d3..27a0784da34 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
@@ -43,6 +43,25 @@ internal NullableAnalysisData(int maxRecursionDepth = -1)
}
}
+ ///
+ /// Additional info for getter null resilience analysis.
+ /// When this value is passed down through 'Analyze()', it means we are in the process of inferring the nullable annotation of 'field'.
+ /// The 'assumedAnnotation' should be used as the field's nullable annotation for this analysis pass.
+ /// See https://github.com/dotnet/csharplang/blob/229406aa6dc51c1e37b98e90eb868d979ec6d195/proposals/csharp-14.0/field-keyword.md#nullability-of-the-backing-field
+ ///
+ /// Indicates whether the *not-annotated* pass or the *annotated* pass is being performed.
+ internal readonly struct GetterNullResilienceData(SynthesizedBackingFieldSymbol field, NullableAnnotation assumedAnnotation)
+ {
+ public readonly SynthesizedBackingFieldSymbol field = field;
+ public readonly NullableAnnotation assumedAnnotation = assumedAnnotation;
+
+ public void Deconstruct(out SynthesizedBackingFieldSymbol field, out NullableAnnotation assumedAnnotation)
+ {
+ field = this.field;
+ assumedAnnotation = this.assumedAnnotation;
+ }
+ }
+
///
/// Used to copy variable slots and types from the NullableWalker for the containing method
/// or lambda to the NullableWalker created for a nested lambda or local function.
@@ -184,7 +203,7 @@ internal string GetDebuggerDisplay()
/// Non-null if we are performing the 'null-resilience' analysis of a getter which uses the 'field' keyword.
/// In this case, the inferred nullable annotation of the backing field must not be used, as we are currently in the process of inferring it.
///
- private readonly (SynthesizedBackingFieldSymbol field, NullableAnnotation assumedAnnotation)? _getterNullResilienceData;
+ private readonly GetterNullResilienceData? _getterNullResilienceData;
///
/// If true, the parameter types and nullability from _delegateInvokeMethod is used for
@@ -460,7 +479,7 @@ private NullableWalker(
CSharpCompilation compilation,
Symbol? symbol,
bool useConstructorExitWarnings,
- (SynthesizedBackingFieldSymbol field, NullableAnnotation assumedAnnotation)? getterNullResilienceData,
+ GetterNullResilienceData? getterNullResilienceData,
bool useDelegateInvokeParameterTypes,
bool useDelegateInvokeReturnType,
MethodSymbol? delegateInvokeMethodOpt,
@@ -1738,7 +1757,7 @@ internal static void AnalyzeIfNeeded(
BoundNode node,
SyntaxNode syntax,
DiagnosticBag diagnostics,
- (SourcePropertyAccessorSymbol getter, SynthesizedBackingFieldSymbol field, NullableAnnotation assumedNullableAnnotation)? getterNullResilienceData = null)
+ (SourcePropertyAccessorSymbol symbol, GetterNullResilienceData getterNullResilienceData)? symbolAndGetterNullResilienceData = null)
{
bool requiresAnalysis = true;
var compilation = binder.Compilation;
@@ -1754,13 +1773,13 @@ internal static void AnalyzeIfNeeded(
Analyze(
compilation,
- symbol: getterNullResilienceData?.getter,
+ symbol: symbolAndGetterNullResilienceData?.symbol,
node,
binder,
binder.Conversions,
diagnostics,
useConstructorExitWarnings: false,
- getterNullResilienceData is var (_, field, annotation) ? (field, annotation) : null,
+ getterNullResilienceData: symbolAndGetterNullResilienceData?.getterNullResilienceData,
useDelegateInvokeParameterTypes: false,
useDelegateInvokeReturnType: false,
delegateInvokeMethodOpt: null,
@@ -1781,7 +1800,8 @@ internal static void Analyze(
DiagnosticBag diagnostics,
MethodSymbol? delegateInvokeMethodOpt,
VariableState initialState,
- ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)>? returnTypesOpt)
+ ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)>? returnTypesOpt,
+ GetterNullResilienceData? getterNullResilienceData)
{
var symbol = lambda.Symbol;
var variables = Variables.Create(initialState.Variables).CreateNestedMethodScope(symbol);
@@ -1790,7 +1810,7 @@ internal static void Analyze(
compilation,
symbol,
useConstructorExitWarnings: false,
- getterNullResilienceData: null,
+ getterNullResilienceData: getterNullResilienceData,
useDelegateInvokeParameterTypes: useDelegateInvokeParameterTypes,
useDelegateInvokeReturnType: useDelegateInvokeReturnType,
delegateInvokeMethodOpt: delegateInvokeMethodOpt,
@@ -1821,7 +1841,7 @@ private static void Analyze(
Conversions conversions,
DiagnosticBag diagnostics,
bool useConstructorExitWarnings,
- (SynthesizedBackingFieldSymbol field, NullableAnnotation assumedAnnotation)? getterNullResilienceData,
+ GetterNullResilienceData? getterNullResilienceData,
bool useDelegateInvokeParameterTypes,
bool useDelegateInvokeReturnType,
MethodSymbol? delegateInvokeMethodOpt,
@@ -8493,7 +8513,7 @@ BoundExpression getArgumentForMethodTypeInference(BoundExpression argument, Visi
// MethodTypeInferrer must infer nullability for lambdas based on the nullability
// from flow analysis rather than the declared nullability. To allow that, we need
// to re-bind lambdas in MethodTypeInferrer.
- return getUnboundLambda((BoundLambda)argument, GetVariableState(_variables, lambdaState.Value));
+ return getUnboundLambda((BoundLambda)argument, GetVariableState(_variables, lambdaState.Value), _getterNullResilienceData);
}
if (argument.Kind == BoundKind.CollectionExpression)
@@ -8539,9 +8559,9 @@ BoundExpression getArgumentForMethodTypeInference(BoundExpression argument, Visi
return new BoundExpressionWithNullability(argument.Syntax, argument, argumentType.NullableAnnotation, argumentType.Type);
}
- static UnboundLambda getUnboundLambda(BoundLambda expr, VariableState variableState)
+ static UnboundLambda getUnboundLambda(BoundLambda expr, VariableState variableState, GetterNullResilienceData? getterNullResilienceData)
{
- return expr.UnboundLambda.WithNullableState(variableState);
+ return expr.UnboundLambda.WithNullabilityInfo(variableState, getterNullResilienceData);
}
}
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/RuntimeAsyncRewriter.cs b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/RuntimeAsyncRewriter.cs
index 972b5f14079..1a38c2de037 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/RuntimeAsyncRewriter.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/RuntimeAsyncRewriter.cs
@@ -5,7 +5,9 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.CSharp;
@@ -22,30 +24,78 @@ public static BoundStatement Rewrite(
return node;
}
- // https://github.com/dotnet/roslyn/issues/79763: struct lifting
var variablesToHoist = IteratorAndAsyncCaptureWalker.Analyze(compilationState.Compilation, method, node, isRuntimeAsync: true, diagnostics.DiagnosticBag);
+ var hoistedLocals = ArrayBuilder.GetInstance();
+ var factory = new SyntheticBoundNodeFactory(method, node.Syntax, compilationState, diagnostics);
+ var rewriter = new RuntimeAsyncRewriter(factory, variablesToHoist, hoistedLocals);
+ var thisStore = hoistThisIfNeeded(rewriter);
+ var result = (BoundStatement)rewriter.Visit(node);
- if (variablesToHoist.Count > 0)
+ if (thisStore is not null)
{
- foreach (var variable in variablesToHoist)
- {
- // Method '{0}' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- diagnostics.Add(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, variable.GetFirstLocation(), method);
- }
+ result = factory.Block(hoistedLocals.ToImmutableAndFree(),
+ factory.HiddenSequencePoint(),
+ factory.ExpressionStatement(thisStore),
+ result);
+ }
+ else if (hoistedLocals.Count > 0)
+ {
+ result = factory.Block(hoistedLocals.ToImmutableAndFree(), result);
+ }
+ else
+ {
+ hoistedLocals.Free();
}
- var rewriter = new RuntimeAsyncRewriter(new SyntheticBoundNodeFactory(method, node.Syntax, compilationState, diagnostics));
- var result = (BoundStatement)rewriter.Visit(node);
return SpillSequenceSpiller.Rewrite(result, method, compilationState, diagnostics);
+
+ static BoundAssignmentOperator? hoistThisIfNeeded(RuntimeAsyncRewriter rewriter)
+ {
+ Debug.Assert(rewriter._factory.CurrentFunction is not null);
+ var thisParameter = rewriter._factory.CurrentFunction.ThisParameter;
+ if (thisParameter is { Type.IsValueType: true, RefKind: not RefKind.None })
+ {
+ // This is a struct or a type parameter. We need to replace it with a hoisted local to preserve behavior from
+ // compiler-generated state machines; `this` is a ref, but results are not observable outside of the method.
+ // We do this regardless of whether `this` is captured to a ref local, because any usage of `ldarg.0` in these
+ // scenarios is illegal after the first await. We could be more precise and only do this if `this` is actually
+ // used after the first await, but at the moment we don't feel that is worth the complexity.
+ var hoistedThis = rewriter._factory.StoreToTemp(rewriter._factory.This(), out BoundAssignmentOperator store, kind: SynthesizedLocalKind.AwaitByRefSpill);
+ rewriter._hoistedLocals.Add(hoistedThis.LocalSymbol);
+ rewriter._proxies.Add(thisParameter, new CapturedToExpressionSymbolReplacement(hoistedThis, hoistedSymbols: [], isReusable: true));
+ return store;
+ }
+
+ return null;
+ }
}
private readonly SyntheticBoundNodeFactory _factory;
private readonly Dictionary _placeholderMap;
+ private readonly IReadOnlySet _variablesToHoist;
+ private readonly RefInitializationHoister _refInitializationHoister;
+ private readonly ArrayBuilder _hoistedLocals;
+ private readonly Dictionary _proxies = [];
- private RuntimeAsyncRewriter(SyntheticBoundNodeFactory factory)
+ private RuntimeAsyncRewriter(SyntheticBoundNodeFactory factory, IReadOnlySet variablesToHoist, ArrayBuilder hoistedLocals)
{
+ Debug.Assert(factory.CurrentFunction != null);
_factory = factory;
_placeholderMap = [];
+ _variablesToHoist = variablesToHoist;
+ _refInitializationHoister = new RefInitializationHoister(_factory, _factory.CurrentFunction, TypeMap.Empty);
+ _hoistedLocals = hoistedLocals;
+ }
+
+ [return: NotNullIfNotNull(nameof(node))]
+ public override BoundNode? Visit(BoundNode? node)
+ {
+ if (node == null) return node;
+ var oldSyntax = _factory.Syntax;
+ _factory.Syntax = node.Syntax;
+ var result = base.Visit(node);
+ _factory.Syntax = oldSyntax;
+ return result;
}
[return: NotNullIfNotNull(nameof(node))]
@@ -161,4 +211,117 @@ public override BoundNode VisitAwaitableValuePlaceholder(BoundAwaitableValuePlac
{
return _placeholderMap[node];
}
+
+ public override BoundNode? VisitAssignmentOperator(BoundAssignmentOperator node)
+ {
+ if (node.Left is not BoundLocal leftLocal)
+ {
+ return base.VisitAssignmentOperator(node);
+ }
+
+ BoundExpression visitedRight;
+
+ if (_variablesToHoist.Contains(leftLocal.LocalSymbol) && !_proxies.ContainsKey(leftLocal.LocalSymbol))
+ {
+ Debug.Assert(leftLocal.LocalSymbol.SynthesizedKind == SynthesizedLocalKind.Spill ||
+ (leftLocal.LocalSymbol.SynthesizedKind == SynthesizedLocalKind.ForEachArray && leftLocal.LocalSymbol.Type.HasInlineArrayAttribute(out _) && leftLocal.LocalSymbol.Type.TryGetInlineArrayElementField() is object));
+ Debug.Assert(node.IsRef);
+ visitedRight = VisitExpression(node.Right);
+ return _refInitializationHoister.HoistRefInitialization(
+ leftLocal.LocalSymbol,
+ visitedRight,
+ _proxies,
+ createHoistedLocal,
+ createHoistedAccess,
+ this,
+ isRuntimeAsync: true);
+ }
+
+ var visitedLeftOrProxy = VisitExpression(leftLocal);
+ visitedRight = VisitExpression(node.Right);
+
+ if (visitedLeftOrProxy is not BoundLocal visitLeftLocal)
+ {
+ // Proxy replacement occurred. We need to reassign the proxy into our local as a sequence.
+ // ref leftLocal = ref proxy;
+ // leftLocal = visitedRight;
+ var assignment = _factory.AssignmentExpression(leftLocal, visitedLeftOrProxy, isRef: true);
+ return _factory.Sequence([assignment], node.Update(leftLocal, visitedRight, node.IsRef, node.Type));
+ }
+
+ return node.Update(visitedLeftOrProxy, visitedRight, node.IsRef, node.Type);
+
+ static LocalSymbol createHoistedLocal(TypeSymbol type, RuntimeAsyncRewriter @this, LocalSymbol local)
+ {
+ var hoistedLocal = @this._factory.SynthesizedLocal(type, syntax: local.GetDeclaratorSyntax(), kind: SynthesizedLocalKind.AwaitByRefSpill);
+ @this._hoistedLocals.Add(hoistedLocal);
+ return hoistedLocal;
+ }
+
+ static BoundLocal createHoistedAccess(LocalSymbol local, RuntimeAsyncRewriter @this)
+ => @this._factory.Local(local);
+ }
+
+ private bool TryReplaceWithProxy(Symbol localOrParameter, SyntaxNode syntax, [NotNullWhen(true)] out BoundNode? replacement)
+ {
+ if (_proxies.TryGetValue(localOrParameter, out CapturedSymbolReplacement? proxy))
+ {
+ replacement = proxy.Replacement(syntax, makeFrame: null, this);
+ return true;
+ }
+
+ replacement = null;
+ return false;
+ }
+
+ public override BoundNode VisitLocal(BoundLocal node)
+ {
+ if (TryReplaceWithProxy(node.LocalSymbol, node.Syntax, out BoundNode? replacement))
+ {
+ return replacement;
+ }
+
+ Debug.Assert(!_variablesToHoist.Contains(node.LocalSymbol));
+ return base.VisitLocal(node)!;
+ }
+
+ public override BoundNode? VisitParameter(BoundParameter node)
+ {
+ if (TryReplaceWithProxy(node.ParameterSymbol, node.Syntax, out BoundNode? replacement))
+ {
+ // Currently, the only parameter we expect to be replaced is `this`, which is handled through VisitThisReference.
+ // Any other ref to a parameter should have either already been hoisted to a local during local rewriting, or should
+ // be an illegal ref to a parameter across an await.
+ throw ExceptionUtilities.Unreachable();
+ }
+
+ Debug.Assert(!_variablesToHoist.Contains(node.ParameterSymbol));
+ return base.VisitParameter(node);
+ }
+
+ public override BoundNode? VisitThisReference(BoundThisReference node)
+ {
+ Debug.Assert(_factory.CurrentFunction is not null);
+ var thisParameter = this._factory.CurrentFunction.ThisParameter;
+ if (TryReplaceWithProxy(thisParameter, node.Syntax, out BoundNode? replacement))
+ {
+ return replacement;
+ }
+
+ Debug.Assert(thisParameter is not { Type.IsValueType: true, RefKind: RefKind.Ref });
+ return base.VisitThisReference(node);
+ }
+
+ public override BoundNode? VisitExpressionStatement(BoundExpressionStatement node)
+ {
+ var expr = VisitExpression(node.Expression);
+ if (expr is null)
+ {
+ // Happens when the node is a hoisted expression that has no side effects.
+ // The generated proxy will have the original content from this node and we can drop it.
+ return _factory.StatementList();
+ }
+
+ return node.Update(expr);
+ }
}
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/BoundTreeToDifferentEnclosingContextRewriter.cs b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/BoundTreeToDifferentEnclosingContextRewriter.cs
index 07fd38f7fef..0ac7e0bfe8d 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/BoundTreeToDifferentEnclosingContextRewriter.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/BoundTreeToDifferentEnclosingContextRewriter.cs
@@ -192,17 +192,50 @@ public override BoundNode VisitAwaitableValuePlaceholder(BoundAwaitableValuePlac
{
return null;
}
+
if (property.ContainingType.IsAnonymousType)
{
//at this point we expect that the code is lowered and that getters of anonymous types are accessed
- //only via their corresponding get-methods (see VisitMethodSymbol)
+ //only via their corresponding get-methods, except for properties in expression trees
+
+ // Property of an anonymous type
+ var newType = (NamedTypeSymbol)TypeMap.SubstituteType(property.ContainingType).AsTypeSymbolOnly();
+ if (ReferenceEquals(newType, property.ContainingType))
+ {
+ // Anonymous type symbol was not rewritten
+ return property;
+ }
+
+ // get a new property by name
+ foreach (var member in newType.GetMembers(property.Name))
+ {
+ if (member.Kind == SymbolKind.Property)
+ {
+ return (PropertySymbol)member;
+ }
+ }
+
throw ExceptionUtilities.Unreachable();
}
+
return ((PropertySymbol)property.OriginalDefinition)
.AsMember((NamedTypeSymbol)TypeMap.SubstituteType(property.ContainingType).AsTypeSymbolOnly())
;
}
+ [return: NotNullIfNotNull(nameof(field))]
+ public override FieldSymbol? VisitFieldSymbol(FieldSymbol? field)
+ {
+ if (field is null)
+ {
+ return null;
+ }
+
+ // Field of a regular type
+ return ((FieldSymbol)field.OriginalDefinition)
+ .AsMember((NamedTypeSymbol)TypeMap.SubstituteType(field.ContainingType).AsTypeSymbolOnly());
+ }
+
public override BoundNode? VisitMethodDefIndex(BoundMethodDefIndex node)
{
// Cannot replace a MethodDefIndex's Method/Type with a substituted symbol.
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/ExtensionMethodBodyRewriter.cs b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/ExtensionMethodBodyRewriter.cs
index 61c5f3ed28e..73573a03a76 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/ExtensionMethodBodyRewriter.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/ExtensionMethodBodyRewriter.cs
@@ -166,18 +166,6 @@ protected override ImmutableArray VisitDeclaredLocalFunctions(Immu
}
}
- [return: NotNullIfNotNull(nameof(symbol))]
- public override FieldSymbol? VisitFieldSymbol(FieldSymbol? symbol)
- {
- if (symbol is null)
- {
- return null;
- }
-
- return symbol.OriginalDefinition
- .AsMember((NamedTypeSymbol)TypeMap.SubstituteType(symbol.ContainingType).AsTypeSymbolOnly());
- }
-
public override BoundNode? VisitCall(BoundCall node)
{
return ExtensionMethodReferenceRewriter.VisitCall(this, node);
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Call.cs b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Call.cs
index 81d153ff7ad..f38f89b6e7a 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Call.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Call.cs
@@ -1219,23 +1219,13 @@ private static ImmutableArray GetEffectiveArgumentRefKinds(ImmutableArr
for (int i = 0; i < parameters.Length; i++)
{
var paramRefKind = parameters[i].RefKind;
- if (paramRefKind is RefKind.In or RefKind.RefReadOnlyParameter)
+ var currentArgRefKind = argumentRefKindsOpt.IsDefault ? RefKind.None : argumentRefKindsOpt[i];
+ var effectiveArgRefKind = GetEffectiveRefKind(paramRefKind, currentArgRefKind, parameters[i].Type, comRefKindMismatchPossible: false);
+
+ if (currentArgRefKind != effectiveArgRefKind)
{
- var argRefKind = argumentRefKindsOpt.IsDefault ? RefKind.None : argumentRefKindsOpt[i];
fillRefKindsBuilder(argumentRefKindsOpt, parameters, ref refKindsBuilder);
- refKindsBuilder[i] = argRefKind == RefKind.None ? RefKind.In : RefKindExtensions.StrictIn;
- }
- else if (paramRefKind == RefKind.Ref)
- {
- var argRefKind = argumentRefKindsOpt.IsDefault ? RefKind.None : argumentRefKindsOpt[i];
- if (argRefKind == RefKind.None)
- {
- // Interpolated strings used as interpolated string handlers are allowed to match ref parameters without `ref`
- Debug.Assert(parameters[i].Type is NamedTypeSymbol { IsInterpolatedStringHandlerType: true, IsValueType: true });
-
- fillRefKindsBuilder(argumentRefKindsOpt, parameters, ref refKindsBuilder);
- refKindsBuilder[i] = RefKind.Ref;
- }
+ refKindsBuilder[i] = effectiveArgRefKind;
}
}
@@ -1266,6 +1256,38 @@ static void fillRefKindsBuilder(ImmutableArray argumentRefKindsOpt, Imm
}
}
+ internal static RefKind GetEffectiveRefKind(RefKind paramRefKind, RefKind initialArgRefKind, TypeSymbol paramType, bool comRefKindMismatchPossible)
+ {
+ // Patch refKinds for arguments that match 'in' or 'ref readonly' parameters to have effective RefKind
+ // For the purpose of further analysis we will mark the arguments as -
+ // - In if was originally passed as None and matches an 'in' or 'ref readonly' parameter
+ // - StrictIn if was originally passed as In or Ref and matches an 'in' or 'ref readonly' parameter
+ // Here and in the layers after the lowering we only care about None/notNone differences for the arguments
+ // Except for async stack spilling which needs to know whether arguments were originally passed as "In" and must obey "no copying" rule.
+ if (paramRefKind is RefKind.In or RefKind.RefReadOnlyParameter)
+ {
+ Debug.Assert(initialArgRefKind is RefKind.None or RefKind.In or RefKind.Ref);
+ return initialArgRefKind == RefKind.None ? RefKind.In : RefKindExtensions.StrictIn;
+ }
+ else if (paramRefKind == RefKind.Ref && initialArgRefKind == RefKind.None)
+ {
+ // For interpolated string handlers, we allow struct handlers to be passed as ref without a `ref`
+ // keyword
+ if (paramType is NamedTypeSymbol { IsInterpolatedStringHandlerType: true, IsValueType: true })
+ {
+ return RefKind.Ref;
+ }
+ else
+ {
+ // For complex call locations, it's possible that there's a com parameter that allows passing by ref without an explicit ref keyword. This
+ // is not handled at the local rewriter.
+ Debug.Assert(comRefKindMismatchPossible);
+ }
+ }
+
+ return initialArgRefKind;
+ }
+
// temporariesBuilder will be null when factory is null.
internal static bool CanSkipRewriting(
ImmutableArray rewrittenArguments,
@@ -1428,20 +1450,7 @@ private void BuildStoresToTemps(
}
arguments[p] = StoreArgumentToTempIfNecessary(forceLambdaSpilling, storesToTemps, argument, argRefKind, paramRefKind);
-
- // Patch refKinds for arguments that match 'in' or 'ref readonly' parameters to have effective RefKind
- // For the purpose of further analysis we will mark the arguments as -
- // - In if was originally passed as None and matches an 'in' or 'ref readonly' parameter
- // - StrictIn if was originally passed as In or Ref and matches an 'in' or 'ref readonly' parameter
- // Here and in the layers after the lowering we only care about None/notNone differences for the arguments
- // Except for async stack spilling which needs to know whether arguments were originally passed as "In" and must obey "no copying" rule.
- if (paramRefKind is RefKind.In or RefKind.RefReadOnlyParameter)
- {
- Debug.Assert(argRefKind is RefKind.None or RefKind.In or RefKind.Ref);
- argRefKind = argRefKind == RefKind.None ? RefKind.In : RefKindExtensions.StrictIn;
- }
-
- refKinds[p] = argRefKind;
+ refKinds[p] = GetEffectiveRefKind(paramRefKind, argRefKind, parameters[p].Type, comRefKindMismatchPossible: true);
}
return;
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ForEachStatement.cs b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ForEachStatement.cs
index 44fe74506b1..6e2467f28d6 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ForEachStatement.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ForEachStatement.cs
@@ -69,26 +69,31 @@ public override BoundNode VisitForEachStatement(BoundForEachStatement node)
}
private bool CanRewriteForEachAsFor(SyntaxNode forEachSyntax, TypeSymbol nodeExpressionType, [NotNullWhen(true)] out MethodSymbol? indexerGet, [NotNullWhen(true)] out MethodSymbol? lengthGet)
+ {
+ return CanRewriteForEachAsFor(_compilation, forEachSyntax, nodeExpressionType, out indexerGet, out lengthGet, _diagnostics);
+ }
+
+ internal static bool CanRewriteForEachAsFor(CSharpCompilation compilation, SyntaxNode forEachSyntax, TypeSymbol nodeExpressionType, [NotNullWhen(true)] out MethodSymbol? indexerGet, [NotNullWhen(true)] out MethodSymbol? lengthGet, BindingDiagnosticBag diagnostics)
{
lengthGet = indexerGet = null;
var origDefinition = nodeExpressionType.OriginalDefinition;
if (origDefinition.SpecialType == SpecialType.System_String)
{
- lengthGet = UnsafeGetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Length);
- indexerGet = UnsafeGetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Chars);
+ lengthGet = UnsafeGetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Length, compilation, diagnostics);
+ indexerGet = UnsafeGetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Chars, compilation, diagnostics);
}
- else if ((object)origDefinition == this._compilation.GetWellKnownType(WellKnownType.System_Span_T))
+ else if ((object)origDefinition == compilation.GetWellKnownType(WellKnownType.System_Span_T))
{
var spanType = (NamedTypeSymbol)nodeExpressionType;
- lengthGet = (MethodSymbol?)_factory.WellKnownMember(WellKnownMember.System_Span_T__get_Length, isOptional: true)?.SymbolAsMember(spanType);
- indexerGet = (MethodSymbol?)_factory.WellKnownMember(WellKnownMember.System_Span_T__get_Item, isOptional: true)?.SymbolAsMember(spanType);
+ lengthGet = (MethodSymbol?)Binder.GetWellKnownTypeMember(compilation, WellKnownMember.System_Span_T__get_Length, diagnostics, syntax: forEachSyntax, isOptional: true)?.SymbolAsMember(spanType);
+ indexerGet = (MethodSymbol?)Binder.GetWellKnownTypeMember(compilation, WellKnownMember.System_Span_T__get_Item, diagnostics, syntax: forEachSyntax, isOptional: true)?.SymbolAsMember(spanType);
}
- else if ((object)origDefinition == this._compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T))
+ else if ((object)origDefinition == compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T))
{
var spanType = (NamedTypeSymbol)nodeExpressionType;
- lengthGet = (MethodSymbol?)_factory.WellKnownMember(WellKnownMember.System_ReadOnlySpan_T__get_Length, isOptional: true)?.SymbolAsMember(spanType);
- indexerGet = (MethodSymbol?)_factory.WellKnownMember(WellKnownMember.System_ReadOnlySpan_T__get_Item, isOptional: true)?.SymbolAsMember(spanType);
+ lengthGet = (MethodSymbol?)Binder.GetWellKnownTypeMember(compilation, WellKnownMember.System_ReadOnlySpan_T__get_Length, diagnostics, syntax: forEachSyntax, isOptional: true)?.SymbolAsMember(spanType);
+ indexerGet = (MethodSymbol?)Binder.GetWellKnownTypeMember(compilation, WellKnownMember.System_ReadOnlySpan_T__get_Item, diagnostics, syntax: forEachSyntax, isOptional: true)?.SymbolAsMember(spanType);
}
return lengthGet is { } && indexerGet is { };
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs
index ec31dbca802..0cb989bc6d6 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs
@@ -178,6 +178,7 @@ private MethodSymbol GetOrCreateBaseFunctionWrapper(MethodSymbol methodBeingWrap
return wrapper;
}
+ /// Any new usage of this method will need a similar update in
private bool TryReplaceWithProxy(Symbol parameterOrLocal, SyntaxNode syntax, [NotNullWhen(true)] out BoundNode? replacement)
{
if (proxies.TryGetValue(parameterOrLocal, out CapturedSymbolReplacement? proxy))
@@ -349,48 +350,6 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE
return node.Update(rewrittenArgument, method, node.IsExtensionMethod, node.WasTargetTyped, type);
}
- [return: NotNullIfNotNull(nameof(property))]
- private new PropertySymbol? VisitPropertySymbol(PropertySymbol? property)
- {
- if (property is null)
- {
- return null;
- }
-
- if (!property.ContainingType.IsAnonymousType)
- {
- // Property of a regular type
- return ((PropertySymbol)property.OriginalDefinition)
- .AsMember((NamedTypeSymbol)TypeMap.SubstituteType(property.ContainingType).AsTypeSymbolOnly());
- }
-
- // Method of an anonymous type
- var newType = (NamedTypeSymbol)TypeMap.SubstituteType(property.ContainingType).AsTypeSymbolOnly();
- if (ReferenceEquals(newType, property.ContainingType))
- {
- // Anonymous type symbol was not rewritten
- return property;
- }
-
- // get a new property by name
- foreach (var member in newType.GetMembers(property.Name))
- {
- if (member.Kind == SymbolKind.Property)
- {
- return (PropertySymbol)member;
- }
- }
-
- throw ExceptionUtilities.Unreachable();
- }
-
- private new FieldSymbol VisitFieldSymbol(FieldSymbol field)
- {
- // Property of a regular type
- return ((FieldSymbol)field.OriginalDefinition)
- .AsMember((NamedTypeSymbol)TypeMap.SubstituteType(field.ContainingType).AsTypeSymbolOnly());
- }
-
public override BoundNode VisitObjectInitializerMember(BoundObjectInitializerMember node)
{
ImmutableArray arguments = (ImmutableArray)this.VisitList(node.Arguments);
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/CapturedSymbol.cs b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/CapturedSymbol.cs
index a78955a399c..f7c465b0913 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/CapturedSymbol.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/CapturedSymbol.cs
@@ -62,16 +62,17 @@ public override BoundExpression Replacement(SyntaxNode node, Func : CapturedSymbolReplacement
+ where THoistedSymbolType : Symbol
{
private readonly BoundExpression _replacement;
- public readonly ImmutableArray HoistedFields;
+ public readonly ImmutableArray HoistedSymbols;
- public CapturedToExpressionSymbolReplacement(BoundExpression replacement, ImmutableArray hoistedFields, bool isReusable)
+ public CapturedToExpressionSymbolReplacement(BoundExpression replacement, ImmutableArray hoistedSymbols, bool isReusable)
: base(isReusable)
{
_replacement = replacement;
- this.HoistedFields = hoistedFields;
+ this.HoistedSymbols = hoistedSymbols;
}
public override BoundExpression Replacement(SyntaxNode node, Func makeFrame, TArg arg)
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs
index 3671e459416..6c62a86c384 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs
@@ -96,6 +96,8 @@ internal abstract class MethodToStateMachineRewriter : MethodToClassRewriter
// Instrumentation related bound nodes:
protected BoundBlockInstrumentation? instrumentation;
+ private readonly RefInitializationHoister _refInitializationHoister;
+
// new:
public MethodToStateMachineRewriter(
SyntheticBoundNodeFactory F,
@@ -161,6 +163,8 @@ public MethodToStateMachineRewriter(
slotAllocatorOpt,
firstState: FirstIncreasingResumableState,
increasing: true);
+
+ _refInitializationHoister = new RefInitializationHoister(F, OriginalMethod, TypeMap);
}
#nullable disable
@@ -365,7 +369,7 @@ private BoundStatement PossibleIteratorScope(ImmutableArray locals,
}
else
{
- foreach (var field in ((CapturedToExpressionSymbolReplacement)proxy).HoistedFields)
+ foreach (var field in ((CapturedToExpressionSymbolReplacement)proxy).HoistedSymbols)
{
AddVariableCleanup(variableCleanup, field);
@@ -505,226 +509,6 @@ private void FreeReusableHoistedField(StateMachineFieldSymbol field)
fields.Add(field);
}
- private BoundExpression HoistRefInitialization(LocalSymbol local, BoundAssignmentOperator node)
- {
- Debug.Assert(
- local switch
- {
- TypeSubstitutedLocalSymbol tsl => tsl.UnderlyingLocalSymbol,
- _ => local
- } is SynthesizedLocal
- );
- Debug.Assert(local.SynthesizedKind == SynthesizedLocalKind.Spill ||
- (local.SynthesizedKind == SynthesizedLocalKind.ForEachArray && local.Type.HasInlineArrayAttribute(out _) && local.Type.TryGetInlineArrayElementField() is object));
- Debug.Assert(local.GetDeclaratorSyntax() != null);
-#pragma warning disable format
- Debug.Assert(local.SynthesizedKind switch
- {
- SynthesizedLocalKind.Spill => this.OriginalMethod.IsAsync,
- SynthesizedLocalKind.ForEachArray => this.OriginalMethod.IsAsync || this.OriginalMethod.IsIterator,
- _ => false
- });
-#pragma warning restore format
-
- var right = (BoundExpression)Visit(node.Right);
-
- var sideEffects = ArrayBuilder.GetInstance();
- bool needsSacrificialEvaluation = false;
- var hoistedFields = ArrayBuilder.GetInstance();
-
- SyntaxNode awaitSyntaxOpt;
- int syntaxOffset;
- if (F.Compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
- {
- awaitSyntaxOpt = local.GetDeclaratorSyntax();
-#pragma warning disable format
- Debug.Assert(local.SynthesizedKind switch
- {
- SynthesizedLocalKind.Spill => awaitSyntaxOpt.IsKind(SyntaxKind.AwaitExpression) || awaitSyntaxOpt.IsKind(SyntaxKind.SwitchExpression),
- SynthesizedLocalKind.ForEachArray => awaitSyntaxOpt is CommonForEachStatementSyntax,
- _ => false
- });
-#pragma warning restore format
- syntaxOffset = OriginalMethod.CalculateLocalSyntaxOffset(LambdaUtilities.GetDeclaratorPosition(awaitSyntaxOpt), awaitSyntaxOpt.SyntaxTree);
- }
- else
- {
- // These are only used to calculate debug id for ref-spilled variables,
- // no need to do so in release build.
- awaitSyntaxOpt = null;
- syntaxOffset = -1;
- }
-
- var replacement = HoistExpression(right, awaitSyntaxOpt, syntaxOffset, local.RefKind, sideEffects, hoistedFields, ref needsSacrificialEvaluation);
-
- proxies.Add(local, new CapturedToExpressionSymbolReplacement(replacement, hoistedFields.ToImmutableAndFree(), isReusable: true));
-
- if (needsSacrificialEvaluation)
- {
- var type = TypeMap.SubstituteType(local.Type).Type;
- var sacrificialTemp = F.SynthesizedLocal(type, refKind: RefKind.Ref);
- Debug.Assert(TypeSymbol.Equals(type, replacement.Type, TypeCompareKind.ConsiderEverything2));
- return F.Sequence(ImmutableArray.Create(sacrificialTemp), sideEffects.ToImmutableAndFree(), F.AssignmentExpression(F.Local(sacrificialTemp), replacement, isRef: true));
- }
-
- if (sideEffects.Count == 0)
- {
- sideEffects.Free();
- return null;
- }
-
- var last = sideEffects.Last();
- sideEffects.RemoveLast();
- return F.Sequence(ImmutableArray.Empty, sideEffects.ToImmutableAndFree(), last);
- }
-
- private BoundExpression HoistExpression(
- BoundExpression expr,
- SyntaxNode awaitSyntaxOpt,
- int syntaxOffset,
- RefKind refKind,
- ArrayBuilder sideEffects,
- ArrayBuilder hoistedFields,
- ref bool needsSacrificialEvaluation)
- {
- switch (expr.Kind)
- {
- case BoundKind.ArrayAccess:
- {
- var array = (BoundArrayAccess)expr;
- BoundExpression expression = HoistExpression(array.Expression, awaitSyntaxOpt, syntaxOffset, RefKind.None, sideEffects, hoistedFields, ref needsSacrificialEvaluation);
- var indices = ArrayBuilder.GetInstance();
- foreach (var index in array.Indices)
- {
- indices.Add(HoistExpression(index, awaitSyntaxOpt, syntaxOffset, RefKind.None, sideEffects, hoistedFields, ref needsSacrificialEvaluation));
- }
-
- needsSacrificialEvaluation = true; // need to force array index out of bounds exceptions
- return array.Update(expression, indices.ToImmutableAndFree(), array.Type);
- }
-
- case BoundKind.FieldAccess:
- {
- var field = (BoundFieldAccess)expr;
- if (field.FieldSymbol.IsStatic)
- {
- // the address of a static field, and the value of a readonly static field, is stable
- if (refKind != RefKind.None || field.FieldSymbol.IsReadOnly) return expr;
- goto default;
- }
-
- if (refKind == RefKind.None)
- {
- goto default;
- }
-
- var isFieldOfStruct = !field.FieldSymbol.ContainingType.IsReferenceType;
-
- var receiver = HoistExpression(field.ReceiverOpt, awaitSyntaxOpt, syntaxOffset,
- isFieldOfStruct ? refKind : RefKind.None, sideEffects, hoistedFields, ref needsSacrificialEvaluation);
- if (receiver.Kind != BoundKind.ThisReference && !isFieldOfStruct)
- {
- needsSacrificialEvaluation = true; // need the null check in field receiver
- }
-
- return F.Field(receiver, field.FieldSymbol);
- }
-
- case BoundKind.ThisReference:
- case BoundKind.BaseReference:
- case BoundKind.DefaultExpression:
- return expr;
-
- case BoundKind.Call:
- var call = (BoundCall)expr;
- // NOTE: There are two kinds of 'In' arguments that we may see at this point:
- // - `RefKindExtensions.StrictIn` (originally specified with 'in' modifier)
- // - `RefKind.In` (specified with no modifiers and matched an 'in' or 'ref readonly' parameter)
- //
- // It is allowed to spill ordinary `In` arguments by value if reference-preserving spilling is not possible.
- // The "strict" ones do not permit implicit copying, so the same situation should result in an error.
- if (refKind != RefKind.None && refKind != RefKind.In)
- {
- Debug.Assert(refKind is RefKindExtensions.StrictIn or RefKind.Ref or RefKind.Out);
- Debug.Assert(call.Method.RefKind != RefKind.None);
- F.Diagnostics.Add(ErrorCode.ERR_RefReturningCallAndAwait, F.Syntax.Location, call.Method);
- }
- // method call is not referentially transparent, we can only spill the result value.
- refKind = RefKind.None;
- goto default;
-
- case BoundKind.ConditionalOperator:
- var conditional = (BoundConditionalOperator)expr;
- // NOTE: There are two kinds of 'In' arguments that we may see at this point:
- // - `RefKindExtensions.StrictIn` (originally specified with 'in' modifier)
- // - `RefKind.In` (specified with no modifiers and matched an 'in' or 'ref readonly' parameter)
- //
- // It is allowed to spill ordinary `In` arguments by value if reference-preserving spilling is not possible.
- // The "strict" ones do not permit implicit copying, so the same situation should result in an error.
- if (refKind != RefKind.None && refKind != RefKind.RefReadOnly)
- {
- Debug.Assert(refKind is RefKindExtensions.StrictIn or RefKind.Ref or RefKind.In);
- Debug.Assert(conditional.IsRef);
- F.Diagnostics.Add(ErrorCode.ERR_RefConditionalAndAwait, F.Syntax.Location);
- }
- // conditional expr is not referentially transparent, we can only spill the result value.
- refKind = RefKind.None;
- goto default;
-
- default:
- if (expr.ConstantValueOpt != null)
- {
- return expr;
- }
-
- if (refKind != RefKind.None)
- {
- throw ExceptionUtilities.UnexpectedValue(expr.Kind);
- }
-
- TypeSymbol fieldType = expr.Type;
- StateMachineFieldSymbol hoistedField;
- if (F.Compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
- {
- const SynthesizedLocalKind kind = SynthesizedLocalKind.AwaitByRefSpill;
-
- Debug.Assert(awaitSyntaxOpt != null);
-
- int ordinal = _synthesizedLocalOrdinals.AssignLocalOrdinal(kind, syntaxOffset);
- var id = new LocalDebugId(syntaxOffset, ordinal);
-
- // Editing await expression is not allowed. Thus all spilled fields will be present in the previous state machine.
- // However, it may happen that the type changes, in which case we need to allocate a new slot.
- int slotIndex;
- if (slotAllocator == null ||
- !slotAllocator.TryGetPreviousHoistedLocalSlotIndex(
- awaitSyntaxOpt,
- F.ModuleBuilderOpt.Translate(fieldType, awaitSyntaxOpt, Diagnostics.DiagnosticBag),
- kind,
- id,
- Diagnostics.DiagnosticBag,
- out slotIndex))
- {
- slotIndex = _nextFreeHoistedLocalSlot++;
- }
-
- string fieldName = GeneratedNames.MakeHoistedLocalFieldName(kind, slotIndex);
- hoistedField = F.StateMachineField(expr.Type, fieldName, new LocalSlotDebugInfo(kind, id), slotIndex);
- _fieldsForCleanup.Add(hoistedField);
- }
- else
- {
- hoistedField = GetOrAllocateReusableHoistedField(fieldType, reused: out _);
- }
-
- hoistedFields.Add(hoistedField);
-
- var replacement = F.Field(F.This(), hoistedField);
- sideEffects.Add(F.AssignmentExpression(replacement, expr));
- return replacement;
- }
- }
-
#region Visitors
public override BoundNode Visit(BoundNode node)
@@ -863,7 +647,69 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node)
// We have an assignment to a variable that has not yet been assigned a proxy.
// So we assign the proxy before translating the assignment.
- return HoistRefInitialization(leftLocal, node);
+ var visitedRight = (BoundExpression)Visit(node.Right);
+ return _refInitializationHoister.HoistRefInitialization(
+ leftLocal,
+ visitedRight,
+ proxies,
+ createHoistedSymbol,
+ createHoistedAccess,
+ this,
+ isRuntimeAsync: false);
+
+ static StateMachineFieldSymbol createHoistedSymbol(TypeSymbol type, MethodToStateMachineRewriter @this, LocalSymbol assignedLocal)
+ {
+ StateMachineFieldSymbol hoistedSymbol;
+
+ // https://github.com/dotnet/roslyn/issues/79793 - consider whether runtime async will need some of this work for enc
+ if (@this.F.Compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
+ {
+ const SynthesizedLocalKind kind = SynthesizedLocalKind.AwaitByRefSpill;
+ SyntaxNode awaitSyntax = assignedLocal.GetDeclaratorSyntax();
+#pragma warning disable format
+ Debug.Assert(assignedLocal.SynthesizedKind switch
+ {
+ SynthesizedLocalKind.Spill => awaitSyntax.IsKind(SyntaxKind.AwaitExpression) || awaitSyntax.IsKind(SyntaxKind.SwitchExpression),
+ SynthesizedLocalKind.ForEachArray => awaitSyntax is CommonForEachStatementSyntax,
+ _ => false
+ });
+#pragma warning restore format
+ int syntaxOffset = @this.OriginalMethod.CalculateLocalSyntaxOffset(LambdaUtilities.GetDeclaratorPosition(awaitSyntax), awaitSyntax.SyntaxTree);
+
+ Debug.Assert(awaitSyntax != null);
+
+ int ordinal = @this._synthesizedLocalOrdinals.AssignLocalOrdinal(kind, syntaxOffset);
+ var id = new LocalDebugId(syntaxOffset, ordinal);
+
+ // Editing await expression is not allowed. Thus all spilled fields will be present in the previous state machine.
+ // However, it may happen that the type changes, in which case we need to allocate a new slot.
+ int slotIndex;
+ if (@this.slotAllocator == null ||
+ !@this.slotAllocator.TryGetPreviousHoistedLocalSlotIndex(
+ awaitSyntax,
+ @this.F.ModuleBuilderOpt.Translate(type, awaitSyntax, @this.Diagnostics.DiagnosticBag),
+ kind,
+ id,
+ @this.Diagnostics.DiagnosticBag,
+ out slotIndex))
+ {
+ slotIndex = @this._nextFreeHoistedLocalSlot++;
+ }
+
+ string fieldName = GeneratedNames.MakeHoistedLocalFieldName(kind, slotIndex);
+ hoistedSymbol = @this.F.StateMachineField(type, fieldName, new LocalSlotDebugInfo(kind, id), slotIndex);
+ @this._fieldsForCleanup.Add(hoistedSymbol);
+ }
+ else
+ {
+ hoistedSymbol = @this.GetOrAllocateReusableHoistedField(type, out _);
+ }
+
+ return hoistedSymbol;
+ }
+
+ static BoundFieldAccess createHoistedAccess(StateMachineFieldSymbol fieldSymbol, MethodToStateMachineRewriter @this)
+ => @this.F.Field(@this.F.This(), fieldSymbol);
}
///
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/RefInitializationHoister.cs b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/RefInitializationHoister.cs
new file mode 100644
index 00000000000..47e165a8f0b
--- /dev/null
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/RefInitializationHoister.cs
@@ -0,0 +1,304 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Microsoft.CodeAnalysis.PooledObjects;
+
+namespace Microsoft.CodeAnalysis.CSharp;
+
+///
+/// Helper used during state machine lowering (async / iterator) to "hoist" the initialization of
+/// synthesized ref locals whose right-hand side may contain await or otherwise needs to be
+/// evaluated before suspension points.
+///
+/// A ref local whose initializer contains side effects (invocations, indexing, field dereference with
+/// a non-trivial receiver, etc.) must be rewritten so that:
+///
+/// - All side effects are performed exactly once and in the original left-to-right order.
+/// - Potential exceptions (null dereference, bounds checks, etc.) occur before the first suspension (e.g. an await inside the method) just as they would have in the original code.
+/// - The resulting stored reference (the value of the ref local) remains stable across suspension (i.e. subsequent uses of the ref local after rewrites refer to a syntactically simple expression comprised only of the hoisted symbols and stable primitives).
+///
+///
+///
+internal class RefInitializationHoister(SyntheticBoundNodeFactory f, MethodSymbol originalMethod, TypeMap typeMap)
+ where THoistedSymbol : Symbol
+ where THoistedAccess : BoundExpression
+{
+ private readonly SyntheticBoundNodeFactory _factory = f;
+ private readonly MethodSymbol _originalMethod = originalMethod;
+ private readonly TypeMap _typeMap = typeMap;
+ private bool _reportedError;
+
+ ///
+ /// Hoists the right-hand side of a ref local (or similar synthesized local) initialization.
+ ///
+ /// Additional context type passed through to creation callbacks.
+ /// The synthesized local whose initialization is being processed. Must be of a supported synthesized kind.
+ /// The (already recursively visited by the enclosing rewriter) original right-hand side expression.
+ /// Dictionary receiving a proxy replacement mapping from to a stable expression assembled from hoisted components.
+ /// Factory that creates a new hoisted symbol for a sub-expression value of a given .
+ /// Factory that produces an access expression to a previously created hoisted symbol.
+ /// Additional context forwarded to the factories (typically state machine specific info).
+ /// True when performing lowered transformation for runtime-async (MoveNext-like) method body; affects some validation / debug assertions.
+ ///
+ /// A sequence expression containing the side-effect assignments (and possibly a sacrificial evaluation)
+ /// whose value is the final replacement expression used to initialize the ref local, or null
+ /// if no side effects needed hoisting.
+ ///
+ ///
+ /// On success a entry is added for the local.
+ /// Subsequent usages of the local are rewritten (elsewhere) to the replacement expression so the
+ /// state machine no longer needs to track the original local.
+ ///
+ internal BoundExpression? HoistRefInitialization(
+ LocalSymbol local,
+ BoundExpression visitedRight,
+ Dictionary proxies,
+ Func createHoistedSymbol,
+ Func createHoistedAccess,
+ TArg arg,
+ bool isRuntimeAsync)
+ {
+ Debug.Assert(
+ local switch
+ {
+ TypeSubstitutedLocalSymbol tsl => tsl.UnderlyingLocalSymbol,
+ _ => local
+ } is SynthesizedLocal
+ );
+ Debug.Assert(local.SynthesizedKind == SynthesizedLocalKind.Spill ||
+ (local.SynthesizedKind == SynthesizedLocalKind.ForEachArray && local.Type.HasInlineArrayAttribute(out _) && local.Type.TryGetInlineArrayElementField() is object));
+ Debug.Assert(local.GetDeclaratorSyntax() != null);
+#pragma warning disable format
+ Debug.Assert(local.SynthesizedKind switch
+ {
+ SynthesizedLocalKind.Spill => this._originalMethod.IsAsync,
+ SynthesizedLocalKind.ForEachArray => this._originalMethod.IsAsync || this._originalMethod.IsIterator,
+ _ => false
+ });
+#pragma warning restore format
+
+ var sideEffects = ArrayBuilder.GetInstance();
+ bool needsSacrificialEvaluation = false;
+ var hoistedSymbols = ArrayBuilder.GetInstance();
+
+ var replacement = HoistExpression(visitedRight, local, local.RefKind, sideEffects, hoistedSymbols, ref needsSacrificialEvaluation, createHoistedSymbol, createHoistedAccess, arg, isRuntimeAsync, isFieldAccessOfStruct: false);
+
+ proxies.Add(local, new CapturedToExpressionSymbolReplacement(replacement, hoistedSymbols.ToImmutableAndFree(), isReusable: true));
+
+ if (needsSacrificialEvaluation)
+ {
+ var type = _typeMap.SubstituteType(local.Type).Type;
+ var sacrificialTemp = _factory.SynthesizedLocal(type, refKind: RefKind.Ref);
+ Debug.Assert(TypeSymbol.Equals(type, replacement.Type, TypeCompareKind.ConsiderEverything2));
+ return _factory.Sequence(ImmutableArray.Create(sacrificialTemp), sideEffects.ToImmutableAndFree(), _factory.AssignmentExpression(_factory.Local(sacrificialTemp), replacement, isRef: true));
+ }
+
+ if (sideEffects.Count == 0)
+ {
+ sideEffects.Free();
+ return null;
+ }
+
+ var last = sideEffects.Last();
+ sideEffects.RemoveLast();
+ return _factory.Sequence(ImmutableArray.Empty, sideEffects.ToImmutableAndFree(), last);
+ }
+
+ ///
+ /// Recursively processes , hoisting side-effecting / non-stable sub-expressions into
+ /// separate symbols and returning a (syntactically) simpler expression tree composed only of:
+ ///
+ /// - Original stable nodes (e.g. constants, this, static readonly field access when allowed).
+ /// - Accesses to hoisted symbols created for previous sub-expressions.
+ ///
+ ///
+ /// Additional context argument type.
+ /// Expression to transform.
+ /// The local being initialized ultimately (used for diagnostics and to associate hoisted symbols).
+ /// The desired ref kind of the full expression result (propagated selectively when it impacts legality of hoisting).
+ /// Builder collecting assignment expressions that realize side effects exactly once.
+ /// Builder receiving the created hoisted symbols (parallel to order).
+ /// Flag that is set if the final composed expression must still be evaluated once now (to force exceptions / checks) even though the reference itself is stable.
+ /// Callback that creates a hoisted symbol.
+ /// Callback that creates an access to a hoisted symbol.
+ /// Additional callback context.
+ /// Indicates we are in runtime-async lowering path; changes certain debug-time invariants.
+ /// Whether the current expression is a field access whose receiver is a struct (important for reference preservation rules).
+ /// The replacement (side-effect free / stable) expression that can stand in for after the collected side effects execute.
+ private BoundExpression HoistExpression(
+ BoundExpression expr,
+ LocalSymbol assignedLocal,
+ RefKind refKind,
+ ArrayBuilder sideEffects,
+ ArrayBuilder hoistedSymbols,
+ ref bool needsSacrificialEvaluation,
+ Func createHoistedSymbol,
+ Func createHoistedAccess,
+ TArg arg,
+ bool isRuntimeAsync,
+ bool isFieldAccessOfStruct)
+ {
+ switch (expr.Kind)
+ {
+ case BoundKind.ArrayAccess:
+ {
+ var array = (BoundArrayAccess)expr;
+ BoundExpression expression = HoistExpression(
+ array.Expression,
+ assignedLocal,
+ refKind: RefKind.None,
+ sideEffects,
+ hoistedSymbols,
+ ref needsSacrificialEvaluation,
+ createHoistedSymbol,
+ createHoistedAccess,
+ arg,
+ isRuntimeAsync,
+ isFieldAccessOfStruct: false);
+
+ var indices = ArrayBuilder.GetInstance();
+ foreach (var index in array.Indices)
+ {
+ indices.Add(HoistExpression(
+ index,
+ assignedLocal,
+ refKind: RefKind.None,
+ sideEffects,
+ hoistedSymbols,
+ ref needsSacrificialEvaluation,
+ createHoistedSymbol,
+ createHoistedAccess,
+ arg,
+ isRuntimeAsync,
+ isFieldAccessOfStruct: false));
+ }
+
+ needsSacrificialEvaluation = true; // need to force array index out of bounds exceptions
+ return array.Update(expression, indices.ToImmutableAndFree(), array.Type);
+ }
+
+ case BoundKind.FieldAccess:
+ {
+ var field = (BoundFieldAccess)expr;
+ if (field.FieldSymbol.IsStatic)
+ {
+ // the address of a static field, and the value of a readonly static field, is stable
+ if (refKind != RefKind.None || field.FieldSymbol.IsReadOnly) return expr;
+ goto default;
+ }
+ Debug.Assert(field.ReceiverOpt != null);
+
+ if (refKind == RefKind.None)
+ {
+ goto default;
+ }
+
+ var isFieldOfStruct = !field.FieldSymbol.ContainingType.IsReferenceType;
+
+ var receiver = HoistExpression(
+ field.ReceiverOpt,
+ assignedLocal,
+ refKind: isFieldOfStruct ? refKind : RefKind.None,
+ sideEffects,
+ hoistedSymbols,
+ ref needsSacrificialEvaluation,
+ createHoistedSymbol,
+ createHoistedAccess,
+ arg,
+ isRuntimeAsync,
+ isFieldAccessOfStruct: isFieldOfStruct);
+ if (receiver.Kind != BoundKind.ThisReference && !isFieldOfStruct)
+ {
+ // Make sure that any potential NRE on the receiver happens before the await.
+ needsSacrificialEvaluation = true;
+ }
+
+ return _factory.Field(receiver, field.FieldSymbol);
+ }
+
+ case BoundKind.ThisReference:
+ case BoundKind.BaseReference:
+ case BoundKind.DefaultExpression:
+ return expr;
+
+ case BoundKind.Call:
+ var call = (BoundCall)expr;
+ // NOTE: There are two kinds of 'In' arguments that we may see at this point:
+ // - `RefKindExtensions.StrictIn` (originally specified with 'in' modifier)
+ // - `RefKind.In` (specified with no modifiers and matched an 'in' or 'ref readonly' parameter)
+ //
+ // It is allowed to spill ordinary `In` arguments by value if reference-preserving spilling is not possible.
+ // The "strict" ones do not permit implicit copying, so the same situation should result in an error.
+ if (refKind != RefKind.None && refKind != RefKind.In)
+ {
+ Debug.Assert(refKind is RefKindExtensions.StrictIn or RefKind.Ref or RefKind.Out);
+ if (call.Method.RefKind != RefKind.None)
+ {
+ _factory.Diagnostics.Add(ErrorCode.ERR_RefReturningCallAndAwait, _factory.Syntax.Location, call.Method);
+ _reportedError = true;
+ }
+ }
+ // method call is not referentially transparent, we can only spill the result value.
+ refKind = RefKind.None;
+ goto default;
+
+ case BoundKind.ConditionalOperator:
+ var conditional = (BoundConditionalOperator)expr;
+ // NOTE: There are two kinds of 'In' arguments that we may see at this point:
+ // - `RefKindExtensions.StrictIn` (originally specified with 'in' modifier)
+ // - `RefKind.In` (specified with no modifiers and matched an 'in' or 'ref readonly' parameter)
+ //
+ // It is allowed to spill ordinary `In` arguments by value if reference-preserving spilling is not possible.
+ // The "strict" ones do not permit implicit copying, so the same situation should result in an error.
+ if (refKind != RefKind.None && refKind != RefKind.RefReadOnly)
+ {
+ Debug.Assert(refKind is RefKindExtensions.StrictIn or RefKind.Ref or RefKind.In);
+ Debug.Assert(conditional.IsRef);
+ _factory.Diagnostics.Add(ErrorCode.ERR_RefConditionalAndAwait, _factory.Syntax.Location);
+ _reportedError = true;
+ }
+ // conditional expr is not referentially transparent, we can only spill the result value.
+ refKind = RefKind.None;
+ goto default;
+
+ default:
+ if (expr.ConstantValueOpt != null)
+ {
+ return expr;
+ }
+
+ if (refKind != RefKind.None)
+ {
+ if (isRuntimeAsync)
+ {
+ // If an error was reported about ref escaping earlier, there could be illegal ref accesses later in the method,
+ // so we track that to ensure that we don't see unexpected cases here.
+ // This is an access to a field of a struct, or parameter or local of a type parameter, both of which happen by reference.
+ // The receiver should be a non-ref local or parameter.
+ // This is safe to hoist into a proxy as the original local will be accessed directly.
+ Debug.Assert(_reportedError || isFieldAccessOfStruct || expr.Type!.IsTypeParameter());
+ Debug.Assert(_reportedError || expr is BoundLocal { LocalSymbol.RefKind: RefKind.None }
+ or BoundParameter { ParameterSymbol.RefKind: RefKind.None });
+ }
+ else
+ {
+ throw ExceptionUtilities.UnexpectedValue(expr.Kind);
+ }
+ }
+
+ Debug.Assert(expr.Type is not null);
+ var hoistedSymbol = createHoistedSymbol(expr.Type, arg, assignedLocal);
+ hoistedSymbols.Add(hoistedSymbol);
+
+ var replacement = createHoistedAccess(hoistedSymbol, arg);
+ sideEffects.Add(_factory.AssignmentExpression(replacement, expr));
+ return replacement;
+ }
+ }
+}
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/roslyn/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
index 03c05482213..f154bc7cae4 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
@@ -3241,7 +3241,9 @@ private MemberDeclarationSyntax ParseMemberDeclarationCore(SyntaxKind parentKind
private bool IsExtensionContainerStart()
{
- return this.CurrentToken.ContextualKind == SyntaxKind.ExtensionKeyword && IsFeatureEnabled(MessageID.IDS_FeatureExtensions);
+ // For error recovery, we recognize `extension` followed by `<` even in older language versions
+ return this.CurrentToken.ContextualKind == SyntaxKind.ExtensionKeyword &&
+ (IsFeatureEnabled(MessageID.IDS_FeatureExtensions) || this.PeekToken(1).Kind == SyntaxKind.LessThanToken);
}
// if the modifiers do not contain async or replace and the type is the identifier "async" or "replace", then
@@ -8313,7 +8315,7 @@ private bool IsPossibleLocalDeclarationStatement(bool isGlobalScriptLevel)
return true;
}
- return IsPossibleFirstTypedIdentifierInLocaDeclarationStatement(isGlobalScriptLevel);
+ return IsPossibleFirstTypedIdentifierInLocalDeclarationStatement(isGlobalScriptLevel);
}
private bool IsPossibleScopedKeyword(bool isFunctionPointerParameter)
@@ -8322,7 +8324,7 @@ private bool IsPossibleScopedKeyword(bool isFunctionPointerParameter)
return ParsePossibleScopedKeyword(isFunctionPointerParameter, isLambdaParameter: false) != null;
}
- private bool IsPossibleFirstTypedIdentifierInLocaDeclarationStatement(bool isGlobalScriptLevel)
+ private bool IsPossibleFirstTypedIdentifierInLocalDeclarationStatement(bool isGlobalScriptLevel)
{
bool? typedIdentifier = IsPossibleTypedIdentifierStart(this.CurrentToken, this.PeekToken(1), allowThisKeyword: false);
if (typedIdentifier != null)
@@ -8394,11 +8396,22 @@ private bool IsPossibleFirstTypedIdentifierInLocaDeclarationStatement(bool isGlo
return true;
}
- if (st == ScanTypeFlags.NotType || this.CurrentToken.Kind != SyntaxKind.IdentifierToken)
+ if (st == ScanTypeFlags.NotType)
{
return false;
}
+ if (this.CurrentToken.Kind != SyntaxKind.IdentifierToken)
+ {
+ // In the case of something like:
+ // List
+ // if
+ // we know that we're in an error case, as the following keyword must be the start of a new statement.
+ // We'd prefer to assume that this is an incomplete local declaration over an expression, as it's more likely
+ // the user is just in the middle of writing a local declaration, and not an expression.
+ return st == ScanTypeFlags.GenericTypeOrExpression && (IsDefiniteStatement() || IsTypeDeclarationStart() || IsAccessibilityModifier(CurrentToken.Kind));
+ }
+
// T? and T* might start an expression, we need to parse further to disambiguate:
if (isGlobalScriptLevel)
{
@@ -8457,7 +8470,7 @@ private bool IsPossibleTopLevelUsingLocalDeclarationStatement()
EatToken();
}
- return IsPossibleFirstTypedIdentifierInLocaDeclarationStatement(isGlobalScriptLevel: false);
+ return IsPossibleFirstTypedIdentifierInLocalDeclarationStatement(isGlobalScriptLevel: false);
}
// Looks ahead for a declaration of a field, property or method declaration following a nullable type T?.
@@ -8905,17 +8918,16 @@ private PostSkipAction SkipBadStatementListTokens(SyntaxListBuilder
+ /// Separate pool for assembly symbols as these collections commonly exceed ArrayBuilder's size threshold.
+ ///
+ private static readonly ObjectPool> s_symbolPool = new ObjectPool>(() => new ArrayBuilder());
+
///
/// The system assembly, which provides primitive types like Object, String, etc., e.g. mscorlib.dll.
/// The value is provided by ReferenceManager and must not be modified. For SourceAssemblySymbol, non-missing
@@ -948,7 +953,7 @@ internal NamedTypeSymbol GetPrimitiveType(Microsoft.Cci.PrimitiveTypeCode type)
Debug.Assert(this is SourceAssemblySymbol,
"Never include references for a non-source assembly, because they don't know about aliases.");
- var assemblies = ArrayBuilder.GetInstance();
+ var assemblies = s_symbolPool.Allocate();
// ignore reference aliases if searching for a type from a specific assembly:
if (assemblyOpt != null)
@@ -1015,7 +1020,13 @@ internal NamedTypeSymbol GetPrimitiveType(Microsoft.Cci.PrimitiveTypeCode type)
result = candidate;
}
- assemblies.Free();
+ assemblies.Clear();
+
+ // Do not call assemblies.Free, as the ArrayBuilder isn't associated with our pool and even if it were, we don't
+ // want the default freeing behavior of limiting pooled array size to ArrayBuilder.PooledArrayLengthLimitExclusive.
+ // Instead, we need to explicitly add this item back to our pool.
+ s_symbolPool.Free(assemblies);
+
Debug.Assert(result?.IsErrorType() != true);
return result;
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/PublicModel/MethodSymbol.cs b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/PublicModel/MethodSymbol.cs
index a2dd62da743..09eb8d8bc5a 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/PublicModel/MethodSymbol.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/PublicModel/MethodSymbol.cs
@@ -332,6 +332,21 @@ INamedTypeSymbol IMethodSymbol.AssociatedAnonymousDelegate
DllImportData IMethodSymbol.GetDllImportData() => _underlying.GetDllImportData();
+#nullable enable
+ IMethodSymbol? IMethodSymbol.AssociatedExtensionImplementation
+ {
+ get
+ {
+ if (!_underlying.IsDefinition || !_underlying.GetIsNewExtensionMember())
+ {
+ return null;
+ }
+
+ return _underlying.TryGetCorrespondingExtensionImplementationMethod().GetPublicSymbol();
+ }
+ }
+#nullable disable
+
#region ISymbol Members
protected override void Accept(SymbolVisitor visitor)
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/PublicModel/NamedTypeSymbol.cs b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/PublicModel/NamedTypeSymbol.cs
index 38863cab17c..0091d809d2f 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/PublicModel/NamedTypeSymbol.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/PublicModel/NamedTypeSymbol.cs
@@ -202,6 +202,12 @@ UnderlyingNamedTypeSymbol.OriginalDefinition is SourceMemberContainerTypeSymbol
INamedTypeSymbol INamedTypeSymbol.NativeIntegerUnderlyingType => UnderlyingNamedTypeSymbol.NativeIntegerUnderlyingType.GetPublicSymbol();
+#nullable enable
+ bool INamedTypeSymbol.IsExtension => UnderlyingNamedTypeSymbol.IsExtension;
+
+ IParameterSymbol? INamedTypeSymbol.ExtensionParameter => UnderlyingNamedTypeSymbol.ExtensionParameter?.GetPublicSymbol();
+#nullable disable
+
#region ISymbol Members
protected sealed override void Accept(SymbolVisitor visitor)
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs
index 4e71714542d..01254ba3f24 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs
@@ -47,8 +47,16 @@ private SourceConstructorSymbol(
if (syntax.Identifier.ValueText != containingType.Name)
{
- // This is probably a method declaration with the type missing.
- diagnostics.Add(ErrorCode.ERR_MemberNeedsType, location);
+ if (syntax.Identifier.Text == "extension")
+ {
+ bool reported = !MessageID.IDS_FeatureExtensions.CheckFeatureAvailability(diagnostics, syntax);
+ Debug.Assert(reported);
+ }
+ else
+ {
+ // This is probably a method declaration with the type missing.
+ diagnostics.Add(ErrorCode.ERR_MemberNeedsType, location);
+ }
}
bool hasAnyBody = syntax.HasAnyBody();
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
index f9cb27bf315..53d26e08435 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
@@ -1843,6 +1843,8 @@ internal override IEnumerable GetInstanceFieldsAndEvents()
protected void AfterMembersChecks(BindingDiagnosticBag diagnostics)
{
var compilation = DeclaringCompilation;
+ var location = GetFirstLocation();
+
if (IsInterface)
{
CheckInterfaceMembers(this.GetMembersAndInitializers().NonTypeMembers, diagnostics);
@@ -1850,6 +1852,7 @@ protected void AfterMembersChecks(BindingDiagnosticBag diagnostics)
else if (IsExtension)
{
CheckExtensionMembers(this.GetMembers(), diagnostics);
+ MessageID.IDS_FeatureExtensions.CheckFeatureAvailability(diagnostics, compilation, location);
}
CheckMemberNamesDistinctFromType(diagnostics);
@@ -1869,8 +1872,6 @@ protected void AfterMembersChecks(BindingDiagnosticBag diagnostics)
ReportRequiredMembers(diagnostics);
}
- var location = GetFirstLocation();
-
if (this.IsRefLikeType)
{
compilation.EnsureIsByRefLikeAttributeExists(diagnostics, location, modifyCompilation: true);
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs
index f635e571f4b..4f5b4603fc0 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedBackingFieldSymbol.cs
@@ -147,6 +147,14 @@ internal bool InfersNullableAnnotation
}
}
+ ///
+ /// Gets the inferred nullable annotation of the backing field,
+ /// potentially binding and nullable-analyzing the associated get accessor.
+ ///
+ ///
+ /// The for this symbol does not expose this inferred nullable annotation.
+ /// For that API, the nullable annotation of the associated property is used instead.
+ ///
internal NullableAnnotation GetInferredNullableAnnotation()
{
if (_inferredNullableAnnotation == (int)NullableAnnotation.Ignored)
@@ -217,7 +225,7 @@ private NullableAnnotation ComputeInferredNullableAnnotation()
DiagnosticBag nullableAnalyzeAndFilterDiagnostics(NullableAnnotation assumedNullableAnnotation)
{
var diagnostics = DiagnosticBag.GetInstance();
- NullableWalker.AnalyzeIfNeeded(binder, boundGetAccessor, boundGetAccessor.Syntax, diagnostics, getterNullResilienceData: (getAccessor, _property.BackingField, assumedNullableAnnotation));
+ NullableWalker.AnalyzeIfNeeded(binder, boundGetAccessor, boundGetAccessor.Syntax, diagnostics, symbolAndGetterNullResilienceData: (getAccessor, new NullableWalker.GetterNullResilienceData(_property.BackingField, assumedNullableAnnotation)));
if (diagnostics.IsEmptyWithoutResolution)
{
return diagnostics;
diff --git a/src/roslyn/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs b/src/roslyn/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs
index e8001e59e11..9ce1d27ab03 100644
--- a/src/roslyn/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs
+++ b/src/roslyn/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs
@@ -903,7 +903,7 @@ private static bool NeedsSeparator(SyntaxToken token, SyntaxToken next)
return true;
}
- if (IsKeyword(token.Kind()))
+ if (IsKeyword(token.Kind()) && !token.IsKind(SyntaxKind.ExtensionKeyword))
{
if (!next.IsKind(SyntaxKind.ColonToken) &&
!next.IsKind(SyntaxKind.DotToken) &&
diff --git a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs
index bddf43f5220..3ce646e6931 100644
--- a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs
+++ b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncEHTests.cs
@@ -15,6 +15,7 @@
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
+ [CompilerTrait(CompilerFeature.Async)]
public class CodeGenAsyncEHTests : EmitMetadataTestBase
{
private static readonly MetadataReference[] s_asyncRefs = new[] { MscorlibRef_v4_0_30316_17626, SystemRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929 };
diff --git a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs
index 6b49e879285..435e3bd64c3 100644
--- a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs
+++ b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs
@@ -31,7 +31,7 @@ internal enum Instruction
YieldBreak
}
- [CompilerTrait(CompilerFeature.AsyncStreams)]
+ [CompilerTrait(CompilerFeature.AsyncStreams, CompilerFeature.Async)]
public class CodeGenAsyncIteratorTests : EmitMetadataTestBase
{
internal static string ExpectedOutput(string output)
diff --git a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncLocalsTests.cs b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncLocalsTests.cs
index 3bbd16b6f85..95e4fa9f304 100644
--- a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncLocalsTests.cs
+++ b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncLocalsTests.cs
@@ -16,6 +16,7 @@
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
+ [CompilerTrait(CompilerFeature.Async)]
public class CodeGenAsyncLocalsTests : EmitMetadataTestBase
{
private static readonly MetadataReference[] s_asyncRefs = new[] { MscorlibRef_v4_0_30316_17626, SystemRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929 };
diff --git a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMainTests.cs b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMainTests.cs
index a822b966564..379636e59b2 100644
--- a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMainTests.cs
+++ b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMainTests.cs
@@ -16,7 +16,7 @@
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
- [CompilerTrait(CompilerFeature.AsyncMain)]
+ [CompilerTrait(CompilerFeature.AsyncMain, CompilerFeature.Async)]
public class CodeGenAsyncMainTests : EmitMetadataTestBase
{
[Fact]
diff --git a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMethodBuilderOverrideTests.cs b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMethodBuilderOverrideTests.cs
index fc204d27f2e..2d74fd74e00 100644
--- a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMethodBuilderOverrideTests.cs
+++ b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncMethodBuilderOverrideTests.cs
@@ -12,6 +12,7 @@
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
+ [CompilerTrait(CompilerFeature.Async)]
public class CodeGenAsyncMethodBuilderOverrideTests : EmitMetadataTestBase
{
private const string AsyncMethodBuilderAttribute =
diff --git a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
index 8ae68599773..bc5f8f01cdd 100644
--- a/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
+++ b/src/roslyn/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncSpillTests.cs
@@ -14,6 +14,7 @@
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
+ [CompilerTrait(CompilerFeature.Async)]
public class CodeGenAsyncSpillTests : EmitMetadataTestBase
{
public CodeGenAsyncSpillTests()
@@ -1119,6 +1120,8 @@ public static async Task F(int[] array)
";
var v = CompileAndVerify(source, options: TestOptions.DebugDll);
+ // https://github.com/dotnet/roslyn/issues/80147 - There's an extra unneeded array
+ // load before the await that could be removed
v.VerifyIL("Test.d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext",
@"{
// Code size 273 (0x111)
@@ -1255,64 +1258,66 @@ .locals init (int V_0,
}", sequencePoints: "Test+d__2.MoveNext");
var comp = CreateRuntimeAsyncCompilation(source);
- comp.VerifyEmitDiagnostics(
- // (18,38): error CS9328: Method 'Test.F(int[])' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // H(array[1] += 2, array[3] += await G(), 4);
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await G()").WithArguments("Test.F(int[])").WithLocation(18, 38)
- );
- // https://github.com/dotnet/roslyn/issues/79763
- // var verifier = CompileAndVerify(comp, verify: Verification.Fails with
- // {
- // ILVerifyMessage = """
- // [F]: Unexpected type on the stack. { Offset = 0x35, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
- // """
- // });
-
- // verifier.VerifyDiagnostics();
- // verifier.VerifyIL("Test.F(int[])", """
- // {
- // // Code size 54 (0x36)
- // .maxstack 4
- // .locals init (int& V_0,
- // int V_1,
- // int V_2,
- // int V_3)
- // IL_0000: ldarg.0
- // IL_0001: ldc.i4.1
- // IL_0002: ldelema "int"
- // IL_0007: dup
- // IL_0008: ldind.i4
- // IL_0009: ldc.i4.2
- // IL_000a: add
- // IL_000b: dup
- // IL_000c: stloc.3
- // IL_000d: stind.i4
- // IL_000e: ldloc.3
- // IL_000f: ldarg.0
- // IL_0010: ldc.i4.3
- // IL_0011: ldelema "int"
- // IL_0016: stloc.0
- // IL_0017: ldloc.0
- // IL_0018: ldind.i4
- // IL_0019: stloc.1
- // IL_001a: call "System.Threading.Tasks.Task Test.G()"
- // IL_001f: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0024: stloc.2
- // IL_0025: ldloc.0
- // IL_0026: ldloc.1
- // IL_0027: ldloc.2
- // IL_0028: add
- // IL_0029: dup
- // IL_002a: stloc.3
- // IL_002b: stind.i4
- // IL_002c: ldloc.3
- // IL_002d: ldc.i4.4
- // IL_002e: call "int Test.H(int, int, int)"
- // IL_0033: pop
- // IL_0034: ldc.i4.1
- // IL_0035: ret
- // }
- // """);
+ var verifier = CompileAndVerify(comp, verify: Verification.Fails with
+ {
+ ILVerifyMessage = """
+ [F]: Unexpected type on the stack. { Offset = 0x40, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
+ """
+ });
+
+ verifier.VerifyDiagnostics();
+ verifier.VerifyIL("Test.F(int[])", """
+ {
+ // Code size 65 (0x41)
+ .maxstack 4
+ .locals init (int[] V_0,
+ int& V_1,
+ int V_2,
+ int V_3,
+ int V_4)
+ IL_0000: ldarg.0
+ IL_0001: ldc.i4.1
+ IL_0002: ldelema "int"
+ IL_0007: dup
+ IL_0008: ldind.i4
+ IL_0009: ldc.i4.2
+ IL_000a: add
+ IL_000b: dup
+ IL_000c: stloc.s V_4
+ IL_000e: stind.i4
+ IL_000f: ldloc.s V_4
+ IL_0011: ldarg.0
+ IL_0012: stloc.0
+ IL_0013: ldloc.0
+ IL_0014: ldc.i4.3
+ IL_0015: ldelem.i4
+ IL_0016: pop
+ IL_0017: ldloc.0
+ IL_0018: ldc.i4.3
+ IL_0019: ldelem.i4
+ IL_001a: stloc.2
+ IL_001b: call "System.Threading.Tasks.Task Test.G()"
+ IL_0020: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_0025: stloc.3
+ IL_0026: ldloc.0
+ IL_0027: ldc.i4.3
+ IL_0028: ldelema "int"
+ IL_002d: stloc.1
+ IL_002e: ldloc.1
+ IL_002f: ldloc.2
+ IL_0030: ldloc.3
+ IL_0031: add
+ IL_0032: dup
+ IL_0033: stloc.s V_4
+ IL_0035: stind.i4
+ IL_0036: ldloc.s V_4
+ IL_0038: ldc.i4.4
+ IL_0039: call "int Test.H(int, int, int)"
+ IL_003e: pop
+ IL_003f: ldc.i4.1
+ IL_0040: ret
+ }
+ """);
}
[Fact]
@@ -1468,164 +1473,180 @@ .locals init (int V_0,
}", sequencePoints: "Test+d__2.MoveNext");
var comp = CreateRuntimeAsyncCompilation(source);
- comp.VerifyEmitDiagnostics(
- // (18,38): error CS9328: Method 'Test.F(int[])' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // H(array[1] += 2, array[3] += await G(), 4);
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await G()").WithArguments("Test.F(int[])").WithLocation(18, 38)
- );
- // https://github.com/dotnet/roslyn/issues/79763
- // var verifier = CompileAndVerify(comp, verify: Verification.Fails with
- // {
- // ILVerifyMessage = """
- // [F]: Unexpected type on the stack. { Offset = 0x35, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
- // """
- // });
-
- // verifier.VerifyDiagnostics();
- // verifier.VerifyIL("Test.F(int[])", """
- // {
- // // Code size 54 (0x36)
- // .maxstack 4
- // .locals init (int& V_0,
- // int V_1,
- // int V_2,
- // int V_3)
- // IL_0000: ldarg.0
- // IL_0001: ldc.i4.1
- // IL_0002: ldelema "int"
- // IL_0007: dup
- // IL_0008: ldind.i4
- // IL_0009: ldc.i4.2
- // IL_000a: add
- // IL_000b: dup
- // IL_000c: stloc.3
- // IL_000d: stind.i4
- // IL_000e: ldloc.3
- // IL_000f: ldarg.0
- // IL_0010: ldc.i4.3
- // IL_0011: ldelema "int"
- // IL_0016: stloc.0
- // IL_0017: ldloc.0
- // IL_0018: ldind.i4
- // IL_0019: stloc.1
- // IL_001a: call "System.Threading.Tasks.Task Test.G()"
- // IL_001f: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0024: stloc.2
- // IL_0025: ldloc.0
- // IL_0026: ldloc.1
- // IL_0027: ldloc.2
- // IL_0028: add
- // IL_0029: dup
- // IL_002a: stloc.3
- // IL_002b: stind.i4
- // IL_002c: ldloc.3
- // IL_002d: ldc.i4.4
- // IL_002e: call "int Test.H(int, int, int)"
- // IL_0033: pop
- // IL_0034: ldc.i4.1
- // IL_0035: ret
- // }
- // """);
+ var verifier = CompileAndVerify(comp, verify: Verification.Fails with
+ {
+ ILVerifyMessage = """
+ [F]: Unexpected type on the stack. { Offset = 0x40, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
+ """
+ });
+
+ verifier.VerifyDiagnostics();
+ verifier.VerifyIL("Test.F(int[])", """
+ {
+ // Code size 65 (0x41)
+ .maxstack 4
+ .locals init (int[] V_0,
+ int& V_1,
+ int V_2,
+ int V_3,
+ int V_4)
+ IL_0000: ldarg.0
+ IL_0001: ldc.i4.1
+ IL_0002: ldelema "int"
+ IL_0007: dup
+ IL_0008: ldind.i4
+ IL_0009: ldc.i4.2
+ IL_000a: add
+ IL_000b: dup
+ IL_000c: stloc.s V_4
+ IL_000e: stind.i4
+ IL_000f: ldloc.s V_4
+ IL_0011: ldarg.0
+ IL_0012: stloc.0
+ IL_0013: ldloc.0
+ IL_0014: ldc.i4.3
+ IL_0015: ldelem.i4
+ IL_0016: pop
+ IL_0017: ldloc.0
+ IL_0018: ldc.i4.3
+ IL_0019: ldelem.i4
+ IL_001a: stloc.2
+ IL_001b: call "System.Threading.Tasks.Task Test.G()"
+ IL_0020: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_0025: stloc.3
+ IL_0026: ldloc.0
+ IL_0027: ldc.i4.3
+ IL_0028: ldelema "int"
+ IL_002d: stloc.1
+ IL_002e: ldloc.1
+ IL_002f: ldloc.2
+ IL_0030: ldloc.3
+ IL_0031: add
+ IL_0032: dup
+ IL_0033: stloc.s V_4
+ IL_0035: stind.i4
+ IL_0036: ldloc.s V_4
+ IL_0038: ldc.i4.4
+ IL_0039: call "int Test.H(int, int, int)"
+ IL_003e: pop
+ IL_003f: ldc.i4.1
+ IL_0040: ret
+ }
+ """);
}
[Fact]
public void SpillSequencesInConditionalExpression1()
{
var source = @"
+using System;
using System.Threading.Tasks;
public class Test
{
public static int H(int a, int b, int c)
{
+ Console.Write($""H{a},{b},{c};"");
return a;
}
- public static Task G()
+ public static Task G(int i)
{
- return null;
+ Console.Write($""G{i}"");
+ return Task.FromResult(i);
}
public static async Task F(int[] array)
{
- H(0, (1 == await G()) ? array[3] += await G() : 1, 4);
+ H(0, (1 == await G(1)) ? array[3] += await G(2) : 1, 4);
return 1;
}
+
+ public static async Task Main()
+ {
+ await F(new int[4]);
+ }
}
";
- CompileAndVerify(source, options: TestOptions.DebugDll);
+
+ var expectedOutput = "G1G2H0,2,4;";
+ CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: expectedOutput);
var comp = CreateRuntimeAsyncCompilation(source);
- comp.VerifyEmitDiagnostics(
- // (18,45): error CS9328: Method 'Test.F(int[])' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // H(0, (1 == await G()) ? array[3] += await G() : 1, 4);
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await G()").WithArguments("Test.F(int[])").WithLocation(18, 45)
- );
- // https://github.com/dotnet/roslyn/issues/79763
- // var verifier = CompileAndVerify(comp, verify: Verification.Fails with
- // {
- // ILVerifyMessage = """
- // [F]: Unexpected type on the stack. { Offset = 0x3c, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
- // """
- // });
-
- // verifier.VerifyDiagnostics();
- // verifier.VerifyIL("Test.F(int[])", """
- // {
- // // Code size 61 (0x3d)
- // .maxstack 3
- // .locals init (int V_0,
- // int V_1,
- // int V_2,
- // int V_3,
- // int V_4)
- // IL_0000: call "System.Threading.Tasks.Task Test.G()"
- // IL_0005: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_000a: stloc.0
- // IL_000b: ldc.i4.1
- // IL_000c: ldloc.0
- // IL_000d: bne.un.s IL_0030
- // IL_000f: ldarg.0
- // IL_0010: ldc.i4.3
- // IL_0011: ldelema "int"
- // IL_0016: dup
- // IL_0017: ldind.i4
- // IL_0018: stloc.2
- // IL_0019: call "System.Threading.Tasks.Task Test.G()"
- // IL_001e: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0023: stloc.3
- // IL_0024: ldloc.2
- // IL_0025: ldloc.3
- // IL_0026: add
- // IL_0027: dup
- // IL_0028: stloc.s V_4
- // IL_002a: stind.i4
- // IL_002b: ldloc.s V_4
- // IL_002d: stloc.1
- // IL_002e: br.s IL_0032
- // IL_0030: ldc.i4.1
- // IL_0031: stloc.1
- // IL_0032: ldc.i4.0
- // IL_0033: ldloc.1
- // IL_0034: ldc.i4.4
- // IL_0035: call "int Test.H(int, int, int)"
- // IL_003a: pop
- // IL_003b: ldc.i4.1
- // IL_003c: ret
- // }
- // """);
+ var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
+ {
+ ILVerifyMessage = """
+ [F]: Unexpected type on the stack. { Offset = 0x43, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
+ [Main]: Return value missing on the stack. { Offset = 0x11 }
+ """
+ });
+
+ verifier.VerifyDiagnostics();
+ verifier.VerifyIL("Test.F(int[])", """
+ {
+ // Code size 68 (0x44)
+ .maxstack 3
+ .locals init (int V_0,
+ int V_1,
+ int V_2,
+ int V_3,
+ int V_4)
+ IL_0000: ldc.i4.1
+ IL_0001: call "System.Threading.Tasks.Task Test.G(int)"
+ IL_0006: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_000b: stloc.0
+ IL_000c: ldc.i4.1
+ IL_000d: ldloc.0
+ IL_000e: bne.un.s IL_0037
+ IL_0010: ldarg.0
+ IL_0011: dup
+ IL_0012: ldc.i4.3
+ IL_0013: ldelem.i4
+ IL_0014: pop
+ IL_0015: dup
+ IL_0016: ldc.i4.3
+ IL_0017: ldelem.i4
+ IL_0018: stloc.2
+ IL_0019: ldc.i4.2
+ IL_001a: call "System.Threading.Tasks.Task Test.G(int)"
+ IL_001f: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_0024: stloc.3
+ IL_0025: ldc.i4.3
+ IL_0026: ldelema "int"
+ IL_002b: ldloc.2
+ IL_002c: ldloc.3
+ IL_002d: add
+ IL_002e: dup
+ IL_002f: stloc.s V_4
+ IL_0031: stind.i4
+ IL_0032: ldloc.s V_4
+ IL_0034: stloc.1
+ IL_0035: br.s IL_0039
+ IL_0037: ldc.i4.1
+ IL_0038: stloc.1
+ IL_0039: ldc.i4.0
+ IL_003a: ldloc.1
+ IL_003b: ldc.i4.4
+ IL_003c: call "int Test.H(int, int, int)"
+ IL_0041: pop
+ IL_0042: ldc.i4.1
+ IL_0043: ret
+ }
+ """);
}
[Fact]
public void SpillSequencesInNullCoalescingOperator1()
{
var source = @"
+using System;
using System.Threading.Tasks;
public class C
{
public static int H(int a, object b, int c)
{
+ Console.Write($""H{a},{b},{c};"");
return a;
}
@@ -1634,19 +1655,27 @@ public static object O(int a)
return null;
}
- public static Task G()
+ public static Task G(int i)
{
- return null;
+ Console.Write($""G{i};"");
+ return Task.FromResult(i);
}
public static async Task F(int[] array)
{
- H(0, O(array[0] += await G()) ?? (array[1] += await G()), 4);
+ H(0, O(array[0] += await G(1)) ?? (array[1] += await G(2)), 4);
return 1;
}
+
+ public static async Task Main()
+ {
+ await F(new int[4]);
+ }
}
";
- CompileAndVerify(source, options: TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module =>
+
+ var expectedOutput = "G1;G2;H0,2,4;";
+ CompileAndVerify(source, options: TestOptions.ReleaseExe.WithMetadataImportOptions(MetadataImportOptions.All), expectedOutput: expectedOutput, symbolValidator: module =>
{
AssertEx.Equal(new[]
{
@@ -1661,7 +1690,7 @@ public static async Task F(int[] array)
}, module.GetFieldNames("C.d__3"));
});
- CompileAndVerify(source, verify: Verification.Passes, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module =>
+ CompileAndVerify(source, verify: Verification.Passes, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), expectedOutput: expectedOutput, symbolValidator: module =>
{
AssertEx.Equal(new[]
{
@@ -1681,80 +1710,84 @@ public static async Task F(int[] array)
});
var comp = CreateRuntimeAsyncCompilation(source);
- comp.VerifyEmitDiagnostics(
- // (23,28): error CS9328: Method 'C.F(int[])' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // H(0, O(array[0] += await G()) ?? (array[1] += await G()), 4);
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await G()").WithArguments("C.F(int[])").WithLocation(23, 28),
- // (23,55): error CS9328: Method 'C.F(int[])' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // H(0, O(array[0] += await G()) ?? (array[1] += await G()), 4);
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await G()").WithArguments("C.F(int[])").WithLocation(23, 55)
- );
- // https://github.com/dotnet/roslyn/issues/79763
- // var verifier = CompileAndVerify(comp, verify: Verification.Fails with
- // {
- // ILVerifyMessage = """
- // [F]: Unexpected type on the stack. { Offset = 0x55, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
- // """
- // });
-
- // verifier.VerifyDiagnostics();
- // verifier.VerifyIL("C.F(int[])", """
- // {
- // // Code size 86 (0x56)
- // .maxstack 3
- // .locals init (int V_0,
- // int V_1,
- // object V_2,
- // int V_3,
- // int V_4,
- // int V_5)
- // IL_0000: ldarg.0
- // IL_0001: ldc.i4.0
- // IL_0002: ldelema "int"
- // IL_0007: dup
- // IL_0008: ldind.i4
- // IL_0009: stloc.0
- // IL_000a: call "System.Threading.Tasks.Task C.G()"
- // IL_000f: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0014: stloc.1
- // IL_0015: ldloc.0
- // IL_0016: ldloc.1
- // IL_0017: add
- // IL_0018: dup
- // IL_0019: stloc.3
- // IL_001a: stind.i4
- // IL_001b: ldloc.3
- // IL_001c: call "object C.O(int)"
- // IL_0021: stloc.2
- // IL_0022: ldloc.2
- // IL_0023: brtrue.s IL_004b
- // IL_0025: ldarg.0
- // IL_0026: ldc.i4.1
- // IL_0027: ldelema "int"
- // IL_002c: dup
- // IL_002d: ldind.i4
- // IL_002e: stloc.3
- // IL_002f: call "System.Threading.Tasks.Task C.G()"
- // IL_0034: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0039: stloc.s V_4
- // IL_003b: ldloc.3
- // IL_003c: ldloc.s V_4
- // IL_003e: add
- // IL_003f: dup
- // IL_0040: stloc.s V_5
- // IL_0042: stind.i4
- // IL_0043: ldloc.s V_5
- // IL_0045: box "int"
- // IL_004a: stloc.2
- // IL_004b: ldc.i4.0
- // IL_004c: ldloc.2
- // IL_004d: ldc.i4.4
- // IL_004e: call "int C.H(int, object, int)"
- // IL_0053: pop
- // IL_0054: ldc.i4.1
- // IL_0055: ret
- // }
- // """);
+ var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
+ {
+ ILVerifyMessage = """
+ [F]: Unexpected type on the stack. { Offset = 0x61, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
+ [Main]: Return value missing on the stack. { Offset = 0x11 }
+ """
+ });
+
+ verifier.VerifyDiagnostics();
+ verifier.VerifyIL("C.F(int[])", """
+ {
+ // Code size 98 (0x62)
+ .maxstack 3
+ .locals init (int V_0,
+ int V_1,
+ object V_2,
+ int V_3,
+ int V_4,
+ int V_5)
+ IL_0000: ldarg.0
+ IL_0001: dup
+ IL_0002: ldc.i4.0
+ IL_0003: ldelem.i4
+ IL_0004: pop
+ IL_0005: dup
+ IL_0006: ldc.i4.0
+ IL_0007: ldelem.i4
+ IL_0008: stloc.0
+ IL_0009: ldc.i4.1
+ IL_000a: call "System.Threading.Tasks.Task C.G(int)"
+ IL_000f: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_0014: stloc.1
+ IL_0015: ldc.i4.0
+ IL_0016: ldelema "int"
+ IL_001b: ldloc.0
+ IL_001c: ldloc.1
+ IL_001d: add
+ IL_001e: dup
+ IL_001f: stloc.3
+ IL_0020: stind.i4
+ IL_0021: ldloc.3
+ IL_0022: call "object C.O(int)"
+ IL_0027: stloc.2
+ IL_0028: ldloc.2
+ IL_0029: brtrue.s IL_0057
+ IL_002b: ldarg.0
+ IL_002c: dup
+ IL_002d: ldc.i4.1
+ IL_002e: ldelem.i4
+ IL_002f: pop
+ IL_0030: dup
+ IL_0031: ldc.i4.1
+ IL_0032: ldelem.i4
+ IL_0033: stloc.3
+ IL_0034: ldc.i4.2
+ IL_0035: call "System.Threading.Tasks.Task C.G(int)"
+ IL_003a: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_003f: stloc.s V_4
+ IL_0041: ldc.i4.1
+ IL_0042: ldelema "int"
+ IL_0047: ldloc.3
+ IL_0048: ldloc.s V_4
+ IL_004a: add
+ IL_004b: dup
+ IL_004c: stloc.s V_5
+ IL_004e: stind.i4
+ IL_004f: ldloc.s V_5
+ IL_0051: box "int"
+ IL_0056: stloc.2
+ IL_0057: ldc.i4.0
+ IL_0058: ldloc.2
+ IL_0059: ldc.i4.4
+ IL_005a: call "int C.H(int, object, int)"
+ IL_005f: pop
+ IL_0060: ldc.i4.1
+ IL_0061: ret
+ }
+ """);
}
[WorkItem(4628, "https://github.com/dotnet/roslyn/issues/4628")]
@@ -2061,80 +2094,81 @@ public static async Task F(int[] array)
CompileAndVerify(source, options: TestOptions.DebugDll);
var comp = CreateRuntimeAsyncCompilation(source);
- comp.VerifyEmitDiagnostics(
- // (23,28): error CS9328: Method 'Test.F(int[])' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // H(0, B(array[0] += await G()) || B(array[1] += await G()), 4);
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await G()").WithArguments("Test.F(int[])").WithLocation(23, 28),
- // (23,56): error CS9328: Method 'Test.F(int[])' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // H(0, B(array[0] += await G()) || B(array[1] += await G()), 4);
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await G()").WithArguments("Test.F(int[])").WithLocation(23, 56)
- );
- // https://github.com/dotnet/roslyn/issues/79763
- // var verifier = CompileAndVerify(comp, verify: Verification.Fails with
- // {
- // ILVerifyMessage = """
- // [F]: Unexpected type on the stack. { Offset = 0x55, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
- // """
- // });
-
- // verifier.VerifyDiagnostics();
- // verifier.VerifyIL("Test.F(int[])", """
- // {
- // // Code size 86 (0x56)
- // .maxstack 3
- // .locals init (int V_0,
- // int V_1,
- // bool V_2,
- // int V_3,
- // int V_4,
- // int V_5)
- // IL_0000: ldarg.0
- // IL_0001: ldc.i4.0
- // IL_0002: ldelema "int"
- // IL_0007: dup
- // IL_0008: ldind.i4
- // IL_0009: stloc.0
- // IL_000a: call "System.Threading.Tasks.Task Test.G()"
- // IL_000f: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0014: stloc.1
- // IL_0015: ldloc.0
- // IL_0016: ldloc.1
- // IL_0017: add
- // IL_0018: dup
- // IL_0019: stloc.3
- // IL_001a: stind.i4
- // IL_001b: ldloc.3
- // IL_001c: call "bool Test.B(int)"
- // IL_0021: stloc.2
- // IL_0022: ldloc.2
- // IL_0023: brtrue.s IL_004b
- // IL_0025: ldarg.0
- // IL_0026: ldc.i4.1
- // IL_0027: ldelema "int"
- // IL_002c: dup
- // IL_002d: ldind.i4
- // IL_002e: stloc.3
- // IL_002f: call "System.Threading.Tasks.Task Test.G()"
- // IL_0034: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0039: stloc.s V_4
- // IL_003b: ldloc.3
- // IL_003c: ldloc.s V_4
- // IL_003e: add
- // IL_003f: dup
- // IL_0040: stloc.s V_5
- // IL_0042: stind.i4
- // IL_0043: ldloc.s V_5
- // IL_0045: call "bool Test.B(int)"
- // IL_004a: stloc.2
- // IL_004b: ldc.i4.0
- // IL_004c: ldloc.2
- // IL_004d: ldc.i4.4
- // IL_004e: call "int Test.H(int, bool, int)"
- // IL_0053: pop
- // IL_0054: ldc.i4.1
- // IL_0055: ret
- // }
- // """);
+ var verifier = CompileAndVerify(comp, verify: Verification.Fails with
+ {
+ ILVerifyMessage = """
+ [F]: Unexpected type on the stack. { Offset = 0x5f, Found = Int32, Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
+ """
+ });
+
+ verifier.VerifyDiagnostics();
+ verifier.VerifyIL("Test.F(int[])", """
+ {
+ // Code size 96 (0x60)
+ .maxstack 3
+ .locals init (int V_0,
+ int V_1,
+ bool V_2,
+ int V_3,
+ int V_4,
+ int V_5)
+ IL_0000: ldarg.0
+ IL_0001: dup
+ IL_0002: ldc.i4.0
+ IL_0003: ldelem.i4
+ IL_0004: pop
+ IL_0005: dup
+ IL_0006: ldc.i4.0
+ IL_0007: ldelem.i4
+ IL_0008: stloc.0
+ IL_0009: call "System.Threading.Tasks.Task Test.G()"
+ IL_000e: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_0013: stloc.1
+ IL_0014: ldc.i4.0
+ IL_0015: ldelema "int"
+ IL_001a: ldloc.0
+ IL_001b: ldloc.1
+ IL_001c: add
+ IL_001d: dup
+ IL_001e: stloc.3
+ IL_001f: stind.i4
+ IL_0020: ldloc.3
+ IL_0021: call "bool Test.B(int)"
+ IL_0026: stloc.2
+ IL_0027: ldloc.2
+ IL_0028: brtrue.s IL_0055
+ IL_002a: ldarg.0
+ IL_002b: dup
+ IL_002c: ldc.i4.1
+ IL_002d: ldelem.i4
+ IL_002e: pop
+ IL_002f: dup
+ IL_0030: ldc.i4.1
+ IL_0031: ldelem.i4
+ IL_0032: stloc.3
+ IL_0033: call "System.Threading.Tasks.Task Test.G()"
+ IL_0038: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_003d: stloc.s V_4
+ IL_003f: ldc.i4.1
+ IL_0040: ldelema "int"
+ IL_0045: ldloc.3
+ IL_0046: ldloc.s V_4
+ IL_0048: add
+ IL_0049: dup
+ IL_004a: stloc.s V_5
+ IL_004c: stind.i4
+ IL_004d: ldloc.s V_5
+ IL_004f: call "bool Test.B(int)"
+ IL_0054: stloc.2
+ IL_0055: ldc.i4.0
+ IL_0056: ldloc.2
+ IL_0057: ldc.i4.4
+ IL_0058: call "int Test.H(int, bool, int)"
+ IL_005d: pop
+ IL_005e: ldc.i4.1
+ IL_005f: ret
+ }
+ """);
}
[Fact]
@@ -2929,81 +2963,80 @@ static void Main()
CompileAndVerify(source, expectedOutput);
var comp = CreateRuntimeAsyncCompilation(source);
- comp.VerifyEmitDiagnostics(
- // (23,23): error CS9328: Method 'TestCase.Run(T)' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // arr[0] += await GetVal(4);
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await GetVal(4)").WithArguments("TestCase.Run(T)").WithLocation(23, 23)
- );
- // https://github.com/dotnet/roslyn/issues/79763
- // var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
- // {
- // ILVerifyMessage = """
- // [GetVal]: Unexpected type on the stack. { Offset = 0xc, Found = value 'T', Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
- // [Run]: Return value missing on the stack. { Offset = 0x56 }
- // """
- // });
-
- // verifier.VerifyDiagnostics();
- // verifier.VerifyIL("TestCase.Run(T)", """
- // {
- // // Code size 87 (0x57)
- // .maxstack 4
- // .locals init (int V_0, //tests
- // int V_1,
- // int V_2)
- // IL_0000: ldc.i4.0
- // IL_0001: stloc.0
- // .try
- // {
- // IL_0002: ldc.i4.4
- // IL_0003: newarr "int"
- // IL_0008: dup
- // IL_0009: ldc.i4.0
- // IL_000a: ldc.i4.4
- // IL_000b: stelem.i4
- // IL_000c: ldloc.0
- // IL_000d: ldc.i4.1
- // IL_000e: add
- // IL_000f: stloc.0
- // IL_0010: dup
- // IL_0011: ldc.i4.0
- // IL_0012: ldelema "int"
- // IL_0017: dup
- // IL_0018: ldind.i4
- // IL_0019: stloc.1
- // IL_001a: ldarg.0
- // IL_001b: ldc.i4.4
- // IL_001c: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0021: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0026: stloc.2
- // IL_0027: ldloc.1
- // IL_0028: ldloc.2
- // IL_0029: add
- // IL_002a: stind.i4
- // IL_002b: ldc.i4.0
- // IL_002c: ldelem.i4
- // IL_002d: ldc.i4.8
- // IL_002e: bne.un.s IL_003c
- // IL_0030: ldsfld "int Driver.Count"
- // IL_0035: ldc.i4.1
- // IL_0036: add
- // IL_0037: stsfld "int Driver.Count"
- // IL_003c: leave.s IL_0056
- // }
- // finally
- // {
- // IL_003e: ldsfld "int Driver.Count"
- // IL_0043: ldloc.0
- // IL_0044: sub
- // IL_0045: stsfld "int Driver.Result"
- // IL_004a: ldsfld "System.Threading.AutoResetEvent Driver.CompletedSignal"
- // IL_004f: callvirt "bool System.Threading.EventWaitHandle.Set()"
- // IL_0054: pop
- // IL_0055: endfinally
- // }
- // IL_0056: ret
- // }
- // """);
+ var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
+ {
+ ILVerifyMessage = """
+ [GetVal]: Unexpected type on the stack. { Offset = 0xc, Found = value 'T', Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
+ [Run]: Return value missing on the stack. { Offset = 0x5b }
+ """
+ });
+
+ verifier.VerifyDiagnostics();
+ verifier.VerifyIL("TestCase.Run(T)", """
+ {
+ // Code size 92 (0x5c)
+ .maxstack 4
+ .locals init (int V_0, //tests
+ int V_1,
+ int V_2)
+ IL_0000: ldc.i4.0
+ IL_0001: stloc.0
+ .try
+ {
+ IL_0002: ldc.i4.4
+ IL_0003: newarr "int"
+ IL_0008: dup
+ IL_0009: ldc.i4.0
+ IL_000a: ldc.i4.4
+ IL_000b: stelem.i4
+ IL_000c: ldloc.0
+ IL_000d: ldc.i4.1
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: dup
+ IL_0011: dup
+ IL_0012: ldc.i4.0
+ IL_0013: ldelem.i4
+ IL_0014: pop
+ IL_0015: dup
+ IL_0016: ldc.i4.0
+ IL_0017: ldelem.i4
+ IL_0018: stloc.1
+ IL_0019: ldarg.0
+ IL_001a: ldc.i4.4
+ IL_001b: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
+ IL_0020: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_0025: stloc.2
+ IL_0026: ldc.i4.0
+ IL_0027: ldelema "int"
+ IL_002c: ldloc.1
+ IL_002d: ldloc.2
+ IL_002e: add
+ IL_002f: stind.i4
+ IL_0030: ldc.i4.0
+ IL_0031: ldelem.i4
+ IL_0032: ldc.i4.8
+ IL_0033: bne.un.s IL_0041
+ IL_0035: ldsfld "int Driver.Count"
+ IL_003a: ldc.i4.1
+ IL_003b: add
+ IL_003c: stsfld "int Driver.Count"
+ IL_0041: leave.s IL_005b
+ }
+ finally
+ {
+ IL_0043: ldsfld "int Driver.Count"
+ IL_0048: ldloc.0
+ IL_0049: sub
+ IL_004a: stsfld "int Driver.Result"
+ IL_004f: ldsfld "System.Threading.AutoResetEvent Driver.CompletedSignal"
+ IL_0054: callvirt "bool System.Threading.EventWaitHandle.Set()"
+ IL_0059: pop
+ IL_005a: endfinally
+ }
+ IL_005b: ret
+ }
+ """);
}
[Fact]
@@ -3128,86 +3161,85 @@ static void Main()
CompileAndVerify(source, expectedOutput);
var comp = CreateRuntimeAsyncCompilation(source);
- comp.VerifyEmitDiagnostics(
- // (22,23): error CS9328: Method 'TestCase.Run(T)' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // arr[1] += await (GetVal(arr[0]));
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await (GetVal(arr[0]))").WithArguments("TestCase.Run(T)").WithLocation(22, 23)
- );
- // https://github.com/dotnet/roslyn/issues/79763
- // var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
- // {
- // ILVerifyMessage = """
- // [GetVal]: Unexpected type on the stack. { Offset = 0xc, Found = value 'T', Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
- // [Run]: Return value missing on the stack. { Offset = 0x5a }
- // """
- // });
-
- // verifier.VerifyDiagnostics();
- // verifier.VerifyIL("TestCase.Run(T)", """
- // {
- // // Code size 91 (0x5b)
- // .maxstack 4
- // .locals init (int V_0, //tests
- // int[] V_1, //arr
- // int V_2,
- // int V_3)
- // IL_0000: ldc.i4.0
- // IL_0001: stloc.0
- // .try
- // {
- // IL_0002: ldc.i4.4
- // IL_0003: newarr "int"
- // IL_0008: dup
- // IL_0009: ldc.i4.0
- // IL_000a: ldc.i4.8
- // IL_000b: stelem.i4
- // IL_000c: stloc.1
- // IL_000d: ldloc.0
- // IL_000e: ldc.i4.1
- // IL_000f: add
- // IL_0010: stloc.0
- // IL_0011: ldloc.1
- // IL_0012: ldc.i4.1
- // IL_0013: ldelema "int"
- // IL_0018: dup
- // IL_0019: ldind.i4
- // IL_001a: stloc.2
- // IL_001b: ldarg.0
- // IL_001c: ldloc.1
- // IL_001d: ldc.i4.0
- // IL_001e: ldelem.i4
- // IL_001f: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0024: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0029: stloc.3
- // IL_002a: ldloc.2
- // IL_002b: ldloc.3
- // IL_002c: add
- // IL_002d: stind.i4
- // IL_002e: ldloc.1
- // IL_002f: ldc.i4.1
- // IL_0030: ldelem.i4
- // IL_0031: ldc.i4.8
- // IL_0032: bne.un.s IL_0040
- // IL_0034: ldsfld "int Driver.Count"
- // IL_0039: ldc.i4.1
- // IL_003a: add
- // IL_003b: stsfld "int Driver.Count"
- // IL_0040: leave.s IL_005a
- // }
- // finally
- // {
- // IL_0042: ldsfld "int Driver.Count"
- // IL_0047: ldloc.0
- // IL_0048: sub
- // IL_0049: stsfld "int Driver.Result"
- // IL_004e: ldsfld "System.Threading.AutoResetEvent Driver.CompletedSignal"
- // IL_0053: callvirt "bool System.Threading.EventWaitHandle.Set()"
- // IL_0058: pop
- // IL_0059: endfinally
- // }
- // IL_005a: ret
- // }
- // """);
+ var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
+ {
+ ILVerifyMessage = """
+ [GetVal]: Unexpected type on the stack. { Offset = 0xc, Found = value 'T', Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
+ [Run]: Return value missing on the stack. { Offset = 0x5f }
+ """
+ });
+
+ verifier.VerifyDiagnostics();
+ verifier.VerifyIL("TestCase.Run(T)", """
+ {
+ // Code size 96 (0x60)
+ .maxstack 4
+ .locals init (int V_0, //tests
+ int[] V_1, //arr
+ int V_2,
+ int V_3)
+ IL_0000: ldc.i4.0
+ IL_0001: stloc.0
+ .try
+ {
+ IL_0002: ldc.i4.4
+ IL_0003: newarr "int"
+ IL_0008: dup
+ IL_0009: ldc.i4.0
+ IL_000a: ldc.i4.8
+ IL_000b: stelem.i4
+ IL_000c: stloc.1
+ IL_000d: ldloc.0
+ IL_000e: ldc.i4.1
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: ldloc.1
+ IL_0012: dup
+ IL_0013: ldc.i4.1
+ IL_0014: ldelem.i4
+ IL_0015: pop
+ IL_0016: dup
+ IL_0017: ldc.i4.1
+ IL_0018: ldelem.i4
+ IL_0019: stloc.2
+ IL_001a: ldarg.0
+ IL_001b: ldloc.1
+ IL_001c: ldc.i4.0
+ IL_001d: ldelem.i4
+ IL_001e: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
+ IL_0023: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_0028: stloc.3
+ IL_0029: ldc.i4.1
+ IL_002a: ldelema "int"
+ IL_002f: ldloc.2
+ IL_0030: ldloc.3
+ IL_0031: add
+ IL_0032: stind.i4
+ IL_0033: ldloc.1
+ IL_0034: ldc.i4.1
+ IL_0035: ldelem.i4
+ IL_0036: ldc.i4.8
+ IL_0037: bne.un.s IL_0045
+ IL_0039: ldsfld "int Driver.Count"
+ IL_003e: ldc.i4.1
+ IL_003f: add
+ IL_0040: stsfld "int Driver.Count"
+ IL_0045: leave.s IL_005f
+ }
+ finally
+ {
+ IL_0047: ldsfld "int Driver.Count"
+ IL_004c: ldloc.0
+ IL_004d: sub
+ IL_004e: stsfld "int Driver.Result"
+ IL_0053: ldsfld "System.Threading.AutoResetEvent Driver.CompletedSignal"
+ IL_0058: callvirt "bool System.Threading.EventWaitHandle.Set()"
+ IL_005d: pop
+ IL_005e: endfinally
+ }
+ IL_005f: ret
+ }
+ """);
}
[Fact]
@@ -3342,127 +3374,126 @@ static void Main()
CompileAndVerify(source, expectedOutput);
var comp = CreateRuntimeAsyncCompilation(source);
- comp.VerifyEmitDiagnostics(
- // (22,23): error CS9328: Method 'TestCase.Run(T)' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // arr[1] += await (GetVal(arr[await GetVal(0)]));
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await (GetVal(arr[await GetVal(0)]))").WithArguments("TestCase.Run(T)").WithLocation(22, 23)
- );
- // https://github.com/dotnet/roslyn/issues/79763
- // var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
- // {
- // ILVerifyMessage = """
- // [GetVal]: Unexpected type on the stack. { Offset = 0xc, Found = value 'T', Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
- // [Run]: Return value missing on the stack. { Offset = 0xa3 }
- // """
- // });
-
- // verifier.VerifyDiagnostics();
- // verifier.VerifyIL("TestCase.Run(T)", """
- // {
- // // Code size 164 (0xa4)
- // .maxstack 4
- // .locals init (int V_0, //tests
- // int& V_1,
- // int V_2,
- // int V_3,
- // int[] V_4,
- // int V_5)
- // IL_0000: ldc.i4.0
- // IL_0001: stloc.0
- // .try
- // {
- // IL_0002: ldc.i4.4
- // IL_0003: newarr "int"
- // IL_0008: dup
- // IL_0009: ldc.i4.0
- // IL_000a: ldc.i4.8
- // IL_000b: stelem.i4
- // IL_000c: dup
- // IL_000d: ldc.i4.1
- // IL_000e: ldc.i4.8
- // IL_000f: stelem.i4
- // IL_0010: ldloc.0
- // IL_0011: ldc.i4.1
- // IL_0012: add
- // IL_0013: stloc.0
- // IL_0014: dup
- // IL_0015: ldc.i4.1
- // IL_0016: ldelema "int"
- // IL_001b: stloc.1
- // IL_001c: ldloc.1
- // IL_001d: ldind.i4
- // IL_001e: stloc.2
- // IL_001f: dup
- // IL_0020: stloc.s V_4
- // IL_0022: ldarg.0
- // IL_0023: ldc.i4.0
- // IL_0024: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0029: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_002e: stloc.s V_5
- // IL_0030: ldarg.0
- // IL_0031: ldloc.s V_4
- // IL_0033: ldloc.s V_5
- // IL_0035: ldelem.i4
- // IL_0036: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_003b: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0040: stloc.3
- // IL_0041: ldloc.1
- // IL_0042: ldloc.2
- // IL_0043: ldloc.3
- // IL_0044: add
- // IL_0045: stind.i4
- // IL_0046: dup
- // IL_0047: ldc.i4.1
- // IL_0048: ldelem.i4
- // IL_0049: ldc.i4.s 16
- // IL_004b: bne.un.s IL_0059
- // IL_004d: ldsfld "int Driver.Count"
- // IL_0052: ldc.i4.1
- // IL_0053: add
- // IL_0054: stsfld "int Driver.Count"
- // IL_0059: ldloc.0
- // IL_005a: ldc.i4.1
- // IL_005b: add
- // IL_005c: stloc.0
- // IL_005d: dup
- // IL_005e: ldarg.0
- // IL_005f: ldc.i4.2
- // IL_0060: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0065: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_006a: stloc.3
- // IL_006b: ldloc.3
- // IL_006c: ldelema "int"
- // IL_0071: dup
- // IL_0072: ldind.i4
- // IL_0073: stloc.2
- // IL_0074: ldloc.2
- // IL_0075: ldc.i4.1
- // IL_0076: add
- // IL_0077: stind.i4
- // IL_0078: ldc.i4.2
- // IL_0079: ldelem.i4
- // IL_007a: ldc.i4.1
- // IL_007b: bne.un.s IL_0089
- // IL_007d: ldsfld "int Driver.Count"
- // IL_0082: ldc.i4.1
- // IL_0083: add
- // IL_0084: stsfld "int Driver.Count"
- // IL_0089: leave.s IL_00a3
- // }
- // finally
- // {
- // IL_008b: ldsfld "int Driver.Count"
- // IL_0090: ldloc.0
- // IL_0091: sub
- // IL_0092: stsfld "int Driver.Result"
- // IL_0097: ldsfld "System.Threading.AutoResetEvent Driver.CompletedSignal"
- // IL_009c: callvirt "bool System.Threading.EventWaitHandle.Set()"
- // IL_00a1: pop
- // IL_00a2: endfinally
- // }
- // IL_00a3: ret
- // }
- // """);
+ var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
+ {
+ ILVerifyMessage = """
+ [GetVal]: Unexpected type on the stack. { Offset = 0xc, Found = value 'T', Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
+ [Run]: Return value missing on the stack. { Offset = 0xa8 }
+ """
+ });
+
+ verifier.VerifyDiagnostics();
+ verifier.VerifyIL("TestCase.Run(T)", """
+ {
+ // Code size 169 (0xa9)
+ .maxstack 4
+ .locals init (int[] V_0,
+ int V_1, //tests
+ int V_2,
+ int V_3,
+ int[] V_4,
+ int V_5)
+ IL_0000: ldc.i4.0
+ IL_0001: stloc.1
+ .try
+ {
+ IL_0002: ldc.i4.4
+ IL_0003: newarr "int"
+ IL_0008: dup
+ IL_0009: ldc.i4.0
+ IL_000a: ldc.i4.8
+ IL_000b: stelem.i4
+ IL_000c: dup
+ IL_000d: ldc.i4.1
+ IL_000e: ldc.i4.8
+ IL_000f: stelem.i4
+ IL_0010: ldloc.1
+ IL_0011: ldc.i4.1
+ IL_0012: add
+ IL_0013: stloc.1
+ IL_0014: dup
+ IL_0015: stloc.0
+ IL_0016: ldloc.0
+ IL_0017: ldc.i4.1
+ IL_0018: ldelem.i4
+ IL_0019: pop
+ IL_001a: ldloc.0
+ IL_001b: ldc.i4.1
+ IL_001c: ldelem.i4
+ IL_001d: stloc.2
+ IL_001e: dup
+ IL_001f: stloc.s V_4
+ IL_0021: ldarg.0
+ IL_0022: ldc.i4.0
+ IL_0023: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
+ IL_0028: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_002d: stloc.s V_5
+ IL_002f: ldarg.0
+ IL_0030: ldloc.s V_4
+ IL_0032: ldloc.s V_5
+ IL_0034: ldelem.i4
+ IL_0035: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
+ IL_003a: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_003f: stloc.3
+ IL_0040: ldloc.0
+ IL_0041: ldc.i4.1
+ IL_0042: ldelema "int"
+ IL_0047: ldloc.2
+ IL_0048: ldloc.3
+ IL_0049: add
+ IL_004a: stind.i4
+ IL_004b: dup
+ IL_004c: ldc.i4.1
+ IL_004d: ldelem.i4
+ IL_004e: ldc.i4.s 16
+ IL_0050: bne.un.s IL_005e
+ IL_0052: ldsfld "int Driver.Count"
+ IL_0057: ldc.i4.1
+ IL_0058: add
+ IL_0059: stsfld "int Driver.Count"
+ IL_005e: ldloc.1
+ IL_005f: ldc.i4.1
+ IL_0060: add
+ IL_0061: stloc.1
+ IL_0062: dup
+ IL_0063: ldarg.0
+ IL_0064: ldc.i4.2
+ IL_0065: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
+ IL_006a: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_006f: stloc.3
+ IL_0070: ldloc.3
+ IL_0071: ldelema "int"
+ IL_0076: dup
+ IL_0077: ldind.i4
+ IL_0078: stloc.2
+ IL_0079: ldloc.2
+ IL_007a: ldc.i4.1
+ IL_007b: add
+ IL_007c: stind.i4
+ IL_007d: ldc.i4.2
+ IL_007e: ldelem.i4
+ IL_007f: ldc.i4.1
+ IL_0080: bne.un.s IL_008e
+ IL_0082: ldsfld "int Driver.Count"
+ IL_0087: ldc.i4.1
+ IL_0088: add
+ IL_0089: stsfld "int Driver.Count"
+ IL_008e: leave.s IL_00a8
+ }
+ finally
+ {
+ IL_0090: ldsfld "int Driver.Count"
+ IL_0095: ldloc.1
+ IL_0096: sub
+ IL_0097: stsfld "int Driver.Result"
+ IL_009c: ldsfld "System.Threading.AutoResetEvent Driver.CompletedSignal"
+ IL_00a1: callvirt "bool System.Threading.EventWaitHandle.Set()"
+ IL_00a6: pop
+ IL_00a7: endfinally
+ }
+ IL_00a8: ret
+ }
+ """);
}
[Fact]
@@ -3816,239 +3847,248 @@ static void Main()
CompileAndVerify(source, expectedOutput);
var comp = CreateRuntimeAsyncCompilation(source);
- comp.VerifyEmitDiagnostics(
- // (27,26): error CS9328: Method 'TestCase.Run(T)' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // arr[0, 0] += await GetVal(4);
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await GetVal(4)").WithArguments("TestCase.Run(T)").WithLocation(27, 26),
- // (32,26): error CS9328: Method 'TestCase.Run(T)' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // arr[1, 1] += await (GetVal(arr[0, 0]));
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await (GetVal(arr[0, 0]))").WithArguments("TestCase.Run(T)").WithLocation(32, 26),
- // (37,26): error CS9328: Method 'TestCase.Run(T)' uses a feature that is not supported by runtime async currently. Opt the method out of runtime async by attributing it with 'System.Runtime.CompilerServices.RuntimeAsyncMethodGenerationAttribute(false)'.
- // arr[1, 1] += await (GetVal(arr[0, await GetVal(0)]));
- Diagnostic(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync, "await (GetVal(arr[0, await GetVal(0)]))").WithArguments("TestCase.Run(T)").WithLocation(37, 26)
- );
- // https://github.com/dotnet/roslyn/issues/79763
- // var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
- // {
- // ILVerifyMessage = """
- // [GetVal]: Unexpected type on the stack. { Offset = 0xc, Found = value 'T', Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
- // [Run]: Return value missing on the stack. { Offset = 0x178 }
- // """
- // });
-
- // verifier.VerifyDiagnostics();
- // verifier.VerifyIL("TestCase.Run(T)", """
- // {
- // // Code size 377 (0x179)
- // .maxstack 5
- // .locals init (int V_0, //tests
- // int[,] V_1, //arr
- // int V_2,
- // int V_3,
- // int[,] V_4,
- // int V_5)
- // IL_0000: ldc.i4.0
- // IL_0001: stloc.0
- // .try
- // {
- // IL_0002: ldarg.0
- // IL_0003: ldc.i4.4
- // IL_0004: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0009: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_000e: ldarg.0
- // IL_000f: ldc.i4.4
- // IL_0010: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0015: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_001a: stloc.2
- // IL_001b: ldloc.2
- // IL_001c: newobj "int[*,*]..ctor"
- // IL_0021: stloc.1
- // IL_0022: ldloc.0
- // IL_0023: ldc.i4.1
- // IL_0024: add
- // IL_0025: stloc.0
- // IL_0026: ldloc.1
- // IL_0027: ldarg.0
- // IL_0028: ldc.i4.4
- // IL_0029: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_002e: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0033: stloc.2
- // IL_0034: ldc.i4.0
- // IL_0035: ldc.i4.0
- // IL_0036: ldloc.2
- // IL_0037: call "int[*,*].Set"
- // IL_003c: ldloc.1
- // IL_003d: ldarg.0
- // IL_003e: ldc.i4.0
- // IL_003f: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0044: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0049: stloc.2
- // IL_004a: ldc.i4.0
- // IL_004b: ldloc.2
- // IL_004c: call "int[*,*].Get"
- // IL_0051: ldc.i4.4
- // IL_0052: bne.un.s IL_0060
- // IL_0054: ldsfld "int Driver.Count"
- // IL_0059: ldc.i4.1
- // IL_005a: add
- // IL_005b: stsfld "int Driver.Count"
- // IL_0060: ldloc.0
- // IL_0061: ldc.i4.1
- // IL_0062: add
- // IL_0063: stloc.0
- // IL_0064: ldloc.1
- // IL_0065: ldc.i4.0
- // IL_0066: ldc.i4.0
- // IL_0067: call "int[*,*].Address"
- // IL_006c: dup
- // IL_006d: ldind.i4
- // IL_006e: stloc.2
- // IL_006f: ldarg.0
- // IL_0070: ldc.i4.4
- // IL_0071: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0076: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_007b: stloc.3
- // IL_007c: ldloc.2
- // IL_007d: ldloc.3
- // IL_007e: add
- // IL_007f: stind.i4
- // IL_0080: ldloc.1
- // IL_0081: ldc.i4.0
- // IL_0082: ldc.i4.0
- // IL_0083: call "int[*,*].Get"
- // IL_0088: ldc.i4.8
- // IL_0089: bne.un.s IL_0097
- // IL_008b: ldsfld "int Driver.Count"
- // IL_0090: ldc.i4.1
- // IL_0091: add
- // IL_0092: stsfld "int Driver.Count"
- // IL_0097: ldloc.0
- // IL_0098: ldc.i4.1
- // IL_0099: add
- // IL_009a: stloc.0
- // IL_009b: ldloc.1
- // IL_009c: ldc.i4.1
- // IL_009d: ldc.i4.1
- // IL_009e: call "int[*,*].Address"
- // IL_00a3: dup
- // IL_00a4: ldind.i4
- // IL_00a5: stloc.3
- // IL_00a6: ldarg.0
- // IL_00a7: ldloc.1
- // IL_00a8: ldc.i4.0
- // IL_00a9: ldc.i4.0
- // IL_00aa: call "int[*,*].Get"
- // IL_00af: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_00b4: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_00b9: stloc.2
- // IL_00ba: ldloc.3
- // IL_00bb: ldloc.2
- // IL_00bc: add
- // IL_00bd: stind.i4
- // IL_00be: ldloc.1
- // IL_00bf: ldc.i4.1
- // IL_00c0: ldc.i4.1
- // IL_00c1: call "int[*,*].Get"
- // IL_00c6: ldc.i4.8
- // IL_00c7: bne.un.s IL_00d5
- // IL_00c9: ldsfld "int Driver.Count"
- // IL_00ce: ldc.i4.1
- // IL_00cf: add
- // IL_00d0: stsfld "int Driver.Count"
- // IL_00d5: ldloc.0
- // IL_00d6: ldc.i4.1
- // IL_00d7: add
- // IL_00d8: stloc.0
- // IL_00d9: ldloc.1
- // IL_00da: ldc.i4.1
- // IL_00db: ldc.i4.1
- // IL_00dc: call "int[*,*].Address"
- // IL_00e1: dup
- // IL_00e2: ldind.i4
- // IL_00e3: stloc.2
- // IL_00e4: ldloc.1
- // IL_00e5: stloc.s V_4
- // IL_00e7: ldarg.0
- // IL_00e8: ldc.i4.0
- // IL_00e9: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_00ee: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_00f3: stloc.s V_5
- // IL_00f5: ldarg.0
- // IL_00f6: ldloc.s V_4
- // IL_00f8: ldc.i4.0
- // IL_00f9: ldloc.s V_5
- // IL_00fb: call "int[*,*].Get"
- // IL_0100: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0105: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_010a: stloc.3
- // IL_010b: ldloc.2
- // IL_010c: ldloc.3
- // IL_010d: add
- // IL_010e: stind.i4
- // IL_010f: ldloc.1
- // IL_0110: ldc.i4.1
- // IL_0111: ldc.i4.1
- // IL_0112: call "int[*,*].Get"
- // IL_0117: ldc.i4.s 16
- // IL_0119: bne.un.s IL_0127
- // IL_011b: ldsfld "int Driver.Count"
- // IL_0120: ldc.i4.1
- // IL_0121: add
- // IL_0122: stsfld "int Driver.Count"
- // IL_0127: ldloc.0
- // IL_0128: ldc.i4.1
- // IL_0129: add
- // IL_012a: stloc.0
- // IL_012b: ldloc.1
- // IL_012c: ldarg.0
- // IL_012d: ldc.i4.2
- // IL_012e: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
- // IL_0133: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
- // IL_0138: stloc.3
- // IL_0139: ldc.i4.2
- // IL_013a: ldloc.3
- // IL_013b: call "int[*,*].Address"
- // IL_0140: dup
- // IL_0141: ldind.i4
- // IL_0142: stloc.2
- // IL_0143: ldloc.2
- // IL_0144: ldc.i4.1
- // IL_0145: add
- // IL_0146: stind.i4
- // IL_0147: ldloc.1
- // IL_0148: ldc.i4.2
- // IL_0149: ldc.i4.2
- // IL_014a: call "int[*,*].Get"
- // IL_014f: ldc.i4.1
- // IL_0150: bne.un.s IL_015e
- // IL_0152: ldsfld "int Driver.Count"
- // IL_0157: ldc.i4.1
- // IL_0158: add
- // IL_0159: stsfld "int Driver.Count"
- // IL_015e: leave.s IL_0178
- // }
- // finally
- // {
- // IL_0160: ldsfld "int Driver.Count"
- // IL_0165: ldloc.0
- // IL_0166: sub
- // IL_0167: stsfld "int Driver.Result"
- // IL_016c: ldsfld "System.Threading.AutoResetEvent Driver.CompletedSignal"
- // IL_0171: callvirt "bool System.Threading.EventWaitHandle.Set()"
- // IL_0176: pop
- // IL_0177: endfinally
- // }
- // IL_0178: ret
- // }
- // """);
- }
+ var verifier = CompileAndVerify(comp, expectedOutput: CodeGenAsyncTests.ExpectedOutput(expectedOutput, isRuntimeAsync: true), verify: Verification.Fails with
+ {
+ ILVerifyMessage = """
+ [GetVal]: Unexpected type on the stack. { Offset = 0xc, Found = value 'T', Expected = ref '[System.Runtime]System.Threading.Tasks.Task`1' }
+ [Run]: Return value missing on the stack. { Offset = 0x1a5 }
+ """
+ });
- [Fact]
- public void SpillArray04()
- {
- var source = @"
-using System.Threading;
-using System.Threading.Tasks;
+ verifier.VerifyDiagnostics();
+ verifier.VerifyIL("TestCase.Run(T)", """
+ {
+ // Code size 422 (0x1a6)
+ .maxstack 5
+ .locals init (int V_0, //tests
+ int[,] V_1, //arr
+ int V_2,
+ int V_3,
+ int[,] V_4,
+ int V_5)
+ IL_0000: ldc.i4.0
+ IL_0001: stloc.0
+ .try
+ {
+ IL_0002: ldarg.0
+ IL_0003: ldc.i4.4
+ IL_0004: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
+ IL_0009: call "int System.Runtime.CompilerServices.AsyncHelpers.Await(System.Threading.Tasks.Task)"
+ IL_000e: ldarg.0
+ IL_000f: ldc.i4.4
+ IL_0010: call "System.Threading.Tasks.Task TestCase.GetVal(int)"
+ IL_0015: call "int System.Runtime.CompilerServices.AsyncHelpers.Await