diff --git a/Roslyn.sln b/Roslyn.sln
index 016b90b55746c..f1940655bbe97 100644
--- a/Roslyn.sln
+++ b/Roslyn.sln
@@ -500,6 +500,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.CSha
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.Remote.ServiceHub.UnitTests", "src\Workspaces\Remote\ServiceHubTest\Microsoft.CodeAnalysis.Remote.ServiceHub.UnitTests.csproj", "{8D830CBB-CA6E-47D8-9FB8-9230AAD272F3}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.LanguageServices.New.IntegrationTests", "src\VisualStudio\IntegrationTest\New.IntegrationTests\Microsoft.VisualStudio.LanguageServices.New.IntegrationTests.csproj", "{6272739B-31E4-483E-A3A5-2ABB5040ABF0}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Analyzers\VisualBasic\CodeFixes\VisualBasicCodeFixes.projitems*{0141285d-8f6c-42c7-baf3-3c0ccd61c716}*SharedItemsImports = 5
@@ -1235,10 +1237,10 @@ Global
{8D22FC91-BDFE-4342-999B-D695E1C57E85}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D22FC91-BDFE-4342-999B-D695E1C57E85}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D22FC91-BDFE-4342-999B-D695E1C57E85}.Release|Any CPU.Build.0 = Release|Any CPU
- {2801F82B-78CE-4BAE-B06F-537574751E2E}.Debug|Any CPU.ActiveCfg = Debug|x86
- {2801F82B-78CE-4BAE-B06F-537574751E2E}.Debug|Any CPU.Build.0 = Debug|x86
- {2801F82B-78CE-4BAE-B06F-537574751E2E}.Release|Any CPU.ActiveCfg = Release|x86
- {2801F82B-78CE-4BAE-B06F-537574751E2E}.Release|Any CPU.Build.0 = Release|x86
+ {2801F82B-78CE-4BAE-B06F-537574751E2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2801F82B-78CE-4BAE-B06F-537574751E2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2801F82B-78CE-4BAE-B06F-537574751E2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2801F82B-78CE-4BAE-B06F-537574751E2E}.Release|Any CPU.Build.0 = Release|Any CPU
{9B25E472-DF94-4E24-9F5D-E487CE5A91FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B25E472-DF94-4E24-9F5D-E487CE5A91FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B25E472-DF94-4E24-9F5D-E487CE5A91FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -1303,6 +1305,10 @@ Global
{8D830CBB-CA6E-47D8-9FB8-9230AAD272F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D830CBB-CA6E-47D8-9FB8-9230AAD272F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D830CBB-CA6E-47D8-9FB8-9230AAD272F3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6272739B-31E4-483E-A3A5-2ABB5040ABF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6272739B-31E4-483E-A3A5-2ABB5040ABF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6272739B-31E4-483E-A3A5-2ABB5040ABF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6272739B-31E4-483E-A3A5-2ABB5040ABF0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1531,6 +1537,7 @@ Global
{8FCD1B85-BE63-4A2F-8E19-37244F19BE0F} = {55A62CFA-1155-46F1-ADF3-BEEE51B58AB5}
{2B7DC612-1B37-41F7-BE31-4D600930EAC9} = {32A48625-F0AD-419D-828B-A50BDABA38EA}
{8D830CBB-CA6E-47D8-9FB8-9230AAD272F3} = {55A62CFA-1155-46F1-ADF3-BEEE51B58AB5}
+ {6272739B-31E4-483E-A3A5-2ABB5040ABF0} = {CC126D03-7EAC-493F-B187-DCDEE1EF6A70}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {604E6B91-7BC0-4126-AE07-D4D2FEFC3D29}
diff --git a/azure-pipelines-integration-corehost.yml b/azure-pipelines-integration-corehost.yml
index 8423888c6ed22..d34995411c3cc 100644
--- a/azure-pipelines-integration-corehost.yml
+++ b/azure-pipelines-integration-corehost.yml
@@ -18,11 +18,15 @@ pr:
- features/*
- demos/*
+variables:
+ - name: XUNIT_LOGS
+ value: $(Build.SourcesDirectory)\artifacts\log\$(_configuration)
+
jobs:
- job: VS_Integration_CoreHost
pool:
- name: NetCorePublic-Pool
- queue: $(queueName)
+ name: NetCore1ESPool-Public
+ demands: ImageOverride -equals $(queueName)
strategy:
maxParallel: 2
matrix:
diff --git a/azure-pipelines-integration-lsp.yml b/azure-pipelines-integration-lsp.yml
index 0270799d3b21d..85ba4c6ffbe37 100644
--- a/azure-pipelines-integration-lsp.yml
+++ b/azure-pipelines-integration-lsp.yml
@@ -18,11 +18,15 @@ pr:
- features/*
- demos/*
+variables:
+ - name: XUNIT_LOGS
+ value: $(Build.SourcesDirectory)\artifacts\log\$(_configuration)
+
jobs:
- job: VS_Integration_LSP
pool:
- name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -equals Build.Windows.Amd64.VS2022.Pre.Open
+ name: NetCore1ESPool-Public
+ demands: ImageOverride -equals $(queueName)
timeoutInMinutes: 135
steps:
diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml
index 251f8641c4feb..d47ecd4d8087a 100644
--- a/azure-pipelines-integration.yml
+++ b/azure-pipelines-integration.yml
@@ -14,11 +14,15 @@ pr:
- features/*
- demos/*
+variables:
+ - name: XUNIT_LOGS
+ value: $(Build.SourcesDirectory)\artifacts\log\$(_configuration)
+
jobs:
- job: VS_Integration
pool:
- name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -equals Build.Windows.Amd64.VS2022.Pre.Open
+ name: $(poolName)
+ demands: ImageOverride -equals $(queueName)
strategy:
maxParallel: 4
matrix:
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index 6572395e03a4c..aec790a57e107 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -82,7 +82,7 @@ stages:
displayName: Official Build
timeoutInMinutes: 360
pool:
- name: NetCore1ESPool-Svc-Internal
+ name: NetCore1ESPool-Internal
demands: ImageOverride -equals Build.Server.Amd64.VS2019
steps:
diff --git a/azure-pipelines-pr-validation.yml b/azure-pipelines-pr-validation.yml
index 494eceff5837c..720361ea86da7 100644
--- a/azure-pipelines-pr-validation.yml
+++ b/azure-pipelines-pr-validation.yml
@@ -49,7 +49,7 @@ stages:
timeoutInMinutes: 360
# Conditionally set build pool so we can share this YAML when building with different pipeline
pool:
- name: VSEngSS-MicroBuild2017
+ name: VSEngSS-MicroBuild2019-1ES
demands:
- msbuild
- visualstudio
@@ -89,6 +89,14 @@ stages:
inputs:
nuGetServiceConnections: azure-public/vs-impl, azure-public/vssdk
+ # Needed because the build fails the NuGet Tools restore without it
+ - task: UseDotNet@2
+ displayName: 'Use .NET Core sdk'
+ inputs:
+ packageType: sdk
+ useGlobalJson: true
+ workingDirectory: '$(Build.SourcesDirectory)'
+
# Needed to restore the Microsoft.DevDiv.Optimization.Data.PowerShell package
- task: NuGetCommand@2
displayName: Restore internal tools
@@ -210,7 +218,7 @@ stages:
displayName: Create Insertion
dependsOn:
- build
-
+
jobs:
- job: insert
displayName: Insert to VS
@@ -220,7 +228,7 @@ stages:
- powershell: Write-Host "##vso[task.setvariable variable=SourceBranchName]$('$(Build.SourceBranch)'.Substring('refs/heads/'.Length))"
displayName: Setting SourceBranchName variable
condition: succeeded()
-
+
- template: eng/pipelines/insert.yml
parameters:
createDraftPR: true
@@ -232,4 +240,4 @@ stages:
titlePrefix: ${{ parameters.OptionalTitlePrefix }}
sourceBranch: $(SourceBranchName)
publishDataURI: "https://raw.githubusercontent.com/dotnet/roslyn/main/eng/config/PublishData.json"
-
+
diff --git a/azure-pipelines-richnav.yml b/azure-pipelines-richnav.yml
index 4bf52240ca699..e68c88ad6c78e 100644
--- a/azure-pipelines-richnav.yml
+++ b/azure-pipelines-richnav.yml
@@ -19,8 +19,8 @@ pr: none
jobs:
- job: RichCodeNav_Indexing
pool:
- name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -equals Build.Windows.10.Amd64.Open
+ name: NetCore1ESPool-Public
+ demands: ImageOverride -equals Build.Windows.Amd64.VS2022.Pre.Open
variables:
EnableRichCodeNavigation: true
timeoutInMinutes: 200
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index d4db92b9a244b..14b3d3cb339aa 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -21,14 +21,14 @@ jobs:
jobName: Build_Windows_Debug
testArtifactName: Transport_Artifacts_Windows_Debug
configuration: Debug
- queueName: Build.Windows.10.Amd64.Open
+ queueName: Build.Windows.Amd64.VS2022.Pre.Open
- template: eng/pipelines/build-windows-job.yml
parameters:
jobName: Build_Windows_Release
testArtifactName: Transport_Artifacts_Windows_Release
configuration: Release
- queueName: Build.Windows.10.Amd64.Open
+ queueName: Build.Windows.Amd64.VS2022.Pre.Open
- template: eng/pipelines/test-windows-job.yml
parameters:
@@ -153,7 +153,7 @@ jobs:
- job: Correctness_Determinism
pool:
- name: NetCore1ESPool-Svc-Public
+ name: NetCore1ESPool-Public
demands: ImageOverride -equals Build.Windows.Amd64.VS2022.Pre.Open
timeoutInMinutes: 90
steps:
@@ -169,7 +169,7 @@ jobs:
- job: Correctness_Build
pool:
- name: NetCore1ESPool-Svc-Public
+ name: NetCore1ESPool-Public
demands: ImageOverride -equals Build.Windows.Amd64.VS2022.Pre.Open
timeoutInMinutes: 90
steps:
@@ -201,8 +201,8 @@ jobs:
- job: Correctness_Rebuild
pool:
- name: NetCore1ESPool-Svc-Public
- demands: ImageOverride -equals Build.Windows.10.Amd64.Open
+ name: NetCore1ESPool-Public
+ demands: ImageOverride -equals Build.Windows.Amd64.VS2022.Pre.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-windows-task.yml
diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 6.md b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 6.md
index 4dab166db115b..a530a0ab2d7dc 100644
--- a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 6.md
+++ b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 6.md
@@ -108,4 +108,3 @@ These are _function_type_conversions_.
}
}
```
-
diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
index 483e0973945c6..dd8a7a6b5b2af 100644
--- a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
+++ b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
@@ -34,3 +34,25 @@
public CustomHandler(int literalLength, int formattedCount, C c) {}
}
```
+
+
+3. In Visual Studio 17.1, `ref`/`ref readonly`/`in`/`out` are not allowed to be used on return/parameters of a method attributed with `UnmanagedCallersOnly`.
+https://github.com/dotnet/roslyn/issues/57025
+
+ ```cs
+ using System.Runtime.InteropServices;
+ [UnmanagedCallersOnly]
+ static ref int M1() => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+
+ [UnmanagedCallersOnly]
+ static ref readonly int M2() => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+
+ [UnmanagedCallersOnly]
+ static void M3(ref int o) => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+
+ [UnmanagedCallersOnly]
+ static void M4(in int o) => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+
+ [UnmanagedCallersOnly]
+ static void M5(out int o) => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+ ```
diff --git a/docs/features/pdb-compilation-options.md b/docs/features/pdb-compilation-options.md
index 9e6bd4dcf0985..29c62897cfa3c 100644
--- a/docs/features/pdb-compilation-options.md
+++ b/docs/features/pdb-compilation-options.md
@@ -133,7 +133,7 @@ foreach (var handle in metadataReader.GetCustomDebugInformation(EntityHandle.Mod
### Compiler Options custom debug information
-The remaining values will be stored as key value pairs in the pdb. The storage format will be UTF8 encoded key value pairs that are null terminated. Order is not guaranteed. Any values left out can be assumed to be the default for the type. Keys may be different for Visual Basic and CSharp. They are serialized to reflect the command line arguments representing the same values
+The remaining values will be stored as key value pairs in the pdb. The storage format will be UTF8 encoded key value pairs that are null terminated. Order is not guaranteed. Any values left out can be assumed to be the default for the type. Keys may be different for Visual Basic and C#. They are serialized to reflect the command line arguments representing the same values
Example:
@@ -141,7 +141,7 @@ Example:
## List of Compiler Flags
-#### CSharp Flags That Can Be Derived From PDB or Assembly
+#### C# Flags That Can Be Derived From PDB or Assembly
* baseaddress
* checksumalgorithm
@@ -171,7 +171,7 @@ Example:
* win32manifest
* win32res
-#### CSharp Flags Not Included
+#### C# Flags Not Included
* bugreport
* delaysign
@@ -255,11 +255,11 @@ Example:
* verbose
* warnaserror
-#### Shared Options for CSharp and Visual Basic
+#### Shared Options for C# and Visual Basic
| PDB Key | Format | Default | Description |
| ---------------------- | --------------------------------------- | --------- | ------------ |
-| language | `CSharp\|Visual Basic` | required | Language name. |
+| language | `C#\|Visual Basic` | required | Language name. |
| compiler-version | [SemVer2](https://semver.org/spec/v2.0.0.html) string | required | Full version with SHA |
| runtime-version | [SemVer2](https://semver.org/spec/v2.0.0.html) string | required | [runtime version](#runtime-version) |
| source-file-count | int32 | required | Count of files in the document table that are source files |
@@ -270,7 +270,7 @@ Example:
| output-kind | string | require | The value passed to `/target` |
| platform | string | require | The value passed to `/platform` |
-#### Options For CSharp
+#### Options For C\#
See [compiler options](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/listed-alphabetically) documentation
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 9ac64a192283c..73a54c1c90cb8 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -6,25 +6,25 @@
7e80445ee82adbf9a8e6ae601ac5e239d982afaa
-
+ https://github.com/dotnet/source-build
- a9515db097e05728fcc2169d074eae3c6a4580d0
+ 50f26e9983277650d82d193296b2ccc50683f6b6
-
+ https://github.com/dotnet/arcade
- 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5
+ fecf65bedcee9036b8ba9d8d7feef5413f294914
-
+ https://github.com/dotnet/roslyn
- c1d8c6f043bc80425c6828455eb57f8a404759c6
+ 4ba1d9d2984e212af9d6ebff95dedb8a3739c661
-
+ https://github.com/dotnet/arcade
- 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5
+ fecf65bedcee9036b8ba9d8d7feef5413f294914
diff --git a/eng/Versions.props b/eng/Versions.props
index 9b720af774648..1ed0f66147c21 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -23,7 +23,7 @@
- 4.0.0-5.21469.2
+ 4.1.0-1.21553.8
@@ -33,11 +33,11 @@
4.0.0-3.final16.10.230
- 17.0.391-preview-g5e248c9073
+ 17.0.4875.0.0-alpha1.19409.15.0.0-preview.1.20112.817.0.5133-g7b8c8bd49d
- 17.0.0-previews-4-31709-430
+ 17.0.31723.11216.5.013.0.1
- 2.8.21
+ 2.8.28
Y for the purposes of determining the best
// source type of a set of operators.
//
- // We perpetuate these fictions here.
+ // We perpetuate these fictions here, except when X or Y is not a valid
+ // type argument to `Nullable`.
- if (target.IsNullableType() && convertsTo.IsNonNullableValueType())
+ if (target.IsNullableType() && convertsTo.IsValidNullableTypeArgument())
{
convertsTo = MakeNullableType(convertsTo);
toConversion = EncompassingExplicitConversion(null, convertsTo, target, ref useSiteInfo);
}
- if ((object)source != null && source.IsNullableType() && convertsFrom.IsNonNullableValueType())
+ if ((object)source != null && source.IsNullableType() && convertsFrom.IsValidNullableTypeArgument())
{
convertsFrom = MakeNullableType(convertsFrom);
fromConversion = EncompassingExplicitConversion(null, convertsFrom, source, ref useSiteInfo);
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/UserDefinedImplicitConversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/UserDefinedImplicitConversions.cs
index 03b3cffe5c1b0..a1e447450d3af 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/UserDefinedImplicitConversions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/UserDefinedImplicitConversions.cs
@@ -304,9 +304,12 @@ void addCandidatesFromType(
// actually X-->Y? in source for the purposes of determining the best target
// type of an operator.
//
- // We perpetuate this fiction here.
+ // We perpetuate this fiction here, except for cases when Y is not a valid type
+ // argument for Nullable. This scenario should only be possible when the corlib
+ // defines a type such as int or long to be a ref struct (see
+ // LiftedConversion_InvalidTypeArgument02).
- if ((object)target != null && target.IsNullableType() && convertsTo.IsNonNullableValueType())
+ if ((object)target != null && target.IsNullableType() && convertsTo.IsValidNullableTypeArgument())
{
convertsTo = MakeNullableType(convertsTo);
toConversion = allowAnyTarget ? Conversion.Identity :
@@ -315,7 +318,7 @@ void addCandidatesFromType(
u.Add(UserDefinedConversionAnalysis.Normal(constrainedToTypeOpt, op, fromConversion, toConversion, convertsFrom, convertsTo));
}
- else if ((object)source != null && source.IsNullableType() && convertsFrom.IsNonNullableValueType() &&
+ else if ((object)source != null && source.IsNullableType() && convertsFrom.IsValidNullableTypeArgument() &&
(allowAnyTarget || target.CanBeAssignedNull()))
{
// As mentioned above, here we diverge from the specification, in two ways.
@@ -334,7 +337,7 @@ void addCandidatesFromType(
// If the answer to all those questions is "yes" then we lift to nullable
// and see if the resulting operator is applicable.
TypeSymbol nullableFrom = MakeNullableType(convertsFrom);
- TypeSymbol nullableTo = convertsTo.IsNonNullableValueType() ? MakeNullableType(convertsTo) : convertsTo;
+ TypeSymbol nullableTo = convertsTo.IsValidNullableTypeArgument() ? MakeNullableType(convertsTo) : convertsTo;
Conversion liftedFromConversion = EncompassingImplicitConversion(sourceExpression, source, nullableFrom, ref useSiteInfo);
Conversion liftedToConversion = !allowAnyTarget ?
EncompassingImplicitConversion(null, nullableTo, target, ref useSiteInfo) :
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorOverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorOverloadResolution.cs
index 77c94f0db82a2..82fe0fb80460a 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorOverloadResolution.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/BinaryOperatorOverloadResolution.cs
@@ -929,10 +929,8 @@ private static LiftingResult UserDefinedBinaryOperatorCanBeLifted(TypeSymbol lef
// SPEC: types and if the result type is bool. The lifted form is
// SPEC: constructed by adding a single ? modifier to each operand type.
- if (!left.IsValueType ||
- left.IsNullableType() ||
- !right.IsValueType ||
- right.IsNullableType())
+ if (!left.IsValidNullableTypeArgument() ||
+ !right.IsValidNullableTypeArgument())
{
return LiftingResult.NotLifted;
}
@@ -953,7 +951,7 @@ private static LiftingResult UserDefinedBinaryOperatorCanBeLifted(TypeSymbol lef
LiftingResult.LiftOperandsButNotResult :
LiftingResult.NotLifted;
default:
- return result.IsValueType && !result.IsNullableType() ?
+ return result.IsValidNullableTypeArgument() ?
LiftingResult.LiftOperandsAndResult :
LiftingResult.NotLifted;
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/UnaryOperatorOverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/UnaryOperatorOverloadResolution.cs
index 68f3de987afe9..d0078360916e2 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/UnaryOperatorOverloadResolution.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Operators/UnaryOperatorOverloadResolution.cs
@@ -500,8 +500,8 @@ private void GetUserDefinedUnaryOperatorsFromType(
case UnaryOperatorKind.PostfixIncrement:
case UnaryOperatorKind.LogicalNegation:
case UnaryOperatorKind.BitwiseComplement:
- if (operandType.IsValueType && !operandType.IsNullableType() &&
- resultType.IsValueType && !resultType.IsNullableType())
+ if (operandType.IsValidNullableTypeArgument() &&
+ resultType.IsValidNullableTypeArgument())
{
operators.Add(new UnaryOperatorSignature(
UnaryOperatorKind.Lifted | UnaryOperatorKind.UserDefined | kind,
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberResolutionResult.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberResolutionResult.cs
index 17960c0c15134..b719b9604f3ef 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberResolutionResult.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberResolutionResult.cs
@@ -22,7 +22,7 @@ namespace Microsoft.CodeAnalysis.CSharp
///
internal readonly bool HasTypeArgumentInferredFromFunctionType;
- internal MemberResolutionResult(TMember member, TMember leastOverriddenMember, MemberAnalysisResult result, bool hasTypeArgumentInferredFromFunctionType = false)
+ internal MemberResolutionResult(TMember member, TMember leastOverriddenMember, MemberAnalysisResult result, bool hasTypeArgumentInferredFromFunctionType)
{
_member = member;
_leastOverriddenMember = leastOverriddenMember;
@@ -30,6 +30,11 @@ internal MemberResolutionResult(TMember member, TMember leastOverriddenMember, M
HasTypeArgumentInferredFromFunctionType = hasTypeArgumentInferredFromFunctionType;
}
+ internal MemberResolutionResult WithResult(MemberAnalysisResult result)
+ {
+ return new MemberResolutionResult(Member, LeastOverriddenMember, result, HasTypeArgumentInferredFromFunctionType);
+ }
+
internal bool IsNull
{
get { return (object)_member == null; }
@@ -92,12 +97,12 @@ public bool IsApplicable
internal MemberResolutionResult Worse()
{
- return new MemberResolutionResult(Member, LeastOverriddenMember, MemberAnalysisResult.Worse());
+ return WithResult(MemberAnalysisResult.Worse());
}
internal MemberResolutionResult Worst()
{
- return new MemberResolutionResult(Member, LeastOverriddenMember, MemberAnalysisResult.Worst());
+ return WithResult(MemberAnalysisResult.Worst());
}
internal bool HasUseSiteDiagnosticToReport
diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
index fd6e17709465f..07965c314f1c3 100644
--- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs
@@ -385,7 +385,7 @@ private static void RemoveStaticInstanceMismatches(ArrayBuilder(member, result.LeastOverriddenMember, MemberAnalysisResult.StaticInstanceMismatch());
+ results[f] = result.WithResult(MemberAnalysisResult.StaticInstanceMismatch());
}
}
}
@@ -401,7 +401,7 @@ private static void RemoveMethodsNotDeclaredStatic(ArrayBuilder(member, result.LeastOverriddenMember, MemberAnalysisResult.StaticInstanceMismatch());
+ results[f] = result.WithResult(MemberAnalysisResult.StaticInstanceMismatch());
}
}
}
@@ -426,8 +426,7 @@ private void RemoveConstraintViolations(ArrayBuilder constraintFailureDiagnosticsOpt, template))
{
- results[f] = new MemberResolutionResult(
- result.Member, result.LeastOverriddenMember,
+ results[f] = result.WithResult(
MemberAnalysisResult.ConstraintFailure(constraintFailureDiagnosticsOpt.ToImmutableAndFree()));
}
}
@@ -559,7 +558,7 @@ private void RemoveCallingConventionMismatches(ArrayBuilder makeWrongCallingConvention(MemberResolutionResult result)
- => new MemberResolutionResult(result.Member, result.LeastOverriddenMember, MemberAnalysisResult.WrongCallingConvention());
+ => result.WithResult(MemberAnalysisResult.WrongCallingConvention());
}
#nullable disable
@@ -649,13 +648,11 @@ private void RemoveDelegateConversionsWithWrongReturnType(
if (!returnsMatch)
{
- results[f] = new MemberResolutionResult(
- result.Member, result.LeastOverriddenMember, MemberAnalysisResult.WrongReturnType());
+ results[f] = result.WithResult(MemberAnalysisResult.WrongReturnType());
}
else if (method.RefKind != returnRefKind)
{
- results[f] = new MemberResolutionResult(
- result.Member, result.LeastOverriddenMember, MemberAnalysisResult.WrongRefKind());
+ results[f] = result.WithResult(MemberAnalysisResult.WrongRefKind());
}
}
}
@@ -699,7 +696,7 @@ private void AddConstructorToCandidateSet(MethodSymbol constructor, ArrayBuilder
Debug.Assert(!MemberAnalysisResult.UnsupportedMetadata().HasUseSiteDiagnosticToReportFor(constructor));
if (completeResults)
{
- results.Add(new MemberResolutionResult(constructor, constructor, MemberAnalysisResult.UnsupportedMetadata()));
+ results.Add(new MemberResolutionResult(constructor, constructor, MemberAnalysisResult.UnsupportedMetadata(), hasTypeArgumentInferredFromFunctionType: false));
}
return;
}
@@ -721,7 +718,7 @@ private void AddConstructorToCandidateSet(MethodSymbol constructor, ArrayBuilder
// If the constructor has a use site diagnostic, we don't want to discard it because we'll have to report the diagnostic later.
if (result.IsValid || completeResults || result.HasUseSiteDiagnosticToReportFor(constructor))
{
- results.Add(new MemberResolutionResult(constructor, constructor, result));
+ results.Add(new MemberResolutionResult(constructor, constructor, result, hasTypeArgumentInferredFromFunctionType: false));
}
}
@@ -905,7 +902,7 @@ private void AddMemberToCandidateSet(
Debug.Assert(!MemberAnalysisResult.UnsupportedMetadata().HasUseSiteDiagnosticToReportFor(member));
if (completeResults)
{
- results.Add(new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.UnsupportedMetadata()));
+ results.Add(new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.UnsupportedMetadata(), hasTypeArgumentInferredFromFunctionType: false));
}
return;
}
@@ -1141,7 +1138,7 @@ private void RemoveInaccessibleTypeArguments(ArrayBuilder(result.Member, result.LeastOverriddenMember, MemberAnalysisResult.InaccessibleTypeArgument());
+ results[f] = result.WithResult(MemberAnalysisResult.InaccessibleTypeArgument());
}
}
}
@@ -1272,7 +1269,7 @@ private static void RemoveLessDerivedMembers(ArrayBuilder(result.Member, result.LeastOverriddenMember, MemberAnalysisResult.LessDerived());
+ results[f] = result.WithResult(MemberAnalysisResult.LessDerived());
}
}
}
@@ -1383,7 +1380,7 @@ private static void RemoveAllInterfaceMembers(ArrayBuilder(member, result.LeastOverriddenMember, MemberAnalysisResult.LessDerived());
+ results[f] = result.WithResult(MemberAnalysisResult.LessDerived());
}
}
}
@@ -3284,7 +3281,7 @@ private MemberResolutionResult IsMemberApplicableInNormalForm(
// thus improving the API and intellisense experience.
break;
default:
- return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis));
+ return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis), hasTypeArgumentInferredFromFunctionType: false);
}
}
@@ -3292,7 +3289,7 @@ private MemberResolutionResult IsMemberApplicableInNormalForm(
// NOTE: The diagnostic may not be reported (e.g. if the member is later removed as less-derived).
if (member.HasUseSiteError)
{
- return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.UseSiteError());
+ return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.UseSiteError(), hasTypeArgumentInferredFromFunctionType: false);
}
bool hasAnyRefOmittedArgument;
@@ -3334,7 +3331,7 @@ private MemberResolutionResult IsMemberApplicableInNormalForm(
// type inference and lambda binding. In that case we still need to return the argument mismatch failure here.
if (completeResults && !argumentAnalysis.IsValid)
{
- return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis));
+ return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis), hasTypeArgumentInferredFromFunctionType: false);
}
return applicableResult;
@@ -3355,14 +3352,14 @@ private MemberResolutionResult IsMemberApplicableInExpandedForm(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis));
+ return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis), hasTypeArgumentInferredFromFunctionType: false);
}
// Check after argument analysis, but before more complicated type inference and argument type validation.
// NOTE: The diagnostic may not be reported (e.g. if the member is later removed as less-derived).
if (member.HasUseSiteError)
{
- return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.UseSiteError());
+ return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.UseSiteError(), hasTypeArgumentInferredFromFunctionType: false);
}
bool hasAnyRefOmittedArgument;
@@ -3401,9 +3398,7 @@ private MemberResolutionResult IsMemberApplicableInExpandedForm(
- result.Member,
- result.LeastOverriddenMember,
+ result.WithResult(
MemberAnalysisResult.ExpandedForm(result.Result.ArgsToParamsOpt, result.Result.ConversionsOpt, hasAnyRefOmittedArgument)) :
result;
}
@@ -3465,7 +3460,7 @@ private MemberResolutionResult IsApplicable(
ref useSiteInfo);
if (typeArguments.IsDefault)
{
- return new MemberResolutionResult(member, leastOverriddenMember, inferenceError);
+ return new MemberResolutionResult(member, leastOverriddenMember, inferenceError, hasTypeArgumentInferredFromFunctionType: false);
}
}
@@ -3505,7 +3500,7 @@ private MemberResolutionResult IsApplicable(
{
if (!parameterTypes[i].Type.CheckAllConstraints(Compilation, Conversions))
{
- return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.ConstructedParameterFailedConstraintsCheck(i));
+ return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.ConstructedParameterFailedConstraintsCheck(i), hasTypeArgumentsInferredFromFunctionType);
}
}
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index afbf2313b0fb9..a3e6707d02dbf 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -6902,10 +6902,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
The operation may overflow at runtime (use 'unchecked' syntax to override)
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
newlines in interpolationsInterpolated string handler conversions that reference the instance being indexed cannot be used in indexer member initializers.
+
+ '{0}' cannot be made nullable.
+
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index b992330d3f9f5..e4ee33961c90b 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -2003,6 +2003,10 @@ internal enum ErrorCode
ERR_LambdaExplicitReturnTypeVar = 8975,
ERR_InterpolatedStringsReferencingInstanceCannotBeInObjectInitializers = 8976,
+ // Added in VS 17.1. Technically a breaking change, but the code it breaks was already guaranteed to throw
+ // at runtime.
+ ERR_CannotUseRefInUnmanagedCallersOnly = 8977,
+
ERR_IncorrectNullCheckSyntax = 8990,
ERR_MustNullCheckInImplementation = 8991,
ERR_NonNullableValueTypeIsNullChecked = 8992,
@@ -2012,6 +2016,8 @@ internal enum ErrorCode
#endregion
+ ERR_CannotBeMadeNullable = 8978,
+
// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)
}
}
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.PendingBranchesCollection.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.PendingBranchesCollection.cs
new file mode 100644
index 0000000000000..0dbdec0318d9b
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.PendingBranchesCollection.cs
@@ -0,0 +1,153 @@
+// 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.Collections.Generic;
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Microsoft.CodeAnalysis.PooledObjects;
+
+namespace Microsoft.CodeAnalysis.CSharp
+{
+ internal partial class AbstractFlowPass
+ {
+ internal sealed class PendingBranchesCollection
+ {
+ private ArrayBuilder _unlabeledBranches;
+ private PooledDictionary>? _labeledBranches;
+
+ internal PendingBranchesCollection()
+ {
+ _unlabeledBranches = ArrayBuilder.GetInstance();
+ }
+
+ internal void Free()
+ {
+ _unlabeledBranches.Free();
+ _unlabeledBranches = null!;
+ FreeLabeledBranches();
+ }
+
+ internal void Clear()
+ {
+ _unlabeledBranches.Clear();
+ FreeLabeledBranches();
+ }
+
+ private void FreeLabeledBranches()
+ {
+ if (_labeledBranches is { })
+ {
+ foreach (var branches in _labeledBranches.Values)
+ {
+ branches.Free();
+ }
+ _labeledBranches.Free();
+ _labeledBranches = null;
+ }
+ }
+
+ ///
+ /// Returns the unordered collection of branches.
+ ///
+ internal ImmutableArray ToImmutable()
+ {
+ return _labeledBranches is null ?
+ _unlabeledBranches.ToImmutable() :
+ ImmutableArray.CreateRange(AsEnumerable());
+ }
+
+ internal ArrayBuilder? GetAndRemoveBranches(LabelSymbol? label)
+ {
+ ArrayBuilder? result;
+ if (label is null)
+ {
+ if (_unlabeledBranches.Count == 0)
+ {
+ result = null;
+ }
+ else
+ {
+ result = _unlabeledBranches;
+ _unlabeledBranches = ArrayBuilder.GetInstance();
+ }
+ }
+ else if (_labeledBranches is { } && _labeledBranches.TryGetValue(label, out result))
+ {
+ _labeledBranches.Remove(label);
+ }
+ else
+ {
+ result = null;
+ }
+ return result;
+ }
+
+ internal void Add(PendingBranch branch)
+ {
+ var label = branch.Label;
+ if (label is null)
+ {
+ _unlabeledBranches.Add(branch);
+ }
+ else
+ {
+ var branches = GetOrAddLabeledBranches(label);
+ branches.Add(branch);
+ }
+ }
+
+ internal void AddRange(PendingBranchesCollection collection)
+ {
+ _unlabeledBranches.AddRange(collection._unlabeledBranches);
+ if (collection._labeledBranches is { })
+ {
+ foreach (var pair in collection._labeledBranches)
+ {
+ var branches = GetOrAddLabeledBranches(pair.Key);
+ branches.AddRange(pair.Value);
+ }
+ }
+ }
+
+ private ArrayBuilder GetOrAddLabeledBranches(LabelSymbol label)
+ {
+ if (_labeledBranches is null)
+ {
+ _labeledBranches = PooledDictionary>.GetInstance();
+ }
+ if (!_labeledBranches.TryGetValue(label, out var branches))
+ {
+ branches = ArrayBuilder.GetInstance();
+ _labeledBranches.Add(label, branches);
+ }
+ return branches;
+ }
+
+ ///
+ /// Returns the unordered collection of branches.
+ ///
+ internal IEnumerable AsEnumerable()
+ {
+ return _labeledBranches is null ?
+ _unlabeledBranches :
+ asEnumerableCore();
+
+ IEnumerable asEnumerableCore()
+ {
+ foreach (var branch in _unlabeledBranches)
+ {
+ yield return branch;
+ }
+ foreach (var branches in _labeledBranches.Values)
+ {
+ foreach (var branch in branches)
+ {
+ yield return branch;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs
index 3f839eec29016..57bce8634b8b2 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs
@@ -99,7 +99,7 @@ internal abstract partial class AbstractFlowPass
- protected ArrayBuilder PendingBranches { get; private set; }
+ protected PendingBranchesCollection PendingBranches { get; private set; }
///
/// The definite assignment and/or reachability state at the point currently being analyzed.
@@ -205,7 +205,7 @@ protected AbstractFlowPass(
this.RegionSpan = new TextSpan(startLocation, length);
}
- PendingBranches = ArrayBuilder.GetInstance();
+ PendingBranches = new PendingBranchesCollection();
_labelsSeen = PooledHashSet.GetInstance();
_labels = PooledDictionary.GetInstance();
this.Diagnostics = DiagnosticBag.GetInstance();
@@ -390,14 +390,16 @@ protected override bool ConvertInsufficientExecutionStackExceptionToCancelledByS
/// pending branches to a label in that block we process the branch. Otherwise we relay it
/// up to the enclosing construct as a pending branch of the enclosing construct.
///
- internal class PendingBranch
+ internal sealed class PendingBranch
{
public readonly BoundNode Branch;
public bool IsConditionalState;
public TLocalState State;
public TLocalState StateWhenTrue;
public TLocalState StateWhenFalse;
- public readonly LabelSymbol Label;
+#nullable enable
+ public readonly LabelSymbol? Label;
+#nullable disable
public PendingBranch(BoundNode branch, TLocalState state, LabelSymbol label, bool isConditionalState = false, TLocalState stateWhenTrue = default, TLocalState stateWhenFalse = default)
{
@@ -708,38 +710,14 @@ private void LoopTail(BoundLoopStatement node)
}
}
+#nullable enable
///
/// Used to resolve break statements in each statement form that has a break statement
/// (loops, switch).
///
private void ResolveBreaks(TLocalState breakState, LabelSymbol label)
{
- var pendingBranches = PendingBranches;
- var count = pendingBranches.Count;
-
- if (count != 0)
- {
- int stillPending = 0;
- for (int i = 0; i < count; i++)
- {
- var pending = pendingBranches[i];
- if (pending.Label == label)
- {
- Join(ref breakState, ref pending.State);
- }
- else
- {
- if (stillPending != i)
- {
- pendingBranches[stillPending] = pending;
- }
- stillPending++;
- }
- }
-
- pendingBranches.Clip(stillPending);
- }
-
+ JoinPendingBranches(ref breakState, label);
SetState(breakState);
}
@@ -748,38 +726,27 @@ private void ResolveBreaks(TLocalState breakState, LabelSymbol label)
///
private void ResolveContinues(LabelSymbol continueLabel)
{
- var pendingBranches = PendingBranches;
- var count = pendingBranches.Count;
+ // Technically, nothing in the language specification depends on the state
+ // at the continue label, so we could just discard them instead of merging
+ // the states. In fact, we need not have added continue statements to the
+ // pending jump queue in the first place if we were interested solely in the
+ // flow analysis. However, region analysis (in support of extract method)
+ // and other forms of more precise analysis
+ // depend on continue statements appearing in the pending branch queue, so
+ // we process them from the queue here.
+ JoinPendingBranches(ref this.State, continueLabel);
+ }
- if (count != 0)
+ private void JoinPendingBranches(ref TLocalState state, LabelSymbol label)
+ {
+ var pendingBranches = PendingBranches.GetAndRemoveBranches(label);
+ if (pendingBranches is { })
{
- int stillPending = 0;
- for (int i = 0; i < count; i++)
+ foreach (var pending in pendingBranches)
{
- var pending = pendingBranches[i];
- if (pending.Label == continueLabel)
- {
- // Technically, nothing in the language specification depends on the state
- // at the continue label, so we could just discard them instead of merging
- // the states. In fact, we need not have added continue statements to the
- // pending jump queue in the first place if we were interested solely in the
- // flow analysis. However, region analysis (in support of extract method)
- // and other forms of more precise analysis
- // depend on continue statements appearing in the pending branch queue, so
- // we process them from the queue here.
- Join(ref this.State, ref pending.State);
- }
- else
- {
- if (stillPending != i)
- {
- pendingBranches[stillPending] = pending;
- }
- stillPending++;
- }
+ Join(ref state, ref pending.State);
}
-
- pendingBranches.Clip(stillPending);
+ pendingBranches.Free();
}
}
@@ -798,41 +765,26 @@ protected virtual void NoteBranch(PendingBranch pending, BoundNode gotoStmt, Bou
///
/// Target label
/// Statement containing the target label
- private bool ResolveBranches(LabelSymbol label, BoundStatement target)
+ private bool ResolveBranches(LabelSymbol label, BoundStatement? target)
{
target?.AssertIsLabeledStatementWithLabel(label);
bool labelStateChanged = false;
- var pendingBranches = PendingBranches;
- var count = pendingBranches.Count;
- if (count != 0)
+ var pendingBranches = PendingBranches.GetAndRemoveBranches(label);
+ if (pendingBranches is { })
{
- int stillPending = 0;
- for (int i = 0; i < count; i++)
+ foreach (var pending in pendingBranches)
{
- var pending = pendingBranches[i];
- if (pending.Label == label)
- {
- ResolveBranch(pending, label, target, ref labelStateChanged);
- }
- else
- {
- if (stillPending != i)
- {
- pendingBranches[stillPending] = pending;
- }
- stillPending++;
- }
+ ResolveBranch(pending, label, target, ref labelStateChanged);
}
-
- pendingBranches.Clip(stillPending);
+ pendingBranches.Free();
}
return labelStateChanged;
}
- protected virtual void ResolveBranch(PendingBranch pending, LabelSymbol label, BoundStatement target, ref bool labelStateChanged)
+ protected virtual void ResolveBranch(PendingBranch pending, LabelSymbol label, BoundStatement? target, ref bool labelStateChanged)
{
var state = LabelState(label);
if (target != null)
@@ -848,12 +800,12 @@ protected virtual void ResolveBranch(PendingBranch pending, LabelSymbol label, B
}
}
- protected struct SavedPending
+ protected readonly struct SavedPending
{
- public readonly ArrayBuilder PendingBranches;
+ public readonly PendingBranchesCollection PendingBranches;
public readonly PooledHashSet LabelsSeen;
- public SavedPending(ArrayBuilder pendingBranches, PooledHashSet labelsSeen)
+ public SavedPending(PendingBranchesCollection pendingBranches, PooledHashSet labelsSeen)
{
this.PendingBranches = pendingBranches;
this.LabelsSeen = labelsSeen;
@@ -870,7 +822,7 @@ protected SavedPending SavePending()
Debug.Assert(!this.IsConditionalState);
var result = new SavedPending(PendingBranches, _labelsSeen);
- PendingBranches = ArrayBuilder.GetInstance();
+ PendingBranches = new PendingBranchesCollection();
_labelsSeen = PooledHashSet.GetInstance();
return result;
@@ -927,6 +879,7 @@ protected void RestorePending(SavedPending oldPending)
_labelsSeen.Free();
_labelsSeen = oldPending.LabelsSeen;
}
+#nullable disable
#region visitors
@@ -1541,7 +1494,6 @@ public override BoundNode VisitBadStatement(BoundBadStatement node)
return null;
}
- // Can be called as part of a bad expression.
public override BoundNode VisitArrayInitialization(BoundArrayInitialization node)
{
foreach (var child in node.Initializers)
@@ -1727,7 +1679,7 @@ public override BoundNode VisitTryStatement(BoundTryStatement node)
var tryAndCatchPending = SavePending();
var stateMovedUpInFinally = ReachableBottomState();
VisitFinallyBlockWithAnyTransferFunction(node.FinallyBlockOpt, ref stateMovedUpInFinally);
- foreach (var pend in tryAndCatchPending.PendingBranches)
+ foreach (var pend in tryAndCatchPending.PendingBranches.AsEnumerable())
{
if (pend.Branch == null)
{
@@ -2648,29 +2600,10 @@ public override BoundNode VisitArrayCreation(BoundArrayCreation node)
VisitRvalue(expr);
}
- if (node.InitializerOpt != null)
- {
- VisitArrayInitializationInternal(node, node.InitializerOpt);
- }
-
+ VisitRvalue(node.InitializerOpt);
return null;
}
- private void VisitArrayInitializationInternal(BoundArrayCreation arrayCreation, BoundArrayInitialization node)
- {
- foreach (var child in node.Initializers)
- {
- if (child.Kind == BoundKind.ArrayInitialization)
- {
- VisitArrayInitializationInternal(arrayCreation, (BoundArrayInitialization)child);
- }
- else
- {
- VisitRvalue(child);
- }
- }
- }
-
public override BoundNode VisitForStatement(BoundForStatement node)
{
if (node.Initializer != null)
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/AlwaysAssignedWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/AlwaysAssignedWalker.cs
index c29551afe1292..3056295f7c01b 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/AlwaysAssignedWalker.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/AlwaysAssignedWalker.cs
@@ -126,7 +126,7 @@ protected override void LeaveRegion()
_endOfRegionState = this.State.Clone();
}
- foreach (var branch in base.PendingBranches)
+ foreach (var branch in PendingBranches.AsEnumerable())
{
if (branch.Branch != null && RegionContains(branch.Branch.Syntax.Span) && !_labelsInside.Contains(branch.Label))
{
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/ControlFlowAnalysis.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/ControlFlowAnalysis.cs
index a467bdf6efbc9..c937819fae8bb 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/ControlFlowAnalysis.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/ControlFlowAnalysis.cs
@@ -61,7 +61,7 @@ public override ImmutableArray ExitPoints
if (_exitPoints == null)
{
var result = Succeeded
- ? ((IEnumerable)ExitPointsWalker.Analyze(_context.Compilation, _context.Member, _context.BoundNode, _context.FirstInRegion, _context.LastInRegion)).ToImmutableArray()
+ ? ImmutableArray.CastUp(ExitPointsWalker.Analyze(_context.Compilation, _context.Member, _context.BoundNode, _context.FirstInRegion, _context.LastInRegion))
: ImmutableArray.Empty;
ImmutableInterlocked.InterlockedInitialize(ref _exitPoints, result);
}
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/ControlFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/ControlFlowPass.cs
index 1a1c503bef253..7ff832f2f54f3 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/ControlFlowPass.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/ControlFlowPass.cs
@@ -294,7 +294,7 @@ protected override void VisitFinallyBlock(BoundStatement finallyBlock, ref Local
var oldPending2 = SavePending(); // track only the branches out of the finally block
base.VisitFinallyBlock(finallyBlock, ref endState);
RestorePending(oldPending2); // resolve branches that remain within the finally block
- foreach (var branch in PendingBranches)
+ foreach (var branch in PendingBranches.AsEnumerable())
{
if (branch.Branch == null) continue; // a tracked exception
var location = new SourceLocation(branch.Branch.Syntax.GetFirstToken());
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/ExitPointsWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/ExitPointsWalker.cs
index ef51ef436b2db..c70043503a082 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/ExitPointsWalker.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/ExitPointsWalker.cs
@@ -4,13 +4,10 @@
#nullable disable
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
+using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.PooledObjects;
-using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
@@ -21,7 +18,7 @@ namespace Microsoft.CodeAnalysis.CSharp
internal class ExitPointsWalker : AbstractRegionControlFlowPass
{
private readonly ArrayBuilder _labelsInside;
- private ArrayBuilder _branchesOutOf;
+ private readonly ArrayBuilder _branchesOutOf;
private ExitPointsWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
: base(compilation, member, node, firstInRegion, lastInRegion)
@@ -41,16 +38,12 @@ protected override void Free()
base.Free();
}
- internal static IEnumerable Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
+ internal static ImmutableArray Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
{
var walker = new ExitPointsWalker(compilation, member, node, firstInRegion, lastInRegion);
try
{
- bool badRegion = false;
- walker.Analyze(ref badRegion);
- var result = walker._branchesOutOf.ToImmutableAndFree();
- walker._branchesOutOf = null;
- return badRegion ? SpecializedCollections.EmptyEnumerable() : result;
+ return walker.Analyze();
}
finally
{
@@ -58,10 +51,20 @@ internal static IEnumerable Analyze(CSharpCompilation compilati
}
}
- private void Analyze(ref bool badRegion)
+ private ImmutableArray Analyze()
{
+ bool badRegion = false;
+
// only one pass is needed.
Scan(ref badRegion);
+
+ if (badRegion)
+ {
+ return ImmutableArray.Empty;
+ }
+
+ _branchesOutOf.Sort((x, y) => x.SpanStart - y.SpanStart);
+ return _branchesOutOf.ToImmutable();
}
public override BoundNode VisitLabelStatement(BoundLabelStatement node)
@@ -116,7 +119,7 @@ protected override void EnterRegion()
protected override void LeaveRegion()
{
- foreach (var pending in PendingBranches)
+ foreach (var pending in PendingBranches.AsEnumerable())
{
if (pending.Branch == null || !RegionContains(pending.Branch.Syntax.Span)) continue;
switch (pending.Branch.Kind)
diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs
index bc26b7b69c766..c3045f7fd410f 100644
--- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs
@@ -699,10 +699,12 @@ public override BoundNode VisitArrayAccess(BoundArrayAccess node)
VisitExpression(node.Expression),
out BoundAssignmentOperator arrayAssign);
+ BoundExpression makeOffsetInput = DetermineMakePatternIndexOffsetExpressionStrategy(node.Indices[0], out PatternIndexOffsetLoweringStrategy strategy);
+
var indexOffsetExpr = MakePatternIndexOffsetExpression(
- node.Indices[0],
+ makeOffsetInput,
F.ArrayLength(arrayLocal),
- out _);
+ strategy);
resultExpr = F.Sequence(
ImmutableArray.Create(arrayLocal.LocalSymbol),
diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs
index 4b6bc86dd17e2..8bf9121b538ec 100644
--- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs
@@ -1052,7 +1052,7 @@ private BoundExpression RewriteUserDefinedConversion(
private BoundExpression MakeLiftedUserDefinedConversionConsequence(BoundCall call, TypeSymbol resultType)
{
- if (call.Method.ReturnType.IsNonNullableValueType())
+ if (call.Method.ReturnType.IsValidNullableTypeArgument())
{
Debug.Assert(resultType.IsNullableType() && TypeSymbol.Equals(resultType.GetNullableUnderlyingType(), call.Method.ReturnType, TypeCompareKind.ConsiderEverything2));
MethodSymbol ctor = UnsafeGetNullableMethod(call.Syntax, resultType, SpecialMember.System_Nullable_T__ctor);
diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs
index 796d87af34465..273b03a19c035 100644
--- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs
+++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs
@@ -208,17 +208,50 @@ private BoundSequence VisitIndexPatternIndexerAccess(
{
var F = _factory;
+ var locals = ArrayBuilder.GetInstance(2);
+ var sideeffects = ArrayBuilder.GetInstance(2);
+
Debug.Assert(receiver.Type is { });
var receiverLocal = F.StoreToTemp(
VisitExpression(receiver),
out var receiverStore,
// Store the receiver as a ref local if it's a value type to ensure side effects are propagated
receiver.Type.IsReferenceType ? RefKind.None : RefKind.Ref);
- var indexAccess = MakePatternIndexOffsetExpression(argument, F.Property(receiverLocal, lengthOrCountProperty), out _);
+ locals.Add(receiverLocal.LocalSymbol);
+ sideeffects.Add(receiverStore);
+
+ BoundExpression makeOffsetInput = DetermineMakePatternIndexOffsetExpressionStrategy(argument, out PatternIndexOffsetLoweringStrategy strategy);
+ BoundExpression indexAccess;
+
+ switch (strategy)
+ {
+ case PatternIndexOffsetLoweringStrategy.SubtractFromLength:
+ // ensure we evaluate the input before accessing length
+ if (makeOffsetInput.ConstantValue is null)
+ {
+ makeOffsetInput = F.StoreToTemp(makeOffsetInput, out BoundAssignmentOperator inputStore);
+ locals.Add(((BoundLocal)makeOffsetInput).LocalSymbol);
+ sideeffects.Add(inputStore);
+ }
+
+ indexAccess = MakePatternIndexOffsetExpression(makeOffsetInput, F.Property(receiverLocal, lengthOrCountProperty), strategy);
+ break;
+
+ case PatternIndexOffsetLoweringStrategy.UseAsIs:
+ indexAccess = MakePatternIndexOffsetExpression(makeOffsetInput, lengthAccess: null, strategy);
+ break;
+
+ case PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI:
+ indexAccess = MakePatternIndexOffsetExpression(makeOffsetInput, F.Property(receiverLocal, lengthOrCountProperty), strategy);
+ break;
+
+ default:
+ throw ExceptionUtilities.UnexpectedValue(strategy);
+ }
return (BoundSequence)F.Sequence(
- ImmutableArray.Create(receiverLocal.LocalSymbol),
- ImmutableArray.Create(receiverStore),
+ locals.ToImmutableAndFree(),
+ sideeffects.ToImmutableAndFree(),
MakeIndexerAccess(
syntax,
receiverLocal,
@@ -235,55 +268,108 @@ private BoundSequence VisitIndexPatternIndexerAccess(
}
///
- /// Used to construct a pattern index offset expression, of the form
- /// `unloweredExpr.GetOffset(lengthAccess)`
- /// where unloweredExpr is an expression of type System.Index and the
- /// lengthAccess retrieves the length of the indexing target.
+ /// Used to produce an expression translating to an integer offset
+ /// according to the .
+ /// The implementation should be in sync with .
///
- /// The unlowered argument to the indexing expression
+ /// The lowered input for the translation
///
/// An expression accessing the length of the indexing target. This should
/// be a non-side-effecting operation.
///
- ///
- /// True if we were able to optimize the
- /// to use the operation directly on the receiver, instead of
- /// using System.Index helpers.
- ///
+ /// The translation strategy
private BoundExpression MakePatternIndexOffsetExpression(
+ BoundExpression? loweredExpr,
+ BoundExpression? lengthAccess,
+ PatternIndexOffsetLoweringStrategy strategy)
+ {
+ switch (strategy)
+ {
+ case PatternIndexOffsetLoweringStrategy.Zero:
+ return _factory.Literal(0);
+
+ case PatternIndexOffsetLoweringStrategy.Length:
+ Debug.Assert(lengthAccess is not null);
+ return lengthAccess;
+
+ case PatternIndexOffsetLoweringStrategy.SubtractFromLength:
+ Debug.Assert(loweredExpr is not null);
+ Debug.Assert(lengthAccess is not null);
+ Debug.Assert(loweredExpr.Type!.SpecialType == SpecialType.System_Int32);
+
+ if (loweredExpr.ConstantValue?.Int32Value == 0)
+ {
+ return lengthAccess;
+ }
+
+ return _factory.IntSubtract(lengthAccess, loweredExpr);
+
+ case PatternIndexOffsetLoweringStrategy.UseAsIs:
+ Debug.Assert(loweredExpr is not null);
+ Debug.Assert(loweredExpr.Type!.SpecialType == SpecialType.System_Int32);
+ return loweredExpr;
+
+ case PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI:
+ Debug.Assert(loweredExpr is not null);
+ Debug.Assert(lengthAccess is not null);
+ Debug.Assert(TypeSymbol.Equals(
+ loweredExpr.Type,
+ _compilation.GetWellKnownType(WellKnownType.System_Index),
+ TypeCompareKind.ConsiderEverything));
+
+ return _factory.Call(
+ loweredExpr,
+ WellKnownMember.System_Index__GetOffset,
+ lengthAccess);
+
+ default:
+ throw ExceptionUtilities.UnexpectedValue(strategy);
+ }
+ }
+
+ private enum PatternIndexOffsetLoweringStrategy
+ {
+ Zero,
+ Length,
+ SubtractFromLength,
+ UseAsIs,
+ UseGetOffsetAPI
+ }
+
+ ///
+ /// Determine the lowering strategy for translating a System.Index value to an integer offset value
+ /// and prepare the lowered input for the translation process handled by .
+ /// The implementation should be in sync with .
+ ///
+ private BoundExpression DetermineMakePatternIndexOffsetExpressionStrategy(
BoundExpression unloweredExpr,
- BoundExpression lengthAccess,
- out bool usedLength)
+ out PatternIndexOffsetLoweringStrategy strategy)
{
Debug.Assert(TypeSymbol.Equals(
unloweredExpr.Type,
_compilation.GetWellKnownType(WellKnownType.System_Index),
TypeCompareKind.ConsiderEverything));
- var F = _factory;
-
if (unloweredExpr is BoundFromEndIndexExpression hatExpression)
{
// If the System.Index argument is `^index`, we can replace the
// `argument.GetOffset(length)` call with `length - index`
Debug.Assert(hatExpression.Operand is { Type: { SpecialType: SpecialType.System_Int32 } });
- usedLength = true;
- return F.IntSubtract(lengthAccess, VisitExpression(hatExpression.Operand));
+ strategy = PatternIndexOffsetLoweringStrategy.SubtractFromLength;
+ return VisitExpression(hatExpression.Operand);
}
else if (unloweredExpr is BoundConversion { Operand: { Type: { SpecialType: SpecialType.System_Int32 } } operand })
{
// If the System.Index argument is a conversion from int to Index we
// can return the int directly
- usedLength = false;
+ strategy = PatternIndexOffsetLoweringStrategy.UseAsIs;
return VisitExpression(operand);
}
else
{
- usedLength = true;
- return F.Call(
- VisitExpression(unloweredExpr),
- WellKnownMember.System_Index__GetOffset,
- lengthAccess);
+ // `argument.GetOffset(length)`
+ strategy = PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI;
+ return VisitExpression(unloweredExpr);
}
}
@@ -300,8 +386,8 @@ private BoundSequence VisitRangePatternIndexerAccess(
// Lowered code without optimizations:
// var receiver = receiverExpr;
- // int length = receiver.length;
// Range range = argumentExpr;
+ // int length = receiver.length;
// int start = range.Start.GetOffset(length)
// int rangeSize = range.End.GetOffset(length) - start
// receiver.Slice(start, rangeSize)
@@ -312,7 +398,6 @@ private BoundSequence VisitRangePatternIndexerAccess(
var sideEffectsBuilder = ArrayBuilder.GetInstance();
var receiverLocal = F.StoreToTemp(VisitExpression(receiver), out var receiverStore);
- var lengthLocal = F.StoreToTemp(F.Property(receiverLocal, lengthOrCountProperty), out var lengthStore);
localsBuilder.Add(receiverLocal.LocalSymbol);
sideEffectsBuilder.Add(receiverStore);
@@ -333,63 +418,159 @@ private BoundSequence VisitRangePatternIndexerAccess(
// int start = start.GetOffset(length)
// int rangeSize = end.GetOffset(length) - start
- bool usedLength = false;
+ BoundExpression? startMakeOffsetInput;
+ PatternIndexOffsetLoweringStrategy startStrategy;
if (rangeExpr.LeftOperandOpt is BoundExpression left)
{
- var startLocal = F.StoreToTemp(
- MakePatternIndexOffsetExpression(rangeExpr.LeftOperandOpt, lengthLocal, out usedLength),
- out var startStore);
-
- localsBuilder.Add(startLocal.LocalSymbol);
- sideEffectsBuilder.Add(startStore);
- startExpr = startLocal;
+ startMakeOffsetInput = DetermineMakePatternIndexOffsetExpressionStrategy(left, out startStrategy);
}
else
{
- startExpr = F.Literal(0);
+ startStrategy = PatternIndexOffsetLoweringStrategy.Zero;
+ startMakeOffsetInput = null;
}
- BoundExpression endExpr;
+ BoundExpression? endMakeOffsetInput;
+ PatternIndexOffsetLoweringStrategy endStrategy;
+
if (rangeExpr.RightOperandOpt is BoundExpression right)
{
- endExpr = MakePatternIndexOffsetExpression(
- right,
- lengthLocal,
- out bool usedLengthTemp);
- usedLength |= usedLengthTemp;
+ endMakeOffsetInput = DetermineMakePatternIndexOffsetExpressionStrategy(right, out endStrategy);
}
else
{
- usedLength = true;
- endExpr = lengthLocal;
+ endStrategy = PatternIndexOffsetLoweringStrategy.Length;
+ endMakeOffsetInput = null;
}
- if (usedLength)
+ const int captureStartOffset = 1 << 0;
+ const int captureEndOffset = 1 << 1;
+ const int useLength = 1 << 2;
+ const int captureLength = 1 << 3;
+ const int captureStartValue = 1 << 4;
+
+ int rewriteFlags;
+
+ switch ((startStrategy, endStrategy))
{
- // If we used the length, it needs to be calculated after the receiver (the
- // first bound node in the builder) and before the first use, which could be the
- // second or third node in the builder
- localsBuilder.Insert(1, lengthLocal.LocalSymbol);
- sideEffectsBuilder.Insert(1, lengthStore);
+ case (PatternIndexOffsetLoweringStrategy.Zero, PatternIndexOffsetLoweringStrategy.Length):
+ case (PatternIndexOffsetLoweringStrategy.Zero, PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI):
+ rewriteFlags = useLength;
+ break;
+ case (PatternIndexOffsetLoweringStrategy.Zero, PatternIndexOffsetLoweringStrategy.SubtractFromLength):
+ rewriteFlags = captureEndOffset | useLength;
+ break;
+ case (PatternIndexOffsetLoweringStrategy.Zero, PatternIndexOffsetLoweringStrategy.UseAsIs):
+ rewriteFlags = 0;
+ break;
+ case (PatternIndexOffsetLoweringStrategy.UseAsIs, PatternIndexOffsetLoweringStrategy.Length):
+ case (PatternIndexOffsetLoweringStrategy.UseAsIs, PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI):
+ rewriteFlags = useLength | captureStartValue;
+ break;
+ case (PatternIndexOffsetLoweringStrategy.UseAsIs, PatternIndexOffsetLoweringStrategy.SubtractFromLength):
+ rewriteFlags = captureStartOffset | captureEndOffset | useLength;
+ break;
+ case (PatternIndexOffsetLoweringStrategy.UseAsIs, PatternIndexOffsetLoweringStrategy.UseAsIs):
+ rewriteFlags = captureStartValue;
+ break;
+ case (PatternIndexOffsetLoweringStrategy.SubtractFromLength, PatternIndexOffsetLoweringStrategy.Length):
+ case (PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI, PatternIndexOffsetLoweringStrategy.Length):
+ rewriteFlags = captureStartOffset | useLength | captureLength | captureStartValue;
+ break;
+ case (PatternIndexOffsetLoweringStrategy.SubtractFromLength, PatternIndexOffsetLoweringStrategy.SubtractFromLength):
+ case (PatternIndexOffsetLoweringStrategy.SubtractFromLength, PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI):
+ case (PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI, PatternIndexOffsetLoweringStrategy.SubtractFromLength):
+ case (PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI, PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI):
+ rewriteFlags = captureStartOffset | captureEndOffset | useLength | captureLength | captureStartValue;
+ break;
+ case (PatternIndexOffsetLoweringStrategy.SubtractFromLength, PatternIndexOffsetLoweringStrategy.UseAsIs):
+ case (PatternIndexOffsetLoweringStrategy.UseGetOffsetAPI, PatternIndexOffsetLoweringStrategy.UseAsIs):
+ rewriteFlags = captureStartOffset | captureEndOffset | useLength | captureStartValue;
+ break;
+
+ default:
+ throw ExceptionUtilities.UnexpectedValue(startStrategy);
}
- var rangeSizeLocal = F.StoreToTemp(
- F.IntSubtract(endExpr, startExpr),
- out var rangeStore);
+ Debug.Assert(startStrategy != PatternIndexOffsetLoweringStrategy.Zero || (rewriteFlags & captureStartOffset) == 0);
+ Debug.Assert(startStrategy != PatternIndexOffsetLoweringStrategy.Zero || (rewriteFlags & captureStartValue) == 0);
+ Debug.Assert((rewriteFlags & captureEndOffset) == 0 || (rewriteFlags & captureStartOffset) != 0 || startStrategy == PatternIndexOffsetLoweringStrategy.Zero);
+ Debug.Assert((rewriteFlags & captureStartOffset) == 0 || (rewriteFlags & captureEndOffset) != 0 || endStrategy == PatternIndexOffsetLoweringStrategy.Length);
+ Debug.Assert(endStrategy != PatternIndexOffsetLoweringStrategy.Length || (rewriteFlags & captureEndOffset) == 0);
+ Debug.Assert((rewriteFlags & captureLength) == 0 || (rewriteFlags & useLength) != 0);
- localsBuilder.Add(rangeSizeLocal.LocalSymbol);
- sideEffectsBuilder.Add(rangeStore);
- rangeSizeExpr = rangeSizeLocal;
+ if ((rewriteFlags & captureStartOffset) != 0)
+ {
+ Debug.Assert(startMakeOffsetInput is not null);
+ if (startMakeOffsetInput.ConstantValue is null)
+ {
+ startMakeOffsetInput = F.StoreToTemp(startMakeOffsetInput, out BoundAssignmentOperator inputStore);
+ localsBuilder.Add(((BoundLocal)startMakeOffsetInput).LocalSymbol);
+ sideEffectsBuilder.Add(inputStore);
+ }
+ }
+
+ if ((rewriteFlags & captureEndOffset) != 0)
+ {
+ Debug.Assert(endMakeOffsetInput is not null);
+ if (endMakeOffsetInput.ConstantValue is null)
+ {
+ endMakeOffsetInput = F.StoreToTemp(endMakeOffsetInput, out BoundAssignmentOperator inputStore);
+ localsBuilder.Add(((BoundLocal)endMakeOffsetInput).LocalSymbol);
+ sideEffectsBuilder.Add(inputStore);
+ }
+ }
+
+ BoundExpression? lengthAccess = null;
+
+ if ((rewriteFlags & useLength) != 0)
+ {
+ lengthAccess = F.Property(receiverLocal, lengthOrCountProperty);
+
+ if ((rewriteFlags & captureLength) != 0)
+ {
+ var lengthLocal = F.StoreToTemp(lengthAccess, out var lengthStore);
+ localsBuilder.Add(lengthLocal.LocalSymbol);
+ sideEffectsBuilder.Add(lengthStore);
+ lengthAccess = lengthLocal;
+ }
+ }
+
+ startExpr = MakePatternIndexOffsetExpression(startMakeOffsetInput, lengthAccess, startStrategy);
+
+ if ((rewriteFlags & captureStartValue) != 0 && startExpr.ConstantValue is null)
+ {
+ var startLocal = F.StoreToTemp(startExpr, out var startStore);
+ localsBuilder.Add(startLocal.LocalSymbol);
+ sideEffectsBuilder.Add(startStore);
+ startExpr = startLocal;
+ }
+
+ BoundExpression endExpr = MakePatternIndexOffsetExpression(endMakeOffsetInput, lengthAccess, endStrategy);
+
+ if (startExpr.ConstantValue?.Int32Value == 0)
+ {
+ rangeSizeExpr = endExpr;
+ }
+ else if (startExpr.ConstantValue is { Int32Value: var startConst } && endExpr.ConstantValue is { Int32Value: var endConst })
+ {
+ rangeSizeExpr = F.Literal(unchecked(endConst - startConst));
+ }
+ else
+ {
+ rangeSizeExpr = F.IntSubtract(endExpr, startExpr);
+ }
}
else
{
var rangeLocal = F.StoreToTemp(VisitExpression(rangeArg), out var rangeStore);
+ localsBuilder.Add(rangeLocal.LocalSymbol);
+ sideEffectsBuilder.Add(rangeStore);
+ var lengthLocal = F.StoreToTemp(F.Property(receiverLocal, lengthOrCountProperty), out var lengthStore);
localsBuilder.Add(lengthLocal.LocalSymbol);
sideEffectsBuilder.Add(lengthStore);
- localsBuilder.Add(rangeLocal.LocalSymbol);
- sideEffectsBuilder.Add(rangeStore);
var startLocal = F.StoreToTemp(
F.Call(
diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
index c78eba58a7774..ec682017ee0d0 100644
--- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
+++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
@@ -314,10 +314,13 @@ public CSharpOperationFactory(SemanticModel semanticModel)
break;
}
}
-
ImmutableArray children = GetIOperationChildren(boundNode);
- return new NoneOperation(children, _semanticModel, boundNode.Syntax, type: null, constantValue, isImplicit: isImplicit);
-
+ ITypeSymbol? type = boundNode switch
+ {
+ BoundExpression boundExpr => boundExpr.GetPublicTypeSymbol(),
+ _ => null
+ };
+ return new NoneOperation(children, _semanticModel, boundNode.Syntax, type: type, constantValue, isImplicit: isImplicit);
default:
// If you're hitting this because the IOperation test hook has failed, see
// /docs/Compilers/IOperation Test Hook.md for instructions on how to fix.
@@ -453,16 +456,16 @@ private IOperation CreateBoundFunctionPointerInvocationOperation(BoundFunctionPo
ITypeSymbol? type = boundFunctionPointerInvocation.GetPublicTypeSymbol();
SyntaxNode syntax = boundFunctionPointerInvocation.Syntax;
bool isImplicit = boundFunctionPointerInvocation.WasCompilerGenerated;
- ImmutableArray children;
if (boundFunctionPointerInvocation.ResultKind != LookupResultKind.Viable)
{
- children = CreateFromArray(((IBoundInvalidNode)boundFunctionPointerInvocation).InvalidNodeChildren);
+ ImmutableArray children = CreateFromArray(((IBoundInvalidNode)boundFunctionPointerInvocation).InvalidNodeChildren);
return new InvalidOperation(children, _semanticModel, syntax, type, constantValue: null, isImplicit);
}
- children = GetIOperationChildren(boundFunctionPointerInvocation);
- return new NoneOperation(children, _semanticModel, syntax, type, constantValue: null, isImplicit);
+ var pointer = Create(boundFunctionPointerInvocation.InvokedExpression);
+ var arguments = DeriveArguments(boundFunctionPointerInvocation);
+ return new FunctionPointerInvocationOperation(pointer, arguments, _semanticModel, syntax, type, isImplicit);
}
private IOperation CreateBoundUnconvertedAddressOfOperatorOperation(BoundUnconvertedAddressOfOperator boundUnconvertedAddressOf)
diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs
index d8f22dac45f64..29949cecd5018 100644
--- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs
+++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs
@@ -259,7 +259,17 @@ internal ImmutableArray DeriveArguments(BoundNode containing
boundCollectionElementInitializer.Syntax,
boundCollectionElementInitializer.InvokedAsExtensionMethod);
}
-
+ case BoundKind.FunctionPointerInvocation:
+ {
+ var boundFunctionPointerInvocation = (BoundFunctionPointerInvocation)containingExpression;
+ return DeriveArguments(boundFunctionPointerInvocation.FunctionPointer.Signature,
+ boundFunctionPointerInvocation.Arguments,
+ default,
+ BitVector.Empty,
+ false,
+ boundFunctionPointerInvocation.Syntax,
+ false);
+ }
default:
throw ExceptionUtilities.UnexpectedValue(containingExpression.Kind);
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs
index f10521a2f2eea..60a068e423039 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs
@@ -918,14 +918,19 @@ private void DecodeUnmanagedCallersOnlyAttribute(ref DecodeWellKnownAttributeArg
return;
}
- checkAndReportManagedTypes(ReturnType, returnTypeSyntax, isParam: false, diagnostics);
+ checkAndReportManagedTypes(ReturnType, this.RefKind, returnTypeSyntax, isParam: false, diagnostics);
foreach (var param in Parameters)
{
- checkAndReportManagedTypes(param.Type, param.GetNonNullSyntaxNode(), isParam: true, diagnostics);
+ checkAndReportManagedTypes(param.Type, param.RefKind, param.GetNonNullSyntaxNode(), isParam: true, diagnostics);
}
- static void checkAndReportManagedTypes(TypeSymbol type, SyntaxNode syntax, bool isParam, BindingDiagnosticBag diagnostics)
+ static void checkAndReportManagedTypes(TypeSymbol type, RefKind refKind, SyntaxNode syntax, bool isParam, BindingDiagnosticBag diagnostics)
{
+ if (refKind != RefKind.None)
+ {
+ diagnostics.Add(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, syntax.Location);
+ }
+
// use-site diagnostics will be reported at actual parameter declaration site, we're only interested
// in reporting managed types being used
switch (type.ManagedKindNoUseSiteDiagnostics)
diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
index 3272323630c12..6b0f2459f47c4 100644
--- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
@@ -132,6 +132,14 @@ public static bool IsNullableType(this TypeSymbol type)
return type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T;
}
+ public static bool IsValidNullableTypeArgument(this TypeSymbol type)
+ {
+ return type is { IsValueType: true }
+ && !type.IsNullableType()
+ && !type.IsPointerOrFunctionPointer()
+ && !type.IsRestrictedType();
+ }
+
public static TypeSymbol GetNullableUnderlyingType(this TypeSymbol type)
{
return type.GetNullableUnderlyingTypeWithAnnotations().Type;
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index c47d182743398..534955161f867 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -222,6 +222,11 @@
Atribut AsyncMethodBuilder je u anonymních metod bez explicitního návratového typu zakázaný.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.Typ příjemce {0} není platným typem záznamu a není typem struktury.
@@ -257,6 +262,11 @@
Rozšiřující metoda, kde jako cíl je nastavený příjemce, se nedá použít jako cíl operátoru &.
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.Argumenty InterpolatedStringHandlerArgumentAttribute nemůžou odkazovat na parametr, na kterém se atribut používá.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index 97a2811376d3b..bee442a062f93 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -222,6 +222,11 @@
Das AsyncMethodBuilder-Attribut ist für anonyme Methoden ohne expliziten Rückgabetyp unzulässig.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.Der Empfängertyp "{0}" ist kein gültiger Datensatztyp und kein Strukturtyp.
@@ -257,6 +262,11 @@
Eine Erweiterungsmethode mit einem Empfänger kann nicht als Ziel eines &-Operators verwendet werden.
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.InterpolatedStringHandlerArgumentAttribute-Argumente können nicht auf den Parameter verweisen, für den das Attribut verwendet wird.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index 2c560d8d9200e..151ffc81008c4 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -222,6 +222,11 @@
El atributo AsyncMethodBuilder no se permite en métodos anónimos sin un tipo de valor devuelto explícito.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.El tipo de destinatario '{0}' no es un tipo de registro válido y no es un tipo de registro.
@@ -257,6 +262,11 @@
No se puede usar un método de extensión con un receptor como destino de un operador "&".
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.Los argumentos de InterpolatedStringHandlerArgumentAttribute no pueden hacer referencia al parámetro en el que se usa el atributo.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index 98df771b0f62d..aa2cca41f87e4 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -222,6 +222,11 @@
L'attribut AsyncMethodBuilder n'est pas autorisé pour les méthodes anonymes sans type de retour explicite.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.Le type de récepteur '{0}' n’est pas un type d’enregistrement valide et n’est pas un type struct.
@@ -257,6 +262,11 @@
Impossible d'utiliser une méthode d'extension avec un récepteur en tant que cible d'un opérateur '&'.
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.Les arguments de l'attribut InterpolatedStringHandlerArgumentAttribute ne peuvent pas faire référence au paramètre sur lequel l'attribut est utilisé.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index 670f9ebd2ade1..2490a830c0e6b 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -222,6 +222,11 @@
L'attributo AsyncMethodBuilder non è consentito in metodi anonimi senza un tipo restituito esplicito.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.Il tipo di ricevitore '{0}' non è un tipo di record valido e non è un tipo struct.
@@ -257,6 +262,11 @@
Non è possibile usare un metodo di estensione con un ricevitore come destinazione di un operatore '&'.
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.Gli argomenti di InterpolatedStringHandlerArgumentAttribute non possono fare riferimento al parametro in cui viene usato l'attributo.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index 67e77e00cdece..d267d8119b3d4 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -222,6 +222,11 @@
AsyncMethodBuilder 属性は、明示的な戻り値の型のない匿名メソッドでは許可されていません。
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.レシーバーの種類 '{0}' は有効なレコード型でも構造体型でもありません。
@@ -257,6 +262,11 @@
レシーバーが '&' 演算子の対象となっている拡張メソッドを使用することはできません。
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.InterpolatedStringHandlerArgumentAttribute 引数は、属性が使用されているパラメーターを参照できません。
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index 1370ca584ea46..2041531983122 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -222,6 +222,11 @@
AsyncMethodBuilder 특성은 명시적 반환 형식이 없는 익명 메서드에서 허용되지 않습니다.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.수신기 형식 '{0}'은(는) 올바른 레코드 형식이 아니며 구조체 형식이 아닙니다.
@@ -257,6 +262,11 @@
'&' 연산자의 대상으로 수신기가 있는 확장 메서드는 사용할 수 없습니다.
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.InterpolatedStringHandlerArgumentAttribute 인수는 특성이 사용되는 매개 변수를 참조할 수 없습니다.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index 14c1f0421acbc..a6fd6b61619c0 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -222,6 +222,11 @@
Atrybut AsyncMethodBuilder jest niedozwolony w metodach anonimowych bez jawnego zwracanego typu.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.Typ odbiorcy "{0}" nie jest prawidłowym typem rekordu i nie jest typem struktury.
@@ -257,6 +262,11 @@
Nie można użyć metody rozszerzenia z odbiornikiem jako elementem docelowym operatora „&”.
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.Argumenty atrybutu InterpolatedStringHandlerArgumentAttribute nie mogą odwoływać się do parametru, na podstawie którego jest używany atrybut.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index 8ad9edeb9b875..04f9b792aefb9 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -222,6 +222,11 @@
O atributo AsyncMethodBuilder não é permitido em métodos anônimos sem um tipo de retorno explícito.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.O tipo de receptor '{0}' não é um tipo de registro válido e não é um tipo struct.
@@ -257,6 +262,11 @@
Não é possível usar um método de extensão com um receptor como destino de um operador '&'.
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.Argumentos InterpolatedStringHandlerArgumentAttribute não podem fazer referência ao parâmetro no qual o atributo é usado.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 21a7ed321ee8e..ae4f788696228 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -222,6 +222,11 @@
Атрибут AsyncMethodBuilder запрещен для анонимных методов без явного типа возвращаемого значения.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.Тип получателя "{0}" не является допустимым типом записи и не является типом структуры.
@@ -257,6 +262,11 @@
Невозможно использовать метод расширения с приемником в качестве целевого объекта оператора "&".
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.Аргументы InterpolatedStringHandlerArgumentAttribute не могут ссылаться на параметр, в котором используется атрибут.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index 16403d22aa1e5..2ec632f162270 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -222,6 +222,11 @@
Açık dönüş türü olmadan, anonim yöntemlerde AsyncMethodBuilder özniteliğine izin verilmez.
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.'{0}' alıcı türü geçerli bir kayıt türü değil ve bir yapı türü değil.
@@ -257,6 +262,11 @@
'&' operatörünün hedefi olarak alıcı içeren bir genişletme metodu kullanılamaz.
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.InterpolatedStringHandlerArgumentAttribute bağımsız değişkenleri özniteliğin kullanıldığı parametreye başvuramaz.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index 7b122b800dadb..ec6f6946c8308 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -222,6 +222,11 @@
没有显式返回类型的匿名方法不允许使用 AsyncMethodBuilder 属性。
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.接收方类型 '{0}' 非有效记录类型,且非结构类型。
@@ -257,6 +262,11 @@
不可将具有接收器的扩展方法用作 "&" 运算符的目标。
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.InterpolatedStringHandlerArgumentAttribute 参数不能引用在其上使用该属性的参数。
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index 67000287b6586..d9f12c5da3099 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -222,6 +222,11 @@
沒有明確傳回型別的匿名方法上不允許 AsyncMethodBuilder 屬性。
+
+ '{0}' cannot be made nullable.
+ '{0}' cannot be made nullable.
+
+ The receiver type '{0}' is not a valid record type and is not a struct type.接收器類型 '{0}' 不是有效的記錄類型,而且不是結構類型。
@@ -257,6 +262,11 @@
無法使用具有接收器的擴充方法作為 '&' 運算子的目標。
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute arguments cannot refer to the parameter the attribute is used on.InterpolatedStringHandlerArgumentAttribute 引數無法參考屬性所使用的參數。
diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs
index 96c9ee0369c5d..105541efd79e1 100644
--- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs
+++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs
@@ -9511,32 +9511,23 @@ public void WRN_InvalidSearchPathDir()
}
[WorkItem(650083, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/650083")]
- [ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/55730")]
- public void ReservedDeviceNameAsFileName()
+ [InlineData("a.cs /t:library /appconfig:.\\aux.config")]
+ [InlineData("a.cs /out:com1.dll")]
+ [InlineData("a.cs /doc:..\\lpt2.xml")]
+ [InlineData("a.cs /pdb:..\\prn.pdb")]
+ [Theory]
+ public void ReservedDeviceNameAsFileName(string commandLine)
{
- var parsedArgs = DefaultParse(new[] { "com9.cs", "/t:library " }, WorkingDirectory);
- Assert.Equal(0, parsedArgs.Errors.Length);
-
- parsedArgs = DefaultParse(new[] { "a.cs", "/t:library ", "/appconfig:.\\aux.config" }, WorkingDirectory);
- Assert.Equal(1, parsedArgs.Errors.Length);
- Assert.Equal((int)ErrorCode.FTL_InvalidInputFileName, parsedArgs.Errors.First().Code);
-
-
- parsedArgs = DefaultParse(new[] { "a.cs", "/out:com1.dll " }, WorkingDirectory);
- Assert.Equal(1, parsedArgs.Errors.Length);
- Assert.Equal((int)ErrorCode.FTL_InvalidInputFileName, parsedArgs.Errors.First().Code);
-
- parsedArgs = DefaultParse(new[] { "a.cs", "/doc:..\\lpt2.xml: " }, WorkingDirectory);
- Assert.Equal(1, parsedArgs.Errors.Length);
- Assert.Equal((int)ErrorCode.FTL_InvalidInputFileName, parsedArgs.Errors.First().Code);
-
- parsedArgs = DefaultParse(new[] { "a.cs", "/debug+", "/pdb:.\\prn.pdb" }, WorkingDirectory);
- Assert.Equal(1, parsedArgs.Errors.Length);
- Assert.Equal((int)ErrorCode.FTL_InvalidInputFileName, parsedArgs.Errors.First().Code);
-
- parsedArgs = DefaultParse(new[] { "a.cs", "@con.rsp" }, WorkingDirectory);
- Assert.Equal(1, parsedArgs.Errors.Length);
- Assert.Equal((int)ErrorCode.ERR_OpenResponseFile, parsedArgs.Errors.First().Code);
+ var parsedArgs = DefaultParse(commandLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries), WorkingDirectory);
+ if (ExecutionConditionUtil.OperatingSystemRestrictsFileNames)
+ {
+ Assert.Equal(1, parsedArgs.Errors.Length);
+ Assert.Equal((int)ErrorCode.FTL_InvalidInputFileName, parsedArgs.Errors.First().Code);
+ }
+ else
+ {
+ Assert.Equal(0, parsedArgs.Errors.Length);
+ }
}
[Fact]
@@ -11723,7 +11714,12 @@ public void MicrosoftDiaSymReaderNativeAltLoadPath()
var arguments = "/nologo /t:library /debug:full Source.cs";
// env variable not set (deterministic) -- DSRN is required:
- var result = ProcessUtilities.Run(cscCopy, arguments + " /deterministic", workingDirectory: dir.Path);
+ var result = ProcessUtilities.Run(
+ cscCopy,
+ arguments + " /deterministic",
+ workingDirectory: dir.Path,
+ additionalEnvironmentVars: new[] { KeyValuePairUtil.Create("MICROSOFT_DIASYMREADER_NATIVE_ALT_LOAD_PATH", "") });
+
AssertEx.AssertEqualToleratingWhitespaceDifferences(
"error CS0041: Unexpected error writing debug information -- 'Unable to load DLL 'Microsoft.DiaSymReader.Native.amd64.dll': " +
"The specified module could not be found. (Exception from HRESULT: 0x8007007E)'", result.Output.Trim());
diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs b/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs
index 507f72f53e62e..ba775a35557ac 100644
--- a/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/Attributes/InternalsVisibleToAndStrongNameTests.cs
@@ -2894,5 +2894,280 @@ public class Class1 : TestBaseClass
var c2 = CreateCompilation(new[] { source1, source2 }, new[] { libRef }, assemblyName: "WantsIVTAccess", options: TestOptions.SigningReleaseDll);
c2.VerifyEmitDiagnostics();
}
+
+ [Fact]
+ [WorkItem(57742, "https://github.com/dotnet/roslyn/issues/57742")]
+ public void Issue57742_01()
+ {
+ string lib_cs = @"
+using System.Runtime.CompilerServices;
+
+[ assembly: InternalsVisibleTo(""Issue57742_01, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b986f6b5ea5717d35c72d38561f413e267029efa9b5f107b9331d83df657381325b3a67b75812f63a9436ceccb49494de8f574f8e639d4d26c0fcf8b0e9a1a196b80b6f6ed053628d10d027e032df2ed1d60835e5f47d32c9ef6da10d0366a319573362c821b5f8fa5abc5bb22241de6f666a85d82d6ba8c3090d01636bd2bb"") ]
+internal class PublicKeyConstants
+{
+ public const string PublicKey = ""Something"";
+}
+";
+ var lib = CreateCompilation(lib_cs, assemblyName: "Issue57742_01_Lib");
+
+ string source1 = @"
+[assembly: TestAttribute(""something"" + PublicKeyConstants.PublicKey)]
+
+class TestAttribute : System.Attribute
+{
+ public TestAttribute(string x) {}
+}
+";
+
+ var comp = CreateCompilation(source1, new[] { lib.ToMetadataReference() }, assemblyName: "Issue57742_01");
+ var expected = new[]
+ {
+ // (2,40): error CS0281: Friend access was granted by 'Issue57742_01_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly
+ // [assembly: TestAttribute("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_01_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(2, 40)
+ };
+
+ comp.VerifyDiagnostics(expected);
+
+ comp = CreateCompilation(source1, new[] { lib.EmitToImageReference() }, assemblyName: "Issue57742_01");
+ comp.VerifyDiagnostics(expected);
+ }
+
+ [Fact]
+ [WorkItem(57742, "https://github.com/dotnet/roslyn/issues/57742")]
+ public void Issue57742_02()
+ {
+ string lib_cs = @"
+using System.Runtime.CompilerServices;
+
+[ assembly: InternalsVisibleTo(""Issue57742_02, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b986f6b5ea5717d35c72d38561f413e267029efa9b5f107b9331d83df657381325b3a67b75812f63a9436ceccb49494de8f574f8e639d4d26c0fcf8b0e9a1a196b80b6f6ed053628d10d027e032df2ed1d60835e5f47d32c9ef6da10d0366a319573362c821b5f8fa5abc5bb22241de6f666a85d82d6ba8c3090d01636bd2bb"") ]
+internal class PublicKeyConstants
+{
+ public const string PublicKey = ""Something"";
+}
+";
+ var lib = CreateCompilation(lib_cs, assemblyName: "Issue57742_02_Lib");
+
+ string source1 = @"
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo(""something"" + PublicKeyConstants.PublicKey)]
+";
+
+ var comp = CreateCompilation(source1, new[] { lib.ToMetadataReference() }, assemblyName: "Issue57742_02");
+ var expected = new[]
+ {
+ // (4,45): error CS0281: Friend access was granted by 'Issue57742_02_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: InternalsVisibleTo("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_02_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(4, 45)
+ };
+
+ comp.VerifyDiagnostics(expected);
+
+ comp = CreateCompilation(source1, new[] { lib.EmitToImageReference() }, assemblyName: "Issue57742_02");
+ comp.VerifyDiagnostics(expected);
+ }
+
+ [Fact]
+ [WorkItem(57742, "https://github.com/dotnet/roslyn/issues/57742")]
+ public void Issue57742_03()
+ {
+ string lib_cs = @"
+using System.Runtime.CompilerServices;
+
+[ assembly: InternalsVisibleTo(""Issue57742_03, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b986f6b5ea5717d35c72d38561f413e267029efa9b5f107b9331d83df657381325b3a67b75812f63a9436ceccb49494de8f574f8e639d4d26c0fcf8b0e9a1a196b80b6f6ed053628d10d027e032df2ed1d60835e5f47d32c9ef6da10d0366a319573362c821b5f8fa5abc5bb22241de6f666a85d82d6ba8c3090d01636bd2bb"") ]
+internal class PublicKeyConstants
+{
+ public const string PublicKey = ""Something"";
+}
+";
+ var lib = CreateCompilation(lib_cs, assemblyName: "Issue57742_03_Lib");
+
+ string source1 = @"
+using System.Reflection;
+
+[assembly: TestAttribute(""something"" + PublicKeyConstants.PublicKey)]
+[assembly: AssemblyKeyFile(""something"" + PublicKeyConstants.PublicKey)]
+
+class TestAttribute : System.Attribute
+{
+ public TestAttribute(string x) {}
+}
+";
+
+ CompilationReference compilationReference = lib.ToMetadataReference();
+ var comp = CreateCompilation(source1, new[] { compilationReference }, assemblyName: "Issue57742_03");
+ var expected = new[]
+ {
+ // error CS7027: Error signing output with public key from file 'somethingSomething' -- Assembly signing not supported.
+ Diagnostic(ErrorCode.ERR_PublicKeyFileFailure).WithArguments("somethingSomething", "Assembly signing not supported.").WithLocation(1, 1),
+ // error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('Issue57742_03, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis).WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Issue57742_03, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 1),
+ // (4,40): error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: TestAttribute("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(4, 40),
+ // (5,42): error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: AssemblyKeyFile("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(5, 42)
+ };
+
+ comp.VerifyDiagnostics(expected);
+
+ MetadataReference imageReference = lib.EmitToImageReference();
+ comp = CreateCompilation(source1, new[] { imageReference }, assemblyName: "Issue57742_03");
+ comp.VerifyDiagnostics(expected);
+
+ string source2 = @"
+using System.Reflection;
+
+[assembly: TestAttribute(""something"" + PublicKeyConstants.PublicKey)]
+[assembly: AssemblyKeyName(""something"" + PublicKeyConstants.PublicKey)]
+
+class TestAttribute : System.Attribute
+{
+ public TestAttribute(string x) {}
+}
+";
+
+ var comp2 = CreateCompilation(source2, new[] { compilationReference }, assemblyName: "Issue57742_03");
+ var expected2 = new[]
+ {
+ // error CS7028: Error signing output with public key from container 'somethingSomething' -- Assembly signing not supported.
+ Diagnostic(ErrorCode.ERR_PublicKeyContainerFailure).WithArguments("somethingSomething", "Assembly signing not supported.").WithLocation(1, 1),
+ // error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('Issue57742_03, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis).WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Issue57742_03, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 1),
+ // (4,40): error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: TestAttribute("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(4, 40),
+ // (5,42): error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: AssemblyKeyName("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(5, 42)
+ };
+
+ comp2.VerifyDiagnostics(expected2);
+
+ comp2 = CreateCompilation(source2, new[] { imageReference }, assemblyName: "Issue57742_03");
+ comp2.VerifyDiagnostics(expected2);
+
+ string source3 = @"
+using System.Reflection;
+
+[assembly: AssemblyKeyFile(""something"" + PublicKeyConstants.PublicKey)]
+";
+
+ var comp3 = CreateCompilation(source3, new[] { compilationReference }, assemblyName: "Issue57742_03");
+ var expected3 = new[]
+ {
+ // error CS7027: Error signing output with public key from file 'somethingSomething' -- Assembly signing not supported.
+ Diagnostic(ErrorCode.ERR_PublicKeyFileFailure).WithArguments("somethingSomething", "Assembly signing not supported.").WithLocation(1, 1),
+ // error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('Issue57742_03, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis).WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Issue57742_03, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 1),
+ // (4,42): error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: AssemblyKeyFile("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(4, 42)
+ };
+
+ comp3.VerifyDiagnostics(expected3);
+
+ comp3 = CreateCompilation(source3, new[] { imageReference }, assemblyName: "Issue57742_03");
+ comp3.VerifyDiagnostics(expected3);
+
+ string source4 = @"
+using System.Reflection;
+
+[assembly: AssemblyKeyName(""something"" + PublicKeyConstants.PublicKey)]
+";
+
+ var comp4 = CreateCompilation(source4, new[] { compilationReference }, assemblyName: "Issue57742_03");
+ var expected4 = new[]
+ {
+ // error CS7028: Error signing output with public key from container 'somethingSomething' -- Assembly signing not supported.
+ Diagnostic(ErrorCode.ERR_PublicKeyContainerFailure).WithArguments("somethingSomething", "Assembly signing not supported.").WithLocation(1, 1),
+ // error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('Issue57742_03, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis).WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Issue57742_03, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 1),
+ // (4,42): error CS0281: Friend access was granted by 'Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: AssemblyKeyName("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_03_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(4, 42)
+ };
+
+ comp4.VerifyDiagnostics(expected4);
+
+ comp4 = CreateCompilation(source4, new[] { imageReference }, assemblyName: "Issue57742_03");
+ comp4.VerifyDiagnostics(expected4);
+ }
+
+ [Fact]
+ [WorkItem(57742, "https://github.com/dotnet/roslyn/issues/57742")]
+ public void Issue57742_04()
+ {
+ string lib_cs = @"
+using System.Runtime.CompilerServices;
+
+[ assembly: InternalsVisibleTo(""Issue57742_04, PublicKey=00240000048000009400000006020000002400005253413100040000010001002b986f6b5ea5717d35c72d38561f413e267029efa9b5f107b9331d83df657381325b3a67b75812f63a9436ceccb49494de8f574f8e639d4d26c0fcf8b0e9a1a196b80b6f6ed053628d10d027e032df2ed1d60835e5f47d32c9ef6da10d0366a319573362c821b5f8fa5abc5bb22241de6f666a85d82d6ba8c3090d01636bd2bb"") ]
+internal class PublicKeyConstants
+{
+ public const string PublicKey = ""Something"";
+}
+";
+ var lib = CreateCompilation(lib_cs, assemblyName: "Issue57742_04_Lib");
+
+ string source1 = @"
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo(""something"" + PublicKeyConstants.PublicKey)]
+[assembly: AssemblyKeyFile(""something"" + PublicKeyConstants.PublicKey)]
+";
+
+ CompilationReference compilationReference = lib.ToMetadataReference();
+ var comp = CreateCompilation(source1, new[] { compilationReference }, assemblyName: "Issue57742_04");
+ var expected = new[]
+ {
+ // error CS7027: Error signing output with public key from file 'somethingSomething' -- Assembly signing not supported.
+ Diagnostic(ErrorCode.ERR_PublicKeyFileFailure).WithArguments("somethingSomething", "Assembly signing not supported.").WithLocation(1, 1),
+ // error CS0281: Friend access was granted by 'Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('Issue57742_04, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis).WithArguments("Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Issue57742_04, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 1),
+ // (5,45): error CS0281: Friend access was granted by 'Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: InternalsVisibleTo("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(5, 45),
+ // (6,42): error CS0281: Friend access was granted by 'Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: AssemblyKeyFile("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(6, 42)
+ };
+
+ comp.VerifyDiagnostics(expected);
+
+ MetadataReference imageReference = lib.EmitToImageReference();
+ comp = CreateCompilation(source1, new[] { imageReference }, assemblyName: "Issue57742_04");
+ comp.VerifyDiagnostics(expected);
+
+ string source2 = @"
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo(""something"" + PublicKeyConstants.PublicKey)]
+[assembly: AssemblyKeyName(""something"" + PublicKeyConstants.PublicKey)]
+";
+
+ var comp2 = CreateCompilation(source2, new[] { compilationReference }, assemblyName: "Issue57742_04");
+ var expected2 = new[]
+ {
+ // error CS7028: Error signing output with public key from container 'somethingSomething' -- Assembly signing not supported.
+ Diagnostic(ErrorCode.ERR_PublicKeyContainerFailure).WithArguments("somethingSomething", "Assembly signing not supported.").WithLocation(1, 1),
+ // error CS0281: Friend access was granted by 'Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('Issue57742_04, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis).WithArguments("Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "Issue57742_04, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(1, 1),
+ // (5,45): error CS0281: Friend access was granted by 'Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: InternalsVisibleTo("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(5, 45),
+ // (6,42): error CS0281: Friend access was granted by 'Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null', but the public key of the output assembly ('') does not match that specified by the InternalsVisibleTo attribute in the granting assembly.
+ // [assembly: AssemblyKeyName("something" + PublicKeyConstants.PublicKey)]
+ Diagnostic(ErrorCode.ERR_FriendRefNotEqualToThis, "PublicKeyConstants").WithArguments("Issue57742_04_Lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "").WithLocation(6, 42)
+ };
+
+ comp2.VerifyDiagnostics(expected2);
+
+ comp2 = CreateCompilation(source2, new[] { imageReference }, assemblyName: "Issue57742_04");
+ comp2.VerifyDiagnostics(expected2);
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
index 900bbe013a54a..9fd93e28050f4 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
@@ -8111,6 +8111,49 @@ static void M8(T t) where T : unmanaged {}
);
}
+ [Fact, WorkItem(57025, "https://github.com/dotnet/roslyn/issues/57025")]
+ public void UnmanagedCallersOnlyRequiresNonRef_Errors()
+ {
+ var comp = CreateCompilation(new[] { @"
+using System.Runtime.InteropServices;
+class C
+{
+ [UnmanagedCallersOnly]
+ static ref int M1() => throw null;
+
+ [UnmanagedCallersOnly]
+ static ref readonly int M2() => throw null;
+
+ [UnmanagedCallersOnly]
+ static void M3(ref int o) => throw null;
+
+ [UnmanagedCallersOnly]
+ static void M4(in int o) => throw null;
+
+ [UnmanagedCallersOnly]
+ static void M5(out int o) => throw null;
+}
+", UnmanagedCallersOnlyAttribute });
+
+ comp.VerifyDiagnostics(
+ // (6,12): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static ref int M1() => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "ref int").WithLocation(6, 12),
+ // (9,12): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static ref readonly int M2() => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "ref readonly int").WithLocation(9, 12),
+ // (12,20): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static void M3(ref int o) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "ref int o").WithLocation(12, 20),
+ // (15,20): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static void M4(in int o) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "in int o").WithLocation(15, 20),
+ // (18,20): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static void M5(out int o) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "out int o").WithLocation(18, 20)
+ );
+ }
+
[Fact]
public void UnmanagedCallersOnlyRequiresUnmanagedTypes_Valid()
{
@@ -9471,7 +9514,13 @@ static class CExt
Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "ls").WithArguments("CExt.Deconstruct(S, out int, out int)").WithLocation(11, 32),
// (12,18): error CS8901: 'CExt.Deconstruct(S, out int, out int)' is attributed with 'UnmanagedCallersOnly' and cannot be called directly. Obtain a function pointer to this method.
// _ = s is (int _, int _);
- Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "(int _, int _)").WithArguments("CExt.Deconstruct(S, out int, out int)").WithLocation(12, 18)
+ Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "(int _, int _)").WithArguments("CExt.Deconstruct(S, out int, out int)").WithLocation(12, 18),
+ // (18,46): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // public static void Deconstruct(this S s, out int i1, out int i2) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "out int i1").WithLocation(18, 46),
+ // (18,58): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // public static void Deconstruct(this S s, out int i1, out int i2) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "out int i2").WithLocation(18, 58)
);
}
@@ -9574,7 +9623,10 @@ static class CExt
comp.VerifyDiagnostics(
// (10,29): error CS8901: 'CExt.GetPinnableReference(S)' is attributed with 'UnmanagedCallersOnly' and cannot be called directly. Obtain a function pointer to this method.
// fixed (int* i = s)
- Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "s").WithArguments("CExt.GetPinnableReference(S)").WithLocation(10, 29)
+ Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "s").WithArguments("CExt.GetPinnableReference(S)").WithLocation(10, 29),
+ // (20,19): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // public static ref int GetPinnableReference(this S s) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "ref int").WithLocation(20, 19)
);
}
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
index 2b69bd5d8ef77..e2fedf4e12ac4 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
@@ -5491,15 +5491,15 @@ T M()
var compilation = CreateCompilation(source);
compilation.VerifyDiagnostics(
- // (15,33): error CS0023: Operator '?' cannot be applied to operand of type 'T'
- // Func