diff --git a/.fantomasignore b/.fantomasignore
index a4802164d9b..20249273f54 100644
--- a/.fantomasignore
+++ b/.fantomasignore
@@ -117,6 +117,9 @@ src/Compiler/Facilities/AsyncMemoize.fsi
src/Compiler/Facilities/AsyncMemoize.fs
src/Compiler/AbstractIL/il.fs
+src/Compiler/Driver/GraphChecking/Graph.fsi
+src/Compiler/Driver/GraphChecking/Graph.fs
+
# Fantomas limitations on implementation files (to investigate)
src/Compiler/AbstractIL/ilwrite.fs
diff --git a/Directory.Build.targets b/Directory.Build.targets
index c43425cc369..c6603ea43be 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -10,16 +10,10 @@
$(ArtifactsDir)/bin/fsyacc/$(Configuration)/$(FSharpNetCoreProductDefaultTargetFramework)/$(NETCoreSdkPortableRuntimeIdentifier)/fsyacc.dll
-
-
-
-
-
-
-
+
9
0
- 100
+ 200
0
@@ -43,7 +43,7 @@
$(FSCorePackageVersionValue)-$(PreReleaseVersionLabel).*
- 12
+ 13
9
$(FSBuildVersion)
$(FSRevisionVersion)
@@ -53,7 +53,7 @@
17
- 12
+ 13
$(VSMajorVersion).0
$(VSMajorVersion).$(VSMinorVersion).0
$(VSAssemblyVersionPrefix).0
@@ -186,15 +186,12 @@
5.0.0-preview.7.20364.11
17.4.0
13.0.3
- 3.13.2
- 4.1.0
- 3.11.0
- 2.1.80
1.0.0-beta2-dev3
2.18.48
2.10.69
2.9.0
2.8.2
+ 3.1.17
5.10.3
2.2.0
diff --git a/eng/build.sh b/eng/build.sh
index 8ac4d0a9fa1..c4abb23f6f1 100755
--- a/eng/build.sh
+++ b/eng/build.sh
@@ -214,7 +214,7 @@ function Test() {
projectname=$(basename -- "$testproject")
projectname="${projectname%.*}"
testlogpath="$artifacts_dir/TestResults/$configuration/${projectname}_$targetframework.xml"
- args="test \"$testproject\" --no-restore --no-build -c $configuration -f $targetframework --test-adapter-path . --logger \"nunit;LogFilePath=$testlogpath\" --blame --results-directory $artifacts_dir/TestResults/$configuration -p:vstestusemsbuildoutput=false"
+ args="test \"$testproject\" --no-restore --no-build -c $configuration -f $targetframework --test-adapter-path . --logger \"xunit;LogFilePath=$testlogpath\" --blame --results-directory $artifacts_dir/TestResults/$configuration -p:vstestusemsbuildoutput=false"
"$DOTNET_INSTALL_DIR/dotnet" $args || exit $?
}
diff --git a/src/Compiler/AbstractIL/il.fs b/src/Compiler/AbstractIL/il.fs
index 2aadea335e1..82faea51c5e 100644
--- a/src/Compiler/AbstractIL/il.fs
+++ b/src/Compiler/AbstractIL/il.fs
@@ -1909,6 +1909,23 @@ let inline conditionalAdd condition flagToAdd source =
let NoMetadataIdx = -1
+type InterfaceImpl =
+ { Idx: int; Type: ILType; mutable CustomAttrsStored: ILAttributesStored }
+
+ member x.CustomAttrs =
+ match x.CustomAttrsStored with
+ | ILAttributesStored.Reader f ->
+ let res = ILAttributes(f x.Idx)
+ x.CustomAttrsStored <- ILAttributesStored.Given res
+ res
+ | ILAttributesStored.Given attrs -> attrs
+
+ static member Create(ilType: ILType, customAttrsStored: ILAttributesStored) =
+ { Idx = NoMetadataIdx; Type = ilType; CustomAttrsStored = customAttrsStored }
+
+ static member Create(ilType: ILType) = InterfaceImpl.Create(ilType, emptyILCustomAttrsStored)
+
+
[]
type ILMethodDef
(
@@ -2635,8 +2652,7 @@ type ILTypeDef
name: string,
attributes: TypeAttributes,
layout: ILTypeDefLayout,
- implements: ILTypes,
- implementsCustomAttrs: (ILAttributesStored * int) list option,
+ implements: InterruptibleLazy,
genericParams: ILGenericParameterDefs,
extends: ILType option,
methods: ILMethodDefs,
@@ -2659,7 +2675,6 @@ type ILTypeDef
attributes,
layout,
implements,
- implementsCustomAttrs,
genericParams,
extends,
methods,
@@ -2676,7 +2691,6 @@ type ILTypeDef
attributes,
layout,
implements,
- implementsCustomAttrs,
genericParams,
extends,
methods,
@@ -2703,8 +2717,6 @@ type ILTypeDef
member _.Implements = implements
- member _.ImplementsCustomAttrs = implementsCustomAttrs
-
member _.Extends = extends
member _.Methods = methods
@@ -2744,8 +2756,7 @@ type ILTypeDef
?properties,
?newAdditionalFlags,
?customAttrs,
- ?securityDecls,
- ?implementsCustomAttrs
+ ?securityDecls
) =
ILTypeDef(
name = defaultArg name x.Name,
@@ -2754,7 +2765,6 @@ type ILTypeDef
genericParams = defaultArg genericParams x.GenericParams,
nestedTypes = defaultArg nestedTypes x.NestedTypes,
implements = defaultArg implements x.Implements,
- implementsCustomAttrs = defaultArg implementsCustomAttrs x.ImplementsCustomAttrs,
extends = defaultArg extends x.Extends,
methods = defaultArg methods x.Methods,
securityDecls = defaultArg securityDecls x.SecurityDecls,
@@ -2903,35 +2913,17 @@ and [] ILPreTypeDef =
/// This is a memory-critical class. Very many of these objects get allocated and held to represent the contents of .NET assemblies.
and [] ILPreTypeDefImpl(nameSpace: string list, name: string, metadataIndex: int32, storage: ILTypeDefStored) =
- let mutable store: ILTypeDef = Unchecked.defaultof<_>
- let mutable storage = storage
+ let stored =
+ lazy
+ match storage with
+ | ILTypeDefStored.Given td -> td
+ | ILTypeDefStored.Computed f -> f ()
+ | ILTypeDefStored.Reader f -> f metadataIndex
interface ILPreTypeDef with
member _.Namespace = nameSpace
member _.Name = name
-
- member x.GetTypeDef() =
- match box store with
- | null ->
- let syncObj = storage
- Monitor.Enter(syncObj)
-
- try
- match box store with
- | null ->
- let value =
- match storage with
- | ILTypeDefStored.Given td -> td
- | ILTypeDefStored.Computed f -> f ()
- | ILTypeDefStored.Reader f -> f metadataIndex
-
- store <- value
- storage <- Unchecked.defaultof<_>
- value
- | _ -> store
- finally
- Monitor.Exit(syncObj)
- | _ -> store
+ member x.GetTypeDef() = stored.Value
and ILTypeDefStored =
| Given of ILTypeDef
@@ -3333,6 +3325,8 @@ let mkILTypeDefs l = mkILTypeDefsFromArray (Array.ofList l)
let mkILTypeDefsComputed f = ILTypeDefs f
let emptyILTypeDefs = mkILTypeDefsFromArray [||]
+let emptyILInterfaceImpls = InterruptibleLazy.FromValue([])
+
// --------------------------------------------------------------------
// Operations on method tables.
// --------------------------------------------------------------------
@@ -4240,7 +4234,7 @@ let mkILSimpleStorageCtor (baseTySpec, ty, extraParams, flds, access, tag, impor
let mkILStorageCtor (preblock, ty, flds, access, tag, imports) =
mkILStorageCtorWithParamNames (preblock, ty, [], addParamNames flds, access, tag, imports)
-let mkILGenericClass (nm, access, genparams, extends, impl, methods, fields, nestedTypes, props, events, attrs, init) =
+let mkILGenericClass (nm, access, genparams, extends, impls, methods, fields, nestedTypes, props, events, attrs, init) =
let attributes =
convertTypeAccessFlags access
||| TypeAttributes.AutoLayout
@@ -4254,8 +4248,7 @@ let mkILGenericClass (nm, access, genparams, extends, impl, methods, fields, nes
name = nm,
attributes = attributes,
genericParams = genparams,
- implements = impl,
- implementsCustomAttrs = None,
+ implements = InterruptibleLazy.FromValue(impls),
layout = ILTypeDefLayout.Auto,
extends = Some extends,
methods = methods,
@@ -4279,8 +4272,7 @@ let mkRawDataValueTypeDef (iltyp_ValueType: ILType) (nm, size, pack) =
||| TypeAttributes.ExplicitLayout
||| TypeAttributes.BeforeFieldInit
||| TypeAttributes.AnsiClass),
- implements = [],
- implementsCustomAttrs = None,
+ implements = emptyILInterfaceImpls,
extends = Some iltyp_ValueType,
layout = ILTypeDefLayout.Explicit { Size = Some size; Pack = Some pack },
methods = emptyILMethods,
@@ -5586,7 +5578,7 @@ and refsOfILMethodImpl s m =
and refsOfILTypeDef s (td: ILTypeDef) =
refsOfILTypeDefs s td.NestedTypes
refsOfILGenericParams s td.GenericParams
- refsOfILTypes s td.Implements
+ refsOfILTypes s (td.Implements.Value |> List.map _.Type)
Option.iter (refsOfILType s) td.Extends
refsOfILMethodDefs s td.Methods
refsOfILFieldDefs s (td.Fields.AsList())
diff --git a/src/Compiler/AbstractIL/il.fsi b/src/Compiler/AbstractIL/il.fsi
index e3ec95a40d7..1487830e8f0 100644
--- a/src/Compiler/AbstractIL/il.fsi
+++ b/src/Compiler/AbstractIL/il.fsi
@@ -327,6 +327,15 @@ type ILCallingSignature =
ArgTypes: ILTypes
ReturnType: ILType }
+type InterfaceImpl =
+ { Idx: int
+ Type: ILType
+ mutable CustomAttrsStored: ILAttributesStored }
+
+ member CustomAttrs: ILAttributes
+ static member Create: ilType: ILType * customAttrsStored: ILAttributesStored -> InterfaceImpl
+ static member Create: ilType: ILType -> InterfaceImpl
+
/// Actual generic parameters are always types.
type ILGenericArgs = ILType list
@@ -1518,8 +1527,7 @@ type ILTypeDef =
name: string *
attributes: TypeAttributes *
layout: ILTypeDefLayout *
- implements: ILTypes *
- implementsCustomAttrs: (ILAttributesStored * int) list option *
+ implements: InterruptibleLazy *
genericParams: ILGenericParameterDefs *
extends: ILType option *
methods: ILMethodDefs *
@@ -1539,8 +1547,7 @@ type ILTypeDef =
name: string *
attributes: TypeAttributes *
layout: ILTypeDefLayout *
- implements: ILTypes *
- implementsCustomAttrs: (ILAttributesStored * int) list option *
+ implements: InterruptibleLazy *
genericParams: ILGenericParameterDefs *
extends: ILType option *
methods: ILMethodDefs *
@@ -1559,8 +1566,7 @@ type ILTypeDef =
member GenericParams: ILGenericParameterDefs
member Layout: ILTypeDefLayout
member NestedTypes: ILTypeDefs
- member Implements: ILTypes
- member ImplementsCustomAttrs: (ILAttributesStored * int) list option
+ member Implements: InterruptibleLazy
member Extends: ILType option
member Methods: ILMethodDefs
member SecurityDecls: ILSecurityDecls
@@ -1609,7 +1615,7 @@ type ILTypeDef =
?name: string *
?attributes: TypeAttributes *
?layout: ILTypeDefLayout *
- ?implements: ILTypes *
+ ?implements: InterruptibleLazy *
?genericParams: ILGenericParameterDefs *
?extends: ILType option *
?methods: ILMethodDefs *
@@ -1620,8 +1626,7 @@ type ILTypeDef =
?properties: ILPropertyDefs *
?newAdditionalFlags: ILTypeDefAdditionalFlags *
?customAttrs: ILAttributesStored *
- ?securityDecls: ILSecurityDecls *
- ?implementsCustomAttrs: (ILAttributesStored * int) list option ->
+ ?securityDecls: ILSecurityDecls ->
ILTypeDef
/// Represents a prefix of information for ILTypeDef.
@@ -2161,7 +2166,7 @@ val internal mkILGenericClass:
ILTypeDefAccess *
ILGenericParameterDefs *
ILType *
- ILType list *
+ InterfaceImpl list *
ILMethodDefs *
ILFieldDefs *
ILTypeDefs *
@@ -2245,6 +2250,8 @@ val internal mkCtorMethSpecForDelegate: ILGlobals -> ILType * bool -> ILMethodSp
/// The toplevel "class" for a module or assembly.
val internal mkILTypeForGlobalFunctions: ILScopeRef -> ILType
+val emptyILInterfaceImpls: InterruptibleLazy
+
/// Making tables of custom attributes, etc.
val mkILCustomAttrs: ILAttribute list -> ILAttributes
val mkILCustomAttrsFromArray: ILAttribute[] -> ILAttributes
diff --git a/src/Compiler/AbstractIL/ilmorph.fs b/src/Compiler/AbstractIL/ilmorph.fs
index 334ed93d212..9f2f3d0582f 100644
--- a/src/Compiler/AbstractIL/ilmorph.fs
+++ b/src/Compiler/AbstractIL/ilmorph.fs
@@ -368,8 +368,13 @@ let rec tdef_ty2ty_ilmbody2ilmbody_mdefs2mdefs isInKnownSet enc fs (tdef: ILType
let mdefsR = fMethodDefs (enc, tdef) tdef.Methods
let fdefsR = fdefs_ty2ty fTyInCtxtR tdef.Fields
+ let implements =
+ tdef.Implements.Value
+ |> List.map (fun x -> { x with Type = fTyInCtxtR x.Type })
+ |> InterruptibleLazy.FromValue
+
tdef.With(
- implements = List.map fTyInCtxtR tdef.Implements,
+ implements = implements,
genericParams = gparams_ty2ty fTyInCtxtR tdef.GenericParams,
extends = Option.map fTyInCtxtR tdef.Extends,
methods = mdefsR,
diff --git a/src/Compiler/AbstractIL/ilpars.fsy b/src/Compiler/AbstractIL/ilpars.fsy
index b8380364f6b..ca06f6570be 100644
--- a/src/Compiler/AbstractIL/ilpars.fsy
+++ b/src/Compiler/AbstractIL/ilpars.fsy
@@ -2,7 +2,6 @@
%{
-#nowarn "64" // turn off warnings that type variables used in production annotations are instantiated to concrete type
#nowarn "1182" // the generated code often has unused variable "parseState"
#nowarn "3261" // the generated code would need to properly annotate nulls, e.g. changing System.Object to `obj|null`
diff --git a/src/Compiler/AbstractIL/ilprint.fs b/src/Compiler/AbstractIL/ilprint.fs
index 9d278dbe317..6ed8aec9286 100644
--- a/src/Compiler/AbstractIL/ilprint.fs
+++ b/src/Compiler/AbstractIL/ilprint.fs
@@ -752,8 +752,9 @@ let goutput_superclass env os =
output_string os "extends "
(goutput_typ_with_shortened_class_syntax env) os typ
-let goutput_implements env os (imp: ILTypes) =
+let goutput_implements env os (imp: InterfaceImpl list) =
if not (List.isEmpty imp) then
+ let imp = imp |> Seq.map _.Type
output_string os "implements "
output_seq ", " (goutput_typ_with_shortened_class_syntax env) os imp
@@ -836,7 +837,7 @@ let rec goutput_tdef enc env contents os (cd: ILTypeDef) =
output_string os "\n\t"
goutput_superclass env os cd.Extends
output_string os "\n\t"
- goutput_implements env os cd.Implements
+ goutput_implements env os cd.Implements.Value
output_string os "\n{\n "
if contents then
diff --git a/src/Compiler/AbstractIL/ilread.fs b/src/Compiler/AbstractIL/ilread.fs
index 02696c53f0e..5bedfe05752 100644
--- a/src/Compiler/AbstractIL/ilread.fs
+++ b/src/Compiler/AbstractIL/ilread.fs
@@ -2144,11 +2144,6 @@ and typeDefReader ctxtH : ILTypeDefStored =
else
let mutable attrIdx = attrsStartIdx
- let looksLikeSystemAssembly =
- ctxt.fileName.EndsWith("System.Runtime.dll")
- || ctxt.fileName.EndsWith("mscorlib.dll")
- || ctxt.fileName.EndsWith("netstandard.dll")
-
while attrIdx <= attrsEndIdx && not containsExtensionMethods do
let mutable addr = ctxt.rowAddr TableNames.CustomAttribute attrIdx
// skip parentIndex to read typeIndex
@@ -2159,12 +2154,9 @@ and typeDefReader ctxtH : ILTypeDefStored =
let name =
if attrTypeIndex.tag = cat_MethodDef then
// the ExtensionAttribute constructor can be cat_MethodDef if the metadata is read from the assembly
- // in which the corresponding attribute is defined -- from the system library
- if not looksLikeSystemAssembly then
- ""
- else
- let _, (_, nameIdx, namespaceIdx, _, _, _) = seekMethodDefParent ctxt attrCtorIdx
- readBlobHeapAsTypeName ctxt (nameIdx, namespaceIdx)
+ // in which the corresponding attribute is defined
+ let _, (_, nameIdx, namespaceIdx, _, _, _) = seekMethodDefParent ctxt attrCtorIdx
+ readBlobHeapAsTypeName ctxt (nameIdx, namespaceIdx)
else
let mutable addr = ctxt.rowAddr TableNames.MemberRef attrCtorIdx
let mrpTag = seekReadMemberRefParentIdx ctxt mdv &addr
@@ -2192,8 +2184,7 @@ and typeDefReader ctxtH : ILTypeDefStored =
let fdefs = seekReadFields ctxt (numTypars, hasLayout) fieldsIdx endFieldsIdx
let nested = seekReadNestedTypeDefs ctxt idx
- let impls, intImplsAttrs =
- seekReadInterfaceImpls ctxt mdv numTypars idx |> List.unzip
+ let impls = seekReadInterfaceImpls ctxt mdv numTypars idx
let mimpls = seekReadMethodImpls ctxt numTypars idx
let props = seekReadProperties ctxt numTypars idx
@@ -2206,7 +2197,6 @@ and typeDefReader ctxtH : ILTypeDefStored =
layout = layout,
nestedTypes = nested,
implements = impls,
- implementsCustomAttrs = Some intImplsAttrs,
extends = super,
methods = mdefs,
securityDeclsStored = ctxt.securityDeclsReader_TypeDef,
@@ -2240,19 +2230,26 @@ and seekReadNestedTypeDefs (ctxt: ILMetadataReader) tidx =
|])
and seekReadInterfaceImpls (ctxt: ILMetadataReader) mdv numTypars tidx =
- seekReadIndexedRows (
- ctxt.getNumRows TableNames.InterfaceImpl,
- id,
- id,
- (fun idx ->
- let mutable addr = ctxt.rowAddr TableNames.InterfaceImpl idx
- let _tidx = seekReadUntaggedIdx TableNames.TypeDef ctxt mdv &addr
- simpleIndexCompare tidx _tidx),
- isSorted ctxt TableNames.InterfaceImpl,
- (fun idx ->
- let intfIdx = seekReadInterfaceIdx ctxt mdv idx
- seekReadTypeDefOrRef ctxt numTypars AsObject [] intfIdx, (ctxt.customAttrsReader_InterfaceImpl, idx))
- )
+ InterruptibleLazy(fun () ->
+ seekReadIndexedRows (
+ ctxt.getNumRows TableNames.InterfaceImpl,
+ id,
+ id,
+ (fun idx ->
+ let mutable addr = ctxt.rowAddr TableNames.InterfaceImpl idx
+ let _tidx = seekReadUntaggedIdx TableNames.TypeDef ctxt mdv &addr
+ simpleIndexCompare tidx _tidx),
+ isSorted ctxt TableNames.InterfaceImpl,
+ (fun idx ->
+ let intfIdx = seekReadInterfaceIdx ctxt mdv idx
+ let ilType = seekReadTypeDefOrRef ctxt numTypars AsObject [] intfIdx
+
+ {
+ Idx = idx
+ Type = ilType
+ CustomAttrsStored = ctxt.customAttrsReader_InterfaceImpl
+ })
+ ))
and seekReadGenericParams ctxt numTypars (a, b) : ILGenericParameterDefs =
ctxt.seekReadGenericParams (GenericParamsIdx(numTypars, a, b))
diff --git a/src/Compiler/AbstractIL/ilreflect.fs b/src/Compiler/AbstractIL/ilreflect.fs
index 9b0b7eddb9e..5a52ddc017a 100644
--- a/src/Compiler/AbstractIL/ilreflect.fs
+++ b/src/Compiler/AbstractIL/ilreflect.fs
@@ -277,7 +277,7 @@ type TypeBuilder with
match m with
| null -> raise (MissingMethodException nm)
- | m -> m.Invoke(null, args)
+ | m -> m.Invoke(null, (args: obj array))
member typB.SetCustomAttributeAndLog(cinfo, bytes) =
if logRefEmitCalls then
@@ -2178,7 +2178,8 @@ let rec buildTypeDefPass2 cenv nesting emEnv (tdef: ILTypeDef) =
let typB = envGetTypB emEnv tref
let emEnv = envPushTyvars emEnv (getGenericArgumentsOfType typB)
// add interface impls
- tdef.Implements
+ tdef.Implements.Value
+ |> List.map _.Type
|> convTypes cenv emEnv
|> List.iter (fun implT -> typB.AddInterfaceImplementationAndLog implT)
// add methods, properties
@@ -2339,7 +2340,8 @@ let createTypeRef (visited: Dictionary<_, _>, created: Dictionary<_, _>) emEnv t
if verbose2 then
dprintf "buildTypeDefPass4: Creating Interface Chain of %s\n" tdef.Name
- tdef.Implements |> List.iter (traverseType CollectTypes.All)
+ tdef.Implements.Value
+ |> List.iter (fun x -> traverseType CollectTypes.All x.Type)
if verbose2 then
dprintf "buildTypeDefPass4: Do value types in fields of %s\n" tdef.Name
diff --git a/src/Compiler/AbstractIL/ilwrite.fs b/src/Compiler/AbstractIL/ilwrite.fs
index 832aa1c2810..3cbdd3c752b 100644
--- a/src/Compiler/AbstractIL/ilwrite.fs
+++ b/src/Compiler/AbstractIL/ilwrite.fs
@@ -1323,7 +1323,7 @@ and GenTypeDefPass2 pidx enc cenv (tdef: ILTypeDef) =
// Now generate or assign index numbers for tables referenced by the maps.
// Don't yet generate contents of these tables - leave that to pass3, as
// code may need to embed these entries.
- cenv.implementsIdxs[tidx] <- tdef.Implements |> List.map (GenImplementsPass2 cenv env tidx)
+ cenv.implementsIdxs[tidx] <- tdef.Implements.Value |> List.map (fun x -> GenImplementsPass2 cenv env tidx x.Type)
tdef.Fields.AsList() |> List.iter (GenFieldDefPass2 tdef cenv tidx)
tdef.Methods |> Seq.iter (GenMethodDefPass2 tdef cenv tidx)
@@ -2875,12 +2875,9 @@ let rec GenTypeDefPass3 enc cenv (tdef: ILTypeDef) =
let env = envForTypeDef tdef
let tidx = GetIdxForTypeDef cenv (TdKey(enc, tdef.Name))
- match tdef.ImplementsCustomAttrs with
- | None -> ()
- | Some attrList ->
- attrList
- |> List.zip cenv.implementsIdxs[tidx]
- |> List.iter (fun (impIdx,(attrs,metadataIdx)) -> GenCustomAttrsPass3Or4 cenv (hca_InterfaceImpl,impIdx) (attrs.GetCustomAttrs metadataIdx))
+ tdef.Implements.Value
+ |> List.zip cenv.implementsIdxs[tidx]
+ |> List.iter (fun (impIdx, impl) -> GenCustomAttrsPass3Or4 cenv (hca_InterfaceImpl,impIdx) impl.CustomAttrs)
tdef.Properties.AsList() |> List.iter (GenPropertyPass3 cenv env)
tdef.Events.AsList() |> List.iter (GenEventPass3 cenv env)
diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs
index a91ace98d4a..8ef659ac20e 100644
--- a/src/Compiler/Checking/AttributeChecking.fs
+++ b/src/Compiler/Checking/AttributeChecking.fs
@@ -466,9 +466,9 @@ let MethInfoIsUnseen g (m: range) (ty: TType) minfo =
let isUnseenByHidingAttribute () =
#if !NO_TYPEPROVIDERS
- not (isObjTy g ty) &&
+ not (isObjTyAnyNullness g ty) &&
isAppTy g ty &&
- isObjTy g minfo.ApparentEnclosingType &&
+ isObjTyAnyNullness g minfo.ApparentEnclosingType &&
let tcref = tcrefOfAppTy g ty
match tcref.TypeReprInfo with
| TProvidedTypeRepr info ->
diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs
index f9ed37fe9ca..6c79c33be97 100644
--- a/src/Compiler/Checking/ConstraintSolver.fs
+++ b/src/Compiler/Checking/ConstraintSolver.fs
@@ -1225,164 +1225,165 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr
TransactMemberConstraintSolution traitInfo trace traitSln
| _ -> ()
- if ty1 === ty2 then CompleteD else
+ if ty1 === ty2 then
+ CompleteD
+ else
+ let canShortcut = not trace.HasTrace
+ let sty1 = stripTyEqnsA csenv.g canShortcut ty1
+ let sty2 = stripTyEqnsA csenv.g canShortcut ty2
+
+ let csenv =
+ match ty1 with
+ | TType.TType_var(r,_) when r.typar_flags.IsSupportsNullFlex ->
+ { csenv with IsSupportsNullFlex = true}
+ | _ -> csenv
+
+ match sty1, sty2 with
+ // type vars inside forall-types may be alpha-equivalent
+ | TType_var (tp1, nullness1), TType_var (tp2, nullness2) when typarEq tp1 tp2 || (match aenv.EquivTypars.TryFind tp1 with | Some tpTy1 when typeEquiv g tpTy1 ty2 -> true | _ -> false) ->
+ SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2
+
+ | TType_var (tp1, nullness1), TType_var (tp2, nullness2) when PreferUnifyTypar tp1 tp2 ->
+ match nullness1.TryEvaluate(), nullness2.TryEvaluate() with
+ // Unifying 'T1? and 'T2?
+ | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull ->
+ SolveTyparEqualsType csenv ndeep m2 trace sty1 (TType_var (tp2, g.knownWithoutNull))
+ | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithoutNull ->
+ let tpNew = NewCompGenTypar(TyparKind.Type, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, false)
+ trackErrors {
+ do! SolveTypeEqualsType csenv ndeep m2 trace cxsln sty2 (TType_var(tpNew, g.knownWithNull))
+ do! SolveTypeEqualsType csenv ndeep m2 trace cxsln (TType_var(tpNew, g.knownWithoutNull)) sty1
+ }
+ //// Unifying 'T1 % and 'T2 %
+ //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull ->
+ // SolveTyparEqualsType csenv ndeep m2 trace sty1 (TType_var (tp2, g.knownWithoutNull))
+ | _ ->
+ trackErrors {
+ do! SolveTyparEqualsType csenv ndeep m2 trace sty1 ty2
+ let nullnessAfterSolution1 = combineNullness (nullnessOfTy g sty1) nullness1
+ do! SolveNullnessEquiv csenv m2 trace ty1 ty2 nullnessAfterSolution1 nullness2
+ }
- let canShortcut = not trace.HasTrace
- let sty1 = stripTyEqnsA csenv.g canShortcut ty1
- let sty2 = stripTyEqnsA csenv.g canShortcut ty2
- let csenv =
- match ty1 with
- | TType.TType_var(r,_) when r.typar_flags.IsSupportsNullFlex ->
- { csenv with IsSupportsNullFlex = true}
- | _ -> csenv
-
- match sty1, sty2 with
- // type vars inside forall-types may be alpha-equivalent
- | TType_var (tp1, nullness1), TType_var (tp2, nullness2) when typarEq tp1 tp2 || (match aenv.EquivTypars.TryFind tp1 with | Some tpTy1 when typeEquiv g tpTy1 ty2 -> true | _ -> false) ->
- SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2
-
- | TType_var (tp1, nullness1), TType_var (tp2, nullness2) when PreferUnifyTypar tp1 tp2 ->
- match nullness1.TryEvaluate(), nullness2.TryEvaluate() with
- // Unifying 'T1? and 'T2?
- | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull ->
- SolveTyparEqualsType csenv ndeep m2 trace sty1 (TType_var (tp2, g.knownWithoutNull))
- | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithoutNull ->
- let tpNew = NewCompGenTypar(TyparKind.Type, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, false)
- trackErrors {
- do! SolveTypeEqualsType csenv ndeep m2 trace cxsln sty2 (TType_var(tpNew, g.knownWithNull))
- do! SolveTypeEqualsType csenv ndeep m2 trace cxsln (TType_var(tpNew, g.knownWithoutNull)) sty1
- }
- //// Unifying 'T1 % and 'T2 %
- //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull ->
- // SolveTyparEqualsType csenv ndeep m2 trace sty1 (TType_var (tp2, g.knownWithoutNull))
- | _ ->
- trackErrors {
- do! SolveTyparEqualsType csenv ndeep m2 trace sty1 ty2
- let nullnessAfterSolution1 = combineNullness (nullnessOfTy g sty1) nullness1
- do! SolveNullnessEquiv csenv m2 trace ty1 ty2 nullnessAfterSolution1 nullness2
- }
+ | TType_var (tp1, nullness1), TType_var (tp2, nullness2) when not csenv.MatchingOnly && PreferUnifyTypar tp2 tp1 ->
+ match nullness1.TryEvaluate(), nullness2.TryEvaluate() with
+ // Unifying 'T1? and 'T2?
+ | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull ->
+ SolveTyparEqualsType csenv ndeep m2 trace sty2 (TType_var (tp1, g.knownWithoutNull))
+ | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithoutNull ->
+ let tpNew = NewCompGenTypar(TyparKind.Type, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, false)
+ trackErrors {
+ do! SolveTypeEqualsType csenv ndeep m2 trace cxsln sty2 (TType_var(tpNew, g.knownWithNull))
+ do! SolveTypeEqualsType csenv ndeep m2 trace cxsln (TType_var(tpNew, g.knownWithoutNull)) sty1
+ }
+ //// Unifying 'T1 % and 'T2 %
+ //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull ->
+ // SolveTyparEqualsType csenv ndeep m2 trace sty2 (TType_var (tp1, g.knownWithoutNull))
+ | _ ->
+ // Unifying 'T1 ? and 'T2 %
+ // Unifying 'T1 % and 'T2 ?
+ trackErrors {
+ do! SolveTyparEqualsType csenv ndeep m2 trace sty2 ty1
+ let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2
+ do! SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullnessAfterSolution2
+ }
+ | TType_var (tp1, nullness1), _ when not (IsRigid csenv tp1) ->
+ match nullness1.TryEvaluate(), (nullnessOfTy g sty2).TryEvaluate() with
+ // Unifying 'T1? and 'T2?
+ | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull ->
+ SolveTyparEqualsType csenv ndeep m2 trace sty1 (replaceNullnessOfTy g.knownWithoutNull sty2)
+ | ValueSome NullnessInfo.WithoutNull, ValueSome NullnessInfo.WithoutNull when
+ csenv.IsSupportsNullFlex &&
+ isAppTy g sty2 &&
+ tp1.Constraints |> List.exists (function TyparConstraint.SupportsNull _ -> true | _ -> false) ->
+ let tpNew = NewCompGenTypar(TyparKind.Type, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, false)
+ trackErrors {
+ do! SolveTypeEqualsType csenv ndeep m2 trace cxsln (TType_var(tpNew, g.knownWithoutNull)) sty2
+ do! SolveTypeEqualsType csenv ndeep m2 trace cxsln ty1 (TType_var(tpNew, g.knownWithNull))
+ }
+ // Unifying 'T1 % and 'T2 %
+ //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull ->
+ // SolveTyparEqualsType csenv ndeep m2 trace sty1 (replaceNullnessOfTy g.knownWithoutNull sty2)
+ | _ ->
+ trackErrors {
+ do! SolveTyparEqualsType csenv ndeep m2 trace sty1 ty2
+ let nullnessAfterSolution1 = combineNullness (nullnessOfTy g sty1) nullness1
+ do! SolveNullnessEquiv csenv m2 trace ty1 ty2 nullnessAfterSolution1 (nullnessOfTy g sty2)
+ }
- | TType_var (tp1, nullness1), TType_var (tp2, nullness2) when not csenv.MatchingOnly && PreferUnifyTypar tp2 tp1 ->
- match nullness1.TryEvaluate(), nullness2.TryEvaluate() with
- // Unifying 'T1? and 'T2?
- | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull ->
- SolveTyparEqualsType csenv ndeep m2 trace sty2 (TType_var (tp1, g.knownWithoutNull))
- | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithoutNull ->
- let tpNew = NewCompGenTypar(TyparKind.Type, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, false)
- trackErrors {
- do! SolveTypeEqualsType csenv ndeep m2 trace cxsln sty2 (TType_var(tpNew, g.knownWithNull))
- do! SolveTypeEqualsType csenv ndeep m2 trace cxsln (TType_var(tpNew, g.knownWithoutNull)) sty1
- }
- //// Unifying 'T1 % and 'T2 %
- //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull ->
- // SolveTyparEqualsType csenv ndeep m2 trace sty2 (TType_var (tp1, g.knownWithoutNull))
- | _ ->
- // Unifying 'T1 ? and 'T2 %
- // Unifying 'T1 % and 'T2 ?
+ | _, TType_var (tp2, nullness2) when not csenv.MatchingOnly && not (IsRigid csenv tp2) ->
+ match (nullnessOfTy g sty1).TryEvaluate(), nullness2.TryEvaluate() with
+ // Unifying 'T1? and 'T2?
+ | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull ->
+ SolveTyparEqualsType csenv ndeep m2 trace sty2 (replaceNullnessOfTy g.knownWithoutNull sty1)
+ // Unifying 'T1 % and 'T2 %
+ //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull ->
+ // SolveTyparEqualsType csenv ndeep m2 trace sty2 (replaceNullnessOfTy g.knownWithoutNull sty1)
+ | _ ->
+ trackErrors {
+ do! SolveTyparEqualsType csenv ndeep m2 trace sty2 ty1
+ let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2
+ do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullnessAfterSolution2
+ }
+
+ // Catch float<_>=float<1>, float32<_>=float32<1> and decimal<_>=decimal<1>
+ | (_, TType_app (tc2, [ms2], _)) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2])) ->
trackErrors {
- do! SolveTyparEqualsType csenv ndeep m2 trace sty2 ty1
- let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2
- do! SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullnessAfterSolution2
+ do! SolveTypeEqualsType csenv ndeep m2 trace None (TType_measure Measure.One) ms2
+ do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
}
- | TType_var (tp1, nullness1), _ when not (IsRigid csenv tp1) ->
- match nullness1.TryEvaluate(), (nullnessOfTy g sty2).TryEvaluate() with
- // Unifying 'T1? and 'T2?
- | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull ->
- SolveTyparEqualsType csenv ndeep m2 trace sty1 (replaceNullnessOfTy g.knownWithoutNull sty2)
- | ValueSome NullnessInfo.WithoutNull, ValueSome NullnessInfo.WithoutNull when
- csenv.IsSupportsNullFlex &&
- isAppTy g sty2 &&
- tp1.Constraints |> List.exists (function TyparConstraint.SupportsNull _ -> true | _ -> false) ->
- let tpNew = NewCompGenTypar(TyparKind.Type, TyparRigidity.Flexible, TyparStaticReq.None, TyparDynamicReq.No, false)
- trackErrors {
- do! SolveTypeEqualsType csenv ndeep m2 trace cxsln (TType_var(tpNew, g.knownWithoutNull)) sty2
- do! SolveTypeEqualsType csenv ndeep m2 trace cxsln ty1 (TType_var(tpNew, g.knownWithNull))
- }
- // Unifying 'T1 % and 'T2 %
- //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull ->
- // SolveTyparEqualsType csenv ndeep m2 trace sty1 (replaceNullnessOfTy g.knownWithoutNull sty2)
- | _ ->
+ | (TType_app (tc1, [ms1], _), _) when (tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1])) ->
trackErrors {
- do! SolveTyparEqualsType csenv ndeep m2 trace sty1 ty2
- let nullnessAfterSolution1 = combineNullness (nullnessOfTy g sty1) nullness1
- do! SolveNullnessEquiv csenv m2 trace ty1 ty2 nullnessAfterSolution1 (nullnessOfTy g sty2)
+ do! SolveTypeEqualsType csenv ndeep m2 trace None ms1 (TType_measure Measure.One)
+ do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
}
- | _, TType_var (tp2, nullness2) when not csenv.MatchingOnly && not (IsRigid csenv tp2) ->
- match (nullnessOfTy g sty1).TryEvaluate(), nullness2.TryEvaluate() with
- // Unifying 'T1? and 'T2?
- | ValueSome NullnessInfo.WithNull, ValueSome NullnessInfo.WithNull ->
- SolveTyparEqualsType csenv ndeep m2 trace sty2 (replaceNullnessOfTy g.knownWithoutNull sty1)
- // Unifying 'T1 % and 'T2 %
- //| ValueSome NullnessInfo.AmbivalentToNull, ValueSome NullnessInfo.AmbivalentToNull ->
- // SolveTyparEqualsType csenv ndeep m2 trace sty2 (replaceNullnessOfTy g.knownWithoutNull sty1)
- | _ ->
+ | TType_app (tc1, l1, _), TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 ->
trackErrors {
- do! SolveTyparEqualsType csenv ndeep m2 trace sty2 ty1
- let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2
- do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullnessAfterSolution2
+ do! SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2
+ do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
}
+ | TType_app _, TType_app _ ->
+ localAbortD
- // Catch float<_>=float<1>, float32<_>=float32<1> and decimal<_>=decimal<1>
- | (_, TType_app (tc2, [ms2], _)) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2])) ->
- trackErrors {
- do! SolveTypeEqualsType csenv ndeep m2 trace None (TType_measure Measure.One) ms2
- do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
- }
-
- | (TType_app (tc1, [ms1], _), _) when (tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1])) ->
- trackErrors {
- do! SolveTypeEqualsType csenv ndeep m2 trace None ms1 (TType_measure Measure.One)
- do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
- }
-
- | TType_app (tc1, l1, _), TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 ->
- trackErrors {
- do! SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2
- do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
- }
- | TType_app _, TType_app _ ->
- localAbortD
-
- | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) ->
- if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then
- ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2))
- else
- SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2
+ | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) ->
+ if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then
+ ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2))
+ else
+ SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2
- | TType_anon (anonInfo1, l1),TType_anon (anonInfo2, l2) ->
- trackErrors {
- do! SolveAnonInfoEqualsAnonInfo csenv m2 anonInfo1 anonInfo2
- do! SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2
- }
+ | TType_anon (anonInfo1, l1),TType_anon (anonInfo2, l2) ->
+ trackErrors {
+ do! SolveAnonInfoEqualsAnonInfo csenv m2 anonInfo1 anonInfo2
+ do! SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2
+ }
- | TType_fun (domainTy1, rangeTy1, nullness1), TType_fun (domainTy2, rangeTy2, nullness2) ->
- trackErrors {
- do! SolveFunTypeEqn csenv ndeep m2 trace None domainTy1 domainTy2 rangeTy1 rangeTy2
- do! SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2
- }
+ | TType_fun (domainTy1, rangeTy1, nullness1), TType_fun (domainTy2, rangeTy2, nullness2) ->
+ trackErrors {
+ do! SolveFunTypeEqn csenv ndeep m2 trace None domainTy1 domainTy2 rangeTy1 rangeTy2
+ do! SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2
+ }
- | TType_measure ms1, TType_measure ms2 ->
- UnifyMeasures csenv trace ms1 ms2
+ | TType_measure ms1, TType_measure ms2 ->
+ UnifyMeasures csenv trace ms1 ms2
- | TType_forall(tps1, bodyTy1), TType_forall(tps2, bodyTy2) ->
- if tps1.Length <> tps2.Length then
- localAbortD
- else
- let aenv = aenv.BindEquivTypars tps1 tps2
- let csenv = {csenv with EquivEnv = aenv }
- if not (typarsAEquiv g aenv tps1 tps2) then
+ | TType_forall(tps1, bodyTy1), TType_forall(tps2, bodyTy2) ->
+ if tps1.Length <> tps2.Length then
localAbortD
else
- SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace bodyTy1 bodyTy2
+ let aenv = aenv.BindEquivTypars tps1 tps2
+ let csenv = {csenv with EquivEnv = aenv }
+ if not (typarsAEquiv g aenv tps1 tps2) then
+ localAbortD
+ else
+ SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace bodyTy1 bodyTy2
- | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 ->
- SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2
+ | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 ->
+ SolveTypeEqualsTypeEqns csenv ndeep m2 trace None l1 l2
- | _ -> localAbortD
+ | _ -> localAbortD
and SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace ty1 ty2 =
SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace None ty1 ty2
@@ -1455,132 +1456,136 @@ and SolveFunTypeEqn csenv ndeep m2 trace cxsln domainTy1 domainTy2 rangeTy1 rang
//
// "ty2 casts to ty1"
// "a value of type ty2 can be used where a value of type ty1 is expected"
-and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) cxsln ty1 ty2 =
- // 'a :> obj --->
+and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTrace) cxsln ty1 ty2 =
let ndeep = ndeep + 1
let g = csenv.g
- if isObjTy g ty1 then CompleteD else
let canShortcut = not trace.HasTrace
- let sty1 = stripTyEqnsA csenv.g canShortcut ty1
- let sty2 = stripTyEqnsA csenv.g canShortcut ty2
- let amap = csenv.amap
- let aenv = csenv.EquivEnv
- let denv = csenv.DisplayEnv
+ // 'a :> objnull --->
+ if isObjNullTy g ty1 then
+ CompleteD
+ elif isObjTyAnyNullness g ty1 && not csenv.MatchingOnly && not(isTyparTy g ty2) then
+ let nullness t = t |> stripTyEqnsA g canShortcut |> nullnessOfTy g
+ SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullness ty1) (nullness ty2)
+ else
+ let sty1 = stripTyEqnsA csenv.g canShortcut ty1
+ let sty2 = stripTyEqnsA csenv.g canShortcut ty2
+ let amap = csenv.amap
+ let aenv = csenv.EquivEnv
+ let denv = csenv.DisplayEnv
- match sty1, sty2 with
- | TType_var (tp1, nullness1) , _ ->
- match aenv.EquivTypars.TryFind tp1 with
- | Some tpTy1 -> SolveTypeSubsumesType csenv ndeep m2 trace cxsln tpTy1 ty2
- | _ ->
- match sty2 with
- | TType_var (r2, nullness2) when typarEq tp1 r2 ->
- SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2
- | TType_var (r2, nullness2) when not csenv.MatchingOnly ->
+ match sty1, sty2 with
+ | TType_var (tp1, nullness1) , _ ->
+ match aenv.EquivTypars.TryFind tp1 with
+ | Some tpTy1 -> SolveTypeSubsumesType csenv ndeep m2 trace cxsln tpTy1 ty2
+ | _ ->
+ match sty2 with
+ | TType_var (r2, nullness2) when typarEq tp1 r2 ->
+ SolveNullnessEquiv csenv m2 trace ty1 ty2 nullness1 nullness2
+ | TType_var (r2, nullness2) when not csenv.MatchingOnly ->
+ trackErrors {
+ do! SolveTyparSubtypeOfType csenv ndeep m2 trace r2 ty1
+ let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2
+ do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 nullnessAfterSolution2
+ }
+ | _ -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ty1 ty2
+
+ | _, TType_var (r2, nullness2) when not csenv.MatchingOnly ->
trackErrors {
do! SolveTyparSubtypeOfType csenv ndeep m2 trace r2 ty1
let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2
- do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 nullnessAfterSolution2
+ do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullnessAfterSolution2
}
- | _ -> SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ty1 ty2
-
- | _, TType_var (r2, nullness2) when not csenv.MatchingOnly ->
- trackErrors {
- do! SolveTyparSubtypeOfType csenv ndeep m2 trace r2 ty1
- let nullnessAfterSolution2 = combineNullness (nullnessOfTy g sty2) nullness2
- do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) nullnessAfterSolution2
- }
-
- | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) ->
- if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then
- ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2))
- else
- SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 (* nb. can unify since no variance *)
- | TType_fun (domainTy1, rangeTy1, nullness1), TType_fun (domainTy2, rangeTy2, nullness2) ->
- // nb. can unify since no variance
- trackErrors {
- do! SolveFunTypeEqn csenv ndeep m2 trace cxsln domainTy1 domainTy2 rangeTy1 rangeTy2
- do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 nullness2
- }
- | TType_anon (anonInfo1, l1), TType_anon (anonInfo2, l2) ->
- trackErrors {
- do! SolveAnonInfoEqualsAnonInfo csenv m2 anonInfo1 anonInfo2
- do! SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2
- }
- | TType_measure ms1, TType_measure ms2 ->
- UnifyMeasures csenv trace ms1 ms2
- // Enforce the identities float=float<1>, float32=float32<1> and decimal=decimal<1>
- | _, TType_app (tc2, [ms2], _) when tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2]) ->
- trackErrors {
- do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms2 (TType_measure Measure.One)
- do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
- }
-
- | TType_app (tc1, [ms1], _), _ when tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1]) ->
- trackErrors {
- do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms1 (TType_measure Measure.One)
- do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
- }
+ | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2) ->
+ if evalTupInfoIsStruct tupInfo1 <> evalTupInfoIsStruct tupInfo2 then
+ ErrorD (ConstraintSolverError(FSComp.SR.tcTupleStructMismatch(), csenv.m, m2))
+ else
+ SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2 (* nb. can unify since no variance *)
+ | TType_fun (domainTy1, rangeTy1, nullness1), TType_fun (domainTy2, rangeTy2, nullness2) ->
+ // nb. can unify since no variance
+ trackErrors {
+ do! SolveFunTypeEqn csenv ndeep m2 trace cxsln domainTy1 domainTy2 rangeTy1 rangeTy2
+ do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 nullness1 nullness2
+ }
+ | TType_anon (anonInfo1, l1), TType_anon (anonInfo2, l2) ->
+ trackErrors {
+ do! SolveAnonInfoEqualsAnonInfo csenv m2 anonInfo1 anonInfo2
+ do! SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2
+ }
+ | TType_measure ms1, TType_measure ms2 ->
+ UnifyMeasures csenv trace ms1 ms2
- // Special subsumption rule for byref tags
- | TType_app (tc1, l1, _) , TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 && g.byref2_tcr.CanDeref && tyconRefEq g g.byref2_tcr tc1 ->
- match l1, l2 with
- | [ h1; tag1 ], [ h2; tag2 ] -> trackErrors {
- do! SolveTypeEqualsType csenv ndeep m2 trace None h1 h2
- match stripTyEqnsA csenv.g canShortcut tag1, stripTyEqnsA csenv.g canShortcut tag2 with
- | TType_app(tagc1, [], _), TType_app(tagc2, [], _)
- when (tyconRefEq g tagc2 g.byrefkind_InOut_tcr &&
- (tyconRefEq g tagc1 g.byrefkind_In_tcr || tyconRefEq g tagc1 g.byrefkind_Out_tcr) ) -> ()
- | _ -> return! SolveTypeEqualsType csenv ndeep m2 trace cxsln tag1 tag2
- }
- | _ -> SolveTypeEqualsTypeWithContravarianceEqns csenv ndeep m2 trace cxsln l1 l2 tc1.TyparsNoRange
-
- | TType_app (tc1, l1, _) , TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 ->
- trackErrors {
- do! SolveTypeEqualsTypeWithContravarianceEqns csenv ndeep m2 trace cxsln l1 l2 tc1.TyparsNoRange
- do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
- }
+ // Enforce the identities float=float<1>, float32=float32<1> and decimal=decimal<1>
+ | _, TType_app (tc2, [ms2], _) when tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2]) ->
+ trackErrors {
+ do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms2 (TType_measure Measure.One)
+ do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
+ }
- | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 ->
- SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2
+ | TType_app (tc1, [ms1], _), _ when tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1]) ->
+ trackErrors {
+ do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms1 (TType_measure Measure.One)
+ do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
+ }
- | _ ->
- // By now we know the type is not a variable type
+ // Special subsumption rule for byref tags
+ | TType_app (tc1, l1, _) , TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 && g.byref2_tcr.CanDeref && tyconRefEq g g.byref2_tcr tc1 ->
+ match l1, l2 with
+ | [ h1; tag1 ], [ h2; tag2 ] -> trackErrors {
+ do! SolveTypeEqualsType csenv ndeep m2 trace None h1 h2
+ match stripTyEqnsA csenv.g canShortcut tag1, stripTyEqnsA csenv.g canShortcut tag2 with
+ | TType_app(tagc1, [], _), TType_app(tagc2, [], _)
+ when (tyconRefEq g tagc2 g.byrefkind_InOut_tcr &&
+ (tyconRefEq g tagc1 g.byrefkind_In_tcr || tyconRefEq g tagc1 g.byrefkind_Out_tcr) ) -> ()
+ | _ -> return! SolveTypeEqualsType csenv ndeep m2 trace cxsln tag1 tag2
+ }
+ | _ -> SolveTypeEqualsTypeWithContravarianceEqns csenv ndeep m2 trace cxsln l1 l2 tc1.TyparsNoRange
- // C :> obj --->
- if isObjTy g ty1 then CompleteD else
-
- let m = csenv.m
+ | TType_app (tc1, l1, _) , TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 ->
+ trackErrors {
+ do! SolveTypeEqualsTypeWithContravarianceEqns csenv ndeep m2 trace cxsln l1 l2 tc1.TyparsNoRange
+ do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2)
+ }
- // 'a[] :> IList<'b> ---> 'a = 'b
- // 'a[] :> ICollection<'b> ---> 'a = 'b
- // 'a[] :> IEnumerable<'b> ---> 'a = 'b
- // 'a[] :> IReadOnlyList<'b> ---> 'a = 'b
- // 'a[] :> IReadOnlyCollection<'b> ---> 'a = 'b
- // Note we don't support co-variance on array types nor
- // the special .NET conversions for these types
- match ty1 with
- | AppTy g (tcref1, tinst1) when
- isArray1DTy g ty2 &&
- (tyconRefEq g tcref1 g.tcref_System_Collections_Generic_IList ||
- tyconRefEq g tcref1 g.tcref_System_Collections_Generic_ICollection ||
- tyconRefEq g tcref1 g.tcref_System_Collections_Generic_IReadOnlyList ||
- tyconRefEq g tcref1 g.tcref_System_Collections_Generic_IReadOnlyCollection ||
- tyconRefEq g tcref1 g.tcref_System_Collections_Generic_IEnumerable) ->
- match tinst1 with
- | [elemTy1] ->
- let elemTy2 = destArrayTy g ty2
- SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln elemTy1 elemTy2
- | _ -> error(InternalError("destArrayTy", m))
+ | TType_ucase (uc1, l1), TType_ucase (uc2, l2) when g.unionCaseRefEq uc1 uc2 ->
+ SolveTypeEqualsTypeEqns csenv ndeep m2 trace cxsln l1 l2
| _ ->
- // D :> Head<_> --> C :> Head<_> for the
- // first interface or super-class C supported by D which
- // may feasibly convert to Head.
- match FindUniqueFeasibleSupertype g amap m ty1 ty2 with
- | None -> ErrorD(ConstraintSolverTypesNotInSubsumptionRelation(denv, ty1, ty2, m, m2))
- | Some t -> SolveTypeSubsumesType csenv ndeep m2 trace cxsln ty1 t
+ // By now we know the type is not a variable type
+ // C :> obj --->
+ if isObjNullTy g ty1 then
+ CompleteD
+ else
+ let m = csenv.m
+ // 'a[] :> IList<'b> ---> 'a = 'b
+ // 'a[] :> ICollection<'b> ---> 'a = 'b
+ // 'a[] :> IEnumerable<'b> ---> 'a = 'b
+ // 'a[] :> IReadOnlyList<'b> ---> 'a = 'b
+ // 'a[] :> IReadOnlyCollection<'b> ---> 'a = 'b
+ // Note we don't support co-variance on array types nor
+ // the special .NET conversions for these types
+ match ty1 with
+ | AppTy g (tcref1, tinst1) when
+ isArray1DTy g ty2 &&
+ (tyconRefEq g tcref1 g.tcref_System_Collections_Generic_IList ||
+ tyconRefEq g tcref1 g.tcref_System_Collections_Generic_ICollection ||
+ tyconRefEq g tcref1 g.tcref_System_Collections_Generic_IReadOnlyList ||
+ tyconRefEq g tcref1 g.tcref_System_Collections_Generic_IReadOnlyCollection ||
+ tyconRefEq g tcref1 g.tcref_System_Collections_Generic_IEnumerable) ->
+ match tinst1 with
+ | [elemTy1] ->
+ let elemTy2 = destArrayTy g ty2
+ SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln elemTy1 elemTy2
+ | _ -> error(InternalError("destArrayTy", m))
+
+ | _ ->
+ // D :> Head<_> --> C :> Head<_> for the
+ // first interface or super-class C supported by D which
+ // may feasibly convert to Head.
+ match FindUniqueFeasibleSupertype g amap m ty1 ty2 with
+ | None -> ErrorD(ConstraintSolverTypesNotInSubsumptionRelation(denv, ty1, ty2, m, m2))
+ | Some t -> SolveTypeSubsumesType csenv ndeep m2 trace cxsln ty1 t
and SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m2 trace cxsln ty1 ty2 =
let denv = csenv.DisplayEnv
@@ -1595,15 +1600,22 @@ and SolveTypeSubsumesTypeKeepAbbrevs csenv ndeep m2 trace cxsln ty1 ty2 =
and SolveTyparSubtypeOfType (csenv: ConstraintSolverEnv) ndeep m2 trace tp ty1 =
let g = csenv.g
- if isObjTy g ty1 then CompleteD
- elif typeEquiv g ty1 (mkTyparTy tp) then CompleteD
+ if isObjNullTy g ty1 then
+ CompleteD
+ elif isObjTyAnyNullness g ty1 then
+ AddConstraint csenv ndeep m2 trace tp (TyparConstraint.NotSupportsNull csenv.m)
+ elif typeEquiv g ty1 (mkTyparTy tp) then
+ CompleteD
elif isSealedTy g ty1 then
SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace (mkTyparTy tp) ty1
else
AddConstraint csenv ndeep m2 trace tp (TyparConstraint.CoercesTo(ty1, csenv.m))
and DepthCheck ndeep m =
- if ndeep > 300 then error(Error(FSComp.SR.csTypeInferenceMaxDepth(), m)) else CompleteD
+ if ndeep > 300 then
+ error(Error(FSComp.SR.csTypeInferenceMaxDepth(), m))
+ else
+ CompleteD
// If this is a type that's parameterized on a unit-of-measure (expected to be numeric), unify its measure with 1
and SolveDimensionlessNumericType (csenv: ConstraintSolverEnv) ndeep m2 trace ty =
@@ -1625,434 +1637,435 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload
trackErrors {
let (TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, source, sln)) = traitInfo
// Do not re-solve if already solved
- if sln.Value.IsSome then return true else
-
- let g = csenv.g
- let m = csenv.m
- let amap = csenv.amap
- let aenv = csenv.EquivEnv
- let denv = csenv.DisplayEnv
+ if sln.Value.IsSome then
+ return true
+ else
+ let g = csenv.g
+ let m = csenv.m
+ let amap = csenv.amap
+ let aenv = csenv.EquivEnv
+ let denv = csenv.DisplayEnv
- let ndeep = ndeep + 1
- do! DepthCheck ndeep m
+ let ndeep = ndeep + 1
+ do! DepthCheck ndeep m
- // Remove duplicates from the set of types in the support
- let supportTys = ListSet.setify (typeAEquiv g aenv) supportTys
+ // Remove duplicates from the set of types in the support
+ let supportTys = ListSet.setify (typeAEquiv g aenv) supportTys
- // Rebuild the trait info after removing duplicates
- let traitInfo = traitInfo.WithSupportTypes supportTys
- let retTy = GetFSharpViewOfReturnType g retTy
+ // Rebuild the trait info after removing duplicates
+ let traitInfo = traitInfo.WithSupportTypes supportTys
+ let retTy = GetFSharpViewOfReturnType g retTy
- // Assert the object type if the constraint is for an instance member
- if memFlags.IsInstance then
- match supportTys, traitObjAndArgTys with
- | [ty], h :: _ -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace h ty
- | _ -> do! ErrorD (ConstraintSolverError(FSComp.SR.csExpectedArguments(), m, m2))
+ // Assert the object type if the constraint is for an instance member
+ if memFlags.IsInstance then
+ match supportTys, traitObjAndArgTys with
+ | [ty], h :: _ -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace h ty
+ | _ -> do! ErrorD (ConstraintSolverError(FSComp.SR.csExpectedArguments(), m, m2))
+
+ // Trait calls are only supported on pseudo type (variables)
+ if not (g.langVersion.SupportsFeature LanguageFeature.InterfacesWithAbstractStaticMembers) then
+ for e in supportTys do
+ do! SolveTypStaticReq csenv trace TyparStaticReq.HeadType e
+
+ // SRTP constraints on rigid type parameters do not need to be solved
+ let isRigid =
+ supportTys |> List.forall (fun ty ->
+ match tryDestTyparTy g ty with
+ | ValueSome tp ->
+ match tp.Rigidity with
+ | TyparRigidity.Rigid
+ | TyparRigidity.WillBeRigid -> true
+ | _ -> false
+ | ValueNone -> false)
+
+ let argTys = if memFlags.IsInstance then List.tail traitObjAndArgTys else traitObjAndArgTys
+
+ let minfos = GetRelevantMethodsForTrait csenv permitWeakResolution nm traitInfo
+
+ let! res =
+ trackErrors {
+ match minfos, supportTys, memFlags.IsInstance, nm, argTys with
+ | _, _, false, ("op_Division" | "op_Multiply"), [argTy1;argTy2]
+ when
+ // This simulates the existence of
+ // float * float -> float
+ // float32 * float32 -> float32
+ // float<'u> * float<'v> -> float<'u 'v>
+ // float32<'u> * float32<'v> -> float32<'u 'v>
+ // decimal<'u> * decimal<'v> -> decimal<'u 'v>
+ // decimal<'u> * decimal -> decimal<'u>
+ // float32<'u> * float32<'v> -> float32<'u 'v>
+ // int * int -> int
+ // int64 * int64 -> int64
+ //
+ // The rule is triggered by these sorts of inputs when permitWeakResolution=false
+ // float * float
+ // float * float32 // will give error
+ // decimal * decimal
+ // decimal * decimal <-- Note this one triggers even though "decimal" has some possibly-relevant methods
+ // float * Matrix // the rule doesn't trigger for this one since Matrix has overloads we can use and we prefer those instead
+ // float * Matrix // the rule doesn't trigger for this one since Matrix has overloads we can use and we prefer those instead
+ //
+ // The rule is triggered by these sorts of inputs when permitWeakResolution=true
+ // float * 'a
+ // 'a * float
+ // decimal<'u> * 'a
+ (let checkRuleAppliesInPreferenceToMethods argTy1 argTy2 =
+ // Check that at least one of the argument types is numeric
+ IsNumericOrIntegralEnumType g argTy1 &&
+ // Check the other type is nominal, unless using weak resolution
+ IsBinaryOpOtherArgType g permitWeakResolution argTy2 &&
+ // This next condition checks that either
+ // - Neither type contributes any methods OR
+ // - We have the special case "decimal<_> * decimal". In this case we have some
+ // possibly-relevant methods from "decimal" but we ignore them in this case.
+ (isNil minfos || (Option.isSome (getMeasureOfType g argTy1) && isDecimalTy g argTy2)) in
+
+ checkRuleAppliesInPreferenceToMethods argTy1 argTy2 ||
+ checkRuleAppliesInPreferenceToMethods argTy2 argTy1) ->
+
+ match getMeasureOfType g argTy1 with
+ | Some (tcref, ms1) ->
+ let ms2 = freshMeasure ()
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 (mkWoNullAppTy tcref [TType_measure ms2])
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))])
+ return TTraitBuiltIn
- // Trait calls are only supported on pseudo type (variables)
- if not (g.langVersion.SupportsFeature LanguageFeature.InterfacesWithAbstractStaticMembers) then
- for e in supportTys do
- do! SolveTypStaticReq csenv trace TyparStaticReq.HeadType e
+ | _ ->
- // SRTP constraints on rigid type parameters do not need to be solved
- let isRigid =
- supportTys |> List.forall (fun ty ->
- match tryDestTyparTy g ty with
- | ValueSome tp ->
- match tp.Rigidity with
- | TyparRigidity.Rigid
- | TyparRigidity.WillBeRigid -> true
- | _ -> false
- | ValueNone -> false)
+ match getMeasureOfType g argTy2 with
+ | Some (tcref, ms2) ->
+ let ms1 = freshMeasure ()
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkWoNullAppTy tcref [TType_measure ms1])
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))])
+ return TTraitBuiltIn
+
+ | _ ->
+
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
+ return TTraitBuiltIn
+
+ | _, _, false, ("op_Addition" | "op_Subtraction" | "op_Modulus"), [argTy1;argTy2]
+ when // Ignore any explicit +/- overloads from any basic integral types
+ (minfos |> List.forall (fun (_, minfo) -> isIntegerTy g minfo.ApparentEnclosingType ) &&
+ ( IsAddSubModType nm g argTy1 && IsBinaryOpOtherArgType g permitWeakResolution argTy2
+ || IsAddSubModType nm g argTy2 && IsBinaryOpOtherArgType g permitWeakResolution argTy1)) ->
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
+ return TTraitBuiltIn
- let argTys = if memFlags.IsInstance then List.tail traitObjAndArgTys else traitObjAndArgTys
+ | _, _, false, ("op_LessThan" | "op_LessThanOrEqual" | "op_GreaterThan" | "op_GreaterThanOrEqual" | "op_Equality" | "op_Inequality" ), [argTy1;argTy2]
+ when // Ignore any explicit overloads from any basic integral types
+ (minfos |> List.forall (fun (_, minfo) -> isIntegerTy g minfo.ApparentEnclosingType ) &&
+ ( IsRelationalType g argTy1 && IsBinaryOpOtherArgType g permitWeakResolution argTy2
+ || IsRelationalType g argTy2 && IsBinaryOpOtherArgType g permitWeakResolution argTy1)) ->
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy g.bool_ty
+ return TTraitBuiltIn
- let minfos = GetRelevantMethodsForTrait csenv permitWeakResolution nm traitInfo
+ // We pretend for uniformity that the numeric types have a static property called Zero and One
+ // As with constants, only zero is polymorphic in its units
+ | [], [ty], false, "get_Zero", []
+ when isNumericType g ty || isCharTy g ty ->
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy ty
+ return TTraitBuiltIn
- let! res =
- trackErrors {
- match minfos, supportTys, memFlags.IsInstance, nm, argTys with
- | _, _, false, ("op_Division" | "op_Multiply"), [argTy1;argTy2]
- when
- // This simulates the existence of
- // float * float -> float
- // float32 * float32 -> float32
- // float<'u> * float<'v> -> float<'u 'v>
- // float32<'u> * float32<'v> -> float32<'u 'v>
- // decimal<'u> * decimal<'v> -> decimal<'u 'v>
- // decimal<'u> * decimal -> decimal<'u>
- // float32<'u> * float32<'v> -> float32<'u 'v>
- // int * int -> int
- // int64 * int64 -> int64
- //
- // The rule is triggered by these sorts of inputs when permitWeakResolution=false
- // float * float
- // float * float32 // will give error
- // decimal * decimal
- // decimal * decimal <-- Note this one triggers even though "decimal" has some possibly-relevant methods
- // float * Matrix // the rule doesn't trigger for this one since Matrix has overloads we can use and we prefer those instead
- // float * Matrix // the rule doesn't trigger for this one since Matrix has overloads we can use and we prefer those instead
- //
- // The rule is triggered by these sorts of inputs when permitWeakResolution=true
- // float * 'a
- // 'a * float
- // decimal<'u> * 'a
- (let checkRuleAppliesInPreferenceToMethods argTy1 argTy2 =
- // Check that at least one of the argument types is numeric
- IsNumericOrIntegralEnumType g argTy1 &&
- // Check the other type is nominal, unless using weak resolution
- IsBinaryOpOtherArgType g permitWeakResolution argTy2 &&
- // This next condition checks that either
- // - Neither type contributes any methods OR
- // - We have the special case "decimal<_> * decimal". In this case we have some
- // possibly-relevant methods from "decimal" but we ignore them in this case.
- (isNil minfos || (Option.isSome (getMeasureOfType g argTy1) && isDecimalTy g argTy2)) in
-
- checkRuleAppliesInPreferenceToMethods argTy1 argTy2 ||
- checkRuleAppliesInPreferenceToMethods argTy2 argTy1) ->
-
- match getMeasureOfType g argTy1 with
- | Some (tcref, ms1) ->
- let ms2 = freshMeasure ()
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 (mkWoNullAppTy tcref [TType_measure ms2])
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))])
+ | [], [ty], false, "get_One", []
+ when isNumericType g ty || isCharTy g ty ->
+ do! SolveDimensionlessNumericType csenv ndeep m2 trace ty
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy ty
return TTraitBuiltIn
- | _ ->
+ | [], _, false, "DivideByInt", [argTy1;argTy2]
+ when isFpTy g argTy1 || isDecimalTy g argTy1 ->
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 g.int_ty
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
+ return TTraitBuiltIn
- match getMeasureOfType g argTy2 with
- | Some (tcref, ms2) ->
- let ms1 = freshMeasure ()
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkWoNullAppTy tcref [TType_measure ms1])
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))])
- return TTraitBuiltIn
+ // We pretend for uniformity that the 'string' and 'array' types have an indexer property called 'Item'
+ | [], [ty], true, "get_Item", [argTy1]
+ when isStringTy g ty ->
- | _ ->
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 g.int_ty
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy g.char_ty
+ return TTraitBuiltIn
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
- return TTraitBuiltIn
+ | [], [ty], true, "get_Item", argTys
+ when isArrayTy g ty ->
+
+ if rankOfArrayTy g ty <> argTys.Length then
+ do! ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), argTys.Length), m, m2))
+
+ for argTy in argTys do
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy g.int_ty
- | _, _, false, ("op_Addition" | "op_Subtraction" | "op_Modulus"), [argTy1;argTy2]
- when // Ignore any explicit +/- overloads from any basic integral types
- (minfos |> List.forall (fun (_, minfo) -> isIntegerTy g minfo.ApparentEnclosingType ) &&
- ( IsAddSubModType nm g argTy1 && IsBinaryOpOtherArgType g permitWeakResolution argTy2
- || IsAddSubModType nm g argTy2 && IsBinaryOpOtherArgType g permitWeakResolution argTy1)) ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
- return TTraitBuiltIn
-
- | _, _, false, ("op_LessThan" | "op_LessThanOrEqual" | "op_GreaterThan" | "op_GreaterThanOrEqual" | "op_Equality" | "op_Inequality" ), [argTy1;argTy2]
- when // Ignore any explicit overloads from any basic integral types
- (minfos |> List.forall (fun (_, minfo) -> isIntegerTy g minfo.ApparentEnclosingType ) &&
- ( IsRelationalType g argTy1 && IsBinaryOpOtherArgType g permitWeakResolution argTy2
- || IsRelationalType g argTy2 && IsBinaryOpOtherArgType g permitWeakResolution argTy1)) ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy g.bool_ty
- return TTraitBuiltIn
-
- // We pretend for uniformity that the numeric types have a static property called Zero and One
- // As with constants, only zero is polymorphic in its units
- | [], [ty], false, "get_Zero", []
- when isNumericType g ty || isCharTy g ty ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy ty
- return TTraitBuiltIn
-
- | [], [ty], false, "get_One", []
- when isNumericType g ty || isCharTy g ty ->
- do! SolveDimensionlessNumericType csenv ndeep m2 trace ty
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy ty
- return TTraitBuiltIn
-
- | [], _, false, "DivideByInt", [argTy1;argTy2]
- when isFpTy g argTy1 || isDecimalTy g argTy1 ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 g.int_ty
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
- return TTraitBuiltIn
-
- // We pretend for uniformity that the 'string' and 'array' types have an indexer property called 'Item'
- | [], [ty], true, "get_Item", [argTy1]
- when isStringTy g ty ->
-
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 g.int_ty
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy g.char_ty
- return TTraitBuiltIn
-
- | [], [ty], true, "get_Item", argTys
- when isArrayTy g ty ->
-
- if rankOfArrayTy g ty <> argTys.Length then
- do! ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), argTys.Length), m, m2))
-
- for argTy in argTys do
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy g.int_ty
-
- let ety = destArrayTy g ty
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy ety
- return TTraitBuiltIn
-
- | [], [ty], true, "set_Item", argTys
- when isArrayTy g ty ->
+ let ety = destArrayTy g ty
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy ety
+ return TTraitBuiltIn
+
+ | [], [ty], true, "set_Item", argTys
+ when isArrayTy g ty ->
- if rankOfArrayTy g ty <> argTys.Length - 1 then
- do! ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), (argTys.Length - 1)), m, m2))
- let argTys, lastTy = List.frontAndBack argTys
+ if rankOfArrayTy g ty <> argTys.Length - 1 then
+ do! ErrorD(ConstraintSolverError(FSComp.SR.csIndexArgumentMismatch((rankOfArrayTy g ty), (argTys.Length - 1)), m, m2))
+ let argTys, lastTy = List.frontAndBack argTys
+
+ for argTy in argTys do
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy g.int_ty
+
+ let elemTy = destArrayTy g ty
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace lastTy elemTy
+ return TTraitBuiltIn
- for argTy in argTys do
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy g.int_ty
+ | [], _, false, ("op_BitwiseAnd" | "op_BitwiseOr" | "op_ExclusiveOr"), [argTy1;argTy2]
+ when IsBitwiseOpType g argTy1 && IsBinaryOpOtherArgType g permitWeakResolution argTy2
+ || IsBitwiseOpType g argTy2 && IsBinaryOpOtherArgType g permitWeakResolution argTy1 ->
- let elemTy = destArrayTy g ty
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace lastTy elemTy
- return TTraitBuiltIn
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
+ do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy1
+ return TTraitBuiltIn
- | [], _, false, ("op_BitwiseAnd" | "op_BitwiseOr" | "op_ExclusiveOr"), [argTy1;argTy2]
- when IsBitwiseOpType g argTy1 && IsBinaryOpOtherArgType g permitWeakResolution argTy2
- || IsBitwiseOpType g argTy2 && IsBinaryOpOtherArgType g permitWeakResolution argTy1 ->
+ | [], _, false, ("op_LeftShift" | "op_RightShift"), [argTy1;argTy2]
+ when IsIntegerOrIntegerEnumTy g argTy1 ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
- do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy1
- return TTraitBuiltIn
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 g.int_ty
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
+ do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy1
+ return TTraitBuiltIn
- | [], _, false, ("op_LeftShift" | "op_RightShift"), [argTy1;argTy2]
- when IsIntegerOrIntegerEnumTy g argTy1 ->
+ | _, _, false, "op_UnaryPlus", [argTy]
+ when IsNumericOrIntegralEnumType g argTy ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 g.int_ty
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
- do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy1
- return TTraitBuiltIn
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
+ return TTraitBuiltIn
- | _, _, false, "op_UnaryPlus", [argTy]
- when IsNumericOrIntegralEnumType g argTy ->
+ | _, _, false, "op_UnaryNegation", [argTy]
+ when isSignedIntegerTy g argTy || isFpTy g argTy || isDecimalTy g argTy ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
- return TTraitBuiltIn
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
+ return TTraitBuiltIn
- | _, _, false, "op_UnaryNegation", [argTy]
- when isSignedIntegerTy g argTy || isFpTy g argTy || isDecimalTy g argTy ->
+ | _, _, true, "get_Sign", []
+ when IsSignType g supportTys.Head ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
- return TTraitBuiltIn
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy g.int32_ty
+ return TTraitBuiltIn
- | _, _, true, "get_Sign", []
- when IsSignType g supportTys.Head ->
+ | _, _, false, ("op_LogicalNot" | "op_OnesComplement"), [argTy]
+ when IsIntegerOrIntegerEnumTy g argTy ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy g.int32_ty
- return TTraitBuiltIn
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
+ do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy
+ return TTraitBuiltIn
- | _, _, false, ("op_LogicalNot" | "op_OnesComplement"), [argTy]
- when IsIntegerOrIntegerEnumTy g argTy ->
+ | _, _, false, "Abs", [argTy]
+ when isSignedIntegerTy g argTy || isFpTy g argTy || isDecimalTy g argTy ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
- do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy
- return TTraitBuiltIn
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
+ return TTraitBuiltIn
- | _, _, false, "Abs", [argTy]
- when isSignedIntegerTy g argTy || isFpTy g argTy || isDecimalTy g argTy ->
+ | _, _, false, "Sqrt", [argTy1]
+ when isFpTy g argTy1 ->
+ match getMeasureOfType g argTy1 with
+ | Some (tcref, _) ->
+ let ms1 = freshMeasure ()
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkWoNullAppTy tcref [TType_measure (Measure.Prod (ms1, ms1))])
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure ms1])
+ return TTraitBuiltIn
+ | None ->
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
+ return TTraitBuiltIn
+
+ | _, _, false, ("Sin" | "Cos" | "Tan" | "Sinh" | "Cosh" | "Tanh" | "Atan" | "Acos" | "Asin" | "Exp" | "Ceiling" | "Floor" | "Round" | "Truncate" | "Log10" | "Log" | "Sqrt"), [argTy]
+ when isFpTy g argTy ->
+
+ do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
+ return TTraitBuiltIn
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
- return TTraitBuiltIn
+ // Conversions from non-decimal numbers / strings / chars to non-decimal numbers / chars are built-in
+ | _, _, false, "op_Explicit", [argTy]
+ when (// The input type.
+ (IsNonDecimalNumericOrIntegralEnumType g argTy || isStringTy g argTy || isCharTy g argTy) &&
+ // The output type
+ (IsNonDecimalNumericOrIntegralEnumType g retTy || isCharTy g retTy)) ->
- | _, _, false, "Sqrt", [argTy1]
- when isFpTy g argTy1 ->
- match getMeasureOfType g argTy1 with
- | Some (tcref, _) ->
- let ms1 = freshMeasure ()
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkWoNullAppTy tcref [TType_measure (Measure.Prod (ms1, ms1))])
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure ms1])
- return TTraitBuiltIn
- | None ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
- return TTraitBuiltIn
+ return TTraitBuiltIn
+
+ // Conversions from (including decimal) numbers / strings / chars to decimals are built-in
+ | _, _, false, "op_Explicit", [argTy]
+ when (// The input type.
+ (IsNumericOrIntegralEnumType g argTy || isStringTy g argTy || isCharTy g argTy) &&
+ // The output type
+ (isDecimalTy g retTy)) ->
+ return TTraitBuiltIn
+
+ // Conversions from decimal numbers to native integers are built-in
+ // The rest of decimal conversions are handled via op_Explicit lookup on System.Decimal (which also looks for op_Implicit)
+ | _, _, false, "op_Explicit", [argTy]
+ when (// The input type.
+ (isDecimalTy g argTy) &&
+ // The output type
+ (isNativeIntegerTy g retTy)) ->
+ return TTraitBuiltIn
- | _, _, false, ("Sin" | "Cos" | "Tan" | "Sinh" | "Cosh" | "Tanh" | "Atan" | "Acos" | "Asin" | "Exp" | "Ceiling" | "Floor" | "Round" | "Truncate" | "Log10" | "Log" | "Sqrt"), [argTy]
- when isFpTy g argTy ->
-
- do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy
- return TTraitBuiltIn
-
- // Conversions from non-decimal numbers / strings / chars to non-decimal numbers / chars are built-in
- | _, _, false, "op_Explicit", [argTy]
- when (// The input type.
- (IsNonDecimalNumericOrIntegralEnumType g argTy || isStringTy g argTy || isCharTy g argTy) &&
- // The output type
- (IsNonDecimalNumericOrIntegralEnumType g retTy || isCharTy g retTy)) ->
-
- return TTraitBuiltIn
-
- // Conversions from (including decimal) numbers / strings / chars to decimals are built-in
- | _, _, false, "op_Explicit", [argTy]
- when (// The input type.
- (IsNumericOrIntegralEnumType g argTy || isStringTy g argTy || isCharTy g argTy) &&
- // The output type
- (isDecimalTy g retTy)) ->
- return TTraitBuiltIn
-
- // Conversions from decimal numbers to native integers are built-in
- // The rest of decimal conversions are handled via op_Explicit lookup on System.Decimal (which also looks for op_Implicit)
- | _, _, false, "op_Explicit", [argTy]
- when (// The input type.
- (isDecimalTy g argTy) &&
- // The output type
- (isNativeIntegerTy g retTy)) ->
- return TTraitBuiltIn
-
- | [], _, false, "Pow", [argTy1; argTy2]
- when isFpTy g argTy1 ->
+ | [], _, false, "Pow", [argTy1; argTy2]
+ when isFpTy g argTy1 ->
- do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy1
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
- return TTraitBuiltIn
-
- | _, _, false, "Atan2", [argTy1; argTy2]
- when isFpTy g argTy1 ->
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
- match getMeasureOfType g argTy1 with
- | None -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
- | Some (tcref, _) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure Measure.One])
- return TTraitBuiltIn
+ do! SolveDimensionlessNumericType csenv ndeep m2 trace argTy1
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
+ return TTraitBuiltIn
- | _ ->
- // OK, this is not solved by a built-in constraint.
- // Now look for real solutions
-
- // First look for a solution by a record property
- let recdPropSearch =
- let isGetProp = nm.StartsWithOrdinal("get_")
- let isSetProp = nm.StartsWithOrdinal("set_")
- if not isRigid && ((argTys.IsEmpty && isGetProp) || isSetProp) then
- let propName = nm[4..]
- let props =
- supportTys |> List.choose (fun ty ->
- match TryFindIntrinsicNamedItemOfType csenv.InfoReader (propName, AccessibleFromEverywhere, false) FindMemberFlag.IgnoreOverrides m ty with
- | Some (RecdFieldItem rfinfo)
- when (isGetProp || rfinfo.RecdField.IsMutable) &&
- (rfinfo.IsStatic = not memFlags.IsInstance) &&
- IsRecdFieldAccessible amap m AccessibleFromEverywhere rfinfo.RecdFieldRef &&
- not rfinfo.LiteralValue.IsSome &&
- not rfinfo.RecdField.IsCompilerGenerated ->
- Some (rfinfo, isSetProp)
- | _ -> None)
- match props with
- | [ prop ] -> Some prop
- | _ -> None
- else
- None
-
- let anonRecdPropSearch =
- let isGetProp = nm.StartsWithOrdinal("get_")
- if not isRigid && isGetProp && memFlags.IsInstance then
- let propName = nm[4..]
- let props =
- supportTys |> List.choose (fun ty ->
- match TryFindAnonRecdFieldOfType g ty propName with
- | Some (Item.AnonRecdField(anonInfo, tinst, i, _)) -> Some (anonInfo, tinst, i)
- | _ -> None)
- match props with
- | [ prop ] -> Some prop
- | _ -> None
- else
- None
-
- // Now check if there are no feasible solutions at all
- match minfos, recdPropSearch, anonRecdPropSearch with
- | [], None, None when MemberConstraintIsReadyForStrongResolution csenv traitInfo ->
- if supportTys |> List.exists (isFunTy g) then
- return! ErrorD (ConstraintSolverError(FSComp.SR.csExpectTypeWithOperatorButGivenFunction(ConvertValLogicalNameToDisplayNameCore nm), m, m2))
- elif supportTys |> List.exists (isAnyTupleTy g) then
- return! ErrorD (ConstraintSolverError(FSComp.SR.csExpectTypeWithOperatorButGivenTuple(ConvertValLogicalNameToDisplayNameCore nm), m, m2))
- else
- match nm, argTys with
- | "op_Explicit", [argTy] ->
- let argTyString = NicePrint.prettyStringOfTy denv argTy
- let rtyString = NicePrint.prettyStringOfTy denv retTy
- return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotSupportConversion(argTyString, rtyString), m, m2))
- | _ ->
- let tyString =
- match supportTys with
- | [ty] -> NicePrint.minimalStringOfType denv ty
- | _ -> supportTys |> List.map (NicePrint.minimalStringOfType denv) |> String.concat ", "
- let opName = ConvertValLogicalNameToDisplayNameCore nm
- let err =
- match opName with
- | "?>=" | "?>" | "?<=" | "?<" | "?=" | "?<>"
- | ">=?" | ">?" | "<=?" | "" | "=?" | "<>?"
- | "?>=?" | "?>?" | "?<=?" | "?" | "?=?" | "?<>?" ->
- if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperatorNullable(tyString, opName)
- else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName)
- | _ ->
- match supportTys, source.Value with
- | [_], Some s when s.StartsWith("Operators.") ->
- let opSource = s[10..]
- if opSource = nm then FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName)
- else FSComp.SR.csTypeDoesNotSupportOperator(tyString, opSource)
- | [_], Some s ->
- FSComp.SR.csFunctionDoesNotSupportType(s, tyString, nm)
- | [_], _
- -> FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName)
- | _, _
- -> FSComp.SR.csTypesDoNotSupportOperator(tyString, opName)
- return! ErrorD(ConstraintSolverError(err, m, m2))
+ | _, _, false, "Atan2", [argTy1; argTy2]
+ when isFpTy g argTy1 ->
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1
+ match getMeasureOfType g argTy1 with
+ | None -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1
+ | Some (tcref, _) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure Measure.One])
+ return TTraitBuiltIn
| _ ->
- let dummyExpr = mkUnit g m
- let calledMethGroup =
- minfos
- // curried members may not be used to satisfy constraints
- |> List.choose (fun (staticTy, minfo) ->
- if minfo.IsCurried then
- None
- else
- let callerArgs =
- {
- Unnamed = [ (argTys |> List.map (fun argTy -> CallerArg(argTy, m, false, dummyExpr))) ]
- Named = [ [ ] ]
- }
- let minst = FreshenMethInfo m minfo
- let objtys = minfo.GetObjArgTypes(amap, m, minst)
- Some(CalledMeth(csenv.InfoReader, None, false, FreshenMethInfo, m, AccessibleFromEverywhere, minfo, minst, minst, None, objtys, callerArgs, false, false, None, Some staticTy)))
-
- let methOverloadResult, errors =
- trace.CollectThenUndoOrCommit
- (fun (a, _) -> Option.isSome a)
- (fun trace -> ResolveOverloading csenv (WithTrace trace) nm ndeep (Some traitInfo) CallerArgs.Empty AccessibleFromEverywhere calledMethGroup false (Some (MustEqual retTy)))
-
- match anonRecdPropSearch, recdPropSearch, methOverloadResult with
- | Some (anonInfo, tinst, i), None, None ->
- // OK, the constraint is solved by a record property. Assert that the return types match.
- let rty2 = List.item i tinst
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy rty2
- return TTraitSolvedAnonRecdProp(anonInfo, tinst, i)
-
- | None, Some (rfinfo, isSetProp), None ->
- // OK, the constraint is solved by a record property. Assert that the return types match.
- let rty2 = if isSetProp then g.unit_ty else rfinfo.FieldType
- do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy rty2
- return TTraitSolvedRecdProp(rfinfo, isSetProp)
-
- | None, None, Some (calledMeth: CalledMeth<_>) ->
- // OK, the constraint is solved.
- let minfo = calledMeth.Method
-
- do! errors
- let isInstance = minfo.IsInstance
- if isInstance <> memFlags.IsInstance then
- return!
- if isInstance then
- ErrorD(ConstraintSolverError(FSComp.SR.csMethodFoundButIsNotStatic((NicePrint.minimalStringOfType denv minfo.ApparentEnclosingType), (ConvertValLogicalNameToDisplayNameCore nm), nm), m, m2 ))
- else
- ErrorD(ConstraintSolverError(FSComp.SR.csMethodFoundButIsStatic((NicePrint.minimalStringOfType denv minfo.ApparentEnclosingType), (ConvertValLogicalNameToDisplayNameCore nm), nm), m, m2 ))
- else
- do! CheckMethInfoAttributes g m None minfo
- return TTraitSolved (minfo, calledMeth.CalledTyArgs, calledMeth.OptionalStaticType)
+ // OK, this is not solved by a built-in constraint.
+ // Now look for real solutions
+
+ // First look for a solution by a record property
+ let recdPropSearch =
+ let isGetProp = nm.StartsWithOrdinal("get_")
+ let isSetProp = nm.StartsWithOrdinal("set_")
+ if not isRigid && ((argTys.IsEmpty && isGetProp) || isSetProp) then
+ let propName = nm[4..]
+ let props =
+ supportTys |> List.choose (fun ty ->
+ match TryFindIntrinsicNamedItemOfType csenv.InfoReader (propName, AccessibleFromEverywhere, false) FindMemberFlag.IgnoreOverrides m ty with
+ | Some (RecdFieldItem rfinfo)
+ when (isGetProp || rfinfo.RecdField.IsMutable) &&
+ (rfinfo.IsStatic = not memFlags.IsInstance) &&
+ IsRecdFieldAccessible amap m AccessibleFromEverywhere rfinfo.RecdFieldRef &&
+ not rfinfo.LiteralValue.IsSome &&
+ not rfinfo.RecdField.IsCompilerGenerated ->
+ Some (rfinfo, isSetProp)
+ | _ -> None)
+ match props with
+ | [ prop ] -> Some prop
+ | _ -> None
+ else
+ None
+
+ let anonRecdPropSearch =
+ let isGetProp = nm.StartsWithOrdinal("get_")
+ if not isRigid && isGetProp && memFlags.IsInstance then
+ let propName = nm[4..]
+ let props =
+ supportTys |> List.choose (fun ty ->
+ match TryFindAnonRecdFieldOfType g ty propName with
+ | Some (Item.AnonRecdField(anonInfo, tinst, i, _)) -> Some (anonInfo, tinst, i)
+ | _ -> None)
+ match props with
+ | [ prop ] -> Some prop
+ | _ -> None
+ else
+ None
+
+ // Now check if there are no feasible solutions at all
+ match minfos, recdPropSearch, anonRecdPropSearch with
+ | [], None, None when MemberConstraintIsReadyForStrongResolution csenv traitInfo ->
+ if supportTys |> List.exists (isFunTy g) then
+ return! ErrorD (ConstraintSolverError(FSComp.SR.csExpectTypeWithOperatorButGivenFunction(ConvertValLogicalNameToDisplayNameCore nm), m, m2))
+ elif supportTys |> List.exists (isAnyTupleTy g) then
+ return! ErrorD (ConstraintSolverError(FSComp.SR.csExpectTypeWithOperatorButGivenTuple(ConvertValLogicalNameToDisplayNameCore nm), m, m2))
+ else
+ match nm, argTys with
+ | "op_Explicit", [argTy] ->
+ let argTyString = NicePrint.prettyStringOfTy denv argTy
+ let rtyString = NicePrint.prettyStringOfTy denv retTy
+ return! ErrorD (ConstraintSolverError(FSComp.SR.csTypeDoesNotSupportConversion(argTyString, rtyString), m, m2))
+ | _ ->
+ let tyString =
+ match supportTys with
+ | [ty] -> NicePrint.minimalStringOfType denv ty
+ | _ -> supportTys |> List.map (NicePrint.minimalStringOfType denv) |> String.concat ", "
+ let opName = ConvertValLogicalNameToDisplayNameCore nm
+ let err =
+ match opName with
+ | "?>=" | "?>" | "?<=" | "?<" | "?=" | "?<>"
+ | ">=?" | ">?" | "<=?" | "" | "=?" | "<>?"
+ | "?>=?" | "?>?" | "?<=?" | "?" | "?=?" | "?<>?" ->
+ if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperatorNullable(tyString, opName)
+ else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName)
+ | _ ->
+ match supportTys, source.Value with
+ | [_], Some s when s.StartsWith("Operators.") ->
+ let opSource = s[10..]
+ if opSource = nm then FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName)
+ else FSComp.SR.csTypeDoesNotSupportOperator(tyString, opSource)
+ | [_], Some s ->
+ FSComp.SR.csFunctionDoesNotSupportType(s, tyString, nm)
+ | [_], _
+ -> FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName)
+ | _, _
+ -> FSComp.SR.csTypesDoNotSupportOperator(tyString, opName)
+ return! ErrorD(ConstraintSolverError(err, m, m2))
| _ ->
- do! AddUnsolvedMemberConstraint csenv ndeep m2 trace permitWeakResolution ignoreUnresolvedOverload traitInfo errors
- return TTraitUnsolved
- }
- return! RecordMemberConstraintSolution csenv.SolverState m trace traitInfo res
+ let dummyExpr = mkUnit g m
+ let calledMethGroup =
+ minfos
+ // curried members may not be used to satisfy constraints
+ |> List.choose (fun (staticTy, minfo) ->
+ if minfo.IsCurried then
+ None
+ else
+ let callerArgs =
+ {
+ Unnamed = [ (argTys |> List.map (fun argTy -> CallerArg(argTy, m, false, dummyExpr))) ]
+ Named = [ [ ] ]
+ }
+ let minst = FreshenMethInfo m minfo
+ let objtys = minfo.GetObjArgTypes(amap, m, minst)
+ Some(CalledMeth(csenv.InfoReader, None, false, FreshenMethInfo, m, AccessibleFromEverywhere, minfo, minst, minst, None, objtys, callerArgs, false, false, None, Some staticTy)))
+
+ let methOverloadResult, errors =
+ trace.CollectThenUndoOrCommit
+ (fun (a, _) -> Option.isSome a)
+ (fun trace -> ResolveOverloading csenv (WithTrace trace) nm ndeep (Some traitInfo) CallerArgs.Empty AccessibleFromEverywhere calledMethGroup false (Some (MustEqual retTy)))
+
+ match anonRecdPropSearch, recdPropSearch, methOverloadResult with
+ | Some (anonInfo, tinst, i), None, None ->
+ // OK, the constraint is solved by a record property. Assert that the return types match.
+ let rty2 = List.item i tinst
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy rty2
+ return TTraitSolvedAnonRecdProp(anonInfo, tinst, i)
+
+ | None, Some (rfinfo, isSetProp), None ->
+ // OK, the constraint is solved by a record property. Assert that the return types match.
+ let rty2 = if isSetProp then g.unit_ty else rfinfo.FieldType
+ do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy rty2
+ return TTraitSolvedRecdProp(rfinfo, isSetProp)
+
+ | None, None, Some (calledMeth: CalledMeth<_>) ->
+ // OK, the constraint is solved.
+ let minfo = calledMeth.Method
+
+ do! errors
+ let isInstance = minfo.IsInstance
+ if isInstance <> memFlags.IsInstance then
+ return!
+ if isInstance then
+ ErrorD(ConstraintSolverError(FSComp.SR.csMethodFoundButIsNotStatic((NicePrint.minimalStringOfType denv minfo.ApparentEnclosingType), (ConvertValLogicalNameToDisplayNameCore nm), nm), m, m2 ))
+ else
+ ErrorD(ConstraintSolverError(FSComp.SR.csMethodFoundButIsStatic((NicePrint.minimalStringOfType denv minfo.ApparentEnclosingType), (ConvertValLogicalNameToDisplayNameCore nm), nm), m, m2 ))
+ else
+ do! CheckMethInfoAttributes g m None minfo
+ return TTraitSolved (minfo, calledMeth.CalledTyArgs, calledMeth.OptionalStaticType)
+
+ | _ ->
+ do! AddUnsolvedMemberConstraint csenv ndeep m2 trace permitWeakResolution ignoreUnresolvedOverload traitInfo errors
+ return TTraitUnsolved
+ }
+ return! RecordMemberConstraintSolution csenv.SolverState m trace traitInfo res
}
and AddUnsolvedMemberConstraint csenv ndeep m2 trace permitWeakResolution ignoreUnresolvedOverload traitInfo errors =
diff --git a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
index 3a3682fbf53..c1aa4dafc5d 100644
--- a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
+++ b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
@@ -1545,7 +1545,9 @@ let rec TryTranslateComputationExpression
let dataCompPrior =
translatedCtxt (
- TranslateComputationExpressionNoQueryOps ceenv (SynExpr.YieldOrReturn((true, false), varSpaceExpr, mClause))
+ TranslateComputationExpressionNoQueryOps
+ ceenv
+ (SynExpr.YieldOrReturn((true, false), varSpaceExpr, mClause, SynExprYieldOrReturnTrivia.Zero))
)
// Rebind using for ...
@@ -1576,7 +1578,9 @@ let rec TryTranslateComputationExpression
let isYield = not (customOperationMaintainsVarSpaceUsingBind ceenv nm)
translatedCtxt (
- TranslateComputationExpressionNoQueryOps ceenv (SynExpr.YieldOrReturn((isYield, false), varSpaceExpr, mClause))
+ TranslateComputationExpressionNoQueryOps
+ ceenv
+ (SynExpr.YieldOrReturn((isYield, false), varSpaceExpr, mClause, SynExprYieldOrReturnTrivia.Zero))
)
// Now run the consumeCustomOpClauses
@@ -1589,10 +1593,10 @@ let rec TryTranslateComputationExpression
Some(TranslateComputationExpression ceenv CompExprTranslationPass.Initial q varSpace innerComp2 translatedCtxt)
else
-
if ceenv.isQuery && not (innerComp1.IsArbExprAndThusAlreadyReportedError) then
match innerComp1 with
- | SynExpr.JoinIn _ -> () // an error will be reported later when we process innerComp1 as a sequential
+ | SynExpr.JoinIn _ -> ()
+ | SynExpr.DoBang(trivia = { DoBangKeyword = m }) -> errorR (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), m))
| _ -> errorR (Error(FSComp.SR.tcUnrecognizedQueryOperator (), innerComp1.RangeOfFirstPortion))
match
@@ -1657,7 +1661,7 @@ let rec TryTranslateComputationExpression
| None ->
// "do! expr; cexpr" is treated as { let! () = expr in cexpr }
match innerComp1 with
- | SynExpr.DoBang(rhsExpr, m) ->
+ | SynExpr.DoBang(expr = rhsExpr; range = m) ->
let sp =
match sp with
| DebugPointAtSequential.SuppressExpr -> DebugPointAtBinding.NoneAtDo
@@ -1854,12 +1858,14 @@ let rec TryTranslateComputationExpression
// or
// --> build.BindReturn(e1, (fun _argN -> match _argN with pat -> expr-without-return))
| SynExpr.LetOrUseBang(
- bindDebugPoint = spBind; isUse = false; isFromSource = isFromSource; pat = pat; rhs = rhsExpr; andBangs = []; body = innerComp) ->
-
- let mBind =
- match spBind with
- | DebugPointAtBinding.Yes m -> m
- | _ -> rhsExpr.Range
+ bindDebugPoint = spBind
+ isUse = false
+ isFromSource = isFromSource
+ pat = pat
+ rhs = rhsExpr
+ andBangs = []
+ body = innerComp
+ trivia = { LetOrUseBangKeyword = mBind }) ->
if ceenv.isQuery then
error (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), mBind))
@@ -1900,7 +1906,8 @@ let rec TryTranslateComputationExpression
pat = SynPat.Named(ident = SynIdent(id, _); isThisVal = false) as pat
rhs = rhsExpr
andBangs = []
- body = innerComp)
+ body = innerComp
+ trivia = { LetOrUseBangKeyword = mBind })
| SynExpr.LetOrUseBang(
bindDebugPoint = spBind
isUse = true
@@ -1908,12 +1915,8 @@ let rec TryTranslateComputationExpression
pat = SynPat.LongIdent(longDotId = SynLongIdent(id = [ id ])) as pat
rhs = rhsExpr
andBangs = []
- body = innerComp) ->
-
- let mBind =
- match spBind with
- | DebugPointAtBinding.Yes m -> m
- | _ -> rhsExpr.Range
+ body = innerComp
+ trivia = { LetOrUseBangKeyword = mBind }) ->
if ceenv.isQuery then
error (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), mBind))
@@ -1988,9 +1991,9 @@ let rec TryTranslateComputationExpression
Some(translatedCtxt bindExpr)
// 'use! pat = e1 ... in e2' where 'pat' is not a simple name -> error
- | SynExpr.LetOrUseBang(isUse = true; pat = pat; andBangs = andBangs) ->
+ | SynExpr.LetOrUseBang(isUse = true; andBangs = andBangs; trivia = { LetOrUseBangKeyword = mBind }) ->
if isNil andBangs then
- error (Error(FSComp.SR.tcInvalidUseBangBinding (), pat.Range))
+ error (Error(FSComp.SR.tcInvalidUseBangBinding (), mBind))
else
let m =
match andBangs with
@@ -2013,17 +2016,17 @@ let rec TryTranslateComputationExpression
rhs = letRhsExpr
andBangs = andBangBindings
body = innerComp
- range = letBindRange) ->
+ trivia = { LetOrUseBangKeyword = mBind }) ->
if not (cenv.g.langVersion.SupportsFeature LanguageFeature.AndBang) then
- error (Error(FSComp.SR.tcAndBangNotSupported (), comp.Range))
+ let andBangRange =
+ match andBangBindings with
+ | [] -> comp.Range
+ | h :: _ -> h.Trivia.AndBangKeyword
- if ceenv.isQuery then
- error (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), letBindRange))
+ error (Error(FSComp.SR.tcAndBangNotSupported (), andBangRange))
- let mBind =
- match spBind with
- | DebugPointAtBinding.Yes m -> m
- | _ -> letRhsExpr.Range
+ if ceenv.isQuery then
+ error (Error(FSComp.SR.tcBindMayNotBeUsedInQueries (), mBind))
let sources =
(letRhsExpr
@@ -2375,7 +2378,7 @@ let rec TryTranslateComputationExpression
Some(translatedCtxt callExpr)
- | SynExpr.YieldOrReturnFrom((true, _), synYieldExpr, m) ->
+ | SynExpr.YieldOrReturnFrom((true, _), synYieldExpr, _, { YieldOrReturnFromKeyword = m }) ->
let yieldFromExpr =
mkSourceExpr synYieldExpr ceenv.sourceMethInfo ceenv.builderValName
@@ -2393,7 +2396,8 @@ let rec TryTranslateComputationExpression
then
error (Error(FSComp.SR.tcRequireBuilderMethod ("YieldFrom"), m))
- let yieldFromCall = mkSynCall "YieldFrom" m [ yieldFromExpr ] ceenv.builderValName
+ let yieldFromCall =
+ mkSynCall "YieldFrom" synYieldExpr.Range [ yieldFromExpr ] ceenv.builderValName
let yieldFromCall =
if IsControlFlowExpression synYieldExpr then
@@ -2403,7 +2407,7 @@ let rec TryTranslateComputationExpression
Some(translatedCtxt yieldFromCall)
- | SynExpr.YieldOrReturnFrom((false, _), synReturnExpr, m) ->
+ | SynExpr.YieldOrReturnFrom((false, _), synReturnExpr, _, { YieldOrReturnFromKeyword = m }) ->
let returnFromExpr =
mkSourceExpr synReturnExpr ceenv.sourceMethInfo ceenv.builderValName
@@ -2425,7 +2429,7 @@ let rec TryTranslateComputationExpression
error (Error(FSComp.SR.tcRequireBuilderMethod ("ReturnFrom"), m))
let returnFromCall =
- mkSynCall "ReturnFrom" m [ returnFromExpr ] ceenv.builderValName
+ mkSynCall "ReturnFrom" synReturnExpr.Range [ returnFromExpr ] ceenv.builderValName
let returnFromCall =
if IsControlFlowExpression synReturnExpr then
@@ -2435,7 +2439,7 @@ let rec TryTranslateComputationExpression
Some(translatedCtxt returnFromCall)
- | SynExpr.YieldOrReturn((isYield, _), synYieldOrReturnExpr, m) ->
+ | SynExpr.YieldOrReturn((isYield, _), synYieldOrReturnExpr, _, { YieldOrReturnKeyword = m }) ->
let methName = (if isYield then "Yield" else "Return")
if ceenv.isQuery && not isYield then
@@ -2453,10 +2457,10 @@ let rec TryTranslateComputationExpression
ceenv.builderTy
)
then
- error (Error(FSComp.SR.tcRequireBuilderMethod (methName), m))
+ error (Error(FSComp.SR.tcRequireBuilderMethod methName, m))
let yieldOrReturnCall =
- mkSynCall methName m [ synYieldOrReturnExpr ] ceenv.builderValName
+ mkSynCall methName synYieldOrReturnExpr.Range [ synYieldOrReturnExpr ] ceenv.builderValName
let yieldOrReturnCall =
if IsControlFlowExpression synYieldOrReturnExpr then
@@ -2760,7 +2764,7 @@ and TranslateComputationExpressionBind
/// The inner option indicates if a custom operation is involved inside
and convertSimpleReturnToExpr (ceenv: ComputationExpressionContext<'a>) comp varSpace innerComp =
match innerComp with
- | SynExpr.YieldOrReturn((false, _), returnExpr, m) ->
+ | SynExpr.YieldOrReturn((false, _), returnExpr, m, _) ->
let returnExpr = SynExpr.DebugPoint(DebugPointAtLeafExpr.Yes m, false, returnExpr)
Some(returnExpr, None)
@@ -2868,7 +2872,7 @@ and TranslateComputationExpression (ceenv: ComputationExpressionContext<'a>) fir
// This only occurs in final position in a sequence
match comp with
// "do! expr;" in final position is treated as { let! () = expr in return () } when Return is provided (and no Zero with Default attribute is available) or as { let! () = expr in zero } otherwise
- | SynExpr.DoBang(rhsExpr, m) ->
+ | SynExpr.DoBang(expr = rhsExpr; trivia = { DoBangKeyword = m }) ->
let mUnit = rhsExpr.Range
let rhsExpr = mkSourceExpr rhsExpr ceenv.sourceMethInfo ceenv.builderValName
@@ -2902,7 +2906,7 @@ and TranslateComputationExpression (ceenv: ComputationExpressionContext<'a>) fir
with
| minfo :: _ when MethInfoHasAttribute ceenv.cenv.g m ceenv.cenv.g.attrib_DefaultValueAttribute minfo ->
SynExpr.ImplicitZero m
- | _ -> SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m)
+ | _ -> SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m, SynExprYieldOrReturnTrivia.Zero)
let letBangBind =
SynExpr.LetOrUseBang(
diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs
index b5cc414e721..4325d503206 100644
--- a/src/Compiler/Checking/Expressions/CheckExpressions.fs
+++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs
@@ -3283,7 +3283,7 @@ let AnalyzeArbitraryExprAsEnumerable (cenv: cenv) (env: TcEnv) localAlloc m expr
let enumElemTy =
- if isObjTy g enumElemTy then
+ if isObjTyAnyNullness g enumElemTy then
// Look for an 'Item' property, or a set of these with consistent return types
let allEquivReturnTypes (minfo: MethInfo) (others: MethInfo list) =
let returnTy = minfo.GetFSharpReturnType(cenv.amap, m, [])
@@ -5991,23 +5991,23 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy.Commit, env.AccessRights)
TcQuotationExpr cenv overallTy env tpenv (oper, raw, ast, isFromQueryExpression, m)
- | SynExpr.YieldOrReturn ((isTrueYield, _), _, m)
- | SynExpr.YieldOrReturnFrom ((isTrueYield, _), _, m) when isTrueYield ->
+ | SynExpr.YieldOrReturn ((isTrueYield, _), _, _m, { YieldOrReturnKeyword = m })
+ | SynExpr.YieldOrReturnFrom ((isTrueYield, _), _, _m, { YieldOrReturnFromKeyword = m }) when isTrueYield ->
error(Error(FSComp.SR.tcConstructRequiresListArrayOrSequence(), m))
- | SynExpr.YieldOrReturn ((_, isTrueReturn), _, m)
- | SynExpr.YieldOrReturnFrom ((_, isTrueReturn), _, m) when isTrueReturn ->
+ | SynExpr.YieldOrReturn ((_, isTrueReturn), _, _m, { YieldOrReturnKeyword = m })
+ | SynExpr.YieldOrReturnFrom ((_, isTrueReturn), _, _m, { YieldOrReturnFromKeyword = m }) when isTrueReturn ->
error(Error(FSComp.SR.tcConstructRequiresComputationExpressions(), m))
- | SynExpr.YieldOrReturn (_, _, m)
- | SynExpr.YieldOrReturnFrom (_, _, m)
+ | SynExpr.YieldOrReturn (trivia = { YieldOrReturnKeyword = m })
+ | SynExpr.YieldOrReturnFrom (trivia = { YieldOrReturnFromKeyword = m })
| SynExpr.ImplicitZero m ->
error(Error(FSComp.SR.tcConstructRequiresSequenceOrComputations(), m))
- | SynExpr.DoBang (_, m)
- | SynExpr.MatchBang (range = m)
+ | SynExpr.DoBang (trivia = { DoBangKeyword = m })
+ | SynExpr.MatchBang (trivia = { MatchBangKeyword = m })
| SynExpr.WhileBang (range = m)
- | SynExpr.LetOrUseBang (range = m) ->
+ | SynExpr.LetOrUseBang (trivia = { LetOrUseBangKeyword = m }) ->
error(Error(FSComp.SR.tcConstructRequiresComputationExpression(), m))
| SynExpr.IndexFromEnd (rightExpr, m) ->
@@ -6195,7 +6195,7 @@ and TcExprObjectExpr (cenv: cenv) overallTy env tpenv (synObjTy, argopt, binds,
errorR(Error(FSComp.SR.tcCannotInheritFromErasedType(), m))
(m, intfTy, overrides), tpenv)
- let realObjTy = if isObjTy g objTy && not (isNil extraImpls) then (p23 (List.head extraImpls)) else objTy
+ let realObjTy = if isObjTyAnyNullness g objTy && not (isNil extraImpls) then (p23 (List.head extraImpls)) else objTy
TcPropagatingExprLeafThenConvert cenv overallTy realObjTy env (* canAdhoc *) m (fun () ->
TcObjectExpr cenv env tpenv (objTy, realObjTy, argopt, binds, extraImpls, mObjTy, mNewExpr, m)
@@ -7320,7 +7320,7 @@ and TcFormatStringExpr cenv (overallTy: OverallTy) env m tpenv (fmtString: strin
let formatTy = mkPrintfFormatTy g aty bty cty dty ety
// This might qualify as a format string - check via a type directed rule
- let ok = not (isObjTy g overallTy.Commit) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit formatTy
+ let ok = not (isObjTyAnyNullness g overallTy.Commit) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit formatTy
if ok then
// Parse the format string to work out the phantom types
@@ -7399,7 +7399,7 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn
Choice1Of2 (true, newFormatMethod)
// ... or if that fails then may be a FormattableString by a type-directed rule....
- elif (not (isObjTy g overallTy.Commit) &&
+ elif (not (isObjTyAnyNullness g overallTy.Commit) &&
((g.system_FormattableString_tcref.CanDeref && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit g.system_FormattableString_ty)
|| (g.system_IFormattable_tcref.CanDeref && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit g.system_IFormattable_ty))) then
@@ -7420,7 +7420,7 @@ and TcInterpolatedStringExpr cenv (overallTy: OverallTy) env m tpenv (parts: Syn
| None -> languageFeatureNotSupportedInLibraryError LanguageFeature.StringInterpolation m
// ... or if that fails then may be a PrintfFormat by a type-directed rule....
- elif not (isObjTy g overallTy.Commit) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit formatTy then
+ elif not (isObjTyAnyNullness g overallTy.Commit) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy.Commit formatTy then
// And if that succeeds, the printerTy and printerResultTy must be the same (there are no curried arguments)
UnifyTypes cenv env m printerTy printerResultTy
diff --git a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs
index 31be49131ab..781060c8af4 100644
--- a/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs
+++ b/src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs
@@ -168,7 +168,7 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT
| SynExpr.ImplicitZero m -> Some(mkSeqEmpty cenv env m genOuterTy, tpenv)
- | SynExpr.DoBang(_rhsExpr, m) -> error (Error(FSComp.SR.tcDoBangIllegalInSequenceExpression (), m))
+ | SynExpr.DoBang(trivia = { DoBangKeyword = m }) -> error (Error(FSComp.SR.tcDoBangIllegalInSequenceExpression (), m))
| SynExpr.Sequential(sp, true, innerComp1, innerComp2, m, _) ->
let env1 =
@@ -353,43 +353,44 @@ let TcSequenceExpression (cenv: TcFileState) env tpenv comp (overallTy: OverallT
Some(combinatorExpr, tpenv)
- | SynExpr.YieldOrReturnFrom((isYield, _), synYieldExpr, m) ->
+ | SynExpr.YieldOrReturnFrom(flags = (isYield, _); expr = synYieldExpr; trivia = { YieldOrReturnFromKeyword = m }) ->
let env = { env with eIsControlFlow = false }
let resultExpr, genExprTy, tpenv = TcExprOfUnknownType cenv env tpenv synYieldExpr
if not isYield then
errorR (Error(FSComp.SR.tcUseYieldBangForMultipleResults (), m))
- AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace genOuterTy genExprTy
+ AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css synYieldExpr.Range NoTrace genOuterTy genExprTy
- let resultExpr = mkCoerceExpr (resultExpr, genOuterTy, m, genExprTy)
+ let resultExpr =
+ mkCoerceExpr (resultExpr, genOuterTy, synYieldExpr.Range, genExprTy)
let resultExpr =
if IsControlFlowExpression synYieldExpr then
resultExpr
else
- mkDebugPoint m resultExpr
+ mkDebugPoint resultExpr.Range resultExpr
Some(resultExpr, tpenv)
- | SynExpr.YieldOrReturn((isYield, _), synYieldExpr, m) ->
+ | SynExpr.YieldOrReturn(flags = (isYield, _); expr = synYieldExpr; trivia = { YieldOrReturnKeyword = m }) ->
let env = { env with eIsControlFlow = false }
let genResultTy = NewInferenceType g
if not isYield then
errorR (Error(FSComp.SR.tcSeqResultsUseYield (), m))
- UnifyTypes cenv env m genOuterTy (mkSeqTy cenv.g genResultTy)
+ UnifyTypes cenv env synYieldExpr.Range genOuterTy (mkSeqTy cenv.g genResultTy)
let resultExpr, tpenv = TcExprFlex cenv flex true genResultTy env tpenv synYieldExpr
- let resultExpr = mkCallSeqSingleton cenv.g m genResultTy resultExpr
+ let resultExpr = mkCallSeqSingleton cenv.g synYieldExpr.Range genResultTy resultExpr
let resultExpr =
if IsControlFlowExpression synYieldExpr then
resultExpr
else
- mkDebugPoint m resultExpr
+ mkDebugPoint synYieldExpr.Range resultExpr
Some(resultExpr, tpenv)
diff --git a/src/Compiler/Checking/InfoReader.fs b/src/Compiler/Checking/InfoReader.fs
index f4a9f033c64..24a2d5bbf6e 100644
--- a/src/Compiler/Checking/InfoReader.fs
+++ b/src/Compiler/Checking/InfoReader.fs
@@ -1082,7 +1082,7 @@ let TryDestStandardDelegateType (infoReader: InfoReader) m ad delTy =
let g = infoReader.g
let (SigOfFunctionForDelegate(_, delArgTys, delRetTy, _)) = GetSigOfFunctionForDelegate infoReader delTy m ad
match delArgTys with
- | senderTy :: argTys when (isObjTy g senderTy) && not (List.exists (isByrefTy g) argTys) -> Some(mkRefTupledTy g argTys, delRetTy)
+ | senderTy :: argTys when (isObjTyAnyNullness g senderTy) && not (List.exists (isByrefTy g) argTys) -> Some(mkRefTupledTy g argTys, delRetTy)
| _ -> None
diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs
index 72363943549..ac4d92141d8 100644
--- a/src/Compiler/Checking/MethodCalls.fs
+++ b/src/Compiler/Checking/MethodCalls.fs
@@ -1319,7 +1319,7 @@ let BuildNewDelegateExpr (eventInfoOpt: EventInfo option, g, amap, delegateTy, d
| Some einfo ->
match delArgVals with
| [] -> error(nonStandardEventError einfo.EventName m)
- | h :: _ when not (isObjTy g h.Type) -> error(nonStandardEventError einfo.EventName m)
+ | h :: _ when not (isObjTyAnyNullness g h.Type) -> error(nonStandardEventError einfo.EventName m)
| h :: t -> [exprForVal m h; mkRefTupledVars g m t]
| None ->
if isNil delArgTys then [mkUnit g m] else List.map (exprForVal m) delArgVals
diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs
index 2eb5b14fa02..010e9e0cd8d 100644
--- a/src/Compiler/Checking/NameResolution.fs
+++ b/src/Compiler/Checking/NameResolution.fs
@@ -4422,14 +4422,14 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso
//
// Don't show GetHashCode or Equals for F# types that admit equality as an abnormal operation
let isUnseenDueToBasicObjRules =
- not (isObjTy g ty) &&
+ not (isObjTyAnyNullness g ty) &&
not minfo.IsExtensionMember &&
match minfo.LogicalName with
| "GetType" -> false
- | "GetHashCode" -> isObjTy g minfo.ApparentEnclosingType && not (AugmentTypeDefinitions.TypeDefinitelyHasEquality g ty)
+ | "GetHashCode" -> isObjTyAnyNullness g minfo.ApparentEnclosingType && not (AugmentTypeDefinitions.TypeDefinitelyHasEquality g ty)
| "ToString" -> false
| "Equals" ->
- if not (isObjTy g minfo.ApparentEnclosingType) then
+ if not (isObjTyAnyNullness g minfo.ApparentEnclosingType) then
// declaring type is not System.Object - show it
false
elif minfo.IsInstance then
@@ -4440,7 +4440,7 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv (completionTargets: Reso
true
| _ ->
// filter out self methods of obj type
- isObjTy g minfo.ApparentEnclosingType
+ isObjTyAnyNullness g minfo.ApparentEnclosingType
let result =
not isUnseenDueToBasicObjRules &&
@@ -5121,14 +5121,14 @@ let ResolveCompletionsInTypeForItem (ncenv: NameResolver) nenv m ad statics ty (
//
// Don't show GetHashCode or Equals for F# types that admit equality as an abnormal operation
let isUnseenDueToBasicObjRules =
- not (isObjTy g ty) &&
+ not (isObjTyAnyNullness g ty) &&
not minfo.IsExtensionMember &&
match minfo.LogicalName with
| "GetType" -> false
- | "GetHashCode" -> isObjTy g minfo.ApparentEnclosingType && not (AugmentTypeDefinitions.TypeDefinitelyHasEquality g ty)
+ | "GetHashCode" -> isObjTyAnyNullness g minfo.ApparentEnclosingType && not (AugmentTypeDefinitions.TypeDefinitelyHasEquality g ty)
| "ToString" -> false
| "Equals" ->
- if not (isObjTy g minfo.ApparentEnclosingType) then
+ if not (isObjTyAnyNullness g minfo.ApparentEnclosingType) then
// declaring type is not System.Object - show it
false
elif minfo.IsInstance then
@@ -5139,7 +5139,7 @@ let ResolveCompletionsInTypeForItem (ncenv: NameResolver) nenv m ad statics ty (
true
| _ ->
// filter out self methods of obj type
- isObjTy g minfo.ApparentEnclosingType
+ isObjTyAnyNullness g minfo.ApparentEnclosingType
let result =
not isUnseenDueToBasicObjRules &&
not minfo.IsInstance = statics &&
diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs
index 812837a3edd..09e8708b894 100644
--- a/src/Compiler/Checking/NicePrint.fs
+++ b/src/Compiler/Checking/NicePrint.fs
@@ -2191,7 +2191,7 @@ module TastDefinitionPrinting =
let inherits =
[ if not (suppressInheritanceAndInterfacesForTyInSimplifiedDisplays g amap m ty) then
match GetSuperTypeOfType g amap m ty with
- | Some superTy when not (isObjTy g superTy) && not (isValueTypeTy g superTy) ->
+ | Some superTy when not (isObjTyAnyNullness g superTy) && not (isValueTypeTy g superTy) ->
superTy
| _ -> ()
]
diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs
index e9860a76efa..645f43fe3cb 100644
--- a/src/Compiler/Checking/PostInferenceChecks.fs
+++ b/src/Compiler/Checking/PostInferenceChecks.fs
@@ -1958,7 +1958,8 @@ and CheckAttribArgExpr cenv env expr =
| Const.Single _
| Const.Char _
| Const.Zero
- | Const.String _ -> ()
+ | Const.String _
+ | Const.Decimal _ -> ()
| _ ->
if cenv.reportErrors then
errorR (Error (FSComp.SR.tastNotAConstantExpression(), m))
diff --git a/src/Compiler/Checking/TypeHierarchy.fs b/src/Compiler/Checking/TypeHierarchy.fs
index 1ccde31b75e..9bf7c2ec892 100644
--- a/src/Compiler/Checking/TypeHierarchy.fs
+++ b/src/Compiler/Checking/TypeHierarchy.fs
@@ -67,7 +67,7 @@ let GetSuperTypeOfType g amap m ty =
Some (instType (mkInstForAppTy g ty) (superOfTycon g tcref.Deref))
elif isArrayTy g ty then
Some g.system_Array_ty
- elif isRefTy g ty && not (isObjTy g ty) then
+ elif isRefTy g ty && not (isObjTyAnyNullness g ty) then
Some g.obj_ty_noNulls
elif isStructTupleTy g ty then
Some g.system_Value_ty
@@ -117,17 +117,16 @@ let GetImmediateInterfacesOfMetadataType g amap m skipUnref ty (tcref: TyconRef)
// succeeded with more reported. There are pathological corner cases where this
// doesn't apply: e.g. for mscorlib interfaces like IComparable, but we can always
// assume those are present.
- match tdef.ImplementsCustomAttrs with
- | Some attrsList when g.langFeatureNullness && g.checkNullness ->
- for (attrs,attrsIdx),intfTy in tdef.Implements |> List.zip attrsList do
- if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then
+ let checkNullness = g.langFeatureNullness && g.checkNullness
+ for {Idx = attrsIdx; Type = intfTy; CustomAttrsStored = attrs} in tdef.Implements.Value do
+ if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then
+ if checkNullness then
let typeAttrs = AttributesFromIL(attrsIdx,attrs)
let nullness = {DirectAttributes = typeAttrs; Fallback = FromClass typeAttrs}
RescopeAndImportILType scoref amap m tinst nullness intfTy
- | _ ->
- for intfTy in tdef.Implements do
- if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then
+ else
RescopeAndImportILTypeSkipNullness scoref amap m tinst intfTy
+
| FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata ->
for intfTy in tcref.ImmediateInterfaceTypesOfFSharpTycon do
instType (mkInstForAppTy g ty) intfTy ]
diff --git a/src/Compiler/Checking/TypeRelations.fs b/src/Compiler/Checking/TypeRelations.fs
index b52a1da1574..498fd3e3bb8 100644
--- a/src/Compiler/Checking/TypeRelations.fs
+++ b/src/Compiler/Checking/TypeRelations.fs
@@ -117,7 +117,7 @@ let rec TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce ty2 =
| _ ->
// F# reference types are subtypes of type 'obj'
- (isObjTy g ty1 && (canCoerce = CanCoerce || isRefTy g ty2))
+ (isObjTyAnyNullness g ty1 && (canCoerce = CanCoerce || isRefTy g ty2))
||
(isAppTy g ty2 &&
(canCoerce = CanCoerce || isRefTy g ty2) &&
diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs
index 23afa7bece5..18add6588d0 100644
--- a/src/Compiler/Checking/infos.fs
+++ b/src/Compiler/Checking/infos.fs
@@ -207,7 +207,7 @@ type OptionalArgInfo =
if isByrefTy g ty then
let ty = destByrefTy g ty
PassByRef (ty, analyze ty)
- elif isObjTy g ty then
+ elif isObjTyAnyNullness g ty then
match ilParam.Marshal with
| Some(ILNativeType.IUnknown | ILNativeType.IDispatch | ILNativeType.Interface) -> Constant ILFieldInit.Null
| _ ->
@@ -296,7 +296,7 @@ let CrackParamAttribsInfo g (ty: TType, argInfo: ArgReprInfo) =
| None ->
// Do a type-directed analysis of the type to determine the default value to pass.
// Similar rules as OptionalArgInfo.FromILParameter are applied here, except for the COM and byref-related stuff.
- CallerSide (if isObjTy g ty then MissingValue else DefaultValue)
+ CallerSide (if isObjTyAnyNullness g ty then MissingValue else DefaultValue)
| Some attr ->
let defaultValue = OptionalArgInfo.ValueOfDefaultParameterValueAttrib attr
match defaultValue with
@@ -364,7 +364,9 @@ type ILFieldInit with
| :? uint32 as i -> ILFieldInit.UInt32 i
| :? int64 as i -> ILFieldInit.Int64 i
| :? uint64 as i -> ILFieldInit.UInt64 i
- | _ -> error(Error(FSComp.SR.infosInvalidProvidedLiteralValue(try !!v.ToString() with _ -> "?"), m))
+ | _ ->
+ let txt = match v with | null -> "?" | v -> try !!v.ToString() with _ -> "?"
+ error(Error(FSComp.SR.infosInvalidProvidedLiteralValue(txt), m))
/// Compute the OptionalArgInfo for a provided parameter.
@@ -382,7 +384,7 @@ let OptionalArgInfoOfProvidedParameter (amap: ImportMap) m (provParam : Tainted<
if isByrefTy g ty then
let ty = destByrefTy g ty
PassByRef (ty, analyze ty)
- elif isObjTy g ty then MissingValue
+ elif isObjTyAnyNullness g ty then MissingValue
else DefaultValue
let paramTy = ImportProvidedType amap m (provParam.PApply((fun p -> p.ParameterType), m))
diff --git a/src/Compiler/CodeGen/EraseClosures.fs b/src/Compiler/CodeGen/EraseClosures.fs
index ed32d83b369..df2604717ed 100644
--- a/src/Compiler/CodeGen/EraseClosures.fs
+++ b/src/Compiler/CodeGen/EraseClosures.fs
@@ -572,8 +572,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo =
name = td.Name,
genericParams = td.GenericParams,
attributes = td.Attributes,
- implements = [],
- implementsCustomAttrs = None,
+ implements = emptyILInterfaceImpls,
nestedTypes = emptyILTypeDefs,
layout = ILTypeDefLayout.Auto,
extends = Some cenv.mkILTyFuncTy,
@@ -707,8 +706,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo =
name = td.Name,
genericParams = td.GenericParams,
attributes = td.Attributes,
- implements = [],
- implementsCustomAttrs = None,
+ implements = emptyILInterfaceImpls,
layout = ILTypeDefLayout.Auto,
nestedTypes = emptyILTypeDefs,
extends = Some nowEnvParentClass,
diff --git a/src/Compiler/CodeGen/EraseUnions.fs b/src/Compiler/CodeGen/EraseUnions.fs
index 88336c057b2..79788107475 100644
--- a/src/Compiler/CodeGen/EraseUnions.fs
+++ b/src/Compiler/CodeGen/EraseUnions.fs
@@ -1571,8 +1571,7 @@ let mkClassUnionDef
genericParams = td.GenericParams,
attributes = enum 0,
layout = ILTypeDefLayout.Auto,
- implements = [],
- implementsCustomAttrs = None,
+ implements = emptyILInterfaceImpls,
extends = Some g.ilg.typ_Object,
methods = emptyILMethods,
securityDecls = emptyILSecurityDecls,
diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs
index 6758b6dcd94..2a1c876b8f5 100644
--- a/src/Compiler/CodeGen/IlxGen.fs
+++ b/src/Compiler/CodeGen/IlxGen.fs
@@ -2227,7 +2227,8 @@ type AnonTypeGenerationTable() =
let ilInterfaceTys =
[
- for intfTy, _, _ in tcaug.tcaug_interfaces -> GenType cenv m (TypeReprEnv.Empty.ForTypars tps) intfTy
+ for intfTy, _, _ in tcaug.tcaug_interfaces ->
+ GenType cenv m (TypeReprEnv.Empty.ForTypars tps) intfTy |> InterfaceImpl.Create
]
let ilTypeDef =
@@ -3781,11 +3782,11 @@ and GenCoerce cenv cgbuf eenv (e, tgtTy, m, srcTy) sequel =
else
GenExpr cenv cgbuf eenv e Continue
- if not (isObjTy g srcTy) then
+ if not (isObjTyAnyNullness g srcTy) then
let ilFromTy = GenType cenv m eenv.tyenv srcTy
CG.EmitInstr cgbuf (pop 1) (Push [ g.ilg.typ_Object ]) (I_box ilFromTy)
- if not (isObjTy g tgtTy) then
+ if not (isObjTyAnyNullness g tgtTy) then
let ilToTy = GenType cenv m eenv.tyenv tgtTy
CG.EmitInstr cgbuf (pop 1) (Push [ ilToTy ]) (I_unbox_any ilToTy)
@@ -6023,7 +6024,8 @@ and GenStructStateMachine cenv cgbuf eenvouter (res: LoweredStateMachine) sequel
let interfaceTys =
GetImmediateInterfacesOfType SkipUnrefInterfaces.Yes g cenv.amap m templateStructTy
- let ilInterfaceTys = List.map (GenType cenv m eenvinner.tyenv) interfaceTys
+ let ilInterfaceTys =
+ List.map (GenType cenv m eenvinner.tyenv >> InterfaceImpl.Create) interfaceTys
let super = g.iltyp_ValueType
@@ -6254,8 +6256,7 @@ and GenStructStateMachine cenv cgbuf eenvouter (res: LoweredStateMachine) sequel
methods = mkILMethods mdefs,
methodImpls = mkILMethodImpls mimpls,
nestedTypes = emptyILTypeDefs,
- implements = ilInterfaceTys,
- implementsCustomAttrs = None,
+ implements = InterruptibleLazy.FromValue(ilInterfaceTys),
extends = Some super,
additionalFlags = ILTypeDefAdditionalFlags.None,
securityDecls = emptyILSecurityDecls
@@ -6381,7 +6382,8 @@ and GenObjectExpr cenv cgbuf eenvouter objExpr (baseType, baseValOpt, basecall,
let mimpls = mimpls |> List.choose id // choose the ones that actually have method impls
let interfaceTys =
- interfaceImpls |> List.map (fst >> GenType cenv m eenvinner.tyenv)
+ interfaceImpls
+ |> List.map (fst >> GenType cenv m eenvinner.tyenv >> InterfaceImpl.Create)
let super =
(if isInterfaceTy g baseType then
@@ -6390,7 +6392,11 @@ and GenObjectExpr cenv cgbuf eenvouter objExpr (baseType, baseValOpt, basecall,
ilCloRetTy)
let interfaceTys =
- interfaceTys @ (if isInterfaceTy g baseType then [ ilCloRetTy ] else [])
+ interfaceTys
+ @ (if isInterfaceTy g baseType then
+ [ InterfaceImpl.Create(ilCloRetTy) ]
+ else
+ [])
let cloTypeDefs =
GenClosureTypeDefs
@@ -6688,8 +6694,7 @@ and GenClosureTypeDefs
methods = mkILMethods mdefs,
methodImpls = mkILMethodImpls mimpls,
nestedTypes = emptyILTypeDefs,
- implements = ilIntfTys,
- implementsCustomAttrs = None,
+ implements = InterruptibleLazy.FromValue(ilIntfTys),
extends = Some ext,
additionalFlags = ILTypeDefAdditionalFlags.None,
securityDecls = emptyILSecurityDecls
@@ -8558,10 +8563,15 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv bind isStateVar startMarkOpt =
let ilFieldDef = mkILStaticField (fspec.Name, fty, None, None, access)
+ let isDecimalConstant =
+ match vref.LiteralValue with
+ | Some(Const.Decimal _) -> true
+ | _ -> false
+
let ilFieldDef =
match vref.LiteralValue with
- | Some konst -> ilFieldDef.WithLiteralDefaultValue(Some(GenFieldInit m konst))
- | None -> ilFieldDef
+ | Some konst when not isDecimalConstant -> ilFieldDef.WithLiteralDefaultValue(Some(GenFieldInit m konst))
+ | _ -> ilFieldDef
let ilFieldDef =
let isClassInitializer = (cgbuf.MethodName = ".cctor")
@@ -8573,6 +8583,7 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv bind isStateVar startMarkOpt =
|| not isClassInitializer
|| hasLiteralAttr
)
+ || isDecimalConstant
)
let ilAttribs =
@@ -8585,6 +8596,64 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv bind isStateVar startMarkOpt =
let ilAttribs = GenAdditionalAttributesForTy g vspec.Type @ ilAttribs
+ let ilAttribs =
+ if isDecimalConstant then
+ match vref.LiteralValue with
+ | Some(Const.Decimal d) ->
+ match System.Decimal.GetBits d with
+ | [| lo; med; hi; signExp |] ->
+ let scale = (min (((signExp &&& 0xFF0000) >>> 16) &&& 0xFF) 28) |> byte
+ let sign = if (signExp &&& 0x80000000) <> 0 then 1uy else 0uy
+
+ let attrib =
+ mkILCustomAttribute (
+ g.attrib_DecimalConstantAttribute.TypeRef,
+ [
+ g.ilg.typ_Byte
+ g.ilg.typ_Byte
+ g.ilg.typ_Int32
+ g.ilg.typ_Int32
+ g.ilg.typ_Int32
+ ],
+ [
+ ILAttribElem.Byte scale
+ ILAttribElem.Byte sign
+ ILAttribElem.UInt32(uint32 hi)
+ ILAttribElem.UInt32(uint32 med)
+ ILAttribElem.UInt32(uint32 lo)
+ ],
+ []
+ )
+
+ let ilInstrs =
+ [
+ mkLdcInt32 lo
+ mkLdcInt32 med
+ mkLdcInt32 hi
+ mkLdcInt32 (int32 sign)
+ mkLdcInt32 (int32 scale)
+ mkNormalNewobj (
+ mkILCtorMethSpecForTy (
+ fspec.ActualType,
+ [
+ g.ilg.typ_Int32
+ g.ilg.typ_Int32
+ g.ilg.typ_Int32
+ g.ilg.typ_Bool
+ g.ilg.typ_Byte
+ ]
+ )
+ )
+ mkNormalStsfld fspec
+ ]
+
+ CG.EmitInstrs cgbuf (pop 0) (Push0) ilInstrs
+ [ attrib ]
+ | _ -> failwith "unreachable"
+ | _ -> failwith "unreachable"
+ else
+ ilAttribs
+
let ilFieldDef =
ilFieldDef.With(customAttrs = mkILCustomAttrs (ilAttribs @ [ g.DebuggerBrowsableNeverAttribute ]))
@@ -10770,23 +10839,20 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) : ILTypeRef option
let ilThisTy = GenType cenv m eenvinner.tyenv thisTy
let tref = ilThisTy.TypeRef
let ilGenParams = GenGenericParams cenv eenvinner tycon.TyparsNoRange
+ let checkNullness = g.langFeatureNullness && g.checkNullness
let ilIntfTys =
tycon.ImmediateInterfaceTypesOfFSharpTycon
- |> List.map (GenType cenv m eenvinner.tyenv)
-
- let ilIntCustomAttrs =
- if g.langFeatureNullness && g.checkNullness && not (isNil ilIntfTys) then
- tycon.ImmediateInterfaceTypesOfFSharpTycon
- |> List.map (
- GenAdditionalAttributesForTy g
- >> mkILCustomAttrs
- >> ILAttributesStored.Given
- >> (fun x -> x, 0)
- )
- |> Some
- else
- None
+ |> List.map (fun x ->
+ let ilType = GenType cenv m eenvinner.tyenv x
+
+ let customAttrs =
+ if checkNullness then
+ GenAdditionalAttributesForTy g x |> mkILCustomAttrs |> ILAttributesStored.Given
+ else
+ emptyILCustomAttrsStored
+
+ InterfaceImpl.Create(ilType, customAttrs))
let ilTypeName = tref.Name
@@ -11447,11 +11513,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) : ILTypeRef option
.WithSerializable(isSerializable)
.WithAbstract(isAbstract)
.WithImport(isComInteropTy g thisTy)
- .With(
- methodImpls = mkILMethodImpls methodImpls,
- newAdditionalFlags = additionalFlags,
- implementsCustomAttrs = ilIntCustomAttrs
- )
+ .With(methodImpls = mkILMethodImpls methodImpls, newAdditionalFlags = additionalFlags)
let tdLayout, tdEncoding =
match TryFindFSharpAttribute g g.attrib_StructLayoutAttribute tycon.Attribs with
@@ -11613,8 +11675,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) : ILTypeRef option
methods = mkILMethods ilMethods,
methodImpls = mkILMethodImpls methodImpls,
nestedTypes = emptyILTypeDefs,
- implements = ilIntfTys,
- implementsCustomAttrs = None,
+ implements = InterruptibleLazy.FromValue(ilIntfTys),
extends =
Some(
if tycon.IsStructOrEnumTycon then
@@ -11837,7 +11898,7 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) : ILTypeRef option =
let interfaces =
exnc.ImmediateInterfaceTypesOfFSharpTycon
- |> List.map (GenType cenv m eenv.tyenv)
+ |> List.map (GenType cenv m eenv.tyenv >> InterfaceImpl.Create)
let tdef =
mkILGenericClass (
@@ -12121,7 +12182,7 @@ let LookupGeneratedValue (cenv: cenv) (ctxt: ExecutionContext) eenv (v: Val) =
None
// Invoke the set_Foo method for a declaration with a value. Used to create variables with values programmatically in fsi.exe.
-let SetGeneratedValue (ctxt: ExecutionContext) eenv isForced (v: Val) (value: obj) =
+let SetGeneratedValue (ctxt: ExecutionContext) eenv isForced (v: Val) (value: objnull) =
try
match StorageForVal v.Range v eenv with
| StaticPropertyWithField(fspec, _, hasLiteralAttr, _, _, _, _f, ilSetterMethRef, _) ->
diff --git a/src/Compiler/CodeGen/IlxGenSupport.fs b/src/Compiler/CodeGen/IlxGenSupport.fs
index 073b4473ea9..0e163db4069 100644
--- a/src/Compiler/CodeGen/IlxGenSupport.fs
+++ b/src/Compiler/CodeGen/IlxGenSupport.fs
@@ -46,7 +46,7 @@ let mkLocalPrivateAttributeWithDefaultConstructor (g: TcGlobals, name: string) =
ILTypeDefAccess.Private,
ILGenericParameterDefs.Empty,
g.ilg.typ_Attribute,
- ILTypes.Empty,
+ [],
ilMethods,
emptyILFields,
emptyILTypeDefs,
@@ -140,7 +140,7 @@ let mkLocalPrivateAttributeWithPropertyConstructors
ILTypeDefAccess.Private,
ILGenericParameterDefs.Empty,
g.ilg.typ_Attribute,
- ILTypes.Empty,
+ [],
mkILMethods (
ilCtorDef
:: (ilElements |> List.fold (fun acc (_, getter, _, _) -> getter @ acc) [])
@@ -205,7 +205,7 @@ let mkLocalPrivateAttributeWithByteAndByteArrayConstructors (g: TcGlobals, name:
ILTypeDefAccess.Private,
ILGenericParameterDefs.Empty,
g.ilg.typ_Attribute,
- ILTypes.Empty,
+ [],
mkILMethods ([ ilScalarCtorDef; ilArrayCtorDef ]),
mkILFields [ fieldDef ],
emptyILTypeDefs,
@@ -233,7 +233,7 @@ let mkLocalPrivateInt32Enum (g: TcGlobals, tref: ILTypeRef, values: (string * in
ILTypeDefAccess.Private,
ILGenericParameterDefs.Empty,
g.ilg.typ_Enum,
- ILTypes.Empty,
+ [],
mkILMethods [],
mkILFields enumFields,
emptyILTypeDefs,
diff --git a/src/Compiler/DependencyManager/DependencyProvider.fs b/src/Compiler/DependencyManager/DependencyProvider.fs
index 709899e9a05..a241880e620 100644
--- a/src/Compiler/DependencyManager/DependencyProvider.fs
+++ b/src/Compiler/DependencyManager/DependencyProvider.fs
@@ -160,19 +160,19 @@ type ReflectionDependencyManagerProvider
let instance =
if not (isNull (theType.GetConstructor([| typeof; typeof |]))) then
- Activator.CreateInstance(theType, [| outputDir :> obj; useResultsCache :> obj |])
+ Activator.CreateInstance(theType, [| outputDir :> objnull; useResultsCache :> objnull |])
else
- Activator.CreateInstance(theType, [| outputDir :> obj |])
+ Activator.CreateInstance(theType, [| outputDir :> objnull |])
- let nameProperty = nameProperty.GetValue >> string
- let keyProperty = keyProperty.GetValue >> string
+ let nameProperty (x: objnull) = x |> nameProperty.GetValue |> string
+ let keyProperty (x: objnull) = x |> keyProperty.GetValue |> string
- let helpMessagesProperty =
- let toStringArray (o: obj) = o :?> string[]
+ let helpMessagesProperty (x: objnull) =
+ let toStringArray (o: objnull) = o :?> string[]
match helpMessagesProperty with
- | Some helpMessagesProperty -> helpMessagesProperty.GetValue >> toStringArray
- | None -> fun _ -> [||]
+ | Some helpMessagesProperty -> x |> helpMessagesProperty.GetValue |> toStringArray
+ | None -> [||]
static member InstanceMaker(theType: Type, outputDir: string option, useResultsCache: bool) =
match
@@ -453,14 +453,18 @@ type ReflectionDependencyManagerProvider
None, [||]
match method with
+ | None -> ReflectionDependencyManagerProvider.MakeResultFromFields(false, [||], [||], Seq.empty, Seq.empty, Seq.empty)
| Some m ->
- let result = m.Invoke(instance, arguments)
+ match m.Invoke(instance, arguments) with
+ | null -> ReflectionDependencyManagerProvider.MakeResultFromFields(false, [||], [||], Seq.empty, Seq.empty, Seq.empty)
// Verify the number of arguments returned in the tuple returned by resolvedependencies, it can be:
// 1 - object with properties
// 3 - (bool * string list * string list)
// Support legacy api return shape (bool, seq, seq) --- original paket packagemanager
- if FSharpType.IsTuple(result.GetType()) then
+ | result when FSharpType.IsTuple(result.GetType()) |> not ->
+ ReflectionDependencyManagerProvider.MakeResultFromObject(result)
+ | result ->
// Verify the number of arguments returned in the tuple returned by resolvedependencies, it can be:
// 3 - (bool * string list * string list)
let success, sourceFiles, packageRoots =
@@ -474,10 +478,6 @@ type ReflectionDependencyManagerProvider
| _ -> false, seqEmpty, seqEmpty
ReflectionDependencyManagerProvider.MakeResultFromFields(success, [||], [||], Seq.empty, sourceFiles, packageRoots)
- else
- ReflectionDependencyManagerProvider.MakeResultFromObject(result)
-
- | None -> ReflectionDependencyManagerProvider.MakeResultFromFields(false, [||], [||], Seq.empty, Seq.empty, Seq.empty)
/// Provides DependencyManagement functions.
/// Class is IDisposable
diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs
index c73b8e5d197..1c50ca26781 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fs
+++ b/src/Compiler/Driver/CompilerDiagnostics.fs
@@ -24,7 +24,6 @@ open FSharp.Compiler.ConstraintSolver
open FSharp.Compiler.DiagnosticMessage
open FSharp.Compiler.Diagnostics
open FSharp.Compiler.DiagnosticsLogger
-open FSharp.Compiler.Features
open FSharp.Compiler.Infos
open FSharp.Compiler.IO
open FSharp.Compiler.Lexhelp
@@ -2300,13 +2299,17 @@ type PhasedDiagnostic with
// 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
- (langVersion: LanguageVersion, scopedPragmas, diagnosticOptions: FSharpDiagnosticOptions, diagnosticsLogger: DiagnosticsLogger) =
+ (checkFile, scopedPragmas, diagnosticOptions: FSharpDiagnosticOptions, diagnosticsLogger: DiagnosticsLogger) =
inherit DiagnosticsLogger("DiagnosticsLoggerFilteringByScopedPragmas")
- let needCompatibilityWithEarlierInconsistentInteraction =
- not (langVersion.SupportsFeature LanguageFeature.ConsistentNowarnLineDirectiveInteraction)
-
let mutable realErrorPresent = false
override _.DiagnosticSink(diagnostic: PhasedDiagnostic, severity) =
@@ -2320,10 +2323,12 @@ type DiagnosticsLoggerFilteringByScopedPragmas
match diagnostic.Range with
| Some m ->
scopedPragmas
- |> List.exists (fun (ScopedPragma.WarningOff(pragmaRange, warningNumFromPragma)) ->
+ |> List.exists (fun pragma ->
+ let (ScopedPragma.WarningOff(pragmaRange, warningNumFromPragma)) = pragma
+
warningNum = warningNumFromPragma
- && (needCompatibilityWithEarlierInconsistentInteraction
- || m.FileIndex = pragmaRange.FileIndex && posGeq m.Start pragmaRange.Start))
+ && (not checkFile || m.FileIndex = pragmaRange.FileIndex)
+ && posGeq m.Start pragmaRange.Start)
|> not
| None -> true
@@ -2339,5 +2344,5 @@ type DiagnosticsLoggerFilteringByScopedPragmas
override _.CheckForRealErrorsIgnoringWarnings = realErrorPresent
-let GetDiagnosticsLoggerFilteringByScopedPragmas (langVersion, scopedPragmas, diagnosticOptions, diagnosticsLogger) =
- DiagnosticsLoggerFilteringByScopedPragmas(langVersion, scopedPragmas, diagnosticOptions, diagnosticsLogger) :> DiagnosticsLogger
+let GetDiagnosticsLoggerFilteringByScopedPragmas (checkFile, scopedPragmas, diagnosticOptions, diagnosticsLogger) =
+ DiagnosticsLoggerFilteringByScopedPragmas(checkFile, scopedPragmas, diagnosticOptions, diagnosticsLogger) :> DiagnosticsLogger
diff --git a/src/Compiler/Driver/CompilerDiagnostics.fsi b/src/Compiler/Driver/CompilerDiagnostics.fsi
index 7c5acef17d4..6139da434cf 100644
--- a/src/Compiler/Driver/CompilerDiagnostics.fsi
+++ b/src/Compiler/Driver/CompilerDiagnostics.fsi
@@ -7,7 +7,6 @@ open System.Text
open FSharp.Compiler.CompilerConfig
open FSharp.Compiler.Diagnostics
open FSharp.Compiler.DiagnosticsLogger
-open FSharp.Compiler.Features
open FSharp.Compiler.Syntax
open FSharp.Compiler.Text
@@ -85,7 +84,7 @@ type PhasedDiagnostic with
/// Get a diagnostics logger that filters the reporting of warnings based on scoped pragma information
val GetDiagnosticsLoggerFilteringByScopedPragmas:
- langVersion: LanguageVersion *
+ checkFile: bool *
scopedPragmas: ScopedPragma list *
diagnosticOptions: FSharpDiagnosticOptions *
diagnosticsLogger: DiagnosticsLogger ->
diff --git a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs
index c1f6ce8ddb4..5fd190b1995 100644
--- a/src/Compiler/Driver/GraphChecking/FileContentMapping.fs
+++ b/src/Compiler/Driver/GraphChecking/FileContentMapping.fs
@@ -523,7 +523,7 @@ let visitSynExpr (e: SynExpr) : FileContentEntry list =
visit expr (fun exprNodes ->
[ yield! exprNodes; yield! List.collect visitSynMatchClause clauses ]
|> continuation)
- | SynExpr.DoBang(expr, _) -> visit expr continuation
+ | SynExpr.DoBang(expr = expr) -> visit expr continuation
| SynExpr.WhileBang(whileExpr = whileExpr; doExpr = doExpr) ->
visit whileExpr (fun whileNodes -> visit doExpr (fun doNodes -> whileNodes @ doNodes |> continuation))
| SynExpr.LibraryOnlyILAssembly(typeArgs = typeArgs; args = args; retTy = retTy) ->
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fs b/src/Compiler/Driver/GraphChecking/Graph.fs
index 210ca927c7f..6bfb1199181 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fs
+++ b/src/Compiler/Driver/GraphChecking/Graph.fs
@@ -83,7 +83,7 @@ module internal Graph =
graph
|> Seq.iter (fun (KeyValue(file, deps)) -> printfn $"{file} -> {deps |> Array.map nodePrinter |> join}")
- let print (graph: Graph<'Node>) : unit =
+ let print (graph: Graph<'Node> when 'Node: not null) : unit =
printCustom graph (fun node -> node.ToString() |> string)
let serialiseToMermaid (graph: Graph) =
diff --git a/src/Compiler/Driver/GraphChecking/Graph.fsi b/src/Compiler/Driver/GraphChecking/Graph.fsi
index a93e429d2fe..2caf421dc54 100644
--- a/src/Compiler/Driver/GraphChecking/Graph.fsi
+++ b/src/Compiler/Driver/GraphChecking/Graph.fsi
@@ -20,7 +20,7 @@ module internal Graph =
/// Create a reverse of the graph.
val reverse<'Node when 'Node: equality> : originalGraph: Graph<'Node> -> Graph<'Node>
/// Print the contents of the graph to the standard output.
- val print: graph: Graph<'Node> -> unit
+ val print: graph: Graph<'Node> -> unit when 'Node: not null
/// Create a simple Mermaid graph
val serialiseToMermaid: graph: Graph -> string
/// Create a simple Mermaid graph and save it under the path specified.
diff --git a/src/Compiler/Driver/ParseAndCheckInputs.fs b/src/Compiler/Driver/ParseAndCheckInputs.fs
index d5d18d79651..a6804bfe746 100644
--- a/src/Compiler/Driver/ParseAndCheckInputs.fs
+++ b/src/Compiler/Driver/ParseAndCheckInputs.fs
@@ -511,7 +511,7 @@ let ParseInput
finally
// OK, now commit the errors, since the ScopedPragmas will (hopefully) have been scraped
let filteringDiagnosticsLogger =
- GetDiagnosticsLoggerFilteringByScopedPragmas(lexbuf.LanguageVersion, scopedPragmas, diagnosticOptions, diagnosticsLogger)
+ GetDiagnosticsLoggerFilteringByScopedPragmas(false, scopedPragmas, diagnosticOptions, diagnosticsLogger)
delayLogger.CommitDelayedDiagnostics filteringDiagnosticsLogger
@@ -1429,7 +1429,7 @@ let CheckOneInput
// Within a file, equip loggers to locally filter w.r.t. scope pragmas in each input
let DiagnosticsLoggerForInput (tcConfig: TcConfig, input: ParsedInput, oldLogger) =
- GetDiagnosticsLoggerFilteringByScopedPragmas(tcConfig.langVersion, input.ScopedPragmas, tcConfig.diagnosticsOptions, oldLogger)
+ GetDiagnosticsLoggerFilteringByScopedPragmas(false, input.ScopedPragmas, tcConfig.diagnosticsOptions, oldLogger)
/// Typecheck a single file (or interactive entry into F# Interactive)
let CheckOneInputEntry (ctok, checkForErrors, tcConfig: TcConfig, tcImports, tcGlobals, prefixPathOpt) tcState input =
diff --git a/src/Compiler/Driver/fsc.fs b/src/Compiler/Driver/fsc.fs
index 9dccdec826d..ac4ee179538 100644
--- a/src/Compiler/Driver/fsc.fs
+++ b/src/Compiler/Driver/fsc.fs
@@ -745,7 +745,7 @@ let main2
yield! pragmas
]
- GetDiagnosticsLoggerFilteringByScopedPragmas(tcConfig.langVersion, scopedPragmas, tcConfig.diagnosticsOptions, oldLogger)
+ GetDiagnosticsLoggerFilteringByScopedPragmas(true, scopedPragmas, tcConfig.diagnosticsOptions, oldLogger)
SetThreadDiagnosticsLoggerNoUnwind diagnosticsLogger
diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt
index 2e391fa5515..b5a50afc7c0 100644
--- a/src/Compiler/FSComp.txt
+++ b/src/Compiler/FSComp.txt
@@ -1783,5 +1783,4 @@ featureEmptyBodiedComputationExpressions,"Support for computation expressions wi
featureAllowAccessModifiersToAutoPropertiesGettersAndSetters,"Allow access modifiers to auto properties getters and setters"
3871,tcAccessModifiersNotAllowedInSRTPConstraint,"Access modifiers cannot be applied to an SRTP constraint."
featureAllowObjectExpressionWithoutOverrides,"Allow object expressions without overrides"
-3872,tcPartialActivePattern,"Multi-case partial active patterns are not supported. Consider using a single-case partial active pattern or a full active pattern."
-featureConsistentNowarnLineDirectiveInteraction,"The interaction between #nowarn and #line is now consistent."
+3872,tcPartialActivePattern,"Multi-case partial active patterns are not supported. Consider using a single-case partial active pattern or a full active pattern."
\ No newline at end of file
diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs
index 5f16aead30a..5c311237594 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fs
+++ b/src/Compiler/Facilities/LanguageFeatures.fs
@@ -94,7 +94,6 @@ type LanguageFeature =
| ParsedHashDirectiveArgumentNonQuotes
| EmptyBodiedComputationExpressions
| AllowObjectExpressionWithoutOverrides
- | ConsistentNowarnLineDirectiveInteraction
/// LanguageVersion management
type LanguageVersion(versionText) =
@@ -213,10 +212,9 @@ type LanguageVersion(versionText) =
LanguageFeature.LowerSimpleMappingsInComprehensionsToFastLoops, languageVersion90
LanguageFeature.ParsedHashDirectiveArgumentNonQuotes, languageVersion90
LanguageFeature.EmptyBodiedComputationExpressions, languageVersion90
- LanguageFeature.ConsistentNowarnLineDirectiveInteraction, languageVersion90
+ LanguageFeature.EnforceAttributeTargets, languageVersion90
// F# preview
- LanguageFeature.EnforceAttributeTargets, previewVersion // waiting for fix of https://github.com/dotnet/fsharp/issues/17731
LanguageFeature.UnmanagedConstraintCsharpInterop, previewVersion // not enabled because: https://github.com/dotnet/fsharp/issues/17509
LanguageFeature.FromEndSlicing, previewVersion // Unfinished features --- needs work
LanguageFeature.AllowAccessModifiersToAutoPropertiesGettersAndSetters, previewVersion
@@ -377,7 +375,6 @@ type LanguageVersion(versionText) =
| LanguageFeature.ParsedHashDirectiveArgumentNonQuotes -> FSComp.SR.featureParsedHashDirectiveArgumentNonString ()
| LanguageFeature.EmptyBodiedComputationExpressions -> FSComp.SR.featureEmptyBodiedComputationExpressions ()
| LanguageFeature.AllowObjectExpressionWithoutOverrides -> FSComp.SR.featureAllowObjectExpressionWithoutOverrides ()
- | LanguageFeature.ConsistentNowarnLineDirectiveInteraction -> FSComp.SR.featureConsistentNowarnLineDirectiveInteraction ()
/// Get a version string associated with the given feature.
static member GetFeatureVersionString feature =
diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi
index 4ae722c7f60..7408300b943 100644
--- a/src/Compiler/Facilities/LanguageFeatures.fsi
+++ b/src/Compiler/Facilities/LanguageFeatures.fsi
@@ -85,7 +85,6 @@ type LanguageFeature =
| ParsedHashDirectiveArgumentNonQuotes
| EmptyBodiedComputationExpressions
| AllowObjectExpressionWithoutOverrides
- | ConsistentNowarnLineDirectiveInteraction
/// LanguageVersion management
type LanguageVersion =
diff --git a/src/Compiler/Facilities/prim-parsing.fs b/src/Compiler/Facilities/prim-parsing.fs
index 3088a5579ed..7fb0d7fca41 100644
--- a/src/Compiler/Facilities/prim-parsing.fs
+++ b/src/Compiler/Facilities/prim-parsing.fs
@@ -14,7 +14,7 @@ exception Accept of obj
[]
type internal IParseState
- (ruleStartPoss: Position[], ruleEndPoss: Position[], lhsPos: Position[], ruleValues: obj[], lexbuf: LexBuffer) =
+ (ruleStartPoss: Position[], ruleEndPoss: Position[], lhsPos: Position[], ruleValues: objnull[], lexbuf: LexBuffer) =
member _.LexBuffer = lexbuf
member _.InputRange index =
@@ -125,7 +125,7 @@ type Stack<'a>(n) =
member buf.PrintStack() =
for i = 0 to (count - 1) do
- Console.Write("{0}{1}", contents[i], (if i = count - 1 then ":" else "-"))
+ Console.Write("{0}{1}", contents[i] :> objnull, (if i = count - 1 then ":" else "-"))
module Flags =
#if DEBUG
@@ -151,7 +151,10 @@ module internal Implementation =
//-------------------------------------------------------------------------
// Read the tables written by FSYACC.
- type AssocTable(elemTab: uint16[], offsetTab: uint16[], cache: int[], cacheSize: int) =
+ type AssocTable(elemTab: uint16[], offsetTab: uint16[], cache: int[]) =
+
+ do Array.fill cache 0 cache.Length -1
+ let cacheSize = cache.Length / 2
member t.ReadAssoc(minElemNum, maxElemNum, defaultValueOfAssoc, keyToFind) =
// do a binary chop on the table
@@ -231,7 +234,7 @@ module internal Implementation =
[]
[]
type ValueInfo =
- val value: obj
+ val value: objnull
val startPos: Position
val endPos: Position
@@ -269,17 +272,12 @@ module internal Implementation =
// The 100 here means a maximum of 100 elements for each rule
let ruleStartPoss = (Array.zeroCreate 100: Position[])
let ruleEndPoss = (Array.zeroCreate 100: Position[])
- let ruleValues = (Array.zeroCreate 100: obj[])
+ let ruleValues = (Array.zeroCreate 100: objnull[])
let lhsPos = (Array.zeroCreate 2: Position[])
let reductions = tables.reductions
let cacheSize = 7919 // the 1000'th prime
- // Use a simpler hash table with faster lookup, but only one
- // hash bucket per key.
let actionTableCache = ArrayPool.Shared.Rent(cacheSize * 2)
let gotoTableCache = ArrayPool.Shared.Rent(cacheSize * 2)
- // Clear the arrays since ArrayPool does not
- Array.Clear(actionTableCache, 0, actionTableCache.Length)
- Array.Clear(gotoTableCache, 0, gotoTableCache.Length)
use _cacheDisposal =
{ new IDisposable with
@@ -289,10 +287,10 @@ module internal Implementation =
}
let actionTable =
- AssocTable(tables.actionTableElements, tables.actionTableRowOffsets, actionTableCache, cacheSize)
+ AssocTable(tables.actionTableElements, tables.actionTableRowOffsets, actionTableCache)
let gotoTable =
- AssocTable(tables.gotos, tables.sparseGotoTableRowOffsets, gotoTableCache, cacheSize)
+ AssocTable(tables.gotos, tables.sparseGotoTableRowOffsets, gotoTableCache)
let stateToProdIdxsTable =
IdxToIdxListTable(tables.stateToProdIdxsTableElements, tables.stateToProdIdxsTableRowOffsets)
diff --git a/src/Compiler/Interactive/fsi.fs b/src/Compiler/Interactive/fsi.fs
index 832327656d9..74fcc37340c 100644
--- a/src/Compiler/Interactive/fsi.fs
+++ b/src/Compiler/Interactive/fsi.fs
@@ -1675,34 +1675,6 @@ let internal mkBoundValueTypedImpl tcGlobals m moduleName name ty =
let qname = QualifiedNameOfFile.QualifiedNameOfFile(Ident(moduleName, m))
entity, v, CheckedImplFile.CheckedImplFile(qname, [], mty, contents, false, false, StampMap.Empty, Map.empty)
-let scriptingSymbolsPath =
- let createDirectory (path: string) =
- lazy
- try
- if not (Directory.Exists(path)) then
- Directory.CreateDirectory(path) |> ignore
-
- path
- with _ ->
- path
-
- createDirectory (Path.Combine(Path.GetTempPath(), $"{DateTime.Now:s}-{Guid.NewGuid():n}".Replace(':', '-')))
-
-let deleteScriptingSymbols () =
- try
-#if !DEBUG
- if scriptingSymbolsPath.IsValueCreated then
- if Directory.Exists(scriptingSymbolsPath.Value) then
- Directory.Delete(scriptingSymbolsPath.Value, true)
-#else
- ()
-#endif
- with _ ->
- ()
-
-AppDomain.CurrentDomain.ProcessExit
-|> Event.add (fun _ -> deleteScriptingSymbols ())
-
let dynamicCcuName = "FSI-ASSEMBLY"
/// Encapsulates the coordination of the typechecking, optimization and code generation
@@ -1764,6 +1736,33 @@ type internal FsiDynamicCompiler
let reportedAssemblies = Dictionary()
+ let scriptingSymbolsPath =
+ let createDirectory (path: string) =
+ try
+ if not (Directory.Exists(path)) then
+ Directory.CreateDirectory(path) |> ignore
+
+ path
+ with _ ->
+ path
+
+ createDirectory (Path.Combine(Path.GetTempPath(), $"{DateTime.Now:s}-{Guid.NewGuid():n}".Replace(':', '-')))
+
+ let deleteScriptingSymbols () =
+ try
+#if !DEBUG
+ if Directory.Exists(scriptingSymbolsPath) then
+ Directory.Delete(scriptingSymbolsPath, true)
+#else
+ ()
+#endif
+ with _ ->
+ ()
+
+ do
+ AppDomain.CurrentDomain.ProcessExit
+ |> Event.add (fun _ -> deleteScriptingSymbols ())
+
/// Add attributes
let CreateModuleFragment (tcConfigB: TcConfigBuilder, dynamicCcuName, codegenResults) =
if progress then
@@ -1841,7 +1840,7 @@ type internal FsiDynamicCompiler
{
ilg = tcGlobals.ilg
outfile = $"{multiAssemblyName}-{dynamicAssemblyId}.dll"
- pdbfile = Some(Path.Combine(scriptingSymbolsPath.Value, $"{multiAssemblyName}-{dynamicAssemblyId}.pdb"))
+ pdbfile = Some(Path.Combine(scriptingSymbolsPath, $"{multiAssemblyName}-{dynamicAssemblyId}.pdb"))
emitTailcalls = tcConfig.emitTailcalls
deterministic = tcConfig.deterministic
portablePDB = true
@@ -4694,7 +4693,7 @@ type FsiEvaluationSession
let lexResourceManager = LexResourceManager()
/// The lock stops the type checker running at the same time as the server intellisense implementation.
- let tcLockObject = box 7 // any new object will do
+ let tcLockObject = box 7 |> Unchecked.nonNull // any new object will do
let resolveAssemblyRef (aref: ILAssemblyRef) =
// Explanation: This callback is invoked during compilation to resolve assembly references
diff --git a/src/Compiler/Service/BackgroundCompiler.fs b/src/Compiler/Service/BackgroundCompiler.fs
index a2f5457b1b6..1089f5774e8 100644
--- a/src/Compiler/Service/BackgroundCompiler.fs
+++ b/src/Compiler/Service/BackgroundCompiler.fs
@@ -266,8 +266,7 @@ type internal BackgroundCompiler
parallelReferenceResolution,
captureIdentifiersWhenParsing,
getSource: (string -> Async) option,
- useChangeNotifications,
- useSyntaxTreeCache
+ useChangeNotifications
) as self =
let beforeFileChecked = Event()
@@ -403,8 +402,7 @@ type internal BackgroundCompiler
parallelReferenceResolution,
captureIdentifiersWhenParsing,
getSource,
- useChangeNotifications,
- useSyntaxTreeCache
+ useChangeNotifications
)
match builderOpt with
diff --git a/src/Compiler/Service/BackgroundCompiler.fsi b/src/Compiler/Service/BackgroundCompiler.fsi
index 9ca174a5686..d93ece6217b 100644
--- a/src/Compiler/Service/BackgroundCompiler.fsi
+++ b/src/Compiler/Service/BackgroundCompiler.fsi
@@ -235,8 +235,7 @@ type internal BackgroundCompiler =
parallelReferenceResolution: ParallelReferenceResolution *
captureIdentifiersWhenParsing: bool *
getSource: (string -> Async) option *
- useChangeNotifications: bool *
- useSyntaxTreeCache: bool ->
+ useChangeNotifications: bool ->
BackgroundCompiler
static member ActualCheckFileCount: int
diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs
index 34958588b79..2623cbde347 100644
--- a/src/Compiler/Service/FSharpParseFileResults.fs
+++ b/src/Compiler/Service/FSharpParseFileResults.fs
@@ -573,12 +573,12 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
yield! checkRange m
yield! walkExpr isControlFlow innerExpr
- | SynExpr.YieldOrReturn(_, e, m) ->
+ | SynExpr.YieldOrReturn(_, e, m, _) ->
yield! checkRange m
yield! walkExpr false e
- | SynExpr.YieldOrReturnFrom(_, e, _)
- | SynExpr.DoBang(e, _) ->
+ | SynExpr.YieldOrReturnFrom(_, e, _, _)
+ | SynExpr.DoBang(expr = e) ->
yield! checkRange e.Range
yield! walkExpr false e
diff --git a/src/Compiler/Service/IncrementalBuild.fs b/src/Compiler/Service/IncrementalBuild.fs
index 7951f3c9328..29059b4873b 100644
--- a/src/Compiler/Service/IncrementalBuild.fs
+++ b/src/Compiler/Service/IncrementalBuild.fs
@@ -259,7 +259,7 @@ type BoundModel private (
IncrementalBuilderEventTesting.MRU.Add(IncrementalBuilderEventTesting.IBETypechecked fileName)
let capturingDiagnosticsLogger = CapturingDiagnosticsLogger("TypeCheck")
- let diagnosticsLogger = GetDiagnosticsLoggerFilteringByScopedPragmas(tcConfig.langVersion, input.ScopedPragmas, tcConfig.diagnosticsOptions, capturingDiagnosticsLogger)
+ let diagnosticsLogger = GetDiagnosticsLoggerFilteringByScopedPragmas(false, input.ScopedPragmas, tcConfig.diagnosticsOptions, capturingDiagnosticsLogger)
use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.TypeCheck)
beforeFileChecked.Trigger fileName
@@ -507,10 +507,12 @@ type FrameworkImportsCache(size) =
let frameworkTcImportsCache = AgedLookup>(size, areSimilar=(fun (x, y) -> x = y))
/// Reduce the size of the cache in low-memory scenarios
- member _.Downsize() = frameworkTcImportsCache.Resize(AnyCallerThread, newKeepStrongly=0)
+ member _.Downsize() = lock gate <| fun () ->
+ frameworkTcImportsCache.Resize(AnyCallerThread, newKeepStrongly=0)
/// Clear the cache
- member _.Clear() = frameworkTcImportsCache.Clear AnyCallerThread
+ member _.Clear() = lock gate <| fun () ->
+ frameworkTcImportsCache.Clear AnyCallerThread
/// This function strips the "System" assemblies from the tcConfig and returns a age-cached TcImports for them.
member _.GetNode(tcConfig: TcConfig, frameworkDLLs: AssemblyResolution list, nonFrameworkResolutions: AssemblyResolution list) =
@@ -886,7 +888,6 @@ type IncrementalBuilderInitialState =
defaultTimeStamp: DateTime
mutable isImportsInvalidated: bool
useChangeNotifications: bool
- useSyntaxTreeCache: bool
}
static member Create
@@ -908,8 +909,7 @@ type IncrementalBuilderInitialState =
#endif
allDependencies,
defaultTimeStamp: DateTime,
- useChangeNotifications: bool,
- useSyntaxTreeCache
+ useChangeNotifications: bool
) =
let initialState =
@@ -935,7 +935,6 @@ type IncrementalBuilderInitialState =
defaultTimeStamp = defaultTimeStamp
isImportsInvalidated = false
useChangeNotifications = useChangeNotifications
- useSyntaxTreeCache = useSyntaxTreeCache
}
#if !NO_TYPEPROVIDERS
importsInvalidatedByTypeProvider.Publish.Add(fun () -> initialState.isImportsInvalidated <- true)
@@ -1407,8 +1406,7 @@ type IncrementalBuilder(initialState: IncrementalBuilderInitialState, state: Inc
parallelReferenceResolution,
captureIdentifiersWhenParsing,
getSource,
- useChangeNotifications,
- useSyntaxTreeCache
+ useChangeNotifications
) =
let useSimpleResolutionSwitch = "--simpleresolution"
@@ -1650,8 +1648,7 @@ type IncrementalBuilder(initialState: IncrementalBuilderInitialState, state: Inc
#endif
allDependencies,
defaultTimeStamp,
- useChangeNotifications,
- useSyntaxTreeCache
+ useChangeNotifications
)
let builder = IncrementalBuilder(initialState, IncrementalBuilderState.Create(initialState))
diff --git a/src/Compiler/Service/IncrementalBuild.fsi b/src/Compiler/Service/IncrementalBuild.fsi
index 21b2fb23404..0f8ed5582da 100644
--- a/src/Compiler/Service/IncrementalBuild.fsi
+++ b/src/Compiler/Service/IncrementalBuild.fsi
@@ -296,8 +296,7 @@ type internal IncrementalBuilder =
parallelReferenceResolution: ParallelReferenceResolution *
captureIdentifiersWhenParsing: bool *
getSource: (string -> Async) option *
- useChangeNotifications: bool *
- useSyntaxTreeCache: bool ->
+ useChangeNotifications: bool ->
Async
/// Generalized Incremental Builder. This is exposed only for unit testing purposes.
diff --git a/src/Compiler/Service/ServiceInterfaceStubGenerator.fs b/src/Compiler/Service/ServiceInterfaceStubGenerator.fs
index d691e002c0a..f0ddc777b14 100644
--- a/src/Compiler/Service/ServiceInterfaceStubGenerator.fs
+++ b/src/Compiler/Service/ServiceInterfaceStubGenerator.fs
@@ -952,9 +952,9 @@ module InterfaceStubGenerator =
| SynExpr.Null _range
| SynExpr.ImplicitZero _range -> None
- | SynExpr.YieldOrReturn(_, synExpr, _range)
- | SynExpr.YieldOrReturnFrom(_, synExpr, _range)
- | SynExpr.DoBang(synExpr, _range) -> walkExpr synExpr
+ | SynExpr.YieldOrReturn(expr = synExpr)
+ | SynExpr.YieldOrReturnFrom(expr = synExpr)
+ | SynExpr.DoBang(expr = synExpr) -> walkExpr synExpr
| SynExpr.LetOrUseBang(rhs = synExpr1; andBangs = synExprAndBangs; body = synExpr2) ->
[
diff --git a/src/Compiler/Service/ServiceStructure.fs b/src/Compiler/Service/ServiceStructure.fs
index 1d0f7c7f8ec..5fab5ef9eb5 100644
--- a/src/Compiler/Service/ServiceStructure.fs
+++ b/src/Compiler/Service/ServiceStructure.fs
@@ -246,15 +246,15 @@ module Structure =
rcheck Scope.New Collapse.Below r e.Range
parseExpr e
- | SynExpr.YieldOrReturn(_, e, r) ->
+ | SynExpr.YieldOrReturn(_, e, r, _) ->
rcheck Scope.YieldOrReturn Collapse.Below r r
parseExpr e
- | SynExpr.YieldOrReturnFrom(_, e, r) ->
+ | SynExpr.YieldOrReturnFrom(_, e, r, _) ->
rcheck Scope.YieldOrReturnBang Collapse.Below r r
parseExpr e
- | SynExpr.DoBang(e, r) ->
+ | SynExpr.DoBang(expr = e; range = r) ->
rcheck Scope.Do Collapse.Below r <| Range.modStart 3 r
parseExpr e
diff --git a/src/Compiler/Service/TransparentCompiler.fs b/src/Compiler/Service/TransparentCompiler.fs
index 735a6b241f1..5158ac7f25c 100644
--- a/src/Compiler/Service/TransparentCompiler.fs
+++ b/src/Compiler/Service/TransparentCompiler.fs
@@ -326,8 +326,7 @@ type internal TransparentCompiler
parallelReferenceResolution,
captureIdentifiersWhenParsing,
getSource: (string -> Async) option,
- useChangeNotifications,
- useSyntaxTreeCache
+ useChangeNotifications
) as self =
let documentSource =
@@ -374,8 +373,7 @@ type internal TransparentCompiler
parallelReferenceResolution,
captureIdentifiersWhenParsing,
getSource,
- useChangeNotifications,
- useSyntaxTreeCache
+ useChangeNotifications
)
:> IBackgroundCompiler
@@ -1303,12 +1301,7 @@ type internal TransparentCompiler
let diagnosticsLogger = errHandler.DiagnosticsLogger
let diagnosticsLogger =
- GetDiagnosticsLoggerFilteringByScopedPragmas(
- tcConfig.langVersion,
- input.ScopedPragmas,
- tcConfig.diagnosticsOptions,
- diagnosticsLogger
- )
+ GetDiagnosticsLoggerFilteringByScopedPragmas(false, input.ScopedPragmas, tcConfig.diagnosticsOptions, diagnosticsLogger)
use _ = new CompilationGlobalsScope(diagnosticsLogger, BuildPhase.TypeCheck)
diff --git a/src/Compiler/Service/TransparentCompiler.fsi b/src/Compiler/Service/TransparentCompiler.fsi
index be1f5ab64fa..7746445c0af 100644
--- a/src/Compiler/Service/TransparentCompiler.fsi
+++ b/src/Compiler/Service/TransparentCompiler.fsi
@@ -155,8 +155,7 @@ type internal TransparentCompiler =
parallelReferenceResolution: ParallelReferenceResolution *
captureIdentifiersWhenParsing: bool *
getSource: (string -> Async) option *
- useChangeNotifications: bool *
- useSyntaxTreeCache: bool ->
+ useChangeNotifications: bool ->
TransparentCompiler
member FindReferencesInFile:
diff --git a/src/Compiler/Service/service.fs b/src/Compiler/Service/service.fs
index 2c915870f84..525faf3be3d 100644
--- a/src/Compiler/Service/service.fs
+++ b/src/Compiler/Service/service.fs
@@ -125,7 +125,6 @@ type FSharpChecker
captureIdentifiersWhenParsing,
getSource,
useChangeNotifications,
- useSyntaxTreeCache,
useTransparentCompiler
) =
@@ -144,8 +143,7 @@ type FSharpChecker
parallelReferenceResolution,
captureIdentifiersWhenParsing,
getSource,
- useChangeNotifications,
- useSyntaxTreeCache
+ useChangeNotifications
)
:> IBackgroundCompiler
else
@@ -162,8 +160,7 @@ type FSharpChecker
parallelReferenceResolution,
captureIdentifiersWhenParsing,
getSource,
- useChangeNotifications,
- useSyntaxTreeCache
+ useChangeNotifications
)
:> IBackgroundCompiler
@@ -209,7 +206,6 @@ type FSharpChecker
?parallelReferenceResolution: bool,
?captureIdentifiersWhenParsing: bool,
?documentSource: DocumentSource,
- ?useSyntaxTreeCache: bool,
?useTransparentCompiler: bool
) =
@@ -238,8 +234,6 @@ type FSharpChecker
| Some(DocumentSource.Custom _) -> true
| _ -> false
- let useSyntaxTreeCache = defaultArg useSyntaxTreeCache true
-
if keepAssemblyContents && enablePartialTypeChecking then
invalidArg "enablePartialTypeChecking" "'keepAssemblyContents' and 'enablePartialTypeChecking' cannot be both enabled."
@@ -261,7 +255,6 @@ type FSharpChecker
| Some(DocumentSource.Custom f) -> Some f
| _ -> None),
useChangeNotifications,
- useSyntaxTreeCache,
useTransparentCompiler
)
diff --git a/src/Compiler/Service/service.fsi b/src/Compiler/Service/service.fsi
index 0a6c601344c..0e48a0d6360 100644
--- a/src/Compiler/Service/service.fsi
+++ b/src/Compiler/Service/service.fsi
@@ -38,7 +38,6 @@ type public FSharpChecker =
/// Indicates whether to resolve references in parallel.
/// When set to true we create a set of all identifiers for each parsed file which can be used to speed up finding references.
/// Default: FileSystem. You can use Custom source to provide a function that will return the source for a given file path instead of reading it from the file system. Note that with this option the FSharpChecker will also not monitor the file system for file changes. It will expect to be notified of changes via the NotifyFileChanged method.
- /// Default: true. Indicates whether to keep parsing results in a cache.
/// Default: false. Indicates whether we use a new experimental background compiler. This does not yet support all features
static member Create:
?projectCacheSize: int *
@@ -54,8 +53,6 @@ type public FSharpChecker =
?captureIdentifiersWhenParsing: bool *
[] ?documentSource:
DocumentSource *
- [] ?useSyntaxTreeCache:
- bool *
[] ?useTransparentCompiler:
bool ->
FSharpChecker
diff --git a/src/Compiler/Symbols/Exprs.fs b/src/Compiler/Symbols/Exprs.fs
index 15b1bb2a3f6..91480597cc2 100644
--- a/src/Compiler/Symbols/Exprs.fs
+++ b/src/Compiler/Symbols/Exprs.fs
@@ -121,7 +121,7 @@ type E =
| ValueSet of FSharpMemberOrFunctionOrValue * FSharpExpr
| Unused
| DefaultValue of FSharpType
- | Const of obj * FSharpType
+ | Const of objnull * FSharpType
| AddressOf of FSharpExpr
| Sequential of FSharpExpr * FSharpExpr
| IntegerForLoop of FSharpExpr * FSharpExpr * FSharpExpr * bool * DebugPointAtFor * DebugPointAtInOrTo
diff --git a/src/Compiler/SyntaxTree/ParseHelpers.fs b/src/Compiler/SyntaxTree/ParseHelpers.fs
index 22c27eeb9b0..8d62a724972 100644
--- a/src/Compiler/SyntaxTree/ParseHelpers.fs
+++ b/src/Compiler/SyntaxTree/ParseHelpers.fs
@@ -108,7 +108,7 @@ module LexbufLocalXmlDocStore =
|> unbox
let ClearXmlDoc (lexbuf: Lexbuf) =
- lexbuf.BufferLocalStore[xmlDocKey] <- box (XmlDocCollector())
+ lexbuf.BufferLocalStore[xmlDocKey] <- box (XmlDocCollector()) |> Unchecked.nonNull
/// Called from the lexer to save a single line of XML doc comment.
let SaveXmlDocLine (lexbuf: Lexbuf, lineText, range: range) =
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs
index 962188c2f21..fc0c811e55d 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fs
@@ -704,9 +704,9 @@ type SynExpr =
| SequentialOrImplicitYield of debugPoint: DebugPointAtSequential * expr1: SynExpr * expr2: SynExpr * ifNotStmt: SynExpr * range: range
- | YieldOrReturn of flags: (bool * bool) * expr: SynExpr * range: range
+ | YieldOrReturn of flags: (bool * bool) * expr: SynExpr * range: range * trivia: SynExprYieldOrReturnTrivia
- | YieldOrReturnFrom of flags: (bool * bool) * expr: SynExpr * range: range
+ | YieldOrReturnFrom of flags: (bool * bool) * expr: SynExpr * range: range * trivia: SynExprYieldOrReturnFromTrivia
| LetOrUseBang of
bindDebugPoint: DebugPointAtBinding *
@@ -726,7 +726,7 @@ type SynExpr =
range: range *
trivia: SynExprMatchBangTrivia
- | DoBang of expr: SynExpr * range: range
+ | DoBang of expr: SynExpr * range: range * trivia: SynExprDoBangTrivia
| WhileBang of whileDebugPoint: DebugPointAtWhile * whileExpr: SynExpr * doExpr: SynExpr * range: range
diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi
index f2c75d8dfac..45b03ad3b75 100644
--- a/src/Compiler/SyntaxTree/SyntaxTree.fsi
+++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi
@@ -877,12 +877,12 @@ type SynExpr =
/// F# syntax: yield expr
/// F# syntax: return expr
/// Computation expressions only
- | YieldOrReturn of flags: (bool * bool) * expr: SynExpr * range: range
+ | YieldOrReturn of flags: (bool * bool) * expr: SynExpr * range: range * trivia: SynExprYieldOrReturnTrivia
/// F# syntax: yield! expr
/// F# syntax: return! expr
/// Computation expressions only
- | YieldOrReturnFrom of flags: (bool * bool) * expr: SynExpr * range: range
+ | YieldOrReturnFrom of flags: (bool * bool) * expr: SynExpr * range: range * trivia: SynExprYieldOrReturnFromTrivia
/// F# syntax: let! pat = expr in expr
/// F# syntax: use! pat = expr in expr
@@ -909,7 +909,7 @@ type SynExpr =
/// F# syntax: do! expr
/// Computation expressions only
- | DoBang of expr: SynExpr * range: range
+ | DoBang of expr: SynExpr * range: range * trivia: SynExprDoBangTrivia
/// F# syntax: 'while! ... do ...'
| WhileBang of whileDebugPoint: DebugPointAtWhile * whileExpr: SynExpr * doExpr: SynExpr * range: range
diff --git a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs
index dc08afd6368..8dc46313341 100644
--- a/src/Compiler/SyntaxTree/SyntaxTreeOps.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTreeOps.fs
@@ -883,9 +883,9 @@ let rec synExprContainsError inpExpr =
| SynExpr.InferredDowncast(e, _)
| SynExpr.Lazy(e, _)
| SynExpr.TraitCall(_, _, e, _)
- | SynExpr.YieldOrReturn(_, e, _)
- | SynExpr.YieldOrReturnFrom(_, e, _)
- | SynExpr.DoBang(e, _)
+ | SynExpr.YieldOrReturn(_, e, _, _)
+ | SynExpr.YieldOrReturnFrom(_, e, _, _)
+ | SynExpr.DoBang(e, _, _)
| SynExpr.Fixed(e, _)
| SynExpr.DebugPoint(_, _, e)
| SynExpr.Paren(e, _, _, _) -> walkExpr e
diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fs b/src/Compiler/SyntaxTree/SyntaxTrivia.fs
index 0932befd7c1..10aee262292 100644
--- a/src/Compiler/SyntaxTree/SyntaxTrivia.fs
+++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fs
@@ -93,10 +93,15 @@ type SynExprLetOrUseTrivia =
[]
type SynExprLetOrUseBangTrivia =
{
+ LetOrUseBangKeyword: range
EqualsRange: range option
}
- static member Zero: SynExprLetOrUseBangTrivia = { EqualsRange = None }
+ static member Zero: SynExprLetOrUseBangTrivia =
+ {
+ LetOrUseBangKeyword = Range.Zero
+ EqualsRange = None
+ }
[]
type SynExprMatchTrivia =
@@ -112,6 +117,28 @@ type SynExprMatchBangTrivia =
WithKeyword: range
}
+[]
+type SynExprYieldOrReturnTrivia =
+ {
+ YieldOrReturnKeyword: range
+ }
+
+ static member Zero: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = Range.Zero }
+
+[]
+type SynExprYieldOrReturnFromTrivia =
+ {
+ YieldOrReturnFromKeyword: range
+ }
+
+ static member Zero: SynExprYieldOrReturnFromTrivia =
+ {
+ YieldOrReturnFromKeyword = Range.Zero
+ }
+
+[]
+type SynExprDoBangTrivia = { DoBangKeyword: range }
+
[]
type SynExprAnonRecdTrivia = { OpeningBraceRange: range }
diff --git a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
index 24bfc1b7a52..fff834beb41 100644
--- a/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
+++ b/src/Compiler/SyntaxTree/SyntaxTrivia.fsi
@@ -139,6 +139,8 @@ type SynExprLetOrUseTrivia =
[]
type SynExprLetOrUseBangTrivia =
{
+ /// The syntax range of the `let!` or `use!` keyword.
+ LetOrUseBangKeyword: range
/// The syntax range of the `=` token.
EqualsRange: range option
}
@@ -167,6 +169,32 @@ type SynExprMatchBangTrivia =
WithKeyword: range
}
+/// Represents additional information for SynExpr.DoBang
+[]
+type SynExprDoBangTrivia =
+ {
+ /// The syntax range of the `do!` keyword
+ DoBangKeyword: range
+ }
+
+/// Represents additional information for SynExpr.YieldOrReturn
+[]
+type SynExprYieldOrReturnTrivia =
+ {
+ /// The syntax range of the `yield` or `return` keyword.
+ YieldOrReturnKeyword: range
+ }
+
+ static member Zero: SynExprYieldOrReturnTrivia
+
+/// Represents additional information for SynExpr.YieldOrReturnFrom
+[]
+type SynExprYieldOrReturnFromTrivia =
+ {
+ /// The syntax range of the `yield!` or `return!` keyword.
+ YieldOrReturnFromKeyword: range
+ }
+
/// Represents additional information for SynExpr.AnonRecd
[]
type SynExprAnonRecdTrivia =
diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs
index 2c065437f2b..531ef79d264 100644
--- a/src/Compiler/TypedTree/TcGlobals.fs
+++ b/src/Compiler/TypedTree/TcGlobals.fs
@@ -1490,6 +1490,7 @@ type TcGlobals(
member val attrib_CallerFilePathAttribute = findSysAttrib "System.Runtime.CompilerServices.CallerFilePathAttribute"
member val attrib_CallerMemberNameAttribute = findSysAttrib "System.Runtime.CompilerServices.CallerMemberNameAttribute"
member val attrib_SkipLocalsInitAttribute = findSysAttrib "System.Runtime.CompilerServices.SkipLocalsInitAttribute"
+ member val attrib_DecimalConstantAttribute = findSysAttrib "System.Runtime.CompilerServices.DecimalConstantAttribute"
member val attribs_Unsupported = v_attribs_Unsupported
member val attrib_ProjectionParameterAttribute = mk_MFCore_attrib "ProjectionParameterAttribute"
diff --git a/src/Compiler/TypedTree/TcGlobals.fsi b/src/Compiler/TypedTree/TcGlobals.fsi
index 950d5217500..b7d5a892d06 100644
--- a/src/Compiler/TypedTree/TcGlobals.fsi
+++ b/src/Compiler/TypedTree/TcGlobals.fsi
@@ -474,6 +474,8 @@ type internal TcGlobals =
member attrib_SkipLocalsInitAttribute: BuiltinAttribInfo
+ member attrib_DecimalConstantAttribute: BuiltinAttribInfo
+
member attrib_StructAttribute: BuiltinAttribInfo
member attrib_StructLayoutAttribute: BuiltinAttribInfo
diff --git a/src/Compiler/TypedTree/TypeProviders.fs b/src/Compiler/TypedTree/TypeProviders.fs
index 78baba4ee9d..5c81312e135 100644
--- a/src/Compiler/TypedTree/TypeProviders.fs
+++ b/src/Compiler/TypedTree/TypeProviders.fs
@@ -979,7 +979,7 @@ type ProvidedExprType =
| ProvidedTryFinallyExpr of ProvidedExpr * ProvidedExpr
| ProvidedLambdaExpr of ProvidedVar * ProvidedExpr
| ProvidedCallExpr of ProvidedExpr option * ProvidedMethodInfo * ProvidedExpr[]
- | ProvidedConstantExpr of obj * ProvidedType
+ | ProvidedConstantExpr of objnull * ProvidedType
| ProvidedDefaultExpr of ProvidedType
| ProvidedNewTupleExpr of ProvidedExpr[]
| ProvidedTupleGetExpr of ProvidedExpr * int
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs
index e7c4576b24e..71f26dbf95b 100644
--- a/src/Compiler/TypedTree/TypedTreeOps.fs
+++ b/src/Compiler/TypedTree/TypedTreeOps.fs
@@ -1853,7 +1853,20 @@ let isArray1DTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -
let isUnitTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tyconRefEq g g.unit_tcr_canon tcref | _ -> false)
-let isObjTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tyconRefEq g g.system_Object_tcref tcref | _ -> false)
+let isObjTyAnyNullness g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tyconRefEq g g.system_Object_tcref tcref | _ -> false)
+
+let isObjNullTy g ty =
+ ty
+ |> stripTyEqns g
+ |> (function TType_app(tcref, _, n) when (not g.checkNullness) || (n.TryEvaluate() <> ValueSome(NullnessInfo.WithoutNull))
+ -> tyconRefEq g g.system_Object_tcref tcref | _ -> false)
+
+let isObjTyWithoutNull (g:TcGlobals) ty =
+ g.checkNullness &&
+ ty
+ |> stripTyEqns g
+ |> (function TType_app(tcref, _, n) when (n.TryEvaluate() = ValueSome(NullnessInfo.WithoutNull))
+ -> tyconRefEq g g.system_Object_tcref tcref | _ -> false)
let isValueTypeTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _, _) -> tyconRefEq g g.system_Value_tcref tcref | _ -> false)
@@ -10020,7 +10033,7 @@ let EvalArithUnOp (opInt8, opInt16, opInt32, opInt64, opUInt8, opUInt16, opUInt3
| _ -> error (Error ( FSComp.SR.tastNotAConstantExpression(), m))
with :? System.OverflowException -> error (Error ( FSComp.SR.tastConstantExpressionOverflow(), m))
-let EvalArithBinOp (opInt8, opInt16, opInt32, opInt64, opUInt8, opUInt16, opUInt32, opUInt64, opSingle, opDouble) (arg1: Expr) (arg2: Expr) =
+let EvalArithBinOp (opInt8, opInt16, opInt32, opInt64, opUInt8, opUInt16, opUInt32, opUInt64, opSingle, opDouble, opDecimal) (arg1: Expr) (arg2: Expr) =
// At compile-time we check arithmetic
let m = unionRanges arg1.Range arg2.Range
try
@@ -10035,6 +10048,7 @@ let EvalArithBinOp (opInt8, opInt16, opInt32, opInt64, opUInt8, opUInt16, opUInt
| Expr.Const (Const.UInt64 x1, _, ty), Expr.Const (Const.UInt64 x2, _, _) -> Expr.Const (Const.UInt64 (opUInt64 x1 x2), m, ty)
| Expr.Const (Const.Single x1, _, ty), Expr.Const (Const.Single x2, _, _) -> Expr.Const (Const.Single (opSingle x1 x2), m, ty)
| Expr.Const (Const.Double x1, _, ty), Expr.Const (Const.Double x2, _, _) -> Expr.Const (Const.Double (opDouble x1 x2), m, ty)
+ | Expr.Const (Const.Decimal x1, _, ty), Expr.Const (Const.Decimal x2, _, _) -> Expr.Const (Const.Decimal (opDecimal x1 x2), m, ty)
| _ -> error (Error ( FSComp.SR.tastNotAConstantExpression(), m))
with :? System.OverflowException -> error (Error ( FSComp.SR.tastConstantExpressionOverflow(), m))
@@ -10066,9 +10080,10 @@ let rec EvalAttribArgExpr suppressLangFeatureCheck (g: TcGlobals) (x: Expr) =
| Const.Single _
| Const.Char _
| Const.Zero
- | Const.String _ ->
+ | Const.String _
+ | Const.Decimal _ ->
x
- | Const.Decimal _ | Const.IntPtr _ | Const.UIntPtr _ | Const.Unit ->
+ | Const.IntPtr _ | Const.UIntPtr _ | Const.Unit ->
errorR (Error ( FSComp.SR.tastNotAConstantExpression(), m))
x
@@ -10084,7 +10099,7 @@ let rec EvalAttribArgExpr suppressLangFeatureCheck (g: TcGlobals) (x: Expr) =
match v1 with
| IntegerConstExpr ->
- EvalArithBinOp ((|||), (|||), (|||), (|||), (|||), (|||), (|||), (|||), ignore2, ignore2) v1 (EvalAttribArgExpr suppressLangFeatureCheck g arg2)
+ EvalArithBinOp ((|||), (|||), (|||), (|||), (|||), (|||), (|||), (|||), ignore2, ignore2, ignore2) v1 (EvalAttribArgExpr suppressLangFeatureCheck g arg2)
| _ ->
errorR (Error ( FSComp.SR.tastNotAConstantExpression(), x.Range))
x
@@ -10099,7 +10114,7 @@ let rec EvalAttribArgExpr suppressLangFeatureCheck (g: TcGlobals) (x: Expr) =
Expr.Const (Const.Char (x1 + x2), m, ty)
| _ ->
checkFeature()
- EvalArithBinOp (Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+)) v1 v2
+ EvalArithBinOp (Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+), Checked.(+)) v1 v2
| SpecificBinopExpr g g.unchecked_subtraction_vref (arg1, arg2) ->
checkFeature()
let v1, v2 = EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg1, EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2
@@ -10108,16 +10123,16 @@ let rec EvalAttribArgExpr suppressLangFeatureCheck (g: TcGlobals) (x: Expr) =
| Expr.Const (Const.Char x1, m, ty), Expr.Const (Const.Char x2, _, _) ->
Expr.Const (Const.Char (x1 - x2), m, ty)
| _ ->
- EvalArithBinOp (Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-)) v1 v2
+ EvalArithBinOp (Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-), Checked.(-)) v1 v2
| SpecificBinopExpr g g.unchecked_multiply_vref (arg1, arg2) ->
checkFeature()
- EvalArithBinOp (Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*)) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg1) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
+ EvalArithBinOp (Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*), Checked.(*)) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg1) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
| SpecificBinopExpr g g.unchecked_division_vref (arg1, arg2) ->
checkFeature()
- EvalArithBinOp ((/), (/), (/), (/), (/), (/), (/), (/), (/), (/)) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg1) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
+ EvalArithBinOp ((/), (/), (/), (/), (/), (/), (/), (/), (/), (/), (/)) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg1) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
| SpecificBinopExpr g g.unchecked_modulus_vref (arg1, arg2) ->
checkFeature()
- EvalArithBinOp ((%), (%), (%), (%), (%), (%), (%), (%), (%), (%)) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg1) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
+ EvalArithBinOp ((%), (%), (%), (%), (%), (%), (%), (%), (%), (%), (%)) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg1) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
| SpecificBinopExpr g g.bitwise_shift_left_vref (arg1, arg2) ->
checkFeature()
EvalArithShiftOp ((<<<), (<<<), (<<<), (<<<), (<<<), (<<<), (<<<), (<<<)) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg1) (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
@@ -10130,7 +10145,7 @@ let rec EvalAttribArgExpr suppressLangFeatureCheck (g: TcGlobals) (x: Expr) =
match v1 with
| IntegerConstExpr ->
- EvalArithBinOp ((&&&), (&&&), (&&&), (&&&), (&&&), (&&&), (&&&), (&&&), ignore2, ignore2) v1 (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
+ EvalArithBinOp ((&&&), (&&&), (&&&), (&&&), (&&&), (&&&), (&&&), (&&&), ignore2, ignore2, ignore2) v1 (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
| _ ->
errorR (Error ( FSComp.SR.tastNotAConstantExpression(), x.Range))
x
@@ -10140,7 +10155,7 @@ let rec EvalAttribArgExpr suppressLangFeatureCheck (g: TcGlobals) (x: Expr) =
match v1 with
| IntegerConstExpr ->
- EvalArithBinOp ((^^^), (^^^), (^^^), (^^^), (^^^), (^^^), (^^^), (^^^), ignore2, ignore2) v1 (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
+ EvalArithBinOp ((^^^), (^^^), (^^^), (^^^), (^^^), (^^^), (^^^), (^^^), ignore2, ignore2, ignore2) v1 (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
| _ ->
errorR (Error (FSComp.SR.tastNotAConstantExpression(), x.Range))
x
@@ -10150,7 +10165,7 @@ let rec EvalAttribArgExpr suppressLangFeatureCheck (g: TcGlobals) (x: Expr) =
match v1 with
| FloatConstExpr ->
- EvalArithBinOp (ignore2, ignore2, ignore2, ignore2, ignore2, ignore2, ignore2, ignore2, ( ** ), ( ** )) v1 (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
+ EvalArithBinOp (ignore2, ignore2, ignore2, ignore2, ignore2, ignore2, ignore2, ignore2, ( ** ), ( ** ), ignore2) v1 (EvalAttribArgExpr SuppressLanguageFeatureCheck.Yes g arg2)
| _ ->
errorR (Error (FSComp.SR.tastNotAConstantExpression(), x.Range))
x
diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi
index 8c17d530762..85c2adaab91 100755
--- a/src/Compiler/TypedTree/TypedTreeOps.fsi
+++ b/src/Compiler/TypedTree/TypedTreeOps.fsi
@@ -1666,8 +1666,14 @@ val rankOfArrayTyconRef: TcGlobals -> TyconRef -> int
/// Determine if a type is the F# unit type
val isUnitTy: TcGlobals -> TType -> bool
-/// Determine if a type is the System.Object type
-val isObjTy: TcGlobals -> TType -> bool
+/// Determine if a type is the System.Object type with any nullness qualifier
+val isObjTyAnyNullness: TcGlobals -> TType -> bool
+
+/// Determine if a type is the (System.Object | null) type. Allows either nullness if null checking is disabled.
+val isObjNullTy: TcGlobals -> TType -> bool
+
+/// Determine if a type is a strictly non-nullable System.Object type. If nullness checking is disabled, this returns false.
+val isObjTyWithoutNull: TcGlobals -> TType -> bool
/// Determine if a type is the System.ValueType type
val isValueTypeTy: TcGlobals -> TType -> bool
diff --git a/src/Compiler/Utilities/FileSystem.fs b/src/Compiler/Utilities/FileSystem.fs
index cb8c1cdbea8..a541234199e 100644
--- a/src/Compiler/Utilities/FileSystem.fs
+++ b/src/Compiler/Utilities/FileSystem.fs
@@ -157,7 +157,7 @@ type ByteArrayMemory(bytes: byte[], offset, length) =
type SafeUnmanagedMemoryStream =
inherit UnmanagedMemoryStream
- val mutable private holder: obj
+ val mutable private holder: objnull
val mutable private isDisposed: bool
new(addr, length, holder) =
diff --git a/src/Compiler/Utilities/illib.fs b/src/Compiler/Utilities/illib.fs
index 6c5a52a2fd8..e09c650e39b 100644
--- a/src/Compiler/Utilities/illib.fs
+++ b/src/Compiler/Utilities/illib.fs
@@ -1139,7 +1139,7 @@ module IPartialEqualityComparer =
member _.GetHashCode(Wrap x) = per.GetHashCode x
}
// Wrap a Wrap _ around all keys in case the key type is itself a type using null as a representation
- let dict = Dictionary, obj>(wper)
+ let dict = Dictionary, _>(wper)
seq
|> List.filter (fun v ->
diff --git a/src/Compiler/Utilities/sformat.fs b/src/Compiler/Utilities/sformat.fs
index 9279bf093d0..f6fc27b1e51 100644
--- a/src/Compiler/Utilities/sformat.fs
+++ b/src/Compiler/Utilities/sformat.fs
@@ -1012,7 +1012,7 @@ module Display =
// Recursive descent
let rec nestedObjL depthLim prec (x: obj, ty: Type) = objL ShowAll depthLim prec (x, ty)
- and objL showMode depthLim prec (x: obj, ty: Type) =
+ and objL showMode depthLim prec (x: objnull, ty: Type) =
let info = Value.GetValueInfo bindingFlags (x, ty)
try
if depthLim <= 0 || exceededPrintSize () then
@@ -1337,9 +1337,6 @@ module Display =
if
word = "map"
- && (match v with
- | null -> false
- | _ -> true)
&& tyv.IsGenericType
&& tyv.GetGenericTypeDefinition() = typedefof>
then
diff --git a/src/Compiler/Utilities/sr.fs b/src/Compiler/Utilities/sr.fs
index 9473cc8d78e..10a615846e3 100644
--- a/src/Compiler/Utilities/sr.fs
+++ b/src/Compiler/Utilities/sr.fs
@@ -27,7 +27,7 @@ module internal DiagnosticMessage =
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
- let mkFunctionValue (tys: System.Type[]) (impl: obj -> obj) =
+ let mkFunctionValue (tys: System.Type[]) (impl: objnull -> objnull) =
FSharpValue.MakeFunction(FSharpType.MakeFunctionType(tys[0], tys[1]), impl)
let funTyC = typeof obj>.GetGenericTypeDefinition()
diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy
index 54d47b7c4fb..185bd1ed842 100644
--- a/src/Compiler/pars.fsy
+++ b/src/Compiler/pars.fsy
@@ -2,7 +2,6 @@
%{
-#nowarn "64" // turn off warnings that type variables used in production annotations are instantiated to concrete type
#nowarn "1182" // generated code has lots of unused "parseState"
#nowarn "3261" // the generated code would need to properly annotate nulls, e.g. changing System.Object to `obj|null`
@@ -4403,24 +4402,28 @@ declExpr:
exprFromParseError (SynExpr.ForEach(spFor, spIn, SeqExprOnly false, true, $2, arbExpr ("forLoopCollection", mFor), arbExpr ("forLoopBody3", mForLoopBodyArb), mForLoopAll)) }
| YIELD declExpr
- { SynExpr.YieldOrReturn(($1, not $1), $2, unionRanges (rhs parseState 1) $2.Range) }
+ { let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 }
+ SynExpr.YieldOrReturn(($1, not $1), $2, (unionRanges (rhs parseState 1) $2.Range), trivia) }
| YIELD_BANG declExpr
- { SynExpr.YieldOrReturnFrom(($1, not $1), $2, unionRanges (rhs parseState 1) $2.Range) }
+ { let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 }
+ SynExpr.YieldOrReturnFrom(($1, not $1), $2, (unionRanges (rhs parseState 1) $2.Range), trivia) }
| YIELD recover
{ let mYieldAll = rhs parseState 1
- SynExpr.YieldOrReturn(($1, not $1), arbExpr ("yield", mYieldAll), mYieldAll) }
+ let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 }
+ SynExpr.YieldOrReturn(($1, not $1), arbExpr ("yield", mYieldAll), mYieldAll, trivia) }
| YIELD_BANG recover
{ let mYieldAll = rhs parseState 1
- SynExpr.YieldOrReturnFrom(($1, not $1), arbExpr ("yield!", mYieldAll), mYieldAll) }
+ let trivia: SynExprYieldOrReturnFromTrivia = { YieldOrReturnFromKeyword = rhs parseState 1 }
+ SynExpr.YieldOrReturnFrom(($1, not $1), arbExpr ("yield!", mYieldAll), mYieldAll, trivia) }
| BINDER headBindingPattern EQUALS typedSequentialExprBlock IN opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let
{ let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5)
let mEquals = rhs parseState 3
let m = unionRanges (rhs parseState 1) $8.Range
- let trivia: SynExprLetOrUseBangTrivia = { EqualsRange = Some mEquals }
+ let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals }
SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m, trivia) }
| OBINDER headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let
@@ -4429,7 +4432,7 @@ declExpr:
let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range)
let mEquals = rhs parseState 3
let m = unionRanges (rhs parseState 1) $8.Range
- let trivia: SynExprLetOrUseBangTrivia = { EqualsRange = Some mEquals }
+ let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals }
SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m, trivia) }
| OBINDER headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let
@@ -4438,16 +4441,19 @@ declExpr:
let mEquals = rhs parseState 3
let mAll = unionRanges (rhs parseState 1) (rhs parseState 7)
let m = $4.Range.EndRange // zero-width range
- let trivia: SynExprLetOrUseBangTrivia = { EqualsRange = Some mEquals }
+ let trivia: SynExprLetOrUseBangTrivia = { LetOrUseBangKeyword = rhs parseState 1 ; EqualsRange = Some mEquals }
SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, [], SynExpr.ImplicitZero m, mAll, trivia) }
| DO_BANG typedSequentialExpr IN opt_OBLOCKSEP typedSequentialExprBlock %prec expr_let
{ let spBind = DebugPointAtBinding.NoneAtDo
- let trivia: SynExprLetOrUseBangTrivia = { EqualsRange = None }
- SynExpr.LetOrUseBang(spBind, false, true, SynPat.Const(SynConst.Unit, $2.Range), $2, [], $5, unionRanges (rhs parseState 1) $5.Range, trivia) }
+ let trivia: SynExprDoBangTrivia = { DoBangKeyword = rhs parseState 1 }
+ let m = unionRanges (rhs parseState 1) $5.Range
+ SynExpr.DoBang($2, m, trivia) }
| ODO_BANG typedSequentialExprBlock hardwhiteDefnBindingsTerminator %prec expr_let
- { SynExpr.DoBang($2, unionRanges (rhs parseState 1) $2.Range) }
+ { let trivia: SynExprDoBangTrivia = { DoBangKeyword = rhs parseState 1 }
+ let m = unionRanges (rhs parseState 1) $2.Range
+ SynExpr.DoBang($2, m, trivia) }
| FIXED declExpr
{ SynExpr.Fixed($2, (unionRanges (rhs parseState 1) $2.Range)) }
@@ -4456,7 +4462,8 @@ declExpr:
{ errorR(Error(FSComp.SR.parsArrowUseIsLimited(), lhs parseState))
let mArrow = rhs parseState 1
let expr = $2 mArrow
- SynExpr.YieldOrReturn((true, true), expr, (unionRanges mArrow expr.Range)) }
+ let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = rhs parseState 1 }
+ SynExpr.YieldOrReturn((true, true), expr, (unionRanges mArrow expr.Range), trivia) }
| declExpr COLON_QMARK typ
{ SynExpr.TypeTest($1, $3, unionRanges $1.Range $3.Range) }
@@ -5454,7 +5461,8 @@ arrowThenExprR:
| RARROW typedSequentialExprBlockR
{ let mArrow = rhs parseState 1
let expr = $2 mArrow
- SynExpr.YieldOrReturn((true, false), expr, unionRanges mArrow expr.Range) }
+ let trivia: SynExprYieldOrReturnTrivia = { YieldOrReturnKeyword = mArrow }
+ SynExpr.YieldOrReturn((true, false), expr, (unionRanges mArrow expr.Range), trivia) }
forLoopBinder:
| parenPattern IN declExpr
diff --git a/src/Compiler/pppars.fsy b/src/Compiler/pppars.fsy
index 41cb41ff38a..cd27722a254 100644
--- a/src/Compiler/pppars.fsy
+++ b/src/Compiler/pppars.fsy
@@ -3,7 +3,6 @@
%{
open FSharp.Compiler.DiagnosticsLogger
-#nowarn "64" // turn off warnings that type variables used in production annotations are instantiated to concrete type
#nowarn "3261" // the generated code would need to properly annotate nulls, e.g. changing System.Object to `obj|null`
let dummy = IfdefId("DUMMY")
diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf
index e384127d444..958a1357ac9 100644
--- a/src/Compiler/xlf/FSComp.txt.cs.xlf
+++ b/src/Compiler/xlf/FSComp.txt.cs.xlf
@@ -307,11 +307,6 @@
Vyvolá upozornění, pokud je atribut TailCall použit u nerekurzivních funkcí.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
Průnik omezení u flexibilních typů
diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf
index 2cd51bff66a..d7233a5d2fc 100644
--- a/src/Compiler/xlf/FSComp.txt.de.xlf
+++ b/src/Compiler/xlf/FSComp.txt.de.xlf
@@ -307,11 +307,6 @@
Löst Warnungen aus, wenn das Attribut "TailCall" für nicht rekursive Funktionen verwendet wird.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
Einschränkungsüberschneidung für flexible Typen
diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf
index 47c41d9d5a3..1b3205ffa53 100644
--- a/src/Compiler/xlf/FSComp.txt.es.xlf
+++ b/src/Compiler/xlf/FSComp.txt.es.xlf
@@ -307,11 +307,6 @@
Genera advertencias si el atributo 'TailCall' se usa en funciones no recursivas.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
Intersección de restricciones en tipos flexibles
diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf
index 2509d30cd3c..018180a8fb6 100644
--- a/src/Compiler/xlf/FSComp.txt.fr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.fr.xlf
@@ -307,11 +307,6 @@
Émet des avertissements si l’attribut « TailCall » est utilisé sur des fonctions non récursives.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
Intersection de contraintes sur les types flexibles
diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf
index 932620230c2..7cc3f46259b 100644
--- a/src/Compiler/xlf/FSComp.txt.it.xlf
+++ b/src/Compiler/xlf/FSComp.txt.it.xlf
@@ -307,11 +307,6 @@
Genera avvisi se l'attributo 'TailCall' viene utilizzato in funzioni non ricorsive.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
Intersezione di vincoli su tipi flessibili
diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf
index 0d7aee793bf..10c5f06f4ff 100644
--- a/src/Compiler/xlf/FSComp.txt.ja.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ja.xlf
@@ -307,11 +307,6 @@
'TailCall' 属性が再帰関数以外で使用されている場合、警告が発せられます。
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
フレキシブル型の制約積集合
diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf
index aaf528ddf61..94cd344f052 100644
--- a/src/Compiler/xlf/FSComp.txt.ko.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ko.xlf
@@ -307,11 +307,6 @@
'TailCall' 특성이 비 재귀 함수에 사용되는 경우 경고를 발생합니다.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
유연한 형식의 제약 조건 교집합
diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf
index 5727c48f9ef..01f2ff1d5e3 100644
--- a/src/Compiler/xlf/FSComp.txt.pl.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pl.xlf
@@ -307,11 +307,6 @@
Zgłasza ostrzeżenia, jeśli atrybut „TailCall” jest używany w funkcjach niekursywnych.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
Przecięcie ograniczenia dla typów elastycznych
diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
index 481824624bd..63da6a667b1 100644
--- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
+++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf
@@ -307,11 +307,6 @@
Gera avisos se o atributo "TailCall" for usado em funções não recursivas.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
Interseção de restrição em tipos flexíveis
diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf
index 597b46ad265..231bc83103b 100644
--- a/src/Compiler/xlf/FSComp.txt.ru.xlf
+++ b/src/Compiler/xlf/FSComp.txt.ru.xlf
@@ -307,11 +307,6 @@
Выдает предупреждения, если атрибут TailCall используется в нерекурсивных функциях.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
Пересечение ограничений на гибких типах
diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf
index 9896d5fec9b..a3bab7e5a92 100644
--- a/src/Compiler/xlf/FSComp.txt.tr.xlf
+++ b/src/Compiler/xlf/FSComp.txt.tr.xlf
@@ -307,11 +307,6 @@
'TailCall' özniteliği özyinelemeli olmayan işlevlerde kullanılıyorsa uyarılar oluşturur.
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
Esnek türlerde kısıtlama kesişimi
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
index 41a056b3bd7..579ac9b79c3 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
@@ -307,11 +307,6 @@
如果在非递归函数上使用“TailCall”属性,则引发警告。
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
灵活类型的约束交集
diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
index 74c4b57ae60..09818a7487b 100644
--- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
+++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
@@ -307,11 +307,6 @@
如果 'TailCall' 屬性用於非遞迴函數,則引發警告。
-
- The interaction between #nowarn and #line is now consistent.
- The interaction between #nowarn and #line is now consistent.
-
-
Constraint intersection on flexible types
彈性類型上的條件約束交集
diff --git a/src/FSharp.Build/FSharpEmbedResourceText.fs b/src/FSharp.Build/FSharpEmbedResourceText.fs
index ac0adf8329d..061715184de 100644
--- a/src/FSharp.Build/FSharpEmbedResourceText.fs
+++ b/src/FSharp.Build/FSharpEmbedResourceText.fs
@@ -295,7 +295,7 @@ open Printf
#endif
- static let mkFunctionValue (tys: System.Type[]) (impl:obj->obj) =
+ static let mkFunctionValue (tys: System.Type[]) (impl:objnull->objnull) =
FSharpValue.MakeFunction(FSharpType.MakeFunctionType(tys.[0],tys.[1]), impl)
static let funTyC = typeof<(obj -> obj)>.GetGenericTypeDefinition()
diff --git a/src/FSharp.Build/Fsc.fs b/src/FSharp.Build/Fsc.fs
index c18b42a3989..25cdbd34195 100644
--- a/src/FSharp.Build/Fsc.fs
+++ b/src/FSharp.Build/Fsc.fs
@@ -786,10 +786,10 @@ type public Fsc() as this =
let builder = generateCommandLineBuilder ()
builder.GetCapturedArguments() |> String.concat Environment.NewLine
- // expose this to internal components (for nunit testing)
+ // expose this to internal components (for unit testing)
member internal fsc.InternalGenerateCommandLineCommands() = fsc.GenerateCommandLineCommands()
- // expose this to internal components (for nunit testing)
+ // expose this to internal components (for unit testing)
member internal fsc.InternalGenerateResponseFileCommands() = fsc.GenerateResponseFileCommands()
member internal fsc.InternalExecuteTool(pathToTool, responseFileCommands, commandLineCommands) =
diff --git a/src/FSharp.Build/Fsi.fs b/src/FSharp.Build/Fsi.fs
index dd0ccff9754..dc362420db0 100644
--- a/src/FSharp.Build/Fsi.fs
+++ b/src/FSharp.Build/Fsi.fs
@@ -161,6 +161,34 @@ type public Fsi() as this =
builder
+ let mutable bufferLimit = None
+
+ let textOutput =
+ lazy System.Collections.Generic.Queue<_>(defaultArg bufferLimit 1024)
+
+ override this.LogEventsFromTextOutput(line, msgImportance) =
+ if this.CaptureTextOutput then
+ textOutput.Value.Enqueue line
+
+ match bufferLimit with
+ | Some limit when textOutput.Value.Count > limit -> textOutput.Value.Dequeue() |> ignore
+ | _ -> ()
+
+ base.LogEventsFromTextOutput(line, msgImportance)
+
+ member _.BufferLimit
+ with get () = defaultArg bufferLimit 0
+ and set limit = bufferLimit <- if limit = 0 then None else Some limit
+
+ member val CaptureTextOutput = false with get, set
+
+ [
@@ -21,8 +22,6 @@
-
-
diff --git a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj
index b884948e8b8..d4d410bacd4 100644
--- a/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj
+++ b/tests/EndToEndBuildTests/ComboProvider/ComboProvider.Tests/ComboProvider.Tests.fsproj
@@ -7,6 +7,7 @@
false
$(FSharpCoreShippedPackageVersionValue)
NO_GENERATIVE
+ xunit
@@ -18,8 +19,6 @@
-
-
diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Nowarn.fs b/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Nowarn.fs
deleted file mode 100644
index 78067aa8c32..00000000000
--- a/tests/FSharp.Compiler.ComponentTests/CompilerDirectives/Nowarn.fs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
-namespace CompilerDirectives
-
-open Xunit
-open FSharp.Test.Compiler
-
-module Nowarn =
-
- let warn20Text = "The result of this expression has type 'string' and is implicitly ignored. Consider using 'ignore' to discard this value explicitly, e.g. 'expr |> ignore', or 'let' to bind the result to a name, e.g. 'let result = expr'."
-
- let checkFileBugSource = """
-module A
-#nowarn "20"
-#line 1 "xyz.fs"
-""
- """
-
- let checkFileBugSource2 = """
-module A
-#line 1 "xyz.fs"
-#nowarn "20"
-""
- """
-
-
- []
- let ``checkFile bug simulation for compatibility`` () =
-
- FSharp checkFileBugSource
- |> withLangVersion80
- |> compile
- |> shouldSucceed
-
- []
- let ``checkFile bug fixed leads to new warning`` () =
-
- FSharp checkFileBugSource
- |> withLangVersion90
- |> compile
- |> shouldFail
- |> withDiagnostics [
- (Warning 20, Line 1, Col 1, Line 1, Col 3, warn20Text)
- ]
-
- []
- let ``checkFile bug fixed, no warning if nowarn is correctly used`` () =
-
- FSharp checkFileBugSource2
- |> withLangVersion90
- |> compile
- |> shouldSucceed
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs
index bf413c777d3..9b7cdc5a053 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs
@@ -98,7 +98,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargets01_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -134,7 +134,7 @@ module CustomAttributes_AttributeUsage =
let ``E_AttributeTargetIsField01_fs`` compilation =
compilation
|> withOptions ["--nowarn:25"]
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -187,7 +187,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetIsMethod02_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> withOptions ["--nowarn:25"]
|> verifyCompile
|> shouldFail
@@ -218,7 +218,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetIsMethod03_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> withOptions ["--nowarn:25"]
|> verifyCompile
|> shouldFail
@@ -336,7 +336,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetIsStruct_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -366,7 +366,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetIsClass_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -387,7 +387,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetIsClass01_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -485,7 +485,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetIsField03_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -505,7 +505,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetIsProperty01_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -525,7 +525,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetIsCtor01_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -562,7 +562,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetIsEnum01_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -599,7 +599,7 @@ module CustomAttributes_AttributeUsage =
[]
let ``E_AttributeTargetsIsDelegate01_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -648,7 +648,7 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
[]
let ``E_AttributeTargetIsInterface_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -670,7 +670,7 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
[]
let ``E_AttributeTargetIsClass02_fs`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -698,9 +698,9 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
// SOURCE=CLIMutableAttribute01.fs # CLIMutableAttribute01.fs
[]
- let ``CLIMutableAttribute01 preview`` compilation =
+ let ``CLIMutableAttribute01 90`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldSucceed
@@ -724,9 +724,9 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
// SOURCE=E_CLIMutableAttribute.fs # E_CLIMutableAttribute.fs
[]
- let ``E_CLIMutableAttribute preview`` compilation =
+ let ``E_CLIMutableAttribute 90`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -761,9 +761,9 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
// SOURCE=E_AllowNullLiteral.fs # E_AllowNullLiteral.fs
[]
- let ``E_AllowNullLiteral preview`` compilation =
+ let ``E_AllowNullLiteral 90`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -788,9 +788,9 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
// SOURCE=AllowNullLiteral01.fs # AllowNullLiteral01.fs
[]
- let ``AllowNullLiteral01 preview`` compilation =
+ let ``AllowNullLiteral01 90`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldSucceed
@@ -816,9 +816,9 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
// SOURCE=E_VolatileField.fs # E_VolatileField.fs
[]
- let ``E_VolatileField preview`` compilation =
+ let ``E_VolatileField 90`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -844,9 +844,9 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
// SOURCE=VolatileField01.fs # VolatileField01.fs
[]
- let ``VolatileField01 preview`` compilation =
+ let ``VolatileField01 90`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldSucceed
@@ -865,9 +865,9 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
// SOURCE=E_SealedAttribute01.fs # E_SealedAttribute01.fs
[]
- let ``E_SealedAttribute01 preview`` compilation =
+ let ``E_SealedAttribute01 90`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -893,9 +893,9 @@ type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
// SOURCE=E_StructLayout01.fs # E_StructLayout01.fs
[]
- let ``E_StructLayout01 preview`` compilation =
+ let ``E_StructLayout01 90`` compilation =
compilation
- |> withLangVersionPreview
+ |> withLangVersion90
|> verifyCompile
|> shouldFail
|> withDiagnostics [
@@ -925,7 +925,7 @@ and []
"""
[]
- []
+ []
[]
let ``Regression for - F# 9 compiler cannot find constructor for attribute`` langVersion =
FSharp missingConstructorRepro
@@ -933,3 +933,36 @@ and []
|> verifyCompile
|> shouldSucceed
#endif
+
+ [] // Regression for https://github.com/dotnet/fsharp/issues/14304
+ let ``Construct an object with default and params parameters using parameterless constructor`` () =
+ Fsx """
+open System
+open System.Runtime.InteropServices
+
+type DefaultAndParams([]x: int, [] value: string[]) =
+ inherit Attribute()
+
+type ParamsOnly([] value: string[]) =
+ inherit Attribute()
+
+type DefaultOnly([]x: int) =
+ inherit Attribute()
+
+[]
+type Q1 = struct end
+
+[] // ok
+type Q11 = struct end
+
+[] // ok
+type Q12 = struct end
+
+[]
+type Q2 = struct end
+
+[]
+type Q3 = struct end
+ """
+ |> typecheck
+ |> shouldSucceed
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs
index d67f22efdc8..c0a19c9ad3e 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/Basic.fs
@@ -144,13 +144,12 @@ module LetBindings_Basic =
|> verifyCompile
|> shouldFail
|> withDiagnostics [
- (Error 267, Line 11, Col 18, Line 11, Col 19, "This is not a valid constant expression or custom attribute value")
- (Error 837, Line 11, Col 13, Line 11, Col 31, "This is not a valid constant expression")
- (Error 267, Line 14, Col 13, Line 14, Col 17, "This is not a valid constant expression or custom attribute value")
- (Error 267, Line 17, Col 13, Line 17, Col 15, "This is not a valid constant expression or custom attribute value")
- (Error 267, Line 20, Col 13, Line 20, Col 17, "This is not a valid constant expression or custom attribute value")
- (Error 267, Line 23, Col 13, Line 23, Col 18, "This is not a valid constant expression or custom attribute value")
- (Warning 3178, Line 26, Col 13, Line 26, Col 26, "This is not valid literal expression. The [] attribute will be ignored.")
+ (Error 267, Line 10, Col 18, Line 10, Col 19, "This is not a valid constant expression or custom attribute value")
+ (Error 837, Line 10, Col 13, Line 10, Col 31, "This is not a valid constant expression")
+ (Error 267, Line 16, Col 13, Line 16, Col 15, "This is not a valid constant expression or custom attribute value")
+ (Error 267, Line 19, Col 13, Line 19, Col 17, "This is not a valid constant expression or custom attribute value")
+ (Error 267, Line 22, Col 13, Line 22, Col 18, "This is not a valid constant expression or custom attribute value")
+ (Warning 3178, Line 25, Col 13, Line 25, Col 26, "This is not valid literal expression. The [] attribute will be ignored.")
]
// SOURCE=E_Pathological01.fs SCFLAGS=--test:ErrorRanges # E_Pathological01.fs
@@ -303,4 +302,4 @@ type C() =
|> withDiagnostics [
(Warning 3582, Line 4, Col 5, Line 4, Col 12, "This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses.")
(Warning 3582, Line 5, Col 5, Line 5, Col 11, "This is a function definition that shadows a union case. If this is what you want, ignore or suppress this warning. If you want it to be a union case deconstruction, add parentheses.")
- ]
+ ]
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/E_Literals04.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/E_Literals04.fs
index aa3395e0b6f..c253d840657 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/E_Literals04.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/LetBindings/Basic/E_Literals04.fs
@@ -1,11 +1,10 @@
// #Regression #Conformance #DeclarationElements #LetBindings
-//This is not a valid constant expression or custom attribute value$
-//This is not a valid constant expression$
-//This is not a valid constant expression or custom attribute value$
-//This is not a valid constant expression or custom attribute value$
-//This is not a valid constant expression or custom attribute value$
-//This is not a valid constant expression or custom attribute value$
-//This is not valid literal expression. The \[\] attribute will be ignored\.$
+//This is not a valid constant expression or custom attribute value$
+//This is not a valid constant expression$
+//This is not a valid constant expression or custom attribute value$
+//This is not a valid constant expression or custom attribute value$
+//This is not a valid constant expression or custom attribute value$
+//This is not valid literal expression. The \[\] attribute will be ignored\.$
[]
let lit01 = (let x = "2" in x)
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/InferenceProcedures/ByrefSafetyAnalysis/MigratedTest02.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/InferenceProcedures/ByrefSafetyAnalysis/MigratedTest02.fs
index c34bd114f35..9c166a47aac 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/InferenceProcedures/ByrefSafetyAnalysis/MigratedTest02.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/InferenceProcedures/ByrefSafetyAnalysis/MigratedTest02.fs
@@ -57,4 +57,4 @@ module Tests =
let test3 () =
StaticTest.Test2 // is passing, but probably shouldn't be
-printfn "Test Passed"
+printf "TEST PASSED OK"
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Decimal/Decimal.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Decimal/Decimal.fs
new file mode 100644
index 00000000000..1f168db110f
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Decimal/Decimal.fs
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace Conformance.PatternMatching
+
+open Xunit
+open FSharp.Test
+open FSharp.Test.Compiler
+
+module Decimal =
+
+ []
+ let ``Decimal - literal01.fs - --test:ErrorRanges`` compilation =
+ compilation
+ |> asFsx
+ |> withOptions ["--test:ErrorRanges";]
+ |> compile
+ |> shouldSucceed
+
+ []
+ let ``Decimal - incompleteMatchesLiteral01.fs - --test:ErrorRanges`` compilation =
+ compilation
+ |> asFs
+ |> withOptions ["--test:ErrorRanges"]
+ |> typecheck
+ |> shouldFail
+ |> withSingleDiagnostic (Warning 25, Line 7, Col 11, Line 7, Col 13, "Incomplete pattern matches on this expression. For example, the value '3M' may indicate a case not covered by the pattern(s).")
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Decimal/incompleteMatchesLiteral01.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Decimal/incompleteMatchesLiteral01.fs
new file mode 100644
index 00000000000..2397eeee743
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Decimal/incompleteMatchesLiteral01.fs
@@ -0,0 +1,11 @@
+[]
+let One = 1m
+[]
+let Two = 2m
+
+let test() =
+ match 3m with
+ | 0m -> false
+ | One | Two -> false
+
+exit 0
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Decimal/literal01.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Decimal/literal01.fs
new file mode 100644
index 00000000000..764958b9bd7
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Decimal/literal01.fs
@@ -0,0 +1,26 @@
+// #Conformance #PatternMatching
+#light
+
+// Pattern match decimal literals
+
+[]
+let Decimal1 = 5m
+
+[]
+let Decimal2 = 42.42m
+
+let testDecimal x =
+ match x with
+ | Decimal1 -> 1
+ | Decimal2 -> 2
+ | _ -> 0
+
+if testDecimal 1m <> 0 then exit 1
+
+if testDecimal Decimal1 <> 1 then exit 1
+if testDecimal 5m <> 1 then exit 1
+
+if testDecimal Decimal2 <> 2 then exit 1
+if testDecimal 42.42m <> 2 then exit 1
+
+exit 0
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Literals.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Literals.fs
index 9ac49148a78..d2dc41a3235 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Literals.fs
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Literals.fs
@@ -176,36 +176,95 @@ let [] x = System.Int32.MaxValue + 1
}
[]
- let ``Compilation fails when using decimal arithmetic in literal``() =
+ let ``Arithmetic can be used for constructing decimal literals``() =
FSharp """
module LiteralArithmetic
-let [] x = 1m + 1m
+[]
+let x = 1m + 2m
"""
|> withLangVersion80
|> compile
- |> shouldFail
- |> withResults [
- { Error = Error 267
- Range = { StartLine = 4
- StartColumn = 21
- EndLine = 4
- EndColumn = 23 }
- Message = "This is not a valid constant expression or custom attribute value" }
- { Error = Error 267
- Range = { StartLine = 4
- StartColumn = 26
- EndLine = 4
- EndColumn = 28 }
- Message = "This is not a valid constant expression or custom attribute value" }
- { Error = Error 267
- Range = { StartLine = 4
- StartColumn = 21
- EndLine = 4
- EndColumn = 28 }
- Message = "This is not a valid constant expression or custom attribute value" }
+ |> shouldSucceed
+ |> verifyIL [
+ """.field public static initonly valuetype [runtime]System.Decimal x"""
+ """.custom instance void [runtime]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ int32,
+ int32,
+ int32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00
+ 00 00 )"""
+ """.maxstack 8"""
+ """IL_0000: ldc.i4.3"""
+ """IL_0001: ldc.i4.0"""
+ """IL_0002: ldc.i4.0"""
+ """IL_0003: ldc.i4.0"""
+ """IL_0004: ldc.i4.0"""
+ """IL_0005: newobj instance void [runtime]System.Decimal::.ctor(int32,
+ int32,
+ int32,
+ bool,
+ uint8)"""
+ """IL_000a: stsfld valuetype [runtime]System.Decimal LiteralArithmetic::x"""
+ """IL_000f: ret"""
+ ]
+
+ []
+ let ``Pattern matching decimal literal``() =
+ FSharp """
+module PatternMatch
+
+[]
+let x = 5m
+
+let test () =
+ match x with
+ | 5m -> 0
+ | _ -> 1
+ """
+ |> withLangVersion80
+ |> compile
+ |> shouldSucceed
+ |> verifyIL [
+ """.field public static initonly valuetype [runtime]System.Decimal x"""
+ """ .custom instance void [runtime]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
+ uint8,
+ int32,
+ int32,
+ int32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00
+ 00 00 )"""
+ """IL_0016: call bool [netstandard]System.Decimal::op_Equality(valuetype [netstandard]System.Decimal,
+ valuetype [netstandard]System.Decimal)"""
+ """.maxstack 8"""
+ """IL_0000: ldc.i4.5"""
+ """IL_0001: ldc.i4.0"""
+ """IL_0002: ldc.i4.0"""
+ """IL_0003: ldc.i4.0"""
+ """IL_0004: ldc.i4.0"""
+ """IL_0005: newobj instance void [runtime]System.Decimal::.ctor(int32,
+ int32,
+ int32,
+ bool,
+ uint8)"""
+ """IL_000a: stsfld valuetype [runtime]System.Decimal PatternMatch::x"""
+ """IL_000f: ret"""
]
+ []
+ let ``Multiple decimals literals can be created``() =
+ FSharp """
+module DecimalLiterals
+
+[]
+let x = 41m
+
+[]
+let y = 42m
+ """
+ |> withLangVersion80
+ |> compile
+ |> shouldSucceed
+
[]
let ``Compilation fails when using arithmetic with a non-literal in literal``() =
FSharp """
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericCode.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericCode.fs
new file mode 100644
index 00000000000..06c0b1f3031
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericCode.fs
@@ -0,0 +1,19 @@
+module MyLibrary
+let strictlyNotNull (x:obj) = ()
+
+let myGenericFunction1 (p:_|null) =
+ match p with
+ | null -> ()
+ | p -> strictlyNotNull p
+
+let myGenericFunction2 p =
+ match p with
+ | Null -> ()
+ | NonNull p -> strictlyNotNull p
+
+let myGenericFunction3 p =
+ match p with
+ | null -> ()
+ // By the time we typecheck `| null`, we assign T to be a nullable type. Imagine there could be plenty of code before this pattern match got to be typechecked.
+ // As of now, the inference decision in the middle of a function cannot suddenly switch from (T which supports null) (T | null, where T is not nullable)
+ | pnn -> strictlyNotNull (pnn |> Unchecked.nonNull)
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericCode.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericCode.fs.il.net472.bsl
new file mode 100644
index 00000000000..0e958b024af
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericCode.fs.il.net472.bsl
@@ -0,0 +1,222 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed MyLibrary
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .custom instance void System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
+ .method public static void strictlyNotNull(object x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void myGenericFunction1(!!a p) cil managed
+ {
+ .param type a
+ .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
+ .param [1]
+ .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 )
+
+ .maxstack 3
+ .locals init (!!a V_0,
+ !!a V_1)
+ IL_0000: ldarg.0
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: box !!a
+ IL_0008: brfalse.s IL_000c
+
+ IL_000a: br.s IL_000d
+
+ IL_000c: ret
+
+ IL_000d: ldloc.0
+ IL_000e: stloc.1
+ IL_000f: ldloc.1
+ IL_0010: box !!a
+ IL_0015: call void MyLibrary::strictlyNotNull(object)
+ IL_001a: ret
+ }
+
+ .method public static void myGenericFunction2(!!a p) cil managed
+ {
+ .param type a
+ .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
+ .param [1]
+ .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 )
+
+ .maxstack 3
+ .locals init (!!a V_0,
+ class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2 V_1,
+ !!a V_2,
+ !!a V_3)
+ IL_0000: ldarg.0
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: stloc.2
+ IL_0004: ldloc.2
+ IL_0005: box !!a
+ IL_000a: brfalse.s IL_000e
+
+ IL_000c: br.s IL_0016
+
+ IL_000e: ldnull
+ IL_000f: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2 class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2::NewChoice1Of2(!0)
+ IL_0014: br.s IL_001c
+
+ IL_0016: ldloc.2
+ IL_0017: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2 class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2::NewChoice2Of2(!1)
+ IL_001c: stloc.1
+ IL_001d: ldloc.1
+ IL_001e: isinst class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2/Choice2Of2
+ IL_0023: brfalse.s IL_0027
+
+ IL_0025: br.s IL_0028
+
+ IL_0027: ret
+
+ IL_0028: ldloc.1
+ IL_0029: castclass class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2/Choice2Of2
+ IL_002e: call instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2/Choice2Of2::get_Item()
+ IL_0033: stloc.3
+ IL_0034: ldloc.3
+ IL_0035: box !!a
+ IL_003a: call void MyLibrary::strictlyNotNull(object)
+ IL_003f: ret
+ }
+
+ .method public static void myGenericFunction3(!!a p) cil managed
+ {
+ .param type a
+ .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
+ .param [1]
+ .custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 )
+
+ .maxstack 3
+ .locals init (!!a V_0,
+ !!a V_1,
+ !!a V_2,
+ !!a V_3)
+ IL_0000: ldarg.0
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: box !!a
+ IL_0008: brfalse.s IL_000c
+
+ IL_000a: br.s IL_000d
+
+ IL_000c: ret
+
+ IL_000d: ldloc.0
+ IL_000e: stloc.1
+ IL_000f: ldloc.1
+ IL_0010: stloc.2
+ IL_0011: ldloc.2
+ IL_0012: stloc.3
+ IL_0013: ldloc.3
+ IL_0014: box !!a
+ IL_0019: call void MyLibrary::strictlyNotNull(object)
+ IL_001e: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$MyLibrary
+ extends [runtime]System.Object
+{
+}
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableAttribute
+ extends [runtime]System.Attribute
+{
+ .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .field public uint8[] NullableFlags
+ .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor(uint8 scalarByteValue) cil managed
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [runtime]System.Attribute::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: ldc.i4.1
+ IL_0008: newarr [runtime]System.Byte
+ IL_000d: dup
+ IL_000e: ldc.i4.0
+ IL_000f: ldarg.1
+ IL_0010: stelem.i1
+ IL_0011: stfld uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+ IL_0016: ret
+ }
+
+ .method public specialname rtspecialname instance void .ctor(uint8[] NullableFlags) cil managed
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [runtime]System.Attribute::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: ldarg.1
+ IL_0008: stfld uint8[] System.Runtime.CompilerServices.NullableAttribute::NullableFlags
+ IL_000d: ret
+ }
+
+}
+
+.class private auto ansi beforefieldinit System.Runtime.CompilerServices.NullableContextAttribute
+ extends [runtime]System.Attribute
+{
+ .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .field public uint8 Flag
+ .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 )
+ .method public specialname rtspecialname instance void .ctor(uint8 Flag) cil managed
+ {
+ .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 )
+
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [runtime]System.Attribute::.ctor()
+ IL_0006: ldarg.0
+ IL_0007: ldarg.1
+ IL_0008: stfld uint8 System.Runtime.CompilerServices.NullableContextAttribute::Flag
+ IL_000d: ret
+ }
+
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericCode.fs.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericCode.fs.il.netcore.bsl
new file mode 100644
index 00000000000..ca54c9be1ee
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/GenericCode.fs.il.netcore.bsl
@@ -0,0 +1,157 @@
+
+
+
+
+
+.assembly extern runtime { }
+.assembly extern FSharp.Core { }
+.assembly assembly
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module assembly.dll
+
+.imagebase {value}
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+
+
+
+
+.class public abstract auto ansi sealed MyLibrary
+ extends [runtime]System.Object
+{
+ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
+ .custom instance void [runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
+ .method public static void strictlyNotNull(object x) cil managed
+ {
+
+ .maxstack 8
+ IL_0000: ret
+ }
+
+ .method public static void myGenericFunction1(!!a p) cil managed
+ {
+ .param type a
+ .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
+ .param [1]
+ .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 )
+
+ .maxstack 3
+ .locals init (!!a V_0,
+ !!a V_1)
+ IL_0000: ldarg.0
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: box !!a
+ IL_0008: brfalse.s IL_000c
+
+ IL_000a: br.s IL_000d
+
+ IL_000c: ret
+
+ IL_000d: ldloc.0
+ IL_000e: stloc.1
+ IL_000f: ldloc.1
+ IL_0010: box !!a
+ IL_0015: call void MyLibrary::strictlyNotNull(object)
+ IL_001a: ret
+ }
+
+ .method public static void myGenericFunction2(!!a p) cil managed
+ {
+ .param type a
+ .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
+ .param [1]
+ .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 )
+
+ .maxstack 3
+ .locals init (!!a V_0,
+ class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2 V_1,
+ !!a V_2,
+ !!a V_3)
+ IL_0000: ldarg.0
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: stloc.2
+ IL_0004: ldloc.2
+ IL_0005: box !!a
+ IL_000a: brfalse.s IL_000e
+
+ IL_000c: br.s IL_0016
+
+ IL_000e: ldnull
+ IL_000f: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2 class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2::NewChoice1Of2(!0)
+ IL_0014: br.s IL_001c
+
+ IL_0016: ldloc.2
+ IL_0017: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2 class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2::NewChoice2Of2(!1)
+ IL_001c: stloc.1
+ IL_001d: ldloc.1
+ IL_001e: isinst class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2/Choice2Of2
+ IL_0023: brfalse.s IL_0027
+
+ IL_0025: br.s IL_0028
+
+ IL_0027: ret
+
+ IL_0028: ldloc.1
+ IL_0029: castclass class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2/Choice2Of2
+ IL_002e: call instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpChoice`2/Choice2Of2::get_Item()
+ IL_0033: stloc.3
+ IL_0034: ldloc.3
+ IL_0035: box !!a
+ IL_003a: call void MyLibrary::strictlyNotNull(object)
+ IL_003f: ret
+ }
+
+ .method public static void myGenericFunction3(!!a p) cil managed
+ {
+ .param type a
+ .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 01 00 00 )
+ .param [1]
+ .custom instance void [runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = ( 01 00 02 00 00 )
+
+ .maxstack 3
+ .locals init (!!a V_0,
+ !!a V_1,
+ !!a V_2,
+ !!a V_3)
+ IL_0000: ldarg.0
+ IL_0001: stloc.0
+ IL_0002: ldloc.0
+ IL_0003: box !!a
+ IL_0008: brfalse.s IL_000c
+
+ IL_000a: br.s IL_000d
+
+ IL_000c: ret
+
+ IL_000d: ldloc.0
+ IL_000e: stloc.1
+ IL_000f: ldloc.1
+ IL_0010: stloc.2
+ IL_0011: ldloc.2
+ IL_0012: stloc.3
+ IL_0013: ldloc.3
+ IL_0014: box !!a
+ IL_0019: call void MyLibrary::strictlyNotNull(object)
+ IL_001e: ret
+ }
+
+}
+
+.class private abstract auto ansi sealed ''.$MyLibrary
+ extends [runtime]System.Object
+{
+}
+
+
+
+
+
+
diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs
index 3476cf07b2e..f0ebdfa0c34 100644
--- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs
+++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Nullness/NullnessMetadata.fs
@@ -89,6 +89,12 @@ let ``SupportsNull`` compilation =
|> withNoWarn 52
|> verifyCompilation DoNotOptimize
+[]
+let ``GenericCode`` compilation =
+ compilation
+ |> withNoWarn 52
+ |> verifyCompilation DoNotOptimize
+
module Interop =
open System.IO
diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs
index 34263b3f7bc..53cb33b5b78 100644
--- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TypeMismatchTests.fs
@@ -347,7 +347,7 @@ let f4 =
|> withDiagnostics [
(Error 1, Line 6, Col 9, Line 6, Col 16, "This expression was expected to have type\n 'int' \nbut here has type\n 'string' ")
(Error 1, Line 12, Col 13, Line 12, Col 16, "This expression was expected to have type\n 'int' \nbut here has type\n 'string' ")
- (Error 193, Line 21, Col 9, Line 21, Col 24, "Type constraint mismatch. The type \n 'int list' \nis not compatible with type\n 'string seq' \n")
+ (Error 193, Line 21, Col 16, Line 21, Col 24, "Type constraint mismatch. The type \n 'int list' \nis not compatible with type\n 'string seq' \n")
(Error 1, Line 28, Col 9, Line 28, Col 12, "This expression was expected to have type\n 'int64' \nbut here has type\n 'float' ")
]
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 96265fdd24b..4b50b28aa12 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -33,7 +33,6 @@
-
@@ -117,6 +116,7 @@
+
@@ -259,6 +259,7 @@
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Interop/Literals.fs b/tests/FSharp.Compiler.ComponentTests/Interop/Literals.fs
new file mode 100644
index 00000000000..5eeea2822b4
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Interop/Literals.fs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace Interop
+
+open Xunit
+open FSharp.Test.Compiler
+
+module ``Literals interop`` =
+
+ []
+ let ``Instantiate F# decimal literal from C#`` () =
+ let FSLib =
+ FSharp """
+namespace Interop.FS
+
+module DecimalLiteral =
+ []
+ let x = 7m
+ """
+ |> withName "FSLib"
+
+ let app =
+ CSharp """
+using System;
+using Interop.FS;
+public class C {
+ public Decimal y = DecimalLiteral.x;
+}
+ """
+ |> withReferences [FSLib]
+ |> withName "CSharpApp"
+
+ app
+ |> compile
+ |> shouldSucceed
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/CodeQuotationTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/CodeQuotationTests.fs
index dc98a4be095..90a4a188e4f 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/CodeQuotationTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/CodeQuotationTests.fs
@@ -39,3 +39,22 @@ let z : unit =
|> withLangVersion50
|> compileAndRun
|> shouldSucceed
+
+ []
+ let ``Quotation on decimal literal compiles and runs`` () =
+ FSharp """
+open Microsoft.FSharp.Quotations.DerivedPatterns
+
+[]
+let x = 7m
+
+let expr = <@ x @>
+
+match expr with
+| Decimal n -> printfn "%M" n
+| _ -> failwith (string expr)
+ """
+ |> asExe
+ |> withLangVersion80
+ |> compileAndRun
+ |> shouldSucceed
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs
index d5c6a5a0a63..9d276c13629 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/ComputationExpressionTests.fs
@@ -246,4 +246,402 @@ let run r2 r3 =
|> shouldFail
|> withDiagnostics [
(Error 3345, Line 22, Col 9, Line 22, Col 13, "use! may not be combined with and!")
+ ]
+
+ []
+ let ``This control construct may only be used if the computation expression builder defines a 'Bind' method`` () =
+ Fsx """
+module Result =
+ let zip x1 x2 =
+ match x1,x2 with
+ | Ok x1res, Ok x2res -> Ok (x1res, x2res)
+ | Error e, _ -> Error e
+ | _, Error e -> Error e
+
+type ResultBuilder() =
+ member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2
+ member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x
+ member _.Delay(f) = f()
+
+ member _.TryWith(r: Result<'T,'U>, f) =
+ match r with
+ | Ok x -> Ok x
+ | Error e -> f e
+
+let result = ResultBuilder()
+
+let run r2 r3 =
+ result {
+ let! a = r2
+ return! a
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 708, Line 23, Col 9, Line 23, Col 13, "This control construct may only be used if the computation expression builder defines a 'Bind' method")
+ ]
+
+ []
+ let ``This control construct may only be used if the computation expression builder defines a 'Using' method`` () =
+ Fsx """
+module Result =
+ let zip x1 x2 =
+ match x1,x2 with
+ | Ok x1res, Ok x2res -> Ok (x1res, x2res)
+ | Error e, _ -> Error e
+ | _, Error e -> Error e
+
+type ResultBuilder() =
+ member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2
+ member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x
+ member _.Delay(f) = f()
+
+ member _.TryWith(r: Result<'T,'U>, f) =
+ match r with
+ | Ok x -> Ok x
+ | Error e -> f e
+
+let result = ResultBuilder()
+
+let run r2 r3 =
+ result {
+ use! a = r2
+ return! a
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 708, Line 23, Col 9, Line 23, Col 13, "This control construct may only be used if the computation expression builder defines a 'Using' method")
+ ]
+
+ []
+ let ``do! expressions may not be used in queries`` () =
+ Fsx """
+query {
+ do! failwith ""
+ yield 1
+}
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3143, Line 3, Col 5, Line 3, Col 8, "'let!', 'use!' and 'do!' expressions may not be used in queries")
+ ]
+
+ []
+ let ``let! expressions may not be used in queries`` () =
+ Fsx """
+query {
+ let! x = failwith ""
+ yield 1
+}
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3143, Line 3, Col 5, Line 3, Col 9, "'let!', 'use!' and 'do!' expressions may not be used in queries")
+ ]
+
+ []
+ let ``let!, and! expressions may not be used in queries`` () =
+ Fsx """
+query {
+ let! x = failwith ""
+ and! y = failwith ""
+ yield 1
+}
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3143, Line 3, Col 5, Line 3, Col 9, "'let!', 'use!' and 'do!' expressions may not be used in queries")
+ ]
+
+ []
+ let ``use! expressions may not be used in queries`` () =
+ Fsx """
+query {
+ use! x = failwith ""
+ yield 1
+}
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3143, Line 3, Col 5, Line 3, Col 9, "'let!', 'use!' and 'do!' expressions may not be used in queries")
+ ]
+
+ []
+ let ``do! expressions may not be used in queries(SynExpr.Sequential)`` () =
+ Fsx """
+query {
+ for c in [1..10] do
+ do! failwith ""
+ yield 1
+}
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3143, Line 4, Col 5, Line 4, Col 8, "'let!', 'use!' and 'do!' expressions may not be used in queries")
+ ]
+
+ []
+ let ``let! expressions may not be used in queries(SynExpr.Sequential)`` () =
+ Fsx """
+query {
+ for c in [1..10] do
+ let! x = failwith ""
+ yield 1
+}
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3143, Line 4, Col 5, Line 4, Col 9, "'let!', 'use!' and 'do!' expressions may not be used in queries")
+ ]
+
+ []
+ let ``let!, and! expressions may not be used in queries(SynExpr.Sequential)`` () =
+ Fsx """
+query {
+ for c in [1..10] do
+ let! x = failwith ""
+ and! y = failwith ""
+ yield 1
+}
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3143, Line 4, Col 5, Line 4, Col 9, "'let!', 'use!' and 'do!' expressions may not be used in queries")
+ ]
+
+ []
+ let ``use! expressions may not be used in queries(SynExpr.Sequential)`` () =
+ Fsx """
+query {
+ for c in [1..10] do
+ use! x = failwith ""
+ yield 1
+}
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 3143, Line 4, Col 5, Line 4, Col 9, "'let!', 'use!' and 'do!' expressions may not be used in queries")
+ ]
+
+ []
+ let ``This control construct may only be used if the computation expression builder defines a 'Bind' method(match!)`` () =
+ Fsx """
+module Result =
+ let zip x1 x2 =
+ match x1,x2 with
+ | Ok x1res, Ok x2res -> Ok (x1res, x2res)
+ | Error e, _ -> Error e
+ | _, Error e -> Error e
+
+type ResultBuilder() =
+ member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2
+ member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x
+ member _.Delay(f) = f()
+
+ member _.TryWith(r: Result<'T,'U>, f) =
+ match r with
+ | Ok x -> Ok x
+ | Error e -> f e
+
+let result = ResultBuilder()
+
+let run r2 r3 =
+ result {
+ match! r2 with
+ | Ok x -> return x
+ | Error e -> return e
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 708, Line 23, Col 9, Line 23, Col 15, "This control construct may only be used if the computation expression builder defines a 'Bind' method")
+ ]
+
+ []
+ let ``This construct may only be used within computation expressions(match!)`` () =
+ Fsx """
+let run r2 r3 =
+ match! r2 with
+ | Ok x -> x
+ | Error e -> e
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 750, Line 3, Col 5, Line 3, Col 11, "This construct may only be used within computation expressions")
+ ]
+
+ []
+ let ``This control construct may only be used if the computation expression builder defines a 'Yield' method`` () =
+ Fsx """
+let f3 =
+ async {
+ if true then
+ yield "a"
+ else
+ yield "b"
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 708, Line 5, Col 13, Line 5, Col 18, "This control construct may only be used if the computation expression builder defines a 'Yield' method")
+ ]
+
+ []
+ let ``This control construct may only be used if the computation expression builder defines a 'YieldFrom' method`` () =
+ Fsx """
+let f3 =
+ async {
+ if true then
+ yield! "a"
+ else
+ yield "b"
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 708, Line 5, Col 13, Line 5, Col 19, "This control construct may only be used if the computation expression builder defines a 'YieldFrom' method")
+ ]
+
+
+ []
+ let ``This control construct may only be used if the computation expression builder defines a 'Return' method`` () =
+ Fsx """
+module Result =
+ let zip x1 x2 =
+ match x1,x2 with
+ | Ok x1res, Ok x2res -> Ok (x1res, x2res)
+ | Error e, _ -> Error e
+ | _, Error e -> Error e
+
+type ResultBuilder() =
+ member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2
+ member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x
+ member _.Delay(f) = f()
+
+ member _.TryWith(r: Result<'T,'U>, f) =
+ match r with
+ | Ok x -> Ok x
+ | Error e -> f e
+
+let result = ResultBuilder()
+
+let run r2 r3 =
+ result {
+ match r2 with
+ | Ok x -> return x
+ | Error e -> return e
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 708, Line 24, Col 19, Line 24, Col 25, "This control construct may only be used if the computation expression builder defines a 'Return' method")
+ ]
+
+
+ []
+ let ``This control construct may only be used if the computation expression builder defines a 'ReturnFrom' method`` () =
+ Fsx """
+module Result =
+ let zip x1 x2 =
+ match x1,x2 with
+ | Ok x1res, Ok x2res -> Ok (x1res, x2res)
+ | Error e, _ -> Error e
+ | _, Error e -> Error e
+
+type ResultBuilder() =
+ member _.MergeSources(t1: Result<'T,'U>, t2: Result<'T1,'U>) = Result.zip t1 t2
+ member _.BindReturn(x: Result<'T,'U>, f) = Result.map f x
+ member _.Delay(f) = f()
+
+ member _.TryWith(r: Result<'T,'U>, f) =
+ match r with
+ | Ok x -> Ok x
+ | Error e -> f e
+
+let result = ResultBuilder()
+
+let run r2 r3 =
+ result {
+ match r2 with
+ | Ok x -> return! x
+ | Error e -> return e
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 708, Line 24, Col 19, Line 24, Col 26, "This control construct may only be used if the computation expression builder defines a 'ReturnFrom' method")
+ ]
+
+ []
+ let ``Type constraint mismatch when using return!`` () =
+ Fsx """
+open System.Threading.Tasks
+
+let maybeTask = task { return false }
+
+let indexHandler (): Task =
+ task {
+ return! maybeTask
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 193, Line 8, Col 17, Line 8, Col 26, "Type constraint mismatch. The type \n 'TaskCode' \nis not compatible with type\n 'TaskCode' \n")
+ ]
+
+ []
+ let ``Type constraint mismatch when using return`` () =
+ Fsx """
+open System.Threading.Tasks
+
+let maybeTask = task { return false }
+
+let indexHandler (): Task =
+ task {
+ return maybeTask
+ }
+ """
+ |> ignoreWarnings
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 1, Line 8, Col 16, Line 8, Col 25, "This expression was expected to have type
+ 'string'
+but here has type
+ 'Task' ")
]
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs
index de6d1c888ca..1edfbfd7961 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/NullableReferenceTypesTests.fs
@@ -17,6 +17,49 @@ let typeCheckWithStrictNullness cu =
|> withNullnessOptions
|> typecheck
+
+
+[]
+let ``Can convert generic value to objnull arg`` () =
+ FSharp """module TestLib
+
+let writeObj(tw:System.IO.TextWriter, a:'a) =
+ tw.Write(a)
+
+writeObj(System.IO.TextWriter.Null,null)
+ """
+ |> asLibrary
+ |> typeCheckWithStrictNullness
+ |> shouldSucceed
+
+[]
+let ``Can pass nulll to objnull arg`` () =
+ FSharp """module TestLib
+let doStuff args =
+ let ty = typeof
+ let m = ty.GetMethod("ToString") |> Unchecked.nonNull
+ m.Invoke(null,args)
+ """
+ |> asLibrary
+ |> typeCheckWithStrictNullness
+ |> shouldSucceed
+
+[]
+let ``Can cast from objTy to interfaceTy`` () =
+ FSharp """module TestLib
+open System
+let safeHolder : IDisposable =
+ { new obj() with
+ override x.Finalize() = (x :?> IDisposable).Dispose()
+ interface IDisposable with
+ member x.Dispose() =
+ GC.SuppressFinalize x
+ }
+ """
+ |> asLibrary
+ |> typeCheckWithStrictNullness
+ |> shouldSucceed
+
[]
let ``Does not duplicate warnings`` () =
FSharp """
@@ -28,6 +71,66 @@ let getLength (x: string | null) = x.Length
|> shouldFail
|> withDiagnostics [Error 3261, Line 3, Col 36, Line 3, Col 44, "Nullness warning: The types 'string' and 'string | null' do not have compatible nullability."]
+[]
+let ``Does report warning on obj to static member`` () =
+ FSharp """
+type Test() =
+ member _.XX(o:obj) = ()
+ static member X(o: obj) = ()
+ static member XString(x:string) = ()
+let x: obj | null = null
+Test.X x // warning expected
+let y2 = Test.X(x) // warning also expected
+Test.X(null:(obj|null)) // warning also expected
+let t = Test()
+t.XX(x)
+Test.XString(null)
+Test.XString("x":(string|null))
+ """
+ |> asLibrary
+ |> typeCheckWithStrictNullness
+ |> shouldFail
+ |> withDiagnostics
+ [ Error 3261, Line 7, Col 8, Line 7, Col 9, "Nullness warning: The type 'obj | null' supports 'null' but a non-null type is expected."
+ Error 3261, Line 7, Col 1, Line 7, Col 9, "Nullness warning: The types 'obj' and 'obj | null' do not have compatible nullability."
+ Error 3261, Line 8, Col 17, Line 8, Col 18, "Nullness warning: The type 'obj | null' supports 'null' but a non-null type is expected."
+ Error 3261, Line 8, Col 10, Line 8, Col 19, "Nullness warning: The types 'obj' and 'obj | null' do not have compatible nullability."
+ Error 3261, Line 9, Col 8, Line 9, Col 23, "Nullness warning: The type 'obj | null' supports 'null' but a non-null type is expected."
+ Error 3261, Line 9, Col 1, Line 9, Col 24, "Nullness warning: The types 'obj' and 'obj | null' do not have compatible nullability."
+ Error 3261, Line 11, Col 6, Line 11, Col 7, "Nullness warning: The type 'obj | null' supports 'null' but a non-null type is expected."
+ Error 3261, Line 11, Col 1, Line 11, Col 8, "Nullness warning: The types 'obj' and 'obj | null' do not have compatible nullability."
+ Error 3261, Line 12, Col 14, Line 12, Col 18, "Nullness warning: The type 'string' does not support 'null'."
+ Error 3261, Line 13, Col 14, Line 13, Col 31, "Nullness warning: The types 'string' and 'string | null' do not have equivalent nullability."]
+
+[]
+let ``Typar infered to nonnull obj`` () =
+
+ FSharp """module Tests
+let asObj(x:obj) = x
+let asObjNull(x:objnull) = x
+
+let genericWithoutNull x = asObj x
+let genericWithNull x = asObjNull x
+
+let result0 = genericWithoutNull null
+let result1 = genericWithoutNull ("":(obj|null))
+let result2 = genericWithoutNull 15
+let result3 = genericWithoutNull "xxx"
+let result4 = genericWithoutNull ("xxx":(string|null))
+let result5 = genericWithNull null
+let result6 = genericWithNull 15
+let result7 = genericWithNull "xxx"
+let result8 = genericWithNull ("":(obj|null))
+
+ """
+ |> asLibrary
+ |> typeCheckWithStrictNullness
+ |> shouldFail
+ |> withDiagnostics
+ [ Error 43, Line 8, Col 34, Line 8, Col 38, "The constraints 'null' and 'not null' are inconsistent"
+ Error 3261, Line 9, Col 35, Line 9, Col 48, "Nullness warning: The type 'obj | null' supports 'null' but a non-null type is expected."
+ Error 3261, Line 12, Col 35, Line 12, Col 54, "Nullness warning: The type 'string | null' supports 'null' but a non-null type is expected."]
+
[]
let ``Cannot pass possibly null value to a strict function``() =
@@ -608,10 +711,16 @@ strictFunc("hi") |> ignore """
[]
let ``Supports null in generic code`` () =
FSharp """module MyLibrary
-let myGenericFunction p =
+let myGenericFunctionForInnerNotNull (p:_|null) =
match p with
| null -> ()
- | p -> printfn "%s" (p.ToString())
+ | nnp -> printfn "%s" (nnp.ToString())
+
+let myGenericFunctionSupportingNull (p) =
+ match p with
+ | null -> 0
+ | nnp -> hash nnp
+
[]
type X(p:int) =
@@ -619,20 +728,15 @@ type X(p:int) =
let myValOfX : X = null
-myGenericFunction "HiThere"
-myGenericFunction ("HiThere":string | null)
-myGenericFunction (System.DateTime.Now)
-myGenericFunction 123
-myGenericFunction myValOfX
+myGenericFunctionForInnerNotNull "HiThere"
+myGenericFunctionForInnerNotNull ("HiThere":string | null)
+myGenericFunctionSupportingNull myValOfX |> ignore
+myGenericFunctionSupportingNull ("HiThere":string | null) |> ignore
"""
|> asLibrary
|> typeCheckWithStrictNullness
- |> shouldFail
- |> withDiagnostics
- [Error 3261, Line 13, Col 19, Line 13, Col 28, "Nullness warning: The type 'string' does not support 'null'."
- Error 193, Line 15, Col 20, Line 15, Col 39, "The type 'System.DateTime' does not have 'null' as a proper value"
- Error 1, Line 16, Col 19, Line 16, Col 22, "The type 'int' does not have 'null' as a proper value"]
+ |> shouldSucceed
[]
let ``Null assignment in generic code`` () =
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/using-nullness-syntax-positive.fs b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/using-nullness-syntax-positive.fs
index 2757ab30aea..69b554bd48f 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/using-nullness-syntax-positive.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/using-nullness-syntax-positive.fs
@@ -120,9 +120,9 @@ System.Console.WriteLine("a")
System.Console.WriteLine("a", (null: obj[])) // Expected to give a Nullness warning
KonsoleWithNulls.WriteLine("Hello world")
-KonsoleWithNulls.WriteLine(null) // WRONG: gives an incorrect Nullness warning for String | null and String | null
+KonsoleWithNulls.WriteLine(null)
KonsoleWithNulls.WriteLine("Hello","world")
-KonsoleWithNulls.WriteLine("Hello","world","there") // // WRONG: gives an incorrect Nullness warning for String | null and String | null
+KonsoleWithNulls.WriteLine("Hello","world","there")
KonsoleNoNulls.WriteLine("Hello world")
try
@@ -169,7 +169,7 @@ with :? System.ArgumentNullException -> ()
// Param array cases
KonsoleNoNulls.WriteLine("Hello","world","there")
-KonsoleWithNulls.WriteLine("Hello","world",null) // Expected to give a Nullness warning
+KonsoleWithNulls.WriteLine("Hello","world",null) // Expected to give no Nullness warning
KonsoleNoNulls.WriteLine("Hello","world",null) // Expected to give a Nullness warning
System.Console.WriteLine("a", (null: obj[] | null))
System.Console.WriteLine("a", (null: (obj | null)[] | null))
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/using-nullness-syntax-positive.fs.checknulls_on.err.bsl b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/using-nullness-syntax-positive.fs.checknulls_on.err.bsl
index 5154ce43e79..709c3c309b3 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/Nullness/using-nullness-syntax-positive.fs.checknulls_on.err.bsl
+++ b/tests/FSharp.Compiler.ComponentTests/Language/Nullness/using-nullness-syntax-positive.fs.checknulls_on.err.bsl
@@ -31,5 +31,6 @@ using-nullness-syntax-positive.fs (154,40)-(154,44) typecheck error Nullness war
using-nullness-syntax-positive.fs (159,36)-(159,40) typecheck error Nullness warning: The type 'String' does not support 'null'.
using-nullness-syntax-positive.fs (162,41)-(162,45) typecheck error Nullness warning: The type 'String' does not support 'null'.
using-nullness-syntax-positive.fs (164,37)-(164,41) typecheck error Nullness warning: The type 'String' does not support 'null'.
+using-nullness-syntax-positive.fs (173,42)-(173,46) typecheck error The constraints 'null' and 'not null' are inconsistent
using-nullness-syntax-positive.fs (183,14)-(183,16) typecheck error Nullness warning: The type 'string' does not support 'null'.
using-nullness-syntax-positive.fs (189,17)-(189,26) typecheck error Nullness warning: The type 'String' does not support 'null'.
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs
index 982ae0c820b..8247eaf60e3 100644
--- a/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Language/SequenceExpressionTests.fs
@@ -442,4 +442,29 @@ let typedSeq =
|> withErrorCode 30
|> withDiagnosticMessageMatches "Value restriction: The value 'typedSeq' has an inferred generic type"
|> withDiagnosticMessageMatches "val typedSeq: '_a seq"
-
\ No newline at end of file
+
+[]
+let ``yield may only be used within list, array, and sequence expressions``() =
+ Fsx """
+let f1 = yield [ 3; 4 ]
+let f2 = yield! [ 3; 4 ]
+ """
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 747, Line 2, Col 10, Line 2, Col 15, "This construct may only be used within list, array and sequence expressions, e.g. expressions of the form 'seq { ... }', '[ ... ]' or '[| ... |]'. These use the syntax 'for ... in ... do ... yield...' to generate elements");
+ (Error 747, Line 3, Col 10, Line 3, Col 16, "This construct may only be used within list, array and sequence expressions, e.g. expressions of the form 'seq { ... }', '[ ... ]' or '[| ... |]'. These use the syntax 'for ... in ... do ... yield...' to generate elements")
+ ]
+
+[]
+let ``return may only be used within list, array, and sequence expressions``() =
+ Fsx """
+let f1 = return [ 3; 4 ]
+let f2 = return! [ 3; 4 ]
+ """
+ |> typecheck
+ |> shouldFail
+ |> withDiagnostics [
+ (Error 748, Line 2, Col 10, Line 2, Col 16, "This construct may only be used within computation expressions. To return a value from an ordinary function simply write the expression without 'return'.");
+ (Error 748, Line 3, Col 10, Line 3, Col 17, "This construct may only be used within computation expressions. To return a value from an ordinary function simply write the expression without 'return'.")
+ ]
\ No newline at end of file
diff --git a/tests/FSharp.Compiler.ComponentTests/Miscellaneous/FsharpSuiteMigrated.fs b/tests/FSharp.Compiler.ComponentTests/Miscellaneous/FsharpSuiteMigrated.fs
index 2490e301e05..3f17e0cfa11 100644
--- a/tests/FSharp.Compiler.ComponentTests/Miscellaneous/FsharpSuiteMigrated.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Miscellaneous/FsharpSuiteMigrated.fs
@@ -31,16 +31,15 @@ module ScriptRunner =
let cu = cu |> withDefines defaultDefines
match cu with
| FS fsSource ->
- File.Delete("test.ok")
let engine = createEngine (fsSource.Options |> Array.ofList,version)
let res = evalScriptFromDiskInSharedSession engine cu
match res with
| CompilationResult.Failure _ -> res
- | CompilationResult.Success s ->
- if File.Exists("test.ok") then
+ | CompilationResult.Success s ->
+ if engine.GetOutput().Contains "TEST PASSED OK" then
res
else
- failwith $"Results looked correct, but 'test.ok' file was not created. Result: %A{s}"
+ failwith $"Results looked correct, but 'TEST PASSED OK' was not printed. Result: %A{s}"
| _ -> failwith $"Compilation unit other than fsharp is not supported, cannot process %A{cu}"
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/HashConstraintTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/HashConstraintTests.fs
index beb33a8bac5..ac624ec19a7 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/HashConstraintTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/HashConstraintTests.fs
@@ -21,8 +21,7 @@ let noa<'n when 'n :> Node> (n: 'n option) =
| Some n -> [| n :> Node |]
"""
|> printSignatures
- |> should
- equal
+ |> assertEqualIgnoreLineEnding
"""
module Foo
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/MemberTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/MemberTests.fs
index 2452a900881..3475535249a 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/MemberTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/MemberTests.fs
@@ -15,8 +15,7 @@ type Foo() =
member f.X with internal get (key1, key2) = true and public set (key1, key2) value = ()
"""
|> printSignatures
- |> should
- equal
+ |> assertEqualIgnoreLineEnding
"""
module Foo
@@ -38,8 +37,7 @@ type Foo() =
member f.Y with public get () = 'y' and internal set y = ignore y
"""
|> printSignatures
- |> should
- equal
+ |> assertEqualIgnoreLineEnding
"""
module Foo
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/ModuleOrNamespaceTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/ModuleOrNamespaceTests.fs
index d4d9d408df9..413e4a7fdf9 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/ModuleOrNamespaceTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/ModuleOrNamespaceTests.fs
@@ -20,8 +20,7 @@ type Map<'t,'v> =
"""
|> printSignatures
|> prependNewline
- |> should
- equal
+ |> assertEqualIgnoreLineEnding
"""
namespace Foo.Types
@@ -43,8 +42,7 @@ type Foo =
"""
|> printSignatures
|> prependNewline
- |> should
- equal
+ |> assertEqualIgnoreLineEnding
"""
namespace Hey.There
@@ -101,8 +99,7 @@ module internal CodePrinter =
id"""
|> printSignatures
|> prependNewline
- |> should
- equal
+ |> assertEqualIgnoreLineEnding
"""
namespace Fantomas.Core
@@ -156,7 +153,7 @@ open System.Runtime.CompilerServices
do ()
"""
|> printSignatures
- |> should equal "namespace System"
+ |> assertEqualIgnoreLineEnding "namespace System"
[]
let ``Empty module`` () =
@@ -167,7 +164,7 @@ module Foobar
do ()
"""
|> printSignatures
- |> should equal "module Foobar"
+ |> assertEqualIgnoreLineEnding "module Foobar"
[]
let ``Two empty namespaces`` () =
@@ -183,7 +180,7 @@ do ()
"""
|> printSignatures
|> prependNewline
- |> should equal """
+ |> assertEqualIgnoreLineEnding """
namespace Foo
namespace Bar"""
@@ -196,7 +193,7 @@ namespace rec Foobar
do ()
"""
|> printSignatures
- |> should equal "namespace Foobar"
+ |> assertEqualIgnoreLineEnding "namespace Foobar"
[]
let ``Attribute on nested module`` () =
@@ -211,7 +208,7 @@ module Area =
"""
|> printSignatures
|> prependNewline
- |> should equal """
+ |> assertEqualIgnoreLineEnding """
namespace MyApp.Types
[ (4))>]
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/NestedTypeTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/NestedTypeTests.fs
index 669faca6d5f..4dfce060679 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/NestedTypeTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/NestedTypeTests.fs
@@ -35,7 +35,7 @@ let f (g: Upper.Lower) = g.Meh()
"""
|> withReferences [ CSLib ]
|> printSignatures
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
module Sample
@@ -74,7 +74,7 @@ let f (g: Root.Foo withReferences [ CSLib ]
|> printSignatures
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
module Sample
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/RecordTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/RecordTests.fs
index 27c5159a3f3..cb5ec18da97 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/RecordTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/RecordTests.fs
@@ -19,8 +19,7 @@ type PullActions =
}
"""
|> printSignaturesWith 80
- |> should
- equal
+ |> assertEqualIgnoreLineEnding
"""
module SignatureFileGeneration.MyModule
@@ -63,7 +62,7 @@ type SomeTypeName =
"""
|> printSignatures
|> prependNewline
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
namespace MyApp.Types
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access.fsx b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access.fsx
index a8c3798a685..6790e4dfbee 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access.fsx
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/access.fsx
@@ -278,7 +278,7 @@ let aa =
match failures.Value with
| [] ->
stdout.WriteLine "Test Passed"
- System.IO.File.WriteAllText("test.ok","ok")
+ printf "TEST PASSED OK" ;
exit 0
| _ ->
stdout.WriteLine "Test Failed"
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/array.fsx b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/array.fsx
index 8c55d727f92..dd61a8f7474 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/array.fsx
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/array.fsx
@@ -1142,7 +1142,7 @@ let aa =
match failures with
| [] ->
stdout.WriteLine "Test Passed"
- System.IO.File.WriteAllText("test.ok","ok")
+ printf "TEST PASSED OK" ;
exit 0
| _ ->
stdout.WriteLine "Test Failed"
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/libtest.fsx b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/libtest.fsx
index 23c2125ab51..515e1428697 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/libtest.fsx
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/TestCasesForGenerationRoundTrip/libtest.fsx
@@ -5651,7 +5651,7 @@ let aa =
match !failures with
| [] ->
stdout.WriteLine "Test Passed"
- System.IO.File.WriteAllText("test.ok","ok")
+ printf "TEST PASSED OK" ;
exit 0
| _ ->
stdout.WriteLine "Test Failed"
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/TestHelpers.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/TestHelpers.fs
index 8f3d1019ae0..b778cb3d783 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/TestHelpers.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/TestHelpers.fs
@@ -1,20 +1,15 @@
module Signatures.TestHelpers
open System
-open FsUnit
+open Xunit
open FSharp.Test.Compiler
let prependNewline v = String.Concat("\n", v)
-let equal x =
- let x =
- match box x with
- | :? String as s -> s.Replace("\r\n", "\n") |> box
- | x -> x
-
- equal x
+let assertEqualIgnoreLineEnding (x: string) (y: string) =
+ Assert.Equal(x, y, ignoreLineEndingDifferences = true)
let assertSingleSignatureBinding implementation signature =
FSharp $"module A\n\n{implementation}"
|> printSignatures
- |> should equal $"\nmodule A\n\n{signature}"
+ |> assertEqualIgnoreLineEnding $"\nmodule A\n\n{signature}"
diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/TypeTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/TypeTests.fs
index 1494c465af9..d066d74dd9a 100644
--- a/tests/FSharp.Compiler.ComponentTests/Signatures/TypeTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Signatures/TypeTests.fs
@@ -44,7 +44,7 @@ and FormatSelectionRange =
"""
|> printSignatures
|> prependNewline
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
namespace Foo.Types
@@ -87,7 +87,7 @@ type List<'E> with
member this.X = this.Head
"""
|> printSignatures
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
module Extensions
type List<'E> with
@@ -104,7 +104,7 @@ type Map<'K, 'V when 'K: comparison> with
member m.X (t: 'T) (k: 'K) = Some k, ({| n = [|k|] |}, 0)
"""
|> printSignatures
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
module Extensions
type Map<'K,'V when 'K: comparison> with
@@ -126,7 +126,7 @@ type ConcurrentDictionary<'key, 'value> with
| _ -> None
"""
|> printSignatures
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
module Extensions
type System.Collections.Concurrent.ConcurrentDictionary<'key,'value> with
@@ -161,7 +161,7 @@ type DataItem< ^input> with
DataItem.Create< ^input>(stringValue, friendlyStringValue, item)
"""
|> printSignatures
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
module Extensions
@@ -237,7 +237,7 @@ type Foo =
member x.Bar with get () = 5 and set v = ignore v
"""
|> printSignatures
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
module Lib
@@ -254,7 +254,7 @@ type Foo =
member x.Bar with get (a:int) = 5 and set (a:int) v = ignore v
"""
|> printSignatures
- |> should equal
+ |> assertEqualIgnoreLineEnding
"""
module Lib
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs
index 4525d7286f2..9cfbbb9df80 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/CompilationFromCmdlineArgsTests.fs
@@ -5,19 +5,19 @@ module CompilationFromCmdlineArgsTests =
open System
open System.IO
open FSharp.Compiler.CodeAnalysis
- open NUnit.Framework
+ open Xunit
open CompilationTests
// Point to a generated args.txt file.
// Use scrape.fsx to generate an args.txt from a binary log file.
// The path needs to be absolute.
- let localProjects: string list =
+ let localProjects =
[
@"C:\Projects\fantomas\src\Fantomas.Core\Fantomas.Core.args.txt"
@"C:\Projects\FsAutoComplete\src\FsAutoComplete\FsAutoComplete.args.txt"
@"C:\Projects\fsharp\src\Compiler\FSharp.Compiler.Service.args.txt"
@"C:\Projects\fsharp\tests\FSharp.Compiler.ComponentTests\FSharp.Compiler.ComponentTests.args.txt"
- ]
+ ] |> Seq.map (fun p -> [| box p |])
let checker = FSharpChecker.Create()
@@ -43,16 +43,16 @@ module CompilationFromCmdlineArgsTests =
for diag in diagnostics do
printfn "%A" diag
- Assert.That(exitCode, Is.Zero)
+ Assert.Equal(exitCode, 0)
finally
Environment.CurrentDirectory <- oldWorkDir
- []
- []
+ []
+ []
let ``Test sequential type-checking`` (projectArgumentsFilePath: string) =
testCompilerFromArgs Method.Sequential projectArgumentsFilePath
- []
- []
+ []
+ []
let ``Test graph-based type-checking`` (projectArgumentsFilePath: string) =
testCompilerFromArgs Method.Graph projectArgumentsFilePath
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/DependencyResolutionTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/DependencyResolutionTests.fs
index 36a246d6ced..81adc540766 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/DependencyResolutionTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/DependencyResolutionTests.fs
@@ -1,11 +1,14 @@
module TypeChecks.DependencyResolutionTests
open TypeChecks.TestUtils
-open NUnit.Framework
+open Xunit
open FSharp.Compiler.GraphChecking
open Scenarios
-[]
+let scenarios = scenarios |> Seq.map (fun p -> [| box p |])
+
+[]
+[]
let ``Supported scenario`` (scenario: Scenario) =
let files =
scenario.Files
@@ -18,4 +21,4 @@ let ``Supported scenario`` (scenario: Scenario) =
for file in scenario.Files do
let expectedDeps = file.ExpectedDependencies
let actualDeps = set graph.[file.Index]
- Assert.AreEqual(expectedDeps, actualDeps, $"Dependencies don't match for {System.IO.Path.GetFileName file.FileName}")
+ Assert.True((expectedDeps = actualDeps), $"Dependencies don't match for {System.IO.Path.GetFileName file.FileName}")
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/FileContentMappingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/FileContentMappingTests.fs
index 12f171de5fa..070133a3d8d 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/FileContentMappingTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/FileContentMappingTests.fs
@@ -1,6 +1,6 @@
module TypeChecks.FileContentMappingTests
-open NUnit.Framework
+open Xunit
open FSharp.Compiler.GraphChecking
open TestUtils
@@ -35,7 +35,7 @@ let private (|NestedModule|_|) value e =
| FileContentEntry.NestedModule(name, nestedContent) -> if name = value then Some(nestedContent) else None
| _ -> None
-[]
+[]
let ``Top level module only exposes namespace`` () =
let content =
getContent
@@ -45,10 +45,10 @@ module X.Y.Z
"""
match content with
- | [ TopLevelNamespace "X.Y" [] ] -> Assert.Pass()
+ | [ TopLevelNamespace "X.Y" [] ] -> ()
| content -> Assert.Fail($"Unexpected content: {content}")
-[]
+[]
let ``Top level namespace`` () =
let content =
getContent
@@ -58,10 +58,10 @@ namespace X.Y
"""
match content with
- | [ TopLevelNamespace "X.Y" [] ] -> Assert.Pass()
+ | [ TopLevelNamespace "X.Y" [] ] -> ()
| content -> Assert.Fail($"Unexpected content: {content}")
-[]
+[]
let ``Open statement in top level module`` () =
let content =
getContent
@@ -73,10 +73,10 @@ open A.B.C
"""
match content with
- | [ TopLevelNamespace "X.Y" [ OpenStatement "A.B.C" ] ] -> Assert.Pass()
+ | [ TopLevelNamespace "X.Y" [ OpenStatement "A.B.C" ] ] -> ()
| content -> Assert.Fail($"Unexpected content: {content}")
-[]
+[]
let ``PrefixedIdentifier in type annotation`` () =
let content =
getContent
@@ -88,10 +88,10 @@ let fn (a: A.B.CType) = ()
"""
match content with
- | [ TopLevelNamespace "X.Y" [ PrefixedIdentifier "A.B" ] ] -> Assert.Pass()
+ | [ TopLevelNamespace "X.Y" [ PrefixedIdentifier "A.B" ] ] -> ()
| content -> Assert.Fail($"Unexpected content: {content}")
-[]
+[]
let ``Nested module`` () =
let content =
getContent
@@ -104,10 +104,10 @@ module Z =
"""
match content with
- | [ TopLevelNamespace "X" [ NestedModule "Z" [] ] ] -> Assert.Pass()
+ | [ TopLevelNamespace "X" [ NestedModule "Z" [] ] ] -> ()
| content -> Assert.Fail($"Unexpected content: {content}")
-[]
+[]
let ``Single ident module abbreviation`` () =
let content =
getContent
@@ -119,13 +119,13 @@ module B = C
"""
match content with
- | [ TopLevelNamespace "" [ PrefixedIdentifier "C" ] ] -> Assert.Pass()
+ | [ TopLevelNamespace "" [ PrefixedIdentifier "C" ] ] -> ()
| content -> Assert.Fail($"Unexpected content: {content}")
module InvalidSyntax =
- []
+ []
let ``Nested module`` () =
let content =
getContent
@@ -137,11 +137,11 @@ module InvalidSyntax =
"""
match content with
- | [ TopLevelNamespace "" [] ] -> Assert.Pass()
+ | [ TopLevelNamespace "" [] ] -> ()
| content -> Assert.Fail($"Unexpected content: {content}")
- []
+ []
let ``Module above namespace`` () =
let content =
getContent
@@ -153,5 +153,5 @@ module InvalidSyntax =
"""
match content with
- | [ TopLevelNamespace "" [] ] -> Assert.Pass()
+ | [ TopLevelNamespace "" [] ] -> ()
| content -> Assert.Fail($"Unexpected content: {content}")
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphProcessingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphProcessingTests.fs
index f8a4c8d2d23..675294acf0c 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphProcessingTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/GraphProcessingTests.fs
@@ -2,9 +2,9 @@
open System.Threading
open FSharp.Compiler.GraphChecking.GraphProcessing
-open NUnit.Framework
+open Xunit
-[]
+[]
let ``When processing a node throws an exception, an exception is raised with the original exception included`` () =
let graph = [1, [|2|]; 2, [||]] |> readOnlyDict
let work (_processor : int -> ProcessedNode) (_node : NodeInfo) : string = failwith "Work exception"
@@ -18,6 +18,6 @@ let ``When processing a node throws an exception, an exception is raised with th
CancellationToken.None
|> ignore
)
- Assert.That(exn.Message, Is.EqualTo("Encountered exception when processing item '2'"))
- Assert.That(exn.InnerException, Is.Not.Null)
- Assert.That(exn.InnerException.Message, Is.EqualTo("Work exception"))
+ Assert.Equal(exn.Message, "Encountered exception when processing item '2'")
+ Assert.NotNull(exn.InnerException)
+ Assert.Equal(exn.InnerException.Message, "Work exception")
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/QueryTrieTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/QueryTrieTests.fs
index 613d77a29ee..524535efa32 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/QueryTrieTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/QueryTrieTests.fs
@@ -2,7 +2,7 @@
open System.Collections.Generic
open System.Collections.Immutable
-open NUnit.Framework
+open Xunit
open FSharp.Compiler.GraphChecking
open FSharp.Compiler.GraphChecking.DependencyResolution
@@ -757,24 +757,24 @@ let private fantomasCoreTrie: TrieNode =
|]
}
-[]
+[]
let ``Query nonexistent node in trie`` () =
let result =
queryTrie fantomasCoreTrie [ "System"; "System"; "Runtime"; "CompilerServices" ]
match result with
- | QueryTrieNodeResult.NodeDoesNotExist -> Assert.Pass()
+ | QueryTrieNodeResult.NodeDoesNotExist -> ()
| result -> Assert.Fail $"Unexpected result: %A{result}"
-[]
+[]
let ``Query node that does not expose data in trie`` () =
let result = queryTrie fantomasCoreTrie [ "Fantomas"; "Core" ]
match result with
- | QueryTrieNodeResult.NodeDoesNotExposeData -> Assert.Pass()
+ | QueryTrieNodeResult.NodeDoesNotExposeData -> ()
| result -> Assert.Fail $"Unexpected result: %A{result}"
-[]
+[]
let ``Query module node that exposes one file`` () =
let result =
queryTrie fantomasCoreTrie [ "Fantomas"; "Core"; "ISourceTextExtensions" ]
@@ -782,10 +782,10 @@ let ``Query module node that exposes one file`` () =
match result with
| QueryTrieNodeResult.NodeExposesData file ->
let file = Seq.exactlyOne file
- Assert.AreEqual(indexOf "ISourceTextExtensions.fs", file)
+ Assert.Equal(indexOf "ISourceTextExtensions.fs", file)
| result -> Assert.Fail $"Unexpected result: %A{result}"
-[]
+[]
let ``ProcessOpenStatement full path match`` () =
let state =
FileContentQueryState.Create Set.empty
@@ -794,4 +794,4 @@ let ``ProcessOpenStatement full path match`` () =
processOpenPath fantomasCoreTrie [ "Fantomas"; "Core"; "AstExtensions" ] state
let dep = Seq.exactlyOne result.FoundDependencies
- Assert.AreEqual(indexOf "AstExtensions.fsi", dep)
+ Assert.Equal(indexOf "AstExtensions.fsi", dep)
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TrieMappingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TrieMappingTests.fs
index 6ad29818a2a..2a3d7b608ea 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TrieMappingTests.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TrieMappingTests.fs
@@ -1,6 +1,6 @@
module TypeChecks.TrieMappingTests
-open NUnit.Framework
+open Xunit
open FSharp.Compiler.GraphChecking
open TestUtils
@@ -8,7 +8,7 @@ let private noDependencies = Set.empty
let private getLastTrie files = TrieMapping.mkTrie files |> Array.last |> snd
-[]
+[]
let ``Basic trie`` () =
let sampleFiles =
[|
@@ -49,22 +49,22 @@ type C = { CX: int; CY: int }
| current -> Assert.Fail($"mkTrie should always return a TrieNodeInfo.Root, got {current}")
let xNode = trie.Children.["X"]
- Assert.AreEqual(1, xNode.Children.Count)
+ Assert.Equal(1, xNode.Children.Count)
Assert.True(Seq.isEmpty xNode.Files)
let yNode = xNode.Children["Y"]
- Assert.AreEqual(2, yNode.Children.Count)
- Assert.AreEqual(set [| 2 |], yNode.Files)
+ Assert.Equal(2, yNode.Children.Count)
+ Assert.Equal>(set [| 2 |], yNode.Files)
let aNode = yNode.Children["A"]
- Assert.AreEqual(0, aNode.Children.Count)
- Assert.AreEqual(set [| 0 |], aNode.Files)
+ Assert.Equal(0, aNode.Children.Count)
+ Assert.Equal>(set [| 0 |], aNode.Files)
let bNode = yNode.Children["B"]
- Assert.AreEqual(0, bNode.Children.Count)
- Assert.AreEqual(set [| 1 |], bNode.Files)
+ Assert.Equal(0, bNode.Children.Count)
+ Assert.Equal>(set [| 1 |], bNode.Files)
-[]
+[]
let ``Toplevel AutoOpen module with prefixed namespace`` () =
let trie =
getLastTrie
@@ -87,11 +87,11 @@ let a = 0
// Assert that both A and B expose file index 0
let aNode = trie.Children.["A"]
- Assert.AreEqual(set [| 0 |], aNode.Files)
+ Assert.Equal>(set [| 0 |], aNode.Files)
let bNode = aNode.Children.["B"]
- Assert.AreEqual(set [| 0 |], bNode.Files)
+ Assert.Equal>(set [| 0 |], bNode.Files)
-[]
+[]
let ``Toplevel AutoOpen module with multi prefixed namespace`` () =
let trie =
getLastTrie
@@ -114,13 +114,13 @@ let a = 0
// Assert that B and C expose file index 0, namespace A should not.
let aNode = trie.Children.["A"]
- Assert.AreEqual(noDependencies, aNode.Files)
+ Assert.Equal>(noDependencies, aNode.Files)
let bNode = aNode.Children.["B"]
- Assert.AreEqual(set [| 0 |], bNode.Files)
+ Assert.Equal>(set [| 0 |], bNode.Files)
let cNode = bNode.Children.["C"]
- Assert.AreEqual(set [| 0 |], cNode.Files)
+ Assert.Equal>(set [| 0 |], cNode.Files)
-[]
+[]
let ``Global namespace should link files to the root node`` () =
let trie =
getLastTrie
@@ -159,9 +159,9 @@ type B = { Y : int }
}
|]
- Assert.AreEqual(set [| 0; 1 |], trie.Files)
+ Assert.Equal>(set [| 0; 1 |], trie.Files)
-[]
+[]
let ``Module with a single ident and AutoOpen attribute should link files to root`` () =
let trie =
getLastTrie
@@ -202,10 +202,10 @@ type B = { Y : int }
}
|]
- Assert.AreEqual(set [| 0; 1 |], trie.Files)
- Assert.AreEqual(0, trie.Children.Count)
+ Assert.Equal>(set [| 0; 1 |], trie.Files)
+ Assert.Equal(0, trie.Children.Count)
-[]
+[]
let ``Module with AutoOpen attribute and two ident should expose file at two levels`` () =
let trie =
getLastTrie
@@ -226,13 +226,13 @@ type A = { A : int }
}
|]
- Assert.AreEqual(noDependencies, trie.Files)
+ Assert.Equal>(noDependencies, trie.Files)
let xNode = trie.Children.["X"]
- Assert.AreEqual(set [| 0 |], xNode.Files)
+ Assert.Equal>(set [| 0 |], xNode.Files)
let yNode = xNode.Children.["Y"]
- Assert.AreEqual(set [| 0 |], yNode.Files)
+ Assert.Equal>(set [| 0 |], yNode.Files)
-[]
+[]
let ``Module with AutoOpen attribute and three ident should expose file at last two levels`` () =
let trie =
getLastTrie
@@ -253,15 +253,15 @@ type A = { A : int }
}
|]
- Assert.AreEqual(noDependencies, trie.Files)
+ Assert.Equal>(noDependencies, trie.Files)
let xNode = trie.Children.["X"]
- Assert.AreEqual(noDependencies, xNode.Files)
+ Assert.Equal>(noDependencies, xNode.Files)
let yNode = xNode.Children.["Y"]
- Assert.AreEqual(set [| 0 |], yNode.Files)
+ Assert.Equal>(set [| 0 |], yNode.Files)
let zNode = yNode.Children.["Z"]
- Assert.AreEqual(set [| 0 |], zNode.Files)
+ Assert.Equal>(set [| 0 |], zNode.Files)
-[]
+[]
let ``Nested AutoOpen module in namespace will expose the file to the namespace node`` () =
let trie =
getLastTrie
@@ -284,15 +284,15 @@ module Z =
}
|]
- Assert.AreEqual(noDependencies, trie.Files)
+ Assert.Equal>(noDependencies, trie.Files)
let xNode = trie.Children.["X"]
- Assert.AreEqual(noDependencies, xNode.Files)
+ Assert.Equal>(noDependencies, xNode.Files)
let yNode = xNode.Children.["Y"]
- Assert.AreEqual(set [| 0 |], yNode.Files)
+ Assert.Equal>(set [| 0 |], yNode.Files)
let zNode = yNode.Children.["Z"]
- Assert.AreEqual(set [| 0 |], zNode.Files)
+ Assert.Equal>(set [| 0 |], zNode.Files)
-[]
+[]
let ``Two modules with the same name, only the first file exposes the index`` () =
let trie =
getLastTrie
@@ -325,11 +325,11 @@ let _ = ()
}
|]
- Assert.AreEqual(1, trie.Children.Count)
+ Assert.Equal(1, trie.Children.Count)
let aNode = trie.Children.["A"]
- Assert.AreEqual(set [| 0 |], aNode.Files)
+ Assert.Equal>(set [| 0 |], aNode.Files)
-[]
+[]
let ``Two nested modules with the same name, in named namespace`` () =
let trie =
getLastTrie
@@ -352,11 +352,11 @@ module ``module`` =
}
|]
- Assert.AreEqual(1, trie.Children.Count)
+ Assert.Equal(1, trie.Children.Count)
let node = trie.Children.["N"]
- Assert.AreEqual(1, node.Children.Count)
+ Assert.Equal(1, node.Children.Count)
-[]
+[]
let ``Two nested modules with the same name, in namespace global`` () =
let trie =
getLastTrie
@@ -380,9 +380,9 @@ module ``module`` =
|]
// namespace global leads to a Root entry, no further processing will be done.
- Assert.AreEqual(set [| 0 |], trie.Files)
+ Assert.Equal>(set [| 0 |], trie.Files)
-[]
+[]
let ``Two nested modules with the same name, in anonymous module`` () =
let trie =
getLastTrie
@@ -403,10 +403,10 @@ module ``module`` =
}
|]
- Assert.AreEqual(1, trie.Children.Count)
+ Assert.Equal(1, trie.Children.Count)
Assert.True(trie.Children.ContainsKey("module"))
-[]
+[]
let ``Two nested modules with the same name, in nested module`` () =
let trie =
getLastTrie
@@ -432,10 +432,10 @@ module B =
|]
let bNode = trie.Children["A"].Children["B"]
- Assert.AreEqual(1, bNode.Children.Count)
+ Assert.Equal(1, bNode.Children.Count)
Assert.True(bNode.Children.ContainsKey("module"))
-[]
+[]
let ``Two nested modules with the same name, in nested module in signature file`` () =
let trie =
getLastTrie
@@ -459,10 +459,10 @@ module B =
|]
let bNode = trie.Children["A"].Children["B"]
- Assert.AreEqual(1, bNode.Children.Count)
+ Assert.Equal(1, bNode.Children.Count)
Assert.True(bNode.Children.ContainsKey("module"))
-[]
+[]
let ``Two namespaces with the same name in the same implementation file`` () =
let trie =
getLastTrie
@@ -486,9 +486,9 @@ module C = begin end
|]
let aNode = trie.Children["A"]
- Assert.AreEqual(2, aNode.Children.Count)
+ Assert.Equal(2, aNode.Children.Count)
-[]
+[]
let ``Two namespaces with the same name in the same signature file`` () =
let trie =
getLastTrie
@@ -512,9 +512,9 @@ module C = begin end
|]
let aNode = trie.Children["A"]
- Assert.AreEqual(2, aNode.Children.Count)
+ Assert.Equal(2, aNode.Children.Count)
-[]
+[]
let ``Tries are built up incrementally`` () =
let trie =
TrieMapping.mkTrie
@@ -542,12 +542,12 @@ let ``Tries are built up incrementally`` () =
|]
for idx, t in trie do
- Assert.AreEqual(idx + 1, t.Children.Count)
+ Assert.Equal(idx + 1, t.Children.Count)
module InvalidSyntax =
- []
+ []
let ``Unnamed module`` () =
let trie =
getLastTrie
diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs
index c4680870efc..dc89f4f9a4c 100644
--- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs
+++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TypedTreeGraph.fs
@@ -7,7 +7,7 @@ open System.IO
open FSharp.Compiler.CodeAnalysis
open FSharp.Compiler.Text
open FSharp.Compiler.Symbols
-open NUnit.Framework
+open Xunit
open FSharp.Compiler.GraphChecking
open TypeChecks.TestUtils
@@ -100,8 +100,8 @@ let graphFromTypedTree (checker: FSharpChecker) (projectOptions: FSharpProjectOp
return files, graph
}
-[]
-[]
+[]
+[]
let ``Create Graph from typed tree`` (projectArgumentsFilePath: string) =
let previousDir = Environment.CurrentDirectory
@@ -181,7 +181,7 @@ let ``Create Graph from typed tree`` (projectArgumentsFilePath: string) =
let isSuperSet = Set.isSuperset depsFromHeuristic depsFromTypedTree
let delta = Set.difference depsFromTypedTree depsFromHeuristic
- Assert.IsTrue(
+ Assert.True(
isSuperSet,
$"""{relativePath fileName} did not contain a superset of the typed tree dependencies:
{source} is missing dependencies: %A{depNames delta}."""
diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs
index 8a1bb95b2d2..cc027d098af 100644
--- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs
+++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/DependencyManagerInteractiveTests.fs
@@ -760,10 +760,9 @@ x |> Seq.iter(fun r ->
if found = expected.Length then sawExpectedOutput.Set() |> ignore
let text = "#help"
- use output = new RedirectConsoleOutput()
use script = new FSharpScript(quiet = false, langVersion = LangVersion.V47)
let mutable found = 0
- output.OutputProduced.Add (fun line -> verifyOutput line)
+ script.OutputProduced.Add (fun line -> verifyOutput line)
let opt = script.Eval(text) |> getValue
Assert.True(sawExpectedOutput.WaitOne(TimeSpan.FromSeconds(5.0)), sprintf "Expected to see error sentinel value written\nexpected:%A\nactual:%A" expected lines)
@@ -811,10 +810,9 @@ x |> Seq.iter(fun r ->
if found = expected.Length then sawExpectedOutput.Set() |> ignore
let text = "#help"
- use output = new RedirectConsoleOutput()
use script = new FSharpScript(quiet = false, langVersion = LangVersion.Preview)
let mutable found = 0
- output.OutputProduced.Add (fun line -> verifyOutput line)
+ script.OutputProduced.Add (fun line -> verifyOutput line)
let opt = script.Eval(text) |> getValue
Assert.True(sawExpectedOutput.WaitOne(TimeSpan.FromSeconds(5.0)), sprintf "Expected to see error sentinel value written\nexpected:%A\nactual:%A" expected lines)
diff --git a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs
index a8739d93390..aff47308ad2 100644
--- a/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs
+++ b/tests/FSharp.Compiler.Private.Scripting.UnitTests/FSharpScriptTests.fs
@@ -83,9 +83,7 @@ x
[]
member _.``Capture console input``() =
- use input = new RedirectConsoleInput()
- use script = new FSharpScript()
- input.ProvideInput "stdin:1234\r\n"
+ use script = new FSharpScript(input = "stdin:1234\r\n")
let opt = script.Eval("System.Console.ReadLine()") |> getValue
let value = opt.Value
Assert.Equal(typeof, value.ReflectionType)
@@ -93,12 +91,11 @@ x
[]
member _.``Capture console output/error``() =
- use output = new RedirectConsoleOutput()
use script = new FSharpScript()
use sawOutputSentinel = new ManualResetEvent(false)
use sawErrorSentinel = new ManualResetEvent(false)
- output.OutputProduced.Add (fun line -> if line = "stdout:1234" then sawOutputSentinel.Set() |> ignore)
- output.ErrorProduced.Add (fun line -> if line = "stderr:5678" then sawErrorSentinel.Set() |> ignore)
+ script.OutputProduced.Add (fun line -> if line = "stdout:1234" then sawOutputSentinel.Set() |> ignore)
+ script.ErrorProduced.Add (fun line -> if line = "stderr:5678" then sawErrorSentinel.Set() |> ignore)
script.Eval("printfn \"stdout:1234\"; eprintfn \"stderr:5678\"") |> ignoreValue
Assert.True(sawOutputSentinel.WaitOne(TimeSpan.FromSeconds(5.0)), "Expected to see output sentinel value written")
Assert.True(sawErrorSentinel.WaitOne(TimeSpan.FromSeconds(5.0)), "Expected to see error sentinel value written")
@@ -305,11 +302,10 @@ printfn ""%A"" result
[]
member _.``Eval script with invalid PackageName should fail immediately``() =
- use output = new RedirectConsoleOutput()
use script = new FSharpScript(additionalArgs=[| |])
let mutable found = 0
let outp = System.Collections.Generic.List()
- output.OutputProduced.Add(
+ script.OutputProduced.Add(
fun line ->
if line.Contains("error NU1101:") && line.Contains("FSharp.Really.Not.A.Package") then
found <- found + 1
@@ -321,10 +317,9 @@ printfn ""%A"" result
[]
member _.``Eval script with invalid PackageName should fail immediately and resolve one time only``() =
- use output = new RedirectConsoleOutput()
use script = new FSharpScript(additionalArgs=[| |])
let mutable foundResolve = 0
- output.OutputProduced.Add (fun line -> if line.Contains("error NU1101:") then foundResolve <- foundResolve + 1)
+ script.OutputProduced.Add (fun line -> if line.Contains("error NU1101:") then foundResolve <- foundResolve + 1)
let result, errors =
script.Eval("""
#r "nuget:FSharp.Really.Not.A.Package"
@@ -352,6 +347,22 @@ tInput.Length
let value = opt.Value
Assert.Equal(4L, downcast value.ReflectionValue)
+ [] // usessdkrefs is not a valid option for desktop compiler
+ member _.``ML - use assembly with ref dependencies and without refing SMemory``() =
+ let code = """
+#r "nuget:Microsoft.ML.OnnxTransformer,1.4.0"
+
+open System
+open System.Numerics.Tensors
+let inputValues = [| 12.0; 10.0; 17.0; 5.0 |]
+let tInput = new DenseTensor(inputValues.AsMemory(), new ReadOnlySpan([|4|]))
+tInput.Length
+"""
+ use script = new FSharpScript(additionalArgs=[| "/usesdkrefs-" |])
+ let opt = script.Eval(code) |> getValue
+ let value = opt.Value
+ Assert.Equal(4L, downcast value.ReflectionValue)
+
[]
member _.``System.Device.Gpio - Ensure we reference the runtime version of the assembly``() =
let code = """
diff --git a/tests/FSharp.Compiler.Service.Tests/AssemblyReaderShim.fs b/tests/FSharp.Compiler.Service.Tests/AssemblyReaderShim.fs
index a38210a6fe4..ebe2c3dd61d 100644
--- a/tests/FSharp.Compiler.Service.Tests/AssemblyReaderShim.fs
+++ b/tests/FSharp.Compiler.Service.Tests/AssemblyReaderShim.fs
@@ -23,4 +23,4 @@ let x = 123
let fileName, options = mkTestFileAndOptions source [| |]
checker.ParseAndCheckFileInProject(fileName, 0, SourceText.ofString source, options) |> Async.RunImmediate |> ignore
- gotRequest |> should be True
+ gotRequest |> Assert.True
diff --git a/tests/FSharp.Compiler.Service.Tests/CSharpProjectAnalysis.fs b/tests/FSharp.Compiler.Service.Tests/CSharpProjectAnalysis.fs
index a2f4c122591..aa4cc9af679 100644
--- a/tests/FSharp.Compiler.Service.Tests/CSharpProjectAnalysis.fs
+++ b/tests/FSharp.Compiler.Service.Tests/CSharpProjectAnalysis.fs
@@ -144,8 +144,8 @@ let _ = CSharpClass(0)
match (ctor :?> FSharpMemberOrFunctionOrValue).DeclaringEntity with
| Some e ->
let members = e.MembersFunctionsAndValues
- Seq.exists (fun (mfv : FSharpMemberOrFunctionOrValue) -> mfv.IsConstructor) members |> should be True
- Seq.exists (fun (mfv : FSharpMemberOrFunctionOrValue) -> mfv.IsEffectivelySameAs ctor) members |> should be True
+ Seq.exists (fun (mfv : FSharpMemberOrFunctionOrValue) -> mfv.IsConstructor) members |> Assert.True
+ Seq.exists (fun (mfv : FSharpMemberOrFunctionOrValue) -> mfv.IsEffectivelySameAs ctor) members |> Assert.True
| None -> failwith "Expected Some for DeclaringEntity"
let getEntitiesUses source =
@@ -172,7 +172,7 @@ let (s2: FSharp.Compiler.Service.Tests.String) = null
|> List.filter (fun entity -> entity.LogicalName = "String")
match stringSymbols with
- | e1 :: e2 :: [] -> e1.IsEffectivelySameAs(e2) |> should be False
+ | e1 :: e2 :: [] -> e1.IsEffectivelySameAs(e2) |> Assert.False
| _ -> sprintf "Expecting two symbols, got %A" stringSymbols |> failwith
[]
@@ -189,5 +189,5 @@ open FSharp.Compiler.Service.Tests.Linq
|> List.filter (fun entity -> entity.LogicalName = "Linq")
match stringSymbols with
- | e1 :: e2 :: [] -> e1.IsEffectivelySameAs(e2) |> should be False
+ | e1 :: e2 :: [] -> e1.IsEffectivelySameAs(e2) |> Assert.False
| _ -> sprintf "Expecting two symbols, got %A" stringSymbols |> failwith
diff --git a/tests/FSharp.Compiler.Service.Tests/ExprTests.fs b/tests/FSharp.Compiler.Service.Tests/ExprTests.fs
index 3a7cf3eb68d..c8870dd700e 100644
--- a/tests/FSharp.Compiler.Service.Tests/ExprTests.fs
+++ b/tests/FSharp.Compiler.Service.Tests/ExprTests.fs
@@ -788,12 +788,12 @@ let ``Test Unoptimized Declarations Project1`` useTransparentCompiler =
printDeclarations None (List.ofSeq file1.Declarations)
|> Seq.toList
|> Utils.filterHack
- |> shouldPairwiseEqual (Utils.filterHack expected)
+ |> shouldEqual (Utils.filterHack expected)
printDeclarations None (List.ofSeq file2.Declarations)
|> Seq.toList
|> Utils.filterHack
- |> shouldPairwiseEqual (Utils.filterHack expected2)
+ |> shouldEqual (Utils.filterHack expected2)
()
@@ -930,12 +930,12 @@ let ``Test Optimized Declarations Project1`` useTransparentCompiler =
printDeclarations None (List.ofSeq file1.Declarations)
|> Seq.toList
|> Utils.filterHack
- |> shouldPairwiseEqual (Utils.filterHack expected)
+ |> shouldEqual (Utils.filterHack expected)
printDeclarations None (List.ofSeq file2.Declarations)
|> Seq.toList
|> Utils.filterHack
- |> shouldPairwiseEqual (Utils.filterHack expected2)
+ |> shouldEqual (Utils.filterHack expected2)
()
@@ -1045,11 +1045,11 @@ let testOperators dnName fsName excludedTests expectedUnoptimized expectedOptimi
// fail test on first line that fails, show difference in output window
resultUnoptFiltered
- |> shouldPairwiseEqual expectedUnoptFiltered
+ |> shouldEqual expectedUnoptFiltered
// fail test on first line that fails, show difference in output window
resultOptFiltered
- |> shouldPairwiseEqual expectedOptFiltered
+ |> shouldEqual expectedOptFiltered
end
[]
@@ -3134,7 +3134,7 @@ let BigSequenceExpression(outFileOpt,docFileOpt,baseAddressOpt) =
let createOptions() = createProjectOptions dirName [fileSource1] []
#if !NETFRAMEWORK && DEBUG
-[]
+[]
#else
[]
[]
@@ -3263,7 +3263,7 @@ let ``Test ProjectForWitnesses1`` useTransparentCompiler =
|> Seq.toList
printfn "actual:\n\n%A" actual
actual
- |> shouldPairwiseEqual expected
+ |> shouldEqual expected
[]
@@ -3380,7 +3380,7 @@ let ``Test ProjectForWitnesses2`` useTransparentCompiler =
|> Seq.toList
printfn "actual:\n\n%A" actual
actual
- |> shouldPairwiseEqual expected
+ |> shouldEqual expected
//---------------------------------------------------------------------------------------------------------
// This project is for witness arguments, testing for https://github.com/dotnet/fsharp/issues/10364
@@ -3437,7 +3437,7 @@ let ``Test ProjectForWitnesses3`` useTransparentCompiler =
|> Seq.toList
printfn "actual:\n\n%A" actual
actual
- |> shouldPairwiseEqual expected
+ |> shouldEqual expected
[]
[