[RFCs FS-1051, FS-1052, FS-1053] support for span, readonly refs, byref-like structs (#4888)

* initial support for span, readonly refs, byref-like structs

* fix proto build

* make proto work with previous FSharp.Core

* make proto work with previous FSharp.Core

* update baselines

* integrate code cleanup

* integrate code cleanup

* integrate code cleanup

* integrate code cleanup

* fix build

* fix build

* implicit deref of byref returns

* add tests for Memory, ReadOnlySpan and ReadOnlyMemory

* fix tests

* simplify diff

* simplify diff

* remove duplicate error messages

* fix build

* test updates

* fix build

* fix build

* update baselines

* fix uses of NativePtr.toByRef

* switch to inference using byref pointer capabilities

* fix proto build

* update baselines, byref extension methods

* fix test errors

* emit in,out,modreq attributes correctly

* update tests

* fix build

* fix build

* fix tests

* fix tests

* get it right silly boy

* fix test

* minor cleanup

* add more tests

* clarify overloading behaviour + test case

* fix build break

* fix build of tests

* update tests

* add more tests

* byref fixes

* updates for subsumption calls, error message, assign-to-return-byref

* test updates, implicit deref on byref return for normal functions

* update baseline

* improve debug formatting, better error message on implicit deref, improve error messages

* add more tests for recursive functions

* update baselines

* fix baselines

* updates for new test cases

* updates for new test cases

* test updates and byref-to-byreflike

* deal with 'M() <- expr'

* restrict addresses of immutable top-level things

* fix IsByRefLike on struct

* update tests

* fix test

* fix test

* improve check for no-return-of-struct-field-addresses

* fix test case
This commit is contained in:
Don Syme 2018-06-04 16:35:46 +01:00 коммит произвёл Will Smith
Родитель e21c296355
Коммит 5bfd9fcd38
90 изменённых файлов: 6843 добавлений и 2734 удалений

Просмотреть файл

@ -224,7 +224,6 @@ To do this, build the non-buildfromsource version of FSharp.Compiler.Private (sr
.\build net40
copy /y src\fsharp\FSharp.Compiler.Private\obj\release\net40\FSComp.* src\buildfromsource\FSharp.Compiler.Private\
#### Configuring proxy server
If you are behind a proxy server, NuGet client tool must be configured to use it:

Просмотреть файл

@ -38,6 +38,11 @@
<package id="Microsoft.FSharp.TupleSample" version="1.0.0-alpha-161121"/>
<package id="Microsoft.VSSDK.BuildTools" version="15.1.192" />
<!-- Testing Span -->
<package id="System.Memory" version="4.5.0-rc1" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.0-rc1" />
<package id="NETStandard.Library.NETFramework" version="2.0.0-preview2-25405-01" />
<!-- Annoyingly the build of FSharp.Compiler.Server.Shared references a Visual Studio-specific attribute -->
<!-- That DLL is logically part of the F# Compiler and F# Interactive but is shipped as part of the Visual F# IDE Tools -->
<package id="Microsoft.VisualStudio.Shell.Immutable.10.0" version="10.0.30319" targetFramework="net46" />

Просмотреть файл

@ -8,6 +8,7 @@ module Microsoft.FSharp.Compiler.AbstractIL.IL
open System
open System.Diagnostics
open System.IO
open System.Collections
open System.Collections.Generic
@ -568,7 +569,7 @@ type ILBoxity =
| AsValue
// IL type references have a pre-computed hash code to enable quick lookup tables during binary generation.
[<CustomEquality; CustomComparison>]
[<CustomEquality; CustomComparison; StructuredFormatDisplay("{DebugText}")>]
type ILTypeRef =
{ trefScope: ILScopeRef
trefEnclosing: string list
@ -637,11 +638,15 @@ type ILTypeRef =
member tref.QualifiedName =
tref.AddQualifiedNameExtension(tref.BasicQualifiedName)
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
/// For debugging
override x.ToString() = x.FullName
and
[<StructuralEquality; StructuralComparison>]
and [<StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugText}")>]
ILTypeSpec =
{ tspecTypeRef: ILTypeRef
/// The type instantiation if the type is generic.
@ -671,9 +676,13 @@ and
member x.FullName=x.TypeRef.FullName
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = x.TypeRef.ToString() + if isNil x.GenericArgs then "" else "<...>"
and [<RequireQualifiedAccess; StructuralEquality; StructuralComparison>]
and [<RequireQualifiedAccess; StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugText}")>]
ILType =
| Void
| Array of ILArrayShape * ILType
@ -740,6 +749,10 @@ and [<RequireQualifiedAccess; StructuralEquality; StructuralComparison>]
match x with
| ILType.TypeVar _ -> true | _ -> false
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = x.QualifiedName
and [<StructuralEquality; StructuralComparison>]
@ -756,6 +769,7 @@ let mkILCallSig (cc, args, ret) = { ArgTypes=args; CallingConv=cc; ReturnType=re
let mkILBoxedType (tspec:ILTypeSpec) = tspec.TypeRef.AsBoxedType tspec
[<StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugText}")>]
type ILMethodRef =
{ mrefParent: ILTypeRef
mrefCallconv: ILCallingConv
@ -783,18 +797,26 @@ type ILMethodRef =
static member Create(a, b, c, d, e, f) =
{ mrefParent= a;mrefCallconv=b;mrefName=c;mrefGenericArity=d; mrefArgs=e;mrefReturn=f }
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = x.DeclaringTypeRef.ToString() + "::" + x.Name + "(...)"
[<StructuralEquality; StructuralComparison>]
[<StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugText}")>]
type ILFieldRef =
{ DeclaringTypeRef: ILTypeRef
Name: string
Type: ILType }
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = x.DeclaringTypeRef.ToString() + "::" + x.Name
[<StructuralEquality; StructuralComparison>]
[<StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugText}")>]
type ILMethodSpec =
{ mspecMethodRef: ILMethodRef
@ -820,8 +842,13 @@ type ILMethodSpec =
member x.FormalReturnType = x.MethodRef.ReturnType
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = x.MethodRef.ToString() + "(...)"
[<StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugText}")>]
type ILFieldSpec =
{ FieldRef: ILFieldRef
DeclaringType: ILType }
@ -832,6 +859,10 @@ type ILFieldSpec =
member x.DeclaringTypeRef = x.FieldRef.DeclaringTypeRef
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = x.FieldRef.ToString()
// --------------------------------------------------------------------
@ -865,6 +896,7 @@ type ILSourceDocument =
member x.File=x.sourceFile
[<StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugText}")>]
type ILSourceMarker =
{ sourceDocument: ILSourceDocument
sourceLine: int
@ -889,6 +921,10 @@ type ILSourceMarker =
member x.EndColumn=x.sourceEndColumn
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = sprintf "(%d, %d)-(%d, %d)" x.Line x.Column x.EndLine x.EndColumn
type ILAttribElem =
@ -912,11 +948,16 @@ type ILAttribElem =
type ILAttributeNamedArg = (string * ILType * bool * ILAttribElem)
[<StructuralEquality; StructuralComparison; StructuredFormatDisplay("{DebugText}")>]
type ILAttribute =
{ Method: ILMethodSpec
Data: byte[]
Elements: ILAttribElem list }
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = x.Method.ToString() + "(...)"
[<NoEquality; NoComparison; Struct>]
@ -1424,6 +1465,8 @@ type ILReturn =
member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex
member x.WithCustomAttrs(customAttrs) = { x with CustomAttrsStored = storeILCustomAttrs customAttrs }
type ILOverridesSpec =
| OverridesSpec of ILMethodRef * ILType
@ -1475,6 +1518,7 @@ type ILGenericVariance =
| CoVariant
| ContraVariant
[<NoEquality; NoComparison; StructuredFormatDisplay("{DebugText}")>]
type ILGenericParameterDef =
{ Name: string
Constraints: ILTypes
@ -1487,6 +1531,10 @@ type ILGenericParameterDef =
member x.CustomAttrs = x.CustomAttrsStored.GetCustomAttrs x.MetadataIndex
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = x.Name
type ILGenericParameterDefs = ILGenericParameterDef list
@ -1665,7 +1713,7 @@ type ILMethodDefs(f : (unit -> ILMethodDef[])) =
member x.FindByNameAndArity (nm, arity) = x.FindByName nm |> List.filter (fun x -> List.length x.Parameters = arity)
[<NoComparison; NoEquality>]
[<NoComparison; NoEquality; StructuredFormatDisplay("{DebugText}")>]
type ILEventDef(eventType: ILType option, name: string, attributes: EventAttributes, addMethod: ILMethodRef, removeMethod: ILMethodRef, fireMethod: ILMethodRef option, otherMethods: ILMethodRef list, customAttrsStored: ILAttributesStored, metadataIndex: int32) =
new (eventType, name, attributes, addMethod, removeMethod, fireMethod, otherMethods, customAttrs) =
@ -1695,6 +1743,10 @@ type ILEventDef(eventType: ILType option, name: string, attributes: EventAttribu
member x.IsSpecialName = (x.Attributes &&& EventAttributes.SpecialName) <> enum<_>(0)
member x.IsRTSpecialName = (x.Attributes &&& EventAttributes.RTSpecialName) <> enum<_>(0)
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = "event " + x.Name
[<NoEquality; NoComparison>]
@ -1705,7 +1757,7 @@ type ILEventDefs =
member x.LookupByName s = let (ILEvents t) = x in t.[s]
[<NoComparison; NoEquality>]
[<NoComparison; NoEquality; StructuredFormatDisplay("{DebugText}")>]
type ILPropertyDef(name: string, attributes: PropertyAttributes, setMethod: ILMethodRef option, getMethod: ILMethodRef option, callingConv: ILThisConvention, propertyType: ILType, init: ILFieldInit option, args: ILTypes, customAttrsStored: ILAttributesStored, metadataIndex: int32) =
new (name, attributes, setMethod, getMethod, callingConv, propertyType, init, args, customAttrs) =
@ -1737,6 +1789,11 @@ type ILPropertyDef(name: string, attributes: PropertyAttributes, setMethod: ILMe
member x.IsSpecialName = (x.Attributes &&& PropertyAttributes.SpecialName) <> enum<_>(0)
member x.IsRTSpecialName = (x.Attributes &&& PropertyAttributes.RTSpecialName) <> enum<_>(0)
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = "property " + x.Name
// Index table by name.
@ -2469,7 +2526,7 @@ let tname_IntPtr = "System.IntPtr"
[<Literal>]
let tname_UIntPtr = "System.UIntPtr"
[<NoEquality; NoComparison>]
[<NoEquality; NoComparison; StructuredFormatDisplay("{DebugText}")>]
// This data structure needs an entirely delayed implementation
type ILGlobals(primaryScopeRef) =
@ -2514,6 +2571,11 @@ type ILGlobals(primaryScopeRef) =
member x.typ_Double = m_typ_Double
member x.typ_Bool = m_typ_Bool
member x.typ_Char = m_typ_Char
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
override x.ToString() = "<ILGlobals>"
let mkILGlobals primaryScopeRef = ILGlobals primaryScopeRef

Просмотреть файл

@ -796,6 +796,8 @@ type ILReturn =
member CustomAttrs: ILAttributes
member WithCustomAttrs: customAttrs: ILAttributes -> ILReturn
[<RequireQualifiedAccess>]
type ILSecurityAction =
| Request

Просмотреть файл

@ -135,6 +135,9 @@ module Array =
loop p l 0
let existsTrue (arr: bool[]) =
let rec loop n = (n < arr.Length) && (arr.[n] || loop (n+1))
loop 0
let findFirstIndexWhereTrue (arr: _[]) p =
let rec look lo hi =
@ -263,6 +266,10 @@ module List =
let rec loop i xs = match xs with [] -> false | h::t -> f i h || loop (i+1) t
loop 0 xs
let existsTrue (xs: bool list) =
let rec loop i xs = match xs with [] -> false | h::t -> h || loop (i+1) t
loop 0 xs
let lengthsEqAndForall2 p l1 l2 =
List.length l1 = List.length l2 &&
List.forall2 p l1 l2

Просмотреть файл

@ -7,27 +7,22 @@
module internal Microsoft.FSharp.Compiler.AbstractIL.ILRuntimeWriter
open Internal.Utilities
open System
open System.Reflection
open System.Reflection.Emit
open System.Runtime.InteropServices
open System.Collections.Generic
open Microsoft.FSharp.Compiler.AbstractIL
open Microsoft.FSharp.Compiler.AbstractIL.Internal
open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
open Microsoft.FSharp.Compiler.AbstractIL.Diagnostics
open Microsoft.FSharp.Compiler.AbstractIL.Extensions
open Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX
open Microsoft.FSharp.Compiler.AbstractIL.Extensions.ILX.Types
open Microsoft.FSharp.Compiler.AbstractIL.IL
open Microsoft.FSharp.Compiler.ErrorLogger
open Microsoft.FSharp.Compiler.Range
open Microsoft.FSharp.Core.Printf
open System
open System.IO
open System.Reflection
open System.Reflection.Emit
open System.Runtime.InteropServices
open System.Collections.Generic
#if FX_RESHAPED_REFLECTION
open Microsoft.FSharp.Core.ReflectionAdapters
#endif
@ -121,13 +116,9 @@ type System.Reflection.Emit.MethodBuilder with
if logRefEmitCalls then printfn "methodBuilder%d.SetImplementationFlags(enum %d)" (abs <| hash methB) (LanguagePrimitives.EnumToValue attrs)
methB.SetImplementationFlags(attrs)
member methB.SetReturnTypeAndLog(rt:System.Type) =
if logRefEmitCalls then printfn "methodBuilder%d.SetReturnType(typeof<%s>)" (abs <| hash methB) rt.FullName
methB.SetReturnType(rt)
member methB.SetParametersAndLog(ps) =
if logRefEmitCalls then printfn "methodBuilder%d.SetParameters(%A)" (abs <| hash methB) ps
methB.SetParameters(ps)
member methB.SetSignatureAndLog(returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers,parameterTypeOptionalCustomModifiers) =
if logRefEmitCalls then printfn "methodBuilder%d.SetSignature(...)" (abs <| hash methB)
methB.SetSignature(returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers,parameterTypeOptionalCustomModifiers)
member methB.DefineParameterAndLog(n, attr, nm) =
if logRefEmitCalls then printfn "methodBuilder%d.DefineParameter(%d, enum %d, %A)" (abs <| hash methB) n (LanguagePrimitives.EnumToValue attr) nm
@ -558,11 +549,11 @@ and convTypeAux cenv emEnv preferCreated typ =
baseT.MakeByRefType()
| ILType.TypeVar tv -> envGetTyvar emEnv tv
// Consider completing the following cases:
| ILType.Modified (false, _, modifiedTy) ->
| ILType.Modified (_, _, modifiedTy) ->
// Note, "modreq" are not being emitted. This is
convTypeAux cenv emEnv preferCreated modifiedTy
| ILType.Modified (true, _, _) -> failwith "convType: modreq"
| ILType.FunctionPointer _callsig -> failwith "convType: fptr"
| ILType.FunctionPointer _callsig -> failwith "convType: fptr"
// [Bug 4063].
// The convType functions convert AbsIL types into concrete Type values.
@ -598,6 +589,25 @@ let convTypesToArray cenv emEnv (typs:ILTypes) = convTypes cenv emEnv typs |> Li
let convCreatedType cenv emEnv typ = convTypeAux cenv emEnv true typ
let convCreatedTypeRef cenv emEnv typ = convTypeRef cenv emEnv true typ
let rec convParamModifiersOfType cenv emEnv (pty: ILType) =
[| match pty with
| ILType.Modified (modreq, ty, modifiedTy) ->
yield (modreq, convTypeRef cenv emEnv false ty)
yield! convParamModifiersOfType cenv emEnv modifiedTy
| _ -> () |]
let splitModifiers mods =
let reqd = mods |> Array.choose (function (true, ty) -> Some ty | _ -> None)
let optional = mods |> Array.choose (function (false, ty) -> Some ty | _ -> None)
reqd, optional
let convParamModifiers cenv emEnv (p: ILParameter) =
let mods = convParamModifiersOfType cenv emEnv p.Type
splitModifiers mods
let convReturnModifiers cenv emEnv (p: ILReturn) =
let mods = convParamModifiersOfType cenv emEnv p.Type
splitModifiers mods
//----------------------------------------------------------------------------
// convFieldInit
@ -1537,11 +1547,22 @@ let rec buildMethodPass2 cenv tref (typB:TypeBuilder) emEnv (mdef : ILMethodDef)
let genArgs = getGenericArgumentsOfMethod methB
let emEnv = envPushTyvars emEnv (Array.append (getGenericArgumentsOfType (typB.AsType())) genArgs)
buildGenParamsPass1b cenv emEnv genArgs mdef.GenericParams;
// Set parameter and return types (may depend on generic args)
methB.SetParametersAndLog(convTypesToArray cenv emEnv mdef.ParameterTypes);
methB.SetReturnTypeAndLog(convType cenv emEnv mdef.Return.Type);
let parameterTypes = convTypesToArray cenv emEnv mdef.ParameterTypes
let parameterTypeRequiredCustomModifiers,parameterTypeOptionalCustomModifiers =
mdef.Parameters
|> List.toArray
|> Array.map (convParamModifiers cenv emEnv)
|> Array.unzip
let returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers = mdef.Return |> convReturnModifiers cenv emEnv
let returnType = convType cenv emEnv mdef.Return.Type
methB.SetSignatureAndLog(returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers,parameterTypeOptionalCustomModifiers);
let emEnv = envPopTyvars emEnv
methB.SetImplementationFlagsAndLog(implflags);
methB.SetImplementationFlagsAndLog(implflags)
envBindMethodRef emEnv mref methB

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -181,7 +181,7 @@
<value>All branches of an 'if' expression must have the same type. This expression was expected to have type '{0}', but here has type '{1}'.</value>
</data>
<data name="followingPatternMatchClauseHasWrongType" xml:space="preserve">
<value>All branches of a pattern match expression must have the same type. This expression was expected to have type '{0}', but here has type '{1}'.</value>
<value>All branches of a pattern match expression must return values of the same type. The first branch returned a value of type '{0}', but this branch returned a value of type '{1}'.</value>
</data>
<data name="patternMatchGuardIsNotBool" xml:space="preserve">
<value>A pattern match guard must be of type 'bool', but this 'when' expression is of type '{0}'.</value>
@ -4029,8 +4029,8 @@
<data name="tcCouldNotFindOffsetToStringData" xml:space="preserve">
<value>Could not find method System.Runtime.CompilerServices.OffsetToStringData in references when building 'fixed' expression.</value>
</data>
<data name="chkNoByrefReturnOfLocal" xml:space="preserve">
<value>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</value>
<data name="chkNoByrefAddressOfLocal" xml:space="preserve">
<value>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</value>
</data>
<data name="tcNamedActivePattern" xml:space="preserve">
<value>{0} is an active pattern and cannot be treated as a discriminated union case with named fields.</value>
@ -4315,4 +4315,34 @@
<data name="ilreadFileChanged" xml:space="preserve">
<value>The file '{0}' changed on disk unexpectedly, please reload.</value>
</data>
<data name="writeToReadOnlyByref" xml:space="preserve">
<value>The byref pointer is readonly, so this write is not permitted.</value>
</data>
<data name="readOnlyAttributeOnStructWithMutableField" xml:space="preserve">
<value>A ReadOnly attribute has been applied to a struct type with a mutable field.</value>
</data>
<data name="tcByrefReturnImplicitlyDereferenced" xml:space="preserve">
<value>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</value>
</data>
<data name="tcByRefLikeNotStruct" xml:space="preserve">
<value>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</value>
</data>
<data name="chkNoByrefReturnOfLocal" xml:space="preserve">
<value>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</value>
</data>
<data name="chkNoReturnOfLimitedSpan" xml:space="preserve">
<value>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</value>
</data>
<data name="chkNoWriteToLimitedSpan" xml:space="preserve">
<value>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</value>
</data>
<data name="tastValueMustBeLocal" xml:space="preserve">
<value>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</value>
</data>
<data name="tcIsReadOnlyNotStruct" xml:space="preserve">
<value>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</value>
</data>
<data name="chkStructsMayNotReturnAddressesOfContents" xml:space="preserve">
<value>Struct members cannot return 'this' or fields by reference</value>
</data>
</root>

Просмотреть файл

@ -248,21 +248,21 @@ let MethInfoHasAttribute g m attribSpec minfo =
/// Check IL attributes for 'ObsoleteAttribute', returning errors and warnings as data
let private CheckILAttributes (g: TcGlobals) cattrs m =
let private CheckILAttributes (g: TcGlobals) isByrefLikeTyconRef cattrs m =
let (AttribInfo(tref,_)) = g.attrib_SystemObsolete
match TryDecodeILAttribute g tref cattrs with
| Some ([ILAttribElem.String (Some msg) ], _) ->
| Some ([ILAttribElem.String (Some msg) ], _) when not isByrefLikeTyconRef ->
WarnD(ObsoleteWarning(msg, m))
| Some ([ILAttribElem.String (Some msg); ILAttribElem.Bool isError ], _) ->
| Some ([ILAttribElem.String (Some msg); ILAttribElem.Bool isError ], _) when not isByrefLikeTyconRef ->
if isError then
ErrorD (ObsoleteError(msg, m))
else
WarnD (ObsoleteWarning(msg, m))
| Some ([ILAttribElem.String None ], _) ->
| Some ([ILAttribElem.String None ], _) when not isByrefLikeTyconRef ->
WarnD(ObsoleteWarning("", m))
| Some _ ->
| Some _ when not isByrefLikeTyconRef ->
WarnD(ObsoleteWarning("", m))
| None ->
| _ ->
CompleteD
/// Check F# attributes for 'ObsoleteAttribute', 'CompilerMessageAttribute' and 'ExperimentalAttribute',
@ -374,7 +374,7 @@ let CheckProvidedAttributesForUnseen (provAttribs: Tainted<IProvidedCustomAttrib
/// Check the attributes associated with a property, returning warnings and errors as data.
let CheckPropInfoAttributes pinfo m =
match pinfo with
| ILProp(ILPropInfo(_, pdef)) -> CheckILAttributes pinfo.TcGlobals pdef.CustomAttrs m
| ILProp(ILPropInfo(_, pdef)) -> CheckILAttributes pinfo.TcGlobals false pdef.CustomAttrs m
| FSProp(g, _, Some vref, _)
| FSProp(g, _, _, Some vref) -> CheckFSharpAttributes g vref.Attribs m
| FSProp _ -> failwith "CheckPropInfoAttributes: unreachable"
@ -389,7 +389,7 @@ let CheckPropInfoAttributes pinfo m =
let CheckILFieldAttributes g (finfo:ILFieldInfo) m =
match finfo with
| ILFieldInfo(_, pd) ->
CheckILAttributes g pd.CustomAttrs m |> CommitOperationResult
CheckILAttributes g false pd.CustomAttrs m |> CommitOperationResult
#if !NO_EXTENSIONTYPING
| ProvidedField (amap, fi, m) ->
CheckProvidedAttributes amap.g m (fi.PApply((fun st -> (st :> IProvidedCustomAttributeProvider)), m)) |> CommitOperationResult
@ -399,7 +399,7 @@ let CheckILFieldAttributes g (finfo:ILFieldInfo) m =
let CheckMethInfoAttributes g m tyargsOpt minfo =
let search =
BindMethInfoAttributes m minfo
(fun ilAttribs -> Some(CheckILAttributes g ilAttribs m))
(fun ilAttribs -> Some(CheckILAttributes g false ilAttribs m))
(fun fsAttribs ->
let res =
CheckFSharpAttributes g fsAttribs m ++ (fun () ->
@ -481,7 +481,7 @@ let PropInfoIsUnseen m pinfo =
/// Check the attributes on an entity, returning errors and warnings as data.
let CheckEntityAttributes g (x:TyconRef) m =
if x.IsILTycon then
CheckILAttributes g x.ILTyconRawMetadata.CustomAttrs m
CheckILAttributes g (isByrefLikeTyconRef g m x) x.ILTyconRawMetadata.CustomAttrs m
else
CheckFSharpAttributes g x.Attribs m

Просмотреть файл

@ -44,14 +44,19 @@ let mkEqualsSlotSig (g: TcGlobals) =
let mkThisTy g ty = if isStructTy g ty then mkByrefTy g ty else ty
let mkCompareObjTy g ty = (mkThisTy g ty) --> (g.obj_ty --> g.int_ty)
let mkCompareTy g ty = (mkThisTy g ty) --> (ty --> g.int_ty)
let mkCompareWithComparerTy g ty = (mkThisTy g ty) --> ((mkRefTupledTy g [g.obj_ty ; g.IComparer_ty]) --> g.int_ty)
let mkEqualsObjTy g ty = (mkThisTy g ty) --> (g.obj_ty --> g.bool_ty)
let mkEqualsTy g ty = (mkThisTy g ty) --> (ty --> g.bool_ty)
let mkEqualsWithComparerTy g ty = (mkThisTy g ty) --> ((mkRefTupledTy g [g.obj_ty ; g.IEqualityComparer_ty]) --> g.bool_ty)
let mkHashTy g ty = (mkThisTy g ty) --> (g.unit_ty --> g.int_ty)
let mkHashWithComparerTy g ty = (mkThisTy g ty) --> (g.IEqualityComparer_ty --> g.int_ty)
//-------------------------------------------------------------------------
@ -59,7 +64,9 @@ let mkHashWithComparerTy g ty = (mkThisTy g ty) --> (g.IEqualityComparer_ty -->
//-------------------------------------------------------------------------
let mkRelBinOp (g: TcGlobals) op m e1 e2 = mkAsmExpr ([ op ],[], [e1; e2],[g.bool_ty],m)
let mkClt g m e1 e2 = mkRelBinOp g IL.AI_clt m e1 e2
let mkCgt g m e1 e2 = mkRelBinOp g IL.AI_cgt m e1 e2
//-------------------------------------------------------------------------
@ -84,7 +91,9 @@ let mkILCallGetEqualityComparer (g: TcGlobals) m =
let mkThisVar g m ty = mkCompGenLocal m "this" (mkThisTy g ty)
let mkShl g m acce n = mkAsmExpr([ IL.AI_shl ],[],[acce; mkInt g m n],[g.int_ty],m)
let mkShr g m acce n = mkAsmExpr([ IL.AI_shr ],[],[acce; mkInt g m n],[g.int_ty],m)
let mkAdd (g: TcGlobals) m e1 e2 = mkAsmExpr([ IL.AI_add ],[],[e1;e2],[g.int_ty],m)
let mkAddToHashAcc g m e accv acce =
@ -101,6 +110,7 @@ let mkCombineHashGenerators g m exprs accv acce =
//-------------------------------------------------------------------------
let mkThatAddrLocal g m ty = mkCompGenLocal m "obj" (mkThisTy g ty)
let mkThatAddrLocalIfNeeded g m tcve ty =
if isStructTy g ty then
let thataddrv, thataddre = mkCompGenLocal m "obj" (mkThisTy g ty)
@ -115,13 +125,13 @@ let mkThisVarThatVar g m ty =
let mkThatVarBind g m ty thataddrv expr =
if isStructTy g ty then
let thatv2,_ = mkMutableCompGenLocal m "obj" ty
thatv2,mkCompGenLet m thataddrv (mkValAddr m (mkLocalValRef thatv2)) expr
thatv2,mkCompGenLet m thataddrv (mkValAddr m false (mkLocalValRef thatv2)) expr
else thataddrv,expr
let mkBindThatAddr g m ty thataddrv thatv thate expr =
if isStructTy g ty then
// let thataddrv = &thatv
mkCompGenLet m thataddrv (mkValAddr m (mkLocalValRef thatv)) expr
mkCompGenLet m thataddrv (mkValAddr m false (mkLocalValRef thatv)) expr
else
// let thataddrv = that
mkCompGenLet m thataddrv thate expr
@ -131,7 +141,7 @@ let mkBindThatAddrIfNeeded m thataddrvOpt thatv expr =
| None -> expr
| Some thataddrv ->
// let thataddrv = &thatv
mkCompGenLet m thataddrv (mkValAddr m (mkLocalValRef thatv)) expr
mkCompGenLet m thataddrv (mkValAddr m false (mkLocalValRef thatv)) expr
let mkDerefThis g m (thisv: Val) thise =
if isByrefTy g thisv.Type then mkAddrGet m (mkLocalValRef thisv)
@ -506,7 +516,6 @@ let mkUnionEquality g tcref (tycon:Tycon) =
let expr = if tycon.IsStructOrEnumTycon then expr else mkBindThatNullEquals g m thise thataddre expr
thisv,thatv,expr
/// Build the equality implementation for a union type when parameterized by a comparer
let mkUnionEqualityWithComparer g tcref (tycon:Tycon) (_thisv,thise) thatobje (thatv,thate) compe =
let m = tycon.Range
@ -817,7 +826,7 @@ let TyconIsCandidateForAugmentationWithCompare (g: TcGlobals) (tycon:Tycon) =
// This type gets defined in prim-types, before we can add attributes to F# type definitions
let isUnit = g.compilingFslib && tycon.DisplayName = "Unit"
not isUnit &&
not (TyconRefHasAttribute g tycon.Range g.attrib_IsByRefLikeAttribute (mkLocalTyconRef tycon)) &&
match getAugmentationAttribs g tycon with
// [< >]
| true, true, None, None, None, None , None, None, None
@ -832,6 +841,7 @@ let TyconIsCandidateForAugmentationWithEquals (g: TcGlobals) (tycon:Tycon) =
// This type gets defined in prim-types, before we can add attributes to F# type definitions
let isUnit = g.compilingFslib && tycon.DisplayName = "Unit"
not isUnit &&
not (TyconRefHasAttribute g tycon.Range g.attrib_IsByRefLikeAttribute (mkLocalTyconRef tycon)) &&
match getAugmentationAttribs g tycon with
// [< >]

Просмотреть файл

@ -80,6 +80,12 @@ let NewInferenceType () = mkTyparTy (NewTypar (TyparKind.Type, TyparRigidity.Fle
let NewErrorType () = mkTyparTy (NewErrorTypar ())
let NewErrorMeasure () = Measure.Var (NewErrorMeasureVar ())
let NewByRefKindInferenceType (g: TcGlobals) m =
let tp = NewTypar (TyparKind.Type, TyparRigidity.Flexible, Typar(compgenId, HeadTypeStaticReq, true), false, TyparDynamicReq.No, [], false, false)
if g.byrefkind_InOut_tcr.CanDeref then
tp.SetConstraints [TyparConstraint.DefaultsTo(10, TType_app(g.byrefkind_InOut_tcr, []), m)]
mkTyparTy tp
let NewInferenceTypes l = l |> List.map (fun _ -> NewInferenceType ())
// QUERY: should 'rigid' ever really be 'true'? We set this when we know
@ -878,6 +884,18 @@ and SolveTypSubsumesTyp (csenv:ConstraintSolverEnv) ndeep m2 (trace: OptionalTra
| (TType_app (tc2, [ms]), _) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms]))
-> SolveTypEqualsTypKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms (TType_measure Measure.One)
// 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 ] ->
SolveTypEqualsTyp csenv ndeep m2 trace None h1 h2 ++ (fun () ->
match stripTyEqnsA csenv.g canShortcut tag1, stripTyEqnsA csenv.g canShortcut tag2 with
| TType_app(tagc1, []), TType_app(tagc2, choices)
when (tyconRefEq g tagc2 g.choice2_tcr &&
choices |> List.exists (function AppTy g (choicetc, []) -> tyconRefEq g tagc1 choicetc | _ -> false)) -> CompleteD
| _ -> SolveTypEqualsTyp csenv ndeep m2 trace cxsln tag1 tag2)
| _ -> SolveTypEqualsTypEqns csenv ndeep m2 trace cxsln l1 l2
| TType_app (tc1, l1) , TType_app (tc2, l2) when tyconRefEq g tc1 tc2 ->
SolveTypEqualsTypEqns csenv ndeep m2 trace cxsln l1 l2
@ -1901,7 +1919,7 @@ and CanMemberSigsMatchUpToCheck
if not (permitOptArgs || isNil unnamedCalledOptArgs) then ErrorD(Error(FSComp.SR.csOptionalArgumentNotPermittedHere(), m)) else
let calledObjArgTys = minfo.GetObjArgTypes(amap, m, minst)
let calledObjArgTys = calledMeth.CalledObjArgTys(m)
// Check all the argument types.
@ -1919,7 +1937,7 @@ and CanMemberSigsMatchUpToCheck
if isArray1DTy g calledArg.CalledArgumentType then
let paramArrayElemTy = destArrayTy g calledArg.CalledArgumentType
let reflArgInfo = calledArg.ReflArgInfo // propgate the reflected-arg info to each param array argument
calledMeth.ParamArrayCallerArgs |> OptionD (IterateD (fun callerArg -> subsumeArg (CalledArg((0, 0), false, NotOptional, NoCallerInfo, false, None, reflArgInfo, paramArrayElemTy)) callerArg))
calledMeth.ParamArrayCallerArgs |> OptionD (IterateD (fun callerArg -> subsumeArg (CalledArg((0, 0), false, NotOptional, NoCallerInfo, false, false, None, reflArgInfo, paramArrayElemTy)) callerArg))
else
CompleteD)
@ -1942,7 +1960,7 @@ and CanMemberSigsMatchUpToCheck
let calledArgTy = rfinfo.FieldType
rfinfo.Name, calledArgTy
subsumeArg (CalledArg((-1, 0), false, NotOptional, NoCallerInfo, false, Some (mkSynId m name), ReflectedArgInfo.None, calledArgTy)) caller) )) ++ (fun () ->
subsumeArg (CalledArg((-1, 0), false, NotOptional, NoCallerInfo, false, false, Some (mkSynId m name), ReflectedArgInfo.None, calledArgTy)) caller) )) ++ (fun () ->
// - Always take the return type into account for
// -- op_Explicit, op_Implicit
@ -1953,11 +1971,17 @@ and CanMemberSigsMatchUpToCheck
| Some _ when minfo.IsConstructor -> CompleteD
| Some _ when not alwaysCheckReturn && isNil unnamedCalledOutArgs -> CompleteD
| Some reqdRetTy ->
let methodRetTy = calledMeth.ReturnTypeAfterOutArgTupling
let methodRetTy = calledMeth.CalledReturnTypeAfterOutArgTupling
unifyTypes reqdRetTy methodRetTy )))))
// Assert a subtype constraint, and wrap an ErrorsFromAddingSubsumptionConstraint error around any failure
// to allow us to report the outer types involved in the constraint
//
// ty1: expected
// ty2: actual
//
// "ty2 casts to ty1"
// "a value of type ty2 can be used where a value of type ty1 is expected"
and private SolveTypSubsumesTypWithReport (csenv:ConstraintSolverEnv) ndeep m trace cxsln ty1 ty2 =
TryD (fun () -> SolveTypSubsumesTypKeepAbbrevs csenv ndeep m trace cxsln ty1 ty2)
(function
@ -1973,11 +1997,11 @@ and private SolveTypSubsumesTypWithReport (csenv:ConstraintSolverEnv) ndeep m tr
// ty1: actual
// ty2: expected
and private SolveTypEqualsTypWithReport (csenv:ConstraintSolverEnv) ndeep m trace cxsln ty1 ty2 =
TryD (fun () -> SolveTypEqualsTypKeepAbbrevsWithCxsln csenv ndeep m trace cxsln ty1 ty2)
and private SolveTypEqualsTypWithReport (csenv:ConstraintSolverEnv) ndeep m trace cxsln actual expected =
TryD (fun () -> SolveTypEqualsTypKeepAbbrevsWithCxsln csenv ndeep m trace cxsln actual expected)
(function
| LocallyAbortOperationThatFailsToResolveOverload -> CompleteD
| res -> ErrorD (ErrorFromAddingTypeEquation(csenv.g, csenv.DisplayEnv, ty1, ty2, res, m)))
| res -> ErrorD (ErrorFromAddingTypeEquation(csenv.g, csenv.DisplayEnv, actual, expected, res, m)))
and ArgsMustSubsumeOrConvert
(csenv:ConstraintSolverEnv)
@ -2276,15 +2300,21 @@ and ResolveOverloading
let c = compareTypes calledArg1.CalledArgumentType calledArg2.CalledArgumentType
if c <> 0 then c else
// Func<_> is always considered better than any other delegate type
let c =
(calledArg1.CalledArgumentType, calledArg2.CalledArgumentType) ||> compareCond (fun ty1 ty2 ->
// Func<_> is always considered better than any other delegate type
match tryDestAppTy csenv.g ty1 with
| Some tcref1 ->
| Some tcref1 when
tcref1.DisplayName = "Func" &&
(match tcref1.PublicPath with Some p -> p.EnclosingPath = [| "System" |] | _ -> false) &&
isDelegateTy g ty1 &&
isDelegateTy g ty2
isDelegateTy g ty2 -> true
// T is always better than inref<T>
| _ when isInByrefTy csenv.g ty2 && typeEquiv csenv.g ty1 (destByrefTy csenv.g ty2) ->
true
| _ -> false)
if c <> 0 then c else
@ -2438,7 +2468,10 @@ and ResolveOverloading
| None -> CompleteD
| Some _ when calledMeth.Method.IsConstructor -> CompleteD
| Some reqdRetTy ->
let actualRetTy = calledMeth.ReturnTypeAfterOutArgTupling
let actualRetTy = calledMeth.CalledReturnTypeAfterOutArgTupling
if isByrefTy g reqdRetTy then
ErrorD(Error(FSComp.SR.tcByrefReturnImplicitlyDereferenced(), m))
else
MustUnify csenv ndeep trace cxsln reqdRetTy actualRetTy)
| None ->
@ -2649,7 +2682,7 @@ let CodegenWitnessThatTypSupportsTraitConstraint tcVal g amap m (traitInfo:Trait
// the address of the object then go do that
if minfo.IsStruct && minfo.IsInstance && (match argExprs with [] -> false | h :: _ -> not (isByrefTy g (tyOfExpr g h))) then
let h, t = List.headAndTail argExprs
let wrap, h' = mkExprAddrOfExpr g true false PossiblyMutates h None m
let wrap, h', _readonly = mkExprAddrOfExpr g true false PossiblyMutates h None m
ResultD (Some (wrap (Expr.Op(TOp.TraitCall(traitInfo), [], (h' :: t), m))))
else
ResultD (Some (MakeMethInfoCall amap m minfo methArgTys argExprs ))
@ -2664,7 +2697,7 @@ let CodegenWitnessThatTypSupportsTraitConstraint tcVal g amap m (traitInfo:Trait
// the address of the object then go do that
if rfref.Tycon.IsStructOrEnumTycon && not (isByrefTy g (tyOfExpr g argExprs.[0])) then
let h = List.head argExprs
let wrap, h' = mkExprAddrOfExpr g true false DefinitelyMutates h None m
let wrap, h', _readonly = mkExprAddrOfExpr g true false DefinitelyMutates h None m
Some (wrap (mkRecdFieldSetViaExprAddr (h', rfref, tinst, argExprs.[1], m)))
else
Some (mkRecdFieldSetViaExprAddr (argExprs.[0], rfref, tinst, argExprs.[1], m))

Просмотреть файл

@ -22,6 +22,9 @@ val NewAnonTypar : TyparKind * range * TyparRigidity * TyparStaticReq * TyparDyn
/// Create an inference type variable
val NewInferenceType : unit -> TType
/// Create an inference type variable for the kind of a byref pointer
val NewByRefKindInferenceType : TcGlobals -> range -> TType
/// Create an inference type variable representing an error condition when checking an expression
val NewErrorType : unit -> TType

Просмотреть файл

@ -584,10 +584,10 @@ let decideTransform g z v callPatterns (m, tps, vss:Val list list, rty) =
// Public f could be used beyond assembly.
// For now, suppressing any transforms on these.
// Later, could transform f and fix up local calls and provide an f wrapper for beyond.
let eligibleVal g (v:Val) =
let eligibleVal g m (v:Val) =
let dllImportStubOrOtherNeverInline = (v.InlineInfo = ValInline.Never)
let mutableVal = v.IsMutable
let byrefVal = isByrefLikeTy g v.Type
let byrefVal = isByrefLikeTy g m v.Type
not dllImportStubOrOtherNeverInline &&
not byrefVal &&
not mutableVal &&
@ -595,8 +595,8 @@ let eligibleVal g (v:Val) =
not v.IsCompiledAsTopLevel
let determineTransforms g (z : GlobalUsageAnalysis.Results) =
let selectTransform f sites =
if not (eligibleVal g f) then None else
let selectTransform (f: Val) sites =
if not (eligibleVal g f.Range f) then None else
// Consider f, if it has top-level lambda (meaning has term args)
match Zmap.tryFind f z.Defns with
| None -> None // no binding site, so no transform

Просмотреть файл

@ -1331,7 +1331,7 @@ tcTupleStructMismatch,"One tuple type is a struct tuple, the other is a referenc
3206,CallerMemberNameIsOverriden,"The CallerMemberNameAttribute applied to parameter '%s' will have no effect. It is overridden by the CallerFilePathAttribute."
3207,tcFixedNotAllowed,"Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string'"
3208,tcCouldNotFindOffsetToStringData,"Could not find method System.Runtime.CompilerServices.OffsetToStringData in references when building 'fixed' expression."
3209,chkNoByrefReturnOfLocal,"The address of the variable '%s' cannot be used at this point. A method or function may not return the address of this local value."
3209,chkNoByrefAddressOfLocal,"The address of the variable '%s' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope."
3210,tcNamedActivePattern,"%s is an active pattern and cannot be treated as a discriminated union case with named fields."
3211,DefaultParameterValueNotAppropriateForArgument,"The default value does not have the same type as the argument. The DefaultParameterValue attribute and any Optional attribute will be ignored. Note: 'null' needs to be annotated with the correct type, e.g. 'DefaultParameterValue(null:obj)'."
tcGlobalsSystemTypeNotFound,"The system type '%s' was required but no referenced system DLL contained this type"
@ -1426,3 +1426,13 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl
3221,implicitlyDiscardedInSequenceExpression,"This expression returns a value of type '%s' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield'."
3222,implicitlyDiscardedSequenceInSequenceExpression,"This expression returns a value of type '%s' but is implicitly discarded. Consider using 'let' to bind the result to a name, e.g. 'let result = expression'. If you intended to use the expression as a value in the sequence then use an explicit 'yield!'."
3223,ilreadFileChanged,"The file '%s' changed on disk unexpectedly, please reload."
3224,writeToReadOnlyByref,"The byref pointer is readonly, so this write is not permitted."
3225,readOnlyAttributeOnStructWithMutableField,"A ReadOnly attribute has been applied to a struct type with a mutable field."
3226,tcByrefReturnImplicitlyDereferenced,"A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&f(x)' or '&obj.Method(arg1, arg2)'."
3227,tcByRefLikeNotStruct,"A type annotated with IsByRefLike must also be a struct. Consider adding the [<Struct>] attribute to the type."
3228,chkNoByrefReturnOfLocal,"The address of the variable '%s' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope."
3229,chkNoReturnOfLimitedSpan,"The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope."
3230,chkNoWriteToLimitedSpan,"This value can't be assigned because the target '%s' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope."
3231,tastValueMustBeLocal,"A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'"
3232,tcIsReadOnlyNotStruct,"A type annotated with IsReadOnly must also be a struct. Consider adding the [<Struct>] attribute to the type."
3234,chkStructsMayNotReturnAddressesOfContents,"Struct members cannot return the address of fields of the struct by reference"

Просмотреть файл

@ -25,6 +25,14 @@ module NativePtr =
[<CompiledName("ToNativeIntInlined")>]
let inline toNativeInt (address: nativeptr<'T>) = (# "" address : nativeint #)
[<NoDynamicInvocation>]
[<CompiledName("ToVoidPtrInlined")>]
let inline toVoidPtr (address: nativeptr<'T>) = (# "" address : voidptr #)
[<NoDynamicInvocation>]
[<CompiledName("OfVoidPtrInlined")>]
let inline ofVoidPtr (address: voidptr) = (# "" address : nativeptr<'T> #)
[<NoDynamicInvocation>]
[<CompiledName("AddPointerInlined")>]
let inline add (address : nativeptr<'T>) (index:int) : nativeptr<'T> = toNativeInt address + nativeint index * (# "sizeof !0" type('T) : nativeint #) |> ofNativeInt

Просмотреть файл

@ -19,6 +19,22 @@ namespace Microsoft.FSharp.NativeInterop
/// <returns>A typed pointer.</returns>
val inline ofNativeInt : address:nativeint -> nativeptr<'T>
[<Unverifiable>]
[<NoDynamicInvocation>]
[<CompiledName("ToVoidPtrInlined")>]
/// <summary>Returns an untyped native pointer for a given typed pointer.</summary>
/// <param name="address">The pointer address.</param>
/// <returns>A typed pointer.</returns>
val inline toVoidPtr : address:nativeptr<'T> -> voidptr
[<Unverifiable>]
[<NoDynamicInvocation>]
[<CompiledName("OfVoidPtrInlined")>]
/// <summary>Returns a typed native pointer for a untyped native pointer.</summary>
/// <param name="address">The untyped pointer.</param>
/// <returns>A typed pointer.</returns>
val inline ofVoidPtr : voidptr -> nativeptr<'T>
[<Unverifiable>]
[<NoDynamicInvocation>]
[<CompiledName("ToNativeIntInlined")>]

Просмотреть файл

@ -64,8 +64,14 @@ namespace Microsoft.FSharp.Core
type array<'T> = 'T[]
/// <summary>Represents a managed pointer in F# code.</summary>
type byref<'T, 'Kind> = (# "!0&" #)
/// <summary>Represents a managed pointer in F# code. For F# 4.5+ this is considered equivalent to <c>byref&lt'T, ByRefKinds.InOut&gt</c></summary>
type byref<'T> = (# "!0&" #)
type nativeptr<'T when 'T : unmanaged> = (# "native int" #)
type ilsigptr<'T> = (# "!0*" #)
type voidptr = (# "void*" #)
type ilsigptr<'T> = (# "!0*" #)

Просмотреть файл

@ -228,8 +228,10 @@ namespace Microsoft.FSharp.Core
/// values.</remarks>
type 'T array = 'T[]
/// <summary>Represents a managed pointer in F# code.</summary>
type byref<'T, 'Kind> = (# "!0&" #)
/// <summary>Represents a managed pointer in F# code. For F# 4.5+ this is considered equivalent to <c>byref&lt'T, ByRefKinds.InOut&gt</c></summary>
type byref<'T> = (# "!0&" #)
/// <summary>Represents an unmanaged pointer in F# code.</summary>
@ -241,6 +243,15 @@ namespace Microsoft.FSharp.Core
/// by the functions in the <c>NativeInterop.NativePtr</c> module.</remarks>
type nativeptr<'T when 'T : unmanaged> = (# "native int" #)
/// <summary>Represents an untyped unmanaged pointer in F# code.</summary>
///
/// <remarks>This type should only be used when writing F# code that interoperates
/// with native code. Use of this type in F# code may result in
/// unverifiable code being generated. Conversions to and from the
/// <c>nativeint</c> type may be required. Values of this type can be generated
/// by the functions in the <c>NativeInterop.NativePtr</c> module.</remarks>
type voidptr = (# "void*" #)
/// <summary>This type is for internal use by the F# code generator.</summary>
type ilsigptr<'T> = (# "!0*" #)

Просмотреть файл

@ -5649,6 +5649,24 @@ namespace Microsoft.FSharp.Core
if n >= 0 then PowDecimal x n else 1.0M / PowDecimal x n)
/// Represents the types of byrefs in F# 4.5+
module ByRefKinds =
/// Represents a byref that can be written
type Out() = class end
/// Represents a byref that can be read
type In() = class end
/// Represents a byref that can be both read and written
type InOut = Choice<In, Out>
/// <summary>Represents a in-argument or readonly managed pointer in F# code. This type should only be used with F# 4.5+.</summary>
type inref<'T> = byref<'T, ByRefKinds.In>
/// <summary>Represents a out-argument managed pointer in F# code. This type should only be used with F# 4.5+.</summary>
type outref<'T> = byref<'T, ByRefKinds.Out>
namespace Microsoft.FSharp.Control
open System

Просмотреть файл

@ -1659,6 +1659,24 @@ namespace Microsoft.FSharp.Core
/// <returns>The optimized function.</returns>
new : unit -> FSharpFunc<'T1,'T2,'T3,'T4,'T5,'U>
/// Represents the types of byrefs in F# 4.5+
module ByRefKinds =
/// Represents a byref that can be written
type Out = class end
/// Represents a byref that can be read
type In = class end
/// Represents a byref that can be both read and written
type InOut = Choice<In, Out>
/// <summary>Represents a in-argument or readonly managed pointer in F# code. This type should only be used with F# 4.5+.</summary>
type inref<'T> = byref<'T, ByRefKinds.In>
/// <summary>Represents a out-argument managed pointer in F# code. This type should only be used with F# 4.5+.</summary>
type outref<'T> = byref<'T, ByRefKinds.Out>
/// <summary>The type of mutable references. Use the functions [!] and [:=] to get and
/// set values of this type.</summary>
[<StructuralEquality; StructuralComparison>]
@ -3195,6 +3213,7 @@ namespace Microsoft.FSharp.Core
[<CompiledName("ToChar")>]
val inline char : value:^T -> char when ^T : (static member op_Explicit : ^T -> char) and default ^T : int
namespace Microsoft.FSharp.Control
open Microsoft.FSharp.Core

Просмотреть файл

@ -363,14 +363,30 @@ let voidCheck m g permits ty =
error(InternalError("System.Void unexpectedly detected in IL code generation. This should not occur.",m))
#endif
// When generating parameter and return types generate precise .NET IL pointer types
// These can't be generated for generic instantiations, since .NET generics doesn't
// permit this. But for 'naked' values (locals, parameters, return values etc.) machine
// integer values and native pointer values are compatible (though the code is unverifiable).
/// When generating parameter and return types generate precise .NET IL pointer types.
/// These can't be generated for generic instantiations, since .NET generics doesn't
/// permit this. But for 'naked' values (locals, parameters, return values etc.) machine
/// integer values and native pointer values are compatible (though the code is unverifiable).
type PtrsOK =
| PtrTypesOK
| PtrTypesNotOK
let GenReadOnlyAttributeIfNecessary (g: TcGlobals) ty =
let add = isInByrefTy g ty && g.attrib_IsReadOnlyAttribute.TyconRef.CanDeref
if add then
let attr = mkILCustomAttribute g.ilg (g.attrib_IsReadOnlyAttribute.TypeRef, [], [], [])
Some attr
else
None
/// Generate "modreq([mscorlib]System.Runtime.InteropServices.InAttribute)" on inref types.
let GenReadOnlyModReqIfNecessary (g: TcGlobals) ty ilTy =
let add = isInByrefTy g ty && g.attrib_InAttribute.TyconRef.CanDeref
if add then
ILType.Modified(true, g.attrib_InAttribute.TypeRef, ilTy)
else
ilTy
let rec GenTypeArgAux amap m tyenv tyarg =
GenTypeAux amap m tyenv VoidNotOK PtrTypesNotOK tyarg
@ -395,6 +411,7 @@ and GenTyAppAux amap m tyenv repr tinst =
and GenNamedTyAppAux (amap:ImportMap) m tyenv ptrsOK tcref tinst =
let g = amap.g
let tinst = DropErasedTyargs tinst
// See above note on ptrsOK
if ptrsOK = PtrTypesOK && tyconRefEq g tcref g.nativeptr_tcr && (freeInTypes CollectTypars tinst).FreeTypars.IsEmpty then
GenNamedTyAppAux amap m tyenv ptrsOK g.ilsigptr_tcr tinst
@ -417,7 +434,10 @@ and GenTypeAux amap m (tyenv: TypeReprEnv) voidOK ptrsOK ty =
#endif
match stripTyEqnsAndMeasureEqns g ty with
| TType_app (tcref, tinst) -> GenNamedTyAppAux amap m tyenv ptrsOK tcref tinst
| TType_tuple (tupInfo, args) -> GenTypeAux amap m tyenv VoidNotOK ptrsOK (mkCompiledTupleTy g (evalTupInfoIsStruct tupInfo) args)
| TType_fun (dty, returnTy) -> EraseClosures.mkILFuncTy g.ilxPubCloEnv (GenTypeArgAux amap m tyenv dty) (GenTypeArgAux amap m tyenv returnTy)
| TType_ucase (ucref, args) ->
@ -428,7 +448,9 @@ and GenTypeAux amap m (tyenv: TypeReprEnv) voidOK ptrsOK ty =
let tps = DropErasedTypars tps
if tps.IsEmpty then GenTypeAux amap m tyenv VoidNotOK ptrsOK tau
else EraseClosures.mkILTyFuncTy g.ilxPubCloEnv
| TType_var tp -> mkILTyvarTy tyenv.[tp,m]
| TType_measure _ -> g.ilg.typ_Int32
//--------------------------------------------------------------------------
@ -504,13 +526,19 @@ and GenNamedTyApp amap m tyenv tcref tinst = GenNamedTyAppAux amap m tyenv PtrTy
and GenReturnType amap m tyenv returnTyOpt =
match returnTyOpt with
| None -> ILType.Void
| Some returnTy -> GenTypeAux amap m tyenv VoidNotOK(*1*) PtrTypesOK returnTy (*1: generate void from unit, but not accept void *)
| Some returnTy ->
let ilTy = GenTypeAux amap m tyenv VoidNotOK(*1*) PtrTypesOK returnTy (*1: generate void from unit, but not accept void *)
GenReadOnlyModReqIfNecessary amap.g returnTy ilTy
and GenParamType amap m tyenv ty =
ty |> GenTypeAux amap m tyenv VoidNotOK PtrTypesOK
and GenParamType amap m tyenv isSlotSig ty =
let ilTy = GenTypeAux amap m tyenv VoidNotOK PtrTypesOK ty
if isSlotSig then
GenReadOnlyModReqIfNecessary amap.g ty ilTy
else
ilTy
and GenParamTypes amap m tyenv tys =
tys |> List.map (GenTypeAux amap m tyenv VoidNotOK PtrTypesOK)
and GenParamTypes amap m tyenv isSlotSig tys =
tys |> List.map (GenParamType amap m tyenv isSlotSig)
and GenTypeArgs amap m tyenv tyargs = GenTypeArgsAux amap m tyenv tyargs
@ -607,7 +635,7 @@ type ValStorage =
| StaticProperty of ILMethodSpec * OptionalShadowLocal
/// Indicates the value is "stored" as a IL static method (in a "main" class for a F#
/// compilation unit, or as a member) according to its inferred or specified arity.
| Method of ValReprInfo * ValRef * ILMethodSpec * Range.range * ArgReprInfo list * ArgReprInfo
| Method of ValReprInfo * ValRef * ILMethodSpec * Range.range * ArgReprInfo list * TType list * ArgReprInfo
/// Indicates the value is stored at the given position in the closure environment accessed via "ldarg 0"
| Env of ILType * int * ILFieldSpec * NamedLocalIlxClosureInfo ref option
/// Indicates that the value is an argument of a method being generated
@ -775,7 +803,9 @@ let GetMethodSpecForMemberVal amap g (memberInfo:ValMemberInfo) (vref:ValRef) =
let ilActualRetTy =
let ilRetTy = GenReturnType amap m tyenvUnderTypars returnTy
if isCtor || cctor then ILType.Void else ilRetTy
let ilTy = GenType amap m tyenvUnderTypars (mkAppTy parentTcref (List.map mkTyparTy ctps))
if isCompiledAsInstance || isCtor then
// Find the 'this' argument type if any
let thisTy,flatArgInfos =
@ -797,18 +827,19 @@ let GetMethodSpecForMemberVal amap g (memberInfo:ValMemberInfo) (vref:ValRef) =
ctps
thisArgTys
let methodArgTys,paramInfos = List.unzip flatArgInfos
let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars methodArgTys
let isSlotSig = memberInfo.MemberFlags.IsDispatchSlot || memberInfo.MemberFlags.IsOverrideOrExplicitImpl
let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars isSlotSig methodArgTys
let ilMethodInst = GenTypeArgs amap m tyenvUnderTypars (List.map mkTyparTy mtps)
let mspec = mkILInstanceMethSpecInTy (ilTy,vref.CompiledName,ilMethodArgTys,ilActualRetTy,ilMethodInst)
mspec,ctps,mtps,paramInfos,retInfo
mspec,ctps,mtps,paramInfos,retInfo,methodArgTys
else
let methodArgTys,paramInfos = List.unzip flatArgInfos
let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars methodArgTys
let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars false methodArgTys
let ilMethodInst = GenTypeArgs amap m tyenvUnderTypars (List.map mkTyparTy mtps)
let mspec = mkILStaticMethSpecInTy (ilTy,vref.CompiledName,ilMethodArgTys,ilActualRetTy,ilMethodInst)
mspec,ctps,mtps,paramInfos,retInfo
mspec,ctps,mtps,paramInfos,retInfo,methodArgTys
// Generate the ILFieldSpec for a top-level value
@ -894,18 +925,18 @@ let ComputeStorageForTopVal (amap, g, optIntraAssemblyInfo:IlxGenIntraAssemblyIn
| _ ->
match vref.MemberInfo with
| Some memberInfo when not vref.IsExtensionMember ->
let mspec,_,_,paramInfos,retInfo = GetMethodSpecForMemberVal amap g memberInfo vref
Method (topValInfo, vref, mspec, m, paramInfos, retInfo)
let mspec,_,_,paramInfos,retInfo,methodArgTys = GetMethodSpecForMemberVal amap g memberInfo vref
Method (topValInfo, vref, mspec, m, paramInfos, methodArgTys, retInfo)
| _ ->
let (tps, curriedArgInfos, returnTy, retInfo) = GetTopValTypeInCompiledForm g topValInfo vref.Type m
let tyenvUnderTypars = TypeReprEnv.ForTypars tps
let (methodArgTys,paramInfos) = curriedArgInfos |> List.concat |> List.unzip
let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars methodArgTys
let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars false methodArgTys
let ilRetTy = GenReturnType amap m tyenvUnderTypars returnTy
let ilLocTy = mkILTyForCompLoc cloc
let ilMethodInst = GenTypeArgs amap m tyenvUnderTypars (List.map mkTyparTy tps)
let mspec = mkILStaticMethSpecInTy (ilLocTy, nm, ilMethodArgTys, ilRetTy, ilMethodInst)
Method (topValInfo, vref, mspec, m, paramInfos, retInfo)
Method (topValInfo, vref, mspec, m, paramInfos, methodArgTys, retInfo)
let ComputeAndAddStorageForLocalTopVal (amap, g, intraAssemblyFieldTable, isInteractive, optShadowLocal) cloc (v:Val) eenv =
let storage = ComputeStorageForTopVal (amap, g, Some intraAssemblyFieldTable, isInteractive, optShadowLocal, mkLocalValRef v, cloc)
@ -1881,7 +1912,7 @@ let rec GenExpr (cenv:cenv) (cgbuf:CodeGenBuffer) eenv sp expr sequel =
GenGetExnField cenv cgbuf eenv (e,ecref,n,m) sequel
| TOp.UnionCaseFieldGet(ucref,n),[e],_ ->
GenGetUnionCaseField cenv cgbuf eenv (e,ucref,tyargs,n,m) sequel
| TOp.UnionCaseFieldGetAddr(ucref,n),[e],_ ->
| TOp.UnionCaseFieldGetAddr(ucref,n,_readonly),[e],_ ->
GenGetUnionCaseFieldAddr cenv cgbuf eenv (e,ucref,tyargs,n,m) sequel
| TOp.UnionCaseTagGet ucref,[e],_ ->
GenGetUnionCaseTag cenv cgbuf eenv (e,ucref,tyargs,m) sequel
@ -1895,9 +1926,9 @@ let rec GenExpr (cenv:cenv) (cgbuf:CodeGenBuffer) eenv sp expr sequel =
GenGetRecdField cenv cgbuf eenv (e,f,tyargs,m) sequel
| TOp.ValFieldGet f,[],_ ->
GenGetStaticField cenv cgbuf eenv (f,tyargs,m) sequel
| TOp.ValFieldGetAddr f,[e],_ ->
| TOp.ValFieldGetAddr (f, _readonly),[e],_ ->
GenGetRecdFieldAddr cenv cgbuf eenv (e,f,tyargs,m) sequel
| TOp.ValFieldGetAddr f,[],_ ->
| TOp.ValFieldGetAddr (f, _readonly),[],_ ->
GenGetStaticFieldAddr cenv cgbuf eenv (f,tyargs,m) sequel
| TOp.ValFieldSet f,[e1;e2],_ ->
GenSetRecdField cenv cgbuf eenv (e1,f,tyargs,e2,m) sequel
@ -1917,14 +1948,14 @@ let rec GenExpr (cenv:cenv) (cgbuf:CodeGenBuffer) eenv sp expr sequel =
GenTryCatch cenv cgbuf eenv (e1,vf,ef,vh,eh,m,resty,spTry,spWith) sequel
| TOp.ILCall(virt,_,valu,newobj,valUseFlags,_,isDllImport,ilMethRef,enclArgTys,methArgTys,returnTys),args,[] ->
GenILCall cenv cgbuf eenv (virt,valu,newobj,valUseFlags,isDllImport,ilMethRef,enclArgTys,methArgTys,args,returnTys,m) sequel
| TOp.RefAddrGet,[e],[ty] -> GenGetAddrOfRefCellField cenv cgbuf eenv (e,ty,m) sequel
| TOp.RefAddrGet _readonly,[e],[ty] -> GenGetAddrOfRefCellField cenv cgbuf eenv (e,ty,m) sequel
| TOp.Coerce,[e],[tgty;srcty] -> GenCoerce cenv cgbuf eenv (e,tgty,m,srcty) sequel
| TOp.Reraise,[],[rtnty] -> GenReraise cenv cgbuf eenv (rtnty,m) sequel
| TOp.TraitCall(ss),args,[] -> GenTraitCall cenv cgbuf eenv (ss,args, m) expr sequel
| TOp.LValueOp(LSet,v),[e],[] -> GenSetVal cenv cgbuf eenv (v,e,m) sequel
| TOp.LValueOp(LByrefGet,v),[],[] -> GenGetByref cenv cgbuf eenv (v,m) sequel
| TOp.LValueOp(LByrefSet,v),[e],[] -> GenSetByref cenv cgbuf eenv (v,e,m) sequel
| TOp.LValueOp(LGetAddr,v),[],[] -> GenGetValAddr cenv cgbuf eenv (v,m) sequel
| TOp.LValueOp(LAddrOf _,v),[],[] -> GenGetValAddr cenv cgbuf eenv (v,m) sequel
| TOp.Array,elems,[elemTy] -> GenNewArray cenv cgbuf eenv (elems,elemTy,m) sequel
| TOp.Bytes bytes,[],[] ->
if cenv.opts.emitConstantArraysUsingStaticDataBlobs then
@ -2546,7 +2577,7 @@ and GenApp cenv cgbuf eenv (f,fty,tyargs,args,m) sequel =
let storage = StorageForValRef m vref eenv
match storage with
| Method (_,_,mspec,_,_,_) ->
| Method (_,_,mspec,_,_,_,_) ->
CG.EmitInstr cgbuf (pop 0) (Push [cenv.g.iltyp_RuntimeMethodHandle]) (I_ldtoken (ILToken.ILMethod mspec))
| _ ->
errorR(Error(FSComp.SR.ilxgenUnexpectedArgumentToMethodHandleOfDuringCodegen(), m))
@ -2573,7 +2604,7 @@ and GenApp cenv cgbuf eenv (f,fty,tyargs,args,m) sequel =
when
(let storage = StorageForValRef m vref eenv
match storage with
| Method (topValInfo,vref,_,_,_,_) ->
| Method (topValInfo,vref,_,_,_,_,_) ->
(let tps,argtys,_,_ = GetTopValTypeInFSharpForm cenv.g topValInfo vref.Type m
tps.Length = tyargs.Length &&
argtys.Length <= args.Length)
@ -2581,7 +2612,7 @@ and GenApp cenv cgbuf eenv (f,fty,tyargs,args,m) sequel =
let storage = StorageForValRef m vref eenv
match storage with
| Method (topValInfo,vref,mspec,_,_,_) ->
| Method (topValInfo,vref,mspec,_,_,_,_) ->
let nowArgs,laterArgs =
let _,curriedArgInfos,_,_ = GetTopValTypeInFSharpForm cenv.g topValInfo vref.Type m
List.chop curriedArgInfos.Length args
@ -3356,7 +3387,8 @@ and GenGetAddrOfRefCellField cenv cgbuf eenv (e,ty,m) sequel =
and GenGetValAddr cenv cgbuf eenv (v: ValRef, m) sequel =
let vspec = v.Deref
let ilTy = GenTypeOfVal cenv eenv vspec
match StorageForValRef m v eenv with
let storage = StorageForValRef m v eenv
match storage with
| Local (idx,None) ->
CG.EmitInstrs cgbuf (pop 0) (Push [ILType.Byref ilTy]) [ I_ldloca (uint16 idx) ]
| Arg idx ->
@ -3465,16 +3497,24 @@ and GenGenericParam cenv eenv (tp:Typar) =
/// Generates the data used for parameters at definitions of abstract method slots such as interface methods or override methods.
and GenSlotParam m cenv eenv (TSlotParam(nm,ty,inFlag,outFlag,optionalFlag,attribs)) : ILParameter =
let inFlag2,outFlag2,optionalFlag2,defaultParamValue,paramMarshal2,attribs = GenParamAttribs cenv attribs
let ilTy = GenParamType cenv.amap m eenv.tyenv true ty
let inFlag2,outFlag2,optionalFlag2,defaultParamValue,paramMarshal2,attribs = GenParamAttribs cenv ty attribs
let ilAttribs = GenAttrs cenv eenv attribs
let ilAttribs =
match GenReadOnlyAttributeIfNecessary cenv.g ty with
| Some attr -> ilAttribs @ [attr]
| None -> ilAttribs
{ Name=nm
Type= GenParamType cenv.amap m eenv.tyenv ty
Type= ilTy
Default=defaultParamValue
Marshal=paramMarshal2
IsIn=inFlag || inFlag2
IsOut=outFlag || outFlag2
IsOptional=optionalFlag || optionalFlag2
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (GenAttrs cenv eenv attribs))
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs ilAttribs)
MetadataIndex = NoMetadataIdx }
and GenFormalSlotsig m cenv eenv (TSlotSig(_,typ,ctps,mtps,paraml,returnTy)) =
@ -3484,6 +3524,13 @@ and GenFormalSlotsig m cenv eenv (TSlotSig(_,typ,ctps,mtps,paraml,returnTy)) =
let ilParams = paraml |> List.map (GenSlotParam m cenv eenvForSlotSig)
let ilRetTy = GenReturnType cenv.amap m eenvForSlotSig.tyenv returnTy
let ilRet = mkILReturn ilRetTy
let ilRet =
match returnTy with
| None -> ilRet
| Some ty ->
match GenReadOnlyAttributeIfNecessary cenv.g ty with
| Some attr -> ilRet.WithCustomAttrs (mkILCustomAttrs (ilRet.CustomAttrs.AsList @ [attr]))
| None -> ilRet
ilTy, ilParams, ilRet
and instSlotParam inst (TSlotParam(nm,ty,inFlag,fl2,fl3,attrs)) = TSlotParam(nm,instType inst ty,inFlag,fl2,fl3,attrs)
@ -4697,11 +4744,11 @@ and GenBindingAfterSequencePoint cenv cgbuf eenv sp (TBind(vspec,rhsExpr,_)) sta
CommitStartScope cgbuf startScopeMarkOpt
GenExpr cenv cgbuf eenv SPSuppress cctorBody discard
| Method (topValInfo,_,mspec,_,paramInfos,retInfo) ->
| Method (topValInfo,_,mspec,_,paramInfos,methodArgTys,retInfo) ->
let tps,ctorThisValOpt,baseValOpt,vsl,body',bodyty = IteratedAdjustArityOfLambda cenv.g cenv.amap topValInfo rhsExpr
let methodVars = List.concat vsl
CommitStartScope cgbuf startScopeMarkOpt
GenMethodForBinding cenv cgbuf eenv (vspec,mspec,access,paramInfos,retInfo) (topValInfo,ctorThisValOpt,baseValOpt,tps,methodVars, body', bodyty)
GenMethodForBinding cenv cgbuf eenv (vspec,mspec,access,paramInfos,retInfo) (topValInfo,ctorThisValOpt,baseValOpt,tps,methodVars, methodArgTys, body', bodyty)
| StaticProperty (ilGetterMethSpec, optShadowLocal) ->
@ -4948,9 +4995,9 @@ and GenMarshal cenv attribs =
// No MarshalAs detected
None, attribs
and GenParamAttribs cenv attribs =
let inFlag = HasFSharpAttributeOpt cenv.g cenv.g.attrib_InAttribute attribs
let outFlag = HasFSharpAttribute cenv.g cenv.g.attrib_OutAttribute attribs
and GenParamAttribs cenv paramTy attribs =
let inFlag = HasFSharpAttribute cenv.g cenv.g.attrib_InAttribute attribs || isInByrefTy cenv.g paramTy
let outFlag = HasFSharpAttribute cenv.g cenv.g.attrib_OutAttribute attribs || isOutByrefTy cenv.g paramTy
let optionalFlag = HasFSharpAttributeOpt cenv.g cenv.g.attrib_OptionalAttribute attribs
let defaultValue = TryFindFSharpAttributeOpt cenv.g cenv.g.attrib_DefaultParameterValueAttribute attribs
@ -4959,7 +5006,7 @@ and GenParamAttribs cenv attribs =
// as custom attributes in the code - they are implicit from the IL bits for these
let attribs =
attribs
|> List.filter (IsMatchingFSharpAttributeOpt cenv.g cenv.g.attrib_InAttribute >> not)
|> List.filter (IsMatchingFSharpAttribute cenv.g cenv.g.attrib_InAttribute >> not)
|> List.filter (IsMatchingFSharpAttribute cenv.g cenv.g.attrib_OutAttribute >> not)
|> List.filter (IsMatchingFSharpAttributeOpt cenv.g cenv.g.attrib_OptionalAttribute >> not)
|> List.filter (IsMatchingFSharpAttributeOpt cenv.g cenv.g.attrib_DefaultParameterValueAttribute >> not)
@ -4967,7 +5014,7 @@ and GenParamAttribs cenv attribs =
let Marshal,attribs = GenMarshal cenv attribs
inFlag,outFlag,optionalFlag,defaultValue,Marshal,attribs
and GenParams cenv eenv (mspec:ILMethodSpec) (attribs:ArgReprInfo list) (implValsOpt: Val list option) =
and GenParams cenv eenv (mspec:ILMethodSpec) (attribs:ArgReprInfo list) methodArgTys (implValsOpt: Val list option) =
let ilArgTys = mspec.FormalArgTypes
let argInfosAndTypes =
if List.length attribs = List.length ilArgTys then List.zip ilArgTys attribs
@ -4980,9 +5027,9 @@ and GenParams cenv eenv (mspec:ILMethodSpec) (attribs:ArgReprInfo list) (implVal
| _ ->
List.map (fun x -> x,None) argInfosAndTypes
(Set.empty,argInfosAndTypes)
||> List.mapFold (fun takenNames ((ilArgTy,topArgInfo),implValOpt) ->
let inFlag,outFlag,optionalFlag,defaultParamValue,Marshal,attribs = GenParamAttribs cenv topArgInfo.Attribs
(Set.empty,List.zip methodArgTys argInfosAndTypes)
||> List.mapFold (fun takenNames (methodArgTy, ((ilArgTy,topArgInfo),implValOpt)) ->
let inFlag,outFlag,optionalFlag,defaultParamValue,Marshal,attribs = GenParamAttribs cenv methodArgTy topArgInfo.Attribs
let idOpt = (match topArgInfo.Name with
| Some v -> Some v
@ -4998,6 +5045,14 @@ and GenParams cenv eenv (mspec:ILMethodSpec) (attribs:ArgReprInfo list) (implVal
| None ->
None, takenNames
let ilAttribs = GenAttrs cenv eenv attribs
let ilAttribs =
match GenReadOnlyAttributeIfNecessary cenv.g methodArgTy with
| Some attr -> ilAttribs @ [attr]
| None -> ilAttribs
let param : ILParameter =
{ Name=nmOpt
Type= ilArgTy
@ -5006,17 +5061,17 @@ and GenParams cenv eenv (mspec:ILMethodSpec) (attribs:ArgReprInfo list) (implVal
IsIn=inFlag
IsOut=outFlag
IsOptional=optionalFlag
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs (GenAttrs cenv eenv attribs))
CustomAttrsStored = storeILCustomAttrs (mkILCustomAttrs ilAttribs)
MetadataIndex = NoMetadataIdx }
param, takenNames)
|> fst
and GenReturnInfo cenv eenv ilRetTy (retInfo : ArgReprInfo) : ILReturn =
let marshal,attrs = GenMarshal cenv retInfo.Attribs
let marshal,attribs = GenMarshal cenv retInfo.Attribs
{ Type=ilRetTy
Marshal=marshal
CustomAttrsStored= storeILCustomAttrs (mkILCustomAttrs (GenAttrs cenv eenv attrs))
CustomAttrsStored= storeILCustomAttrs (mkILCustomAttrs (GenAttrs cenv eenv attribs))
MetadataIndex = NoMetadataIdx }
and GenPropertyForMethodDef compileAsInstance tref mdef (v:Val) (memberInfo:ValMemberInfo) ilArgTys ilPropTy ilAttrs compiledName =
@ -5108,7 +5163,7 @@ and ComputeMethodImplAttribs cenv (_v:Val) attrs =
and GenMethodForBinding
cenv cgbuf eenv
(v:Val,mspec,access,paramInfos,retInfo)
(topValInfo,ctorThisValOpt,baseValOpt,tps,methodVars, body, returnTy) =
(topValInfo,ctorThisValOpt,baseValOpt,tps,methodVars, methodArgTys, body, returnTy) =
let m = v.Range
let selfMethodVars,nonSelfMethodVars,compileAsInstance =
@ -5122,6 +5177,7 @@ and GenMethodForBinding
let nonUnitNonSelfMethodVars,body = BindUnitVars cenv.g (nonSelfMethodVars,paramInfos,body)
let nonUnitMethodVars = selfMethodVars@nonUnitNonSelfMethodVars
let cmtps,curriedArgInfos,_,_ = GetTopValTypeInCompiledForm cenv.g topValInfo v.Type v.Range
let eenv = bindBaseOrThisVarOpt cenv eenv ctorThisValOpt
let eenv = bindBaseOrThisVarOpt cenv eenv baseValOpt
@ -5204,7 +5260,7 @@ and GenMethodForBinding
yield! GenCompilationArgumentCountsAttr cenv v ]
let ilTypars = GenGenericParams cenv eenvUnderMethLambdaTypars tps
let ilParams = GenParams cenv eenv mspec paramInfos (Some(nonUnitNonSelfMethodVars))
let ilParams = GenParams cenv eenv mspec paramInfos methodArgTys (Some(nonUnitNonSelfMethodVars))
let ilReturn = GenReturnInfo cenv eenv mspec.FormalReturnType retInfo
let methName = mspec.Name
let tref = mspec.MethodRef.DeclaringTypeRef
@ -5432,7 +5488,7 @@ and GenSetStorage m cgbuf storage =
CG.EmitInstr cgbuf (pop 1) Push0 (I_call(Normalcall,mkILMethSpecForMethRefInTy(ilSetterMethRef,ilContainerTy,[]),None))
| StaticProperty (ilGetterMethSpec,_) ->
error(Error(FSComp.SR.ilStaticMethodIsNotLambda(ilGetterMethSpec.Name),m))
| Method (_,_,mspec,m,_,_) ->
| Method (_,_,mspec,m,_,_,_) ->
error(Error(FSComp.SR.ilStaticMethodIsNotLambda(mspec.Name),m))
| Null -> CG.EmitInstr cgbuf (pop 1) Push0 AI_pop
| Arg _ -> error(Error(FSComp.SR.ilMutableVariablesCannotEscapeMethod(),m))
@ -5471,7 +5527,7 @@ and GenGetStorageAndSequel cenv cgbuf eenv m (typ,ilTy) storage storeSequel =
CG.EmitInstr cgbuf (pop 0) (Push [ilTy]) (I_call (Normalcall, ilGetterMethSpec, None))
CommitGetStorageSequel cenv cgbuf eenv m typ None storeSequel
| Method (topValInfo,vref,mspec,_,_,_) ->
| Method (topValInfo,vref,mspec,_,_,_,_) ->
// Get a toplevel value as a first-class value.
// We generate a lambda expression and that simply calls
// the toplevel method. However we optimize the case where we are
@ -5724,7 +5780,7 @@ and GenAttr amap g eenv (Attrib(_,k,args,props,_,_,_)) =
| ILAttrib(mref) -> mkILMethSpec(mref,AsObject,[],[])
| FSAttrib(vref) ->
assert(vref.IsMember)
let mspec,_,_,_,_ = GetMethodSpecForMemberVal amap g (Option.get vref.MemberInfo) vref
let mspec,_,_,_,_,_ = GetMethodSpecForMemberVal amap g (Option.get vref.MemberInfo) vref
mspec
let ilArgs = List.map2 (fun (AttribExpr(_,vexpr)) ty -> GenAttribArg amap g eenv vexpr ty) args mspec.FormalArgTypes
mkILCustomAttribMethRef g.ilg (mspec,ilArgs, props)
@ -6053,11 +6109,11 @@ and GenAbstractBinding cenv eenv tref (vref:ValRef) =
[ yield! GenAttrs cenv eenv attribs
yield! GenCompilationArgumentCountsAttr cenv vref.Deref ]
let mspec,ctps,mtps,argInfos,retInfo = GetMethodSpecForMemberVal cenv.amap cenv.g memberInfo vref
let mspec,ctps,mtps,argInfos,retInfo,methodArgTys = GetMethodSpecForMemberVal cenv.amap cenv.g memberInfo vref
let eenvForMeth = EnvForTypars (ctps@mtps) eenv
let ilMethTypars = GenGenericParams cenv eenvForMeth mtps
let ilReturn = GenReturnInfo cenv eenvForMeth mspec.FormalReturnType retInfo
let ilParams = GenParams cenv eenvForMeth mspec argInfos None
let ilParams = GenParams cenv eenvForMeth mspec argInfos methodArgTys None
let compileAsInstance = ValRefIsCompiledAsInstanceMember cenv.g vref
let mdef = mkILGenericVirtualMethod (vref.CompiledName,ILMemberAccess.Public,ilMethTypars,ilParams,ilReturn,MethodBody.Abstract)
@ -6099,7 +6155,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) =
[
match (eenv.valsInScope.TryFind cenv.g.sprintf_vref.Deref,
eenv.valsInScope.TryFind cenv.g.new_format_vref.Deref) with
| Some(Lazy(Method(_,_,sprintfMethSpec,_,_,_))), Some(Lazy(Method(_,_,newFormatMethSpec,_,_,_))) ->
| Some(Lazy(Method(_,_,sprintfMethSpec,_,_,_,_))), Some(Lazy(Method(_,_,newFormatMethSpec,_,_,_,_))) ->
// The type returned by the 'sprintf' call
let funcTy = EraseClosures.mkILFuncTy cenv.g.ilxPubCloEnv ilThisTy cenv.g.ilg.typ_String
// Give the instantiation of the printf format object, i.e. a Format`5 object compatible with StringFormat<ilThisTy>
@ -6428,7 +6484,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon:Tycon) =
let (|Lazy|) (x:Lazy<_>) = x.Force()
match (eenv.valsInScope.TryFind cenv.g.sprintf_vref.Deref,
eenv.valsInScope.TryFind cenv.g.new_format_vref.Deref) with
| Some(Lazy(Method(_,_,sprintfMethSpec,_,_,_))), Some(Lazy(Method(_,_,newFormatMethSpec,_,_,_))) ->
| Some(Lazy(Method(_,_,sprintfMethSpec,_,_,_,_))), Some(Lazy(Method(_,_,newFormatMethSpec,_,_,_,_))) ->
// The type returned by the 'sprintf' call
let funcTy = EraseClosures.mkILFuncTy cenv.g.ilxPubCloEnv ilThisTy cenv.g.ilg.typ_String
// Give the instantiation of the printf format object, i.e. a Format`5 object compatible with StringFormat<ilThisTy>
@ -6968,7 +7024,7 @@ let defaultOf =
let LookupGeneratedValue (amap:ImportMap) (ctxt: ExecutionContext) eenv (v:Val) =
try
// Convert the v.Type into a System.Type according to ilxgen and ilreflect.
let objTyp =
let objTyp() =
let ilTy = GenType amap v.Range TypeReprEnv.Empty v.Type (* TypeReprEnv.Empty ok, not expecting typars *)
ctxt.LookupType ilTy
// Lookup the compiled v value (as an object).
@ -6986,7 +7042,7 @@ let LookupGeneratedValue (amap:ImportMap) (ctxt: ExecutionContext) eenv (v:Val)
// Rather, we look for the getter MethodInfo from the built type and .Invoke on that.
let methInfo = staticTyp.GetMethod(ilGetterMethRef.Name, BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic)
methInfo.Invoke((null:obj),(null:obj[]))
Some (obj,objTyp)
Some (obj,objTyp())
| StaticProperty (ilGetterMethSpec, _) ->
let obj =
@ -6996,10 +7052,10 @@ let LookupGeneratedValue (amap:ImportMap) (ctxt: ExecutionContext) eenv (v:Val)
// Rather, we look for the getter MethodInfo from the built type and .Invoke on that.
let methInfo = staticTyp.GetMethod(ilGetterMethSpec.Name, BindingFlags.Static ||| BindingFlags.Public ||| BindingFlags.NonPublic)
methInfo.Invoke((null:obj),(null:obj[]))
Some (obj,objTyp)
Some (obj,objTyp())
| Null ->
Some (null,objTyp)
Some (null,objTyp())
| Local _ -> None
| Method _ -> None
| Arg _ -> None

Просмотреть файл

@ -149,7 +149,7 @@ let IsRefusedTLR g (f:Val) =
// things marked ValInline.Never are special
let dllImportStubOrOtherNeverInline = (f.InlineInfo = ValInline.Never)
// Cannot have static fields of byref type
let byrefVal = isByrefLikeTy g f.Type
let byrefVal = isByrefLikeTy g f.Range f.Type
// Special values are instance methods etc. on .NET types. For now leave these alone
let specialVal = f.MemberInfo.IsSome
let alreadyChosen = f.ValReprInfo.IsSome
@ -162,10 +162,9 @@ let IsMandatoryTopLevel (f:Val) =
specialVal || isModulBinding
let IsMandatoryNonTopLevel g (f:Val) =
let byrefVal = isByrefLikeTy g f.Type
let byrefVal = isByrefLikeTy g f.Range f.Type
byrefVal
//-------------------------------------------------------------------------
// pass1: decide which f are to be TLR? and if so, arity(f)
//-------------------------------------------------------------------------
@ -727,7 +726,7 @@ let FlatEnvPacks g fclassM topValS declist (reqdItemsMap: Zmap<BindingGroupShari
// temp
let vals = vals |> List.filter (fun v -> not (isByrefLikeTy g v.Type))
let vals = vals |> List.filter (fun v -> not (isByrefLikeTy g v.Range v.Type))
// Remove values which have been labelled TLR, no need to close over these
let vals = vals |> List.filter (Zset.memberOf topValS >> not)

Просмотреть файл

@ -56,16 +56,18 @@ type CalledArg =
IsParamArray : bool
OptArgInfo : OptionalArgInfo
CallerInfoInfo : CallerInfoInfo
IsInArg: bool
IsOutArg: bool
ReflArgInfo: ReflectedArgInfo
NameOpt: Ident option
CalledArgumentType : TType }
let CalledArg(pos, isParamArray, optArgInfo, callerInfoInfo, isOutArg, nameOpt, reflArgInfo, calledArgTy) =
let CalledArg (pos, isParamArray, optArgInfo, callerInfoInfo, isInArg, isOutArg, nameOpt, reflArgInfo, calledArgTy) =
{ Position=pos
IsParamArray=isParamArray
OptArgInfo =optArgInfo
CallerInfoInfo = callerInfoInfo
IsInArg=isInArg
IsOutArg=isOutArg
ReflArgInfo=reflArgInfo
NameOpt=nameOpt
@ -126,13 +128,24 @@ let AdjustCalledArgType (infoReader:InfoReader) isConstraint (calledArg: CalledA
let calledArgTy = calledArg.CalledArgumentType
let callerArgTy = callerArg.Type
let m = callerArg.Range
if isConstraint then calledArgTy else
// If the called method argument is a byref type, then the caller may provide a byref or ref
if isByrefTy g calledArgTy then
if isConstraint then
calledArgTy
else
// If the called method argument is an inref type, then the caller may provide a byref or value
if isInByrefTy g calledArgTy then
if isByrefTy g callerArgTy then
calledArgTy
else
destByrefTy g calledArgTy
// If the called method argument is a (non inref) byref type, then the caller may provide a byref or ref.
elif isByrefTy g calledArgTy then
if isByrefTy g callerArgTy then
calledArgTy
else
mkRefCellTy g (destByrefTy g calledArgTy)
else
// If the called method argument is a delegate type, then the caller may provide a function
let calledArgTy =
@ -193,11 +206,12 @@ type CalledMethArgSet<'T> =
let MakeCalledArgs amap m (minfo:MethInfo) minst =
// Mark up the arguments with their position, so we can sort them back into order later
let paramDatas = minfo.GetParamDatas(amap, m, minst)
paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg, isOutArg, optArgInfo, callerInfoFlags, nmOpt, reflArgInfo, typeOfCalledArg)) ->
paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfoFlags, nmOpt, reflArgInfo, typeOfCalledArg)) ->
{ Position=(i,j)
IsParamArray=isParamArrayArg
OptArgInfo=optArgInfo
CallerInfoInfo = callerInfoFlags
IsInArg=isInArg
IsOutArg=isOutArg
ReflArgInfo=reflArgInfo
NameOpt=nmOpt
@ -350,6 +364,7 @@ type CalledMeth<'T>
let unnamedCalledOutArgs = argSetInfos |> List.collect (fun (_, _, _, _, _, x) -> x)
member x.infoReader = infoReader
member x.amap = infoReader.amap
/// the method we're attempting to call
@ -372,12 +387,14 @@ type CalledMeth<'T>
/// The argument analysis for each set of curried arguments
member x.ArgSets = argSets
/// return type
member x.ReturnType = methodRetTy
/// return type after implicit deference of byref returns is taken into account
member x.CalledReturnTypeAfterByrefDeref =
let retTy = methodRetTy
if isByrefTy g retTy then destByrefTy g retTy else retTy
/// return type after tupling of out args is taken into account
member x.ReturnTypeAfterOutArgTupling =
let retTy = x.ReturnType
member x.CalledReturnTypeAfterOutArgTupling =
let retTy = x.CalledReturnTypeAfterByrefDeref
if isNil unnamedCalledOutArgs then
retTy
else
@ -408,16 +425,28 @@ type CalledMeth<'T>
member x.NumArgSets = x.ArgSets.Length
member x.HasOptArgs = not (isNil x.UnnamedCalledOptArgs)
member x.HasOutArgs = not (isNil x.UnnamedCalledOutArgs)
member x.UsesParamArrayConversion = x.ArgSets |> List.exists (fun argSet -> argSet.ParamArrayCalledArgOpt.IsSome)
member x.ParamArrayCalledArgOpt = x.ArgSets |> List.tryPick (fun argSet -> argSet.ParamArrayCalledArgOpt)
member x.ParamArrayCallerArgs = x.ArgSets |> List.tryPick (fun argSet -> if Option.isSome argSet.ParamArrayCalledArgOpt then Some argSet.ParamArrayCallerArgs else None )
member x.ParamArrayElementType =
assert (x.UsesParamArrayConversion)
x.ParamArrayCalledArgOpt.Value.CalledArgumentType |> destArrayTy x.amap.g
member x.NumAssignedProps = x.AssignedItemSetters.Length
member x.CalledObjArgTys(m) = x.Method.GetObjArgTypes(x.amap, m, x.CalledTyArgs)
member x.CalledObjArgTys(m) =
match x.Method.GetObjArgTypes(x.amap, m, x.CalledTyArgs) with
| [ thisArgTy ] when isByrefTy g thisArgTy -> [ destByrefTy g thisArgTy ]
| res -> res
member x.NumCalledTyArgs = x.CalledTyArgs.Length
member x.NumCallerTyArgs = x.CallerTyArgs.Length
member x.AssignsAllNamedArgs = isNil x.UnassignedNamedArgs
@ -451,8 +480,11 @@ type CalledMeth<'T>
x.ArgSets |> List.map (fun argSet -> argSet.AssignedNamedArgs)
member x.AllUnnamedCalledArgs = x.ArgSets |> List.collect (fun x -> x.UnnamedCalledArgs)
member x.TotalNumUnnamedCalledArgs = x.ArgSets |> List.sumBy (fun x -> x.NumUnnamedCalledArgs)
member x.TotalNumUnnamedCallerArgs = x.ArgSets |> List.sumBy (fun x -> x.NumUnnamedCallerArgs)
member x.TotalNumAssignedNamedArgs = x.ArgSets |> List.sumBy (fun x -> x.NumAssignedNamedArgs)
let NamesOfCalledArgs (calledArgs: CalledArg list) =
@ -547,15 +579,13 @@ let TakeObjAddrForMethodCall g amap (minfo:MethInfo) isMutable m objArgs f =
match objArgs with
| [objArgExpr] ->
let hasCallInfo = ccallInfo.IsSome
let mustTakeAddress =
(minfo.IsStruct && not minfo.IsExtensionMember) // don't take the address of a struct when passing to an extension member
|| hasCallInfo
let mustTakeAddress = hasCallInfo || minfo.ObjArgNeedsAddress(amap, m)
let objArgTy = tyOfExpr g objArgExpr
let wrap, objArgExpr' = mkExprAddrOfExpr g mustTakeAddress hasCallInfo isMutable objArgExpr None m
let wrap, objArgExpr', _readonly = mkExprAddrOfExpr g mustTakeAddress hasCallInfo isMutable objArgExpr None m
// Extension members and calls to class constraints may need a coercion for their object argument
let objArgExpr' =
if not hasCallInfo && // minfo.IsExtensionMember && minfo.IsStruct &&
if not hasCallInfo &&
not (TypeDefinitelySubsumesTypeNoCoercion 0 g amap m minfo.ApparentEnclosingType objArgTy) then
mkCoerceExpr(objArgExpr', minfo.ApparentEnclosingType, m, objArgTy)
else
@ -1074,7 +1104,7 @@ module ProvidedMethodCalls =
match ea.PApplyOption((function ProvidedAddressOfExpr x -> Some x | _ -> None), m) with
| Some e ->
let eT = exprToExpr e
let wrap, ce = mkExprAddrOfExpr g true false DefinitelyMutates eT None m
let wrap,ce, _readonly = mkExprAddrOfExpr g true false DefinitelyMutates eT None m
let ce = wrap ce
None, (ce, tyOfExpr g ce)
| None ->

Просмотреть файл

@ -467,7 +467,7 @@ let private GetCSharpStyleIndexedExtensionMembersForTyconRef (amap:Import.Import
// So we need to go and crack the type of the 'this' argument.
let thisTy = minfo.GetParamTypes(amap,m,generalizeTypars minfo.FormalMethodTypars).Head.Head
match thisTy with
| AppTy amap.g (tcrefOfTypeExtended, _) -> Some tcrefOfTypeExtended
| AppTy g (tcrefOfTypeExtended, _) when not (isByrefTy g thisTy) -> Some tcrefOfTypeExtended
| _ -> None
Some rs

Просмотреть файл

@ -906,15 +906,28 @@ module private PrintTypes =
| [arg] -> layoutTypeWithInfoAndPrec denv env 2 arg ^^ tcL
| args -> bracketIfL (prec <= 1) (bracketL (layoutTypesWithInfoAndPrec denv env 2 (sepL (tagPunctuation ",")) args) --- tcL)
/// Layout a type, taking precedence into account to insert brackets where needed *)
/// Layout a type, taking precedence into account to insert brackets where needed
and layoutTypeWithInfoAndPrec denv env prec typ =
match stripTyparEqns typ with
// Layout a type application
// Always prefer to format 'byref<ty,ByRefKind.In>' as 'inref<ty>'
| typ when isInByrefTy denv.g typ && (match typ with TType_app (tc, _) when denv.g.inref_tcr.CanDeref && tyconRefEq denv.g tc denv.g.byref2_tcr -> true | _ -> false) ->
layoutTypeWithInfoAndPrec denv env prec (mkInByrefTy denv.g (destByrefTy denv.g typ))
// Always prefer to format 'byref<ty,ByRefKind.Out>' as 'outref<ty>'
| typ when isOutByrefTy denv.g typ && (match typ with TType_app (tc, _) when denv.g.outref_tcr.CanDeref && tyconRefEq denv.g tc denv.g.byref2_tcr -> true | _ -> false) ->
layoutTypeWithInfoAndPrec denv env prec (mkOutByrefTy denv.g (destByrefTy denv.g typ))
// Always prefer to format 'byref<ty,ByRefKind.InOut>' as 'byref<ty>'
| typ when isByrefTy denv.g typ && (match typ with TType_app (tc, _) when denv.g.byref_tcr.CanDeref && tyconRefEq denv.g tc denv.g.byref2_tcr -> true | _ -> false) ->
layoutTypeWithInfoAndPrec denv env prec (mkByrefTy denv.g (destByrefTy denv.g typ))
// Always prefer 'float' to 'float<1>'
| TType_app (tc,args) when tc.IsMeasureableReprTycon && List.forall (isDimensionless denv.g) args ->
layoutTypeWithInfoAndPrec denv env prec (reduceTyconRefMeasureableOrProvided denv.g tc args)
// Layout a type application
| TType_app (tc,args) ->
layoutTypeAppWithInfoAndPrec denv env (layoutTyconRef denv tc) prec tc.IsPrefixDisplay args
@ -1228,7 +1241,7 @@ module InfoMemberPrinting =
/// Format the arguments of a method to a buffer.
///
/// This uses somewhat "old fashioned" printf-style buffer printing.
let layoutParamData denv (ParamData(isParamArray, _isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) =
let layoutParamData denv (ParamData(isParamArray, _isInArg, _isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) =
let isOptArg = optArgInfo.IsOptional
match isParamArray, nmOpt, isOptArg, tryDestOptionTy denv.g pty with
// Layout an optional argument

Просмотреть файл

@ -1248,7 +1248,7 @@ let rec ExprHasEffect g expr =
| Expr.Const _ -> false
/// type applications do not have effects, with the exception of type functions
| Expr.App(f0, _, _, [], _) -> (IsTyFuncValRefExpr f0) || ExprHasEffect g f0
| Expr.Op(op, _, args, _) -> ExprsHaveEffect g args || OpHasEffect g op
| Expr.Op(op, _, args, m) -> ExprsHaveEffect g args || OpHasEffect g m op
| Expr.LetRec(binds, body, _, _) -> BindingsHaveEffect g binds || ExprHasEffect g body
| Expr.Let(bind, body, _, _) -> BindingHasEffect g bind || ExprHasEffect g body
// REVIEW: could add Expr.Obj on an interface type - these are similar to records of lambda expressions
@ -1256,35 +1256,35 @@ let rec ExprHasEffect g expr =
and ExprsHaveEffect g exprs = List.exists (ExprHasEffect g) exprs
and BindingsHaveEffect g binds = List.exists (BindingHasEffect g) binds
and BindingHasEffect g bind = bind.Expr |> ExprHasEffect g
and OpHasEffect g op =
and OpHasEffect g m op =
match op with
| TOp.Tuple _ -> false
| TOp.Recd (ctor, tcref) ->
match ctor with
| RecdExprIsObjInit -> true
| RecdExpr -> isRecdOrUnionOrStructTyconRefDefinitelyMutable g tcref
| TOp.UnionCase ucref -> isRecdOrUnionOrStructTyconRefDefinitelyMutable g ucref.TyconRef
| RecdExpr -> not (isRecdOrStructTyconRefReadOnly g m tcref)
| TOp.UnionCase ucref -> isRecdOrUnionOrStructTyconRefDefinitelyMutable ucref.TyconRef
| TOp.ExnConstr ecref -> isExnDefinitelyMutable ecref
| TOp.Bytes _ | TOp.UInt16s _ | TOp.Array -> true (* alloc observable *)
| TOp.Bytes _ | TOp.UInt16s _ | TOp.Array -> true // mutable
| TOp.UnionCaseTagGet _ -> false
| TOp.UnionCaseProof _ -> false
| TOp.UnionCaseFieldGet (ucref, n) -> isUnionCaseFieldMutable g ucref n
| TOp.ILAsm(instrs, _) -> IlAssemblyCodeHasEffect instrs
| TOp.TupleFieldGet(_) -> false
| TOp.ExnFieldGet(ecref, n) -> isExnFieldMutable ecref n
| TOp.RefAddrGet -> false
| TOp.ValFieldGet rfref -> rfref.RecdField.IsMutable || (TryFindTyconRefBoolAttribute g Range.range0 g.attrib_AllowNullLiteralAttribute rfref.TyconRef = Some(true))
| TOp.ValFieldGetAddr rfref -> rfref.RecdField.IsMutable (* data is immutable, so taking address is ok *)
| TOp.UnionCaseFieldGetAddr _ -> false (* data is immutable, so taking address is ok *)
| TOp.LValueOp (LGetAddr, lv) -> lv.IsMutable
| TOp.RefAddrGet _ -> false
| TOp.ValFieldGet rfref -> rfref.RecdField.IsMutable || (TryFindTyconRefBoolAttribute g Range.range0 g.attrib_AllowNullLiteralAttribute rfref.TyconRef = Some true)
| TOp.ValFieldGetAddr (rfref, _readonly) -> rfref.RecdField.IsMutable
| TOp.UnionCaseFieldGetAddr _ -> false // union case fields are immutable
| TOp.LValueOp (LAddrOf _, lv) -> lv.IsMutable
| TOp.UnionCaseFieldSet _
| TOp.ExnFieldSet _
| TOp.Coerce
| TOp.Reraise
| TOp.For _
| TOp.While _
| TOp.TryCatch _
| TOp.TryFinally _ (* note: these really go through a different path anyway *)
| TOp.TryCatch _ (* conservative *)
| TOp.TryFinally _ (* conservative *)
| TOp.TraitCall _
| TOp.Goto _
| TOp.Label _
@ -1791,17 +1791,17 @@ and OptimizeExprOp cenv env (op, tyargs, args, m) =
MightMakeCriticalTailcall=false
Info=UnknownValue }
(* Handle addresses *)
| TOp.LValueOp (LGetAddr, lv), _, _ ->
| TOp.LValueOp ((LAddrOf _ as lop), lv), _, _ ->
let e, _ = OptimizeExpr cenv env (exprForValRef m lv)
let op' =
match e with
// Do not optimize if it's a top level static binding.
| Expr.Val (v, _, _) when not v.IsCompiledAsTopLevel -> TOp.LValueOp (LGetAddr, v)
| Expr.Val (v, _, _) when not v.IsCompiledAsTopLevel -> TOp.LValueOp (lop, v)
| _ -> op
Expr.Op (op', tyargs, args, m),
{ TotalSize = 1
FunctionSize = 1
HasEffect = OpHasEffect cenv.g op'
HasEffect = OpHasEffect cenv.g m op'
MightMakeCriticalTailcall = false
Info = UnknownValue }
(* Handle these as special cases since mutables are allowed inside their bodies *)
@ -1850,7 +1850,7 @@ and OptimizeExprOpFallback cenv env (op, tyargs, args', m) arginfos valu =
let argsFSize = AddFunctionSizes arginfos
let argEffects = OrEffects arginfos
let argValues = List.map (fun x -> x.Info) arginfos
let effect = OpHasEffect cenv.g op
let effect = OpHasEffect cenv.g m op
let cost, valu =
match op with
| TOp.UnionCase c -> 2, MakeValueInfoForUnionCase c (Array.ofList argValues)
@ -1882,7 +1882,7 @@ and OptimizeExprOpFallback cenv env (op, tyargs, args', m) arginfos valu =
| TOp.ValFieldGetAddr _
| TOp.Array | TOp.For _ | TOp.While _ | TOp.TryCatch _ | TOp.TryFinally _
| TOp.ILCall _ | TOp.TraitCall _ | TOp.LValueOp _ | TOp.ValFieldSet _
| TOp.UnionCaseFieldSet _ | TOp.RefAddrGet | TOp.Coerce | TOp.Reraise
| TOp.UnionCaseFieldSet _ | TOp.RefAddrGet _ | TOp.Coerce | TOp.Reraise
| TOp.UnionCaseFieldGetAddr _
| TOp.ExnFieldSet _ -> 1, valu
| TOp.Recd (ctorInfo, tcref) ->
@ -2277,7 +2277,7 @@ and TakeAddressOfStructArgumentIfNeeded cenv (vref:ValRef) ty args m =
// known calls to known generated F# code for CompareTo, Equals and GetHashCode.
// If we ever reuse DevirtualizeApplication to transform an arbitrary virtual call into a
// direct call then this assumption is not valid.
let wrap, objArgAddress = mkExprAddrOfExpr cenv.g true false NeverMutates objArg None m
let wrap, objArgAddress, _readonly = mkExprAddrOfExpr cenv.g true false NeverMutates objArg None m
wrap, (objArgAddress::rest)
| _ ->
// no wrapper, args stay the same
@ -2760,7 +2760,7 @@ and OptimizeExprThenConsiderSplit cenv env e =
// Decide whether to List.unzip a sub-expression into a new method
//-------------------------------------------------------------------------
and ComputeSplitToMethodCondition flag threshold cenv env (e, einfo) =
and ComputeSplitToMethodCondition flag threshold cenv env (e:Expr, einfo) =
flag &&
// REVIEW: The method splitting optimization is completely disabled if we are not taking tailcalls.
// REVIEW: This should only apply to methods that actually make self-tailcalls (tested further below).
@ -2771,6 +2771,7 @@ and ComputeSplitToMethodCondition flag threshold cenv env (e, einfo) =
// We can only split an expression out as a method if certain conditions are met.
// It can't use any protected or base calls, rethrow(), byrefs etc.
let m = e.Range
(let fvs = freeInExpr CollectLocals e
not fvs.UsesUnboundRethrow &&
not fvs.UsesMethodLocalConstructs &&
@ -2781,12 +2782,12 @@ and ComputeSplitToMethodCondition flag threshold cenv env (e, einfo) =
// All the free variables (apart from things with an arity, i.e. compiled as methods) should be normal, i.e. not base/this etc.
(v.BaseOrThisInfo = NormalVal &&
// None of them should be byrefs
not (isByrefLikeTy cenv.g v.Type) &&
not (isByrefLikeTy cenv.g m v.Type) &&
// None of them should be local polymorphic constrained values
not (IsGenericValWithGenericContraints cenv.g v) &&
// None of them should be mutable
not v.IsMutable)))) &&
not (isByrefLikeTy cenv.g (tyOfExpr cenv.g e))
not (isByrefLikeTy cenv.g m (tyOfExpr cenv.g e))
and ConsiderSplitToMethod flag threshold cenv env (e, einfo) =
if ComputeSplitToMethodCondition flag threshold cenv env (e, einfo) then

Просмотреть файл

@ -904,7 +904,7 @@ let CompilePatternBasic
when isNil topgtvs && ucref.Tycon.IsStructRecordOrUnionTycon ->
let argexp = GetSubExprOfInput subexpr
let vOpt,addrexp = mkExprAddrOfExprAux g true false NeverMutates argexp None matchm
let vOpt, addrexp, _readonly = mkExprAddrOfExprAux g true false NeverMutates argexp None matchm
match vOpt with
| None -> Some addrexp, None
| Some (v,e) ->

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -426,7 +426,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP.
| TOp.UnionCaseFieldGet (ucref,n),tyargs,[e] ->
ConvUnionFieldGet cenv env m ucref n tyargs e
| TOp.ValFieldGetAddr(_rfref),_tyargs,_ ->
| TOp.ValFieldGetAddr(_rfref, _readonly),_tyargs,_ ->
wfail(Error(FSComp.SR.crefQuotationsCantContainAddressOf(), m))
| TOp.UnionCaseFieldGetAddr _,_tyargs,_ ->
@ -518,7 +518,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP.
// rebuild reraise<T>() and Convert
mkReraiseLibCall cenv.g toTy m |> ConvExpr cenv env
| TOp.LValueOp(LGetAddr,vref),[],[] ->
| TOp.LValueOp(LAddrOf _,vref),[],[] ->
QP.mkAddressOf(ConvValRef false cenv env m vref [])
| TOp.LValueOp(LByrefSet,vref),[],[e] ->
@ -586,7 +586,7 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP.
| TOp.UnionCaseTagGet _tycr,_tinst,[_cx] -> wfail(Error(FSComp.SR.crefQuotationsCantFetchUnionIndexes(), m))
| TOp.UnionCaseFieldSet (_c,_i),_tinst,[_cx;_x] -> wfail(Error(FSComp.SR.crefQuotationsCantSetUnionFields(), m))
| TOp.ExnFieldSet(_tcref,_i),[],[_ex;_x] -> wfail(Error(FSComp.SR.crefQuotationsCantSetExceptionFields(), m))
| TOp.RefAddrGet,_,_ -> wfail(Error(FSComp.SR.crefQuotationsCantRequireByref(), m))
| TOp.RefAddrGet _,_,_ -> wfail(Error(FSComp.SR.crefQuotationsCantRequireByref(), m))
| TOp.TraitCall (_ss),_,_ -> wfail(Error(FSComp.SR.crefQuotationsCantCallTraitMembers(), m))
| _ ->
wfail(InternalError( "Unexpected expression shape",m))
@ -665,9 +665,9 @@ and ConvLValueExprCore cenv env expr =
match expr with
| Expr.Op(op,tyargs,args,m) ->
match op, args, tyargs with
| TOp.LValueOp(LGetAddr,vref),_,_ -> ConvValRef false cenv env m vref []
| TOp.ValFieldGetAddr(rfref),_,_ -> ConvClassOrRecdFieldGet cenv env m rfref tyargs args
| TOp.UnionCaseFieldGetAddr(ucref,n),[e],_ -> ConvUnionFieldGet cenv env m ucref n tyargs e
| TOp.LValueOp(LAddrOf _,vref),_,_ -> ConvValRef false cenv env m vref []
| TOp.ValFieldGetAddr(rfref, _),_,_ -> ConvClassOrRecdFieldGet cenv env m rfref tyargs args
| TOp.UnionCaseFieldGetAddr(ucref,n, _),[e],_ -> ConvUnionFieldGet cenv env m ucref n tyargs e
| TOp.ILAsm([ I_ldflda(fspec) ],_rtys),_,_ -> ConvLdfld cenv env m fspec tyargs args
| TOp.ILAsm([ I_ldsflda(fspec) ],_rtys),_,_ -> ConvLdfld cenv env m fspec tyargs args
| TOp.ILAsm(([ I_ldelema(_ro,_isNativePtr,shape,_tyarg) ] ),_), (arr::idxs), [elemty] ->

Просмотреть файл

@ -560,8 +560,45 @@ let tryNormalizeMeasureInType g ty =
// Some basic type builders
//---------------------------------------------------------------------------
let mkNativePtrTy (g:TcGlobals) ty = TType_app (g.nativeptr_tcr, [ty])
let mkByrefTy (g:TcGlobals) ty = TType_app (g.byref_tcr, [ty])
let mkNativePtrTy (g:TcGlobals) ty =
assert g.nativeptr_tcr.CanDeref // this should always be available, but check anyway
TType_app (g.nativeptr_tcr, [ty])
let mkByrefTy (g:TcGlobals) ty =
assert g.byref_tcr.CanDeref // this should always be available, but check anyway
TType_app (g.byref_tcr, [ty])
let mkInByrefTy (g:TcGlobals) ty =
if g.inref_tcr.CanDeref then // If not using sufficient FSharp.Core, then inref<T> = byref<T>, see RFC FS-1053.md
TType_app (g.inref_tcr, [ty])
else
mkByrefTy g ty
let mkOutByrefTy (g:TcGlobals) ty =
if g.outref_tcr.CanDeref then // If not using sufficient FSharp.Core, then outref<T> = byref<T>, see RFC FS-1053.md
TType_app (g.outref_tcr, [ty])
else
mkByrefTy g ty
let mkByrefTyWithFlag g readonly ty =
if readonly then
mkInByrefTy g ty
else
mkByrefTy g ty
let mkByref2Ty (g:TcGlobals) ty1 ty2 =
assert g.byref2_tcr.CanDeref // check we are using sufficient FSharp.Core, caller should check this
TType_app (g.byref2_tcr, [ty1; ty2])
let mkVoidPtrTy (g:TcGlobals) =
assert g.voidptr_tcr.CanDeref // check we are using sufficient FSharp.Core , caller should check this
TType_app (g.voidptr_tcr, [])
let mkByrefTyWithInference (g:TcGlobals) ty1 ty2 =
if g.byref2_tcr.CanDeref then // If not using sufficient FSharp.Core, then inref<T> = byref<T>, see RFC FS-1053.md
TType_app (g.byref2_tcr, [ty1; ty2])
else
TType_app (g.byref_tcr, [ty1])
let mkArrayTy (g:TcGlobals) rank ty m =
if rank < 1 || rank > 32 then
@ -675,7 +712,16 @@ let rec stripTyEqnsA g canShortcut ty =
| Some abbrevTy ->
stripTyEqnsA g canShortcut (applyTyconAbbrev abbrevTy tycon tinst)
| None ->
if tycon.IsMeasureableReprTycon && List.forall (isDimensionless g) tinst then
// This is the point where we get to add additional coditional normalizing equations
// into the type system. Such power!
//
// Add the equation byref<'T> = byref<'T, ByRefKinds.InOut> for when using sufficient FSharp.Core
// See RFC FS-1053.md
if tyconRefEq g tcref g.byref_tcr && g.byref2_tcr.CanDeref && g.byrefkind_InOut_tcr.CanDeref then
mkByref2Ty g tinst.[0] (TType_app(g.byrefkind_InOut_tcr, []))
// Add the equation double<1> = double for units of measure.
elif tycon.IsMeasureableReprTycon && List.forall (isDimensionless g) tinst then
stripTyEqnsA g canShortcut (reduceTyconMeasureableOrProvided g tycon tinst)
else
ty
@ -782,11 +828,6 @@ let (|StripNullableTy|) g ty =
| AppTy g (tcr, [tyarg]) when tyconRefEq g tcr g.system_Nullable_tcref -> tyarg
| _ -> ty
let (|ByrefTy|_|) g ty =
match ty with
| AppTy g (tcr, [tyarg]) when tyconRefEq g tcr g.byref_tcr -> Some tyarg
| _ -> None
let mkInstForAppTy g typ =
match typ with
| AppTy g (tcref, tinst) -> mkTyconRefInst tcref tinst
@ -1231,13 +1272,14 @@ let mkExnExpr(uc, args, m) = Expr.Op (TOp.ExnConstr uc,
let mkTupleFieldGetViaExprAddr(tupInfo, e, tinst, i, m) = Expr.Op (TOp.TupleFieldGet(tupInfo, i), tinst, [e], m)
let mkRecdFieldGetViaExprAddr(e, fref, tinst, m) = Expr.Op (TOp.ValFieldGet(fref), tinst, [e], m)
let mkRecdFieldGetAddrViaExprAddr(e, fref, tinst, m) = Expr.Op (TOp.ValFieldGetAddr(fref), tinst, [e], m)
let mkRecdFieldGetAddrViaExprAddr(readonly, e, fref, tinst, m) = Expr.Op (TOp.ValFieldGetAddr(fref, readonly), tinst, [e], m)
let mkStaticRecdFieldGetAddr(fref, tinst, m) = Expr.Op (TOp.ValFieldGetAddr(fref), tinst, [], m)
let mkStaticRecdFieldGetAddr(readonly, fref, tinst, m) = Expr.Op (TOp.ValFieldGetAddr(fref, readonly), tinst, [], m)
let mkStaticRecdFieldGet(fref, tinst, m) = Expr.Op (TOp.ValFieldGet(fref), tinst, [], m)
let mkStaticRecdFieldSet(fref, tinst, e, m) = Expr.Op (TOp.ValFieldSet(fref), tinst, [e], m)
let mkArrayElemAddress g (readonly, isNativePtr, shape, elemTy, aexpr, nexpr, m) = Expr.Op (TOp.ILAsm ([IL.I_ldelema(readonly, isNativePtr, shape, mkILTyvarTy 0us)], [mkByrefTy g elemTy]), [elemTy], [aexpr;nexpr], m)
let mkArrayElemAddress g (readonly, ilInstrReadOnlyAnnotation, isNativePtr, shape, elemTy, exprs, m) =
Expr.Op (TOp.ILAsm ([IL.I_ldelema(ilInstrReadOnlyAnnotation, isNativePtr, shape, mkILTyvarTy 0us)], [mkByrefTyWithFlag g readonly elemTy]), [elemTy], exprs, m)
let mkRecdFieldSetViaExprAddr (e1, fref, tinst, e2, m) = Expr.Op (TOp.ValFieldSet(fref), tinst, [e1;e2], m)
@ -1254,7 +1296,7 @@ let mkUnionCaseFieldGetProvenViaExprAddr (e1, cref, tinst, j, m) = Expr.Op (TO
/// Build a 'TOp.UnionCaseFieldGetAddr' expression for a field of a union when we've already determined the value to be a particular union case. For ref-unions,
/// the input expression has 'TType_ucase', which is an F# compiler internal "type" corresponding to the union case. For struct-unions,
/// the input should be the address of the expression.
let mkUnionCaseFieldGetAddrProvenViaExprAddr (e1, cref, tinst, j, m) = Expr.Op (TOp.UnionCaseFieldGetAddr(cref, j), tinst, [e1], m)
let mkUnionCaseFieldGetAddrProvenViaExprAddr (readonly, e1, cref, tinst, j, m) = Expr.Op (TOp.UnionCaseFieldGetAddr(cref, j, readonly), tinst, [e1], m)
/// Build a 'get' expression for something we've already determined to be a particular union case, but where
/// the static type of the input is not yet proven to be that particular union case. This requires a type
@ -1287,7 +1329,7 @@ let mkDefault (m, ty) = Expr.Const(Const.Zero, m, ty)
let mkValSet m v e = Expr.Op (TOp.LValueOp (LSet, v), [], [e], m)
let mkAddrSet m v e = Expr.Op (TOp.LValueOp (LByrefSet, v), [], [e], m)
let mkAddrGet m v = Expr.Op (TOp.LValueOp (LByrefGet, v), [], [], m)
let mkValAddr m v = Expr.Op (TOp.LValueOp (LGetAddr, v), [], [], m)
let mkValAddr m readonly v = Expr.Op (TOp.LValueOp (LAddrOf readonly, v), [], [], m)
//--------------------------------------------------------------------------
// Maps tracking extra information for values
@ -1315,14 +1357,21 @@ type ValHash<'T> =
[<Struct; NoEquality; NoComparison>]
type ValMultiMap<'T>(contents: StampMap<'T list>) =
member m.ContainsKey (v: Val) =
contents.ContainsKey v.Stamp
member m.Find (v: Val) =
match contents |> Map.tryFind v.Stamp with
| Some vals -> vals
| _ -> []
member m.Add (v:Val, x) = ValMultiMap<'T>(contents.Add (v.Stamp, x :: m.Find v))
member m.Remove (v: Val) = ValMultiMap<'T>(contents.Remove v.Stamp)
member m.Contents = contents
static member Empty = ValMultiMap<'T>(Map.empty)
[<Struct; NoEquality; NoComparison>]
@ -1529,17 +1578,11 @@ let destListTy (g:TcGlobals) ty =
| AppTy g (tcref, [ty]) when tyconRefEq g tcref g.list_tcr_canon -> ty
| _ -> failwith "destListTy"
let isTypeConstructorEqualToOptional g tcOpt tc =
let tyconRefEqOpt g tcOpt tc =
match tcOpt with
| None -> false
| Some tc2 -> tyconRefEq g tc2 tc
let isByrefLikeTyconRef g tcref =
tyconRefEq g g.byref_tcr tcref ||
isTypeConstructorEqualToOptional g g.system_TypedReference_tcref tcref ||
isTypeConstructorEqualToOptional g g.system_ArgIterator_tcref tcref ||
isTypeConstructorEqualToOptional g g.system_RuntimeArgumentHandle_tcref tcref
let isStringTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tyconRefEq g tcref g.system_String_tcref | _ -> false)
let isListTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tyconRefEq g tcref g.list_tcr_canon | _ -> false)
let isArrayTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> isArrayTyconRef g tcref | _ -> false)
@ -1549,8 +1592,25 @@ let isObjTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) ->
let isVoidTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tyconRefEq g g.system_Void_tcref tcref | _ -> false)
let isILAppTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.IsILTycon | _ -> false)
let isNativePtrTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tyconRefEq g g.nativeptr_tcr tcref | _ -> false)
let isByrefTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tyconRefEq g g.byref_tcr tcref | _ -> false)
let isByrefLikeTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> isByrefLikeTyconRef g tcref | _ -> false)
let isByrefTy g ty =
ty |> stripTyEqns g |> (function
| TType_app(tcref, _) when g.byref2_tcr.CanDeref -> tyconRefEq g g.byref2_tcr tcref
| TType_app(tcref, _) -> tyconRefEq g g.byref_tcr tcref
| _ -> false)
let isInByrefTag g ty = ty |> stripTyEqns g |> (function TType_app(tcref, []) -> tyconRefEq g g.byrefkind_In_tcr tcref | _ -> false)
let isInByrefTy g ty =
ty |> stripTyEqns g |> (function
| TType_app(tcref, [_; tag]) when g.byref2_tcr.CanDeref -> tyconRefEq g g.byref2_tcr tcref && isInByrefTag g tag
| _ -> false)
let isOutByrefTag g ty = ty |> stripTyEqns g |> (function TType_app(tcref, []) -> tyconRefEq g g.byrefkind_Out_tcr tcref | _ -> false)
let isOutByrefTy g ty =
ty |> stripTyEqns g |> (function
| TType_app(tcref, [_; tag]) when g.byref2_tcr.CanDeref -> tyconRefEq g g.byref2_tcr tcref && isOutByrefTag g tag
| _ -> false)
#if !NO_EXTENSIONTYPING
let extensionInfoOfTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tcref.TypeReprInfo | _ -> TNoRepr)
#endif
@ -2754,7 +2814,7 @@ let isILAttribByName (tencl:string list, tname: string) (attr: ILAttribute) =
(attr.Method.DeclaringType.TypeSpec.Name = tname) &&
(attr.Method.DeclaringType.TypeSpec.Enclosing = tencl)
// AbsIL view of attributes (we read these from .NET binaries)
// AbsIL view of attributes (we read these from .NET binaries). The comparison is done by name.
let isILAttrib (tref:ILTypeRef) (attr: ILAttribute) =
isILAttribByName (tref.Enclosing, tref.Name) attr
@ -2762,18 +2822,12 @@ let isILAttrib (tref:ILTypeRef) (attr: ILAttribute) =
// These linear iterations cost us a fair bit when there are lots of attributes
// on imported types. However this is fairly rare and can also be solved by caching the
// results of attribute lookups in the TAST
let HasILAttribute tref (attrs: ILAttributes) = Array.exists (isILAttrib tref) attrs.AsArray
let HasILAttributeByName tname (attrs: ILAttributes) = Array.exists (isILAttribByName ([], tname)) attrs.AsArray
let HasILAttribute tref (attrs: ILAttributes) =
attrs.AsArray |> Array.exists (isILAttrib tref)
let TryDecodeILAttribute (g:TcGlobals) tref (attrs: ILAttributes) =
attrs.AsArray |> Array.tryPick (fun x -> if isILAttrib tref x then Some(decodeILAttribData g.ilg x) else None)
// This one is done by name to ensure the compiler doesn't take a dependency on dereferencing a type that only exists in .NET 3.5
let ILThingHasExtensionAttribute (attrs : ILAttributes) =
attrs.AsArray
|> Array.exists (fun attr -> attr.Method.DeclaringType.TypeSpec.Name = "System.Runtime.CompilerServices.ExtensionAttribute")
// F# view of attributes (these get converted to AbsIL attributes in ilxgen)
let IsMatchingFSharpAttribute g (AttribInfo(_, tcref)) (Attrib(tcref2, _, _, _, _, _, _)) = tyconRefEq g tcref tcref2
let HasFSharpAttribute g tref attrs = List.exists (IsMatchingFSharpAttribute g tref) attrs
@ -2881,15 +2935,44 @@ let TyconRefHasAttribute g m attribSpec tcref =
(fun _ -> Some ())
|> Option.isSome
let isByrefTyconRef (g: TcGlobals) (tcref: TyconRef) =
(g.byref_tcr.CanDeref && tyconRefEq g g.byref_tcr tcref) ||
(g.byref2_tcr.CanDeref && tyconRefEq g g.byref2_tcr tcref) ||
(g.inref_tcr.CanDeref && tyconRefEq g g.inref_tcr tcref) ||
(g.outref_tcr.CanDeref && tyconRefEq g g.outref_tcr tcref) ||
tyconRefEqOpt g g.system_TypedReference_tcref tcref ||
tyconRefEqOpt g g.system_ArgIterator_tcref tcref ||
tyconRefEqOpt g g.system_RuntimeArgumentHandle_tcref tcref
// See RFC FS-1053.md
let isByrefLikeTyconRef (g: TcGlobals) m (tcref: TyconRef) =
tcref.CanDeref &&
match tcref.TryIsByRefLike with
| Some res -> res
| None ->
let res =
isByrefTyconRef g tcref ||
TyconRefHasAttribute g m g.attrib_IsByRefLikeAttribute tcref
tcref.SetIsByRefLike res
res
let isByrefLikeTy g m ty =
ty |> stripTyEqns g |> (function TType_app(tcref, _) -> isByrefLikeTyconRef g m tcref | _ -> false)
//-------------------------------------------------------------------------
// List and reference types...
//-------------------------------------------------------------------------
let destByrefTy g ty =
match ty |> stripTyEqns g with
| TType_app(tcref, [x]) when tyconRefEq g g.byref_tcr tcref -> x
| TType_app(tcref, [x; _]) when g.byref2_tcr.CanDeref && tyconRefEq g g.byref2_tcr tcref -> x // Check sufficient FSharp.Core
| TType_app(tcref, [x]) when tyconRefEq g g.byref_tcr tcref -> x // all others
| _ -> failwith "destByrefTy: not a byref type"
let (|ByrefTy|_|) g ty =
// Because of byref = byref2<ty,tags> it is better to write this using is/dest
if isByrefTy g ty then Some (destByrefTy g ty) else None
let destNativePtrTy g ty =
match ty |> stripTyEqns g with
| TType_app(tcref, [x]) when tyconRefEq g g.nativeptr_tcr tcref -> x
@ -3062,7 +3145,7 @@ module DebugPrint = begin
let lvalopL x =
match x with
| LGetAddr -> wordL (tagText "LGetAddr")
| LAddrOf readonly -> wordL (tagText (sprintf "LAddrOf(%b)" readonly))
| LByrefGet -> wordL (tagText "LByrefGet")
| LSet -> wordL (tagText "LSet")
| LByrefSet -> wordL (tagText "LByrefSet")
@ -3539,9 +3622,9 @@ module DebugPrint = begin
(atomL rx ^^ rightL(tagText ".#") ^^ recdFieldRefL rf)
| Expr.Op (TOp.ValFieldGet rf, _, [], _) ->
recdFieldRefL rf
| Expr.Op (TOp.ValFieldGetAddr rf, _, [rx], _) ->
| Expr.Op (TOp.ValFieldGetAddr (rf, _), _, [rx], _) ->
leftL(tagText "&") ^^ bracketL (atomL rx ^^ rightL(tagText ".!") ^^ recdFieldRefL rf)
| Expr.Op (TOp.ValFieldGetAddr rf, _, [], _) ->
| Expr.Op (TOp.ValFieldGetAddr (rf, _), _, [], _) ->
leftL(tagText "&") ^^ (recdFieldRefL rf)
| Expr.Op (TOp.UnionCaseTagGet tycr, _, [x], _) ->
wordL (tagText ("#" + tycr.LogicalName + ".tag")) ^^ atomL x
@ -3584,7 +3667,7 @@ module DebugPrint = begin
| Expr.Op (TOp.Bytes _, _ , _ , _) ->
wordL(tagText "bytes++")
| Expr.Op (TOp.UInt16s _, _ , _ , _) -> wordL(tagText "uint16++")
| Expr.Op (TOp.RefAddrGet, _tyargs, _args, _) -> wordL(tagText "GetRefLVal...")
| Expr.Op (TOp.RefAddrGet _, _tyargs, _args, _) -> wordL(tagText "GetRefLVal...")
| Expr.Op (TOp.TraitCall _, _tyargs, _args, _) -> wordL(tagText "traitcall...")
| Expr.Op (TOp.ExnFieldGet _, _tyargs, _args, _) -> wordL(tagText "TOp.ExnFieldGet...")
| Expr.Op (TOp.ExnFieldSet _, _tyargs, _args, _) -> wordL(tagText "TOp.ExnFieldSet...")
@ -4307,7 +4390,7 @@ and accFreeInOp opts op acc =
| TOp.TryFinally _
| TOp.For _
| TOp.Coerce
| TOp.RefAddrGet
| TOp.RefAddrGet _
| TOp.Array
| TOp.While _
| TOp.Goto _ | TOp.Label _ | TOp.Return
@ -4320,7 +4403,7 @@ and accFreeInOp opts op acc =
// Things containing just a union case reference
| TOp.UnionCaseProof cr
| TOp.UnionCase cr
| TOp.UnionCaseFieldGetAddr (cr, _)
| TOp.UnionCaseFieldGetAddr (cr, _, _)
| TOp.UnionCaseFieldGet (cr, _)
| TOp.UnionCaseFieldSet (cr, _) -> accFreeUnionCaseRef opts cr acc
@ -4330,7 +4413,7 @@ and accFreeInOp opts op acc =
| TOp.ExnFieldSet (ecr, _) -> accFreeExnRef ecr acc
| TOp.ValFieldGet fr
| TOp.ValFieldGetAddr fr
| TOp.ValFieldGetAddr (fr, _)
| TOp.ValFieldSet fr -> accFreeRecdFieldRef opts fr acc
| TOp.Recd (kind, tcr) ->
@ -4756,23 +4839,23 @@ and remapExpr (g: TcGlobals) (compgen:ValCopyFlag) (tmenv:Remap) x =
// of a temporary local, e.g.
// &(E.RF) --> let mutable v = E.RF in &v
| Expr.Op (TOp.ValFieldGetAddr rfref, tinst, [arg], m) when
| Expr.Op (TOp.ValFieldGetAddr (rfref, readonly), tinst, [arg], m) when
not rfref.RecdField.IsMutable &&
not (entityRefInThisAssembly g.compilingFslib rfref.TyconRef) ->
let tinst = remapTypes tmenv tinst
let arg = remapExpr g compgen tmenv arg
let tmp, _ = mkMutableCompGenLocal m "copyOfStruct" (actualTyOfRecdFieldRef rfref tinst)
mkCompGenLet m tmp (mkRecdFieldGetViaExprAddr(arg, rfref, tinst, m)) (mkValAddr m (mkLocalValRef tmp))
mkCompGenLet m tmp (mkRecdFieldGetViaExprAddr(arg, rfref, tinst, m)) (mkValAddr m readonly (mkLocalValRef tmp))
| Expr.Op (TOp.UnionCaseFieldGetAddr (uref, cidx), tinst, [arg], m) when
| Expr.Op (TOp.UnionCaseFieldGetAddr (uref, cidx, readonly), tinst, [arg], m) when
not (uref.FieldByIndex(cidx).IsMutable) &&
not (entityRefInThisAssembly g.compilingFslib uref.TyconRef) ->
let tinst = remapTypes tmenv tinst
let arg = remapExpr g compgen tmenv arg
let tmp, _ = mkMutableCompGenLocal m "copyOfStruct" (actualTyOfUnionFieldRef uref cidx tinst)
mkCompGenLet m tmp (mkUnionCaseFieldGetProvenViaExprAddr(arg, uref, tinst, cidx, m)) (mkValAddr m (mkLocalValRef tmp))
mkCompGenLet m tmp (mkUnionCaseFieldGetProvenViaExprAddr(arg, uref, tinst, cidx, m)) (mkValAddr m readonly (mkLocalValRef tmp))
| Expr.Op (op, tinst, args, m) ->
let op' = remapOp tmenv op
@ -4842,8 +4925,9 @@ and remapOp tmenv op =
| TOp.ExnFieldSet(ec, n) -> TOp.ExnFieldSet(remapTyconRef tmenv.tyconRefRemap ec, n)
| TOp.ValFieldSet rfref -> TOp.ValFieldSet(remapRecdFieldRef tmenv.tyconRefRemap rfref)
| TOp.ValFieldGet rfref -> TOp.ValFieldGet(remapRecdFieldRef tmenv.tyconRefRemap rfref)
| TOp.ValFieldGetAddr rfref -> TOp.ValFieldGetAddr(remapRecdFieldRef tmenv.tyconRefRemap rfref)
| TOp.ValFieldGetAddr (rfref, readonly) -> TOp.ValFieldGetAddr(remapRecdFieldRef tmenv.tyconRefRemap rfref, readonly)
| TOp.UnionCaseFieldGet(ucref, n) -> TOp.UnionCaseFieldGet(remapUnionCaseRef tmenv.tyconRefRemap ucref, n)
| TOp.UnionCaseFieldGetAddr(ucref, n, readonly) -> TOp.UnionCaseFieldGetAddr(remapUnionCaseRef tmenv.tyconRefRemap ucref, n, readonly)
| TOp.UnionCaseFieldSet(ucref, n) -> TOp.UnionCaseFieldSet(remapUnionCaseRef tmenv.tyconRefRemap ucref, n)
| TOp.ILAsm (instrs, tys) ->
let tys2 = remapTypes tmenv tys
@ -5236,16 +5320,17 @@ let isUnionCaseDefinitelyMutable (uc:UnionCase) = uc.FieldTable.FieldsByIndex |>
let isUnionCaseRefDefinitelyMutable (uc:UnionCaseRef) = uc.UnionCase |> isUnionCaseDefinitelyMutable
/// This is an incomplete check for .NET struct types. Returning 'false' doesn't mean the thing is immutable.
let isRecdOrUnionOrStructTyconDefinitelyMutable (_g:TcGlobals) (tycon:Tycon) =
let isRecdOrUnionOrStructTyconRefDefinitelyMutable (tcref: TyconRef) =
let tycon = tcref.Deref
if tycon.IsUnionTycon then
tycon.UnionCasesArray |> Array.exists isUnionCaseDefinitelyMutable
elif tycon.IsRecordTycon || tycon.IsStructOrEnumTycon then
// Note: This only looks at the F# fields, causing oddities.
// See https://github.com/Microsoft/visualfsharp/pull/4576
tycon.AllFieldsArray |> Array.exists isRecdOrStructFieldDefinitelyMutable
else
false
let isRecdOrUnionOrStructTyconRefDefinitelyMutable g (tcr : TyconRef) = isRecdOrUnionOrStructTyconDefinitelyMutable g tcr.Deref
// Although from the pure F# perspective exception values cannot be changed, the .NET
// implementation of exception objects attaches a whole bunch of stack information to
// each raised object. Hence we treat exception objects as if they have identity
@ -5255,7 +5340,7 @@ let isExnDefinitelyMutable (_ecref:TyconRef) = true
// of the cons cell. These cells are always private, i.e. not accessible by any other
// code until the construction of the entire return list has been completed.
// However, within the implementation code reads of the tail cell must in theory be treated
// with caution. Hence we are conservative and within fslib we don't treat list
// with caution. Hence we are conservative and within FSharp.Core we don't treat list
// reads as if they were pure.
let isUnionCaseFieldMutable (g: TcGlobals) (ucref:UnionCaseRef) n =
(g.compilingFslib && tyconRefEq g ucref.TyconRef g.list_tcr_canon && n = 1) ||
@ -5331,16 +5416,16 @@ let rec tyOfExpr g e =
| (TOp.For _ | TOp.While _) -> g.unit_ty
| TOp.Array -> (match tinst with [ty] -> mkArrayType g ty | _ -> failwith "bad TOp.Array node")
| (TOp.TryCatch _ | TOp.TryFinally _) -> (match tinst with [ty] -> ty | _ -> failwith "bad TOp_try node")
| TOp.ValFieldGetAddr(fref) -> mkByrefTy g (actualTyOfRecdFieldRef fref tinst)
| TOp.ValFieldGetAddr(fref, readonly) -> mkByrefTyWithFlag g readonly (actualTyOfRecdFieldRef fref tinst)
| TOp.ValFieldGet(fref) -> actualTyOfRecdFieldRef fref tinst
| (TOp.ValFieldSet _ | TOp.UnionCaseFieldSet _ | TOp.ExnFieldSet _ | TOp.LValueOp ((LSet | LByrefSet), _)) ->g.unit_ty
| TOp.UnionCaseTagGet _ -> g.int_ty
| TOp.UnionCaseFieldGetAddr(cref, j) -> mkByrefTy g (actualTyOfRecdField (mkTyconRefInst cref.TyconRef tinst) (cref.FieldByIndex j))
| TOp.UnionCaseFieldGetAddr(cref, j, readonly) -> mkByrefTyWithFlag g readonly (actualTyOfRecdField (mkTyconRefInst cref.TyconRef tinst) (cref.FieldByIndex j))
| TOp.UnionCaseFieldGet(cref, j) -> actualTyOfRecdField (mkTyconRefInst cref.TyconRef tinst) (cref.FieldByIndex j)
| TOp.ExnFieldGet(ecref, j) -> recdFieldTyOfExnDefRefByIdx ecref j
| TOp.LValueOp (LByrefGet, v) -> destByrefTy g v.Type
| TOp.LValueOp (LGetAddr, v) -> mkByrefTy g v.Type
| TOp.RefAddrGet -> (match tinst with [ty] -> mkByrefTy g ty | _ -> failwith "bad TOp.RefAddrGet node")
| TOp.LValueOp (LAddrOf readonly, v) -> mkByrefTyWithFlag g readonly v.Type
| TOp.RefAddrGet readonly -> (match tinst with [ty] -> mkByrefTyWithFlag g readonly ty | _ -> failwith "bad TOp.RefAddrGet node")
| TOp.TraitCall (TTrait(_, _, _, _, ty, _)) -> GetFSharpViewOfReturnType g ty
| TOp.Reraise -> (match tinst with [rtn_ty] -> rtn_ty | _ -> failwith "bad TOp.Reraise node")
| TOp.Goto _ | TOp.Label _ | TOp.Return ->
@ -5565,17 +5650,39 @@ let mkAndSimplifyMatch spBind exprm matchm ty tree targets =
// mkExprAddrOfExprAux
//-------------------------------------------------------------------------
type Mutates = DefinitelyMutates | PossiblyMutates | NeverMutates
type Mutates = AddressOfOp | DefinitelyMutates | PossiblyMutates | NeverMutates
exception DefensiveCopyWarning of string * range
let isRecdOrStructTyReadOnly g ty =
match tryDestAppTy g ty with
| None -> false
| Some tcref ->
not (isRecdOrUnionOrStructTyconRefDefinitelyMutable g tcref) ||
let isRecdOrStructTyconRefAssumedImmutable (g: TcGlobals) (tcref: TyconRef) =
tcref.CanDeref &&
not (isRecdOrUnionOrStructTyconRefDefinitelyMutable tcref) ||
tyconRefEq g tcref g.decimal_tcr ||
tyconRefEq g tcref g.date_tcr
let isRecdOrStructTyconRefReadOnly (g: TcGlobals) m (tcref: TyconRef) =
tcref.CanDeref &&
match tcref.TryIsReadOnly with
| Some res -> res
| None ->
let isImmutable = isRecdOrStructTyconRefAssumedImmutable g tcref
let hasAttrib = TyconRefHasAttribute g m g.attrib_IsReadOnlyAttribute tcref
let res = isImmutable || hasAttrib
tcref.SetIsReadOnly res
res
let isRecdOrStructTyReadOnly (g: TcGlobals) m ty =
match tryDestAppTy g ty with
| None -> false
| Some tcref -> isRecdOrStructTyconRefReadOnly g m tcref
let CanTakeAddressOf g m typ mut =
match mut with
| NeverMutates -> true
| PossiblyMutates -> isRecdOrStructTyReadOnly g m typ
| DefinitelyMutates -> false
| AddressOfOp -> true // you can take the address but you might get a (readonly) inref<T> as a result
// We can take the address of values of struct type even if the value is immutable
// under certain conditions
// - all instances of the type are known to be immutable; OR
@ -5591,144 +5698,184 @@ let isRecdOrStructTyReadOnly g ty =
//
// We only do this for true local or closure fields because we can't take addresses of immutable static
// fields across assemblies.
let CanTakeAddressOfImmutableVal g (v:ValRef) mut =
let CanTakeAddressOfImmutableVal (g: TcGlobals) m (vref:ValRef) mut =
// We can take the address of values of struct type if the operation doesn't mutate
// and the value is a true local or closure field.
not v.IsMutable &&
not v.IsMemberOrModuleBinding &&
(match mut with
| NeverMutates -> true
| PossiblyMutates -> isRecdOrStructTyReadOnly g v.Type
| DefinitelyMutates -> false)
not vref.IsMutable &&
not vref.IsMemberOrModuleBinding &&
// Note: We can't add this:
// || valRefInThisAssembly g.compilingFslib vref
// This is because we don't actually guarantee to generate static backing fields for all values like these, e.g. simple constants "let x = 1".
// We always generate a static property but there is no field to take an address of
CanTakeAddressOf g m vref.Type mut
let MustTakeAddressOfVal (g:TcGlobals) (v:ValRef) =
v.IsMutable &&
let MustTakeAddressOfVal (g:TcGlobals) (vref:ValRef) =
vref.IsMutable &&
// We can only take the address of mutable values in the same assembly
valRefInThisAssembly g.compilingFslib v
valRefInThisAssembly g.compilingFslib vref
let MustTakeAddressOfRecdField (rf: RecdField) =
let MustTakeAddressOfByrefGet (g:TcGlobals) (vref:ValRef) =
isByrefTy g vref.Type && not (isInByrefTy g vref.Type)
let CanTakeAddressOfByrefGet (g:TcGlobals) (vref:ValRef) mut =
isInByrefTy g vref.Type &&
CanTakeAddressOf g vref.Range (destByrefTy g vref.Type) mut
let MustTakeAddressOfRecdField (rfref: RecdField) =
// Static mutable fields must be private, hence we don't have to take their address
not rf.IsStatic &&
rf.IsMutable
not rfref.IsStatic &&
rfref.IsMutable
let MustTakeAddressOfRecdFieldRef (rfref: RecdFieldRef) = MustTakeAddressOfRecdField rfref.RecdField
let CanTakeAddressOfRecdFieldRef (g:TcGlobals) (rfref: RecdFieldRef) mut tinst =
mut <> DefinitelyMutates &&
let CanTakeAddressOfRecdFieldRef (g:TcGlobals) m (rfref: RecdFieldRef) tinst mut =
// We only do this if the field is defined in this assembly because we can't take addresses across assemblies for immutable fields
entityRefInThisAssembly g.compilingFslib rfref.TyconRef &&
isRecdOrStructTyReadOnly g (actualTyOfRecdFieldRef rfref tinst)
not rfref.RecdField.IsMutable &&
CanTakeAddressOf g m (actualTyOfRecdFieldRef rfref tinst) mut
let CanTakeAddressOfUnionFieldRef (g:TcGlobals) (uref: UnionCaseRef) mut tinst cidx =
mut <> DefinitelyMutates &&
let CanTakeAddressOfUnionFieldRef (g:TcGlobals) m (uref: UnionCaseRef) cidx tinst mut =
// We only do this if the field is defined in this assembly because we can't take addresses across assemblies for immutable fields
entityRefInThisAssembly g.compilingFslib uref.TyconRef &&
isRecdOrStructTyReadOnly g (actualTyOfUnionFieldRef uref cidx tinst)
let rfref = uref.FieldByIndex cidx
not rfref.IsMutable &&
CanTakeAddressOf g m (actualTyOfUnionFieldRef uref cidx tinst) mut
/// Make the address-of expression and return a wrapper that adds any allocated locals at an appropriate scope.
/// Also return a flag that indicates if the resulting pointer is a not a pointer where writing is allowed and will
/// have intended effect (i.e. is a readonly pointer and/or a defensive copy).
let rec mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress mut expr addrExprVal m =
if mustTakeAddress then
match expr with
// LVALUE of "*x" where "x" is byref is just the byref itself
| Expr.Op (TOp.LValueOp (LByrefGet, vref), _, [], m) when MustTakeAddressOfByrefGet g vref || CanTakeAddressOfByrefGet g vref mut ->
let readonly = not (MustTakeAddressOfByrefGet g vref)
None, exprForValRef m vref, readonly
let rec mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m =
if not mustTakeAddress then None, e else
match e with
// LVALUE: "x" where "x" is byref
| Expr.Op (TOp.LValueOp (LByrefGet, v), _, [], m) ->
None, exprForValRef m v
// LVALUE: "x" where "x" is mutable local, mutable intra-assembly module/static binding, or operation doesn't mutate
// Note: we can always take the address of mutable values
| Expr.Val(v, _, m) when MustTakeAddressOfVal g v || CanTakeAddressOfImmutableVal g v mut ->
None, mkValAddr m v
// LVALUE: "x" where "e.x" is record field.
| Expr.Op (TOp.ValFieldGet rfref, tinst, [e], m) when MustTakeAddressOfRecdFieldRef rfref || CanTakeAddressOfRecdFieldRef g rfref mut tinst ->
let exprty = tyOfExpr g e
let wrap, expra = mkExprAddrOfExprAux g (isStructTy g exprty) false mut e None m
wrap, mkRecdFieldGetAddrViaExprAddr(expra, rfref, tinst, m)
// LVALUE: "x" where "e.x" is union field
| Expr.Op (TOp.UnionCaseFieldGet (uref, cidx), tinst, [e], m) when MustTakeAddressOfRecdField (uref.FieldByIndex(cidx)) || CanTakeAddressOfUnionFieldRef g uref mut tinst cidx ->
let exprty = tyOfExpr g e
let wrap, expra = mkExprAddrOfExprAux g (isStructTy g exprty) false mut e None m
wrap, mkUnionCaseFieldGetAddrProvenViaExprAddr(expra, uref, tinst, cidx, m)
// LVALUE of "x" where "x" is mutable local, mutable intra-assembly module/static binding, or operation doesn't mutate.
// Note: we can always take the address of mutable intra-assembly values
| Expr.Val(vref, _, m) when MustTakeAddressOfVal g vref || CanTakeAddressOfImmutableVal g m vref mut ->
let readonly = not (MustTakeAddressOfVal g vref)
None, mkValAddr m readonly vref, readonly
// LVALUE: "x" where "e.x" is a .NET static field.
// LVALUE of "e.f" where "f" is record field.
| Expr.Op (TOp.ValFieldGet rfref, tinst, [obje], m) when MustTakeAddressOfRecdFieldRef rfref || CanTakeAddressOfRecdFieldRef g m rfref tinst mut ->
let exprty = tyOfExpr g obje
let wrap, expra, readonly = mkExprAddrOfExprAux g (isStructTy g exprty) false mut obje None m
let readonly = readonly || not (MustTakeAddressOfRecdFieldRef rfref)
wrap, mkRecdFieldGetAddrViaExprAddr(readonly, expra, rfref, tinst, m), readonly
// LVALUE of "e.f" where "f" is union field.
| Expr.Op (TOp.UnionCaseFieldGet (uref, cidx), tinst, [obje], m) when MustTakeAddressOfRecdField (uref.FieldByIndex(cidx)) || CanTakeAddressOfUnionFieldRef g m uref cidx tinst mut ->
let exprty = tyOfExpr g obje
let wrap, expra, readonly = mkExprAddrOfExprAux g (isStructTy g exprty) false mut obje None m
let readonly = readonly || not (MustTakeAddressOfRecdField (uref.FieldByIndex(cidx)))
wrap, mkUnionCaseFieldGetAddrProvenViaExprAddr(readonly, expra, uref, tinst, cidx, m), readonly
// LVALUE of "f" where "f" is a .NET static field.
| Expr.Op (TOp.ILAsm ([IL.I_ldsfld(_vol, fspec)], [ty2]), tinst, [], m) ->
None, Expr.Op (TOp.ILAsm ([IL.I_ldsflda(fspec)], [mkByrefTy g ty2]), tinst, [], m)
let readonly = false // we never consider taking the address of a .NET static field to give an inref pointer
None, Expr.Op (TOp.ILAsm ([IL.I_ldsflda(fspec)], [mkByrefTy g ty2]), tinst, [], m), readonly
// LVALUE: "x" where "e.x" is a .NET instance field. "e" may be an lvalue
| Expr.Op (TOp.ILAsm ([IL.I_ldfld(_align, _vol, fspec)], [ty2]), tinst, [e], m)
->
let exprty = tyOfExpr g e
let wrap, expra = mkExprAddrOfExprAux g (isStructTy g exprty) false mut e None m
wrap, Expr.Op (TOp.ILAsm ([IL.I_ldflda(fspec)], [mkByrefTy g ty2]), tinst, [expra], m)
// LVALUE of "e.f" where "f" is a .NET instance field.
| Expr.Op (TOp.ILAsm ([IL.I_ldfld(_align, _vol, fspec)], [ty2]), tinst, [obje], m) ->
let exprty = tyOfExpr g obje
// we never consider taking the address of an .NET instance field to give an inref pointer, unless the object pointer is an inref pointer
let wrap, expra, readonly = mkExprAddrOfExprAux g (isStructTy g exprty) false mut obje None m
wrap, Expr.Op (TOp.ILAsm ([IL.I_ldflda(fspec)], [mkByrefTyWithFlag g readonly ty2]), tinst, [expra], m), readonly
// LVALUE: "x" where "x" is mutable static field.
| Expr.Op (TOp.ValFieldGet rfref, tinst, [], m) when MustTakeAddressOfRecdFieldRef rfref || CanTakeAddressOfRecdFieldRef g rfref mut tinst ->
None, mkStaticRecdFieldGetAddr(rfref, tinst, m)
// LVALUE of "f" where "f" is a static F# field.
| Expr.Op (TOp.ValFieldGet rfref, tinst, [], m) when MustTakeAddressOfRecdFieldRef rfref || CanTakeAddressOfRecdFieldRef g m rfref tinst mut ->
let readonly = not (MustTakeAddressOfRecdFieldRef rfref)
None, mkStaticRecdFieldGetAddr(readonly, rfref, tinst, m), readonly
// LVALUE: "e.[n]" where e is an array of structs
| Expr.App(Expr.Val(vf, _, _), _, [elemTy], [aexpr;nexpr], _)
when (valRefEq g vf g.array_get_vref) ->
// LVALUE of "e.[n]" where e is an array of structs
| Expr.App(Expr.Val(vf, _, _), _, [elemTy], [aexpr;nexpr], _) when (valRefEq g vf g.array_get_vref) ->
let readonly = false // array address is never forced to be readonly
let shape = ILArrayShape.SingleDimensional
let readonly = if isTyparTy g elemTy && useReadonlyForGenericArrayAddress then ReadonlyAddress else NormalAddress
let ilInstrReadOnlyAnnotation = if isTyparTy g elemTy && useReadonlyForGenericArrayAddress then ReadonlyAddress else NormalAddress
let isNativePtr =
match addrExprVal with
| Some(vf) -> valRefEq g vf g.addrof2_vref
| _ -> false
None, mkArrayElemAddress g (readonly, isNativePtr, shape, elemTy, aexpr, nexpr, m)
None, mkArrayElemAddress g (readonly, ilInstrReadOnlyAnnotation, isNativePtr, shape, elemTy, [aexpr; nexpr], m), readonly
// LVALUE: "e.[n1, n2]", "e.[n1, n2, n3]", "e.[n1, n2, n3, n4]" where e is an array of structs
| Expr.App(Expr.Val(vf, _, _), _, [elemTy], (aexpr::args), _)
when (valRefEq g vf g.array2D_get_vref || valRefEq g vf g.array3D_get_vref || valRefEq g vf g.array4D_get_vref) ->
// LVALUE of "e.[n1, n2]", "e.[n1, n2, n3]", "e.[n1, n2, n3, n4]" where e is an array of structs
| Expr.App(Expr.Val(vref, _, _), _, [elemTy], (aexpr::args), _)
when (valRefEq g vref g.array2D_get_vref || valRefEq g vref g.array3D_get_vref || valRefEq g vref g.array4D_get_vref) ->
let readonly = false // array address is never forced to be readonly
let shape = ILArrayShape.FromRank args.Length
let readonly = if isTyparTy g elemTy && useReadonlyForGenericArrayAddress then ReadonlyAddress else NormalAddress
let ilInstrReadOnlyAnnotation = if isTyparTy g elemTy && useReadonlyForGenericArrayAddress then ReadonlyAddress else NormalAddress
let isNativePtr =
match addrExprVal with
| Some(vf) -> valRefEq g vf g.addrof2_vref
| _ -> false
None, Expr.Op (TOp.ILAsm ([IL.I_ldelema(readonly, isNativePtr, shape, mkILTyvarTy 0us)], [mkByrefTy g elemTy]), [elemTy], (aexpr::args), m)
None, mkArrayElemAddress g (readonly, ilInstrReadOnlyAnnotation, isNativePtr, shape, elemTy, (aexpr::args), m), readonly
// Give a nice error message for DefinitelyMutates on immutable values, or mutable values in other assemblies
| Expr.Val(v, _, m) when mut = DefinitelyMutates
->
if isByrefTy g v.Type then error(Error(FSComp.SR.tastUnexpectedByRef(), m));
if v.IsMutable then
error(Error(FSComp.SR.tastInvalidAddressOfMutableAcrossAssemblyBoundary(), m));
else
error(Error(FSComp.SR.tastValueMustBeMutable(), m));
// LVALUE: "&meth(args)" where meth has a byref or inref return. Includes "&span.[idx]".
| Expr.Let(TBind(vref, e, _), Expr.Op(TOp.LValueOp (LByrefGet, vref2), _, _, _), _, _) when (valRefEq g (mkLocalValRef vref) vref2) && (MustTakeAddressOfByrefGet g vref2 || CanTakeAddressOfByrefGet g vref2 mut) ->
let readonly = isInByrefTy g (tyOfExpr g e)
None, e, readonly
// Give a nice error message for address-of-byref
| Expr.Val(vref, _, m) when isByrefTy g vref.Type ->
error(Error(FSComp.SR.tastUnexpectedByRef(), m))
// Give a nice error message for DefinitelyMutates of address-of on mutable values in other assemblies
| Expr.Val(vref, _, m) when (mut = DefinitelyMutates || mut = AddressOfOp) && vref.IsMutable ->
error(Error(FSComp.SR.tastInvalidAddressOfMutableAcrossAssemblyBoundary(), m))
// Give a nice error message for AddressOfOp on immutable values
| Expr.Val _ when mut = AddressOfOp ->
error(Error(FSComp.SR.tastValueMustBeLocal(), m))
// Give a nice error message for mutating a value we can't take the address of
| Expr.Val _ when mut = DefinitelyMutates ->
error(Error(FSComp.SR.tastValueMustBeMutable(), m))
| _ ->
let ty = tyOfExpr g e
let ty = tyOfExpr g expr
if isStructTy g ty then
match mut with
| NeverMutates -> ()
| AddressOfOp -> () // we get an inref
| DefinitelyMutates ->
errorR(Error(FSComp.SR.tastInvalidMutationOfConstant(), m));
// Give a nice error message for mutating something we can't take the address of
errorR(Error(FSComp.SR.tastInvalidMutationOfConstant(), m))
| PossiblyMutates ->
warning(DefensiveCopyWarning(FSComp.SR.tastValueHasBeenCopied(), m));
// Warn on defensive copy of something we can't take the address of
warning(DefensiveCopyWarning(FSComp.SR.tastValueHasBeenCopied(), m))
// Take a defensive copy
let tmp, _ =
match mut with
| NeverMutates -> mkCompGenLocal m "copyOfStruct" ty
| _ -> mkMutableCompGenLocal m "copyOfStruct" ty
Some (tmp, e), (mkValAddr m (mkLocalValRef tmp))
let readonly = true
Some (tmp, expr), (mkValAddr m readonly (mkLocalValRef tmp)), readonly
else
None, expr, false
let mkExprAddrOfExpr g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m =
let optBind, addre = mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m
let optBind, addre, readonly = mkExprAddrOfExprAux g mustTakeAddress useReadonlyForGenericArrayAddress mut e addrExprVal m
match optBind with
| None -> (fun x -> x), addre
| Some (tmp, rval) -> (fun x -> mkCompGenLet m tmp rval x), addre
| None -> (fun x -> x), addre, readonly
| Some (tmp, rval) -> (fun x -> mkCompGenLet m tmp rval x), addre, readonly
let mkTupleFieldGet g (tupInfo, e, tinst, i, m) =
let wrap, e' = mkExprAddrOfExpr g (evalTupInfoIsStruct tupInfo) false NeverMutates e None m
let wrap, e', _readonly = mkExprAddrOfExpr g (evalTupInfoIsStruct tupInfo) false NeverMutates e None m
wrap (mkTupleFieldGetViaExprAddr(tupInfo, e', tinst, i, m))
let mkRecdFieldGet g (e, fref:RecdFieldRef, tinst, m) =
assert (not (isByrefTy g (tyOfExpr g e)))
let wrap, e' = mkExprAddrOfExpr g fref.Tycon.IsStructOrEnumTycon false NeverMutates e None m
let wrap, e', _readonly = mkExprAddrOfExpr g fref.Tycon.IsStructOrEnumTycon false NeverMutates e None m
wrap (mkRecdFieldGetViaExprAddr(e', fref, tinst, m))
let mkUnionCaseFieldGetUnproven g (e, cref:UnionCaseRef, tinst, j, m) =
assert (not (isByrefTy g (tyOfExpr g e)))
let wrap, e' = mkExprAddrOfExpr g cref.Tycon.IsStructOrEnumTycon false NeverMutates e None m
let wrap, e', _readonly = mkExprAddrOfExpr g cref.Tycon.IsStructOrEnumTycon false NeverMutates e None m
wrap (mkUnionCaseFieldGetUnprovenViaExprAddr (e', cref, tinst, j, m))

Просмотреть файл

@ -164,6 +164,9 @@ val isBeingGeneralized : Typar -> TypeScheme -> bool
val mkLazyAnd : TcGlobals -> range -> Expr -> Expr -> Expr
val mkLazyOr : TcGlobals -> range -> Expr -> Expr -> Expr
val mkByrefTy : TcGlobals -> TType -> TType
val mkByrefTyWithInference : TcGlobals -> TType -> TType -> TType
val mkInByrefTy : TcGlobals -> TType -> TType
val mkOutByrefTy : TcGlobals -> TType -> TType
//-------------------------------------------------------------------------
// Make construction operations
@ -183,10 +186,10 @@ val mkReraiseLibCall : TcGlobals -> TType -> range -> Expr
val mkTupleFieldGet : TcGlobals -> TupInfo * Expr * TypeInst * int * range -> Expr
val mkRecdFieldGetViaExprAddr : Expr * RecdFieldRef * TypeInst * range -> Expr
val mkRecdFieldGetAddrViaExprAddr : Expr * RecdFieldRef * TypeInst * range -> Expr
val mkRecdFieldGetAddrViaExprAddr : readonly: bool * Expr * RecdFieldRef * TypeInst * range -> Expr
val mkStaticRecdFieldGet : RecdFieldRef * TypeInst * range -> Expr
val mkStaticRecdFieldSet : RecdFieldRef * TypeInst * Expr * range -> Expr
val mkStaticRecdFieldGetAddr : RecdFieldRef * TypeInst * range -> Expr
val mkStaticRecdFieldGetAddr : readonly: bool * RecdFieldRef * TypeInst * range -> Expr
val mkRecdFieldSetViaExprAddr : Expr * RecdFieldRef * TypeInst * Expr * range -> Expr
val mkUnionCaseTagGetViaExprAddr : Expr * TyconRef * TypeInst * range -> Expr
@ -201,7 +204,7 @@ val mkUnionCaseFieldGetProvenViaExprAddr : Expr * UnionCaseRef * TypeInst * in
/// Build a 'TOp.UnionCaseFieldGetAddr' expression for a field of a union when we've already determined the value to be a particular union case. For ref-unions,
/// the input expression has 'TType_ucase', which is an F# compiler internal "type" corresponding to the union case. For struct-unions,
/// the input should be the address of the expression.
val mkUnionCaseFieldGetAddrProvenViaExprAddr : Expr * UnionCaseRef * TypeInst * int * range -> Expr
val mkUnionCaseFieldGetAddrProvenViaExprAddr : readonly: bool * Expr * UnionCaseRef * TypeInst * int * range -> Expr
/// Build a 'TOp.UnionCaseFieldGetAddr' expression for a field of a union when we've already determined the value to be a particular union case. For ref-unions,
/// the input expression has 'TType_ucase', which is an F# compiler internal "type" corresponding to the union case. For struct-unions,
@ -219,7 +222,7 @@ val mkUnionCaseFieldGetUnproven : TcGlobals -> Expr * UnionCaseRef * TypeIn
val mkExnCaseFieldGet : Expr * TyconRef * int * range -> Expr
val mkExnCaseFieldSet : Expr * TyconRef * int * Expr * range -> Expr
val mkArrayElemAddress : TcGlobals -> ILReadonly * bool * ILArrayShape * TType * Expr * Expr * range -> Expr
val mkArrayElemAddress : TcGlobals -> readonly: bool * ILReadonly * bool * ILArrayShape * TType * Expr list * range -> Expr
//-------------------------------------------------------------------------
// Compiled view of tuples
@ -263,9 +266,9 @@ val convertToTypeWithMetadataIfPossible : TcGlobals -> TType -> TType
//-------------------------------------------------------------------------
exception DefensiveCopyWarning of string * range
type Mutates = DefinitelyMutates | PossiblyMutates | NeverMutates
val mkExprAddrOfExprAux : TcGlobals -> bool -> bool -> Mutates -> Expr -> ValRef option -> range -> (Val * Expr) option * Expr
val mkExprAddrOfExpr : TcGlobals -> bool -> bool -> Mutates -> Expr -> ValRef option -> range -> (Expr -> Expr) * Expr
type Mutates = AddressOfOp | DefinitelyMutates | PossiblyMutates | NeverMutates
val mkExprAddrOfExprAux : TcGlobals -> bool -> bool -> Mutates -> Expr -> ValRef option -> range -> (Val * Expr) option * Expr * bool
val mkExprAddrOfExpr : TcGlobals -> bool -> bool -> Mutates -> Expr -> ValRef option -> range -> (Expr -> Expr) * Expr * bool
//-------------------------------------------------------------------------
// Tables keyed on values and/or type parameters
@ -296,41 +299,64 @@ type ValHash<'T> =
/// Maps Val's to list of T based on stamp keys
[<Struct; NoEquality; NoComparison>]
type ValMultiMap<'T> =
member ContainsKey : Val -> bool
member Find : Val -> 'T list
member Add : Val * 'T -> ValMultiMap<'T>
member Remove : Val -> ValMultiMap<'T>
member Contents : StampMap<'T list>
static member Empty : ValMultiMap<'T>
[<Sealed>]
/// Maps Typar to T based on stamp keys
type TyparMap<'T> =
member Item : Typar -> 'T with get
member ContainsKey : Typar -> bool
member TryFind : Typar -> 'T option
member Add : Typar * 'T -> TyparMap<'T>
static member Empty : TyparMap<'T>
[<NoEquality; NoComparison;Sealed>]
/// Maps TyconRef to T based on stamp keys
type TyconRefMap<'T> =
member Item : TyconRef -> 'T with get
member TryFind : TyconRef -> 'T option
member ContainsKey : TyconRef -> bool
member Add : TyconRef -> 'T -> TyconRefMap<'T>
member Remove : TyconRef -> TyconRefMap<'T>
member IsEmpty : bool
static member Empty : TyconRefMap<'T>
static member OfList : (TyconRef * 'T) list -> TyconRefMap<'T>
/// Maps TyconRef to list of T based on stamp keys
[<Struct; NoEquality; NoComparison>]
type TyconRefMultiMap<'T> =
member Find : TyconRef -> 'T list
member Add : TyconRef * 'T -> TyconRefMultiMap<'T>
static member Empty : TyconRefMultiMap<'T>
static member OfList : (TyconRef * 'T) list -> TyconRefMultiMap<'T>
member Find : TyconRef -> 'T list
member Add : TyconRef * 'T -> TyconRefMultiMap<'T>
static member Empty : TyconRefMultiMap<'T>
static member OfList : (TyconRef * 'T) list -> TyconRefMultiMap<'T>
//-------------------------------------------------------------------------
// Orderings on Tycon, Val, RecdFieldRef, Typar
@ -874,7 +900,7 @@ val mkAddrSet : range -> ValRef -> Expr -> Expr
/// *localv_ptr
val mkAddrGet : range -> ValRef -> Expr
/// &localv
val mkValAddr : range -> ValRef -> Expr
val mkValAddr : range -> readonly: bool -> ValRef -> Expr
//-------------------------------------------------------------------------
// Note these take the address of the record expression if it is a struct, and
@ -978,6 +1004,7 @@ val ExprStats : Expr -> string
//-------------------------------------------------------------------------
val mkNativePtrTy : TcGlobals -> TType -> TType
val mkVoidPtrTy : TcGlobals -> TType
val mkArrayType : TcGlobals -> TType -> TType
val isOptionTy : TcGlobals -> TType -> bool
val destOptionTy : TcGlobals -> TType -> TType
@ -1095,10 +1122,13 @@ val TypeHasDefaultValue : TcGlobals -> range -> TType -> bool
val isAbstractTycon : Tycon -> bool
val isUnionCaseRefDefinitelyMutable : UnionCaseRef -> bool
val isRecdOrUnionOrStructTyconRefDefinitelyMutable : TcGlobals -> TyconRef -> bool
val isRecdOrUnionOrStructTyconRefDefinitelyMutable : TyconRef -> bool
val isExnDefinitelyMutable : TyconRef -> bool
val isUnionCaseFieldMutable : TcGlobals -> UnionCaseRef -> int -> bool
val isExnFieldMutable : TyconRef -> int -> bool
val isRecdOrStructTyconRefReadOnly: TcGlobals -> range -> TyconRef -> bool
val isRecdOrStructTyconRefAssumedImmutable: TcGlobals -> TyconRef -> bool
val isRecdOrStructTyReadOnly: TcGlobals -> range -> TType -> bool
val useGenuineField : Tycon -> RecdField -> bool
val ComputeFieldName : Tycon -> RecdField -> string
@ -1377,7 +1407,6 @@ val TryFindAttributeUsageAttribute : TcGlobals -> range -> TyconRef -> bool opti
val TryDecodeTypeProviderAssemblyAttr : ILGlobals -> ILAttribute -> string option
#endif
val IsSignatureDataVersionAttr : ILAttribute -> bool
val ILThingHasExtensionAttribute : ILAttributes -> bool
val TryFindAutoOpenAttr : IL.ILGlobals -> ILAttribute -> string option
val TryFindInternalsVisibleToAttr : IL.ILGlobals -> ILAttribute -> string option
val IsMatchingSignatureDataVersionAttr : IL.ILGlobals -> ILVersionInfo -> ILAttribute -> bool
@ -1396,13 +1425,17 @@ val mkCompilerGeneratedAttr : TcGlobals -> int -> ILAtt
// More common type construction
//-------------------------------------------------------------------------
val isInByrefTy : TcGlobals -> TType -> bool
val isOutByrefTy : TcGlobals -> TType -> bool
val isByrefTy : TcGlobals -> TType -> bool
val isNativePtrTy : TcGlobals -> TType -> bool
val destByrefTy : TcGlobals -> TType -> TType
val destNativePtrTy : TcGlobals -> TType -> TType
val isByrefLikeTyconRef : TcGlobals -> TyconRef -> bool
val isByrefLikeTy : TcGlobals -> TType -> bool
val isByrefTyconRef : TcGlobals -> TyconRef -> bool
val isByrefLikeTyconRef : TcGlobals -> range -> TyconRef -> bool
val isByrefLikeTy : TcGlobals -> range -> TType -> bool
//-------------------------------------------------------------------------
// Tuple constructors/destructors

Просмотреть файл

@ -2221,7 +2221,7 @@ and p_target (TTarget(a,b,_)) st = p_tup2 p_Vals p_expr (a,b) st
and p_bind (TBind(a,b,_)) st = p_tup2 p_Val p_expr (a,b) st
and p_lval_op_kind x st =
p_byte (match x with LGetAddr -> 0 | LByrefGet -> 1 | LSet -> 2 | LByrefSet -> 3) st
p_byte (match x with LAddrOf _ -> 0 | LByrefGet -> 1 | LSet -> 2 | LByrefSet -> 3) st
and p_recdInfo x st =
match x with
@ -2254,7 +2254,7 @@ and u_bind st = let a = u_Val st in let b = u_expr st in TBind(a,b,NoSequencePoi
and u_lval_op_kind st =
match u_byte st with
| 0 -> LGetAddr
| 0 -> LAddrOf false
| 1 -> LByrefGet
| 2 -> LSet
| 3 -> LByrefSet
@ -2284,7 +2284,7 @@ and p_op x st =
else
p_byte 11 st; p_int a st
| TOp.ILAsm (a,b) -> p_byte 12 st; p_tup2 (p_list p_ILInstr) p_typs (a,b) st
| TOp.RefAddrGet -> p_byte 13 st
| TOp.RefAddrGet _ -> p_byte 13 st
| TOp.UnionCaseProof (a) -> p_byte 14 st; p_ucref a st
| TOp.Coerce -> p_byte 15 st
| TOp.TraitCall (b) -> p_byte 16 st; p_trait b st
@ -2297,10 +2297,10 @@ and p_op x st =
| TOp.Bytes bytes -> p_byte 22 st; p_bytes bytes st
| TOp.TryCatch _ -> p_byte 23 st
| TOp.TryFinally _ -> p_byte 24 st
| TOp.ValFieldGetAddr (a) -> p_byte 25 st; p_rfref a st
| TOp.ValFieldGetAddr (a, _) -> p_byte 25 st; p_rfref a st
| TOp.UInt16s arr -> p_byte 26 st; p_array p_uint16 arr st
| TOp.Reraise -> p_byte 27 st
| TOp.UnionCaseFieldGetAddr (a,b) -> p_byte 28 st; p_tup2 p_ucref p_int (a,b) st
| TOp.UnionCaseFieldGetAddr (a,b, _) -> p_byte 28 st; p_tup2 p_ucref p_int (a,b) st
// Note tag byte 29 is taken for struct tuples, see above
// Note tag byte 30 is taken for struct tuples, see above
| TOp.Goto _ | TOp.Label _ | TOp.Return -> failwith "unexpected backend construct in pickled TAST"
@ -2338,7 +2338,7 @@ and u_op st =
| 12 -> let a = (u_list u_ILInstr) st
let b = u_typs st
TOp.ILAsm (a,b)
| 13 -> TOp.RefAddrGet
| 13 -> TOp.RefAddrGet false // ok to set the 'readonly' flag on these operands to false on re-read since the flag is only used for typechecking purposes
| 14 -> let a = u_ucref st
TOp.UnionCaseProof a
| 15 -> TOp.Coerce
@ -2360,12 +2360,12 @@ and u_op st =
| 23 -> TOp.TryCatch(NoSequencePointAtTry,NoSequencePointAtWith)
| 24 -> TOp.TryFinally(NoSequencePointAtTry,NoSequencePointAtFinally)
| 25 -> let a = u_rfref st
TOp.ValFieldGetAddr a
TOp.ValFieldGetAddr (a, false)
| 26 -> TOp.UInt16s (u_array u_uint16 st)
| 27 -> TOp.Reraise
| 28 -> let a = u_ucref st
let b = u_int st
TOp.UnionCaseFieldGetAddr (a,b)
TOp.UnionCaseFieldGetAddr (a,b, false)
| 29 -> TOp.Tuple tupInfoStruct
| 30 -> let a = u_int st
TOp.TupleFieldGet (tupInfoStruct, a)
@ -2523,7 +2523,7 @@ let _ = fill_u_Vals (u_list u_Val)
//---------------------------------------------------------------------------
let pickleModuleOrNamespace mspec st = p_tycon_spec mspec st
let pickleCcuInfo minfo st =
let pickleCcuInfo (minfo: PickledCcuInfo) st =
p_tup4 pickleModuleOrNamespace p_string p_bool (p_space 3) (minfo.mspec, minfo.compileTimeWorkingDir, minfo.usesQuotations,()) st
let unpickleModuleOrNamespace st = u_tycon_spec st

Просмотреть файл

@ -8,7 +8,9 @@
/// comparison and hashing functions.
module internal Microsoft.FSharp.Compiler.TcGlobals
open Internal.Utilities
open System.Collections.Generic
open System.Diagnostics
open Microsoft.FSharp.Compiler
open Microsoft.FSharp.Compiler.AbstractIL
open Microsoft.FSharp.Compiler.AbstractIL.IL
@ -21,12 +23,24 @@ open Microsoft.FSharp.Compiler.Ast
open Microsoft.FSharp.Compiler.Lib
open Microsoft.FSharp.Compiler.PrettyNaming
open System.Collections.Generic
open Internal.Utilities
let internal DummyFileNameForRangesWithoutASpecificLocation = "startup"
let private envRange = rangeN DummyFileNameForRangesWithoutASpecificLocation 0
type public IntrinsicValRef = IntrinsicValRef of NonLocalEntityRef * string * bool * TType * ValLinkageFullKey
/// Represents an intrinsic value from FSharp.Core known to the compiler
[<NoEquality; NoComparison; StructuredFormatDisplay("{DebugText}")>]
type IntrinsicValRef =
| IntrinsicValRef of NonLocalEntityRef * string * bool * TType * ValLinkageFullKey
member x.Name = (let (IntrinsicValRef(_, nm, _, _, _)) = x in nm)
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
/// For debugging
override x.ToString() = x.Name
let ValRefForIntrinsic (IntrinsicValRef(mvr, _, _, _, key)) = mkNonLocalValRef mvr key
@ -37,7 +51,6 @@ let ValRefForIntrinsic (IntrinsicValRef(mvr, _, _, _, key)) = mkNonLocalValRef
[<AutoOpen>]
module FSharpLib =
let CoreOperatorsName = FSharpLib.Root + ".Core.Operators"
let CoreOperatorsCheckedName = FSharpLib.Root + ".Core.Operators.Checked"
let ControlName = FSharpLib.Root + ".Control"
let LinqName = FSharpLib.Root + ".Linq"
@ -47,22 +60,18 @@ module FSharpLib =
let LinqRuntimeHelpersName = FSharpLib.Root + ".Linq.RuntimeHelpers"
let RuntimeHelpersName = FSharpLib.Root + ".Core.CompilerServices.RuntimeHelpers"
let ExtraTopLevelOperatorsName = FSharpLib.Root + ".Core.ExtraTopLevelOperators"
let HashCompareName = FSharpLib.Root + ".Core.LanguagePrimitives.HashCompare"
let NativeInteropName = FSharpLib.Root + ".NativeInterop"
let QuotationsName = FSharpLib.Root + ".Quotations"
let OperatorsPath = IL.splitNamespace CoreOperatorsName |> Array.ofList
let OperatorsCheckedPath = IL.splitNamespace CoreOperatorsCheckedName |> Array.ofList
let ControlPath = IL.splitNamespace ControlName
let LinqPath = IL.splitNamespace LinqName
let CollectionsPath = IL.splitNamespace CollectionsName
let LanguagePrimitivesPath = IL.splitNamespace LanguagePrimitivesName |> Array.ofList
let HashComparePath = IL.splitNamespace HashCompareName |> Array.ofList
let NativeInteropPath = IL.splitNamespace NativeInteropName |> Array.ofList
let CompilerServicesPath = IL.splitNamespace CompilerServicesName |> Array.ofList
let LinqRuntimeHelpersPath = IL.splitNamespace LinqRuntimeHelpersName |> Array.ofList
let RuntimeHelpersPath = IL.splitNamespace RuntimeHelpersName |> Array.ofList
let QuotationsPath = IL.splitNamespace QuotationsName |> Array.ofList
let ExtraTopLevelOperatorsPath = IL.splitNamespace ExtraTopLevelOperatorsName |> Array.ofList
let RootPathArray = FSharpLib.RootPath |> Array.ofList
let CorePathArray = FSharpLib.CorePath |> Array.ofList
@ -87,11 +96,23 @@ let mk_MFRuntimeHelpers_tcref ccu n = mkNonLocalTyconRef2 ccu FSharpLib.Runtim
let mk_MFControl_tcref ccu n = mkNonLocalTyconRef2 ccu FSharpLib.ControlPathArray n
type public BuiltinAttribInfo =
type
[<NoEquality; NoComparison; StructuredFormatDisplay("{DebugText}")>]
BuiltinAttribInfo =
| AttribInfo of ILTypeRef * TyconRef
member this.TyconRef = let (AttribInfo(_, tcref)) = this in tcref
member this.TypeRef = let (AttribInfo(tref, _)) = this in tref
/// For debugging
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
member x.DebugText = x.ToString()
/// For debugging
override x.ToString() = x.TyconRef.ToString()
[<Literal>]
let tname_DebuggerNonUserCodeAttribute = "System.Diagnostics.DebuggerNonUserCodeAttribute"
[<Literal>]
@ -201,7 +222,11 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
let v_pint16_tcr = mk_MFCore_tcref fslibCcu "int16`1"
let v_pint64_tcr = mk_MFCore_tcref fslibCcu "int64`1"
let v_byref_tcr = mk_MFCore_tcref fslibCcu "byref`1"
let v_byref2_tcr = mk_MFCore_tcref fslibCcu "byref`2"
let v_outref_tcr = mk_MFCore_tcref fslibCcu "outref`1"
let v_inref_tcr = mk_MFCore_tcref fslibCcu "inref`1"
let v_nativeptr_tcr = mk_MFCore_tcref fslibCcu "nativeptr`1"
let v_voidptr_tcr = mk_MFCore_tcref fslibCcu "voidptr"
let v_ilsigptr_tcr = mk_MFCore_tcref fslibCcu "ilsigptr`1"
let v_fastFunc_tcr = mk_MFCore_tcref fslibCcu "FSharpFunc`2"
let v_refcell_tcr_canon = mk_MFCore_tcref fslibCcu "Ref`1"
@ -384,12 +409,14 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
let fslib_MFCompilerServices_nleref = mkNonLocalEntityRef fslibCcu FSharpLib.CompilerServicesPath
let fslib_MFLinqRuntimeHelpers_nleref = mkNonLocalEntityRef fslibCcu FSharpLib.LinqRuntimeHelpersPath
let fslib_MFControl_nleref = mkNonLocalEntityRef fslibCcu FSharpLib.ControlPathArray
let fslib_MFNativeInterop_nleref = mkNonLocalEntityRef fslibCcu FSharpLib.NativeInteropPath
let fslib_MFLanguagePrimitives_nleref = mkNestedNonLocalEntityRef fslib_MFCore_nleref "LanguagePrimitives"
let fslib_MFIntrinsicOperators_nleref = mkNestedNonLocalEntityRef fslib_MFLanguagePrimitives_nleref "IntrinsicOperators"
let fslib_MFIntrinsicFunctions_nleref = mkNestedNonLocalEntityRef fslib_MFLanguagePrimitives_nleref "IntrinsicFunctions"
let fslib_MFHashCompare_nleref = mkNestedNonLocalEntityRef fslib_MFLanguagePrimitives_nleref "HashCompare"
let fslib_MFOperators_nleref = mkNestedNonLocalEntityRef fslib_MFCore_nleref "Operators"
let fslib_MFByRefKinds_nleref = mkNestedNonLocalEntityRef fslib_MFCore_nleref "ByRefKinds"
let fslib_MFOperatorIntrinsics_nleref = mkNestedNonLocalEntityRef fslib_MFOperators_nleref "OperatorIntrinsics"
let fslib_MFOperatorsUnchecked_nleref = mkNestedNonLocalEntityRef fslib_MFOperators_nleref "Unchecked"
let fslib_MFOperatorsChecked_nleref = mkNestedNonLocalEntityRef fslib_MFOperators_nleref "Checked"
@ -408,6 +435,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
let fslib_MFSetModule_nleref = mkNestedNonLocalEntityRef fslib_MFCollections_nleref "SetModule"
let fslib_MFMapModule_nleref = mkNestedNonLocalEntityRef fslib_MFCollections_nleref "MapModule"
let fslib_MFStringModule_nleref = mkNestedNonLocalEntityRef fslib_MFCollections_nleref "StringModule"
let fslib_MFNativePtrModule_nleref = mkNestedNonLocalEntityRef fslib_MFNativeInterop_nleref "NativePtrModule"
let fslib_MFOptionModule_nleref = mkNestedNonLocalEntityRef fslib_MFCore_nleref "OptionModule"
let fslib_MFRuntimeHelpers_nleref = mkNestedNonLocalEntityRef fslib_MFCompilerServices_nleref "RuntimeHelpers"
let fslib_MFQuotations_nleref = mkNestedNonLocalEntityRef fslib_MF_nleref "Quotations"
@ -471,6 +499,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
fslib_MFSetModule_nleref
fslib_MFMapModule_nleref
fslib_MFStringModule_nleref
fslib_MFNativePtrModule_nleref
fslib_MFOptionModule_nleref
fslib_MFRuntimeHelpers_nleref ] do
@ -650,6 +679,8 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
let v_array3D_set_info = makeIntrinsicValRef(fslib_MFIntrinsicFunctions_nleref, "SetArray3D" , None , None , [vara], ([[mkArrayType 3 varaTy];[v_int_ty]; [v_int_ty]; [v_int_ty]; [varaTy]], v_unit_ty))
let v_array4D_set_info = makeIntrinsicValRef(fslib_MFIntrinsicFunctions_nleref, "SetArray4D" , None , None , [vara], ([[mkArrayType 4 varaTy];[v_int_ty]; [v_int_ty]; [v_int_ty]; [v_int_ty]; [varaTy]], v_unit_ty))
let v_nativeptr_tobyref_info = makeIntrinsicValRef(fslib_MFNativePtrModule_nleref, "toByRef" , None , Some "ToByRefInlined", [vara], ([[mkNativePtrTy varaTy]], mkByrefTy varaTy))
let v_seq_collect_info = makeIntrinsicValRef(fslib_MFSeqModule_nleref, "collect" , None , Some "Collect", [vara;varb;varc], ([[varaTy --> varbTy]; [mkSeqTy varaTy]], mkSeqTy varcTy))
let v_seq_delay_info = makeIntrinsicValRef(fslib_MFSeqModule_nleref, "delay" , None , Some "Delay" , [varb], ([[v_unit_ty --> mkSeqTy varbTy]], mkSeqTy varbTy))
let v_seq_append_info = makeIntrinsicValRef(fslib_MFSeqModule_nleref, "append" , None , Some "Append" , [varb], ([[mkSeqTy varbTy]; [mkSeqTy varbTy]], mkSeqTy varbTy))
@ -915,7 +946,11 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
member __.pint16_tcr = v_pint16_tcr
member __.pint64_tcr = v_pint64_tcr
member __.byref_tcr = v_byref_tcr
member __.byref2_tcr = v_byref2_tcr
member __.outref_tcr = v_outref_tcr
member __.inref_tcr = v_inref_tcr
member __.nativeptr_tcr = v_nativeptr_tcr
member __.voidptr_tcr = v_voidptr_tcr
member __.ilsigptr_tcr = v_ilsigptr_tcr
member __.fastFunc_tcr = v_fastFunc_tcr
member __.tcref_IQueryable = v_tcref_IQueryable
@ -925,6 +960,9 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
member __.fslib_IDelegateEvent_tcr = v_fslib_IDelegateEvent_tcr
member __.seq_tcr = v_seq_tcr
member val seq_base_tcr = mk_MFCompilerServices_tcref fslibCcu "GeneratedSequenceBase`1"
member val byrefkind_In_tcr = mkNonLocalTyconRef fslib_MFByRefKinds_nleref "In"
member val byrefkind_Out_tcr = mkNonLocalTyconRef fslib_MFByRefKinds_nleref "Out"
member val byrefkind_InOut_tcr = mkNonLocalTyconRef fslib_MFByRefKinds_nleref "InOut"
member val measureproduct_tcr = mk_MFCompilerServices_tcref fslibCcu "MeasureProduct`2"
member val measureinverse_tcr = mk_MFCompilerServices_tcref fslibCcu "MeasureInverse`1"
member val measureone_tcr = mk_MFCompilerServices_tcref fslibCcu "MeasureOne"
@ -1074,6 +1112,11 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
member val attrib_IDispatchConstantAttribute = tryFindSysAttrib "System.Runtime.CompilerServices.IDispatchConstantAttribute"
member val attrib_IUnknownConstantAttribute = tryFindSysAttrib "System.Runtime.CompilerServices.IUnknownConstantAttribute"
// We use 'findSysAttrib' here because lookup on attribute is done by name comparison, and can proceed
// even if the type is not found in a system assembly.
member val attrib_IsByRefLikeAttribute = findSysAttrib "System.Runtime.CompilerServices.IsByRefLikeAttribute"
member val attrib_IsReadOnlyAttribute = findSysAttrib "System.Runtime.CompilerServices.IsReadOnlyAttribute"
member val attrib_SystemObsolete = findSysAttrib "System.ObsoleteAttribute"
member val attrib_DllImportAttribute = tryFindSysAttrib "System.Runtime.InteropServices.DllImportAttribute"
member val attrib_StructLayoutAttribute = findSysAttrib "System.Runtime.InteropServices.StructLayoutAttribute"
@ -1082,7 +1125,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
member val attrib_ComImportAttribute = tryFindSysAttrib "System.Runtime.InteropServices.ComImportAttribute"
member val attrib_FieldOffsetAttribute = findSysAttrib "System.Runtime.InteropServices.FieldOffsetAttribute"
member val attrib_MarshalAsAttribute = tryFindSysAttrib "System.Runtime.InteropServices.MarshalAsAttribute"
member val attrib_InAttribute = tryFindSysAttrib "System.Runtime.InteropServices.InAttribute"
member val attrib_InAttribute = findSysAttrib "System.Runtime.InteropServices.InAttribute"
member val attrib_OutAttribute = findSysAttrib "System.Runtime.InteropServices.OutAttribute"
member val attrib_OptionalAttribute = tryFindSysAttrib "System.Runtime.InteropServices.OptionalAttribute"
member val attrib_DefaultParameterValueAttribute = tryFindSysAttrib "System.Runtime.InteropServices.DefaultParameterValueAttribute"
@ -1299,6 +1342,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d
member val array4D_get_vref = ValRefForIntrinsic v_array4D_get_info
member val seq_singleton_vref = ValRefForIntrinsic v_seq_singleton_info
member val seq_collect_vref = ValRefForIntrinsic v_seq_collect_info
member val nativeptr_tobyref_vref = ValRefForIntrinsic v_nativeptr_tobyref_info
member val seq_using_vref = ValRefForIntrinsic v_seq_using_info
member val seq_delay_vref = ValRefForIntrinsic v_seq_delay_info
member val seq_append_vref = ValRefForIntrinsic v_seq_append_info

Просмотреть файл

@ -537,8 +537,8 @@ type cenv =
let CopyAndFixupTypars m rigid tpsorig =
ConstraintSolver.FreshenAndFixupTypars m rigid [] [] tpsorig
let UnifyTypes cenv (env: TcEnv) m expectedTy actualTy =
ConstraintSolver.AddCxTypeEqualsType env.eContextInfo env.DisplayEnv cenv.css m (tryNormalizeMeasureInType cenv.g expectedTy) (tryNormalizeMeasureInType cenv.g actualTy)
let UnifyTypes cenv (env: TcEnv) m actualTy expectedTy =
ConstraintSolver.AddCxTypeEqualsType env.eContextInfo env.DisplayEnv cenv.css m (tryNormalizeMeasureInType cenv.g actualTy) (tryNormalizeMeasureInType cenv.g expectedTy)
/// Make the initial type checking environment for a single file with an empty accumulator for the overall contents for the file
let MakeInitialEnv env =
@ -864,7 +864,7 @@ let TcConst cenv ty m env c =
| SynMeasure.Anon _ -> error(Error(FSComp.SR.tcUnexpectedMeasureAnon(), m))
| SynMeasure.Var(_, m) -> error(Error(FSComp.SR.tcNonZeroConstantCannotHaveGenericUnit(), m))
let unif ty2 = UnifyTypes cenv env m ty ty2
let unif expected = UnifyTypes cenv env m ty expected
let unifyMeasureArg iszero tcr c =
let measureTy =
@ -2100,32 +2100,37 @@ module GeneralizationHelpers =
let rec IsGeneralizableValue g t =
match t with
| Expr.Lambda _ | Expr.TyLambda _ | Expr.Const _ | Expr.Val _ -> true
| Expr.Lambda _ | Expr.TyLambda _ | Expr.Const _ -> true
// let f(x: byref<int>) = let v = &x in ... shouldn't generalize "v"
| Expr.Val (vref, _, m) -> not (isByrefLikeTy g m vref.Type)
// Look through coercion nodes corresponding to introduction of subsumption
| Expr.Op(TOp.Coerce, [inputTy;actualTy], [e1], _) when isFunTy g actualTy && isFunTy g inputTy ->
IsGeneralizableValue g e1
| Expr.Op(op, _, args, _) ->
let canGeneralizeOp =
match op with
| TOp.Tuple _ -> true
| TOp.UnionCase uc -> not (isUnionCaseRefDefinitelyMutable uc)
| TOp.Recd(ctorInfo, tcref) ->
match ctorInfo with
| RecdExpr -> not (isRecdOrUnionOrStructTyconRefDefinitelyMutable g tcref)
| RecdExpr -> not (isRecdOrUnionOrStructTyconRefDefinitelyMutable tcref)
| RecdExprIsObjInit -> false
| TOp.Array -> isNil args
| TOp.ExnConstr ec -> not (isExnDefinitelyMutable ec)
| TOp.ILAsm([], _) -> true
| _ -> false
&& List.forall (IsGeneralizableValue g) args
canGeneralizeOp && List.forall (IsGeneralizableValue g) args
| Expr.LetRec(binds, body, _, _) ->
binds |> List.forall (fun b -> not b.Var.IsMutable) &&
binds |> List.forall (fun b -> IsGeneralizableValue g b.Expr) &&
IsGeneralizableValue g body
| Expr.Let(bind, body, _, _) ->
not bind.Var.IsMutable &&
IsGeneralizableValue g bind.Expr &&
@ -2639,6 +2644,9 @@ let FreshenObjectArgType cenv m rigid tcref isExtrinsic declaredTyconTypars =
// Struct members have a byref 'this' type (unless they are extrinsic extension members)
let thisTy =
if not isExtrinsic && tcref.IsStructOrEnumTycon then
if isRecdOrStructTyReadOnly cenv.g m objTy then
mkInByrefTy cenv.g objTy
else
mkByrefTy cenv.g objTy
else
objTy
@ -3058,7 +3066,7 @@ let BuildILFieldGet g amap m objExpr (finfo:ILFieldInfo) =
Expr.Const(TcFieldInit m lit, m, fieldType)
| _ ->
#endif
let wrap, objExpr = mkExprAddrOfExpr g isValueType false NeverMutates objExpr None m
let wrap, objExpr, _readonly = mkExprAddrOfExpr g isValueType false NeverMutates objExpr None m
// The empty instantiation on the AbstractIL fspec is OK, since we make the correct fspec in IlxGen.GenAsm
// This ensures we always get the type instantiation right when doing this from
// polymorphic code, after inlining etc. *
@ -3076,7 +3084,7 @@ let BuildILFieldSet g m objExpr (finfo:ILFieldInfo) argExpr =
// polymorphic code, after inlining etc. *
let fspec = mkILFieldSpec(fref, mkILNamedTy valu fref.DeclaringTypeRef [])
if finfo.IsInitOnly then error (Error (FSComp.SR.tcFieldIsReadonly(), m))
let wrap, objExpr = mkExprAddrOfExpr g isValueType false DefinitelyMutates objExpr None m
let wrap, objExpr, _readonly = mkExprAddrOfExpr g isValueType false DefinitelyMutates objExpr None m
wrap (mkAsmExpr ([ mkNormalStfld fspec ], tinst, [objExpr; argExpr], [], m))
let BuildILStaticFieldSet m (finfo:ILFieldInfo) argExpr =
@ -3095,7 +3103,7 @@ let BuildRecdFieldSet g m objExpr (rfinfo:RecdFieldInfo) argExpr =
let tgty = rfinfo.DeclaringType
let valu = isStructTy g tgty
let objExpr = if valu then objExpr else mkCoerceExpr(objExpr, tgty, m, tyOfExpr g objExpr)
let wrap, objExpr = mkExprAddrOfExpr g valu false DefinitelyMutates objExpr None m
let wrap, objExpr, _readonly = mkExprAddrOfExpr g valu false DefinitelyMutates objExpr None m
wrap (mkRecdFieldSetViaExprAddr (objExpr, rfinfo.RecdFieldRef, rfinfo.TypeInst, argExpr, m) )
@ -3952,30 +3960,75 @@ let CheckAndRewriteObjectCtor g env (ctorLambaExpr:Expr) =
/// Post-typechecking normalizations to enforce semantic constraints
/// lazy and, lazy or, rethrow, address-of
let buildApp cenv expr exprty arg m =
let buildApp cenv expr resultTy arg m =
let g = cenv.g
match expr, arg with
// Special rule for building applications of the 'x && y' operator
| ApplicableExpr(_, Expr.App(Expr.Val(vf, _, _), _, _, [x0], _), _) , _
when valRefEq g vf g.and_vref
|| valRefEq g vf g.and2_vref ->
MakeApplicableExprNoFlex cenv (mkLazyAnd g m x0 arg)
MakeApplicableExprNoFlex cenv (mkLazyAnd g m x0 arg), resultTy
// Special rule for building applications of the 'x || y' operator
| ApplicableExpr(_, Expr.App(Expr.Val(vf, _, _), _, _, [x0], _), _), _
when valRefEq g vf g.or_vref
|| valRefEq g vf g.or2_vref ->
MakeApplicableExprNoFlex cenv (mkLazyOr g m x0 arg )
MakeApplicableExprNoFlex cenv (mkLazyOr g m x0 arg ), resultTy
// Special rule for building applications of the 'reraise' operator
| ApplicableExpr(_, Expr.App(Expr.Val(vf, _, _), _, _, [], _), _), _
when valRefEq g vf g.reraise_vref ->
// exprty is of type: "unit -> 'a". Break it and store the 'a type here, used later as return type.
let _unit_ty, rtn_ty = destFunTy g exprty
MakeApplicableExprNoFlex cenv (mkCompGenSequential m arg (mkReraise m rtn_ty))
MakeApplicableExprNoFlex cenv (mkCompGenSequential m arg (mkReraise m resultTy)), resultTy
// Special rules for NativePtr.ofByRef to generalize result.
// See RFC FS-1053.md
| ApplicableExpr(_, Expr.App(Expr.Val(vf, _, _), _, _, [], _), _), _
when (valRefEq g vf g.addrof_vref ||
valRefEq g vf g.addrof2_vref) ->
if valRefEq g vf g.addrof2_vref then warning(UseOfAddressOfOperator(m))
let wrap, e1a' = mkExprAddrOfExpr g true false DefinitelyMutates arg (Some(vf)) m
MakeApplicableExprNoFlex cenv (wrap(e1a'))
when (valRefEq g vf g.nativeptr_tobyref_vref) ->
let argty = NewInferenceType()
let resultTy = mkByrefTyWithInference g argty (NewByRefKindInferenceType g m)
expr.SupplyArgument(arg, m), resultTy
// Special rules for building applications of the '&expr' operator, which gets the
// address of an expression.
//
// See also RFC FS-1053.md
| ApplicableExpr(_, Expr.App(Expr.Val(vf, _, _), _, _, [], _), _), _
when valRefEq g vf g.addrof_vref ->
let wrap, e1a', readonly = mkExprAddrOfExpr g true false AddressOfOp arg (Some(vf)) m
// Assert the result type to be readonly if we couldn't take the address
let resultTy =
let argTy = tyOfExpr g arg
if readonly then
mkInByrefTy g argTy
else
mkByrefTyWithInference g argTy (NewByRefKindInferenceType g m)
MakeApplicableExprNoFlex cenv (wrap(e1a')), resultTy
// Special rules for building applications of the &&expr' operators, which gets the
// address of an expression.
| ApplicableExpr(_, Expr.App(Expr.Val(vf, _, _), _, _, [], _), _), _
when valRefEq g vf g.addrof2_vref ->
warning(UseOfAddressOfOperator(m))
let wrap, e1a', _readonly = mkExprAddrOfExpr g true false AddressOfOp arg (Some(vf)) m
MakeApplicableExprNoFlex cenv (wrap(e1a')), resultTy
| _ when isByrefTy g resultTy ->
// Handle byref returns, byref-typed returns get implicitly dereferenced
let v, _ = mkCompGenLocal m "byrefReturn" resultTy
let expr = expr.SupplyArgument(arg, m)
let expr = mkCompGenLet m v expr.Expr (mkAddrGet m (mkLocalValRef v))
let resultTy = destByrefTy g resultTy
MakeApplicableExprNoFlex cenv expr, resultTy
| _ ->
expr.SupplyArgument(arg, m)
expr.SupplyArgument(arg, m), resultTy
//-------------------------------------------------------------------------
// Additional data structures used by type checking
@ -5959,6 +6012,10 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) =
let mExprAndDotLookup = unionRanges e1.Range (rangeOfLid longId)
TcExprThen cenv overallTy env tpenv e1 [DelayedDotLookup(longId, mExprAndDotLookup); MakeDelayedSet(e2, mStmt)]
/// e1 <- e2
| SynExpr.Set (e1, e2, mStmt) ->
TcExprThen cenv overallTy env tpenv e1 [MakeDelayedSet(e2, mStmt)]
/// e1.longId(e2) <- e3, very rarely used named property setters
| SynExpr.DotNamedIndexedPropertySet (e1, (LongIdentWithDots(longId, _) as lidwd), e2, e3, mStmt) ->
if lidwd.ThereIsAnExtraDotAtTheEnd then
@ -6159,7 +6216,7 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg
let f, fty, tpenv = TcExprOfUnknownType cenv env tpenv operPath
let domainTy, resultTy = UnifyFunctionType (Some mWholeExpr) cenv env.DisplayEnv mWholeExpr fty
UnifyTypes cenv env mWholeExpr domainTy e1ty
let f' = buildApp cenv (MakeApplicableExprNoFlex cenv f) fty e1' mWholeExpr
let f', resultTy = buildApp cenv (MakeApplicableExprNoFlex cenv f) resultTy e1' mWholeExpr
let delayed = List.foldBack (fun idx acc -> DelayedApp(ExprAtomicFlag.Atomic, idx, mWholeExpr) :: acc) indexArgs delayed // atomic, otherwise no ar.[1] <- xyz
Some (PropagateThenTcDelayed cenv overallTy env tpenv mWholeExpr f' resultTy ExprAtomicFlag.Atomic delayed )
else None
@ -6292,7 +6349,7 @@ and TcRecordConstruction cenv overallTy env tpenv optOrigExpr objTy fldsList m =
match optOrigExpr with
| None -> [], id
| Some (_, _, oldve) ->
let wrap, oldveaddr = mkExprAddrOfExpr cenv.g tycon.IsStructOrEnumTycon false NeverMutates oldve None m
let wrap, oldveaddr, _readonly = mkExprAddrOfExpr cenv.g tycon.IsStructOrEnumTycon false NeverMutates oldve None m
let fieldNameUnbound nom = List.forall (fun (name, _) -> name <> nom) fldsList
let flds =
fspecs |> List.choose (fun rfld ->
@ -8264,24 +8321,50 @@ and TcSequenceExpression cenv env tpenv comp overallTy m =
/// of function application syntax unambiguously implies that 'overallTy' is a function type.
and Propagate cenv overallTy env tpenv (expr: ApplicableExpr) exprty delayed =
let rec propagate delayedList mExpr exprty =
let rec propagate isAddrOf delayedList mExpr exprty =
match delayedList with
| [] ->
// Avoid unifying twice: we're about to unify in TcDelayed
if not (isNil delayed) then
// We generate a tag inference parameter to the return type for "&x" and 'NativePtr.toByRef'
// See RFC FS-1053.md
let exprty =
if isAddrOf && isByrefTy cenv.g exprty then
mkByrefTyWithInference cenv.g (destByrefTy cenv.g exprty) (NewByRefKindInferenceType cenv.g mExpr)
elif isByrefTy cenv.g exprty then
// Implicit dereference on byref on return
if isByrefTy cenv.g overallTy then
errorR(Error(FSComp.SR.tcByrefReturnImplicitlyDereferenced(), mExpr))
destByrefTy cenv.g exprty
else
exprty
UnifyTypesAndRecover cenv env mExpr overallTy exprty
| DelayedDot :: _
| DelayedSet _ :: _
| DelayedDotLookup _ :: _ -> ()
| DelayedTypeApp (_, _mTypeArgs, mExprAndTypeArgs) :: delayedList' ->
// Note this case should not occur: would eventually give an "Unexpected type application" error in TcDelayed
propagate delayedList' mExprAndTypeArgs exprty
propagate isAddrOf delayedList' mExprAndTypeArgs exprty
| DelayedApp (_, arg, mExprAndArg) :: delayedList' ->
let denv = env.DisplayEnv
match UnifyFunctionTypeUndoIfFailed cenv denv mExpr exprty with
| Some (_, resultTy) ->
propagate delayedList' mExprAndArg resultTy
// We add tag parameter to the return type for "&x" and 'NativePtr.toByRef'
// See RFC FS-1053.md
let isAddrOf =
match expr with
| ApplicableExpr(_, Expr.App(Expr.Val(vf, _, _), _, _, [], _), _)
when (valRefEq cenv.g vf cenv.g.addrof_vref ||
valRefEq cenv.g vf cenv.g.nativeptr_tobyref_vref) -> true
| _ -> false
propagate isAddrOf delayedList' mExprAndArg resultTy
| None ->
let mArg = arg.Range
match arg with
@ -8302,7 +8385,7 @@ and Propagate cenv overallTy env tpenv (expr: ApplicableExpr) exprty delayed =
RecordNameAndTypeResolutions_IdeallyWithoutHavingOtherEffects_Delayed cenv env tpenv delayed
error (NotAFunction(denv, overallTy, mExpr, mArg))
propagate delayed expr.Range exprty
propagate false delayed expr.Range exprty
and PropagateThenTcDelayed cenv overallTy env tpenv mExpr expr exprty (atomicFlag:ExprAtomicFlag) delayed =
Propagate cenv overallTy env tpenv expr exprty delayed
@ -8334,8 +8417,16 @@ and TcDelayed cenv overallTy env tpenv mExpr expr exprty (atomicFlag:ExprAtomicF
// f<tyargs>
| DelayedTypeApp (_, mTypeArgs, _mExprAndTypeArgs) :: _ ->
error(Error(FSComp.SR.tcUnexpectedTypeArguments(), mTypeArgs))
| DelayedSet _ :: _ ->
error(Error(FSComp.SR.tcInvalidAssignment(), mExpr))
| DelayedSet (synExpr2, mStmt) :: otherDelayed ->
if not (isNil otherDelayed) then error(Error(FSComp.SR.tcInvalidAssignment(), mExpr))
UnifyTypes cenv env mExpr overallTy cenv.g.unit_ty
let expr = expr.Expr
let _wrap, exprAddress, _readonly = mkExprAddrOfExpr cenv.g true false DefinitelyMutates expr None mExpr
let vty = tyOfExpr cenv.g expr
// Always allow subsumption on assignment to fields
let expr2, tpenv = TcExprFlex cenv true vty env tpenv synExpr2
let v, _ve = mkCompGenLocal mExpr "addr" (mkByrefTy cenv.g vty)
mkCompGenLet mStmt v exprAddress (mkAddrSet mStmt (mkLocalValRef v) expr2), tpenv
/// Convert the delayed identifiers to a dot-lookup.
@ -8377,7 +8468,7 @@ and TcFunctionApplicationThen cenv overallTy env tpenv mExprAndArg expr exprty (
| _ -> ()
let arg, tpenv = TcExpr cenv domainTy env tpenv synArg
let exprAndArg = buildApp cenv expr exprty arg mExprAndArg
let exprAndArg, resultTy = buildApp cenv expr resultTy arg mExprAndArg
TcDelayed cenv overallTy env tpenv mExprAndArg exprAndArg resultTy atomicFlag delayed
| None ->
// OK, 'expr' doesn't have function type, but perhaps 'expr' is a computation expression builder, and 'arg' is '{ ... }'
@ -8766,6 +8857,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
| SynExpr.DotSet _
| SynExpr.DotIndexedSet _
| SynExpr.LongIdentSet _
| SynExpr.Set _
| SynExpr.JoinIn _
| SynExpr.NamedIndexedPropertySet _
| SynExpr.DotNamedIndexedPropertySet _
@ -8839,7 +8931,10 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
// Always allow subsumption on assignment to fields
let e2', tpenv = TcExprFlex cenv true vty2 env tpenv e2
let vexp =
if isByrefTy cenv.g vty then
if isInByrefTy cenv.g vty then
errorR(Error(FSComp.SR.writeToReadOnlyByref(), mStmt))
mkAddrSet mStmt vref e2'
elif isByrefTy cenv.g vty then
mkAddrSet mStmt vref e2'
else
mkValSet mStmt vref e2'
@ -8877,11 +8972,21 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
if not pinfo.IsStatic then error (Error (FSComp.SR.tcPropertyIsNotStatic(nm), mItem))
match delayed with
| DelayedSet(e2, mStmt) :: otherDelayed ->
let args = if pinfo.IsIndexer then args else []
if not (isNil otherDelayed) then error(Error(FSComp.SR.tcInvalidAssignment(), mStmt))
// Static Property Set (possibly indexer)
UnifyTypes cenv env mStmt overallTy cenv.g.unit_ty
let meths = pinfos |> SettersOfPropInfos
if meths.IsEmpty then
let meths = pinfos |> GettersOfPropInfos
let isByrefMethReturnSetter = meths |> List.exists (function (_,Some pinfo) -> isByrefTy cenv.g (pinfo.GetPropertyType(cenv.amap,mItem)) | _ -> false)
if isByrefMethReturnSetter then
// x.P <- ... byref setter
if isNil meths then error (Error (FSComp.SR.tcPropertyIsNotReadable(nm), mItem))
TcMethodApplicationThen cenv env overallTy None tpenv tyargsOpt [] mItem mItem nm ad NeverMutates true meths afterResolution NormalValUse args ExprAtomicFlag.Atomic delayed
else
error (Error (FSComp.SR.tcPropertyCannotBeSet1 nm, mItem))
else
let args = if pinfo.IsIndexer then args else []
if isNil meths then error (Error (FSComp.SR.tcPropertyCannotBeSet1 nm, mItem))
// Note: static calls never mutate a struct object argument
TcMethodApplicationThen cenv env overallTy None tpenv tyargsOpt [] mStmt mItem nm ad NeverMutates true meths afterResolution NormalValUse (args@[e2]) ExprAtomicFlag.NonAtomic otherDelayed
@ -9052,12 +9157,21 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela
match delayed with
| DelayedSet(e2, mStmt) :: otherDelayed ->
let args = if pinfo.IsIndexer then args else []
if not (isNil otherDelayed) then error(Error(FSComp.SR.tcInvalidAssignment(), mStmt))
// Instance property setter
UnifyTypes cenv env mStmt overallTy cenv.g.unit_ty
let meths = SettersOfPropInfos pinfos
if isNil meths then error (Error (FSComp.SR.tcPropertyCannotBeSet1 nm, mItem))
if meths.IsEmpty then
let meths = pinfos |> GettersOfPropInfos
let isByrefMethReturnSetter = meths |> List.exists (function (_,Some pinfo) -> isByrefTy cenv.g (pinfo.GetPropertyType(cenv.amap,mItem)) | _ -> false)
if isByrefMethReturnSetter then
// x.P <- ... byref setter
if isNil meths then error (Error (FSComp.SR.tcPropertyIsNotReadable(nm), mItem))
TcMethodApplicationThen cenv env overallTy None tpenv tyargsOpt objArgs mExprAndItem mItem nm ad PossiblyMutates true meths afterResolution NormalValUse args atomicFlag delayed
else
error (Error (FSComp.SR.tcPropertyCannotBeSet1 nm, mItem))
else
let args = if pinfo.IsIndexer then args else []
let mut = (if isStructTy cenv.g (tyOfExpr cenv.g objExpr) then DefinitelyMutates else PossiblyMutates)
TcMethodApplicationThen cenv env overallTy None tpenv tyargsOpt objArgs mStmt mItem nm ad mut true meths afterResolution NormalValUse (args @ [e2]) atomicFlag []
| _ ->
@ -9213,7 +9327,7 @@ and TcMethodApplicationThen
and GetNewInferenceTypeForMethodArg cenv env tpenv x =
match x with
| SynExprParen(a, _, _, _) -> GetNewInferenceTypeForMethodArg cenv env tpenv a
| SynExpr.AddressOf(true, a, _, _) -> mkByrefTy cenv.g (GetNewInferenceTypeForMethodArg cenv env tpenv a)
| SynExpr.AddressOf(true, a, _, m) -> mkByrefTyWithInference cenv.g (GetNewInferenceTypeForMethodArg cenv env tpenv a) (NewByRefKindInferenceType cenv.g m)
| SynExpr.Lambda(_, _, _, a, _) -> mkFunTy (NewInferenceType ()) (GetNewInferenceTypeForMethodArg cenv env tpenv a)
| SynExpr.Quote(_, raw, a, _, _) ->
if raw then mkRawQuotedExprTy cenv.g
@ -9245,7 +9359,7 @@ and TcMethodApplication
let denv = env.DisplayEnv
let isSimpleFormalArg (isParamArrayArg, isOutArg, optArgInfo: OptionalArgInfo, callerInfoInfo: CallerInfoInfo, _reflArgInfo: ReflectedArgInfo) =
let isSimpleFormalArg (isParamArrayArg, _isInArg, isOutArg, optArgInfo: OptionalArgInfo, callerInfoInfo: CallerInfoInfo, _reflArgInfo: ReflectedArgInfo) =
not isParamArrayArg && not isOutArg && not optArgInfo.IsOptional && callerInfoInfo = NoCallerInfo
let callerObjArgTys = objArgs |> List.map (tyOfExpr cenv.g)
@ -9624,7 +9738,7 @@ and TcMethodApplication
if HasHeadType cenv.g cenv.g.tcref_System_Collections_Generic_Dictionary finalCalledMethInfo.ApparentEnclosingType &&
finalCalledMethInfo.IsConstructor &&
not (finalCalledMethInfo.GetParamDatas(cenv.amap, mItem, finalCalledMeth.CalledTyArgs)
|> List.existsSquared (fun (ParamData(_, _, _, _, _, _, ty)) ->
|> List.existsSquared (fun (ParamData(_, _, _, _, _, _, _, ty)) ->
HasHeadType cenv.g cenv.g.tcref_System_Collections_Generic_IEqualityComparer ty)) then
match argsOfAppTy cenv.g finalCalledMethInfo.ApparentEnclosingType with
@ -9659,53 +9773,65 @@ and TcMethodApplication
// Handle adhoc argument conversions
let coerceExpr isOutArg calledArgTy (reflArgInfo: ReflectedArgInfo) callerArgTy m callerArgExpr =
let g = cenv.g
if isByrefTy cenv.g calledArgTy && isRefCellTy cenv.g callerArgTy then
Expr.Op(TOp.RefAddrGet, [destRefCellTy cenv.g callerArgTy], [callerArgExpr], m)
if isByrefTy g calledArgTy && isRefCellTy g callerArgTy then
None, Expr.Op(TOp.RefAddrGet false, [destRefCellTy g callerArgTy], [callerArgExpr], m)
elif isInByrefTy g calledArgTy && not (isByrefTy cenv.g callerArgTy) then
let wrap, callerArgExprAddress, _readonly = mkExprAddrOfExpr g true false NeverMutates callerArgExpr None m
Some wrap, callerArgExprAddress
elif isDelegateTy cenv.g calledArgTy && isFunTy cenv.g callerArgTy then
CoerceFromFSharpFuncToDelegate cenv.g cenv.amap cenv.infoReader ad callerArgTy m callerArgExpr calledArgTy
None, CoerceFromFSharpFuncToDelegate cenv.g cenv.amap cenv.infoReader ad callerArgTy m callerArgExpr calledArgTy
elif isLinqExpressionTy cenv.g calledArgTy && isDelegateTy cenv.g (destLinqExpressionTy cenv.g calledArgTy) && isFunTy cenv.g callerArgTy then
let delegateTy = destLinqExpressionTy cenv.g calledArgTy
let expr = CoerceFromFSharpFuncToDelegate cenv.g cenv.amap cenv.infoReader ad callerArgTy m callerArgExpr delegateTy
mkCallQuoteToLinqLambdaExpression cenv.g m delegateTy (Expr.Quote(expr, ref None, false, m, mkQuotedExprTy cenv.g delegateTy))
None, mkCallQuoteToLinqLambdaExpression cenv.g m delegateTy (Expr.Quote(expr, ref None, false, m, mkQuotedExprTy cenv.g delegateTy))
// auto conversions to quotations (to match auto conversions to LINQ expressions)
elif reflArgInfo.AutoQuote && isQuotedExprTy cenv.g calledArgTy && not (isQuotedExprTy cenv.g callerArgTy) then
match reflArgInfo with
| ReflectedArgInfo.Quote true ->
mkCallLiftValueWithDefn cenv.g m calledArgTy callerArgExpr
None, mkCallLiftValueWithDefn cenv.g m calledArgTy callerArgExpr
| ReflectedArgInfo.Quote false ->
Expr.Quote(callerArgExpr, ref None, false, m, calledArgTy)
None, Expr.Quote(callerArgExpr, ref None, false, m, calledArgTy)
| ReflectedArgInfo.None -> failwith "unreachable" // unreachable due to reflArgInfo.AutoQuote condition
// Note: out args do not need to be coerced
elif isOutArg then
callerArgExpr
None, callerArgExpr
// Note: not all these casts are reported in quotations
else
mkCoerceIfNeeded cenv.g calledArgTy callerArgTy callerArgExpr
None, mkCoerceIfNeeded cenv.g calledArgTy callerArgTy callerArgExpr
// Handle optional arguments
let optArgPreBinder, allArgs, outArgExprs, outArgTmpBinds =
// Handle param array and optional arguments
let optArgPreBinder, paramArrayPreBinders, allArgs, outArgExprs, outArgTmpBinds =
let normalUnnamedArgs =
(finalUnnamedCalledArgs, finalUnnamedCallerArgs) ||> List.map2 (fun called caller -> { NamedArgIdOpt = None; CalledArg=called; CallerArg=caller })
let paramArrayArgs =
let paramArrayPreBinders, paramArrayArgs =
match finalCalledMeth.ParamArrayCalledArgOpt with
| None -> []
| None ->
[], []
| Some paramArrayCalledArg ->
let paramArrayCalledArgElementType = destArrayTy cenv.g paramArrayCalledArg.CalledArgumentType
let es =
finalParamArrayCallerArgs |> List.map (fun callerArg ->
let paramArrayPreBinders, es =
finalParamArrayCallerArgs
|> List.map (fun callerArg ->
let (CallerArg(callerArgTy, m, isOutArg, callerArgExpr)) = callerArg
coerceExpr isOutArg paramArrayCalledArgElementType paramArrayCalledArg.ReflArgInfo callerArgTy m callerArgExpr)
|> List.unzip
[ { NamedArgIdOpt = None; CalledArg=paramArrayCalledArg; CallerArg=CallerArg(paramArrayCalledArg.CalledArgumentType, mMethExpr, false, Expr.Op(TOp.Array, [paramArrayCalledArgElementType], es , mMethExpr)) } ]
let arg =
[ { NamedArgIdOpt = None
CalledArg=paramArrayCalledArg
CallerArg=CallerArg(paramArrayCalledArg.CalledArgumentType, mMethExpr, false, Expr.Op(TOp.Array, [paramArrayCalledArgElementType], es , mMethExpr)) } ]
paramArrayPreBinders, arg
// CLEANUP: Move all this code into some isolated file, e.g. "optional.fs"
//
@ -9782,7 +9908,7 @@ and TcMethodApplication
| PassByRef (ty, dfltVal2) ->
let v, _ = mkCompGenLocal mMethExpr "defaultByrefArg" ty
let wrapper2, rhs = build currCalledArgTy dfltVal2
(wrapper2 >> mkCompGenLet mMethExpr v rhs), mkValAddr mMethExpr (mkLocalValRef v)
(wrapper2 >> mkCompGenLet mMethExpr v rhs), mkValAddr mMethExpr false (mkLocalValRef v)
build calledArgTy dfltVal
| CalleeSide ->
let calledNonOptTy =
@ -9849,7 +9975,7 @@ and TcMethodApplication
let outArgTy = destByrefTy cenv.g calledArgTy
let outv, outArgExpr = mkMutableCompGenLocal mMethExpr "outArg" outArgTy // mutable!
let expr = mkDefault(mMethExpr, outArgTy)
let callerArg = CallerArg(calledArgTy, mMethExpr, false, mkValAddr mMethExpr (mkLocalValRef outv))
let callerArg = CallerArg(calledArgTy, mMethExpr, false, mkValAddr mMethExpr false (mkLocalValRef outv))
let outArg = { NamedArgIdOpt=None;CalledArg=calledArg;CallerArg=callerArg }
(outArg, outArgExpr), mkCompGenBind outv expr)
|> List.unzip
@ -9866,7 +9992,7 @@ and TcMethodApplication
let allArgs =
allArgs |> List.sortBy (fun x -> x.Position)
optArgPreBinder, allArgs, outArgExprs, outArgTmpBinds
optArgPreBinder, paramArrayPreBinders, allArgs, outArgExprs, outArgTmpBinds
let coerce (assignedArg: AssignedCalledArg<_>) =
let isOutArg = assignedArg.CalledArg.IsOutArg
@ -9884,13 +10010,21 @@ and TcMethodApplication
let item = Item.ArgName (defaultArg assignedArg.CalledArg.NameOpt id, assignedArg.CalledArg.CalledArgumentType, Some(ArgumentContainer.Method(finalCalledMethInfo)))
CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad))
let allArgsCoerced = List.map coerce allArgs
let allArgsPreBinders, allArgsCoerced = List.map coerce allArgs |> List.unzip
// Make the call expression
let expr, exprty =
BuildPossiblyConditionalMethodCall cenv env mut mMethExpr isProp finalCalledMethInfo isSuperInit finalCalledMethInst objArgs allArgsCoerced
// Handle byref returns
let expr =
// byref-typed returns get implicitly dereferenced
let vty = tyOfExpr cenv.g expr
if isByrefTy cenv.g vty then
let v, _ = mkCompGenLocal mMethExpr "byrefReturn" vty
mkCompGenLet mMethExpr v expr (mkAddrGet mMethExpr (mkLocalValRef v))
else
expr
// Bind "out" parameters as part of the result tuple
let expr, exprty =
@ -9903,51 +10037,54 @@ and TcMethodApplication
expr, tyOfExpr cenv.g expr
// Handle post-hoc property assignments
let expr =
if isCheckingAttributeCall then expr else
if isNil finalAssignedItemSetters then expr else
let setterExprPrebinders, expr =
if isCheckingAttributeCall then
[], expr
elif isNil finalAssignedItemSetters then
[], expr
else
// This holds the result of the call
let objv, objExpr = mkMutableCompGenLocal mMethExpr "returnVal" exprty // mutable in case it's a struct
// This expression mutates the properties on the result of the call
let propSetExpr =
(mkUnit cenv.g mMethExpr, finalAssignedItemSetters) ||> List.fold (fun acc (AssignedItemSetter(id, setter, CallerArg(callerArgTy, m, isOptCallerArg, argExpr))) ->
let setterExprPrebinders, propSetExpr =
(mkUnit cenv.g mMethExpr, finalAssignedItemSetters) ||> List.mapFold (fun acc (AssignedItemSetter(id, setter, CallerArg(callerArgTy, m, isOptCallerArg, argExpr))) ->
if isOptCallerArg then error(Error(FSComp.SR.tcInvalidOptionalAssignmentToPropertyOrField(), m))
let action, defnItem =
let argExprPrebinder, action, defnItem =
match setter with
| AssignedPropSetter (pinfo, pminfo, pminst) ->
MethInfoChecks cenv.g cenv.amap true None [objExpr] ad m pminfo
let calledArgTy = List.head (List.head (pminfo.GetParamTypes(cenv.amap, m, pminst)))
let argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr
let argExprPrebinder, argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr
let mut = (if isStructTy cenv.g (tyOfExpr cenv.g objExpr) then DefinitelyMutates else PossiblyMutates)
let action = BuildPossiblyConditionalMethodCall cenv env mut m true pminfo NormalValUse pminst [objExpr] [argExpr] |> fst
action, Item.Property (pinfo.PropertyName, [pinfo])
argExprPrebinder, action, Item.Property (pinfo.PropertyName, [pinfo])
| AssignedILFieldSetter finfo ->
// Get or set instance IL field
ILFieldInstanceChecks cenv.g cenv.amap ad m finfo
let calledArgTy = finfo.FieldType (cenv.amap, m)
let argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr
let argExprPrebinder, argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr
let action = BuildILFieldSet cenv.g m objExpr finfo argExpr
action, Item.ILField finfo
argExprPrebinder, action, Item.ILField finfo
| AssignedRecdFieldSetter rfinfo ->
RecdFieldInstanceChecks cenv.g cenv.amap ad m rfinfo
let calledArgTy = rfinfo.FieldType
CheckRecdFieldMutation m denv rfinfo
let argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr
let argExprPrebinder, argExpr = coerceExpr false calledArgTy ReflectedArgInfo.None callerArgTy m argExpr
let action = BuildRecdFieldSet cenv.g m objExpr rfinfo argExpr
action, Item.RecdField rfinfo
argExprPrebinder, action, Item.RecdField rfinfo
// Record the resolution for the Language Service
let item = Item.SetterArg (id, defnItem)
CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, item, emptyTyparInst, ItemOccurence.Use, env.DisplayEnv, ad)
mkCompGenSequential m acc action)
argExprPrebinder, mkCompGenSequential m acc action)
// now put them together
let expr = mkCompGenLet mMethExpr objv expr (mkCompGenSequential mMethExpr propSetExpr objExpr)
expr
setterExprPrebinders, expr
// Build the lambda expression if any
let expr =
@ -9973,6 +10110,10 @@ and TcMethodApplication
expr, tpenv
// Apply the PreBinders, if any
let expr = (expr, setterExprPrebinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr)
let expr = (expr, paramArrayPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr)
let expr = (expr, allArgsPreBinders) ||> List.fold (fun expr argPreBinder -> match argPreBinder with None -> expr | Some f -> f expr)
let expr = optArgPreBinder expr
let expr = objArgPreBinder expr
@ -10181,7 +10322,7 @@ and TcAndBuildFixedExpr cenv env (overallPatTy, fixedExpr, overallExprTy, mBindi
match stripExpr fixedExpr with
| Expr.Op (op, tyargs, args, _) ->
match op, tyargs, args with
| TOp.ValFieldGetAddr rfref, _, [_] -> not rfref.Tycon.IsStructOrEnumTycon
| TOp.ValFieldGetAddr (rfref, _), _, [_] -> not rfref.Tycon.IsStructOrEnumTycon
| TOp.ILAsm ([ I_ldflda (fspec)], _), _, _ -> fspec.DeclaringType.Boxity = ILBoxity.AsObject
| TOp.ILAsm ([ I_ldelema _], _), _, _ -> true
| TOp.RefAddrGet _, _, _ -> true
@ -10230,7 +10371,7 @@ and TcAndBuildFixedExpr cenv env (overallPatTy, fixedExpr, overallExprTy, mBindi
//
mkCompGenLetIn mBinding "tmpArray" overallExprTy fixedExpr (fun (_, ve) ->
// This is &arr.[0]
let elemZeroAddress = mkArrayElemAddress cenv.g (ILReadonly.NormalAddress, false, ILArrayShape.SingleDimensional, elemTy, ve, mkInt32 cenv.g mBinding 0, mBinding)
let elemZeroAddress = mkArrayElemAddress cenv.g (false, ILReadonly.NormalAddress, false, ILArrayShape.SingleDimensional, elemTy, [ve; mkInt32 cenv.g mBinding 0], mBinding)
// check for non-null and non-empty
let zero = mkConvToNativeInt cenv.g (mkInt32 cenv.g mBinding 0) mBinding
// This is arr.Length
@ -12418,6 +12559,12 @@ module IncrClassChecking =
| InVar false -> true
| _ -> false
member localRep.IsValRepresentedAsMethod (v:Val) =
localRep.IsValWithRepresentation(v) &&
match localRep.LookupRepr(v) with
| InMethod _ -> true
| _ -> false
/// Make the elaborated expression that represents a use of a
/// a "let v = ..." class binding
member localRep.MakeValueLookup thisValOpt tinst safeStaticInitInfo v tyargs m =
@ -12463,19 +12610,19 @@ module IncrClassChecking =
| InMethod _, _ ->
error(InternalError("Local was given method storage, yet later it's been assigned to", m))
member localRep.MakeValueGetAddress thisValOpt tinst safeStaticInitInfo v m =
member localRep.MakeValueGetAddress readonly thisValOpt tinst safeStaticInitInfo v m =
let g = localRep.RepInfoTcGlobals
match localRep.LookupRepr v, thisValOpt with
| InField(false, _, rfref), Some(thisVal) ->
let thise = exprForVal m thisVal
mkRecdFieldGetAddrViaExprAddr(thise, rfref, tinst, m)
mkRecdFieldGetAddrViaExprAddr(readonly, thise, rfref, tinst, m)
| InField(false, _, _rfref), None ->
error(InternalError("Unexpected missing 'this' variable in MakeValueGetAddress", m))
| InField(true, idx, rfref), _ ->
let expr = mkStaticRecdFieldGetAddr(rfref, tinst, m)
let expr = mkStaticRecdFieldGetAddr(readonly, rfref, tinst, m)
MakeCheckSafeInit g tinst safeStaticInitInfo (mkInt g m idx) expr
| InVar _, _ ->
mkValAddr m (mkLocalValRef v)
mkValAddr m readonly (mkLocalValRef v)
| InMethod _, _ ->
error(InternalError("Local was given method storage, yet later it's address was required", m))
@ -12515,42 +12662,42 @@ module IncrClassChecking =
/// Fix up the references to the locals, e.g.
/// v -> this.fieldv
/// f x -> this.method x
member localRep.FixupIncrClassExprPhase2C thisValOpt safeStaticInitInfo (thisTyInst:TypeInst) expr =
member localRep.FixupIncrClassExprPhase2C cenv thisValOpt safeStaticInitInfo (thisTyInst:TypeInst) expr =
// fixup: intercept and expr rewrite
let FixupExprNode rw e =
//dprintfn "Fixup %s" (showL (exprL e))
let g = localRep.RepInfoTcGlobals
let e = NormalizeAndAdjustPossibleSubsumptionExprs g e
match e with
// Rewrite references to applied let-bound-functions-compiled-as-methods
| Expr.App(Expr.Val (ValDeref(v), _, _), _, tyargs, args, m)
when (localRep.IsValWithRepresentation(v) &&
(match localRep.LookupRepr(v) with
| InMethod _ -> true //(methodVal.Typars.Length > thisTyInst.Length)
| _ -> false )) ->
// Rewrite references to applied recursive let-bound-functions-compiled-as-methods
// Rewrite references to applied recursive generic let-bound-functions-compiled-as-methods
| Expr.App(Expr.Val (ValDeref v, _, _), _, tyargs, args, m)
| Expr.App(Expr.Link {contents = Expr.Val (ValDeref v, _, _) }, _, tyargs, args, m)
| Expr.App(Expr.Link {contents = Expr.App(Expr.Val (ValDeref v, _, _), _, tyargs, [], _) }, _, [], args, m)
when localRep.IsValRepresentedAsMethod(v) && not (cenv.recUses.ContainsKey v) ->
//dprintfn "Found application of %s" v.LogicalName
let g = localRep.RepInfoTcGlobals
let expr = localRep.MakeValueLookup thisValOpt thisTyInst safeStaticInitInfo v tyargs m
let args = args |> List.map rw
Some (MakeApplicationAndBetaReduce g (expr, (tyOfExpr g expr), [], args, m))
// Rewrite references to values stored as fields and first class uses of method values
| Expr.Val (ValDeref(v), _, m)
| Expr.Val (ValDeref v, _, m)
when localRep.IsValWithRepresentation(v) ->
//dprintfn "Found use of %s" v.LogicalName
Some (localRep.MakeValueLookup thisValOpt thisTyInst safeStaticInitInfo v [] m)
// Rewrite assignments to mutable values stored as fields
| Expr.Op(TOp.LValueOp (LSet, ValDeref(v)) , [], [arg], m)
| Expr.Op(TOp.LValueOp (LSet, ValDeref v) , [], [arg], m)
when localRep.IsValWithRepresentation(v) ->
let arg = rw arg
Some (localRep.MakeValueAssign thisValOpt thisTyInst safeStaticInitInfo v arg m)
// Rewrite taking the address of mutable values stored as fields
| Expr.Op(TOp.LValueOp (LGetAddr, ValDeref(v)), [], [] , m)
| Expr.Op(TOp.LValueOp (LAddrOf readonly, ValDeref v), [], [] , m)
when localRep.IsValWithRepresentation(v) ->
Some (localRep.MakeValueGetAddress thisValOpt thisTyInst safeStaticInitInfo v m)
Some (localRep.MakeValueGetAddress readonly thisValOpt thisTyInst safeStaticInitInfo v m)
| _ -> None
Tastops.RewriteExpr { PreIntercept = Some FixupExprNode
@ -12657,7 +12804,7 @@ module IncrClassChecking =
let TransBind (reps:IncrClassReprInfo) (TBind(v, rhsExpr, spBind)) =
if v.MustInline then
error(Error(FSComp.SR.tcLocalClassBindingsCannotBeInline(), v.Range))
let rhsExpr = reps.FixupIncrClassExprPhase2C (Some thisVal) safeStaticInitInfo thisTyInst rhsExpr
let rhsExpr = reps.FixupIncrClassExprPhase2C cenv (Some thisVal) safeStaticInitInfo thisTyInst rhsExpr
// The initialization of the 'ref cell' variable for 'this' is the only binding which comes prior to the super init
let isPriorToSuperInit =
@ -12709,7 +12856,7 @@ module IncrClassChecking =
match safeStaticInitInfo with
| SafeInitField (rfref, _) ->
let setExpr = mkStaticRecdFieldSet (rfref, thisTyInst, mkInt cenv.g m idx, m)
let setExpr = reps.FixupIncrClassExprPhase2C (Some(thisVal)) NoSafeInitInfo thisTyInst setExpr
let setExpr = reps.FixupIncrClassExprPhase2C cenv (Some(thisVal)) NoSafeInitInfo thisTyInst setExpr
Some setExpr
| NoSafeInitInfo ->
None
@ -12745,7 +12892,7 @@ module IncrClassChecking =
([], actions, methodBinds), reps
| IncrClassDo (doExpr, isStatic) ->
let doExpr = reps.FixupIncrClassExprPhase2C (Some(thisVal)) safeStaticInitInfo thisTyInst doExpr
let doExpr = reps.FixupIncrClassExprPhase2C cenv (Some(thisVal)) safeStaticInitInfo thisTyInst doExpr
let binder = (fun e -> mkSequential SequencePointsAtSeq doExpr.Range doExpr e)
let isPriorToSuperInit = false
if isStatic then
@ -12765,7 +12912,7 @@ module IncrClassChecking =
| None -> ()
| Some v ->
let setExpr = mkRefCellSet cenv.g m ctorInfo.InstanceCtorThisVal.Type (exprForVal m v) (exprForVal m ctorInfo.InstanceCtorThisVal)
let setExpr = reps.FixupIncrClassExprPhase2C (Some(thisVal)) safeStaticInitInfo thisTyInst setExpr
let setExpr = reps.FixupIncrClassExprPhase2C cenv (Some(thisVal)) safeStaticInitInfo thisTyInst setExpr
let binder = (fun e -> mkSequential SequencePointsAtSeq setExpr.Range setExpr e)
let isPriorToSuperInit = false
yield (isPriorToSuperInit, binder) ]
@ -12779,7 +12926,7 @@ module IncrClassChecking =
[ match ctorInfo.InstanceCtorSafeInitInfo with
| SafeInitField (rfref, _) ->
let setExpr = mkRecdFieldSetViaExprAddr (exprForVal m thisVal, rfref, thisTyInst, mkOne cenv.g m, m)
let setExpr = reps.FixupIncrClassExprPhase2C (Some(thisVal)) safeStaticInitInfo thisTyInst setExpr
let setExpr = reps.FixupIncrClassExprPhase2C cenv (Some(thisVal)) safeStaticInitInfo thisTyInst setExpr
let binder = (fun e -> mkSequential SequencePointsAtSeq setExpr.Range setExpr e)
let isPriorToSuperInit = false
yield (isPriorToSuperInit, binder)
@ -12862,7 +13009,7 @@ module IncrClassChecking =
// Rewrite the expression to convert it to a load of a field if needed.
// We are allowed to load fields from our own object even though we haven't called
// the super class constructor yet.
let ldexpr = reps.FixupIncrClassExprPhase2C (Some(thisVal)) safeStaticInitInfo thisTyInst (exprForVal m v)
let ldexpr = reps.FixupIncrClassExprPhase2C cenv (Some(thisVal)) safeStaticInitInfo thisTyInst (exprForVal m v)
mkInvisibleLet m v ldexpr inheritsExpr
| _ ->
inheritsExpr
@ -13536,7 +13683,7 @@ module MutRecBindingChecking =
// Members have at least as many type parameters as the enclosing class. Just grab the type variables for the type.
let thisTyInst = List.map mkTyparTy (List.take (tcref.Typars(v.Range).Length) v.Typars)
let x = localReps.FixupIncrClassExprPhase2C thisValOpt safeStaticInitInfo thisTyInst x
let x = localReps.FixupIncrClassExprPhase2C cenv thisValOpt safeStaticInitInfo thisTyInst x
{ pgrbind with Binding = TBind(v, x, spBind) } )
@ -14197,7 +14344,7 @@ module TyconConstraintInference =
// If the type was excluded, say why
if not res then
match TryFindFSharpBoolAttribute g g.attrib_StructuralEqualityAttribute tycon.Attribs with
| Some(true) ->
| Some true ->
if AugmentWithHashCompare.TyconIsCandidateForAugmentationWithEquals cenv.g tycon then
match structuralTypes |> List.tryFind (fst >> checkIfFieldTypeSupportsEquality tycon >> not) with
| None ->

Просмотреть файл

@ -629,6 +629,9 @@ and
/// F# syntax: expr.ident...ident <- expr
| DotSet of SynExpr * longDotId:LongIdentWithDots * SynExpr * range:range
/// F# syntax: expr <- expr
| Set of SynExpr * SynExpr * range:range
/// F# syntax: expr.[expr,...,expr]
| DotIndexedGet of SynExpr * SynIndexerArg list * range * range:range
@ -763,6 +766,7 @@ and
| SynExpr.DotIndexedSet (range=m)
| SynExpr.DotGet (range=m)
| SynExpr.DotSet (range=m)
| SynExpr.Set (range=m)
| SynExpr.DotNamedIndexedPropertySet (range=m)
| SynExpr.LibraryOnlyUnionCaseFieldGet (range=m)
| SynExpr.LibraryOnlyUnionCaseFieldSet (range=m)
@ -824,6 +828,7 @@ and
| SynExpr.DotIndexedGet (range=m)
| SynExpr.DotIndexedSet (range=m)
| SynExpr.DotSet (range=m)
| SynExpr.Set (range=m)
| SynExpr.DotNamedIndexedPropertySet (range=m)
| SynExpr.LibraryOnlyUnionCaseFieldGet (range=m)
| SynExpr.LibraryOnlyUnionCaseFieldSet (range=m)
@ -887,6 +892,7 @@ and
| SynExpr.DotIndexedSet (range=m)
| SynExpr.DotGet (range=m)
| SynExpr.DotSet (range=m)
| SynExpr.Set (range=m)
| SynExpr.DotNamedIndexedPropertySet (range=m)
| SynExpr.LibraryOnlyUnionCaseFieldGet (range=m)
| SynExpr.LibraryOnlyUnionCaseFieldSet (range=m)
@ -1857,7 +1863,8 @@ let mkSynAssign (l: SynExpr) (r: SynExpr) =
mkSynDotParenSet m a b r
| SynExpr.App (_, _, SynExpr.LongIdent(false,v,None,_),x,_) -> SynExpr.NamedIndexedPropertySet (v,x,r,m)
| SynExpr.App (_, _, SynExpr.DotGet(e,_,v,_),x,_) -> SynExpr.DotNamedIndexedPropertySet (e,v,x,r,m)
| _ -> errorR(Error(FSComp.SR.astInvalidExprLeftHandOfAssignment(), m)); l // return just the LHS, so the typechecker can see it and capture expression typings that may be useful for dot lookups
| l -> SynExpr.Set (l,r,m)
//| _ -> errorR(Error(FSComp.SR.astInvalidExprLeftHandOfAssignment(), m)); l // return just the LHS, so the typechecker can see it and capture expression typings that may be useful for dot lookups
let rec mkSynDot dotm m l r =
match l with
@ -2356,6 +2363,7 @@ let rec synExprContainsError inpExpr =
| SynExpr.NamedIndexedPropertySet (_,e1,e2,_)
| SynExpr.DotSet (e1,_,e2,_)
| SynExpr.Set (e1,e2,_)
| SynExpr.LibraryOnlyUnionCaseFieldSet (e1,_,_,e2,_)
| SynExpr.JoinIn (e1,_,e2,_)
| SynExpr.App (_,_,e1,e2,_) ->

Просмотреть файл

@ -147,9 +147,9 @@ let TransformExpr g (nvs: ValMap<_>) exprF expr =
Some (mkRefCellSet g m v.Type nve arg)
// Rewrite taking the address of mutable values
| Expr.Op(TOp.LValueOp (LGetAddr, ValDeref(v)), [], [] , m) when nvs.ContainsVal v ->
| Expr.Op(TOp.LValueOp (LAddrOf readonly, ValDeref(v)), [], [], m) when nvs.ContainsVal v ->
let _nv,nve = nvs.[v]
Some (mkRecdFieldGetAddrViaExprAddr (nve, mkRefCellContentsRef g, [v.Type], m))
Some (mkRecdFieldGetAddrViaExprAddr (readonly, nve, mkRefCellContentsRef g, [v.Type], m))
| _ -> None
@ -183,7 +183,8 @@ let TransformImplFile g amap implFile =
|> ValMap.OfList
implFile |>
RewriteImplFile { PreIntercept = Some(TransformExpr g nvs)
RewriteImplFile
{ PreIntercept = Some(TransformExpr g nvs)
PreInterceptBinding = Some(TransformBinding g nvs)
PostTransform = (fun _ -> None)
IsUnderQuotations = false }

Просмотреть файл

@ -168,7 +168,9 @@ let rec ImportILType (env:ImportMap) m tinst typ =
let inst = tspec.GenericArgs |> List.map (ImportILType env m tinst)
ImportTyconRefApp env tcref inst
| ILType.Modified(_,tref,ILType.Byref ty) when tref.Name = "System.Runtime.InteropServices.InAttribute" -> mkInByrefTy env.g (ImportILType env m tinst ty)
| ILType.Byref ty -> mkByrefTy env.g (ImportILType env m tinst ty)
| ILType.Ptr ILType.Void when env.g.voidptr_tcr.CanDeref -> mkVoidPtrTy env.g
| ILType.Ptr ty -> mkNativePtrTy env.g (ImportILType env m tinst ty)
| ILType.FunctionPointer _ -> env.g.nativeint_ty (* failwith "cannot import this kind of type (ptr, fptr)" *)
| ILType.Modified(_,_,ty) ->
@ -260,6 +262,9 @@ let rec ImportProvidedType (env:ImportMap) (m:range) (* (tinst:TypeInst) *) (st:
mkByrefTy g elemTy
elif st.PUntaint((fun st -> st.IsPointer),m) then
let elemTy = (ImportProvidedType env m (* tinst *) (st.PApply((fun st -> st.GetElementType()),m)))
if isUnitTy g elemTy || isVoidTy g elemTy && g.voidptr_tcr.CanDeref then
mkVoidPtrTy g
else
mkNativePtrTy g elemTy
else

Просмотреть файл

@ -573,7 +573,7 @@ type ParamNameAndType =
/// Full information about a parameter returned for use by the type checker and language service.
type ParamData =
/// ParamData(isParamArray, isOut, optArgInfo, callerInfoInfo, nameOpt, reflArgInfo, ttype)
ParamData of bool * bool * OptionalArgInfo * CallerInfoInfo * Ident option * ReflectedArgInfo * TType
ParamData of bool * bool * bool * OptionalArgInfo * CallerInfoInfo * Ident option * ReflectedArgInfo * TType
//-------------------------------------------------------------------------
@ -1182,6 +1182,13 @@ type MethInfo =
| ILMeth (_,_,Some _) -> true
| _ -> false
/// Indicates if this is an extension member (e.g. on a struct) that takes a byref arg
member x.ObjArgNeedsAddress (amap: Import.ImportMap, m) =
(x.IsStruct && not x.IsExtensionMember) ||
match x.GetObjArgTypes (amap, m, x.FormalMethodInst) with
| [h] -> isByrefTy amap.g h
| _ -> false
/// Indicates if this is an F# extension member.
member x.IsFSharpStyleExtensionMember =
match x with FSMeth (_,_,vref,_) -> vref.IsExtensionMember | _ -> false
@ -1350,6 +1357,7 @@ type MethInfo =
| Some _ -> ReflectedArgInfo.Quote false
| _ -> ReflectedArgInfo.None
let isOutArg = (p.IsOut && not p.IsIn)
let isInArg = (p.IsIn && not p.IsOut)
// Note: we get default argument values from VB and other .NET language metadata
let optArgInfo = OptionalArgInfo.FromILParameter g amap m ilMethInfo.MetadataScope ilMethInfo.DeclaringTypeInst p
@ -1369,7 +1377,7 @@ type MethInfo =
if p.Type.TypeRef.FullName = "System.Int32" then CallerFilePath
else CallerLineNumber
yield (isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo) ] ]
yield (isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo) ] ]
| FSMeth(g,_,vref,_) ->
GetArgInfosOfMember x.IsCSharpStyleExtensionMember g vref
@ -1379,7 +1387,8 @@ type MethInfo =
match TryFindFSharpBoolAttributeAssumeFalse g g.attrib_ReflectedDefinitionAttribute argInfo.Attribs with
| Some b -> ReflectedArgInfo.Quote b
| None -> ReflectedArgInfo.None
let isOutArg = HasFSharpAttribute g g.attrib_OutAttribute argInfo.Attribs && isByrefTy g ty
let isOutArg = (HasFSharpAttribute g g.attrib_OutAttribute argInfo.Attribs && isByrefTy g ty) || isOutByrefTy g ty
let isInArg = (HasFSharpAttribute g g.attrib_InAttribute argInfo.Attribs && isByrefTy g ty) || isInByrefTy g ty
let isCalleeSideOptArg = HasFSharpAttribute g g.attrib_OptionalArgumentAttribute argInfo.Attribs
let isCallerSideOptArg = HasFSharpAttributeOpt g g.attrib_OptionalAttribute argInfo.Attribs
let optArgInfo =
@ -1430,7 +1439,7 @@ type MethInfo =
| Some optTy when typeEquiv g g.int32_ty optTy -> CallerFilePath
| _ -> CallerLineNumber
(isParamArrayArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo))
(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo))
| DefaultStructCtor _ ->
[[]]
@ -1446,7 +1455,9 @@ type MethInfo =
| Some ([ Some (:? bool as b) ], _) -> ReflectedArgInfo.Quote b
| Some _ -> ReflectedArgInfo.Quote false
| None -> ReflectedArgInfo.None
yield (isParamArrayArg, p.PUntaint((fun p -> p.IsOut), m), optArgInfo, NoCallerInfo, reflArgInfo)] ]
let isOutArg = p.PUntaint((fun p -> p.IsOut && not p.IsIn), m)
let isInArg = p.PUntaint((fun p -> p.IsIn && not p.IsOut), m)
yield (isParamArrayArg, isInArg, isOutArg, optArgInfo, NoCallerInfo, reflArgInfo)] ]
#endif
@ -1546,12 +1557,12 @@ type MethInfo =
#endif
let paramAttribs = x.GetParamAttribs(amap, m)
(paramAttribs,paramNamesAndTypes) ||> List.map2 (List.map2 (fun (isParamArrayArg,isOutArg,optArgInfo,callerInfoInfo,reflArgInfo) (ParamNameAndType(nmOpt,pty)) ->
ParamData(isParamArrayArg,isOutArg,optArgInfo,callerInfoInfo,nmOpt,reflArgInfo,pty)))
(paramAttribs,paramNamesAndTypes) ||> List.map2 (List.map2 (fun (isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfoInfo, reflArgInfo) (ParamNameAndType(nmOpt,pty)) ->
ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfoInfo, nmOpt, reflArgInfo, pty)))
/// Get the ParamData objects for the parameters of a MethInfo
member x.HasParamArrayArg(amap, m, minst) =
x.GetParamDatas(amap, m, minst) |> List.existsSquared (fun (ParamData(isParamArrayArg,_,_,_,_,_,_)) -> isParamArrayArg)
x.GetParamDatas(amap, m, minst) |> List.existsSquared (fun (ParamData(isParamArrayArg,_,_,_,_,_,_,_)) -> isParamArrayArg)
/// Select all the type parameters of the declaring type of a method.
@ -2134,7 +2145,7 @@ type PropInfo =
/// Get the details of the indexer parameters associated with the property
member x.GetParamDatas(amap,m) =
x.GetParamNamesAndTypes(amap,m)
|> List.map (fun (ParamNameAndType(nmOpt,pty)) -> ParamData(false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None, pty))
|> List.map (fun (ParamNameAndType(nmOpt,pty)) -> ParamData(false, false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None, pty))
/// Get the types of the indexer parameters associated with the property
member x.GetParamTypes(amap,m) =

Просмотреть файл

@ -663,6 +663,9 @@ module ParsedInput =
walkExpr e1
addLongIdentWithDots idents
walkExpr e2
| SynExpr.Set (e1, e2, _) ->
walkExpr e1
walkExpr e2
| SynExpr.DotIndexedGet (e, args, _, _) ->
walkExpr e
List.iter walkIndexerArg args

Просмотреть файл

@ -85,14 +85,14 @@ module internal DescriptionListsImpl =
else
// TODO: in this case ucinst is ignored - it gives the instantiation of the type parameters of
// the union type containing this case.
NicePrint.layoutOfParamData denv (ParamData(false, false, NotOptional, NoCallerInfo, Some f.Id, ReflectedArgInfo.None, f.FormalType))
NicePrint.layoutOfParamData denv (ParamData(false, false, false, NotOptional, NoCallerInfo, Some f.Id, ReflectedArgInfo.None, f.FormalType))
FSharpMethodGroupItemParameter(
name=initial.ParameterName,
canonicalTypeTextForSorting=initial.CanonicalTypeTextForSorting,
display=display,
isOptional=false)
let ParamOfParamData g denv (ParamData(_isParamArrayArg, _isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty) as paramData) =
let ParamOfParamData g denv (ParamData(_isParamArrayArg, _isInArg, _isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty) as paramData) =
FSharpMethodGroupItemParameter(
name = (match nmOpt with None -> "" | Some pn -> pn.idText),
canonicalTypeTextForSorting = printCanonicalizedTypeName g denv pty,
@ -103,7 +103,7 @@ module internal DescriptionListsImpl =
let PrettyParamsOfParamDatas g denv typarInst (paramDatas:ParamData list) rty =
let paramInfo,paramTypes =
paramDatas
|> List.map (fun (ParamData(isParamArrayArg, _isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) ->
|> List.map (fun (ParamData(isParamArrayArg, _isInArg, _isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) ->
let isOptArg = optArgInfo.IsOptional
match nmOpt, isOptArg, tryDestOptionTy denv.g pty with
// Layout an optional argument
@ -237,7 +237,7 @@ module internal DescriptionListsImpl =
let firstCurriedParamDatas =
firstCurriedArgInfo
|> List.map ParamNameAndType.FromArgInfo
|> List.map (fun (ParamNameAndType(nmOpt, pty)) -> ParamData(false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None, pty))
|> List.map (fun (ParamNameAndType(nmOpt, pty)) -> ParamData(false, false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None, pty))
// Adjust the return type so it only strips the first argument
let curriedRetTy =
@ -321,7 +321,7 @@ module internal DescriptionListsImpl =
| None ->
let argNamesAndTys = SymbolHelpers.ParamNameAndTypesOfUnaryCustomOperation g minfo
let argTys, _ = PrettyTypes.PrettifyTypes g (argNamesAndTys |> List.map (fun (ParamNameAndType(_,ty)) -> ty))
let paramDatas = (argNamesAndTys, argTys) ||> List.map2 (fun (ParamNameAndType(nmOpt, _)) argTy -> ParamData(false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None,argTy))
let paramDatas = (argNamesAndTys, argTys) ||> List.map2 (fun (ParamNameAndType(nmOpt, _)) argTy -> ParamData(false, false, false, NotOptional, NoCallerInfo, nmOpt, ReflectedArgInfo.None,argTy))
let rty = minfo.GetFSharpReturnTy(amap, m, minfo.FormalMethodInst)
let _prettyTyparInst, prettyParams, prettyRetTyL, _prettyConstraintsL = PrettyParamsOfParamDatas g denv item.TyparInst paramDatas rty
@ -342,7 +342,7 @@ module internal DescriptionListsImpl =
let (SigOfFunctionForDelegate(_, _, _, fty)) = GetSigOfFunctionForDelegate infoReader delty m AccessibleFromSomewhere
// No need to pass more generic type information in here since the instanitations have already been applied
let _prettyTyparInst, prettyParams, prettyRetTyL, _prettyConstraintsL = PrettyParamsOfParamDatas g denv item.TyparInst [ParamData(false, false, NotOptional, NoCallerInfo, None, ReflectedArgInfo.None, fty)] delty
let _prettyTyparInst, prettyParams, prettyRetTyL, _prettyConstraintsL = PrettyParamsOfParamDatas g denv item.TyparInst [ParamData(false, false, false, NotOptional, NoCallerInfo, None, ReflectedArgInfo.None, fty)] delty
// FUTURE: prettyTyparInst is the pretty version of the known instantiations of type parameters in the output. It could be returned
// for display as part of the method group

Просмотреть файл

@ -840,17 +840,22 @@ module internal InterfaceStubGenerator =
| SynExpr.Ident(_ident) ->
None
| SynExpr.LongIdent(_, _longIdent, _altNameRefCell, _range) ->
None
| SynExpr.LongIdentSet(_longIdent, synExpr, _range) ->
walkExpr synExpr
| SynExpr.DotGet(synExpr, _dotm, _longIdent, _range) ->
walkExpr synExpr
| SynExpr.DotSet(synExpr1, _longIdent, synExpr2, _range) ->
List.tryPick walkExpr [synExpr1; synExpr2]
| SynExpr.Set(synExpr1, synExpr2, _range) ->
List.tryPick walkExpr [synExpr1; synExpr2]
| SynExpr.DotIndexedGet(synExpr, IndexerArgList synExprList, _range, _range2) ->
Option.orElse (walkExpr synExpr) (List.tryPick walkExpr synExprList)

Просмотреть файл

@ -394,7 +394,8 @@ module public AstTraversal =
| SynExpr.LongIdent(_, _longIdent, _altNameRefCell, _range) -> None
| SynExpr.LongIdentSet(_longIdent, synExpr, _range) -> traverseSynExpr synExpr
| SynExpr.DotGet(synExpr, _dotm, _longIdent, _range) -> traverseSynExpr synExpr
| SynExpr.DotSet(synExpr, _longIdent, synExpr2, _range) ->
| SynExpr.Set(synExpr, synExpr2, _)
| SynExpr.DotSet(synExpr, _, synExpr2, _) ->
[dive synExpr synExpr.Range traverseSynExpr
dive synExpr2 synExpr2.Range traverseSynExpr]
|> pick expr

Просмотреть файл

@ -223,10 +223,14 @@ module Structure =
| SynExpr.InferredUpcast (e,_)
| SynExpr.DotGet (e,_,_,_)
| SynExpr.Do (e,_)
| SynExpr.DotSet (e,_,_,_)
| SynExpr.Typed (e,_,_)
| SynExpr.DotIndexedGet (e,_,_,_)
| SynExpr.DotIndexedSet (e,_,_,_,_,_) -> parseExpr e
| SynExpr.DotIndexedGet (e,_,_,_) ->
parseExpr e
| SynExpr.Set (e1,e2,_)
| SynExpr.DotSet (e1,_,e2,_)
| SynExpr.DotIndexedSet (e1,_,e2,_,_,_) ->
parseExpr e1
parseExpr e2
| SynExpr.New (_,_,expr,r) ->
rcheck Scope.New Collapse.Below r expr.Range
parseExpr expr

Просмотреть файл

@ -212,6 +212,7 @@ type FSharpParseFileResults(errors: FSharpErrorInfo[], input: Ast.ParsedInput op
| SynExpr.NamedIndexedPropertySet (_,e1,e2,_)
| SynExpr.DotSet (e1,_,e2,_)
| SynExpr.Set (e1,e2,_)
| SynExpr.LibraryOnlyUnionCaseFieldSet (e1,_,_,e2,_)
| SynExpr.App (_,_,e1,e2,_) ->
yield! walkExpr false e1
@ -480,6 +481,13 @@ module UntypedParseImpl =
else
// see comment below for SynExpr.DotSet
Some((unionRanges synExpr.Range r))
| SynExpr.Set(synExpr, synExpr2, range) ->
if AstTraversal.rangeContainsPosLeftEdgeInclusive synExpr.Range pos then
traverseSynExpr synExpr
elif AstTraversal.rangeContainsPosLeftEdgeInclusive synExpr2.Range pos then
traverseSynExpr synExpr2
else
Some(range)
| SynExpr.DotSet(synExpr, LongIdentWithDots(longIdent,_), synExpr2, _range) ->
if AstTraversal.rangeContainsPosLeftEdgeInclusive synExpr.Range pos then
traverseSynExpr synExpr
@ -642,6 +650,10 @@ module UntypedParseImpl =
dive lidwd lidwd.Range (traverseLidOrElse(Some exprLeft))
dive exprRhs exprRhs.Range traverseSynExpr
] |> pick expr
| SynExpr.Set(exprLeft, exprRhs, _m) ->
[ dive exprLeft exprLeft.Range traverseSynExpr
dive exprRhs exprRhs.Range traverseSynExpr
] |> pick expr
| SynExpr.NamedIndexedPropertySet(lidwd, exprIndexer, exprRhs, _m) ->
[ dive lidwd lidwd.Range (traverseLidOrElse None)
dive exprIndexer exprIndexer.Range traverseSynExpr
@ -843,6 +855,7 @@ module UntypedParseImpl =
| SynExpr.LongIdentSet(_, e, _) -> walkExprWithKind parentKind e
| SynExpr.DotGet(e, _, _, _) -> walkExprWithKind parentKind e
| SynExpr.DotSet(e, _, _, _) -> walkExprWithKind parentKind e
| SynExpr.Set(e, _, _) -> walkExprWithKind parentKind e
| SynExpr.DotIndexedGet(e, args, _, _) -> walkExprWithKind parentKind e |> Option.orElse (List.tryPick walkIndexerArg args)
| SynExpr.DotIndexedSet(e, args, _, _, _, _) -> walkExprWithKind parentKind e |> Option.orElse (List.tryPick walkIndexerArg args)
| SynExpr.NamedIndexedPropertySet(_, e1, e2, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2]

Просмотреть файл

@ -353,7 +353,7 @@ type TypeCheckInfo
methods
|> List.collect (fun meth ->
match meth.GetParamDatas(amap, m, meth.FormalMethodInst) with
| x::_ -> x |> List.choose(fun (ParamData(_isParamArray, _isOut, _optArgInfo, _callerInfoInfo, name, _, ty)) ->
| x::_ -> x |> List.choose(fun (ParamData(_isParamArray, _isInArg, _isOutArg, _optArgInfo, _callerInfoInfo, name, _, ty)) ->
match name with
| Some n -> Some (Item.ArgName(n, ty, Some (ArgumentContainer.Method meth)))
| None -> None

Просмотреть файл

@ -302,10 +302,10 @@ module FSharpExprConvert =
match expr with
| Expr.Op(op, tyargs, args, m) ->
match op, args, tyargs with
| TOp.LValueOp(LGetAddr, vref), _, _ -> exprForValRef m vref
| TOp.ValFieldGetAddr(rfref), [], _ -> mkStaticRecdFieldGet(rfref, tyargs, m)
| TOp.ValFieldGetAddr(rfref), [arg], _ -> mkRecdFieldGetViaExprAddr(exprOfExprAddr cenv arg, rfref, tyargs, m)
| TOp.UnionCaseFieldGetAddr(uref, n), [arg], _ -> mkUnionCaseFieldGetProvenViaExprAddr(exprOfExprAddr cenv arg, uref, tyargs, n, m)
| TOp.LValueOp(LAddrOf _, vref), _, _ -> exprForValRef m vref
| TOp.ValFieldGetAddr(rfref, _), [], _ -> mkStaticRecdFieldGet(rfref, tyargs, m)
| TOp.ValFieldGetAddr(rfref, _), [arg], _ -> mkRecdFieldGetViaExprAddr(exprOfExprAddr cenv arg, rfref, tyargs, m)
| TOp.UnionCaseFieldGetAddr(uref, n, _), [arg], _ -> mkUnionCaseFieldGetProvenViaExprAddr(exprOfExprAddr cenv arg, uref, tyargs, n, m)
| TOp.ILAsm([ I_ldflda(fspec) ], rtys), [arg], _ -> mkAsmExpr([ mkNormalLdfld(fspec) ], tyargs, [exprOfExprAddr cenv arg], rtys, m)
| TOp.ILAsm([ I_ldsflda(fspec) ], rtys), _, _ -> mkAsmExpr([ mkNormalLdsfld(fspec) ], tyargs, args, rtys, m)
| TOp.ILAsm(([ I_ldelema(_ro, _isNativePtr, shape, _tyarg) ] ), _), (arr::idxs), [elemty] ->
@ -581,10 +581,10 @@ module FSharpExprConvert =
let projR = FSharpField(cenv, ucref, n)
E.UnionCaseSet(ConvExpr cenv env e1, typR, mkR, projR, ConvExpr cenv env e2)
| TOp.UnionCaseFieldGetAddr (_ucref, _n), _tyargs, _ ->
| TOp.UnionCaseFieldGetAddr _, _tyargs, _ ->
E.AddressOf(ConvLValueExpr cenv env expr)
| TOp.ValFieldGetAddr(_rfref), _tyargs, _ ->
| TOp.ValFieldGetAddr _, _tyargs, _ ->
E.AddressOf(ConvLValueExpr cenv env expr)
| TOp.ValFieldGet(rfref), tyargs, [] ->
@ -755,7 +755,7 @@ module FSharpExprConvert =
// rebuild reraise<T>() and Convert
mkReraiseLibCall cenv.g toTy m |> ConvExprPrim cenv env
| TOp.LValueOp(LGetAddr, vref), [], [] ->
| TOp.LValueOp(LAddrOf _, vref), [], [] ->
E.AddressOf(ConvExpr cenv env (exprForValRef m vref))
| TOp.LValueOp(LByrefSet, vref), [], [e] ->
@ -815,8 +815,8 @@ module FSharpExprConvert =
let argsR = ConvExprs cenv env args
E.TraitCall(tysR, nm, memFlags, argtysR, tyargsR, argsR)
| TOp.RefAddrGet, [ty], [e] ->
let replExpr = mkRecdFieldGetAddrViaExprAddr(e, mkRefCellContentsRef cenv.g, [ty], m)
| TOp.RefAddrGet readonly, [ty], [e] ->
let replExpr = mkRecdFieldGetAddrViaExprAddr(readonly, e, mkRefCellContentsRef cenv.g, [ty], m)
ConvExprPrim cenv env replExpr
| _ -> wfail (sprintf "unhandled construct in AST", m)

Просмотреть файл

@ -285,7 +285,7 @@ type FSharpSymbol(cenv: SymbolEnv, item: (unit -> Item), access: (FSharpSymbol -
FSharpActivePatternCase(cenv, apinfo, typ, n, None, item) :> _
| Item.ArgName(id, ty, _) ->
FSharpParameter(cenv, ty, {Attribs=[]; Name=Some id}, Some id.idRange, isParamArrayArg=false, isOutArg=false, isOptionalArg=false) :> _
FSharpParameter(cenv, ty, {Attribs=[]; Name=Some id}, Some id.idRange, isParamArrayArg=false, isInArg=false, isOutArg=false, isOptionalArg=false) :> _
// TODO: the following don't currently return any interesting subtype
| Item.ImplicitOp _
@ -1747,11 +1747,11 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
match d with
| P p ->
[ [ for (ParamData(isParamArrayArg, isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) in p.GetParamDatas(cenv.amap, range0) do
[ [ for (ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) in p.GetParamDatas(cenv.amap, range0) do
// INCOMPLETENESS: Attribs is empty here, so we can't look at attributes for
// either .NET or F# parameters
let argInfo: ArgReprInfo = { Name=nmOpt; Attribs= [] }
yield FSharpParameter(cenv, pty, argInfo, x.DeclarationLocationOpt, isParamArrayArg, isOutArg, optArgInfo.IsOptional) ]
yield FSharpParameter(cenv, pty, argInfo, x.DeclarationLocationOpt, isParamArrayArg, isInArg, isOutArg, optArgInfo.IsOptional) ]
|> makeReadOnlyCollection ]
|> makeReadOnlyCollection
@ -1759,11 +1759,11 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
| M m | C m ->
[ for argtys in m.GetParamDatas(cenv.amap, range0, m.FormalMethodInst) do
yield
[ for (ParamData(isParamArrayArg, isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) in argtys do
[ for (ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, _callerInfoInfo, nmOpt, _reflArgInfo, pty)) in argtys do
// INCOMPLETENESS: Attribs is empty here, so we can't look at attributes for
// either .NET or F# parameters
let argInfo: ArgReprInfo = { Name=nmOpt; Attribs= [] }
yield FSharpParameter(cenv, pty, argInfo, x.DeclarationLocationOpt, isParamArrayArg, isOutArg, optArgInfo.IsOptional) ]
yield FSharpParameter(cenv, pty, argInfo, x.DeclarationLocationOpt, isParamArrayArg, isInArg, isOutArg, optArgInfo.IsOptional) ]
|> makeReadOnlyCollection ]
|> makeReadOnlyCollection
@ -1780,7 +1780,7 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
else [typ]
yield
allArguments
|> List.map (fun arg -> FSharpParameter(cenv, arg, { Name=None; Attribs= [] }, x.DeclarationLocationOpt, false, false, false))
|> List.map (fun arg -> FSharpParameter(cenv, arg, { Name=None; Attribs= [] }, x.DeclarationLocationOpt, false, false, false, false))
|> makeReadOnlyCollection ]
|> makeReadOnlyCollection
else makeReadOnlyCollection []
@ -1792,9 +1792,10 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
yield
[ for argty, argInfo in argtys do
let isParamArrayArg = HasFSharpAttribute cenv.g cenv.g.attrib_ParamArrayAttribute argInfo.Attribs
let isInArg = HasFSharpAttribute cenv.g cenv.g.attrib_InAttribute argInfo.Attribs && isByrefTy cenv.g argty
let isOutArg = HasFSharpAttribute cenv.g cenv.g.attrib_OutAttribute argInfo.Attribs && isByrefTy cenv.g argty
let isOptionalArg = HasFSharpAttribute cenv.g cenv.g.attrib_OptionalArgumentAttribute argInfo.Attribs
yield FSharpParameter(cenv, argty, argInfo, x.DeclarationLocationOpt, isParamArrayArg, isOutArg, isOptionalArg) ]
yield FSharpParameter(cenv, argty, argInfo, x.DeclarationLocationOpt, isParamArrayArg, isInArg, isOutArg, isOptionalArg) ]
|> makeReadOnlyCollection ]
|> makeReadOnlyCollection
@ -1810,29 +1811,29 @@ and FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) =
// For non-standard events, just use the delegate type as the ReturnParameter type
e.GetDelegateType(cenv.amap, range0)
FSharpParameter(cenv, rty, retInfo, x.DeclarationLocationOpt, isParamArrayArg=false, isOutArg=false, isOptionalArg=false)
FSharpParameter(cenv, rty, retInfo, x.DeclarationLocationOpt, isParamArrayArg=false, isInArg=false, isOutArg=false, isOptionalArg=false)
| P p ->
// INCOMPLETENESS: Attribs is empty here, so we can't look at return attributes for .NET or F# methods
let retInfo: ArgReprInfo = { Name=None; Attribs= [] }
let rty = p.GetPropertyType(cenv.amap, range0)
FSharpParameter(cenv, rty, retInfo, x.DeclarationLocationOpt, isParamArrayArg=false, isOutArg=false, isOptionalArg=false)
FSharpParameter(cenv, rty, retInfo, x.DeclarationLocationOpt, isParamArrayArg=false, isInArg=false, isOutArg=false, isOptionalArg=false)
| M m | C m ->
// INCOMPLETENESS: Attribs is empty here, so we can't look at return attributes for .NET or F# methods
let retInfo: ArgReprInfo = { Name=None; Attribs= [] }
let rty = m.GetFSharpReturnTy(cenv.amap, range0, m.FormalMethodInst)
FSharpParameter(cenv, rty, retInfo, x.DeclarationLocationOpt, isParamArrayArg=false, isOutArg=false, isOptionalArg=false)
FSharpParameter(cenv, rty, retInfo, x.DeclarationLocationOpt, isParamArrayArg=false, isInArg=false, isOutArg=false, isOptionalArg=false)
| V v ->
match v.ValReprInfo with
| None ->
let _, tau = v.TypeScheme
let _argtysl, rty = stripFunTy cenv.g tau
let empty: ArgReprInfo = { Name=None; Attribs= [] }
FSharpParameter(cenv, rty, empty, x.DeclarationLocationOpt, isParamArrayArg=false, isOutArg=false, isOptionalArg=false)
FSharpParameter(cenv, rty, empty, x.DeclarationLocationOpt, isParamArrayArg=false, isInArg=false, isOutArg=false, isOptionalArg=false)
| Some (ValReprInfo(_typars, argInfos, retInfo)) ->
let tau = v.TauType
let _c, rty = GetTopTauTypeInFSharpForm cenv.g argInfos tau range0
FSharpParameter(cenv, rty, retInfo, x.DeclarationLocationOpt, isParamArrayArg=false, isOutArg=false, isOptionalArg=false)
FSharpParameter(cenv, rty, retInfo, x.DeclarationLocationOpt, isParamArrayArg=false, isInArg=false, isOutArg=false, isOptionalArg=false)
member __.Attributes =
@ -2228,7 +2229,7 @@ and FSharpStaticParameter(cenv, sp: Tainted< ExtensionTyping.ProvidedParameterIn
override x.ToString() =
"static parameter " + x.Name
#endif
and FSharpParameter(cenv, typ:TType, topArgInfo:ArgReprInfo, mOpt, isParamArrayArg, isOutArg, isOptionalArg) =
and FSharpParameter(cenv, typ:TType, topArgInfo:ArgReprInfo, mOpt, isParamArrayArg, isInArg, isOutArg, isOptionalArg) =
inherit FSharpSymbol(cenv,
(fun () ->
let m = match mOpt with Some m -> m | None -> range0
@ -2242,7 +2243,7 @@ and FSharpParameter(cenv, typ:TType, topArgInfo:ArgReprInfo, mOpt, isParamArrayA
member __.cenv: SymbolEnv = cenv
member __.AdjustType(t) = FSharpParameter(cenv, t, topArgInfo, mOpt, isParamArrayArg, isOutArg, isOptionalArg)
member __.AdjustType(t) = FSharpParameter(cenv, t, topArgInfo, mOpt, isParamArrayArg, isInArg, isOutArg, isOptionalArg)
member __.Type: FSharpType = FSharpType(cenv, typ)
@ -2255,6 +2256,8 @@ and FSharpParameter(cenv, typ:TType, topArgInfo:ArgReprInfo, mOpt, isParamArrayA
member __.IsParamArrayArg = isParamArrayArg
member __.IsInArg = isInArg
member __.IsOutArg = isOutArg
member __.IsOptionalArg = isOptionalArg

Просмотреть файл

@ -850,6 +850,9 @@ and [<Class>] public FSharpParameter =
/// Indicate this is an out argument
member IsOutArg: bool
/// Indicate this is an in argument
member IsInArg: bool
/// Indicate this is an optional argument
member IsOptionalArg: bool

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">Neočekávané použití proměnné typu ByRef.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">Hodnota musí být proměnlivá, aby se dal změnit obsah nebo aby se dala převzít adresa typu hodnoty, třeba let mutable x = ...</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">Neplatná mutace konstantního výrazu. Zvažte možnost zkopírovat výraz do lokální proměnné, třeba let mutable x = ...</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">Adresa proměnné {0} se na tomto místě nedá použít. Metoda nebo funkce možná nebude vracet adresu této místní hodnoty.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">Adresa proměnné {0} se na tomto místě nedá použít. Metoda nebo funkce možná nebude vracet adresu této místní hodnoty.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">Soubor {0} se na disku neočekávaně změnil, opakujte prosím načtení.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">Unerwartete Verwendung einer Variablen vom Typ "byref".</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">Ein Wert muss änderbar sein, um die Inhalte eines Werttyps zu mutieren oder seine Adresse zu übernehmen, z.B. "let mutable x = ...".</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">Ungültige Mutation eines konstanten Ausdrucks. Kopieren Sie den Ausdruck in eine änderbare lokale Variable, z.B. "let mutable x = ...".</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">Die Adresse der Variablen "{0}" kann an dieser Stelle nicht verwendet werden. Eine Methode oder Funktion gibt ggf. nicht die Adresse dieses lokalen Werts zurück.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">Die Adresse der Variablen "{0}" kann an dieser Stelle nicht verwendet werden. Eine Methode oder Funktion gibt ggf. nicht die Adresse dieses lokalen Werts zurück.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">Die Datei "{0}" wurde auf dem Datenträger unerwartet geändert. Laden Sie sie erneut.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="new">Unexpected use of a byref-typed variable</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="new">Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="new">The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="new">The file '{0}' changed on disk unexpectedly, please reload.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">Uso inesperado de una variable de tipo byref.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">Un valor debe ser mutable para poder mutar el contenido o tomar la dirección de un tipo de valor; por ejemplo, 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">Mutación no válida de una expresión constante. Considere copiar la expresión en un local mutable; por ejemplo, 'let mutable x = ...'.</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">La dirección de la variable '{0}' no se puede usar en este punto. Puede que el método o la función no devuelvan la dirección de este valor local.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">La dirección de la variable '{0}' no se puede usar en este punto. Puede que el método o la función no devuelvan la dirección de este valor local.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">El archivo "{0}" cambió en el disco de manera inesperada; cárguelo de nuevo.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">Utilisation inattendue d'une variable typée byref</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">Une valeur doit être mutable pour pouvoir muter le contenu ou accepter l'adresse d'un type valeur, par exemple 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">Mutation non valide d'une expression constante. Copiez l'expression dans une variable locale mutable, par exemple 'let mutable x = ...'.</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">Impossible d'utiliser l'adresse de la variable '{0}'. Une méthode ou une fonction ne doit pas retourner l'adresse de cette valeur locale.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">Impossible d'utiliser l'adresse de la variable '{0}'. Une méthode ou une fonction ne doit pas retourner l'adresse de cette valeur locale.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">Changement inattendu du fichier '{0}' sur le disque. Rechargez le fichier.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">Utilizzo non previsto di una variabile di tipo byref</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">Un valore deve essere modificabile per poter modificare i contenuti oppure utilizzare l'indirizzo di un tipo di valore, ad esempio 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">Modifica non valida di un'espressione costante. Provare a copiare l'espressione in un locale modificabile, ad esempio 'let mutable x = ...'.</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">In questo punto non è possibile usare l'indirizzo della variabile '{0}'. Un metodo o una funzione potrebbero non restituire l'indirizzo di questo valore di variabile locale.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">In questo punto non è possibile usare l'indirizzo della variabile '{0}'. Un metodo o una funzione potrebbero non restituire l'indirizzo di questo valore di variabile locale.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">Il file '{0}' è stato modificato su disco in modo imprevisto. Ricaricare.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">byref 型変数の予期しない使用方法です:</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">値の型の内容を変更するか、値の型のアドレスを使用するために、値は変更可能にする必要があります (たとえば、'let mutable x = ...')</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">定数式の変更は無効です。変更可能なローカルに式をコピーしてください (たとえば、'let mutable x = ...')。</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">変数 '{0}' のアドレスはこのポイントでは使用できません。メソッドまたは関数がこのローカル値のアドレスを返さない可能性があります。</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">変数 '{0}' のアドレスはこのポイントでは使用できません。メソッドまたは関数がこのローカル値のアドレスを返さない可能性があります。</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">ファイル '{0}' がディスク上で予期せず変更されました。再度読み込んでください。</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">예기치 않은 byref 형식 변수의 사용입니다.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">내용을 변경하거나 값 형식의 주소를 사용하려면 값을 변경할 수 있어야 합니다(예: 'let mutable x = ...').</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">상수 식을 잘못 변경했습니다. 식을 변경할 수 있는 로컬로 복사하십시오(예: 'let mutable x = ...').</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">지금은 '{0}' 변수의 주소를 사용할 수 없습니다. 메서드 또는 함수가 이 로컬 값의 주소를 반환할 수 없습니다.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">지금은 '{0}' 변수의 주소를 사용할 수 없습니다. 메서드 또는 함수가 이 로컬 값의 주소를 반환할 수 없습니다.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">'{0}' 파일이 디스크에서 예기치 않게 변경되었습니다. 다시 로드하세요.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">Nieoczekiwane użycie zmiennej typu byref</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">Aby można było zmodyfikować zawartość lub pobrać adres typu wartości, wartość musi być modyfikowalna, na przykład „let mutable x = ...”</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">Nieprawidłowa mutacja wyrażenia stałej. Rozważ skopiowanie wyrażenia do modyfikowalnej wartości lokalnej, na przykład „let mutable x = ...”.</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">Adres zmiennej „{0}” nie może być użyty w tym punkcie. Metoda lub funkcja może nie zwrócić adresu tej wartości lokalnej.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">Adres zmiennej „{0}” nie może być użyty w tym punkcie. Metoda lub funkcja może nie zwrócić adresu tej wartości lokalnej.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">Plik „{0}” nieoczekiwanie uległ zmianie na dysku. Załaduj go ponownie.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">Uso inesperado de uma variável do tipo byref</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">Um valor deve ser mutável para que seja possível mudar o conteúdo ou pegar o endereço de um tipo de valor, por exemplo: 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">Mutação inválida de uma expressão constante. Considere copiar a expressão para um local mutável, por exemplo: 'let mutable x = ...'.</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">O endereço da variável '{0}' não pode ser usado neste momento. Um método ou uma função pode não retornar o endereço deste valor local.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">O endereço da variável '{0}' não pode ser usado neste momento. Um método ou uma função pode não retornar o endereço deste valor local.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">O arquivo '{0}' foi alterado no disco inesperadamente. Recarregue-o.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">Недопустимое использование переменной типа byref</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">Чтобы изменить содержимое или получить адрес типа значения, значение должно быть изменяемым, например, "let mutable x = ..."</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">Недопустимое изменение константного выражения. Рекомендуется скопировать выражение в изменяемую локальную переменную, например, "let mutable x = ...".</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">Адрес переменной "{0}" сейчас невозможно использовать. Метод или функция могут не возвратить адрес этого локального значения.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">Адрес переменной "{0}" сейчас невозможно использовать. Метод или функция могут не возвратить адрес этого локального значения.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">Файл "{0}" был неожиданно изменен на диске, повторите загрузку.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">Beklenmeyen byref olarak belirtilmiş değişken kullanımı</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">İçeriği değiştirmek veya değer türünün adresini almak için bir değerin değiştirilebilir olması gerekir, örn. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">Sabit ifadesinin geçersiz olarak değiştirilmesi. İfadeyi değiştirilebilir bir yerel değere kopyalamayı düşünün, örn. 'let mutable x = ...'.</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">'{0}' değişkeninin adresi bu noktada kullanılamaz. Bir metot veya işlev, bu yerel değerin adresini döndüremez.</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">'{0}' değişkeninin adresi bu noktada kullanılamaz. Bir metot veya işlev, bu yerel değerin adresini döndüremez.</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">Diskte '{0}' dosyası beklenmedik şekilde değiştirildi. Lütfen yeniden yükleyin.</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">对 byref 类型化变量的意外使用</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">值必须是可变的以便更改内容或采用值类型的地址例如“let mutable x = ...”</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">常数表达式的变化无效。请考虑将该表达式复制一个可变的本地变量例如“let mutable x = ...”。</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">当前无法使用变量 {0} 的地址。方法或函数可能没有返回该本地值的地址。</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">当前无法使用变量 {0} 的地址。方法或函数可能没有返回该本地值的地址。</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">文件“{0}”在磁盘上意外更改,请重新加载。</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -412,11 +412,6 @@
<target state="translated">未預期的 ByRef 類型變數用法</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="translated">值必須是可變動的,才能變動內容或接受實值類型的位址,例如 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tastInvalidMutationOfConstant">
<source>Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.</source>
<target state="translated">常數運算式無效的變動。請考慮將運算式複製到可變動的區域變數,例如 'let mutable x = ...'。</target>
@ -6523,8 +6518,8 @@
<note />
</trans-unit>
<trans-unit id="chkNoByrefReturnOfLocal">
<source>The address of the variable '{0}' cannot be used at this point. A method or function may not return the address of this local value.</source>
<target state="translated">目前無法使用變數 '{0}' 的位址。方法或函式無法傳回此本機值的位址。</target>
<source>The address of the variable '{0}' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.</source>
<target state="needs-review-translation">目前無法使用變數 '{0}' 的位址。方法或函式無法傳回此本機值的位址。</target>
<note />
</trans-unit>
<trans-unit id="tcNamedActivePattern">
@ -6992,6 +6987,61 @@
<target state="translated">檔案 '{0}' 在磁碟上意外變更,請重新載入。</target>
<note />
</trans-unit>
<trans-unit id="writeToReadOnlyByref">
<source>The byref pointer is readonly, so this write is not permitted.</source>
<target state="new">The byref pointer is readonly, so this write is not permitted.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeMutable">
<source>A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</source>
<target state="new">A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="readOnlyAttributeOnStructWithMutableField">
<source>A ReadOnly attribute has been applied to a struct type with a mutable field.</source>
<target state="new">A ReadOnly attribute has been applied to a struct type with a mutable field.</target>
<note />
</trans-unit>
<trans-unit id="tcByrefReturnImplicitlyDereferenced">
<source>A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</source>
<target state="new">A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&amp;f(x)' or '&amp;obj.Method(arg1, arg2)'.</target>
<note />
</trans-unit>
<trans-unit id="tcByRefLikeNotStruct">
<source>A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsByRefLike must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkNoByrefAddressOfLocal">
<source>The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</source>
<target state="new">The address of the variable '{0}' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoReturnOfLimitedSpan">
<source>The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</source>
<target state="new">The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.</target>
<note />
</trans-unit>
<trans-unit id="chkNoWriteToLimitedSpan">
<source>This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</source>
<target state="new">This value can't be assigned because the target '{0}' may refer to non-stack-local memory, while the expression being assigned is assessed to potentially refer to stack-local memory. This is to help prevent pointers to stack-bound memory escaping their scope.</target>
<note />
</trans-unit>
<trans-unit id="tastValueMustBeLocal">
<source>A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</source>
<target state="new">A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'</target>
<note />
</trans-unit>
<trans-unit id="tcIsReadOnlyNotStruct">
<source>A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</source>
<target state="new">A type annotated with IsReadOnly must also be a struct. Consider adding the [&lt;Struct&gt;] attribute to the type.</target>
<note />
</trans-unit>
<trans-unit id="chkStructsMayNotReturnAddressesOfContents">
<source>Struct members cannot return the address of fields of the struct by reference</source>
<target state="new">Struct members cannot return the address of fields of the struct by reference</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -7,6 +7,7 @@ namespace global
open System
open System.IO
open System.Text
open System.Diagnostics
[<AutoOpen>]
@ -117,15 +118,23 @@ module Scripting =
let p = new Process()
p.EnableRaisingEvents <- true
p.StartInfo <- processInfo
let out = StringBuilder()
let err = StringBuilder()
cmdArgs.RedirectOutput|> Option.iter (fun f ->
processInfo.RedirectStandardOutput <- true
p.OutputDataReceived.Add (fun ea -> if ea.Data <> null then f ea.Data)
p.OutputDataReceived.Add (fun ea ->
if ea.Data <> null then
out.Append(ea.Data + Environment.NewLine) |> ignore
f ea.Data)
)
cmdArgs.RedirectError |> Option.iter (fun f ->
processInfo.RedirectStandardError <- true
p.ErrorDataReceived.Add (fun ea -> if ea.Data <> null then f ea.Data)
p.ErrorDataReceived.Add (fun ea ->
if ea.Data <> null then
err.Append(ea.Data + Environment.NewLine) |> ignore
f ea.Data)
)
cmdArgs.RedirectInput
@ -151,7 +160,7 @@ module Scripting =
match p.ExitCode with
| 0 -> Success
| err ->
let msg = sprintf "Error running command '%s' with args '%s' in directory '%s'" exePath arguments workDir
let msg = sprintf "Error running command '%s' with args '%s' in directory '%s'.\n---- stdout below --- \n%s\n---- stderr below --- \n%s " exePath arguments workDir (out.ToString()) (err.ToString())
ErrorLevel (msg, err)
type OutPipe (writer: TextWriter) =

Просмотреть файл

@ -796,6 +796,20 @@ Microsoft.FSharp.Core.AutoSerializableAttribute: Int32 GetHashCode()
Microsoft.FSharp.Core.AutoSerializableAttribute: System.String ToString()
Microsoft.FSharp.Core.AutoSerializableAttribute: System.Type GetType()
Microsoft.FSharp.Core.AutoSerializableAttribute: Void .ctor(Boolean)
Microsoft.FSharp.Core.ByRefKinds+In: Boolean Equals(System.Object)
Microsoft.FSharp.Core.ByRefKinds+In: Int32 GetHashCode()
Microsoft.FSharp.Core.ByRefKinds+In: System.String ToString()
Microsoft.FSharp.Core.ByRefKinds+In: System.Type GetType()
Microsoft.FSharp.Core.ByRefKinds+Out: Boolean Equals(System.Object)
Microsoft.FSharp.Core.ByRefKinds+Out: Int32 GetHashCode()
Microsoft.FSharp.Core.ByRefKinds+Out: System.String ToString()
Microsoft.FSharp.Core.ByRefKinds+Out: System.Type GetType()
Microsoft.FSharp.Core.ByRefKinds: Boolean Equals(System.Object)
Microsoft.FSharp.Core.ByRefKinds: Int32 GetHashCode()
Microsoft.FSharp.Core.ByRefKinds: Microsoft.FSharp.Core.ByRefKinds+In
Microsoft.FSharp.Core.ByRefKinds: Microsoft.FSharp.Core.ByRefKinds+Out
Microsoft.FSharp.Core.ByRefKinds: System.String ToString()
Microsoft.FSharp.Core.ByRefKinds: System.Type GetType()
Microsoft.FSharp.Core.CLIEventAttribute: Boolean Equals(System.Object)
Microsoft.FSharp.Core.CLIEventAttribute: Boolean Match(System.Object)
Microsoft.FSharp.Core.CLIEventAttribute: Int32 GetHashCode()
@ -3195,6 +3209,8 @@ Microsoft.FSharp.NativeInterop.NativePtrModule: T GetPointerInlined[T](IntPtr, I
Microsoft.FSharp.NativeInterop.NativePtrModule: T ReadPointerInlined[T](IntPtr)
Microsoft.FSharp.NativeInterop.NativePtrModule: Void SetPointerInlined[T](IntPtr, Int32, T)
Microsoft.FSharp.NativeInterop.NativePtrModule: Void WritePointerInlined[T](IntPtr, T)
Microsoft.FSharp.NativeInterop.NativePtrModule: IntPtr OfVoidPtrInlined[T](Void*)
Microsoft.FSharp.NativeInterop.NativePtrModule: Void* ToVoidPtrInlined[T](IntPtr)
Microsoft.FSharp.Quotations.DerivedPatternsModule: Boolean Equals(System.Object)
Microsoft.FSharp.Quotations.DerivedPatternsModule: Int32 GetHashCode()
Microsoft.FSharp.Quotations.DerivedPatternsModule: Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr],Microsoft.FSharp.Collections.FSharpList`1[System.Type],Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]]]] SpecificCallPattern(Microsoft.FSharp.Quotations.FSharpExpr)

Просмотреть файл

@ -800,6 +800,20 @@ Microsoft.FSharp.Core.AutoSerializableAttribute: System.Object get_TypeId()
Microsoft.FSharp.Core.AutoSerializableAttribute: System.String ToString()
Microsoft.FSharp.Core.AutoSerializableAttribute: System.Type GetType()
Microsoft.FSharp.Core.AutoSerializableAttribute: Void .ctor(Boolean)
Microsoft.FSharp.Core.ByRefKinds+In: Boolean Equals(System.Object)
Microsoft.FSharp.Core.ByRefKinds+In: Int32 GetHashCode()
Microsoft.FSharp.Core.ByRefKinds+In: System.String ToString()
Microsoft.FSharp.Core.ByRefKinds+In: System.Type GetType()
Microsoft.FSharp.Core.ByRefKinds+Out: Boolean Equals(System.Object)
Microsoft.FSharp.Core.ByRefKinds+Out: Int32 GetHashCode()
Microsoft.FSharp.Core.ByRefKinds+Out: System.String ToString()
Microsoft.FSharp.Core.ByRefKinds+Out: System.Type GetType()
Microsoft.FSharp.Core.ByRefKinds: Boolean Equals(System.Object)
Microsoft.FSharp.Core.ByRefKinds: Int32 GetHashCode()
Microsoft.FSharp.Core.ByRefKinds: Microsoft.FSharp.Core.ByRefKinds+In
Microsoft.FSharp.Core.ByRefKinds: Microsoft.FSharp.Core.ByRefKinds+Out
Microsoft.FSharp.Core.ByRefKinds: System.String ToString()
Microsoft.FSharp.Core.ByRefKinds: System.Type GetType()
Microsoft.FSharp.Core.CLIEventAttribute: Boolean Equals(System.Object)
Microsoft.FSharp.Core.CLIEventAttribute: Boolean IsDefaultAttribute()
Microsoft.FSharp.Core.CLIEventAttribute: Boolean Match(System.Object)
@ -3342,6 +3356,8 @@ Microsoft.FSharp.NativeInterop.NativePtrModule: T GetPointerInlined[T](IntPtr, I
Microsoft.FSharp.NativeInterop.NativePtrModule: T ReadPointerInlined[T](IntPtr)
Microsoft.FSharp.NativeInterop.NativePtrModule: Void SetPointerInlined[T](IntPtr, Int32, T)
Microsoft.FSharp.NativeInterop.NativePtrModule: Void WritePointerInlined[T](IntPtr, T)
Microsoft.FSharp.NativeInterop.NativePtrModule: IntPtr OfVoidPtrInlined[T](Void*)
Microsoft.FSharp.NativeInterop.NativePtrModule: Void* ToVoidPtrInlined[T](IntPtr)
Microsoft.FSharp.Quotations.DerivedPatternsModule: Boolean Equals(System.Object)
Microsoft.FSharp.Quotations.DerivedPatternsModule: Int32 GetHashCode()
Microsoft.FSharp.Quotations.DerivedPatternsModule: Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr],Microsoft.FSharp.Collections.FSharpList`1[System.Type],Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]]]] SpecificCallPattern(Microsoft.FSharp.Quotations.FSharpExpr)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -50,11 +50,26 @@ namespace CustomExtensions
{
/// Extend an F# type
static public ref readonly DateTime ExtendCSharpTypeWithInRefReturnExtension(in this DateTime inp) { return ref inp; }
static public ref DateTime ExtendCSharpTypeWithRefReturnExtension(ref this DateTime inp) { return ref inp; }
static public void ExtendCSharpTypeWithOutRefExtension(ref this DateTime inp) { inp = inp.Date; }
static public int ExtendCSharpTypeWithInRefExtension(ref this DateTime inp) { return inp.Year; }
static public int ExtendFSharpType(this Lib.recd1 recd) { return 5; }
static public int ExtendCSharpType(this Lib2 recd) { return 4; }
}
}
namespace Fields
{
public class Fields
{
/// Extend an F# type
static public int StaticIntField => 3;
static public System.DateTime StaticDateTimeField => System.DateTime.Now.Date;
}
}
namespace Newtonsoft.Json.Converters
{
internal class SomeClass

Просмотреть файл

@ -16,6 +16,11 @@ let test (s : string) b =
if b then stderr.WriteLine " OK"
else report_failure (s)
let check (s : string) x y =
stderr.Write(s)
if x = y then stderr.WriteLine " OK"
else report_failure (sprintf "%s: expected %A, got %A" s y x)
#if NO_LIB_REFERENCE // Test for https://github.com/Microsoft/visualfsharp/issues/2453#issuecomment-280946177
module TestExtensions =
open CustomExtensions
@ -154,8 +159,19 @@ let TestAccessibility() =
module TestExtensions =
open CustomExtensions
test "dfeweeon" (r1.ExtendFSharpType() = 5)
test "dfeweeon" (Lib2().ExtendCSharpType() = 4)
check "dfeweeon" (r1.ExtendFSharpType()) 5
check "dfeweeon" (Lib2().ExtendCSharpType()) 4
let x = System.DateTime.Now
check "dfeweeon1" (System.DateTime.Now.ExtendCSharpTypeWithInRefReturnExtension()).Date x.Date
check "dfeweeon2" (x.ExtendCSharpTypeWithInRefReturnExtension()).Date x.Date
check "dfeweeon3" (x.ExtendCSharpTypeWithRefReturnExtension()).Date x.Date
let mutable mx = x
check "dfeweeon4" (mx.ExtendCSharpTypeWithOutRefExtension(); mx) x.Date
check "dfeweeon5" (x.ExtendCSharpTypeWithInRefExtension()) x.Year
#endif

Просмотреть файл

@ -31,4 +31,6 @@ try
asmBuilder.Save(filename)
exit 0
with _ -> exit 1
with err ->
printfn "Error: %A" err
exit 1

Просмотреть файл

@ -0,0 +1,401 @@
#r @"..\..\..\..\packages\System.Memory.4.5.0-rc1\lib\netstandard2.0\System.Memory.dll"
#r @"..\..\..\..\packages\NETStandard.Library.NETFramework.2.0.0-preview2-25405-01\build\net461\ref\netstandard.dll"
namespace System.Runtime.CompilerServices
open System
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
[<AttributeUsage(AttributeTargets.All,AllowMultiple=false)>]
[<Sealed>]
type IsReadOnlyAttribute() =
inherit System.Attribute()
[<AttributeUsage(AttributeTargets.All,AllowMultiple=false)>]
[<Sealed>]
type IsByRefLikeAttribute() =
inherit System.Attribute()
namespace Tests
open System
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
open FSharp.NativeInterop
[<AutoOpen>]
module Helpers =
let failures = ref false
let report_failure (s) =
stderr.WriteLine ("NO: " + s);
failures := true
let test s b = if b then () else report_failure(s)
(* TEST SUITE FOR Int32 *)
let out r (s:string) = r := !r @ [s]
let check s actual expected =
if actual = expected then printfn "%s: OK" s
else report_failure (sprintf "%s: FAILED, expected %A, got %A" s expected actual)
let check2 s expected actual = check s actual expected
[<IsReadOnly; Struct>]
type ReadOnlyStruct(count1: int, count2: int) =
member x.Count1 = count1
member x.Count2 = count2
[<IsByRefLike; Struct>]
type ByRefLikeStruct(count1: int, count2: int) =
member x.Count1 = count1
member x.Count2 = count2
module TypeRefTests =
let f1 (x: ByRefLikeStruct) = ()
let f2 (x: ReadOnlyStruct) = x.Count1
let f3 (x: ReadOnlyStruct) = x
let f4 (x: Span<int>) = ()
let f5 (x: Memory<int>) = ()
let f6 (x: ReadOnlySpan<int>) = ()
let f7 (x: ReadOnlyMemory<int>) = ()
module Sample1 =
open FSharp.NativeInterop
open System.Runtime.InteropServices
// this method does not care what kind of memory it works on
let SafeSum(bytes: Span<byte>) =
let mutable sum = 0
for i in 0 .. bytes.Length - 1 do
sum <- sum + int bytes.[i]
sum
let SafeSum2(bytes: Span<byte>) =
let mutable sum = 0
for i in 0 .. bytes.Length - 1 do
let byteAddr = &bytes.[i]
sum <- sum + int byteAddr
sum
let SafeSum3(bytes: Memory<byte>) =
let bytes = bytes.Span
let mutable sum = 0
for i in 0 .. bytes.Length - 1 do
let byteAddr = &bytes.[i]
sum <- sum + int byteAddr
sum
let SafeSum4(bytes: Memory<byte>) =
let bytes = bytes.Span
let mutable sum = 0
for i in 0 .. bytes.Length - 1 do
sum <- sum + int bytes.[i]
sum
let SafeSum5(bytes: ReadOnlySpan<byte>) =
let mutable sum = 0
for i in 0 .. bytes.Length - 1 do
sum <- sum + int bytes.[i]
sum
let SafeSum6(bytes: ReadOnlySpan<byte>) =
let mutable sum = 0
for i in 0 .. bytes.Length - 1 do
let byteAddr = &bytes.[i]
sum <- sum + int byteAddr
sum
let SafeSum7(bytes: ReadOnlyMemory<byte>) =
let bytes = bytes.Span
let mutable sum = 0
for i in 0 .. bytes.Length - 1 do
let byteAddr = &bytes.[i]
sum <- sum + int byteAddr
sum
let SafeSum8(bytes: ReadOnlyMemory<byte>) =
let bytes = bytes.Span
let mutable sum = 0
for i in 0 .. bytes.Length - 1 do
sum <- sum + int bytes.[i]
sum
let f6() =
// managed memory
let arrayMemory = Array.zeroCreate<byte>(100)
let arraySpan = new Span<byte>(arrayMemory)
for i in 0 .. 99 do arrayMemory.[i] <- byte i
SafeSum(arraySpan)|> printfn "res = %d"
// native memory
let nativeMemory = Marshal.AllocHGlobal(100)
let nativeSpan = new Span<byte>(nativeMemory.ToPointer(), 100)
for i in 0 .. 99 do Marshal.WriteByte(nativeMemory, i, byte i)
SafeSum(nativeSpan)|> printfn "res = %d"
Marshal.FreeHGlobal(nativeMemory)
// stack memory
let mem = NativePtr.stackalloc<byte>(100)
let mem2 = mem |> NativePtr.toVoidPtr
for i in 0 .. 99 do NativePtr.set mem i (byte i)
let stackSpan = Span<byte>(mem2, 100)
SafeSum(stackSpan) |> printfn "res = %d"
f6()
[<Struct>]
type AllowedEvilStruct =
[<DefaultValue>]
val mutable v : int
member x.Replace(y:AllowedEvilStruct) = x <- y
module SubsumptionOnMember =
type Doot() = class end
[<Sealed>]
type GiantDad() =
let test (data: Span<byte>) (doot: Doot) =
()
member __.Test(data: Span<byte>) =
test data Unchecked.defaultof<Doot>
module AssignToByrefReturn =
type C() =
static let mutable v = System.DateTime.Now
static member M() = &v
let F1() =
C.M() <- System.DateTime.Now
module AssignToSpanItem =
let F2() =
let data = Span<byte>.Empty
data.[0] <- 1uy
module AssignToSpanItemGeneric =
let F2<'T>() =
let data = Span<'T>.Empty
data.[0] <- Unchecked.defaultof<'T>
module CheckReturnOfSpan1 =
let test () =
let s = Span<byte>.Empty
s
module CheckReturnOfSpan2 =
type Jopac() =
member this.Create() =
let mutable x = 1
this.Create(&x)
member __.Create(x: byref<int>) =
Span<int>.Empty
module CheckReturnOfSpan3 =
type Jopac_NotCompile_WhichIsMightBeIncorrect() =
member __.Create(x: byref<int>) =
Span<int>.Empty
member this.Create() =
let mutable x = 1
let x = this.Create(&x)
x
member this.CreateAgain() =
let mutable x = 1
this.Create(&x)
module ByRefSpanParam =
type C() =
static member M(x: byref<Span<int>>) = x.[0] <- 5
let Test() =
let mutable res = 9
let mutable span = Span<int>(NativePtr.toVoidPtr &&res,1)
let v = C.M(&span)
check "cwvereweoiwekl4" res 5
let minfo = typeof<C>.GetMethod("M")
check "cwnoreeker1" (minfo.GetParameters().[0].IsIn) false
check "cwnoreeker2" (minfo.GetParameters().[0].IsOut) false
check "cwnoreeker3" (minfo.ReturnParameter.IsIn) false
check "cwnoreeker4" (minfo.ReturnParameter.IsOut) false
Test()
module SpanByRefReturn =
type C() =
static member M(x: byref<Span<int>>) = x.[0] <- x.[0] + 1; &x
let Test() =
let mutable res = 9
let mutable span = Span<int>(NativePtr.toVoidPtr &&res,1)
let v = &C.M(&span)
check "cwvereweoiwvw4" v.[0] 10
let minfo = typeof<C>.GetMethod("M")
check "cwnoreeker6d" (minfo.GetParameters().[0].GetRequiredCustomModifiers().Length) 0
check "cwnoreekerr" (minfo.ReturnParameter.IsIn) false
check "cwnoreekert" (minfo.ReturnParameter.IsOut) false
Test()
module SpanReturn =
type C() =
static member M(x: byref<Span<int>>) = x.[0] <- x.[0] + 1; x
let Test() =
let mutable res = 9
let mutable span = Span<int>(NativePtr.toVoidPtr &&res,1)
let v = C.M(&span)
check "cwvereweoiwvw4" v.[0] 10
let minfo = typeof<C>.GetMethod("M")
check "cwnoreeker6d" (minfo.GetParameters().[0].GetRequiredCustomModifiers().Length) 0
check "cwnoreekerr" (minfo.ReturnParameter.IsIn) false
check "cwnoreekert" (minfo.ReturnParameter.IsOut) false
Test()
module SpanSafetyTests0 =
type SpanLikeType = Span<int>
let m1 (x: byref<Span<int>>) (y: Span<byte>) =
// this is all valid, unconcerned with stack-referring stuff
let local = SpanLikeType()
x <- local
x
module SpanSafetyTests1 =
type SpanLikeType = Span<int>
let m1 (x: byref<Span<int>>) (y: Span<byte>) =
// this is all valid, unconcerned with stack-referring stuff
let local = SpanLikeType()
x <- local
x
let test1 (param1: byref<Span<int>>) (param2: Span<byte>) =
let mutable stackReferringBecauseMutable1 = Span<byte>()
//let stackReferringBecauseMutable1 = Span<byte>(NativePtr.toVoidPtr(&&x), 1)
//let stackReferringBecauseMutable1 = Span<byte>(NativePtr.toVoidPtr(NativePtr.ofByRef(&&x)), 1)
//let stackReferring1 = Span<byte>(NativePtr.toVoidPtr(NativePtr.stackalloc< byte>(100), 1)
let mutable stackReferringBecauseMutable2 = Span<int>()
// this is allowed
stackReferringBecauseMutable2 <- m1 &stackReferringBecauseMutable2 stackReferringBecauseMutable1
// this is allowed
stackReferringBecauseMutable2 <- m1 &param1 stackReferringBecauseMutable1
#if NEGATIVE
// this is NOT allowed
param1 <- m1 &stackReferringBecauseMutable2 stackReferringBecauseMutable1
// this is NOT allowed
param1 <- stackReferringBecauseMutable2.Slice(10)
#endif
// this is allowed
param1 <- Span<int>()
// this is allowed
stackReferringBecauseMutable2 <- param1
module SpanSafetyTests2 =
let m2 (x: byref<Span<int>>) =
// should compile
&x
module SpanSafetyTests3 =
type SpanLikeType = Span<int>
let m1 (x: byref<Span<int>>) (y: Span<byte>) =
// this is all valid, unconcerned with stack-referring stuff
let local = SpanLikeType()
x <- local
x
let m2 (x: byref<Span<int>>) =
// should compile
&x
let test2 (param1: byref<Span<int>>) (param2: Span<byte>) =
let mutable stackReferringBecauseMutable1 = Span<byte>()
let mutable stackReferringBecauseMutable2 = Span<int>()
let stackReferring3 = &(m2 &stackReferringBecauseMutable2)
// this is allowed
stackReferring3 <- m1 &stackReferringBecauseMutable2 stackReferringBecauseMutable1
// this is allowed
m2(&stackReferring3) <- stackReferringBecauseMutable2
#if NEGATIVE2
// this is NOT allowed
m1(&param1) <- stackReferringBecauseMutable2
// this is NOT allowed
param1 <- stackReferring3
// this is NOT allowed
&stackReferring3
#endif
// this is allowed
//&param1 - uncomment to test return
module SpanSafetyTests4 =
let test2 (param1: byref<Span<int>>) (param2: Span<byte>) =
// this is allowed
&param1 // uncomment to test return
#if NEGATIVE
module CheckReturnOfSpan4 =
type Jopac_NotCompile_WhichIsCorrect() =
member __.Create(x: byref<int>) =
&x
member this.Create() =
let mutable x = 1
let x = &this.Create(&x)
&x
member this.CreateAgain() =
let mutable x = 1
&this.Create(&x)
#endif
#if NOT_YET
// Disallow this:
[<IsReadOnly; Struct>]
type DisallowedIsReadOnlyStruct =
[<DefaultValue>]
val mutable X : int
// Allow this:
[<IsByRefLike; Struct>]
type ByRefLikeStructWithSpanField(count1: Span, count2: int) =
member x.Count1 = count1
member x.Count2 = count2
[<IsByRefLike; Struct>]
type ByRefLikeStructWithByrefField(count1: Span<int>, count2: int) =
member x.Count1 = count1
member x.Count2 = count2
#endif

Просмотреть файл

@ -0,0 +1,15 @@
namespace System.Runtime.CompilerServices
open System
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
[<AttributeUsage(AttributeTargets.All,AllowMultiple=false)>]
[<Sealed>]
type IsReadOnlyAttribute() =
inherit System.Attribute()
[<AttributeUsage(AttributeTargets.All,AllowMultiple=false)>]
[<Sealed>]
type IsByRefLikeAttribute() =
inherit System.Attribute()

Просмотреть файл

@ -1,5 +1,5 @@
#if INTERACTIVE
//#r @"../../release/net40/bin/FSharp.Compiler.dll"
// vvvvvvvvvvvvv To run these tests in F# Interactive , 'build net40', then send this chunk, then evaluate body of a test vvvvvvvvvvvvvvvv
#if INTERACTIVE
#r @"../../packages/NUnit.3.5.0/lib/net45/nunit.framework.dll"
#load "../../src/scripts/scriptlib.fsx"
#load "test-framework.fs"
@ -25,6 +25,7 @@ let FSI_BASIC = FSI_CORECLR
let FSC_BASIC = FSC_OPT_PLUS_DEBUG
let FSI_BASIC = FSI_FILE
#endif
// ^^^^^^^^^^^^ To run these tests in F# Interactive , 'build net40', then send this chunk, then evaluate body of a test ^^^^^^^^^^^^
module CoreTests =
// These tests are enabled for .NET Framework and .NET Core
@ -176,6 +177,7 @@ module CoreTests =
let cfg = testConfig "core/byrefs"
begin
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe -g" cfg.fsc_flags ["test.fsx"]
@ -183,10 +185,53 @@ module CoreTests =
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
end
begin
use testOkFile = fileguard cfg "test.ok"
fsi cfg "" ["test.fsx"]
testOkFile.CheckExists()
end
begin
use testOkFile = fileguard cfg "test.ok"
fsiAnyCpu cfg "" ["test.fsx"]
testOkFile.CheckExists()
end
[<Test>]
let span () =
let cfg = testConfig "core/span"
begin
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe -g" cfg.fsc_flags ["test.fsx"]
// Execution is disabled until we can be sure .NET 4.7.2 is on the machine
//exec cfg ("." ++ "test.exe") ""
//testOkFile.CheckExists()
end
// Execution is disabled until we can be sure .NET 4.7.2 is on the machine
//begin
// use testOkFile = fileguard cfg "test.ok"
// fsi cfg "" ["test.fsx"]
// testOkFile.CheckExists()
//end
// Execution is disabled until we can be sure .NET 4.7.2 is on the machine
//begin
// use testOkFile = fileguard cfg "test.ok"
// fsiAnyCpu cfg "" ["test.fsx"]
// testOkFile.CheckExists()
//end
[<Test>]
let asyncStackTraces () =
@ -381,19 +426,22 @@ module CoreTests =
peverify cfg "lib.dll"
csc cfg """/nologo /target:library /r:"%s" /r:lib.dll /out:lib2.dll""" cfg.FSCOREDLLPATH ["lib2.cs"]
csc cfg """/nologo /target:library /r:"%s" /r:lib.dll /out:lib2.dll /langversion:7.2""" cfg.FSCOREDLLPATH ["lib2.cs"]
csc cfg """/nologo /target:library /r:"%s" /out:lib3.dll""" cfg.FSCOREDLLPATH ["lib3.cs"]
csc cfg """/nologo /target:library /r:"%s" /out:lib3.dll /langversion:7.2""" cfg.FSCOREDLLPATH ["lib3.cs"]
fsc cfg "%s -r:lib.dll -r:lib2.dll -r:lib3.dll -o:test.exe -g" cfg.fsc_flags ["test.fsx"]
peverify cfg "test.exe"
exec cfg ("." ++ "test.exe") ""
// Same with library references the other way around
fsc cfg "%s -r:lib.dll -r:lib3.dll -r:lib2.dll -o:test.exe -g" cfg.fsc_flags ["test.fsx"]
peverify cfg "test.exe"
exec cfg ("." ++ "test.exe") ""
// Same without the reference to lib.dll - testing an incomplete reference set, but only compiling a subset of the code
fsc cfg "%s -r:System.Runtime.dll --noframework --define:NO_LIB_REFERENCE -r:lib3.dll -r:lib2.dll -o:test.exe -g" cfg.fsc_flags ["test.fsx"]
@ -2299,6 +2347,12 @@ module TypecheckTests =
[<Test>]
let ``type check neg102`` () = singleNegTest (testConfig "typecheck/sigs") "neg102"
[<Test>]
let ``type check neg106`` () = singleNegTest (testConfig "typecheck/sigs") "neg106"
[<Test>]
let ``type check neg107`` () = singleNegTest (testConfig "typecheck/sigs") "neg107"
[<Test>]
let ``type check neg103`` () = singleNegTest (testConfig "typecheck/sigs") "neg103"

Просмотреть файл

@ -1,5 +1,8 @@
namespace global
[<assembly: System.Reflection.AssemblyCopyrightAttribute("hey!")>]
do ()
type TheGeneratedType1() =
member x.Prop1 = 1
static member (+) (x1:TheGeneratedType1,x2:TheGeneratedType1) = x1

124
tests/fsharp/typecheck/sigs/neg106.bsl поставляемый Normal file
Просмотреть файл

@ -0,0 +1,124 @@
neg106.fs(8,59,8,61): typecheck error FS3231: A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'
neg106.fs(13,18,13,72): typecheck error FS0041: No overloads match for method 'CompareExchange'. The available overloads are shown below.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<int>, value: int, comparand: int) : int'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<int64>, value: int64, comparand: int64) : int64'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int64>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<float32>, value: float32, comparand: float32) : float32'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<float32>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<float>, value: float, comparand: float) : float'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<float>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<obj>, value: obj, comparand: obj) : obj'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<obj>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<nativeint>, value: nativeint, comparand: nativeint) : nativeint'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<nativeint>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange<'T when 'T : not struct>(location1: byref<'T>, value: 'T, comparand: 'T) : 'T'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<'a>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: No overloads match for method 'CompareExchange'. The available overloads are shown below.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<int>, value: int, comparand: int) : int'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<int64>, value: int64, comparand: int64) : int64'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int64>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<float32>, value: float32, comparand: float32) : float32'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<float32>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<float>, value: float, comparand: float) : float'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<float>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<obj>, value: obj, comparand: obj) : obj'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<obj>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<nativeint>, value: nativeint, comparand: nativeint) : nativeint'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<nativeint>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange<'T when 'T : not struct>(location1: byref<'T>, value: 'T, comparand: 'T) : 'T'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<'a>'
.
neg106.fs(23,35,23,39): typecheck error FS0001: Type mismatch. Expecting a
'byref<int>'
but given a
'inref<int>'
The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In'
neg106.fs(31,22,31,26): typecheck error FS0001: Type mismatch. Expecting a
'byref<int>'
but given a
'inref<int>'
The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In'
neg106.fs(40,18,40,32): typecheck error FS0041: No overloads match for method 'M'. The available overloads are shown below.
neg106.fs(40,18,40,32): typecheck error FS0041: Possible overload: 'static member C.M : a:string * x:byref<int> -> unit'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int>'
.
neg106.fs(40,18,40,32): typecheck error FS0041: Possible overload: 'static member C.M : a:int * x:byref<int> -> unit'. Type constraint mismatch. The type
'string'
is not compatible with type
'int'
.
neg106.fs(41,19,41,31): typecheck error FS0041: No overloads match for method 'M'. The available overloads are shown below.
neg106.fs(41,19,41,31): typecheck error FS0041: Possible overload: 'static member C.M : a:string * x:byref<int> -> unit'. Type constraint mismatch. The type
'int'
is not compatible with type
'string'
.
neg106.fs(41,19,41,31): typecheck error FS0041: Possible overload: 'static member C.M : a:int * x:byref<int> -> unit'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int>'
.
neg106.fs(49,22,49,26): typecheck error FS0001: Type mismatch. Expecting a
'byref<int>'
but given a
'inref<int>'
The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In'
neg106.fs(60,9,60,25): typecheck error FS3224: The byref pointer is readonly, so this write is not permitted.
neg106.fs(65,42,65,48): typecheck error FS3224: The byref pointer is readonly, so this write is not permitted.
neg106.fs(74,9,74,17): typecheck error FS0257: Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.

Просмотреть файл

@ -0,0 +1,74 @@
module M
//#r @"..\..\..\..\packages\System.Memory.4.5.0-rc1\lib\netstandard2.0\System.Memory.dll"
//#r @"..\..\..\..\packages\NETStandard.Library.NETFramework\2.0.0-preview2-25405-01\build\net461\ref\netstandard.dll"
module CompareExchangeTests_Negative1 =
let x = 3
let v = System.Threading.Interlocked.CompareExchange(&x, 3, 4) // No overloads match for method 'CompareExchange'. 'inref<int>' is not compatible with type 'byref<int>'
module CompareExchangeTests_Negative1b =
let Test() =
let x = 3
let v = System.Threading.Interlocked.CompareExchange(&x, 3, 4) // No overloads match for method 'CompareExchange'. 'inref<int>' is not compatible with type 'byref<int>'
()
module CompareExchangeTests_Negative2 =
let v = System.Threading.Interlocked.CompareExchange(&3, 3, 4) // 'inref<int>' is not compatible with type 'byref<int>'
module TryGetValueTests_Negative1 =
let Test() =
let d = dict [ (3,4) ]
let res = 9
let v = d.TryGetValue(3, &res) // 'inref<int,>' is not compatible with type 'byref<int>'
()
module FSharpDeclaredOutParamTest_Negaative1 =
type C() =
static member M([<System.Runtime.InteropServices.Out>] x: byref<int>) = ()
let Test() =
let res = 9
let v = C.M(&res) //'inref<int>' is not compatible with type 'byref<int>'
()
module FSharpDeclaredOverloadedOutParamTest_Negative1 =
type C() =
static member M(a: int, [<System.Runtime.InteropServices.Out>] x: byref<int>) = x <- 7
static member M(a: string, [<System.Runtime.InteropServices.Out>] x: byref<int>) = x <- 8
let Test() =
let res = 9
let v = C.M("a", &res) //'inref<int>' is not compatible with type 'byref<int>'
let v2 = C.M(3, &res) //'inref<int>' is not compatible with type 'byref<int>'
()
module FSharpDeclaredOutParamTest_Negative1 =
type C() =
static member M([<System.Runtime.InteropServices.Out>] x: byref<int>) = ()
let Test() =
let res = 9
let v = C.M(&res) // 'inref<int>' is not compatible with type 'byref<int>'
()
module TestOneArgumentInRefThenMutate_Negative1 =
type C() =
static member M (x:inref<int>) = &x
let test() =
let mutable r1 = 1
let addr = &C.M (&r1) // Expecting a 'byref<int,ByRefKinds.Out>' but given a 'inref<int>'. The type 'ByRefKinds.Out' does not match the type 'ByRefKinds.In'
addr <- addr + 1 // "The byref pointer is readonly, so this write is not permitted"
module EvilStruct_Negative1 =
[<Struct>]
type EvilStruct(s: int) =
member x.Replace(y:EvilStruct) = x <- y
module MutateInRef1 =
[<Struct>]
type TestMut =
val mutable x : int
let testIn (m: inref<TestMut>) =
m.x <- 1

Просмотреть файл

@ -0,0 +1,124 @@
neg106.fs(8,59,8,61): typecheck error FS3231: A value defined in a module must be mutable in order to take its address, e.g. 'let mutable x = ...'
neg106.fs(13,18,13,72): typecheck error FS0041: No overloads match for method 'CompareExchange'. The available overloads are shown below.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<int>, value: int, comparand: int) : int'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<int64>, value: int64, comparand: int64) : int64'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int64>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<float32>, value: float32, comparand: float32) : float32'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<float32>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<float>, value: float, comparand: float) : float'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<float>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<obj>, value: obj, comparand: obj) : obj'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<obj>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<nativeint>, value: nativeint, comparand: nativeint) : nativeint'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<nativeint>'
.
neg106.fs(13,18,13,72): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange<'T when 'T : not struct>(location1: byref<'T>, value: 'T, comparand: 'T) : 'T'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<'a>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: No overloads match for method 'CompareExchange'. The available overloads are shown below.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<int>, value: int, comparand: int) : int'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<int64>, value: int64, comparand: int64) : int64'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int64>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<float32>, value: float32, comparand: float32) : float32'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<float32>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<float>, value: float, comparand: float) : float'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<float>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<obj>, value: obj, comparand: obj) : obj'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<obj>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange(location1: byref<nativeint>, value: nativeint, comparand: nativeint) : nativeint'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<nativeint>'
.
neg106.fs(17,14,17,68): typecheck error FS0041: Possible overload: 'System.Threading.Interlocked.CompareExchange<'T when 'T : not struct>(location1: byref<'T>, value: 'T, comparand: 'T) : 'T'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<'a>'
.
neg106.fs(23,35,23,39): typecheck error FS0001: Type mismatch. Expecting a
'byref<int>'
but given a
'inref<int>'
The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In'
neg106.fs(31,22,31,26): typecheck error FS0001: Type mismatch. Expecting a
'byref<int>'
but given a
'inref<int>'
The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In'
neg106.fs(40,18,40,32): typecheck error FS0041: No overloads match for method 'M'. The available overloads are shown below.
neg106.fs(40,18,40,32): typecheck error FS0041: Possible overload: 'static member C.M : a:string * x:byref<int> -> unit'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int>'
.
neg106.fs(40,18,40,32): typecheck error FS0041: Possible overload: 'static member C.M : a:int * x:byref<int> -> unit'. Type constraint mismatch. The type
'string'
is not compatible with type
'int'
.
neg106.fs(41,19,41,31): typecheck error FS0041: No overloads match for method 'M'. The available overloads are shown below.
neg106.fs(41,19,41,31): typecheck error FS0041: Possible overload: 'static member C.M : a:string * x:byref<int> -> unit'. Type constraint mismatch. The type
'int'
is not compatible with type
'string'
.
neg106.fs(41,19,41,31): typecheck error FS0041: Possible overload: 'static member C.M : a:int * x:byref<int> -> unit'. Type constraint mismatch. The type
'inref<int>'
is not compatible with type
'byref<int>'
.
neg106.fs(49,22,49,26): typecheck error FS0001: Type mismatch. Expecting a
'byref<int>'
but given a
'inref<int>'
The type 'ByRefKinds.InOut' does not match the type 'ByRefKinds.In'
neg106.fs(60,9,60,25): typecheck error FS3224: The byref pointer is readonly, so this write is not permitted.
neg106.fs(65,42,65,48): typecheck error FS3224: The byref pointer is readonly, so this write is not permitted.
neg106.fs(74,9,74,17): typecheck error FS0257: Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'.

66
tests/fsharp/typecheck/sigs/neg107.bsl поставляемый Normal file
Просмотреть файл

@ -0,0 +1,66 @@
neg107.fsx(26,48,26,59): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(27,69,27,80): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(28,43,28,59): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(28,47,28,58): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(28,57,28,58): typecheck error FS0418: The byref typed value 'a' cannot be used at this point
neg107.fsx(28,47,28,58): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(29,51,29,67): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(29,55,29,66): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(29,65,29,66): typecheck error FS0418: The byref typed value 'a' cannot be used at this point
neg107.fsx(29,55,29,66): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(31,49,31,54): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(31,57,31,65): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(32,70,32,75): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(32,78,32,86): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(33,48,33,53): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(33,48,33,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(33,56,33,64): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(33,56,33,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(33,56,33,64): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(33,48,33,53): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(34,56,34,61): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(34,56,34,61): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(34,64,34,72): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(34,64,34,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(34,64,34,72): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(34,56,34,61): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(37,33,37,34): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(37,33,37,34): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(45,34,45,40): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference
neg107.fsx(45,34,45,38): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference
neg107.fsx(53,34,53,38): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference
neg107.fsx(67,34,67,40): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference
neg107.fsx(67,34,67,38): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference

Просмотреть файл

@ -0,0 +1,67 @@
#r @"..\..\..\..\packages\System.Memory.4.5.0-rc1\lib\netstandard2.0\System.Memory.dll"
#r @"..\..\..\..\packages\NETStandard.Library.NETFramework.2.0.0-preview2-25405-01\build\net461\ref\netstandard.dll"
namespace System.Runtime.CompilerServices
open System
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
[<AttributeUsage(AttributeTargets.All,AllowMultiple=false)>]
[<Sealed>]
type IsReadOnlyAttribute() =
inherit System.Attribute()
[<AttributeUsage(AttributeTargets.All,AllowMultiple=false)>]
[<Sealed>]
type IsByRefLikeAttribute() =
inherit System.Attribute()
namespace Test
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
open System
module Span_Negative1 =
let TestClosure1 (a: inref<int>) = id (fun () -> a)
let TestClosure1b ([<In; IsReadOnly>] a: byref<int>) = id (fun () -> a)
let TestClosure2 (a: Span<int>) = id (fun () -> a)
let TestClosure3 (a: ReadOnlySpan<int>) = id (fun () -> a)
let TestAsyncClosure1 (a: inref<int>) = async { return a }
let TestAsyncClosure1b ([<In; IsReadOnly>] a: byref<int>) = async { return a }
let TestAsyncClosure2 (a: Span<int>) = async { return a }
let TestAsyncClosure3 (a: ReadOnlySpan<int>) = async { return a }
module Span_Negative2 =
let TestLocal1 () = let x = Span() in x
module MutateInRef2 =
[<Struct>]
type TestMut =
val mutable x : int
member this.XAddr = &this.x // not allowed, Struct members cannot return the address of fields of the struct by reference", not entirely clear why C# disallowed this
module MutateInRef3 =
[<Struct>]
type TestMut =
val mutable x : int
member this.XAddr = &this // not allowed, Struct members cannot return the address of fields of the struct by reference", not entirely clear why C# disallowed this
module MutateInRef4 =
[<Struct>]
type TestMut1 =
val mutable x : int
[<Struct>]
type TestMut2 =
val mutable x : TestMut1
member this.XAddr = &this.x.x // not allowed, Struct members cannot return the address of fields of the struct by reference", not entirely clear why C# disallowed this

Просмотреть файл

@ -0,0 +1,66 @@
neg107.fsx(26,48,26,59): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(27,69,27,80): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(28,43,28,59): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(28,47,28,58): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(28,57,28,58): typecheck error FS0418: The byref typed value 'a' cannot be used at this point
neg107.fsx(28,47,28,58): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(29,51,29,67): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(29,55,29,66): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(29,65,29,66): typecheck error FS0418: The byref typed value 'a' cannot be used at this point
neg107.fsx(29,55,29,66): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(31,49,31,54): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(31,57,31,65): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(32,70,32,75): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(32,78,32,86): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(33,48,33,53): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(33,48,33,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(33,56,33,64): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(33,56,33,64): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(33,56,33,64): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(33,48,33,53): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(34,56,34,61): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(34,56,34,61): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(34,64,34,72): typecheck error FS0406: The byref-typed variable 'a' is used in an invalid way. Byrefs cannot be captured by closures or passed to inner functions.
neg107.fsx(34,64,34,72): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg107.fsx(34,64,34,72): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(34,56,34,61): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(37,33,37,34): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(37,33,37,34): typecheck error FS0425: The type of a first-class function cannot contain byrefs
neg107.fsx(45,34,45,40): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference
neg107.fsx(45,34,45,38): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference
neg107.fsx(53,34,53,38): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference
neg107.fsx(67,34,67,40): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference
neg107.fsx(67,34,67,38): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference

4
tests/fsharp/typecheck/sigs/neg63.bsl поставляемый
Просмотреть файл

@ -9,6 +9,6 @@ neg63.fs(11,5,11,13): typecheck error FS0412: A type instantiation involves a by
neg63.fs(14,8,14,9): typecheck error FS3155: A quotation may not involve an assignment to or taking the address of a captured local variable
neg63.fs(18,6,18,7): typecheck error FS3209: The address of the variable 'x' cannot be used at this point. A method or function may not return the address of this local value.
neg63.fs(18,6,18,7): typecheck error FS3209: The address of the variable 'x' or a related expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.
neg63.fs(26,6,26,10): typecheck error FS3209: The address of the variable 'addr' cannot be used at this point. A method or function may not return the address of this local value.
neg63.fs(26,6,26,10): typecheck error FS3228: The address of the variable 'addr' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.

2
tests/fsharp/typecheck/sigs/neg97.bsl поставляемый
Просмотреть файл

@ -1,5 +1,5 @@
neg97.fs(13,1,13,2): typecheck error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'
neg97.fs(13,1,13,10): typecheck error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'
neg97.fs(16,9,16,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.

Просмотреть файл

@ -0,0 +1,28 @@
neg97.fs(13,1,13,10): typecheck error FS0256: A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'
neg97.fs(16,9,16,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.
neg97.fs(16,9,16,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string'
neg97.fs(20,9,20,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.
neg97.fs(20,9,20,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string'
neg97.fs(25,9,25,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.
neg97.fs(25,9,25,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string'
neg97.fs(30,9,30,10): typecheck error FS0009: Uses of this construct may result in the generation of unverifiable .NET IL code. This warning can be disabled using '--nowarn:9' or '#nowarn "9"'.
neg97.fs(30,9,30,10): typecheck error FS3207: Invalid use of 'fixed'. 'fixed' may only be used in a declaration of the form 'use x = fixed expr' where the expression is an array, the address of a field, the address of an array element or a string'
neg97.fs(36,20,36,32): typecheck error FS0698: Invalid constraint: the type used for the constraint is sealed, which means the constraint could only be satisfied by at most one solution
neg97.fs(36,20,36,32): typecheck error FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'T has been constrained to be type 'string'.
neg97.fs(36,12,36,14): typecheck error FS0663: This type parameter has been used in a way that constrains it to always be 'string'
neg97.fs(42,20,42,22): typecheck error FS0039: The type parameter 'T is not defined. Maybe you want one of the following:
'U

Просмотреть файл

@ -1,2 +1,4 @@
neg_byref_16.fs(3,33,3,42): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg_byref_16.fs(3,40,3,41): typecheck error FS0421: The address of the variable 'a' cannot be used at this point

12
tests/fsharp/typecheck/sigs/neg_byref_17.bsl поставляемый
Просмотреть файл

@ -1,6 +1,10 @@
neg_byref_17.fs(2,5,2,8): typecheck error FS0431: A byref typed value would be stored here. Top-level let-bound byref values are not permitted.
neg_byref_17.fs(2,17,2,27): typecheck error FS0001: This expression was expected to have type
'byref<int>'
but here has type
'int'
neg_byref_17.fs(2,17,2,22): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg_byref_17.fs(3,17,3,22): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg_byref_17.fs(3,17,3,24): typecheck error FS0001: This expression was expected to have type
'byref<int>'
but here has type
'int'

12
tests/fsharp/typecheck/sigs/neg_byref_22.bsl поставляемый
Просмотреть файл

@ -1,4 +1,16 @@
neg_byref_22.fs(3,16,3,20): typecheck error FS3226: A byref pointer returned by a function or method is implicitly dereferenced as of F# 4.5. To acquire the return value as a pointer, use the address-of operator, e.g. '&f(x)' or '&obj.Method(arg1, arg2)'.
neg_byref_22.fs(3,16,3,20): typecheck error FS0001: This expression was expected to have type
'byref<int>'
but here has type
'int'
neg_byref_22.fs(3,16,3,20): typecheck error FS0001: This expression was expected to have type
'byref<int>'
but here has type
'int'
neg_byref_22.fs(5,16,5,17): typecheck error FS0001: This expression was expected to have type
'float'
but here has type

2
tests/fsharp/typecheck/sigs/neg_byref_7.bsl поставляемый
Просмотреть файл

@ -19,4 +19,4 @@ neg_byref_7.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves
neg_byref_7.fs(2,47,2,53): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
neg_byref_7.fs(4,41,4,42): typecheck error FS3209: The address of the variable 'y' cannot be used at this point. A method or function may not return the address of this local value.
neg_byref_7.fs(4,41,4,42): typecheck error FS3228: The address of the variable 'y' or a related expression cannot be used at this point. The address may not be passed to a call that returns an address. This is to ensure the address of the local value does not escape its scope.

Просмотреть файл

@ -2,7 +2,7 @@
// Verify appropriate error if attempting to assign a ByRef value to an
// object field. (Disallowed by the CLR.)
//<Expects id="FS0412" span="(14,28-14,37)" status="error">A type instantiation involves a byref type\. This is not permitted by the rules of Common IL\.$</Expects>
//<Expects id="FS0421" span="(14,29-14,30)" status="error">The address of the variable 'x' cannot be used at this point$</Expects>
//<Expects id="FS0412" span="(19,20-19,53)" status="error">A type instantiation involves a byref type\. This is not permitted by the rules of Common IL\.$</Expects>
let mutable mutableObjectField : obj = null

Просмотреть файл

@ -1,7 +1,7 @@

#if INTERACTIVE
#r "../../debug/fcs/net45/FSharp.Compiler.Service.dll" // note, run 'build fcs debug' to generate this, this DLL has a public API so can be used from F# Interactive
#r "../../Debug/net40/bin/FSharp.Compiler.Service.ProjectCracker.dll"
#r "../../debug/fcs/net45/FSharp.Compiler.Service.ProjectCracker.dll"
#r "../../packages/NUnit.3.5.0/lib/net45/nunit.framework.dll"
#load "FsUnit.fs"
#load "Common.fs"
@ -673,7 +673,6 @@ let ``Test Unoptimized Declarations Project1`` () =
"member M2(__) (unitVar1) = __.compiledAsInstanceMethod(()) @ (56,21--56,47)";
"member SM1(unitVar0) = Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (compiledAsStaticField,let x: Microsoft.FSharp.Core.int = compiledAsStaticField in ClassWithImplicitConstructor.compiledAsGenericStaticMethod<Microsoft.FSharp.Core.int> (x)) @ (57,26--57,101)";
"member SM2(unitVar0) = ClassWithImplicitConstructor.compiledAsStaticMethod (()) @ (58,26--58,50)";
//"member ToString(__) (unitVar1) = Operators.op_Addition<Microsoft.FSharp.Core.string,Microsoft.FSharp.Core.string,Microsoft.FSharp.Core.string> (base.ToString(),Operators.ToString<Microsoft.FSharp.Core.int> (999)) @ (59,29--59,57)";
"member TestCallinToString(this) (unitVar1) = this.ToString() @ (60,39--60,54)";
"type Error"; "let err = {Data0 = 3; Data1 = 4} @ (64,10--64,20)";
"let matchOnException(err) = match (if err :? M.Error then $0 else $1) targets ... @ (66,33--66,36)";
@ -693,16 +692,13 @@ let ``Test Unoptimized Declarations Project1`` () =
"let v = M.c ().get_InstanceProperty(()) @ (98,8--98,26)";
"do Console.WriteLine (\"777\")";
"let functionWithSubmsumption(x) = IntrinsicFunctions.UnboxGeneric<Microsoft.FSharp.Core.string> (x) @ (102,40--102,52)";
//"let functionWithCoercion(x) = Operators.op_PipeRight<Microsoft.FSharp.Core.string,Microsoft.FSharp.Core.string> (Operators.op_PipeRight<Microsoft.FSharp.Core.string,Microsoft.FSharp.Core.string> (IntrinsicFunctions.UnboxGeneric<Microsoft.FSharp.Core.string> (x :> Microsoft.FSharp.Core.obj),fun x -> M.functionWithSubmsumption (x :> Microsoft.FSharp.Core.obj)),fun x -> M.functionWithSubmsumption (x :> Microsoft.FSharp.Core.obj)) @ (103,39--103,116)";
"type MultiArgMethods";
"member .ctor(c,d) = (new Object(); ()) @ (105,5--105,20)";
"member Method(x) (a,b) = 1 @ (106,37--106,38)";
"member CurriedMethod(x) (a1,b1) (a2,b2) = 1 @ (107,63--107,64)";
"let testFunctionThatCallsMultiArgMethods(unitVar0) = let m: M.MultiArgMethods = new MultiArgMethods(3,4) in Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (m.Method(7,8),fun tupledArg -> let arg00: Microsoft.FSharp.Core.int = tupledArg.Item0 in let arg01: Microsoft.FSharp.Core.int = tupledArg.Item1 in fun tupledArg -> let arg10: Microsoft.FSharp.Core.int = tupledArg.Item0 in let arg11: Microsoft.FSharp.Core.int = tupledArg.Item1 in m.CurriedMethod(arg00,arg01,arg10,arg11) (9,10) (11,12)) @ (110,8--110,9)";
//"let functionThatUsesObjectExpression(unitVar0) = { new Object() with member x.ToString(unitVar1) = Operators.ToString<Microsoft.FSharp.Core.int> (888) } @ (114,3--114,55)";
//"let functionThatUsesObjectExpressionWithInterfaceImpl(unitVar0) = { new Object() with member x.ToString(unitVar1) = Operators.ToString<Microsoft.FSharp.Core.int> (888) interface System.IComparable with member x.CompareTo(y) = 0 } :> System.IComparable @ (117,3--120,38)";
"let testFunctionThatUsesUnitsOfMeasure(x) (y) = Operators.op_Addition<Microsoft.FSharp.Core.float<'u>,Microsoft.FSharp.Core.float<'u>,Microsoft.FSharp.Core.float<'u>> (x,y) @ (122,70--122,75)";
"let testFunctionThatUsesAddressesAndByrefs(x) = let mutable w: Microsoft.FSharp.Core.int = 4 in let y1: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = x in let y2: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = &w in let arr: Microsoft.FSharp.Core.int Microsoft.FSharp.Core.[] = [|3; 4|] in let r: Microsoft.FSharp.Core.int Microsoft.FSharp.Core.ref = Operators.Ref<Microsoft.FSharp.Core.int> (3) in let y3: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = [I_ldelema (NormalAddress,false,ILArrayShape [(Some 0, None)],TypeVar 0us)](arr,0) in let y4: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = &r.contents in let z: Microsoft.FSharp.Core.int = Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (x,y1),y2),y3) in (w <- 3; (x <- 4; (y2 <- 4; (y3 <- 5; Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (z,x),y1),y2),y3),y4),IntrinsicFunctions.GetArray<Microsoft.FSharp.Core.int> (arr,0)),r.contents))))) @ (125,16--125,17)";
"let testFunctionThatUsesAddressesAndByrefs(x) = let mutable w: Microsoft.FSharp.Core.int = 4 in let y1: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = x in let y2: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = &w in let arr: Microsoft.FSharp.Core.int Microsoft.FSharp.Core.[] = [|3; 4|] in let r: Microsoft.FSharp.Core.int Microsoft.FSharp.Core.ref = Operators.Ref<Microsoft.FSharp.Core.int> (3) in let y3: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = [I_ldelema (NormalAddress,false,ILArrayShapeFIX,!0)](arr,0) in let y4: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = &r.contents in let z: Microsoft.FSharp.Core.int = Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (x,y1),y2),y3) in (w <- 3; (x <- 4; (y2 <- 4; (y3 <- 5; Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (z,x),y1),y2),y3),y4),IntrinsicFunctions.GetArray<Microsoft.FSharp.Core.int> (arr,0)),r.contents))))) @ (125,16--125,17)";
"let testFunctionThatUsesStructs1(dt) = dt.AddDays(3) @ (139,57--139,72)";
"let testFunctionThatUsesStructs2(unitVar0) = let dt1: System.DateTime = DateTime.get_Now () in let mutable dt2: System.DateTime = DateTime.get_Now () in let dt3: System.TimeSpan = Operators.op_Subtraction<System.DateTime,System.DateTime,System.TimeSpan> (dt1,dt2) in let dt4: System.DateTime = dt1.AddDays(3) in let dt5: Microsoft.FSharp.Core.int = dt1.get_Millisecond() in let dt6: Microsoft.FSharp.Core.byref<System.DateTime> = &dt2 in let dt7: System.TimeSpan = Operators.op_Subtraction<System.DateTime,System.DateTime,System.TimeSpan> (dt6,dt4) in dt7 @ (142,7--142,10)";
"let testFunctionThatUsesWhileLoop(unitVar0) = let mutable x: Microsoft.FSharp.Core.int = 1 in (while Operators.op_LessThan<Microsoft.FSharp.Core.int> (x,100) do x <- Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (x,1) done; x) @ (152,15--152,16)";
@ -815,11 +811,6 @@ let ``Test Optimized Declarations Project1`` () =
"member M2(__) (unitVar1) = __.compiledAsInstanceMethod(()) @ (56,21--56,47)";
"member SM1(unitVar0) = Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (compiledAsStaticField,ClassWithImplicitConstructor.compiledAsGenericStaticMethod<Microsoft.FSharp.Core.int> (compiledAsStaticField)) @ (57,26--57,101)";
"member SM2(unitVar0) = ClassWithImplicitConstructor.compiledAsStaticMethod (()) @ (58,26--58,50)";
//#if NO_PROJECTCRACKER // proxy for COMPILER
// "member ToString(__) (unitVar1) = String.Concat (base.ToString(),let value: Microsoft.FSharp.Core.int = 999 in let matchValue: Microsoft.FSharp.Core.obj = Operators.Box<Microsoft.FSharp.Core.int> (value) in match (if Operators.op_Equality<Microsoft.FSharp.Core.obj> (matchValue,dflt) then $0 else (if matchValue :? System.IFormattable then $1 else $2)) targets ...) @ (59,29--59,57)";
//#else
// //"member ToString(__) (unitVar1) = String.Concat (base.ToString(),let x: Microsoft.FSharp.Core.int = 999 in let matchValue: Microsoft.FSharp.Core.obj = Operators.Box<Microsoft.FSharp.Core.int> (x) in match (if Operators.op_Equality<Microsoft.FSharp.Core.obj> (matchValue,dflt) then $0 else (if matchValue :? System.IFormattable then $1 else $2)) targets ...) @ (59,29--59,57)";
//#endif
"member TestCallinToString(this) (unitVar1) = this.ToString() @ (60,39--60,54)";
"type Error"; "let err = {Data0 = 3; Data1 = 4} @ (64,10--64,20)";
"let matchOnException(err) = match (if err :? M.Error then $0 else $1) targets ... @ (66,33--66,36)";
@ -839,25 +830,13 @@ let ``Test Optimized Declarations Project1`` () =
"let v = M.c ().get_InstanceProperty(()) @ (98,8--98,26)";
"do Console.WriteLine (\"777\")";
"let functionWithSubmsumption(x) = IntrinsicFunctions.UnboxGeneric<Microsoft.FSharp.Core.string> (x) @ (102,40--102,52)";
//#if NO_PROJECTCRACKER // proxy for COMPILER
// "let functionWithCoercion(x) = let arg: Microsoft.FSharp.Core.string = let arg: Microsoft.FSharp.Core.string = IntrinsicFunctions.UnboxGeneric<Microsoft.FSharp.Core.string> (x :> Microsoft.FSharp.Core.obj) in M.functionWithSubmsumption (arg :> Microsoft.FSharp.Core.obj) in M.functionWithSubmsumption (arg :> Microsoft.FSharp.Core.obj) @ (103,39--103,116)";
//#else
// "let functionWithCoercion(x) = let x: Microsoft.FSharp.Core.string = let x: Microsoft.FSharp.Core.string = IntrinsicFunctions.UnboxGeneric<Microsoft.FSharp.Core.string> (x :> Microsoft.FSharp.Core.obj) in M.functionWithSubmsumption (x :> Microsoft.FSharp.Core.obj) in M.functionWithSubmsumption (x :> Microsoft.FSharp.Core.obj) @ (103,39--103,116)";
//#endif
"type MultiArgMethods";
"member .ctor(c,d) = (new Object(); ()) @ (105,5--105,20)";
"member Method(x) (a,b) = 1 @ (106,37--106,38)";
"member CurriedMethod(x) (a1,b1) (a2,b2) = 1 @ (107,63--107,64)";
"let testFunctionThatCallsMultiArgMethods(unitVar0) = let m: M.MultiArgMethods = new MultiArgMethods(3,4) in Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (m.Method(7,8),let arg00: Microsoft.FSharp.Core.int = 9 in let arg01: Microsoft.FSharp.Core.int = 10 in let arg10: Microsoft.FSharp.Core.int = 11 in let arg11: Microsoft.FSharp.Core.int = 12 in m.CurriedMethod(arg00,arg01,arg10,arg11)) @ (110,8--110,9)";
//#if NO_PROJECTCRACKER // proxy for COMPILER
// "let functionThatUsesObjectExpression(unitVar0) = { new Object() with member x.ToString(unitVar1) = let value: Microsoft.FSharp.Core.int = 888 in let matchValue: Microsoft.FSharp.Core.obj = Operators.Box<Microsoft.FSharp.Core.int> (value) in match (if Operators.op_Equality<Microsoft.FSharp.Core.obj> (matchValue,dflt) then $0 else (if matchValue :? System.IFormattable then $1 else $2)) targets ... } @ (114,3--114,55)";
// "let functionThatUsesObjectExpressionWithInterfaceImpl(unitVar0) = { new Object() with member x.ToString(unitVar1) = let value: Microsoft.FSharp.Core.int = 888 in let matchValue: Microsoft.FSharp.Core.obj = Operators.Box<Microsoft.FSharp.Core.int> (value) in match (if Operators.op_Equality<Microsoft.FSharp.Core.obj> (matchValue,dflt) then $0 else (if matchValue :? System.IFormattable then $1 else $2)) targets ... interface System.IComparable with member x.CompareTo(y) = 0 } :> System.IComparable @ (117,3--120,38)";
//#else
// "let functionThatUsesObjectExpression(unitVar0) = { new Object() with member x.ToString(unitVar1) = let x: Microsoft.FSharp.Core.int = 888 in let matchValue: Microsoft.FSharp.Core.obj = Operators.Box<Microsoft.FSharp.Core.int> (x) in match (if Operators.op_Equality<Microsoft.FSharp.Core.obj> (matchValue,dflt) then $0 else (if matchValue :? System.IFormattable then $1 else $2)) targets ... } @ (114,3--114,55)";
// "let functionThatUsesObjectExpressionWithInterfaceImpl(unitVar0) = { new Object() with member x.ToString(unitVar1) = let x: Microsoft.FSharp.Core.int = 888 in let matchValue: Microsoft.FSharp.Core.obj = Operators.Box<Microsoft.FSharp.Core.int> (x) in match (if Operators.op_Equality<Microsoft.FSharp.Core.obj> (matchValue,dflt) then $0 else (if matchValue :? System.IFormattable then $1 else $2)) targets ... interface System.IComparable with member x.CompareTo(y) = 0 } :> System.IComparable @ (117,3--120,38)";
//#endif
"let testFunctionThatUsesUnitsOfMeasure(x) (y) = Operators.op_Addition<Microsoft.FSharp.Core.float<'u>,Microsoft.FSharp.Core.float<'u>,Microsoft.FSharp.Core.float<'u>> (x,y) @ (122,70--122,75)";
"let testFunctionThatUsesAddressesAndByrefs(x) = let mutable w: Microsoft.FSharp.Core.int = 4 in let y1: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = x in let y2: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = &w in let arr: Microsoft.FSharp.Core.int Microsoft.FSharp.Core.[] = [|3; 4|] in let r: Microsoft.FSharp.Core.int Microsoft.FSharp.Core.ref = Operators.Ref<Microsoft.FSharp.Core.int> (3) in let y3: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = [I_ldelema (NormalAddress,false,ILArrayShapeFIX,TypeVar 0us)](arr,0) in let y4: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = &r.contents in let z: Microsoft.FSharp.Core.int = Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (x,y1),y2),y3) in (w <- 3; (x <- 4; (y2 <- 4; (y3 <- 5; Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (z,x),y1),y2),y3),y4),IntrinsicFunctions.GetArray<Microsoft.FSharp.Core.int> (arr,0)),r.contents))))) @ (125,16--125,17)";
"let testFunctionThatUsesAddressesAndByrefs(x) = let mutable w: Microsoft.FSharp.Core.int = 4 in let y1: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = x in let y2: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = &w in let arr: Microsoft.FSharp.Core.int Microsoft.FSharp.Core.[] = [|3; 4|] in let r: Microsoft.FSharp.Core.int Microsoft.FSharp.Core.ref = Operators.Ref<Microsoft.FSharp.Core.int> (3) in let y3: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = [I_ldelema (NormalAddress,false,ILArrayShapeFIX,!0)](arr,0) in let y4: Microsoft.FSharp.Core.byref<Microsoft.FSharp.Core.int> = &r.contents in let z: Microsoft.FSharp.Core.int = Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (x,y1),y2),y3) in (w <- 3; (x <- 4; (y2 <- 4; (y3 <- 5; Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32,Microsoft.FSharp.Core.int32> (Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (z,x),y1),y2),y3),y4),IntrinsicFunctions.GetArray<Microsoft.FSharp.Core.int> (arr,0)),r.contents))))) @ (125,16--125,17)";
"let testFunctionThatUsesStructs1(dt) = dt.AddDays(3) @ (139,57--139,72)";
"let testFunctionThatUsesStructs2(unitVar0) = let dt1: System.DateTime = DateTime.get_Now () in let mutable dt2: System.DateTime = DateTime.get_Now () in let dt3: System.TimeSpan = DateTime.op_Subtraction (dt1,dt2) in let dt4: System.DateTime = dt1.AddDays(3) in let dt5: Microsoft.FSharp.Core.int = dt1.get_Millisecond() in let dt6: Microsoft.FSharp.Core.byref<System.DateTime> = &dt2 in let dt7: System.TimeSpan = DateTime.op_Subtraction (dt6,dt4) in dt7 @ (142,7--142,10)";
"let testFunctionThatUsesWhileLoop(unitVar0) = let mutable x: Microsoft.FSharp.Core.int = 1 in (while Operators.op_LessThan<Microsoft.FSharp.Core.int> (x,100) do x <- Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (x,1) done; x) @ (152,15--152,16)";

Просмотреть файл

@ -1,6 +1,6 @@
#if INTERACTIVE
#r "../../debug/fcs/net45/FSharp.Compiler.Service.dll" // note, run 'build fcs debug' to generate this, this DLL has a public API so can be used from F# Interactive
#r "../../Debug/net40/bin/FSharp.Compiler.Service.ProjectCracker.dll"
#r "../../debug/fcs/net45/FSharp.Compiler.Service.ProjectCracker.dll"
#r "../../packages/NUnit.3.5.0/lib/net45/nunit.framework.dll"
#load "FsUnit.fs"
#load "Common.fs"