-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Combine deconstruction assignment and declaration, and support discards. #15548
Conversation
- Combine deconstruction assignment and declaration, and support discards. - Add wildcards.work.md to track outstanding work. - Bind each type syntax once in a deconstruction. - Because tuples may contain declarations, adjust lambda disambiguation and adjust parsing of argument lists. - Diagnose tuple element names on the left of a deconstruction. - Add relational operators to disambiguating tokens in 7.5.4.2
{ | ||
var pending = (BoundDiscardedExpression)expression; | ||
if ((object)pending.Type == null) | ||
{ |
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.
Since the caller has already checked this, I will remove the if
and add an assertion that the type is null
. #Resolved
@@ -719,14 +744,20 @@ private DeconstructionVariable BindDeconstructionVariables(ExpressionSyntax node | |||
} | |||
} | |||
|
|||
private BoundDiscardedExpression BindDiscardedExpression( | |||
DiscardedDesignationSyntax designation, | |||
TypeSymbol declType) |
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.
static
#Closed
} | ||
|
||
// Bind a declaration variable where it isn't permitted. | ||
private BoundExpression BindDeclarationVariables(TypeSymbol declType, VariableDesignationSyntax node, DiagnosticBag 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.
Is this comment correct? From the body of the method, it's not clear that the declaration variable isn't permitted. #ByDesign
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.
While it is true that the code implements them, this is used only to bind them in contexts in which they are not currently permitted, via the method above which gives an error message. As you can see, the type inference (line 735 below) is short-circuited to produce an error type.
In reply to: 89843255 [](ancestors = 89843255)
builder.Add(BindDeclarationVariables(declType, n, diagnostics)); | ||
} | ||
var subExpressions = builder.ToImmutableAndFree(); | ||
var tupleType = (TypeSymbol)this.Compilation.CreateTupleTypeSymbol(subExpressions.Select<BoundExpression, ITypeSymbol>(e => e.Type).ToImmutableArray()); |
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.
Consider using TupleTypeSymbol
directly rather than ITypeSymbol
, etc.:
TupleTypeSymbol.Create(
null,
subExpressions.SelectAsArray(e => e.Type),
default(ImmutableArray<Location>),
default(ImmutableArray<string>,
Compilation);
``` #Resolved
} | ||
var subExpressions = builder.ToImmutableAndFree(); | ||
var tupleType = (TypeSymbol)this.Compilation.CreateTupleTypeSymbol(subExpressions.Select<BoundExpression, ITypeSymbol>(e => e.Type).ToImmutableArray()); | ||
return new BoundTupleLiteral(node, ImmutableArray<string>.Empty, subExpressions, tupleType); |
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 argumentNamesOpt
be default(ImmutableArray<string>)
rather than Empty
? #Resolved
// We only allow assignment-only or declaration-only deconstructions at this point. | ||
// Issue https://github.com/dotnet/roslyn/issues/15050 tracks allowing mixed deconstructions. | ||
// For now we give an error when you mix. | ||
Error(diagnostics, ErrorCode.ERR_MixedDeconstructionUnsupported, 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.
Please add a test for this case. #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.
There already is one: MixedDeconstruction_03
in DeconstructionTests.cs
In reply to: 89845635 [](ancestors = 89845635)
ERR_MixedDeconstructionUnsupported = 8184, | ||
ERR_DeclarationExpressionNotPermitted = 8185, | ||
ERR_MustDeclareForeachIteration = 8186, | ||
ERR_TupleElementNamesInDeconstruction = 8187, |
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.
Please add tests for each of these diagnostics. #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.
For ERR_MixedDeconstructionUnsupported: four tests in Emit\CodeGen\CodeGenDeconstructTests.cs, and two in Syntax\Parsing\DeconstructionTests.cs
for ERR_DeclarationExpressionNotPermitted: many tests in Emit\CodeGen\CodeGenTupleTest.cs, Semantic\Semantics\DeconstructionTests.cs, Semantic\Semantics\LocalFunctionTests.cs, Semantic\Semantics\OutVarTests.cs, and Semantic\Semantics\PatternSwitchTests.cs
for ERR_MustDeclareForeachIteration: two tests in Emit\CodeGen\CodeGenDeconstructTests.cs
for ERR_TupleElementNamesInDeconstruction: two tests in Emit\CodeGen\CodeGenDeconstructTests.cs
Are you saying that you don't think these tests are sufficient?
In reply to: 89845938 [](ancestors = 89845938)
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.
Sorry, I missed those tests since the webpage did not include those in the diff. #Resolved
@@ -255,7 +277,7 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics, | |||
hasErrors = hasErrors || iterationVariableType.IsErrorType(); | |||
|
|||
// Skip the conversion checks and array/enumerator differentiation if we know we have an error (except local name conflicts). | |||
if (hasErrors) | |||
if (hasErrors || _syntax.HasErrors) |
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.
Is the check for _syntax.HasErrors
necessary? What if the error is something simple such as missing in
token? #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.
I'm fine with suppressing semantic errors in the face of syntax errors, given that we've bound all the pieces of the syntax needed for a good IDE/SemanticModel experience.
In reply to: 89846888 [](ancestors = 89846888)
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'll change the syntax errors check to check for syntax errors only on the declaration part. #Resolved
This is now a semantic restriction (until we decide to remove it).
return (deconstruction == null) | ||
? (CommonForEachStatementSyntax)_syntaxFactory.ForEachStatement(@foreach, openParen, type, name, @in, expression, closeParen, statement) | ||
: (CommonForEachStatementSyntax)_syntaxFactory.ForEachVariableStatement(@foreach, openParen, deconstruction, @in, expression, closeParen, statement); | ||
private bool IsValidForeachVariable(ExpressionSyntax variable) |
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.
private [](start = 8, length = 7)
static
#Resolved
// differently, as we check for the comma before concluding that the identifier should cause a | ||
// disambiguation. For example, for the input `(A < B , C > D)`, we treat this as a tuple with | ||
// two elements, because if we considered the `A<B,C>` to be a type, it wouldn't be a tuple at | ||
// all. Since we don't have such as thing as a one-element tuple (even for deconstruction), the |
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.
such as thing [](start = 36, length = 13)
Typo "such as thing" vs. "such a thing"? #Closed
} | ||
|
||
// check for a designation | ||
if (!ScanDesignation(permitTupleDesignation && (lastTokenOfType.IsVar() || IsPredefinedType(lastTokenOfType.Kind)))) |
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.
lastTokenOfType.IsVar() [](start = 64, length = 23)
Will this condition do the right thing for a type name "A.var"? #Closed
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.
Probably not, as we'll want A.var(x, y)
to be an invocation expression. I'll revise it. #Resolved
return false; | ||
case SyntaxKind.IdentifierToken: | ||
var result = this.IsTrueIdentifier(); | ||
this.EatToken(); |
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.
this.EatToken(); [](start = 20, length = 16)
It doesn't feel appropriate to eat the token when we are about to return false. #Closed
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.
When we return false, the caller unwinds the trial parse, so it doesn't matter. #ByDesign
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 it would be cleaner and more intuitive if this function (and the like) wouldn't consume tokens it doesn't accept. #Closed
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.
That isn't possible given the way we scan forward and discard tokens before making a decision. Even if we don't eat the very last token, we will have eaten preceding tokens that we don't accept. Avoiding eating the very last token would be extra work that serves no purpose. #ByDesign
switch (this.CurrentToken.Kind) | ||
{ | ||
case SyntaxKind.CloseParenToken: | ||
this.EatToken(); |
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.
this.EatToken(); [](start = 32, length = 16)
It doesn't feel appropriate to eat the token when we are about to return false. #Closed
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.
As with other scan methods, it is unspecified what tokens have been eaten when it returns false. #ByDesign
@@ -5346,6 +5343,13 @@ private bool IsTrueIdentifier() | |||
return false; | |||
} | |||
|
|||
private bool IsTrueIdentifier(SyntaxToken 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.
IsTrueIdentifier [](start = 21, length = 16)
Should the method above delegate its work to this method? Otherwise, the methods have the same name, but appear to use different criteria. #Closed
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.
Good idea, but not quite so simple to do, as there are a series of helper methods for the previous method intended to help it disambiguate, implicitly based on the current token in declarations; it peeks forward using PeekToken(int)
and even does some trial forward parsing.
This method is for use in executable code (not declarations), so it has a much simpler implementation that depends only on the token passed in and this.IsInQuery
. I'll add some clarifying doc comments. #Resolved
if ((options & NameOptions.AfterIsOrCaseOrOutOrTupleComma) != 0 || | ||
(options & NameOptions.FirstElementOfPossibleTupleLiteral) != 0 && this.PeekToken(1).Kind == SyntaxKind.CommaToken) | ||
{ | ||
// we allow 'G<T,U> x' as a pattern-matching operation and a declaration pattern in a tuple. |
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.
declaration pattern [](start = 85, length = 20)
Typo "declaration pattern in a tuple"? #Closed
var type = this.ParseUnderlyingType(parentIsParameter: mode == ParseTypeMode.Parameter, options: nameOptions); | ||
|
||
if (this.CurrentToken.Kind == SyntaxKind.QuestionToken && | ||
(mode != ParseTypeMode.AfterIsOrCase || !IsTrueIdentifier(this.PeekToken(1)))) |
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.
(mode != ParseTypeMode.AfterIsOrCase || !IsTrueIdentifier(this.PeekToken(1)))) [](start = 16, length = 78)
Consider adding a comment explaining the rational behind this new condition. #Closed
if (tk == SyntaxKind.RefKeyword || | ||
(SyntaxFacts.IsPredefinedType(tk) && this.PeekToken(1).Kind != SyntaxKind.DotToken) || IsDeclarationModifier(tk)) | ||
if (tk == SyntaxKind.RefKeyword || IsDeclarationModifier(tk) || | ||
(SyntaxFacts.IsPredefinedType(tk) && this.PeekToken(1).Kind != SyntaxKind.DotToken && this.PeekToken(1).Kind != SyntaxKind.OpenParenToken)) |
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.
this.PeekToken(1).Kind != SyntaxKind.OpenParenToken [](start = 102, length = 51)
Consider adding a clarifying comment for this condition. #Closed
var assignment = (AssignmentExpressionSyntax)expression; | ||
if (assignment.Left.IsDeconstructionDeclarationLeft()) | ||
{ | ||
statement = this.AddError(statement, ErrorCode.ERR_BadEmbeddedStmt); |
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.
statement = this.AddError(statement, ErrorCode.ERR_BadEmbeddedStmt); [](start = 28, length = 68)
It is not clear why this error is no longer reported. Was there an explicit LDM decision? #Closed
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, the LDM explicitly decided to remove the language concept of a deconstruction declaration statement, which is where this restriction arises. We will discuss tomorrow if the LDM wants to add back any of these restrictions in C# 7, including the ones among the first changes in Binder_Deconstruct.cs
(lines 26-57 in this PR); as of the last LDM they wanted to remove all those restrictions. But when we do we will need additional tests. #ByDesign
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.
The way I read the response, and based on my recollection of the LDM discussion, the answer to my question "Was there an explicit LDM decision?" is No. Meaning the LDM did not make an explicit decision about this error. So, let's hold on on removing it until the decision is made. #Closed
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.
You misread the response. We did discuss the error, I raised the point that it is no longer an error if it is not a declaration when in the position of a controlled statement, and that was OK with Mads and others. If the LDM explicitly decides to change their mind and re-introduce an error here, I will do that. #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.
The LDM met yesterday and reconfirmed this. From the raw LDM notes:
Declarations in embedded statements?
Let's not add errors for deconstruction situations. In principle we probably want to remove even the existing limitation, but it's work we won't push for in C# 7.0.
#Resolved
@@ -7812,28 +7844,22 @@ private StatementSyntax ParseForOrForEachStatement() | |||
var resetPoint = this.GetResetPoint(); | |||
try | |||
{ | |||
if (this.CurrentToken.Kind == SyntaxKind.ForKeyword) | |||
Debug.Assert(this.CurrentToken.Kind == SyntaxKind.ForKeyword); |
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(this.CurrentToken.Kind == SyntaxKind.ForKeyword); [](start = 16, length = 62)
It looks like we already asserted this at the beginning of this function. #Closed
this.CurrentToken.Kind == SyntaxKind.CloseBracketToken) | ||
{ | ||
// convert `]` into `)` or vice versa for error recovery | ||
closeToken = this.ConsumeOneToken(closeKind); |
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.
this.ConsumeOneToken(closeKind) [](start = 33, length = 31)
Why consume the ']' or ')' if it's not the close kind expected? Is it more likely the user closed with the wrong kind or that the expected kind is missing? #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.
We currently parse a C++-style declaration
Type x(args, ...)
using the bracketed argument list, which our syntax trees support. If we don't turn the (
into a [
, then we get out of sync and will think the argument list is a tuple literal. And then we won't parse out
variable declarations properly. Doing the same substitution for the close paren reduces cascaded diagnostics. #Resolved
Should the list of kinds within this element be adjusted? #Closed Refers to: src/Compilers/CSharp/Portable/Syntax/Syntax.xml:2120 in c4d4991. [](commit_id = c4d4991, deletion_comment = False) |
@@ -99,7 +99,8 @@ protected override ImmutableArray<LocalSymbol> BuildLocals() | |||
case SyntaxKind.IdentifierName: | |||
break; | |||
default: | |||
throw ExceptionUtilities.UnexpectedValue(declaration.Kind()); | |||
ExpressionVariableFinder.FindExpressionVariables(this, locals, declaration); |
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.
ExpressionVariableFinder.FindExpressionVariables(this, locals, declaration); [](start = 20, length = 76)
Could you please add a comment about the scenario when we get here and point me to the test(s) that covers this line of code? #Closed
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.
Sure. The tests would be UnitTests.CodeGen.CodeGenDeconstructTests.MixedDeconstruction_06
, UnitTests.CodeGen.CodeGenDeconstructTests.ForeachIntoExpression
, and UnitTests.CodeGen.CodeGenDeconstructTests.MixedDeconstruction_05
. Comments in the next iteration.
In reply to: 91385737 [](ancestors = 91385737)
// absence of the comma after the `D` means we don't treat the `D` as contributing to the | ||
// disambiguation of the expression/type. More formally, ... | ||
// | ||
// If a sequence of tokens can be parsed(in context) as a* simple-name* (§7.6.3), *member-access* (§7.6.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.
member-access [](start = 90, length = 15)
Consider removing the **
annotations throughout this comment. #Closed
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'd prefer to keep the markup from the specification.
In reply to: 91392143 [](ancestors = 91392143)
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.
Is this a* simple-name*
intended markup, note position of the first *
? There are several similar places throughout this comment.
In reply to: 91453230 [](ancestors = 91453230,91392143)
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.
That is what is in the draft spec. I agree it could be improved ever so slightly. If this is what is holding up your approval of the code review, I think we should hold this set of changes until I am back in the office in January.
In reply to: 91570733 [](ancestors = 91570733,91453230,91392143)
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.
Let's not block on the markup here.
return result; | ||
if ((object)this._type == null) | ||
{ | ||
diagnostics.Add(this.ForbiddenDiagnostic, Locations[0], Name); |
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.
diagnostics.Add(this.ForbiddenDiagnostic, Locations[0], Name); [](start = 20, length = 62)
It is not clear why ForbiddenDiagnostic
is an appropriate diagnostics to use in this case. Also, could you please point me to the test(s) covering this line? #Closed
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 don't know of a way to trigger this defensive code. I'll remove it and let the assertion in the caller fail if it (_type == null) occurs.
In reply to: 91395018 [](ancestors = 91395018)
{ | ||
diagnostics.Add(this.ForbiddenDiagnostic, Locations[0], Name); | ||
SetType(new ExtendedErrorTypeSymbol( | ||
((SourceModuleSymbol)this.ContainingModule).DeclaringCompilation, name: "var", arity: 0, errorInfo: null, variableUsedBeforeDeclaration: 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.
variableUsedBeforeDeclaration: true) [](start = 130, length = 36)
Why does it make sense to set variableUsedBeforeDeclaration
to true here and what effect is this going to have? #Closed
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.
It wouldn't have any effect other than recording that the variable's type was required at a location before it was able to be inferred.
In reply to: 91395381 [](ancestors = 91395381)
Debug.Assert((object)this._type != null); | ||
if ((object)this._type == null) | ||
{ | ||
diagnostics.Add(this.ForbiddenDiagnostic, Locations[0], Name); |
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.
diagnostics.Add(this.ForbiddenDiagnostic, Locations[0], Name); [](start = 20, length = 62)
It is not clear why ForbiddenDiagnostic
is an appropriate diagnostics to use in this case. Also, could you please point me to the test(s) covering this line? #Closed
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.
It feels that ERR_TypeInferenceFailedForImplicitlyTypedOutVariable or the like would be more appropriate in this case. Also, it looks like there is no guarantee that this diagnostics is ever going to be surfaced to the user. It would be good to enforce that we are going to get here only for broken code (have syntax errors or something). I would prefer a throw, but an assert should be fine as well.
In reply to: 91395620 [](ancestors = 91395620)
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.
Indeed, diagnostics from this method are always discarded. I'll remove it.
This is covered by OutVarTests.OutVarDeconstruction_02
There isn't a mechanism to "enforce" that we only get here for broken code, because we don't have the necessary compilation diagnostics in hand. Ideas for doing that are welcome.
In reply to: 91397639 [](ancestors = 91397639,91395620)
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.
There isn't a mechanism to "enforce" that we only get here for broken code, because we don't have the necessary compilation diagnostics in hand. Ideas for doing that are welcome.
I believe we should never get here for an Out Var or a pattern variable. It should be fairly easy to detect such cases by examining the syntax. Please add the detection and a throw for them.
In reply to: 91455715 [](ancestors = 91455715,91397639,91395620)
@@ -7246,7 +7246,7 @@ public void M1() | |||
parseOptions: TestOptions.Regular); | |||
} | |||
|
|||
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] | |||
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/15508"), Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] |
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.
Skip = "#15508" [](start = 14, length = 54)
It is fine to merge with skipped test into a feature branch, but I think we should come up with solution or implement a workaround that prevents the crash before we merge this to master. #Closed
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.
Agree. This is an ask mode change to RC. We can't introduce new IDE regressions here without explicit IDE buy off. Otherwise this will not pass the ask mode review. #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.
That (not crashing) was the reason for the addition of "return false" in "CSharpTypeInferenceService.TypeInferrer.cs".
I'll adjust this test so it reflects the "broken" but non-crashing behavior.
In reply to: 91455957 [](ancestors = 91455957)
Done with review pass. A number of active comments remains, I think I reactivated a several existing threads as well. #Closed |
git repository authentication is broken again, so I can't push to the repository. When I can I'll send the next iteration, which addresses all comments. #Resolved |
More specifically, this is now the name of a kind of assignment expression in which the left-hand-side is of one of a couple of forms. In reply to: 265670754 [](ancestors = 265670754,265577755) Refers to: src/Compilers/CSharp/Portable/Parser/LanguageParser.cs:9220 in 1003470. [](commit_id = 1003470, deletion_comment = True) |
All comments have been addressed. May I have a second code review, please? |
@@ -670,9 +673,7 @@ protected override TypeSymbol InferTypeOfVarVariable(DiagnosticBag diagnostics) | |||
throw ExceptionUtilities.UnexpectedValue(_deconstruction.Kind()); | |||
} | |||
|
|||
TypeSymbol result = this._type; | |||
Debug.Assert((object)result != null); |
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((object)result != null); [](start = 16, length = 37)
Please restore the original assert. The earlier we detect the problem the better. #Closed
{ | ||
static void Main(string[] args) | ||
{ | ||
foreach (M(out var x1) in new[] { 1, 2, 3 }) |
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.
foreach (M(out var x1) in new[] { 1, 2, 3 }) [](start = 8, length = 44)
Please add similar test for a var
pattern variable. #Closed
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.
@@ -2570,7 +2570,7 @@ class C | |||
expectedIndentation: 8); | |||
} | |||
|
|||
[WpfFact, Trait(Traits.Feature, Traits.Features.SmartIndent)] | |||
[WpfFact(Skip = "test is no longer correct due to language changes"), Trait(Traits.Feature, Traits.Features.SmartIndent)] |
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.
[WpfFact(Skip = "test is no longer correct due to language changes") [](start = 8, length = 68)
Do we have an issue tracking this? #Closed
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.
Tracking what? Language changes? The deletion of this test?
In reply to: 91584597 [](ancestors = 91584597)
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 the test is skipped, a follow-up should follow. It can take many forms: remove, adjust, test new scenarios enabled by the change. Deciding what to do will be a part of resolving that issue, unless we can do that in context of this change.
In reply to: 91585635 [](ancestors = 91585635,91584597)
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 should not be disabling tests in this manner. If a test is disabled it needs a tracking issue. If it's no longer valid then it should be deleted and we should make the appropriate team (IDE in this case) aware of the change.
Debug.Assert((object)this._type != null); | ||
if ((object)this._type == null) | ||
{ | ||
SetType(_nodeBinder.CreateErrorType("var")); |
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.
SetType(_nodeBinder.CreateErrorType("var")); [](start = 20, length = 44)
There isn't a mechanism to "enforce" that we only get here for broken code, because we don't have the necessary compilation diagnostics in hand. Ideas for doing that are welcome.
I believe we should never get here for an Out Var or a pattern variable. It should be fairly easy to detect such cases by examining the syntax. Please add the detection and a throw for them. #Closed
I am done with review pass. The remaining issues that I think should be addressed are:
|
f9b33ce
to
3e0d9db
Compare
LGTM |
@dotnet-bot test linux_debug_prtest please |
and adjust parsing of argument lists.
BoundVoid
Fixes #15548Fixes #15549
Update (from jcouv): the bug numbers seem wrong. I think the correct ones were #14794
and #14832
/cc @jcouv @AlekseyTs @VSadov @dotnet/roslyn-compiler