-
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
let statement may break compatibility with a user-defined type named let #10624
Comments
People would be able to work around this by using |
It is used in the same position as |
Good point. The following code is valid and compiles with C# 6, so the C# 7 compiler ought to behave the same when encountering a public class Foo
{
static void Main()
{
var x = new var();
}
}
public class var {} However, there is a potential problem in handling the following code, which also shouldn't in a "x is readonly" type error: public class Foo
{
static void Main()
{
let x = new let();
x = new let();
}
}
public class let {} |
@DavidArno Re "People would be able to work around this by using Since they do not already do so, it would be a breaking change to require that. @bbarry Re "It is used in the same position as The contextual keyword |
And? Surely sometimes the team has to be pragmatic over the "never introduce a breaking change"? |
Should these be allowed?
To make it even more complicated, add #10642. |
Yes, as currently specified.
No, because the right-hand-side isn't a valid expression. Patterns do not "target-type" the expression.
No, there is only one pattern-match in the syntax.
Yes.
No, there is only one pattern-match in the syntax.
No, there is no "let expression". Or I have no idea what that
These are not declarators. They are patterns. |
So I suppose this is not exactly a shortcut for #115, since the semantics are quite different.
According to the latest spec (#10644) it's not. But the following is, let var x = e1 when x > 0 else return; Isn't this considered as inconsistent? If this is intended to work, perhaps
More to the point of this issue, right now
Identifier patterns within a value-binding pattern bind new named variables to their matching values. let (x, y) = e; // introduces variables `x` and `y` Value-binding patterns cannot be nested. let (let x, let y) = e; // illegal In pattern-matching context, |
I'm really confused by this. According to the spec:
This appears to be exactly what #115 is asking for (WRT read-only locals; it won't cover parameters). Am I missing something? |
@DavidArno Yes, but still you are matching the expression against a pattern (in this case, a var pattern) not a simple assignment, so it makes sense to don't "target-type" here. However, all bound variables will be read-only, hence the sentence "a convenient way for declaring a read-only local variable." |
Ah, that makes sense. The fact that the vars coming out of patterns are always read-only is something I'd missed. So that means that the following would be a compilation error? var t = (1,1);
switch (t)
{
case (var x, 1):
x = 2; // Cannot redefine `x`
... |
@DavidArno It's a little buried in the spec, but:
|
I would think user-defined types named "let" would be extremely rare, given that "let" is both lowercase and a verb. It's great that you take breaking changes so seriously, but in this case I think it's worth it. I really like the proposed use of the let keyword. |
I am very aware of this problem and go against the idea of let keyword from the start And we should reuse keyword Because it is already keyword so it backward compatible with old code
|
If the |
To clarify @HaloFour's point, the following is handled just fine by the compiler: class var {}
...
var x = 1;
var y = new var(); The compiler can determine that class let {}
...
let x = 1;
let y = new let(); The issue is that let (x, 1) = F(z) else return;
// z is now a read-only value returned in a tuple from F,
// only if the other value returned was 1. I'm not sure if I have the exact syntax right in the above, but it gives you the idea. So we have a choice: Opting for the second option strikes me as taking the "no breaking changes" rule to absurd extremes. |
@gafter Couldn't the parser take additional tokens into consideration when parsing the class let { }
void Foo() {
let x = 123; // CS0029 Cannot implicitly convert type 'int' to 'let'
let var x = 123; // fine
let int x = 123; // fine
let (int x, int y) = (123, 456); // fine
object o = x;
let int x = o else return; // fine
} |
That makes sense as a work-around, just so long as |
@DavidArno Exactly, it would only be necessary in that virtually non-existent case. To most people I'd feel bad for anyone working on a project where both |
It makes sense that there is an opposite extreme case to my own. I configure Resharper to report all uses of explicit types, that could be replaced with But even in that case, your |
The parser doesn't know whether or not there is a user-defined type named
let
, so it parses alet
statement assuming that no such type exists. As a practical matter than would break existing code that useslet
as the name of a type. Do we want to do anything about this?The text was updated successfully, but these errors were encountered: