Skip to content

Semantic model APIs on declaration expressions and discards#16153

Merged
jcouv merged 11 commits into
dotnet:masterfrom
jcouv:decon-semantic
Jan 7, 2017
Merged

Semantic model APIs on declaration expressions and discards#16153
jcouv merged 11 commits into
dotnet:masterfrom
jcouv:decon-semantic

Conversation

@jcouv

@jcouv jcouv commented Dec 30, 2016

Copy link
Copy Markdown
Contributor

Customer scenario

Update semantic model APIs for declaration and discard expressions.

Bugs this fixes:

#15450

Workarounds, if any

Also, why we think they are insufficient for RC vs. RC2, RC3, or RTW

Risk

This is generally a measure our how central the affected code is to adjacent
scenarios and thus how likely your fix is to destabilize a broader area of code

Performance impact

(with a brief justification for that assessment (e.g. "Low perf impact because no extra allocations/no complexity changes" vs. "Low")

Is this a regression from a previous update?

No. Previously the semantic model would return no information for declaration expressions and discards. Now it does.

Root cause analysis:

How did we miss it? What tests are we adding to guard against it in the future?

How was the bug found?

Tracked work item.

@jcouv jcouv self-assigned this Dec 30, 2016
@jcouv jcouv added this to the 2.0 (RC.3) milestone Dec 30, 2016
@jcouv jcouv changed the title Decon semantic Semantic model APIs on declaration expressions and discards Dec 30, 2016
@jcouv jcouv force-pushed the decon-semantic branch 5 times, most recently from 219545b to ce28bd6 Compare January 5, 2017 18:51
@jcouv

jcouv commented Jan 5, 2017

Copy link
Copy Markdown
Contributor Author

@dotnet/roslyn-compiler This is ready for review. Thanks #Resolved

@gafter gafter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jcouv

jcouv commented Jan 6, 2017

Copy link
Copy Markdown
Contributor Author

@AlekseyTs If you can find some time, could you do the second review too? Thanks #Resolved

{
get
{
return new DiscardSymbol(this.Type);

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return new DiscardSymbol(this.Type); [](start = 16, length = 36)

Consider adding an assert that this.Type is not null. #Closed


var type = TupleTypeSymbol.Create(syntax.Location,
elementsBuilder.ToImmutableAndFree(), locationsBuilder.ToImmutableAndFree(),
elementNames: default(ImmutableArray<string>), compilation: this.Compilation, shouldCheckConstraints: false);

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldCheckConstraints: false [](start = 94, length = 29)

Consider adding a comment why constraints shouldn't be checked. #Closed

@jcouv jcouv Jan 6, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a comment.
This makes me think we could construct this final tuple only once. I'll file an issue. #Closed

@jcouv jcouv Jan 6, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed #16311 #Resolved

private BoundTupleLiteral DeconstructVariablesAsTuple(SyntaxNode syntax, ArrayBuilder<DeconstructionVariable> variables)
{
int count = variables.Count;
var argBuilder = ArrayBuilder<BoundExpression>.GetInstance(count);

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

argBuilder [](start = 16, length = 10)

elementValues or valuesBuilder? #Closed

{
int count = variables.Count;
var argBuilder = ArrayBuilder<BoundExpression>.GetInstance(count);
var elementsBuilder = ArrayBuilder<TypeSymbol>.GetInstance(count);

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elementsBuilder [](start = 16, length = 15)

typesBuilder? #Closed

@@ -690,7 +699,7 @@ internal BoundDeconstructionAssignmentOperator BindDeconstruction(
{
DeconstructionVariable locals = BindDeconstructionVariables(left, diagnostics, ref declaration, ref expression);

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BindDeconstructionVariables [](start = 44, length = 27)

Is there still an advantage of using NestedVariables? Could this function produce tuple literal right from the beginning instead of having to translate this structure later on? #Closed

@jcouv jcouv Jan 6, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need NestedVariables because the variables need to be updated (by the inference process). NestedVariables uses a builder, but tuple expression is immutable. #Resolved

(node is AttributeSyntax) ||
(node is CrefSyntax);
(node is CrefSyntax) ||
(node is DeclarationExpressionSyntax);

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(node is DeclarationExpressionSyntax) [](start = 24, length = 37)

Do we really need this extra condition? It feels like the very first condition should be good enough. #Closed

}

var symbol = GetDeclaredSymbol((SingleVariableDesignationSyntax)declaration.Designation, cancellationToken);
return new SymbolInfo(symbol);

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return new SymbolInfo(symbol) [](start = 16, length = 29)

Do we need to handle null symbol specially here? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I added it, but I'm having trouble to hit it with a test though.


In reply to: 95017393 [](ancestors = 95017393)

return GetBindableSyntaxNode(parent);

case SyntaxKind.DeclarationExpression:
case SyntaxKind.TupleExpression:

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case SyntaxKind.TupleExpression: [](start = 20, length = 32)

Are we certain that we can always bind these (both) expressions without knowing context? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed we need to remove this code. Thanks


In reply to: 95018184 [](ancestors = 95018184)


var discard1 = GetDiscardDesignations(tree).ElementAt(0);
Assert.Null(model.GetDeclaredSymbol(discard1));
Assert.Null(model.GetTypeInfo(discard1).Type);

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

model.GetTypeInfo(discard1) [](start = 24, length = 27)

Test GetSymbolInfo too? #Closed

var declaration1 = (DeclarationExpressionSyntax)discard1.Parent;
Assert.Equal("int _", declaration1.ToString());
//Assert.Equal("", model.GetTypeInfo(declaration1).Type.ToTestDisplayString()); // https://github.com/dotnet/roslyn/issues/15450
Assert.Equal("System.Int32", model.GetTypeInfo(declaration1).Type.ToTestDisplayString());

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

model.GetTypeInfo(declaration1) [](start = 41, length = 31)

Test GetSymbolInfo too? #Closed

var declaration2 = (DeclarationExpressionSyntax)discard2.Parent;
Assert.Equal("var _", declaration2.ToString());
//Assert.Equal("", model.GetTypeInfo(declaration2).Type.ToTestDisplayString()); // https://github.com/dotnet/roslyn/issues/15450
Assert.Equal("System.Int32", model.GetTypeInfo(declaration2).Type.ToTestDisplayString());

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

model.GetTypeInfo(declaration2) [](start = 41, length = 31)

Test GetSymbolInfo too? #Closed

var declaration1 = (DeclarationExpressionSyntax)discard1.Parent;
Assert.Equal("int _", declaration1.ToString());
//Assert.Equal("System.Int32", model.GetTypeInfo(declaration1).Type.ToTestDisplayString()); // https://github.com/dotnet/roslyn/issues/15450
Assert.Equal("System.Int32", model.GetTypeInfo(declaration1).Type.ToTestDisplayString());

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

model.GetTypeInfo(declaration1) [](start = 41, length = 31)

Test GetSymbolInfo too? #Closed

var declaration2 = (DeclarationExpressionSyntax)discard2.Parent;
Assert.Equal("var _", declaration2.ToString());
//Assert.Equal("System.Int32", model.GetTypeInfo(declaration2).Type.ToTestDisplayString()); // https://github.com/dotnet/roslyn/issues/15450
Assert.Equal("System.Int32", model.GetTypeInfo(declaration2).Type.ToTestDisplayString());

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

model.GetTypeInfo(declaration2) [](start = 41, length = 31)

Test GetSymbolInfo too? #Closed

var discard3 = GetDiscardIdentifiers(tree).First();
var symbol = (IDiscardSymbol)model.GetSymbolInfo(discard3).Symbol; // returns null https://github.com/dotnet/roslyn/issues/15450
//Assert.Equal("System.Int32", symbol.Type.ToTestDisplayString());
var discard3Symbol = (IDiscardSymbol)model.GetSymbolInfo(discard3).Symbol;

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

model.GetSymbolInfo(discard3) [](start = 49, length = 29)

Test GetTypeInfo too? #Closed

var declaration2 = (DeclarationPatternSyntax)discard2.Parent;
Assert.Equal("var _", declaration2.ToString());
//Assert.Equal("", model.GetTypeInfo(declaration2).Type.ToTestDisplayString()); // https://github.com/dotnet/roslyn/issues/15450
Assert.Null(model.GetTypeInfo(declaration2).Type);

@AlekseyTs AlekseyTs Jan 6, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

model.GetTypeInfo(declaration2) [](start = 24, length = 31)

Test GetSymbolInfo too, if applicable? #Closed

@AlekseyTs

AlekseyTs commented Jan 6, 2017

Copy link
Copy Markdown
Contributor

Done with review pass. #Closed

@jcouv jcouv force-pushed the decon-semantic branch 2 times, most recently from a80e3b8 to af52303 Compare January 6, 2017 23:16

var discard1 = GetDiscardDesignations(tree).ElementAt(0);
Assert.Null(model.GetDeclaredSymbol(discard1));
Assert.Equal(null, model.GetSymbolInfo(discard1).Symbol);

@AlekseyTs AlekseyTs Jan 7, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert.Equal(null, [](start = 12, length = 18)

Assert.Null? #Closed

//Assert.Equal("System.Int32", symbol.Type.ToTestDisplayString());
Assert.Equal("System.Int32", model.GetTypeInfo(discard3).Type.ToTestDisplayString());
var discard3Symbol = (IDiscardSymbol)model.GetSymbolInfo(discard3).Symbol;
Assert.Equal("System.Int32", discard3Symbol.Type.ToTestDisplayString());

@AlekseyTs AlekseyTs Jan 7, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discard3Symbol.Type.ToTestDisplayString() [](start = 41, length = 41)

Print symbol instead? #Closed

{
var symbolInfo = model.GetSymbolInfo(decl);
Assert.Null(symbolInfo.Symbol);
if (expectedSymbol != null)

@AlekseyTs AlekseyTs Jan 7, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (expectedSymbol != null) [](start = 11, length = 28)

Please remove the 'if', we should assert that we get null when null is expected. #Closed

var typeInfo = model.GetTypeInfo(decl);
Assert.Null(typeInfo.Type);
Assert.Null(typeInfo.ConvertedType);
if (expectedType != null)

@AlekseyTs AlekseyTs Jan 7, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (expectedType != null) [](start = 12, length = 25)

Remove if? #Closed

@AlekseyTs

Copy link
Copy Markdown
Contributor

LGTM

@jcouv

jcouv commented Jan 7, 2017

Copy link
Copy Markdown
Contributor Author

@srivatsn for ask mode approval. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants