Skip to content

Commit

Permalink
Improve value restriction error message dotnet#1103 (dotnet#15877)
Browse files Browse the repository at this point in the history
* Improve value restriction error message dotnet#1103

* Update the error message

* Update message

* Update tests

* Update error message

* Update messages

* Add line back

* Update error messages

* Update E_ValueRestriction01.fs

* Update messages

* Update messages

* Update messages

* Does this work?

* hmm

* Update function message

* Escape ()

* Update tests

* Update messages

* Update CompilerDiagnostics.fs

* Update CompilerDiagnostics.fs

---------

Co-authored-by: Petr <[email protected]>
  • Loading branch information
Happypig375 and psfinaki authored Dec 18, 2023
1 parent fd642a9 commit 311360d
Show file tree
Hide file tree
Showing 26 changed files with 183 additions and 413 deletions.
2 changes: 1 addition & 1 deletion src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5577,7 +5577,7 @@ let CheckValueRestriction denvAtEnd infoReader rootSigOpt implFileTypePriorToSig
// for example FSharp 1.0 3661.
(match v.ValReprInfo with None -> true | Some tvi -> tvi.HasNoArgs)) then
match ftyvs with
| tp :: _ -> errorR (ValueRestriction(denvAtEnd, infoReader, false, v, tp, v.Range))
| tp :: _ -> errorR (ValueRestriction(denvAtEnd, infoReader, v, tp, v.Range))
| _ -> ()
mty.ModuleAndNamespaceDefinitions |> List.iter (fun v -> check v.ModuleOrNamespaceType)
try check implFileTypePriorToSig with RecoverableException e -> errorRecovery e m
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ exception UnionPatternsBindDifferentNames of range

exception VarBoundTwice of Ident

exception ValueRestriction of DisplayEnv * InfoReader * bool * Val * Typar * range
exception ValueRestriction of DisplayEnv * InfoReader * Val * Typar * range

exception ValNotMutable of DisplayEnv * ValRef * range

Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/CheckExpressions.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ exception UnionPatternsBindDifferentNames of range

exception VarBoundTwice of Ident

exception ValueRestriction of DisplayEnv * InfoReader * bool * Val * Typar * range
exception ValueRestriction of DisplayEnv * InfoReader * Val * Typar * range

exception ValNotMutable of DisplayEnv * ValRef * range

Expand Down
70 changes: 17 additions & 53 deletions src/Compiler/Driver/CompilerDiagnostics.fs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ type Exception with
| IntfImplInIntrinsicAugmentation m
| OverrideInExtrinsicAugmentation m
| IntfImplInExtrinsicAugmentation m
| ValueRestriction(_, _, _, _, _, m)
| ValueRestriction(_, _, _, _, m)
| LetRecUnsound(_, _, m)
| ObsoleteError(_, m)
| ObsoleteWarning(_, m)
Expand Down Expand Up @@ -579,11 +579,8 @@ module OldStyleMessages =
let DeprecatedE () = Message("Deprecated", "%s")
let LibraryUseOnlyE () = Message("LibraryUseOnly", "")
let MissingFieldsE () = Message("MissingFields", "%s")
let ValueRestriction1E () = Message("ValueRestriction1", "%s%s%s")
let ValueRestriction2E () = Message("ValueRestriction2", "%s%s%s")
let ValueRestriction3E () = Message("ValueRestriction3", "%s")
let ValueRestriction4E () = Message("ValueRestriction4", "%s%s%s")
let ValueRestriction5E () = Message("ValueRestriction5", "%s%s%s")
let ValueRestrictionFunctionE () = Message("ValueRestrictionFunction", "%s%s%s")
let ValueRestrictionE () = Message("ValueRestriction", "%s%s%s")
let RecoverableParseErrorE () = Message("RecoverableParseError", "")
let ReservedKeywordE () = Message("ReservedKeyword", "%s")
let IndentationProblemE () = Message("IndentationProblem", "%s")
Expand Down Expand Up @@ -1760,63 +1757,30 @@ type Exception with

| MissingFields(sl, _) -> os.AppendString(MissingFieldsE().Format(String.concat "," sl + "."))

| ValueRestriction(denv, infoReader, hasSig, v, _, _) ->
| ValueRestriction(denv, infoReader, v, _, _) ->
let denv =
{ denv with
showInferenceTyparAnnotations = true
}

let tau = v.TauType

if hasSig then
if isFunTy denv.g tau && (arityOfVal v).HasNoArgs then
let msg =
ValueRestriction1E().Format
v.DisplayName
(NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v))
v.DisplayName
if isFunTy denv.g tau && (arityOfVal v).HasNoArgs then
let msg =
ValueRestrictionFunctionE().Format
v.DisplayName
(NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v))
v.DisplayName

os.AppendString msg
else
let msg =
ValueRestriction2E().Format
v.DisplayName
(NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v))
v.DisplayName

os.AppendString msg
os.AppendString msg
else
match v.MemberInfo with
| Some membInfo when
(match membInfo.MemberFlags.MemberKind with
| SynMemberKind.PropertyGet
| SynMemberKind.PropertySet
| SynMemberKind.Constructor -> true // can't infer extra polymorphism
// can infer extra polymorphism
| _ -> false)
->
let msg =
ValueRestriction3E()
.Format(NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v))

os.AppendString msg
| _ ->
if isFunTy denv.g tau && (arityOfVal v).HasNoArgs then
let msg =
ValueRestriction4E().Format
v.DisplayName
(NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v))
v.DisplayName

os.AppendString msg
else
let msg =
ValueRestriction5E().Format
v.DisplayName
(NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v))
v.DisplayName
let msg =
ValueRestrictionE().Format
v.DisplayName
(NicePrint.stringOfQualifiedValOrMember denv infoReader (mkLocalValRef v))
v.DisplayName

os.AppendString msg
os.AppendString msg

| Parsing.RecoverableParseError -> os.AppendString(RecoverableParseErrorE().Format)

Expand Down
17 changes: 4 additions & 13 deletions src/Compiler/FSStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1029,20 +1029,11 @@
<data name="MissingFields" xml:space="preserve">
<value>The following fields require values: {0}</value>
</data>
<data name="ValueRestriction1" xml:space="preserve">
<value>Value restriction. The value '{0}' has generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation.</value>
<data name="ValueRestrictionFunction" xml:space="preserve">
<value>Value restriction: The value '{0}' has an inferred generic function type\n {1}\nHowever, values cannot have generic type variables like '_a in "let f: '_a". You should define '{2}' as a function instead by doing one of the following:\n- Add an explicit parameter that is applied instead of using a partial application "let f param"\n- Add a unit parameter like "let f()"\n- Write explicit type parameters like "let f&lt;'a&gt;"\nor if you do not intend for it to be generic, either:\n- Add an explicit type annotation like "let f : obj -&gt; obj"\n- Apply arguments of non-generic types to the function value in later code for type inference like "do f()".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results.</value>
</data>
<data name="ValueRestriction2" xml:space="preserve">
<value>Value restriction. The value '{0}' has generic type\n {1} \nEither make '{2}' into a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.</value>
</data>
<data name="ValueRestriction3" xml:space="preserve">
<value>Value restriction. This member has been inferred to have generic type\n {0} \nConstructors and property getters/setters cannot be more generic than the enclosing type. Add a type annotation to indicate the exact types involved.</value>
</data>
<data name="ValueRestriction4" xml:space="preserve">
<value>Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither make the arguments to '{2}' explicit or, if you do not intend for it to be generic, add a type annotation.</value>
</data>
<data name="ValueRestriction5" xml:space="preserve">
<value>Value restriction. The value '{0}' has been inferred to have generic type\n {1} \nEither define '{2}' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.</value>
<data name="ValueRestriction" xml:space="preserve">
<value>Value restriction: The value '{0}' has an inferred generic type\n {1}\nHowever, values cannot have generic type variables like '_a in "let x: '_a". You can do one of the following:\n- Define it as a simple data term like an integer literal, a string literal or a union case like "let x = 1"\n- Add an explicit type annotation like "let x : int"\n- Use the value as a non-generic type in later code for type inference like "do x"\nor if you still want type-dependent results, you can define '{2}' as a function instead by doing either:\n- Add a unit parameter like "let x()"\n- Write explicit type parameters like "let x&lt;'a&gt;".\nThis error is because a let binding without parameters defines a value, not a function. Values cannot be generic because reading a value is assumed to result in the same everywhere but generic type parameters may invalidate this assumption by enabling type-dependent results.</value>
</data>
<data name="RecoverableParseError" xml:space="preserve">
<value>syntax error</value>
Expand Down
35 changes: 10 additions & 25 deletions src/Compiler/xlf/FSStrings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 311360d

Please sign in to comment.