{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/14794","repository_url":"https://api.github.com/repos/dotnet/roslyn","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/14794/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/14794/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/14794/events","html_url":"https://github.com/dotnet/roslyn/issues/14794","id":185987956,"number":14794,"title":"Proposed changes for deconstruction, declaration expressions, and wildcards","user":{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},"labels":[{"id":166673288,"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Compilers","name":"Area-Compilers","color":"5319e7","default":false},{"id":169838071,"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Language%20Design","name":"Area-Language Design","color":"5319e7","default":false},{"id":168328784,"url":"https://api.github.com/repos/dotnet/roslyn/labels/Design%20Notes","name":"Design Notes","color":"fc2929","default":false},{"id":258871715,"url":"https://api.github.com/repos/dotnet/roslyn/labels/Feature%20Specification","name":"Feature Specification","color":"fc2929","default":false},{"id":166377946,"url":"https://api.github.com/repos/dotnet/roslyn/labels/Language-C%23","name":"Language-C#","color":"207de5","default":false},{"id":359270827,"url":"https://api.github.com/repos/dotnet/roslyn/labels/New%20Language%20Feature%20-%20Out%20Variable%20Declaration","name":"New Language Feature - Out Variable Declaration","color":"bfd4f2","default":false},{"id":326633537,"url":"https://api.github.com/repos/dotnet/roslyn/labels/New%20Language%20Feature%20-%20Pattern%20Matching","name":"New Language Feature - Pattern Matching","color":"bfd4f2","default":false},{"id":332342663,"url":"https://api.github.com/repos/dotnet/roslyn/labels/New%20Language%20Feature%20-%20Tuples","name":"New Language Feature - Tuples","color":"bfd4f2","default":false}],"state":"open","locked":false,"assignee":{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},"assignees":[{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},{"login":"MadsTorgersen","id":6677272,"avatar_url":"https://avatars.githubusercontent.com/u/6677272?v=3","gravatar_id":"","url":"https://api.github.com/users/MadsTorgersen","html_url":"https://github.com/MadsTorgersen","followers_url":"https://api.github.com/users/MadsTorgersen/followers","following_url":"https://api.github.com/users/MadsTorgersen/following{/other_user}","gists_url":"https://api.github.com/users/MadsTorgersen/gists{/gist_id}","starred_url":"https://api.github.com/users/MadsTorgersen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MadsTorgersen/subscriptions","organizations_url":"https://api.github.com/users/MadsTorgersen/orgs","repos_url":"https://api.github.com/users/MadsTorgersen/repos","events_url":"https://api.github.com/users/MadsTorgersen/events{/privacy}","received_events_url":"https://api.github.com/users/MadsTorgersen/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/dotnet/roslyn/milestones/24","html_url":"https://github.com/dotnet/roslyn/milestones/2.0%20(RC.2)","labels_url":"https://api.github.com/repos/dotnet/roslyn/milestones/24/labels","id":2090735,"number":24,"title":"2.0 (RC.2)","description":"","creator":{"login":"jaredpar","id":146967,"avatar_url":"https://avatars.githubusercontent.com/u/146967?v=3","gravatar_id":"","url":"https://api.github.com/users/jaredpar","html_url":"https://github.com/jaredpar","followers_url":"https://api.github.com/users/jaredpar/followers","following_url":"https://api.github.com/users/jaredpar/following{/other_user}","gists_url":"https://api.github.com/users/jaredpar/gists{/gist_id}","starred_url":"https://api.github.com/users/jaredpar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaredpar/subscriptions","organizations_url":"https://api.github.com/users/jaredpar/orgs","repos_url":"https://api.github.com/users/jaredpar/repos","events_url":"https://api.github.com/users/jaredpar/events{/privacy}","received_events_url":"https://api.github.com/users/jaredpar/received_events","type":"User","site_admin":false},"open_issues":200,"closed_issues":47,"state":"open","created_at":"2016-10-24T21:54:24Z","updated_at":"2016-11-08T02:59:46Z","due_on":null,"closed_at":null},"comments":82,"created_at":"2016-10-28T18:18:49Z","updated_at":"2016-11-08T03:03:52Z","closed_at":null,"body":"This week's LDM meetings (2016-10-25 and 2016-10-26) proposed some possible changes to the handling of deconstruction, declaration expressions, and wildcards that, even if done later, would affect the shape of compiler APIs today. That suggests we would want to consider what to do today so that we are compatible with that possible future. This is a summary of the proposed changes and their API impact.\n### Wildcards\n\nThe LDM is proposing to change the character that we would use to represent a \"wildcard\" from `*` to `_`. We also considered some alternatives, but both `*` and `?` have a logical (if not technical) ambiguity, because `int?` and `int*` are valid types. `_` doesn't likely have the same kind of syntactic ambiguity, because it is already an identifier in all of the places where we want to support wildcards. But it may be a _semantic_ ambiguity for that  same reason. The reason we like `_` is that users already introduce variables, for example parameters, named `_` when their intention is to ignore them.\n\nWe want to support both the \"short form\" `_` and the \"long form\" `var _` just in case there is an ambiguity with, for example, a field in scope. We'll return to this later.\n### Declaration Expressions\n\nWe currently represent an out variable declaration using a \"declaration expression\" node in the syntax model. That was done because we were thinking that we may want to generalize declaration expressions in the future.\n\nThere is some slight discomfort with declaration expressions as they appear in the current API and proposed language spec, because while they are expressions in the syntax model, they are not expressions in the draft spec, and do not have types, and therefore there are special rules called out for them wherever they may appear in the specification. Besides the mismatch between the spec and model, we expect we may want to allow declaration expressions in more contexts in the future, in which case we will want them to be treated as expressions. In that case we will be better served by treating them as expressions (i.e. they can have a type) today.\n### Deconstruction\n\nPossibly generalizing declaration expressions in the future makes us want to reconsider our syntax model for deconstruction today. For example, given the statement\n\n``` cs\n(int x, int y) = e;\n```\n\nWe can think of this as a special deconstruction declaration statement (as it is today), or alternatively we can think of it as a statement expressions containing an assignment expression with a tuple expression on the left-hand-side. In that case the tuple expression contains two declaration expressions. The latter formulation makes more sense in the possible future in which we generalize declaration expressions.\n\nSimilarly, given the statement\n\n``` cs\nvar (x, y) = e;\n```\n\nWe can think of this as a special deconstruction declaration statement (as it is today), or alternatively we can think of it as a statement expressions containing an assignment expression with a declaration expression on the left-hand-side. The latter formulation makes more sense in the possible future in which we generalize declaration expressions.\n\nThis reformulation of deconstruction allows us to remove from the syntax model the new statement form for a deconstruction declaration. It also allows us to generalize what we allow in the future:\n\n``` cs\nint x;\n(x, int y) = e;\n```\n\nHere, the left-hand-side contains a mixture of already-existing variables (in this case `x`) and newly declared variables (`int y`). And it can be used in an expression context as well (e.g. as the body of an expression-bodied method).\n### Wildcards (revisited)\n\nGiven this new understanding of the direction of the syntax, there are four forms that wildcards can take. First, it can take the place of an identifier in a _designator_ (i.e. in a declaration expression):\n\n``` cs\nvar (x, _) = e;\n(int x, int _) = e;\nM(out int _);\n```\n\nSince `_` is already an identifier, no syntax model change is required. However, semantically we want this to create an anonymous variable, and shadow any true variable (e.g. parameter or field) from an enclosing scope named `_`. There is no name conflict error if wildcards are declared this way more than once in a scope.\n\nSecond, it can similarly be used to declare a pattern variable:\n\n``` cs\nswitch (o)\n{\n    case int _:\n    case long _:\n        Console.WriteLine(\"int or long\");\n        break;\n}\n```\n\nThird, it can take the place of an identifier in a simple expression where an lvalue is expected and is used as a target in a deconstruction assignment or out parameter, but in that case its special behavior as a wildcard only occurs if looking up `_` doesn't find a variable of that name\n\n``` cs\nM(out _);\n(x, _) = e;\n```\n\nThis special name lookup is similar to the way we handle `var`.\n\nFinally, it can be used where a parameter can be declared today. However, we relax the single-definition rule to allow multiple conflicting declarations (same scope or nested scopes), in which case the identifier `_` binds as a wildcard.\n\n``` cs\nFunc<int, int, int> f = (_,_) => 3;\n```\n\nWe have to be careful with these changes so that any program that uses `_` as an identifier and is legal today continues to compile with the same meaning under these revised rules. \n### Syntax model changes\n\nThis allows us to simplify the handling of the `for` loop to handle deconstruction. Now the deconstruction is just one of the expressions in the expression list of the initializer part, and doesn't require its own placeholder in the syntax. That means that the syntax node for the `for` loop remains unchanged from the C# 6 version.\n\nThis requires a change to the way we handle the deconstruction form of the `foreach` loop. Because we want the left-hand-side to be capable of representing all of these forms\n\n``` cs\nforeach ((int x, int y) in e) ...\nforeach ((int x, _) in e) ...\nforeach (var (x, _) in e) ...\n```\n\nwe now need to use _expression_ for the syntax node before the `in` keyword.\n\nWe can remove the syntax node for the _deconstruction declaration statement_, because that is just an assignment statement in this model.\n### Syntax.xml changes\n\nThe following changes are proposed compared to the current [implementation in master](https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/Syntax/Syntax.xml). We **remove**\n\n``` xml\n  <AbstractNode Name=\"VariableComponentSyntax\" Base=\"CSharpSyntaxNode\">\n  </AbstractNode>\n  <Node Name=\"TypedVariableComponentSyntax\" Base=\"VariableComponentSyntax\">\n    <Kind Name=\"TypedVariableComponent\"/>\n    <Field Name=\"Type\" Type=\"TypeSyntax\"/>\n    <Field Name=\"Designation\" Type=\"VariableDesignationSyntax\"/>\n  </Node>\n  <Node Name=\"ParenthesizedVariableComponentSyntax\" Base=\"VariableComponentSyntax\">\n    <Kind Name=\"ParenthesizedVariableComponent\"/>\n    <Field Name=\"OpenParenToken\" Type=\"SyntaxToken\">\n      <Kind Name=\"OpenParenToken\"/>\n    </Field>\n    <Field Name=\"Variables\" Type=\"SeparatedSyntaxList&lt;VariableComponentSyntax&gt;\"/>\n    <Field Name=\"CloseParenToken\" Type=\"SyntaxToken\">\n      <Kind Name=\"CloseParenToken\"/>\n    </Field>\n  </Node>\n  <Node Name=\"DeconstructionDeclarationStatementSyntax\" Base=\"StatementSyntax\">\n    <Kind Name=\"DeconstructionDeclarationStatement\"/>\n    <Field Name=\"Modifiers\" Type=\"SyntaxList&lt;SyntaxToken&gt;\"/>\n    <Field Name=\"Assignment\" Type=\"VariableComponentAssignmentSyntax\"/>\n    <Field Name=\"SemicolonToken\" Type=\"SyntaxToken\">\n      <Kind Name=\"SemicolonToken\"/>\n    </Field>\n  </Node>\n  <Node Name=\"VariableComponentAssignmentSyntax\" Base=\"CSharpSyntaxNode\">\n    <Kind Name=\"VariableComponentAssignment\"/>\n    <Field Name=\"VariableComponent\" Type=\"VariableComponentSyntax\"/>\n    <Field Name=\"EqualsToken\" Type=\"SyntaxToken\">\n      <Kind Name=\"EqualsToken\"/>\n    </Field>\n    <Field Name=\"Value\" Type=\"ExpressionSyntax\"/>\n  </Node>\n```\n\nand we remove the `Deconstruction` field from the `ForStatementSyntax`\n\nWe change the `VariableComponent` field of `ForEachComponentStatementSyntax` to be an `ExpressionSyntax`, and probably change the name of `ForEachComponentStatementSyntax`.\n\nAnd we change\n\n``` xml\n  <Node Name=\"DeclarationExpressionSyntax\" Base=\"ExpressionSyntax\">\n    <Kind Name=\"DeclarationExpression\"/>\n    <Field Name=\"VariableComponent\" Type=\"VariableComponentSyntax\">\n    </Field>\n  </Node>\n```\n\nto\n\n``` xml\n  <Node Name=\"DeclarationExpressionSyntax\" Base=\"ExpressionSyntax\">\n    <Kind Name=\"DeclarationExpression\"/>\n    <Field Name=\"Type\" Type=\"TypeSyntax\"/>\n    <Field Name=\"Designation\" Type=\"VariableDesignationSyntax\"/>\n  </Node>\n```\n\nWe leave unchanged\n\n``` xml\n  <AbstractNode Name=\"VariableDesignationSyntax\" Base=\"CSharpSyntaxNode\">\n  </AbstractNode>\n  <Node Name=\"SingleVariableDesignationSyntax\" Base=\"VariableDesignationSyntax\">\n    <Kind Name=\"SingleVariableDesignation\"/>\n    <Field Name=\"Identifier\" Type=\"SyntaxToken\">\n      <Kind Name=\"IdentifierToken\"/>\n    </Field>\n  </Node>\n  <Node Name=\"ParenthesizedVariableDesignationSyntax\" Base=\"VariableDesignationSyntax\">\n    <Kind Name=\"ParenthesizedVariableDesignation\"/>\n    <Field Name=\"OpenParenToken\" Type=\"SyntaxToken\">\n      <Kind Name=\"OpenParenToken\"/>\n    </Field>\n    <Field Name=\"Variables\" Type=\"SeparatedSyntaxList&lt;VariableDesignationSyntax&gt;\"/>\n    <Field Name=\"CloseParenToken\" Type=\"SyntaxToken\">\n      <Kind Name=\"CloseParenToken\"/>\n    </Field>\n  </Node>\n```\n### SemanticModel changes\n\nWe may want to change the behavior of `GetTypeInfo` on a declaration expression, depending on how the shape of the specification evolves.\n\nWe probably need to consider what the behavior of `SemanticModel` APIs should be on wildcards.\n### Summary\n\nThe changes to declaration expressions and deconstruction should be done today so that we don't have an incompatible change later.\n\nWildcards are an interesting problem. Even if we don't want to implement them for C# 7, we want to wall off the semantic space so that valid C# 7 programs don't change meaning or become invalid in a later language version. I suspect the simplest way to do that is to implement wildcards today.\n\n/cc @dotnet/ldm @dotnet/roslyn-compiler \n"},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/259032524","html_url":"https://github.com/dotnet/roslyn/issues/14794#issuecomment-259032524","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/14794","id":259032524,"user":{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},"created_at":"2016-11-08T03:03:52Z","updated_at":"2016-11-08T03:03:52Z","body":"In case you don't know the story of Mads and me with the `@` character, see http://gafter.blogspot.com/2007/01/primate-parts.html"}}
{"actor":{"display_login":"gafter"}}