Skip to content
Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ micro.exe
positive.exe
/tests/FSharp.Compiler.ComponentTests/FSharpChecker/StandardError.txt
/tests/FSharp.Compiler.ComponentTests/FSharpChecker/StandardOutput.txt
/tests/FSharp.Compiler.ComponentTests/TestResults/

# ilverify baseline result files
*.bsl.actual
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 @@ -9,6 +9,7 @@
* Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543))
* 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))
* Allow `let!` and `use!` type annotations without requiring parentheses. ([PR #18508](https://github.com/dotnet/fsharp/pull/18508))
* Exception names are now validated for illegal characters using the same mechanism as types/modules/namespaces ([Issue #18763](https://github.com/dotnet/fsharp/issues/18763))

### Fixed

Expand Down
1 change: 1 addition & 0 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2406,6 +2406,7 @@ module TcExceptionDeclarations =
let TcExnDefnCore_Phase1A g cenv env parent (SynExceptionDefnRepr(Attributes synAttrs, SynUnionCase(ident= SynIdent(id,_)), _, xmlDoc, vis, m)) =
let attrs = TcAttributes cenv env AttributeTargets.ExnDecl synAttrs
if not (String.isLeadingIdentifierCharacterUpperCase id.idText) then errorR(NotUpperCaseConstructor id.idRange)
CheckNamespaceModuleOrTypeName g id
let vis, cpath = ComputeAccessAndCompPath g env None m vis None parent
let vis = TcRecdUnionAndEnumDeclarations.CombineReprAccess parent vis
CheckForDuplicateConcreteType env (id.idText + "Exception") id.idRange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ module NonStringArgs =
#nowarn 20 FS1104 "3391" "FS3221"

module Exception =
exception ``Crazy@name.p`` of string
exception ``Crazy@name`` of string

module Decimal =
type T1 = { a : decimal }
Expand Down Expand Up @@ -118,7 +118,7 @@ module DoBinding =
(Error 3350, Line 2, Col 9, Line 2, Col 11, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
(Error 3350, Line 2, Col 12, Line 2, Col 18, "Feature '# directives with non-quoted string arguments' is not available in F# 8.0. Please use language version 9.0 or greater.")
(Warning 203, Line 2, Col 26, Line 2, Col 34, "Invalid warning number 'FS3221'")
(Warning 1104, Line 5, Col 15, Line 5, Col 31, "Identifiers containing '@' are reserved for use in F# code generation")
(Warning 1104, Line 5, Col 15, Line 5, Col 29, "Identifiers containing '@' are reserved for use in F# code generation")
]
else
compileResult
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// #Regression #Conformance #TypesAndModules #Exceptions
// Exception types
// Exception names must not contain illegal characters

#light

exception ``My.Exception`` // err: contains '.'
exception ``My+Exception`` // err: contains '+'
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// #Regression #Conformance #TypesAndModules #Exceptions
// Exception types
// Exception names must not contain illegal characters

#light

exception ``My$Exception`` // err: contains '$'
exception ``My&Exception`` // err: contains '&'
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// #Regression #Conformance #TypesAndModules #Exceptions
// Exception types
// Exception names must not contain illegal characters

#light

exception ``My[Exception`` // err: contains '['
exception ``My]Exception`` // err: contains ']'
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// #Regression #Conformance #TypesAndModules #Exceptions
// Exception types
// Exception names must not contain illegal characters

#light

exception ``My/Exception`` // err: contains '/'
exception ``My\Exception`` // err: contains '\'
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// #Regression #Conformance #TypesAndModules #Exceptions
// Exception types
// Exception names must not contain illegal characters

#light

exception ``My*Exception`` // err: contains '*'
exception ``My"Exception`` // err: contains '"'
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// #Regression #Conformance #TypesAndModules #Exceptions
// Exception types
// Exception names must not contain illegal characters

#light

exception ``My`Exception`` // err: contains '`'
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ module ExceptionDefinition =
|> withDiagnostics [
(Warning 1104, Line 8, Col 11, Line 8, Col 27, "Identifiers containing '@' are reserved for use in F# code generation")
(Warning 1104, Line 10, Col 16, Line 10, Col 41, "Identifiers containing '@' are reserved for use in F# code generation")
(Error 883, Line 8, Col 11, Line 8, Col 27, "Invalid namespace, module, type or union case name")
(Error 39, Line 10, Col 16, Line 10, Col 41, "The type '[email protected]' is not defined. Maybe you want one of the following:\r\n [email protected]")
]

Expand Down Expand Up @@ -385,3 +386,84 @@ module ExceptionDefinition =
|> withOptions ["--warnaserror+"; "--nowarn:988"]
|> compileExeAndRun
|> shouldSucceed

// Test cases for illegal characters in exception names
// SOURCE=E_IllegalCharacters01.fsx SCFLAGS="--test:ErrorRanges" # E_IllegalCharacters01.fsx
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_IllegalCharacters01.fsx"|])>]
let``E_IllegalCharacters01_fsx`` compilation =
compilation
|> asExe
|> compile
|> shouldFail
|> withDiagnostics [
(Error 883, Line 7, Col 11, Line 7, Col 27, "Invalid namespace, module, type or union case name")
(Error 883, Line 8, Col 11, Line 8, Col 27, "Invalid namespace, module, type or union case name")
]

// SOURCE=E_IllegalCharacters02.fsx SCFLAGS="--test:ErrorRanges" # E_IllegalCharacters02.fsx
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_IllegalCharacters02.fsx"|])>]
let``E_IllegalCharacters02_fsx`` compilation =
compilation
|> asExe
|> compile
|> shouldFail
|> withDiagnostics [
(Error 883, Line 7, Col 11, Line 7, Col 27, "Invalid namespace, module, type or union case name")
(Error 883, Line 8, Col 11, Line 8, Col 27, "Invalid namespace, module, type or union case name")
]

// SOURCE=E_IllegalCharacters03.fsx SCFLAGS="--test:ErrorRanges" # E_IllegalCharacters03.fsx
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_IllegalCharacters03.fsx"|])>]
let``E_IllegalCharacters03_fsx`` compilation =
compilation
|> asExe
|> compile
|> shouldFail
|> withDiagnostics [
(Error 883, Line 7, Col 11, Line 7, Col 27, "Invalid namespace, module, type or union case name")
(Error 883, Line 8, Col 11, Line 8, Col 27, "Invalid namespace, module, type or union case name")
]

// SOURCE=E_IllegalCharacters04.fsx SCFLAGS="--test:ErrorRanges" # E_IllegalCharacters04.fsx
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_IllegalCharacters04.fsx"|])>]
let``E_IllegalCharacters04_fsx`` compilation =
compilation
|> asExe
|> compile
|> shouldFail
|> withDiagnostics [
(Error 883, Line 7, Col 11, Line 7, Col 27, "Invalid namespace, module, type or union case name")
(Error 883, Line 8, Col 11, Line 8, Col 27, "Invalid namespace, module, type or union case name")
]

// SOURCE=E_IllegalCharacters05.fsx SCFLAGS="--test:ErrorRanges" # E_IllegalCharacters05.fsx
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_IllegalCharacters05.fsx"|])>]
let``E_IllegalCharacters05_fsx`` compilation =
compilation
|> asExe
|> compile
|> shouldFail
|> withDiagnostics [
(Error 883, Line 7, Col 11, Line 7, Col 27, "Invalid namespace, module, type or union case name")
(Error 883, Line 8, Col 11, Line 8, Col 27, "Invalid namespace, module, type or union case name")
]

// SOURCE=E_IllegalCharacters06.fsx SCFLAGS="--test:ErrorRanges" # E_IllegalCharacters06.fsx
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_IllegalCharacters06.fsx"|])>]
let``E_IllegalCharacters06_fsx`` compilation =
compilation
|> asExe
|> compile
|> shouldFail
|> withDiagnostics [
(Error 883, Line 7, Col 11, Line 7, Col 27, "Invalid namespace, module, type or union case name")
]

// SOURCE=LegalExceptionNames.fsx # LegalExceptionNames.fsx
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"LegalExceptionNames.fsx"|])>]
let``LegalExceptionNames_fsx`` compilation =
compilation
|> asExe
|> withOptions ["--warnaserror+"; "--nowarn:988"]
|> compileExeAndRun
|> shouldSucceed
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// #Regression #Conformance #TypesAndModules #Exceptions
// Exception types
// Legal exception names should compile successfully

#light

exception MyException
exception MyOtherException
exception Exception123
exception ExceptionWithLongName
exception A

let test() =
try
raise (MyException)
with
| MyException -> printfn "Caught MyException"
| _ -> printfn "Caught other"

let () = test()
Loading