-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create default arguments during binding #49186
Conversation
This comment has been minimized.
This comment has been minimized.
c4ad664
to
b6cd75a
Compare
b6cd75a
to
fe03afe
Compare
fe03afe
to
29e0d7a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done review pass (commit 2)
src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArgument.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArgument.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArgument.cs
Outdated
Show resolved
Hide resolved
Thanks for the feedback @333fred. |
@@ -182,6 +233,7 @@ private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind | |||
{ | |||
case BoundKind.PropertyGroup: | |||
expr = BindIndexedPropertyAccess((BoundPropertyGroup)expr, mustHaveAllOptionalParameters: false, diagnostics: diagnostics); | |||
expr = BindIndexerDefaultArguments(expr, valueKind, diagnostics); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BindIndexerDefaultArguments [](start = 27, length = 27)
Does this have any effect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. In some scenarios, we can call an indexer whose parameters are all optional by omitting the element access syntax entirely. Here's a test that demonstrates this:
roslyn/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_CallerInfoAttributes.cs
Lines 3080 to 3139 in 98cbb71
[WorkItem(1006447, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1006447")] | |
[Fact] | |
public void Bug1006447_1() | |
{ | |
const string vbSource = | |
@"Imports System | |
Imports System.Runtime.CompilerServices | |
Imports System.Runtime.InteropServices | |
Imports System.Text | |
<ComImport> | |
<Guid(""1F9C3731-6AA1-498A-AFA0-359828FCF0CE"")> | |
Public Interface I | |
Property X(Optional i as Integer = 0, <CallerFilePath> Optional s As String = Nothing) As StringBuilder | |
End Interface | |
Public Class A | |
Implements I | |
Public Property X(Optional i as Integer = 0, Optional s As String = Nothing) As StringBuilder Implements I.X | |
Get | |
Console.WriteLine(""Get X(""""{0}"""")"", s) | |
Return New StringBuilder | |
End Get | |
Set(value As StringBuilder) | |
Console.WriteLine(""Set X(""""{0}"""")"", s) | |
End Set | |
End Property | |
End Class"; | |
var vbReference = BasicCompilationUtils.CompileToMetadata(vbSource, references: new[] { MscorlibRef_v4_0_30316_17626, SystemCoreRef }); | |
const string csSource = | |
@"using System; | |
class C | |
{ | |
I P = new A(); | |
static void Main() | |
{ | |
new C().P.X = null; | |
new C().P.X[1] = null; | |
new C { P = { X = null } }; | |
new C { P = { X = { Length = 0 } } }; | |
} | |
} | |
"; | |
var compilation = CreateCompilationWithMscorlib45( | |
new[] { SyntaxFactory.ParseSyntaxTree(csSource, path: @"C:\filename", encoding: Encoding.UTF8) }, | |
new[] { SystemCoreRef, vbReference }, | |
TestOptions.ReleaseExe); | |
CompileAndVerify(compilation, expectedOutput: | |
@"Set X(""C:\filename"") | |
Set X(""C:\filename"") | |
Set X(""C:\filename"") | |
Get X(""C:\filename"") | |
"); | |
} |
if (useSetAccessor) | ||
{ | ||
parameters = parameters.RemoveAt(parameters.Length - 1); | ||
Debug.Assert(parameters.Length == indexerAccess.Indexer.Parameters.Length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug.Assert [](start = 20, length = 12)
Consider moving assert after if
so it's executed always.
src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs
Outdated
Show resolved
Hide resolved
{ | ||
// This is only expected to occur in recursive error scenarios, for example: `object F(object param = F()) { }` | ||
// We return a non-error expression here to ensure ERR_DefaultValueMustBeConstant (or another appropriate diagnostics) is produced by the caller. | ||
return new BoundDefaultExpression(syntax, parameterType) { WasCompilerGenerated = true }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could technically change observable behavior for nullability warnings or IOperation results, but I think that's fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we decide to start giving nullability warnings for default arguments then we might want to add a nullable suppression to this node, but we'll cross that bridge if we come to it
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArgument.cs
Show resolved
Hide resolved
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArgument.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArgument.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArgument.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArgument.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IArgument.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done review pass (commit 4). Just a couple of minor comments left.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (commit 6)
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_UsingStatement.cs
Show resolved
Hide resolved
// that never expires, then the failure mode will be to spin wait forever. | ||
// For debug purposes let's instead use a token which expires after a modest amount of time | ||
// to wait for the default syntax value to be available. | ||
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to pick a much higher number here. It is more than reasonable for a thread to hang for 5 secnds in CI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like integration tests use 1 minute to wait for things to complete in some places. I'll go with that as a starting point
public static readonly TimeSpan HangMitigatingTimeout = TimeSpan.FromMinutes(1); |
#else | ||
var token = CancellationToken.None; | ||
#endif | ||
state.SpinWaitComplete(CompletionPart.EndDefaultSyntaxValue, token); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel like ForceComplete
should change to assert that this part has completed. That is the pattern we usually have elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't find examples of asserting that parts are completed instead of spin-waiting for them to complete when looking through the overrides of Symbol.ForceComplete. Could you provide an example of what you had in mind?
* upstream/master: (148 commits) Remove unnecessary ArrayBuilder in MakeCallWithNoExplicitArgument (dotnet#49377) Revert "Skip binary for determinism checking" Use deterministic metadata names for emitted anonymous type fields. (dotnet#49370) Reuse LSP solutions if they don't need re-forking (dotnet#49305) Small nullability fixes (dotnet#49279) Create default arguments during binding (dotnet#49186) Clean nits Backport dotnet#48420 to release/dev16.8 (dotnet#49357) Rewrite AnalyzeFileReference.GetSupportedLanguages without LINQ (dotnet#49337) Use .Any extension of ImmutableArray(Of Symbol) (dotnet#48980) fix 'remove unnecessary cast' when doing bitwise ops on unsigned values. Harden, document, cross-link XunitDisposeHook Simplify x86 hook Fix split comment exporting for VB. Code style fix Overwrite xunit's app domain handling to not call AppDomain.Unload Revert pragma suppression Remove blank line Revert file Move block structure code back to Features layer ...
BoundExpression defaultValue; | ||
if (callerSourceLocation is object && parameter.IsCallerLineNumber) | ||
{ | ||
int line = GetCallerLocation(syntax).SourceTree.GetDisplayLineNumber(callerSourceLocation.SourceSpan); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use callerSourceLocation
here instead of GetCallerLocation
here
* Restore default argument binding behavior to be like it was before dotnet#49186, only asserting that parameters are optional, rather than checking. Prior code steps should have verified this. * Don't bind default arguments for error cases. * Add additional tests.
Closes #17243
Closes #47352
This PR has been organized to try and improve reviewability.