dotnet / dotnet/fsharp

Illegal prefix operators sometimes compile fine, but give confusing errors when applied

Open
#792 1 comment 0 reactions 1 assignee Claimed by @abelbraaksma View on GitHub
Area-Compiler-Syntax Bug Impact-Low
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

When trying to experimentally determine what operators can be overloaded as prefix operators (the [docs are sorely lacking and even misinforming, as this SO question shows](http://stackoverflow.com/questions/2304120/f-what-are-the-valid-prefix-operators)), I stumbled upon the following weird behavior:

```
let (?%) x = x + 1
let test = ?% 2
```

Two things to note:
1. In Visual Studio it shows as a warning (orange curly)
2. When compiled, or when hovering over it, it throws the error _"FS0010: Unexpected infix operator in binding"_ (which itself can be resolved by using parentheses around the operator)

According to the docs and the spec, at least what I make of it, a prefix operator must start with a `!`, a `~`, a `+` or a `-`. The above shows that a prefix operator can also start with a `?`, but this seems a bug (I mean, I think it should be disallowed), because:

```
let (?!) x = x + 1
```

will fail to compile, throwing the (expected) error _"FS1208: Invalid operator definition. Prefix operator definitions must use a valid prefix operator name."_.

I fully realize that I may not understand the docs or the spec well enough to know what prefix operators are illegal or not, but I think the above shows that there is at least some ambiguity to how the compiler treats the rules, and it shows that the docs seem incomplete.

To illustrate the latter, [MSDN F# operator precedence](https://msdn.microsoft.com/en-us/library/dd233228.aspx#Anchor_1) shows `+op` and `-op` as valid, but:

```
let (+^) a = a // compiles
let test = +^ 2 // throws FS1208: Invalid prefix operator
```

Again, this can be resolved by using parentheses, but here we see a _different_ error in a similar situation, besides, this situation uses an example from the docs (and it seems to me this is allowed by the spec as well), but fails to compile, unless you use parentheses (though I fail to see ambiguity issues here, nor precedence rule issues).

Finally, the last (different, again) error I noticed is with:

```
let (+.) a = a // compiles
let test = +. 2 // throws FS0001: The type 'int' does not support the operator '~+.'
// and throws FS0043: The type 'int' does not support the operator '~+.'
```

again solvable by using parentheses which, I think, are again not needed.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.