Skip to content

Commit 0db49dd

Browse files
T-GroCopilot
andauthored
Add regression test: #6929, Literal bindings preserve units of measure (#19463)
* Add regression test for #6929: Literal bindings preserve units of measure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix: use local shouldSucceed wrapper instead of redundant pipeline The test was calling asLibrary |> typecheck |> shouldSucceed, but the local shouldSucceed function (which already does asLibrary/typecheck) was shadowing FSharp.Test.Compiler.shouldSucceed, causing a type mismatch (FS0001). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent fb1ca7e commit 0db49dd

2 files changed

Lines changed: 149 additions & 0 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
---
2+
applyTo:
3+
- "tests/FSharp.Compiler.ComponentTests/**/*.fs"
4+
---
5+
6+
# ComponentTests DSL
7+
8+
Tests use a pipeline: **Create → Configure → Action → Assert**. The action verb is mandatory — never pipe a `CompilationUnit` directly into an assertion.
9+
10+
## Actions (pick the cheapest that covers what you're testing)
11+
12+
```fsharp
13+
// Type errors only, no codegen — fastest
14+
FSharp "..."
15+
|> typecheck
16+
|> shouldSucceed
17+
18+
// Full compile, produces assembly
19+
FSharp "..."
20+
|> compile
21+
|> shouldSucceed
22+
23+
// IL shape verification (needs compile)
24+
FSharp "..."
25+
|> compile
26+
|> verifyILContains [".method"]
27+
28+
// Compile + execute (needs EntryPoint and asExe)
29+
FSharp "..."
30+
|> compileExeAndRun
31+
|> shouldSucceed
32+
33+
// FSI in-process
34+
Fsx "..."
35+
|> eval
36+
|> withEvalValueEquals 2
37+
38+
// FSI subprocess
39+
Fsx "..."
40+
|> runFsi
41+
|> withStdOutContains "hello"
42+
```
43+
44+
Use `typecheck` for anything that doesn't need IL or runtime. Use `compile` only when you need the assembly (IL checks, interop). Use `compileExeAndRun` only when testing runtime behavior.
45+
46+
## Diagnostics
47+
48+
```fsharp
49+
// Exact diagnostic with location and message
50+
FSharp "..."
51+
|> typecheck
52+
|> shouldFail
53+
|> withDiagnostics [
54+
(Error 73, Line 3, Col 5, Line 3, Col 10, "internal error: ...")
55+
(Warning 20, Line 5, Col 1, Line 5, Col 8, "The result of this expression...")
56+
]
57+
58+
// Just error code (when message/location don't matter)
59+
FSharp "..."
60+
|> typecheck
61+
|> shouldFail
62+
|> withErrorCode 73
63+
```
64+
65+
## C# interop
66+
67+
```fsharp
68+
let csLib =
69+
CSharp """public interface I { void M(out int v); }"""
70+
|> withName "CsLib"
71+
72+
FSharp """
73+
open CsLib
74+
type T() = interface I with member _.M(v) = v <- 42
75+
"""
76+
|> withReferences [csLib]
77+
|> compile
78+
|> shouldSucceed
79+
```
80+
81+
## Regression test template
82+
83+
```fsharp
84+
// https://github.com/dotnet/fsharp/issues/NNNNN
85+
[<Fact>]
86+
let ``Issue NNNNN - brief description`` () =
87+
FSharp """
88+
// minimal repro from issue
89+
"""
90+
|> asLibrary
91+
|> typecheck
92+
|> shouldSucceed
93+
```
94+
95+
## Local helpers
96+
97+
If configuration becomes long and boilerplate, extract a local helper or use an existing one in the same module:
98+
99+
```fsharp
100+
// Local helper for repeated configuration
101+
let typecheckWithPreview source =
102+
source
103+
|> asLibrary
104+
|> withLangVersionPreview
105+
|> withOptions ["--test:ErrorRanges"]
106+
|> typecheck
107+
108+
// Usage
109+
FSharp "..."
110+
|> typecheckWithPreview
111+
|> shouldSucceed
112+
```
113+
114+
## Common mistakes
115+
116+
- Missing action: `FSharp "..." |> shouldSucceed` — won't compile, `shouldSucceed` expects `CompilationResult`
117+
- Missing `asExe` for runtime tests: `FSharp "..." |> compile |> run` fails on library output
118+
- Using `compile` when `typecheck` suffices — wastes CI time
119+
120+
## Platform attributes
121+
122+
Use `[<Fact>]` unless the test requires a specific runtime:
123+
- `[<FactForNETCOREAPP>]` — .NET Core only
124+
- `[<FactForDESKTOP>]` — .NET Framework only
125+
- `[<FactForWINDOWS>]` — Windows only
126+
127+
## Workflow
128+
129+
1. Write test with explicit pipeline
130+
2. Build: `dotnet build tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj -c Release`
131+
3. Run: `dotnet test --project tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj -c Release --no-build -- --filter-method "*TestName*"`
132+
4. Format: `dotnet fantomas <file.fs>`

tests/FSharp.Compiler.ComponentTests/Conformance/UnitsOfMeasure/Constants/Constants.fs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,20 @@ module Constants =
4040
(Error 636, Line 22, Col 9, Line 22, Col 15, "Units-of-measure are only supported on float, float32, decimal, and integer types.")
4141
(Error 636, Line 23, Col 9, Line 23, Col 15, "Units-of-measure are only supported on float, float32, decimal, and integer types.")
4242
]
43+
44+
// https://github.com/dotnet/fsharp/issues/6929
45+
[<Fact>]
46+
let ``Issue 6929 - Literal bindings preserve units of measure`` () =
47+
FSharp
48+
"""
49+
[<Measure>] type rad
50+
51+
[<Literal>]
52+
let pi = 3.14<rad>
53+
54+
let a = pi
55+
56+
let f (x: float<rad>) = x
57+
let _ = f a
58+
"""
59+
|> shouldSucceed

0 commit comments

Comments
 (0)