Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scoped nowarn #18049

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7498b0b
WarnScopes (1): feature flag, baseline tests, and WarnScopes module
Martin521 Nov 22, 2024
9590899
WarnScopes (2): changes to lexing and parsing
Martin521 Nov 22, 2024
7b2eeb2
WarnScopes (3): remove legacy #nowarn processing
Martin521 Nov 22, 2024
4520e55
WarnScopes (4): integrate the new functionality and add tests
Martin521 Nov 22, 2024
0fdaa43
WarnScopes (5): add warn directive trivia
Martin521 Nov 22, 2024
fb848d9
WarnScopes (6): enable warn directive trivia
Martin521 Nov 22, 2024
e623fde
WarnScopes (7): remove defunct types and parameters
Martin521 Nov 22, 2024
62eb32a
WarnScopes (8): IlVerify baseline update
Martin521 Nov 22, 2024
5c77ecd
WarnScopes (9): ran fantomas, updated release notes
Martin521 Nov 22, 2024
bbdea9d
updated PR number in release notes
Martin521 Nov 22, 2024
1c97f60
adapted scipt test to WarnScopes
Martin521 Nov 22, 2024
ca6fd7a
updated PR link in release notes (now really)
Martin521 Nov 22, 2024
0d0e7bf
Merge remote-tracking branch 'upstream/main' into scoped-nowarn-dev
Martin521 Nov 22, 2024
29212c5
skipped a test in vsintegration that might need a vs update
Martin521 Nov 25, 2024
6c3ab12
Merge remote-tracking branch 'upstream/main' into scoped-nowarn-dev
Martin521 Nov 25, 2024
ceb7e38
Merge remote-tracking branch 'upstream/main' into scoped-nowarn-dev
Martin521 Nov 25, 2024
23e366f
merge upstream/main
Martin521 Nov 26, 2024
a727e67
moved ilverify baselines
Martin521 Nov 26, 2024
cdfef12
Merge remote-tracking branch 'upstream/main' into scoped-nowarn
Martin521 Nov 27, 2024
e8a35f4
merge upstream/main
Martin521 Nov 29, 2024
2214e83
merge upstream/main
Martin521 Dec 2, 2024
5f358b3
update ilverify baselines
Martin521 Dec 2, 2024
30d66e2
merge upstream/main
Martin521 Dec 3, 2024
387049e
Merge remote-tracking branch 'upstream/main' into scoped-nowarn
Martin521 Dec 3, 2024
d617fbd
Merge remote-tracking branch 'upstream/main' into scoped-nowarn
Martin521 Dec 4, 2024
e7eb32f
update ilverify baseline (line number changes only)
Martin521 Dec 4, 2024
f05f993
merge upstream/main
Martin521 Dec 4, 2024
eba854f
merge upstream/main
Martin521 Dec 6, 2024
7fa6352
merge upstream/main
Martin521 Dec 15, 2024
1301542
fix merge issue
Martin521 Dec 15, 2024
48d0875
ilverify baselines
Martin521 Dec 15, 2024
2d29b15
Merge remote-tracking branch 'upstream/main' into scoped-nowarn
Martin521 Dec 16, 2024
2f44500
made WarnScopes.IsWarnon / IsNowarn public
Martin521 Dec 16, 2024
f526549
merge upstream/main
Martin521 Dec 16, 2024
7e96882
added surface area change (IsNowarn/IsWarnon) to baseline
Martin521 Dec 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion .fantomasignore
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ src/Compiler/Utilities/HashMultiMap.fs
src/Compiler/Facilities/AsyncMemoize.fsi
src/Compiler/Facilities/AsyncMemoize.fs
src/Compiler/AbstractIL/il.fs
src/Compiler/SyntaxTree/LexerStore.fs
src/Compiler/SyntaxTree/UnicodeLexing.fsi
src/Compiler/SyntaxTree/UnicodeLexing.fs

src/Compiler/Driver/GraphChecking/Graph.fsi
src/Compiler/Driver/GraphChecking/Graph.fs
Expand Down
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/9.0.200.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* Added type conversions cache, only enabled for compiler runs, guarded by language version preview ([PR #17668](https://github.com/dotnet/fsharp/pull/17668))
* Added project property ParallelCompilation which turns on graph based type checking, parallel ILXGen and parallel optimization. By default on for users of langversion=preview ([PR #17948](https://github.com/dotnet/fsharp/pull/17948))
* Adding warning when consuming generic method returning T|null for types not supporting nullness (structs,anons,tuples) ([PR #18057](https://github.com/dotnet/fsharp/pull/18057))
* Scoped Nowarn: added the #warnon compiler directive ([Language suggestion #278](https://github.com/fsharp/fslang-suggestions/issues/278), [RFC FS-1146 PR](https://github.com/fsharp/fslang-design/pull/782), [PR #18049](https://github.com/dotnet/fsharp/pull/18049))

### Changed

Expand Down
1 change: 1 addition & 0 deletions docs/release-notes/.Language/preview.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Better generic unmanaged structs handling. ([Language suggestion #692](https://github.com/fsharp/fslang-suggestions/issues/692), [PR #12154](https://github.com/dotnet/fsharp/pull/12154))
* Deprecate places where `seq` can be omitted. ([Language suggestion #1033](https://github.com/fsharp/fslang-suggestions/issues/1033), [PR #17772](https://github.com/dotnet/fsharp/pull/17772))
* Added type conversions cache, only enabled for compiler runs ([PR#17668](https://github.com/dotnet/fsharp/pull/17668))
* Scoped Nowarn: added the #warnon compiler directive ([Language suggestion #278](https://github.com/fsharp/fslang-suggestions/issues/278), [RFC FS-1146 PR](https://github.com/fsharp/fslang-design/pull/782), [PR #18049](https://github.com/dotnet/fsharp/pull/18049))

### Fixed
* Warn on uppercase identifiers in patterns. ([PR #15816](https://github.com/dotnet/fsharp/pull/15816))
Expand Down
4 changes: 2 additions & 2 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5734,7 +5734,7 @@ let CheckOneImplFile
synImplFile,
diagnosticOptions) =

let (ParsedImplFileInput (fileName, isScript, qualNameOfFile, scopedPragmas, _, implFileFrags, isLastCompiland, _, _)) = synImplFile
let (ParsedImplFileInput (fileName, isScript, qualNameOfFile, _, implFileFrags, isLastCompiland, _, _)) = synImplFile
let infoReader = InfoReader(g, amap)

cancellable {
Expand Down Expand Up @@ -5873,7 +5873,7 @@ let CheckOneImplFile
|> Array.map (fun (KeyValue(k,v)) -> (k,v))
|> Map

let implFile = CheckedImplFile (qualNameOfFile, scopedPragmas, implFileTy, implFileContents, hasExplicitEntryPoint, isScript, anonRecdTypes, namedDebugPointsForInlinedCode)
let implFile = CheckedImplFile (qualNameOfFile, implFileTy, implFileContents, hasExplicitEntryPoint, isScript, anonRecdTypes, namedDebugPointsForInlinedCode)

return (topAttrs, implFile, envAtEnd, cenv.createsGeneratedProvidedTypes)
}
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/CodeGen/IlxGen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10399,7 +10399,7 @@ and GenModuleBinding cenv (cgbuf: CodeGenBuffer) (qname: QualifiedNameOfFile) la

/// Generate the namespace fragments in a single file
and GenImplFile cenv (mgbuf: AssemblyBuilder) mainInfoOpt eenv (implFile: CheckedImplFileAfterOptimization) =
let (CheckedImplFile(qname, _, signature, contents, hasExplicitEntryPoint, isScript, anonRecdTypes, _)) =
let (CheckedImplFile(qname, signature, contents, hasExplicitEntryPoint, isScript, anonRecdTypes, _)) =
implFile.ImplFile

let optimizeDuringCodeGen = implFile.OptimizeDuringCodeGen
Expand Down
9 changes: 9 additions & 0 deletions src/Compiler/Driver/CompilerConfig.fs
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ type TcConfigBuilder =

mutable pathMap: PathMap

/// do not set directly, but only through member 'SetLangVersion'
mutable langVersion: LanguageVersion

mutable xmlDocInfoLoader: IXmlDocumentationInfoLoader option
Expand Down Expand Up @@ -877,6 +878,14 @@ type TcConfigBuilder =
compilationMode = TcGlobals.CompilationMode.Unset
}

member tcConfigB.SetLangVersion v =
Copy link
Member

@KevinRansom KevinRansom Dec 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a mutator for langVersion is fine but mostly unnecessary, but please don't let the langVersion mutator set other values in TcConfig that is not the paradigm we use. Yes SetPrimaryAssembly and SetUseSdkRefs also set tcConfigB.fxResolver, they probably shouldn't, actually I think I may fix them so they don't.

TcConfigBuilder is a mutable record and so modifying values is kind of what it's about, after building this is passed to the constructor of TcConfig which then creates the immutable TcConfig that is used to access these values. Perhaps the best thing is to mutate fsharpDiagnosticOptions with the language version when constructing the TcConfig object. Then you would plumb the langversion to the places where FSharpDiagnosticOptions.Default is used and add a langVersion argument to FSharpDiagnosticOptions.Default which would enable the error and warning defaults to change on a per language version basis which is probably usefull longer term. Unfortunately plumbing data about is never fun.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When tcConfigB.diagnosticsOptions is set to FSharpDiagnosticOptions.Default, the langversion is not yet known. The langversion comes only much later with ParseCompilerOpions.
There are two alternatives that I considered but didn't like.
The first was to add to tcConfigB an updated FSharpDiagnosticOptions (updated with the langversion) in all the places where ParseCompilerOptions is called (in fsc.fs, fsi.fs, BackgroundCompiler.fs, TransparentCompiler.fs and FSharpCheckerResults.fs).
The second was to thread the whole tcConfig through all the function calls to the places where I need only the diagnosticsOptions.
But let me check if I find still another way.

tcConfigB.langVersion <- v

tcConfigB.diagnosticsOptions <-
{ tcConfigB.diagnosticsOptions with
WarnScopesFeatureIsSupported = v.SupportsFeature LanguageFeature.ScopedNowarn
}

member tcConfigB.FxResolver =
// We compute the FxResolver on-demand. It depends on some configuration parameters
// which may be later adjusted.
Expand Down
2 changes: 2 additions & 0 deletions src/Compiler/Driver/CompilerConfig.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,8 @@ type TcConfigBuilder =
rangeForErrors: range ->
TcConfigBuilder

member SetLangVersion: LanguageVersion -> unit

member DecideNames: string list -> string * string option * string

member TurnWarningOff: range * string -> unit
Expand Down
58 changes: 19 additions & 39 deletions src/Compiler/Driver/CompilerDiagnostics.fs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ type PhasedDiagnostic with
// Level 2
| _ -> 2

member x.IsEnabled(severity, options) =
member private x.IsEnabled(severity, options) =
let level = options.WarnLevel
let specificWarnOn = options.WarnOn
let n = x.Number
Expand Down Expand Up @@ -412,19 +412,25 @@ type PhasedDiagnostic with
member x.AdjustSeverity(options, severity) =
let n = x.Number

let warnOff () = List.contains n options.WarnOff
let localWarnon () = WarnScopes.IsWarnon options n x.Range

let localNowarn () = WarnScopes.IsNowarn options n x.Range

let warnOff () =
List.contains n options.WarnOff && not (localWarnon ()) || localNowarn ()

match severity with
| FSharpDiagnosticSeverity.Error -> FSharpDiagnosticSeverity.Error
| FSharpDiagnosticSeverity.Warning when
x.IsEnabled(severity, options)
&& ((options.GlobalWarnAsError && not (warnOff ()))
|| List.contains n options.WarnAsError)
|| List.contains n options.WarnAsError && not (localNowarn ()))
&& not (List.contains n options.WarnAsWarn)
->
FSharpDiagnosticSeverity.Error
| FSharpDiagnosticSeverity.Info when List.contains n options.WarnAsError && not (localNowarn ()) -> FSharpDiagnosticSeverity.Error
| FSharpDiagnosticSeverity.Warning when x.IsEnabled(severity, options) && not (warnOff ()) -> FSharpDiagnosticSeverity.Warning
| FSharpDiagnosticSeverity.Info when List.contains n options.WarnAsError -> FSharpDiagnosticSeverity.Error
| FSharpDiagnosticSeverity.Warning when localWarnon () -> FSharpDiagnosticSeverity.Warning
| FSharpDiagnosticSeverity.Info when List.contains n options.WarnOn && not (warnOff ()) -> FSharpDiagnosticSeverity.Warning
| FSharpDiagnosticSeverity.Info when x.IsEnabled(severity, options) && not (warnOff ()) -> FSharpDiagnosticSeverity.Info
| _ -> FSharpDiagnosticSeverity.Hidden
Expand Down Expand Up @@ -2273,51 +2279,25 @@ type PhasedDiagnostic with
diagnostic.OutputContext(buf, prefix, fileLineFunction)
diagnostic.Output(buf, tcConfig, severity))

//----------------------------------------------------------------------------
// Scoped #nowarn pragmas

/// Build an DiagnosticsLogger that delegates to another DiagnosticsLogger but filters warnings turned off by the given pragma declarations
//
// NOTE: we allow a flag to turn of strict file checking. This is because file names sometimes don't match due to use of
// #line directives, e.g. for pars.fs/pars.fsy. In this case we just test by line number - in most cases this is sufficient
// because we install a filtering error handler on a file-by-file basis for parsing and type-checking.
// However this is indicative of a more systematic problem where source-line
// sensitive operations (lexfilter and warning filtering) do not always
// interact well with #line directives.
type DiagnosticsLoggerFilteringByScopedPragmas
(checkFile, scopedPragmas, diagnosticOptions: FSharpDiagnosticOptions, diagnosticsLogger: DiagnosticsLogger) =
inherit DiagnosticsLogger("DiagnosticsLoggerFilteringByScopedPragmas")
/// Build an DiagnosticsLogger that delegates to another DiagnosticsLogger but filters warnings
type DiagnosticsLoggerFilteringByScopedNowarn(diagnosticOptions: FSharpDiagnosticOptions, diagnosticsLogger: DiagnosticsLogger) =
inherit DiagnosticsLogger("DiagnosticsLoggerFilteringByScopedNowarn")

let mutable realErrorPresent = false

override _.DiagnosticSink(diagnostic: PhasedDiagnostic, severity) =

if severity = FSharpDiagnosticSeverity.Error then
realErrorPresent <- true
diagnosticsLogger.DiagnosticSink(diagnostic, severity)
else
let report =
let warningNum = diagnostic.Number

match diagnostic.Range with
| Some m ->
scopedPragmas
|> List.exists (fun pragma ->
let (ScopedPragma.WarningOff(pragmaRange, warningNumFromPragma)) = pragma

warningNum = warningNumFromPragma
&& (not checkFile || m.FileIndex = pragmaRange.FileIndex)
&& posGeq m.Start pragmaRange.Start)
|> not
| None -> true

if report then
match diagnostic.AdjustSeverity(diagnosticOptions, severity) with
| FSharpDiagnosticSeverity.Hidden -> ()
| s -> diagnosticsLogger.DiagnosticSink(diagnostic, s)
match diagnostic.AdjustSeverity(diagnosticOptions, severity) with
| FSharpDiagnosticSeverity.Hidden -> ()
| s -> diagnosticsLogger.DiagnosticSink(diagnostic, s)

override _.ErrorCount = diagnosticsLogger.ErrorCount

override _.CheckForRealErrorsIgnoringWarnings = realErrorPresent

let GetDiagnosticsLoggerFilteringByScopedPragmas (checkFile, scopedPragmas, diagnosticOptions, diagnosticsLogger) =
DiagnosticsLoggerFilteringByScopedPragmas(checkFile, scopedPragmas, diagnosticOptions, diagnosticsLogger) :> DiagnosticsLogger
let GetDiagnosticsLoggerFilteringByScopedNowarn (diagnosticOptions, diagnosticsLogger) =
DiagnosticsLoggerFilteringByScopedNowarn(diagnosticOptions, diagnosticsLogger) :> DiagnosticsLogger
8 changes: 2 additions & 6 deletions src/Compiler/Driver/CompilerDiagnostics.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,8 @@ type PhasedDiagnostic with
unit

/// Get a diagnostics logger that filters the reporting of warnings based on scoped pragma information
val GetDiagnosticsLoggerFilteringByScopedPragmas:
checkFile: bool *
scopedPragmas: ScopedPragma list *
diagnosticOptions: FSharpDiagnosticOptions *
diagnosticsLogger: DiagnosticsLogger ->
DiagnosticsLogger
val GetDiagnosticsLoggerFilteringByScopedNowarn:
diagnosticOptions: FSharpDiagnosticOptions * diagnosticsLogger: DiagnosticsLogger -> DiagnosticsLogger

/// Remove 'implicitIncludeDir' from a file name before output
val SanitizeFileName: fileName: string -> implicitIncludeDir: string -> string
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Driver/CompilerOptions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,7 @@ let languageFlags tcConfigB =
CompilerOption(
"langversion",
tagLangVersionValues,
OptionString(fun switch -> tcConfigB.langVersion <- setLanguageVersion (switch)),
OptionString(fun switch -> tcConfigB.SetLangVersion(setLanguageVersion (switch))),
None,
Some(FSComp.SR.optsSetLangVersion ())
)
Expand Down
Loading
Loading