dotnet / dotnet/fsharp

Funny behaviour for "member .. interface with .. end" on the same line

Open
#3,585 3 comments 0 reactions 0 assignees View on GitHub
Area-Compiler-Syntax Feature Improvement
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

Ok, this is about as low-priority as an issue can be. The only way I can imagine it _ever_ being a problem would require, I don't know, a code generation tool that steadfastedly refused to use newlines.

I almost didn't want to open this issue, but I figure there's always a chance it could help as a clue to some other, actually significant problems with the lexer. Also, I find it interesting because of how bizarre it is.

#### Repro steps

This code compiles:

type I =
abstract member M : int

type T0 = { F : string }
with
interface I with member __.M = 0 end
end

This code does _not_ compile, with squiggles under `interface`, the second `member`, and the second `end`:

type T1 = { F : string }
with
member x.M1 = 0 interface I with member __.M = 0 end
end

```
FS0010 Unexpected keyword 'interface' in expression. Expected incomplete structured construct at or before this point or other token.
FS0010 Incomplete structured construct at or before this point in member definition. Expected 'member', 'override' or other token.
FS0010 Unexpected keyword 'end' in type definition. Expected incomplete structured construct at or before this point or other token.
```

Ok, so you can't put an interface implementation on the same line as a member? Nope! This code _does_ compile:

type T2 = { F : string }
with
member x.M1 = 0 member x.M2 = 0 interface I with member __.M = 0 end
end

But add a third member and the same compilation errors re-appear:

type T3 = { F : string }
with
member x.M1 = 0 member x.M2 = 0 member x.M3 = 0 interface I with member __.M = 0 end
end

And so forth. `interface` after an even number of `member`s = OK, after an odd number of `member`s = error. (Tested up to n = 16.)

Note that only _immediately preceding_ members on the _same line_ matter. Adding members before or after the line has no effect on the above behaviour. For example, in this code, the first `interface` is fine but the second causes errors:

```
type T3a = { F : string }
with
member x.L = 0
member x.M1 = 0 member x.M2 = 0 interface I with member __.M = 0 end member x.M3 = 0 interface I2 with member __.M2 = 1 end
member x.N = 0
end
```

#### Expected behavior

All of the above examples should compile.

#### Known workarounds

- Don't commit crimes against basic coding standards
- Put `interface` on its own line
- Add `#light "off"`

#### Related information

I'm using the nightly release 15.4.1.17091101 on VS2017, but the issue appears just as easily on DotNetFiddle: https://dotnetfiddle.net/wsbL0f

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.