-
Notifications
You must be signed in to change notification settings - Fork 796
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
byref
parameters starting with some non-ASCII identifiers cannot be set.
#18164
Comments
byref
parameters with non-ASCII identifiers cannot be set.byref
parameters with starting with some non-ASCII identifiers cannot be set.
byref
parameters with starting with some non-ASCII identifiers cannot be set.byref
parameters starting with some non-ASCII identifiers cannot be set.
That seems pretty unlikely to me to be by design. |
The AST is different for these two: let f (a叉: int byref) = a叉 <- a叉 + 1 let f (叉: int byref) = 叉 <- 叉 + 1
I believe that comes from here: Lines 3763 to 3769 in c4d36d6
and here: fsharp/src/Compiler/Utilities/illib.fs Lines 745 to 760 in c4d36d6
Edit: see #18164 (comment). We should really probably be calling open System.Text
let s = "叉"
for rune in s.EnumerateRunes () do
printfn $"Rune: {rune}. Is upper: %A{Rune.IsUpper rune}." // Rune: 叉. Is upper: false. Too bad we don't have runes in netstandard2.0... I guess we probably shouldn't try to add a full port of that to the compiler (e.g., stealing the logic from here, here, here, etc.), but otherwise I'm not sure what a suitable compromise between what we have now (which is just wrong for some inputs) and |
Edit: see #18164 (comment). ...Actually, maybe something like this would be good enough? (Edit: forgot the unicameral script part. But still, I think it might be workable.) let isLeadingIdentifierCharacterUpperCase (s: string) =
let isAscii c = uint c <= 0x007fu
let isInRangeInclusive value (lo, hi) = (value - lo) <= (hi - lo)
if s.Length = 0 then false
elif isAscii s[0] then isInRangeInclusive s[0] ('A', 'Z')
else Globalization.CharUnicodeInfo.GetUnicodeCategory (s, 0) = Globalization.UnicodeCategory.UppercaseLetter Compare: |
Oh, duh. That is used to allow unicameral scripts (scripts that have no upper-case) to be used for identifiers in places where identifiers starting with an upper-case grapheme are otherwise required, e.g., In order to be able to use such identifiers in patterns in the same way as identifiers actually starting with upper-case graphemes, they must always be parsed as such. E.g., type U = A | 叉 | हिन्दी
let f (x : U) =
match x with
| A -> …
| 叉 -> …
| हिन्दी -> … requires that those identifiers be parsed the same way in any other pattern context, including as parameters: let f (A | 叉 | हिन्दी) = () Note that this also fails to compile: > let f (A : int byref) = A <- A + 1;;
let f (A : int byref) = A <- A + 1;;
------------------------^^^^^^^^^^
stdin(1,25): error FS0027: This value is not mutable. Consider using the mutable keyword, e.g. 'let mutable A = expression'. So we probably shouldn't change the AST, but we ought to be able to make the type-checking work for this. This works just fine, for example: let f () =
let mutable A = 3
A <- A + 1 ...Playing around some more, there are some additional oddities with the typechecking of set This fails with an internal error, for example: let f a =
let mutable A = a
A <- A
// error FS0073: internal error: Undefined or unsolved type variable: 'a While even this fails with "error FS0971: Undefined value 'a'": let f () =
let mutable a = 3
a <- a
// error FS0971: Undefined value 'a' |
So yeah, as @ijklam pointed out in #18164 (comment), basically the arg pat being parsed as a When that synthetic match expression is typechecked, the When the I don't see an easy way around this without a more invasive change. But maybe I'm not being creative enough? (I tried a few things, like emitting a synthetic mutable let-binding instead of a match. That indeed fixes this scenario—but of course it then incorrectly allows any non-lower-case identifier used in a pattern to be treated as mutable 🙃.) |
byref
parameters whose identifier starting with some non-ASCII (like Chinese characters) cannot be set.Repro steps
Enter this code in fsi:
Expected behavior
The code can be compiled successfully
Actual behavior
A
FS0027
was thrown.Known workarounds
Don't use non-ASCII identifiers.
Related information
Provide any related information (optional):
The text was updated successfully, but these errors were encountered: