Skip to content

Commit 4459532

Browse files
dsymeKevinRansom
authored andcommitted
[ RFC FS-1039] implementation of value options (#4837)
* posible implementation of value options * fix surface area test * fix test * VNone --> ValueNone * fix surface area * fix build * update baselines * fix baselines * fix baselines * fix baselines * fix baselines * fix build
1 parent a8e059f commit 4459532

File tree

14 files changed

+192
-52
lines changed

14 files changed

+192
-52
lines changed

src/absil/illib.fs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -448,16 +448,16 @@ module List =
448448

449449
[<Struct>]
450450
type ValueOption<'T> =
451-
| VSome of 'T
452-
| VNone
453-
member x.IsSome = match x with VSome _ -> true | VNone -> false
454-
member x.IsNone = match x with VSome _ -> false | VNone -> true
455-
member x.Value = match x with VSome r -> r | VNone -> failwith "ValueOption.Value: value is None"
451+
| ValueSome of 'T
452+
| ValueNone
453+
member x.IsSome = match x with ValueSome _ -> true | ValueNone -> false
454+
member x.IsNone = match x with ValueSome _ -> false | ValueNone -> true
455+
member x.Value = match x with ValueSome r -> r | ValueNone -> failwith "ValueOption.Value: value is None"
456456

457457
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
458458
module ValueOption =
459-
let inline ofOption x = match x with Some x -> VSome x | None -> VNone
460-
let inline bind f x = match x with VSome x -> f x | VNone -> VNone
459+
let inline ofOption x = match x with Some x -> ValueSome x | None -> ValueNone
460+
let inline bind f x = match x with ValueSome x -> f x | ValueNone -> ValueNone
461461

462462
module String =
463463
let indexNotFound() = raise (new KeyNotFoundException("An index for the character was not found in the string"))

src/fsharp/AttributeChecking.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,15 +511,15 @@ let IsSecurityAttribute (g: TcGlobals) amap (casmap : Dictionary<Stamp, bool>) (
511511
| None -> false
512512
| Some attr ->
513513
match attr.TyconRef.TryDeref with
514-
| VSome _ ->
514+
| ValueSome _ ->
515515
let tcs = tcref.Stamp
516516
match casmap.TryGetValue(tcs) with
517517
| true, c -> c
518518
| _ ->
519519
let exists = ExistsInEntireHierarchyOfType (fun t -> typeEquiv g t (mkAppTy attr.TyconRef [])) g amap m AllowMultiIntfInstantiations.Yes (mkAppTy tcref [])
520520
casmap.[tcs] <- exists
521521
exists
522-
| VNone -> false
522+
| ValueNone -> false
523523

524524
let IsSecurityCriticalAttribute g (Attrib(tcref, _, _, _, _, _, _)) =
525525
(tyconRefEq g tcref g.attrib_SecurityCriticalAttribute.TyconRef || tyconRefEq g tcref g.attrib_SecuritySafeCriticalAttribute.TyconRef)

src/fsharp/FSharp.Core/prim-types.fs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2972,14 +2972,24 @@ namespace Microsoft.FSharp.Core
29722972

29732973
and 'T option = Option<'T>
29742974

2975-
29762975
[<StructuralEquality; StructuralComparison>]
29772976
[<CompiledName("FSharpResult`2")>]
29782977
[<Struct>]
29792978
type Result<'T,'TError> =
29802979
| Ok of ResultValue:'T
29812980
| Error of ErrorValue:'TError
29822981

2982+
[<StructuralEquality; StructuralComparison>]
2983+
[<Struct>]
2984+
[<CompiledName("FSharpValueOption`1")>]
2985+
type ValueOption<'T> =
2986+
| ValueNone : 'T voption
2987+
| ValueSome : 'T -> 'T voption
2988+
2989+
member x.Value = match x with ValueSome x -> x | ValueNone -> raise (new System.InvalidOperationException("ValueOption.Value"))
2990+
2991+
2992+
and 'T voption = ValueOption<'T>
29832993

29842994
namespace Microsoft.FSharp.Collections
29852995

@@ -3345,11 +3355,11 @@ namespace Microsoft.FSharp.Core
33453355

33463356
let (^) (s1: string) (s2: string) = System.String.Concat(s1, s2)
33473357

3348-
33493358
[<CompiledName("DefaultArg")>]
3350-
[<CodeAnalysis.SuppressMessage("Microsoft.Naming","CA1704:IdentifiersShouldBeSpelledCorrectly")>]
33513359
let defaultArg arg defaultValue = match arg with None -> defaultValue | Some v -> v
33523360

3361+
[<CompiledName("DefaultValueArg")>]
3362+
let defaultValueArg arg defaultValue = match arg with ValueNone -> defaultValue | ValueSome v -> v
33533363

33543364
[<NoDynamicInvocation>]
33553365
let inline (~-) (n: ^T) : ^T =

src/fsharp/FSharp.Core/prim-types.fsi

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,33 @@ namespace Microsoft.FSharp.Core
17331733
/// due to the use of <c>null</c> as a value representation.</remarks>
17341734
and 'T option = Option<'T>
17351735

1736+
/// <summary>The type of optional values, represented as structs.</summary>
1737+
///
1738+
/// <remarks>Use the constructors <c>ValueSome</c> and <c>ValueNone</c> to create values of this type.
1739+
/// Use the values in the <c>ValueOption</c> module to manipulate values of this type,
1740+
/// or pattern match against the values directly.
1741+
[<StructuralEquality; StructuralComparison>]
1742+
[<CompiledName("FSharpValueOption`1")>]
1743+
[<Struct>]
1744+
type ValueOption<'T> =
1745+
/// <summary>The representation of "No value"</summary>
1746+
| ValueNone: 'T voption
1747+
1748+
/// <summary>The representation of "Value of type 'T"</summary>
1749+
/// <param name="Value">The input value.</param>
1750+
/// <returns>An option representing the value.</returns>
1751+
| ValueSome: 'T -> 'T voption
1752+
1753+
/// <summary>Get the value of a 'ValueSome' option. An InvalidOperationException is raised if the option is 'ValueNone'.</summary>
1754+
member Value : 'T
1755+
1756+
/// <summary>The type of optional values, represented as structs.</summary>
1757+
///
1758+
/// <remarks>Use the constructors <c>ValueSome</c> and <c>ValueNone</c> to create values of this type.
1759+
/// Use the values in the <c>ValueOption</c> module to manipulate values of this type,
1760+
/// or pattern match against the values directly.
1761+
and 'T voption = ValueOption<'T>
1762+
17361763
/// <summary>Helper type for error handling without exceptions.</summary>
17371764
[<StructuralEquality; StructuralComparison>]
17381765
[<CompiledName("FSharpResult`2")>]
@@ -1998,6 +2025,13 @@ namespace Microsoft.FSharp.Core
19982025
[<CompiledName("DefaultArg")>]
19992026
val defaultArg : arg:'T option -> defaultValue:'T -> 'T
20002027

2028+
/// <summary>Used to specify a default value for an optional argument in the implementation of a function</summary>
2029+
/// <param name="arg">A value option representing the argument.</param>
2030+
/// <param name="defaultValue">The default value of the argument.</param>
2031+
/// <returns>The argument value. If it is None, the defaultValue is returned.</returns>
2032+
[<CompiledName("DefaultValueArg")>]
2033+
val defaultValueArg : arg:'T voption -> defaultValue:'T -> 'T
2034+
20012035
/// <summary>Concatenate two strings. The operator '+' may also be used.</summary>
20022036
[<CompilerMessage("This construct is for ML compatibility. Consider using the '+' operator instead. This may require a type annotation to indicate it acts on strings. This message can be disabled using '--nowarn:62' or '#nowarn \"62\"'.", 62, IsHidden=true)>]
20032037
val (^): s1:string -> s2:string -> string

src/fsharp/IlxGen.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -714,11 +714,11 @@ let AddStorageForVal (g: TcGlobals) (v,s) eenv =
714714
| None -> eenv
715715
| Some vref ->
716716
match vref.TryDeref with
717-
| VNone ->
717+
| ValueNone ->
718718
//let msg = sprintf "could not dereference external value reference to something in FSharp.Core.dll during code generation, v.MangledName = '%s', v.Range = %s" v.MangledName (stringOfRange v.Range)
719719
//System.Diagnostics.Debug.Assert(false, msg)
720720
eenv
721-
| VSome gv ->
721+
| ValueSome gv ->
722722
{ eenv with valsInScope = eenv.valsInScope.Add gv s }
723723
else
724724
eenv

src/fsharp/NameResolution.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,8 @@ type Item =
249249

250250
let valRefHash (vref: ValRef) =
251251
match vref.TryDeref with
252-
| VNone -> 0
253-
| VSome v -> LanguagePrimitives.PhysicalHash v
252+
| ValueNone -> 0
253+
| ValueSome v -> LanguagePrimitives.PhysicalHash v
254254

255255
[<RequireQualifiedAccess>]
256256
/// Pairs an Item with a TyparInst showing how generic type variables of the item are instantiated at

src/fsharp/TastOps.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6324,9 +6324,9 @@ let mkCallLiftValueWithName (g:TcGlobals) m ty nm e1 =
63246324
let vref = ValRefForIntrinsic g.lift_value_with_name_info
63256325
// Use "Expr.ValueWithName" if it exists in FSharp.Core
63266326
match vref.TryDeref with
6327-
| VSome _ ->
6327+
| ValueSome _ ->
63286328
mkApps g (typedExprForIntrinsic g m g.lift_value_with_name_info , [[ty]], [mkRefTupledNoTypes g m [e1; mkString g m nm]], m)
6329-
| VNone ->
6329+
| ValueNone ->
63306330
mkApps g (typedExprForIntrinsic g m g.lift_value_info , [[ty]], [e1], m)
63316331

63326332
let mkCallLiftValueWithDefn g m qty e1 =
@@ -6335,11 +6335,11 @@ let mkCallLiftValueWithDefn g m qty e1 =
63356335
let vref = ValRefForIntrinsic g.lift_value_with_defn_info
63366336
// Use "Expr.WithValue" if it exists in FSharp.Core
63376337
match vref.TryDeref with
6338-
| VSome _ ->
6338+
| ValueSome _ ->
63396339
let copyOfExpr = copyExpr g ValCopyFlag.CloneAll e1
63406340
let quoteOfCopyOfExpr = Expr.Quote(copyOfExpr, ref None, false, m, qty)
63416341
mkApps g (typedExprForIntrinsic g m g.lift_value_with_defn_info , [[ty]], [mkRefTupledNoTypes g m [e1; quoteOfCopyOfExpr]], m)
6342-
| VNone ->
6342+
| ValueNone ->
63436343
Expr.Quote(e1, ref None, false, m, qty)
63446344

63456345
let mkCallCheckThis g m ty e1 =

src/fsharp/TypeChecker.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16891,8 +16891,8 @@ let ApplyAssemblyLevelAutoOpenAttributeToTcEnv g amap (ccu: CcuThunk) scopem env
1689116891
let h, t = List.frontAndBack p
1689216892
let modref = mkNonLocalTyconRef (mkNonLocalEntityRef ccu (Array.ofList h)) t
1689316893
match modref.TryDeref with
16894-
| VNone -> warn()
16895-
| VSome _ ->
16894+
| ValueNone -> warn()
16895+
| ValueSome _ ->
1689616896
let openDecl = OpenDeclaration.Create ([], [modref], scopem, false)
1689716897
OpenModulesOrNamespaces TcResultsSink.NoSink g amap scopem root env [modref] openDecl
1689816898

src/fsharp/infos.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,7 @@ type MethInfo =
10951095
| ILMeth(_,ilmeth,_) -> ilmeth.IsClassConstructor
10961096
| FSMeth(_,_,vref,_) ->
10971097
match vref.TryDeref with
1098-
| VSome x -> x.IsClassConstructor
1098+
| ValueSome x -> x.IsClassConstructor
10991099
| _ -> false
11001100
| DefaultStructCtor _ -> false
11011101
#if !NO_EXTENSIONTYPING

src/fsharp/tast.fs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2882,15 +2882,15 @@ and NonLocalEntityRef =
28822882

28832883
/// Try to find the entity corresponding to the given path in the given CCU
28842884
static member TryDerefEntityPath(ccu: CcuThunk, path:string[], i:int, entity:Entity) =
2885-
if i >= path.Length then VSome entity
2885+
if i >= path.Length then ValueSome entity
28862886
else
28872887
let next = entity.ModuleOrNamespaceType.AllEntitiesByCompiledAndLogicalMangledNames.TryFind(path.[i])
28882888
match next with
28892889
| Some res -> NonLocalEntityRef.TryDerefEntityPath(ccu, path, (i+1), res)
28902890
#if !NO_EXTENSIONTYPING
28912891
| None -> NonLocalEntityRef.TryDerefEntityPathViaProvidedType(ccu, path, i, entity)
28922892
#else
2893-
| None -> VNone
2893+
| None -> ValueNone
28942894
#endif
28952895

28962896
#if !NO_EXTENSIONTYPING
@@ -2908,11 +2908,11 @@ and NonLocalEntityRef =
29082908
// types until i = path.Length-1. Create the Tycon's as needed
29092909
let rec tryResolveNestedTypeOf(parentEntity:Entity,resolutionEnvironment,st:Tainted<ProvidedType>,i) =
29102910
match st.PApply((fun st -> st.GetNestedType path.[i]),m) with
2911-
| Tainted.Null -> VNone
2911+
| Tainted.Null -> ValueNone
29122912
| st ->
29132913
let newEntity = Construct.NewProvidedTycon(resolutionEnvironment, st, ccu.ImportProvidedType, false, m)
29142914
parentEntity.ModuleOrNamespaceType.AddProvidedTypeEntity(newEntity)
2915-
if i = path.Length-1 then VSome(newEntity)
2915+
if i = path.Length-1 then ValueSome(newEntity)
29162916
else tryResolveNestedTypeOf(newEntity,resolutionEnvironment,st,i+1)
29172917

29182918
tryResolveNestedTypeOf(entity,resolutionEnvironment,st,i)
@@ -2970,18 +2970,18 @@ and NonLocalEntityRef =
29702970
// newEntity is at 'j'
29712971
NonLocalEntityRef.TryDerefEntityPath(ccu, path, (j+1), newEntity)
29722972

2973-
| [] -> VNone
2973+
| [] -> ValueNone
29742974
| _ -> failwith "Unexpected"
29752975

29762976
let rec tryResolvePrefixes j =
2977-
if j >= path.Length then VNone
2977+
if j >= path.Length then ValueNone
29782978
else match tryResolvePrefix j with
2979-
| VNone -> tryResolvePrefixes (j+1)
2980-
| VSome res -> VSome res
2979+
| ValueNone -> tryResolvePrefixes (j+1)
2980+
| ValueSome res -> ValueSome res
29812981

29822982
tryResolvePrefixes i
29832983

2984-
| _ -> VNone
2984+
| _ -> ValueNone
29852985
#endif
29862986

29872987
/// Try to link a non-local entity reference to an actual entity
@@ -2990,11 +2990,11 @@ and NonLocalEntityRef =
29902990
if canError then
29912991
ccu.EnsureDerefable(path)
29922992

2993-
if ccu.IsUnresolvedReference then VNone else
2993+
if ccu.IsUnresolvedReference then ValueNone else
29942994

29952995
match NonLocalEntityRef.TryDerefEntityPath(ccu, path, 0, ccu.Contents) with
2996-
| VSome _ as r -> r
2997-
| VNone ->
2996+
| ValueSome _ as r -> r
2997+
| ValueNone ->
29982998
// OK, the lookup failed. Check if we can redirect through a type forwarder on this assembly.
29992999
// Look for a forwarder for each prefix-path
30003000
let rec tryForwardPrefixPath i =
@@ -3004,7 +3004,7 @@ and NonLocalEntityRef =
30043004
| Some tcref -> NonLocalEntityRef.TryDerefEntityPath(ccu, path, (i+1), tcref.Deref)
30053005
| None -> tryForwardPrefixPath (i+1)
30063006
else
3007-
VNone
3007+
ValueNone
30083008
tryForwardPrefixPath 0
30093009

30103010
/// Get the CCU referenced by the nonlocal reference.
@@ -3036,8 +3036,8 @@ and NonLocalEntityRef =
30363036
/// Dereference the nonlocal reference, and raise an error if this fails.
30373037
member nleref.Deref =
30383038
match nleref.TryDeref(canError=true) with
3039-
| VSome res -> res
3040-
| VNone ->
3039+
| ValueSome res -> res
3040+
| ValueNone ->
30413041
errorR (InternalUndefinedItemRef (FSComp.SR.tastUndefinedItemRefModuleNamespace, nleref.DisplayName, nleref.AssemblyName, "<some module on this path>"))
30423042
raise (KeyNotFoundException())
30433043

@@ -3067,9 +3067,9 @@ and
30673067
member private tcr.Resolve(canError) =
30683068
let res = tcr.nlr.TryDeref(canError)
30693069
match res with
3070-
| VSome r ->
3070+
| ValueSome r ->
30713071
tcr.binding <- nullableSlotFull r
3072-
| VNone ->
3072+
| ValueNone ->
30733073
()
30743074

30753075
/// Dereference the TyconRef to a Tycon. Amortize the cost of doing this.
@@ -3090,11 +3090,11 @@ and
30903090
| null ->
30913091
tcr.Resolve(canError=false)
30923092
match box tcr.binding with
3093-
| null -> VNone
3094-
| _ -> VSome tcr.binding
3093+
| null -> ValueNone
3094+
| _ -> ValueSome tcr.binding
30953095

30963096
| _ ->
3097-
VSome tcr.binding
3097+
ValueSome tcr.binding
30983098

30993099
/// Is the destination assembly available?
31003100
member tcr.CanDeref = tcr.TryDeref.IsSome
@@ -3417,8 +3417,8 @@ and
34173417
let e = nlr.EnclosingEntity.Deref
34183418
let possible = e.ModuleOrNamespaceType.TryLinkVal(nlr.EnclosingEntity.nlr.Ccu, nlr.ItemKey)
34193419
match possible with
3420-
| VNone -> error (InternalUndefinedItemRef (FSComp.SR.tastUndefinedItemRefVal, e.DisplayNameWithStaticParameters, nlr.AssemblyName, sprintf "%+A" nlr.ItemKey.PartialKey))
3421-
| VSome h -> h
3420+
| ValueNone -> error (InternalUndefinedItemRef (FSComp.SR.tastUndefinedItemRefVal, e.DisplayNameWithStaticParameters, nlr.AssemblyName, sprintf "%+A" nlr.ItemKey.PartialKey))
3421+
| ValueSome h -> h
34223422
vr.binding <- nullableSlotFull res
34233423
res
34243424
else vr.binding
@@ -3428,14 +3428,14 @@ and
34283428
if obj.ReferenceEquals(vr.binding, null) then
34293429
let resOpt =
34303430
match vr.nlr.EnclosingEntity.TryDeref with
3431-
| VNone -> VNone
3432-
| VSome e -> e.ModuleOrNamespaceType.TryLinkVal(vr.nlr.EnclosingEntity.nlr.Ccu, vr.nlr.ItemKey)
3431+
| ValueNone -> ValueNone
3432+
| ValueSome e -> e.ModuleOrNamespaceType.TryLinkVal(vr.nlr.EnclosingEntity.nlr.Ccu, vr.nlr.ItemKey)
34333433
match resOpt with
3434-
| VNone -> ()
3435-
| VSome res ->
3434+
| ValueNone -> ()
3435+
| ValueSome res ->
34363436
vr.binding <- nullableSlotFull res
34373437
resOpt
3438-
else VSome vr.binding
3438+
else ValueSome vr.binding
34393439

34403440
/// The type of the value. May be a TType_forall for a generic value.
34413441
/// May be a type variable or type containing type variables during type inference.

0 commit comments

Comments
 (0)