diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 0288911f9e964d69d90ae36e938941cb3e27a5d6..c39e4f27f1bcb1fbf79569c0ae9d654023f7f0fa 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -3,9 +3,9 @@
-
+
https://github.com/dotnet/arcade
- 9d34fd008e754e1ada35c8b6bc3694e7a90b4ed7
+ b902fd6b6948e689a5128fa6d94dc7de13e6af84
diff --git a/eng/common/SetupNugetSources.ps1 b/eng/common/SetupNugetSources.ps1
index 6662e4bc1ece65de8196a7603ae71b6c487dde28..a5a1e711d79c67feda4ff9725ae7df54abf851da 100644
--- a/eng/common/SetupNugetSources.ps1
+++ b/eng/common/SetupNugetSources.ps1
@@ -16,7 +16,7 @@
# condition: eq(variables['Agent.OS'], 'Windows_NT')
# inputs:
# filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1
-# arguments: -ConfigFile ${Env:BUILD_SOURCESDIRECTORY}/NuGet.config -Password $Env:Token
+# arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token
# env:
# Token: $(dn-bot-dnceng-artifact-feeds-rw)
@@ -94,41 +94,48 @@ function InsertMaestroPrivateFeedCredentials($Sources, $Creds, $Password) {
}
}
-try {
- if (!(Test-Path $ConfigFile -PathType Leaf)) {
- Write-PipelineTelemetryError -Category 'Build' -Message "Couldn't find the file NuGet config file: $ConfigFile"
+if (!(Test-Path $ConfigFile -PathType Leaf)) {
+ Write-PipelineTelemetryError -Category 'Build' -Message "Eng/common/SetupNugetSources.ps1 returned a non-zero exit code. Couldn't find the NuGet config file: $ConfigFile"
+ ExitWithExitCode 1
+}
+
+if (!$Password) {
+ Write-PipelineTelemetryError -Category 'Build' -Message 'Eng/common/SetupNugetSources.ps1 returned a non-zero exit code. Please supply a valid PAT'
ExitWithExitCode 1
- }
+}
- # Load NuGet.config
- $doc = New-Object System.Xml.XmlDocument
- $filename = (Get-Item $ConfigFile).FullName
- $doc.Load($filename)
+# Load NuGet.config
+$doc = New-Object System.Xml.XmlDocument
+$filename = (Get-Item $ConfigFile).FullName
+$doc.Load($filename)
- # Get reference to or create one if none exist already
- $sources = $doc.DocumentElement.SelectSingleNode("packageSources")
- if ($sources -eq $null) {
- $sources = $doc.CreateElement("packageSources")
- $doc.DocumentElement.AppendChild($sources) | Out-Null
- }
+# Get reference to or create one if none exist already
+$sources = $doc.DocumentElement.SelectSingleNode("packageSources")
+if ($sources -eq $null) {
+ $sources = $doc.CreateElement("packageSources")
+ $doc.DocumentElement.AppendChild($sources) | Out-Null
+}
- # Looks for a node. Create it if none is found.
- $creds = $doc.DocumentElement.SelectSingleNode("packageSourceCredentials")
- if ($creds -eq $null) {
- $creds = $doc.CreateElement("packageSourceCredentials")
- $doc.DocumentElement.AppendChild($creds) | Out-Null
- }
+# Looks for a node. Create it if none is found.
+$creds = $doc.DocumentElement.SelectSingleNode("packageSourceCredentials")
+if ($creds -eq $null) {
+ $creds = $doc.CreateElement("packageSourceCredentials")
+ $doc.DocumentElement.AppendChild($creds) | Out-Null
+}
- # Insert credential nodes for Maestro's private feeds
- InsertMaestroPrivateFeedCredentials -Sources $sources -Creds $creds -Password $Password
+# Insert credential nodes for Maestro's private feeds
+InsertMaestroPrivateFeedCredentials -Sources $sources -Creds $creds -Password $Password
+$dotnet3Source = $sources.SelectSingleNode("add[@key='dotnet3']")
+if ($dotnet3Source -ne $null) {
AddPackageSource -Sources $sources -SourceName "dotnet3-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal/nuget/v2" -Creds $creds -Username "dn-bot" -Password $Password
AddPackageSource -Sources $sources -SourceName "dotnet3-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3-internal-transport/nuget/v2" -Creds $creds -Username "dn-bot" -Password $Password
-
- $doc.Save($filename)
}
-catch {
- Write-Host $_.ScriptStackTrace
- Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_
- ExitWithExitCode 1
+
+$dotnet31Source = $sources.SelectSingleNode("add[@key='dotnet3.1']")
+if ($dotnet31Source -ne $null) {
+ AddPackageSource -Sources $sources -SourceName "dotnet3.1-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v2" -Creds $creds -Username "dn-bot" -Password $Password
+ AddPackageSource -Sources $sources -SourceName "dotnet3.1-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v2" -Creds $creds -Username "dn-bot" -Password $Password
}
+
+$doc.Save($filename)
diff --git a/eng/common/SetupNugetSources.sh b/eng/common/SetupNugetSources.sh
index 55ad70e3663161702265b03025131fcd9fc664f7..7d6fef27fe495e2c3470b81c9d872e8f470f6c42 100644
--- a/eng/common/SetupNugetSources.sh
+++ b/eng/common/SetupNugetSources.sh
@@ -17,7 +17,7 @@
# displayName: Setup Private Feeds Credentials
# inputs:
# filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh
-# arguments: $BUILD_SOURCESDIRECTORY/NuGet.config $Token
+# arguments: $(Build.SourcesDirectory)/NuGet.config $Token
# condition: ne(variables['Agent.OS'], 'Windows_NT')
# env:
# Token: $(dn-bot-dnceng-artifact-feeds-rw)
@@ -42,7 +42,12 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
. "$scriptroot/tools.sh"
if [ ! -f "$ConfigFile" ]; then
- Write-PipelineTelemetryError -Category 'Build' -Message "Couldn't find the file NuGet config file: $ConfigFile"
+ Write-PipelineTelemetryError -Category 'Build' "Error: Eng/common/SetupNugetSources.sh returned a non-zero exit code. Couldn't find the NuGet config file: $ConfigFile"
+ ExitWithExitCode 1
+fi
+
+if [ -z "$CredToken" ]; then
+ Write-PipelineTelemetryError -category 'Build' "Error: Eng/common/SetupNugetSources.sh returned a non-zero exit code. Please supply a valid PAT"
ExitWithExitCode 1
fi
@@ -52,7 +57,7 @@ if [[ `uname -s` == "Darwin" ]]; then
fi
# Ensure there is a ... section.
-grep -i "" $ConfigFile
+grep -i "" $ConfigFile
if [ "$?" != "0" ]; then
echo "Adding ... section."
ConfigNodeHeader=""
@@ -62,7 +67,7 @@ if [ "$?" != "0" ]; then
fi
# Ensure there is a ... section.
-grep -i "" $ConfigFile
+grep -i "" $ConfigFile
if [ "$?" != "0" ]; then
echo "Adding ... section."
@@ -72,37 +77,64 @@ if [ "$?" != "0" ]; then
sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourcesNodeFooter${NL}$PackageSourceCredentialsTemplate|" NuGet.config
fi
-# Ensure dotnet3-internal and dotnet3-internal-transport is in the packageSources
-grep -i "" $ConfigFile
-if [ "$?" != "0" ]; then
- echo "Adding dotnet3-internal to the packageSources."
+PackageSources=()
- PackageSourcesNodeFooter=""
- PackageSourceTemplate="${TB}"
+# Ensure dotnet3-internal and dotnet3-internal-transport are in the packageSources if the public dotnet3 feeds are present
+grep -i "" $ConfigFile
+ if [ "$?" != "0" ]; then
+ echo "Adding dotnet3-internal to the packageSources."
+ PackageSourcesNodeFooter=""
+ PackageSourceTemplate="${TB}"
+
+ sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
+ fi
+ PackageSources+=('dotnet3-internal')
+
+ grep -i ""
- sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" NuGet.config
+ sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
+ fi
+ PackageSources+=('dotnet3-internal-transport')
fi
-# Ensure dotnet3-internal and dotnet3-internal-transport is in the packageSources
-grep -i "" $ConfigFile
-if [ "$?" != "0" ]; then
- echo "Adding dotnet3-internal-transport to the packageSources."
+# Ensure dotnet3.1-internal and dotnet3.1-internal-transport are in the packageSources if the public dotnet3.1 feeds are present
+grep -i ""
- PackageSourcesNodeFooter=""
- PackageSourceTemplate="${TB}"
+ sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
+ fi
+ PackageSources+=('dotnet3.1-internal')
+
+ grep -i "" $ConfigFile
+ if [ "$?" != "0" ]; then
+ echo "Adding dotnet3.1-internal-transport to the packageSources."
+ PackageSourcesNodeFooter=""
+ PackageSourceTemplate="${TB}"
- sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" NuGet.config
+ sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
+ fi
+ PackageSources+=('dotnet3.1-internal-transport')
fi
# I want things split line by line
PrevIFS=$IFS
IFS=$'\n'
-PackageSources=$(grep -oh '"darc-int-[^"]*"' $ConfigFile | tr -d '"')
+PackageSources+="$IFS"
+PackageSources+=$(grep -oh '"darc-int-[^"]*"' $ConfigFile | tr -d '"')
IFS=$PrevIFS
-PackageSources+=('dotnet3-internal')
-PackageSources+=('dotnet3-internal-transport')
-
for FeedName in ${PackageSources[@]} ; do
# Check if there is no existing credential for this FeedName
grep -i "<$FeedName>" $ConfigFile
@@ -112,6 +144,6 @@ for FeedName in ${PackageSources[@]} ; do
PackageSourceCredentialsNodeFooter=""
NewCredential="${TB}${TB}<$FeedName>${NL}${NL}${NL}$FeedName>"
- sed -i.bak "s|$PackageSourceCredentialsNodeFooter|$NewCredential${NL}$PackageSourceCredentialsNodeFooter|" NuGet.config
+ sed -i.bak "s|$PackageSourceCredentialsNodeFooter|$NewCredential${NL}$PackageSourceCredentialsNodeFooter|" $ConfigFile
fi
done
diff --git a/eng/common/build.ps1 b/eng/common/build.ps1
index 0fd4d9c7f231655e048fa05b6d54116c618a9273..88814514d828b96adc8a82f9bf271fba80b95e76 100644
--- a/eng/common/build.ps1
+++ b/eng/common/build.ps1
@@ -62,6 +62,8 @@ function Print-Usage() {
Write-Host "The above arguments can be shortened as much as to be unambiguous (e.g. -co for configuration, -t for test, etc.)."
}
+. $PSScriptRoot\tools.ps1
+
function InitializeCustomToolset {
if (-not $restore) {
return
@@ -113,8 +115,6 @@ function Build {
}
try {
- . $PSScriptRoot\tools.ps1
-
if ($clean) {
if (Test-Path $ArtifactsDir) {
Remove-Item -Recurse -Force $ArtifactsDir
@@ -122,12 +122,7 @@ try {
}
exit 0
}
-
- if ((Test-Path variable:LastExitCode) -And ($LastExitCode -ne 0)) {
- Write-PipelineTelemetryError -Category 'InitializeToolset' -Message 'Eng/common/tools.ps1 returned a non-zero exit code.'
- ExitWithExitCode $LastExitCode
- }
-
+
if ($help -or (($null -ne $properties) -and ($properties.Contains('/help') -or $properties.Contains('/?')))) {
Print-Usage
exit 0
diff --git a/eng/common/init-tools-native.ps1 b/eng/common/init-tools-native.ps1
index f4409f0835acb2dd6edef9ba4cc88f44a4c0b81b..db830c00a6f8d895705454c3507171b2f0f94705 100644
--- a/eng/common/init-tools-native.ps1
+++ b/eng/common/init-tools-native.ps1
@@ -113,14 +113,16 @@ try {
}
$toolInstallationFailure = $true
} else {
- Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message $errMsg
+ # We cannot change this to Write-PipelineTelemetryError because of https://github.com/dotnet/arcade/issues/4482
+ Write-Host $errMsg
exit 1
}
}
}
if ((Get-Variable 'toolInstallationFailure' -ErrorAction 'SilentlyContinue') -and $toolInstallationFailure) {
- Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message 'Native tools bootstrap failed'
+ # We cannot change this to Write-PipelineTelemetryError because of https://github.com/dotnet/arcade/issues/4482
+ Write-Host 'Native tools bootstrap failed'
exit 1
}
}
diff --git a/eng/common/native/install-tool.ps1 b/eng/common/native/install-tool.ps1
index ca180d03ba189ea72e8af0f2a10562cfe5c68660..f397e1c75d411eaa405647641acdb0f75fd4b1d1 100644
--- a/eng/common/native/install-tool.ps1
+++ b/eng/common/native/install-tool.ps1
@@ -105,7 +105,7 @@ try {
Write-Error "There are multiple copies of $ToolName in $($ToolInstallDirectory): `n$(@($ToolFilePath | out-string))"
exit 1
} elseif (@($ToolFilePath).Length -Lt 1) {
- Write-Error "$ToolName was not found in $ToolFilePath."
+ Write-Host "$ToolName was not found in $ToolFilePath."
exit 1
}
diff --git a/eng/common/pipeline-logging-functions.ps1 b/eng/common/pipeline-logging-functions.ps1
index e0656185886fbcaac183ef55ac6e20a2bc3f6e3d..2688c389bd96693d5b2059cee2ff34cda2f9ebb8 100644
--- a/eng/common/pipeline-logging-functions.ps1
+++ b/eng/common/pipeline-logging-functions.ps1
@@ -85,7 +85,7 @@ function Write-PipelineTaskError {
[switch]$AsOutput,
[bool]$IsMultiJobVariable=$true)
- if(-Not (Test-Path variable:ci) -Or !$ci) {
+ if((Test-Path variable:ci) -And $ci) {
Write-LoggingCommand -Area 'task' -Event 'setvariable' -Data $Value -Properties @{
'variable' = $Name
'isSecret' = $Secret
diff --git a/global.json b/global.json
index 5820271a032f54aebe8ac7bbfb0bfcf8b7ec60de..25b5c5b2dd3a9229e71f9226204eb34f6ffb96a0 100644
--- a/global.json
+++ b/global.json
@@ -7,6 +7,6 @@
"xcopy-msbuild": "16.3.0-alpha"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.19602.4"
+ "Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.19603.17"
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
index 7319f4c701be6fff25f1a426eb96b844d8fbfa94..aafdce6837720aaca3f08c257f7dc392740c60ff 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
@@ -78,6 +78,8 @@ private BoundExpression BindCompoundAssignment(AssignmentExpressionSyntax node,
Error(diagnostics, ErrorCode.ERR_BadBinaryOps, node, node.OperatorToken.Text, left.Display, right.Display);
// error: operator can't be applied on dynamic and a type that is not convertible to dynamic:
+ left = BindToTypeForErrorRecovery(left);
+ right = BindToTypeForErrorRecovery(right);
return new BoundCompoundAssignmentOperator(node, BinaryOperatorSignature.Error, left, right,
Conversion.NoConversion, Conversion.NoConversion, LookupResultKind.Empty, CreateErrorType(), hasErrors: true);
}
@@ -90,6 +92,8 @@ private BoundExpression BindCompoundAssignment(AssignmentExpressionSyntax node,
// be used here.
// NOTE: no overload resolution candidates.
+ left = BindToTypeForErrorRecovery(left);
+ right = BindToTypeForErrorRecovery(right);
return new BoundCompoundAssignmentOperator(node, BinaryOperatorSignature.Error, left, right,
Conversion.NoConversion, Conversion.NoConversion, LookupResultKind.NotAVariable, CreateErrorType(), hasErrors: true);
}
diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
index 986369928f2a747dbccdc3a8c7551c2bd2362864..b7bc03906ad07b2079fae1333c52e9ae2ca040e4 100644
--- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
@@ -1865,14 +1865,14 @@ public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpre
if (initializerOpt != null)
{
- VisitObjectCreationInitializer(null, slot, initializerOpt);
+ VisitObjectCreationInitializer(containingSymbol: null, slot, initializerOpt, leftAnnotations: FlowAnalysisAnnotations.None);
}
SetResultType(node, TypeWithState.Create(type, resultState));
}
#nullable restore
- private void VisitObjectCreationInitializer(Symbol containingSymbol, int containingSlot, BoundExpression node)
+ private void VisitObjectCreationInitializer(Symbol containingSymbol, int containingSlot, BoundExpression node, FlowAnalysisAnnotations leftAnnotations)
{
TakeIncrementalSnapshot(node);
switch (node)
@@ -1913,7 +1913,7 @@ private void VisitObjectCreationInitializer(Symbol containingSymbol, int contain
Debug.Assert((object)containingSymbol != null);
if ((object)containingSymbol != null)
{
- var type = containingSymbol.GetTypeOrReturnType();
+ var type = ApplyLValueAnnotations(containingSymbol.GetTypeOrReturnType(), leftAnnotations);
TypeWithState resultType = VisitOptionalImplicitConversion(node, type, useLegacyWarnings: false, trackMembers: true, AssignmentKind.Assignment);
TrackNullableStateForAssignment(node, type, containingSlot, resultType, MakeSlot(node));
}
@@ -1951,7 +1951,7 @@ private void VisitObjectElementInitializer(int containingSlot, BoundAssignmentOp
if ((object)symbol != null)
{
int slot = (containingSlot < 0) ? -1 : GetOrCreateSlot(symbol, containingSlot);
- VisitObjectCreationInitializer(symbol, slot, node.Right);
+ VisitObjectCreationInitializer(symbol, slot, node.Right, GetLValueAnnotations(node.Left));
// https://github.com/dotnet/roslyn/issues/35040: Should likely be setting _resultType in VisitObjectCreationInitializer
// and using that value instead of reconstructing here
}
@@ -6010,6 +6010,8 @@ private FlowAnalysisAnnotations GetLValueAnnotations(BoundExpression expr)
BoundPropertyAccess property => getSetterAnnotations(property.PropertySymbol),
BoundIndexerAccess indexer => getSetterAnnotations(indexer.Indexer),
BoundFieldAccess field => getFieldAnnotations(field.FieldSymbol),
+ BoundObjectInitializerMember { MemberSymbol: PropertySymbol prop } => getSetterAnnotations(prop),
+ BoundObjectInitializerMember { MemberSymbol: FieldSymbol field } => getFieldAnnotations(field),
_ => FlowAnalysisAnnotations.None
};
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
index 992912bcebffbeefbef999de5164662fccc66049..c5517c4488e286edbf16fae3a56e13d000338210 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
@@ -28032,6 +28032,132 @@ static void M(C c)
comp.VerifyDiagnostics();
}
+ [Fact, WorkItem(39966, "https://github.com/dotnet/roslyn/issues/39966")]
+ public void AllowNull_Property_InObjectInitializer()
+ {
+ var source = @"
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ [AllowNull] public C P { get; set; } // 1
+}
+
+class Program
+{
+ static void M(C c1)
+ {
+ c1.P = null;
+
+ new C
+ {
+ P = null
+ };
+ }
+}";
+
+ var comp = CreateNullableCompilation(new[] { source, AllowNullAttributeDefinition });
+ comp.VerifyDiagnostics(
+ // (5,26): warning CS8618: Non-nullable property 'P' is uninitialized. Consider declaring the property as nullable.
+ // [AllowNull] public C P { get; set; } // 1
+ Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "P").WithArguments("property", "P").WithLocation(5, 26));
+ }
+
+ [Fact, WorkItem(39966, "https://github.com/dotnet/roslyn/issues/39966")]
+ public void AllowNull_Field_InObjectInitializer()
+ {
+ var source = @"
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ [AllowNull] public C F; // 1
+}
+
+class Program
+{
+ static void M(C c1)
+ {
+ c1.F = null;
+
+ new C
+ {
+ F = null
+ };
+ }
+}";
+
+ var comp = CreateNullableCompilation(new[] { source, AllowNullAttributeDefinition });
+ comp.VerifyDiagnostics(
+ // (5,26): warning CS8618: Non-nullable field 'F' is uninitialized. Consider declaring the field as nullable.
+ // [AllowNull] public C F; // 1
+ Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "F").WithArguments("field", "F").WithLocation(5, 26));
+ }
+
+ [Fact, WorkItem(39966, "https://github.com/dotnet/roslyn/issues/39966")]
+ public void DisallowNull_Property_InObjectInitializer()
+ {
+ var source = @"
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ [DisallowNull] public C? P { get; set; }
+}
+
+class Program
+{
+ static void M(C c1)
+ {
+ c1.P = null; // 1
+
+ new C
+ {
+ P = null // 2
+ };
+ }
+}";
+
+ var comp = CreateNullableCompilation(new[] { source, DisallowNullAttributeDefinition });
+ comp.VerifyDiagnostics(
+ // (12,16): warning CS8625: Cannot convert null literal to non-nullable reference type.
+ // c1.P = null; // 1
+ Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 16),
+ // (16,17): warning CS8625: Cannot convert null literal to non-nullable reference type.
+ // P = null // 2
+ Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 17));
+ }
+
+ [Fact, WorkItem(39966, "https://github.com/dotnet/roslyn/issues/39966")]
+ public void DisallowNull_Field_InObjectInitializer()
+ {
+ var source = @"
+using System.Diagnostics.CodeAnalysis;
+public class C
+{
+ [DisallowNull] public C? F;
+}
+
+class Program
+{
+ static void M(C c1)
+ {
+ c1.F = null; // 1
+
+ new C
+ {
+ F = null // 2
+ };
+ }
+}";
+
+ var comp = CreateNullableCompilation(new[] { source, DisallowNullAttributeDefinition });
+ comp.VerifyDiagnostics(
+ // (12,16): warning CS8625: Cannot convert null literal to non-nullable reference type.
+ // c1.F = null; // 1
+ Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(12, 16),
+ // (16,17): warning CS8625: Cannot convert null literal to non-nullable reference type.
+ // F = null // 2
+ Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(16, 17));
+ }
+
[Fact]
public void AllowNull_Property_InDeconstructionAssignment()
{
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs
index 5551c717805fe881f7863ae20528fe2e84db012a..49e88344e3bdb774c273be27aee9ed73cd8be6b0 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OperatorTests.cs
@@ -10904,5 +10904,24 @@ static void Main()
Diagnostic(ErrorCode.ERR_ConstantStringTooLong, "C1").WithLocation(28, 68)
);
}
+
+ [Fact, WorkItem(39975, "https://github.com/dotnet/roslyn/issues/39975")]
+ public void EnsureOperandsConvertedInErrorExpression_01()
+ {
+ string source =
+@"class C
+{
+ static unsafe void M(dynamic d, int* p)
+ {
+ d += p;
+ }
+}
+";
+ CreateCompilation(source, options: TestOptions.ReleaseDll.WithAllowUnsafe(true)).VerifyDiagnostics(
+ // (5,9): error CS0019: Operator '+=' cannot be applied to operands of type 'dynamic' and 'int*'
+ // d += p;
+ Diagnostic(ErrorCode.ERR_BadBinaryOps, "d += p").WithArguments("+=", "dynamic", "int*").WithLocation(5, 9)
+ );
+ }
}
}