Description
Instructions for Adding --typecheck-only
Support to F# Interactive Scripts
Problem Statement
The --typecheck-only
flag already exists for F# project compilation but is not supported for .fsx
script files in F# Interactive (FSI). Currently, there's no way to type-check scripts without executing them through the FSI command line. This feature would allow developers to validate script syntax and types without running potentially side-effect-producing code.
Implementation Steps
1. Add Command Line Option
Add the --typecheck-only
option to the FSI command line parser. Insert a new CompilerOption
in the advanced options section:
CompilerOption("typecheck-only", "", OptionUnit(fun () -> tcConfigB.typeCheckOnly <- true), None, Some("Type-check only, don't execute"))
This should be added alongside other advanced options like exec
, gui
, quiet
, etc.
2. Modify ProcessInputs Function
The core implementation goes in the ProcessInputs
function. In 2 , add a check after CheckClosedInputSet
and before ProcessTypedImpl
:
let tcState, topCustomAttrs, declaredImpls, tcEnvAtEndOfLastInput =
lock tcLockObject (fun _ ->
CheckClosedInputSet(
ctok,
(fun () -> diagnosticsLogger.CheckForRealErrorsIgnoringWarnings),
tcConfig,
tcImports,
tcGlobals,
Some prefixPath,
tcState,
eagerFormat,
inputs
))
// Add this check after CheckClosedInputSet
if tcConfig.typeCheckOnly then
raise StopProcessing
let codegenResults, optEnv, fragName =
ProcessTypedImpl(...)
3. Exception Handling
The StopProcessing
exception is already handled . This infrastructure will properly catch the exception and stop processing without executing the script.
Testing Implementation
Test Location and Structure
All tests should be added to the FSharp.Compiler.ComponentTests
project.
Create a new test file:
tests/FSharp.Compiler.ComponentTests/Scripting/TypeCheckOnlyTests.fs
Test Implementation
module FSharp.Compiler.ComponentTests.Scripting.TypeCheckOnlyTests
open Xunit
open FSharp.Test
open FSharp.Test.Compiler
[<Fact>]
let ``typecheck-only flag works for valid script``() =
Fsx """
let x = 42
printfn "This should not execute"
"""
|> withOptions ["--typecheck-only"]
|> compile
|> shouldSucceed
[<Fact>]
let ``typecheck-only flag catches type errors``() =
Fsx """
let x: int = "string" // Type error
"""
|> withOptions ["--typecheck-only"]
|> compile
|> shouldFail
|> withDiagnostics [
(Error 1, Line 2, Col 14, Line 2, Col 22, "This expression was expected to have type\n 'int' \nbut here has type\n 'string'")
]
[<Fact>]
let ``typecheck-only flag prevents execution side effects``() =
Fsx """
System.IO.File.WriteAllText("test-file.txt", "should not be created")
let x = 42
"""
|> withOptions ["--typecheck-only"]
|> compile
|> shouldSucceed
// Verify file was not created (test would need additional verification logic)
Project File Update
Add the new test file:
<Compile Include="Scripting/TypeCheckOnlyTests.fs" />
Test Utilities
The ComponentTests project references Test utilities , which provides testing utilities like Fsx
, withOptions
, compile
, shouldSucceed
, and shouldFail
.
Key Implementation Notes
-
The
--typecheck-only
flag already exists in the core F# compiler configuration (TcConfigBuilder
), so you're primarily adding FSI-specific handling. -
The
ProcessInputs
function is the correct location for this check because it occurs after parsing and type-checking but before code generation and execution. -
The
StopProcessing
exception mechanism is already established in FSI for handling compilation-stopping conditions. -
All new tests should use the ComponentTests project following modern F# testing practices.
This implementation will allow users to run fsi --typecheck-only script.fsx
to validate script correctness without execution.
Metadata
Metadata
Assignees
Type
Projects
Status