Skip to content

Support --typecheck-only for fsi run (just typecheck, no execution) #18686

Description

@T-Gro

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:

lettcState,topCustomAttrs,declaredImpls,tcEnvAtEndOfLastInput =
lock tcLockObject (fun _ ->
CheckClosedInputSet(
ctok,(fun()-> diagnosticsLogger.CheckForRealErrorsIgnoringWarnings),
tcConfig,
tcImports,
tcGlobals,
Some prefixPath,
tcState,
eagerFormat,
inputs
))// Add this check after CheckClosedInputSetif tcConfig.typeCheckOnly then
raise StopProcessing
letcodegenResults,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

moduleFSharp.Compiler.ComponentTests.Scripting.TypeCheckOnlyTestsopenXunitopenFSharp.TestopenFSharp.Test.Compiler[<Fact>]let``typecheck-only flag works for valid script``()=
Fsx """let x = 42printfn "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:

<CompileInclude="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

  1. The --typecheck-only flag already exists in the core F# compiler configuration (TcConfigBuilder), so you're primarily adding FSI-specific handling.

  2. The ProcessInputs function is the correct location for this check because it occurs after parsing and type-checking but before code generation and execution.

  3. The StopProcessing exception mechanism is already established in FSI for handling compilation-stopping conditions.

  4. 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

Projects

Status
New

Relationships

None yet

Development

No branches or pull requests

Issue actions