Skip to content

Commit c18d785

Browse files
baronfelcartermp
andcommitted
Prevent assignment to literal ILFields (#9797)
* Prevent assignment to literal ILFields * revert old mechanism * add new error message, use it, and provide localizations * add error message for literal and non-literal assignment * first stab at tests * flip directory separator in test project file * fix namespace on file to allow for it to be picked up * Update src/fsharp/TypeChecker.fs Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update tests/FSharp.Compiler.ComponentTests/Interop/SimpleInteropTests.fs Co-authored-by: Phillip Carter <pcarter@fastmail.com> * Update tests/FSharp.Compiler.ComponentTests/Interop/SimpleInteropTests.fs Co-authored-by: Phillip Carter <pcarter@fastmail.com> Co-authored-by: Phillip Carter <pcarter@fastmail.com>
1 parent e7b1570 commit c18d785

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

src/fsharp/FSComp.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,8 +1512,10 @@ featureFixedIndexSlice3d4d,"fixed-index slice 3d/4d"
15121512
featureAndBang,"applicative computation expressions"
15131513
featureNullableOptionalInterop,"nullable optional interop"
15141514
featureDefaultInterfaceMemberConsumption,"default interface member consumption"
1515+
featureWitnessPassing,"witness passing for trait constraints in F# quotations"
1516+
3353,fsiInvalidDirective,"Invalid directive '#%s %s'"
15151517
3360,typrelInterfaceWithConcreteAndVariable,"'%s' cannot implement the interface '%s' with the two instantiations '%s' and '%s' because they may unify."
15161518
3361,typrelInterfaceWithConcreteAndVariableObjectExpression,"You cannot implement the interface '%s' with the two instantiations '%s' and '%s' because they may unify."
15171519
featureInterfacesWithMultipleGenericInstantiation,"interfaces with multiple generic instantiation"
1518-
featureWitnessPassing,"witness passing for trait constraints in F# quotations"
1519-
3353,fsiInvalidDirective,"Invalid directive '#%s %s'"
1520+
3362,tcLiteralFieldAssignmentWithArg,"Cannot assign '%s' to a value marked literal"
1521+
3363,tcLiteralFieldAssignmentNoArg,"Cannot assign a value to another value marked literal"

src/fsharp/TypeChecker.fs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3137,6 +3137,18 @@ let BuildILFieldGet g amap m objExpr (finfo: ILFieldInfo) =
31373137
// Add an I_nop if this is an initonly field to make sure we never recognize it as an lvalue. See mkExprAddrOfExpr.
31383138
wrap (mkAsmExpr (([ mkNormalLdfld fspec ] @ (if finfo.IsInitOnly then [ AI_nop ] else [])), tinst, [objExpr], [fieldType], m))
31393139

3140+
/// Checks that setting a field value does not set a literal or initonly field
3141+
let private CheckFieldLiteralArg (finfo: ILFieldInfo) argExpr m =
3142+
finfo.LiteralValue |> Option.iter (fun _ ->
3143+
match argExpr with
3144+
| Expr.Const (v, _, _) ->
3145+
let literalValue = string v
3146+
error (Error(FSComp.SR.tcLiteralFieldAssignmentWithArg literalValue, m))
3147+
| _ ->
3148+
error (Error(FSComp.SR.tcLiteralFieldAssignmentNoArg(), m))
3149+
)
3150+
if finfo.IsInitOnly then error (Error (FSComp.SR.tcFieldIsReadonly(), m))
3151+
31403152
let BuildILFieldSet g m objExpr (finfo: ILFieldInfo) argExpr =
31413153
let fref = finfo.ILFieldRef
31423154
let isValueType = finfo.IsValueType
@@ -3146,7 +3158,7 @@ let BuildILFieldSet g m objExpr (finfo: ILFieldInfo) argExpr =
31463158
// This ensures we always get the type instantiation right when doing this from
31473159
// polymorphic code, after inlining etc. *
31483160
let fspec = mkILFieldSpec(fref, mkILNamedTy valu fref.DeclaringTypeRef [])
3149-
if finfo.IsInitOnly then error (Error (FSComp.SR.tcFieldIsReadonly(), m))
3161+
CheckFieldLiteralArg finfo argExpr m
31503162
let wrap, objExpr, _readonly, _writeonly = mkExprAddrOfExpr g isValueType false DefinitelyMutates objExpr None m
31513163
wrap (mkAsmExpr ([ mkNormalStfld fspec ], tinst, [objExpr; argExpr], [], m))
31523164

@@ -3159,9 +3171,9 @@ let BuildILStaticFieldSet m (finfo: ILFieldInfo) argExpr =
31593171
// This ensures we always get the type instantiation right when doing this from
31603172
// polymorphic code, after inlining etc.
31613173
let fspec = mkILFieldSpec(fref, mkILNamedTy valu fref.DeclaringTypeRef [])
3162-
if finfo.IsInitOnly then error (Error (FSComp.SR.tcFieldIsReadonly(), m))
3174+
CheckFieldLiteralArg finfo argExpr m
31633175
mkAsmExpr ([ mkNormalStsfld fspec ], tinst, [argExpr], [], m)
3164-
3176+
31653177
let BuildRecdFieldSet g m objExpr (rfinfo: RecdFieldInfo) argExpr =
31663178
let tgtTy = rfinfo.DeclaringType
31673179
let valu = isStructTy g tgtTy

0 commit comments

Comments
 (0)