Skip to content

Commit

Permalink
Ref/Span fixes (#5146) - dev15.8 branch (#5218)
Browse files Browse the repository at this point in the history
* Ref/Span fixes (#5146)

* Added LimitedValFlags for PostInferenceChecks

* More work

* Renamed IsLimited to IsLimitedSpanLike

* Don't use isByRefReturnCall in CheckExprs

* Minor cleanup

* Changed error message. Fixed safety rule regarding byrefs returning and passing.

* Fixed an edge case with returning span. Simplified Expr.App

* Cleanup

* Fixed a few ref return checks. Partially handling byref of span-like types

* Simplifying flags. Added CheckCall

* Updated test baseline. Added several CheckCall functions

* Updated baseline tests

* Handling byref of span likes

* Added a little bit better error msg for LByrefGet

* Removed commented code

* Fixed test

* Fixed inability to use byref<Span<>> for delegates and slots

* Minor cleanup with some comments

* Few more comments

* Running neg tests in core/span. Fixed bug in IsByRefLike structs with span fields

* Updated baseline

* Fixed more issues with slots. Simplified PermitByRefType

* Added a little better error messages on spans

* Fixed record construction for span likes. Fixed setting fields on mutable structs not having any rules for span likes. Updated a few error msgs. Added lots of tests.

* Updated error msg on function call. Added a removed comment from previous commit. Updated baselines

* Added internalTestSpanStackReferring test option

* Added special handling for receivers

* Fixing build

* Fixing build

* Fixing build

* More tests, updated baseline

* Opening System in PostInferenceChecks
  • Loading branch information
TIHan authored and KevinRansom committed Jun 20, 2018
1 parent ba5829a commit 8d66249
Show file tree
Hide file tree
Showing 34 changed files with 1,157 additions and 292 deletions.
20 changes: 16 additions & 4 deletions src/buildfromsource/FSharp.Compiler.Private/FSComp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4324,10 +4324,10 @@ type internal SR private() =
/// A type annotated with IsByRefLike must also be a struct. Consider adding the [<Struct>] attribute to the type.
/// (Originally from ..\FSComp.txt:1432)
static member tcByRefLikeNotStruct() = (3227, GetStringFunc("tcByRefLikeNotStruct",",,,") )
/// 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.
/// The address of a value returned from the expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope.
/// (Originally from ..\FSComp.txt:1433)
static member chkNoByrefReturnOfLocal(a0 : System.String) = (3228, GetStringFunc("chkNoByrefReturnOfLocal",",,,%s,,,") a0)
/// The IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.
static member chkNoByrefAddressOfValueFromExpression() = (3228, GetStringFunc("chkNoByrefAddressOfValueFromExpression",",,,") )
/// The Span or IsByRefLike expression cannot be returned from this function or method, because it is composed using elements that may escape their scope.
/// (Originally from ..\FSComp.txt:1434)
static member chkNoReturnOfLimitedSpan() = (3229, GetStringFunc("chkNoReturnOfLimitedSpan",",,,") )
/// 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.
Expand All @@ -4342,6 +4342,15 @@ type internal SR private() =
/// Struct members cannot return 'this' or fields by reference
/// (Originally from ..\FSComp.txt:1438)
static member chkStructsMayNotReturnAddressesOfContents() = (3234, GetStringFunc("chkStructsMayNotReturnAddressesOfContents",",,,") )
/// The function or method call cannot be used at this point, because one argument that is a byref of a non-stack-local Span or IsByRefLike type is used with another argument that is a stack-local Span or IsByRefLike type. This is to ensure the address of the local value does not escape its scope.
/// (Originally from ..\FSComp.txt:1439)
static member chkNoByrefLikeFunctionCall() = (3235, GetStringFunc("chkNoByrefLikeFunctionCall",",,,") )
/// The Span or IsByRefLike variable '%s' cannot be used at this point. This is to ensure the address of the local value does not escape its scope.
/// (Originally from ..\FSComp.txt:1440)
static member chkNoSpanLikeVariable(a0 : System.String) = (3236, GetStringFunc("chkNoSpanLikeVariable",",,,%s,,,") a0)
/// A Span or IsByRefLike value returned from the expression cannot be used at ths point. This is to ensure the address of the local value does not escape its scope.
/// (Originally from ..\FSComp.txt:1441)
static member chkNoSpanLikeValueFromExpression() = (3237, GetStringFunc("chkNoSpanLikeValueFromExpression",",,,") )

/// Call this method once to validate that all known resources are valid; throws if not
static member RunStartupValidation() =
Expand Down Expand Up @@ -5748,10 +5757,13 @@ type internal SR private() =
ignore(GetString("readOnlyAttributeOnStructWithMutableField"))
ignore(GetString("tcByrefReturnImplicitlyDereferenced"))
ignore(GetString("tcByRefLikeNotStruct"))
ignore(GetString("chkNoByrefReturnOfLocal"))
ignore(GetString("chkNoByrefAddressOfValueFromExpression"))
ignore(GetString("chkNoReturnOfLimitedSpan"))
ignore(GetString("chkNoWriteToLimitedSpan"))
ignore(GetString("tastValueMustBeLocal"))
ignore(GetString("tcIsReadOnlyNotStruct"))
ignore(GetString("chkStructsMayNotReturnAddressesOfContents"))
ignore(GetString("chkNoByrefLikeFunctionCall"))
ignore(GetString("chkNoSpanLikeVariable"))
ignore(GetString("chkNoSpanLikeValueFromExpression"))
()
15 changes: 12 additions & 3 deletions src/buildfromsource/FSharp.Compiler.Private/FSComp.resx
Original file line number Diff line number Diff line change
Expand Up @@ -4327,11 +4327,11 @@
<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 name="chkNoByrefAddressOfValueFromExpression" xml:space="preserve">
<value>The address of a value returned from the 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="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>
<value>The Span or 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>
Expand All @@ -4345,4 +4345,13 @@
<data name="chkStructsMayNotReturnAddressesOfContents" xml:space="preserve">
<value>Struct members cannot return 'this' or fields by reference</value>
</data>
<data name="chkNoByrefLikeFunctionCall" xml:space="preserve">
<value>The function or method call cannot be used at this point, because one argument that is a byref of a non-stack-local Span or IsByRefLike type is used with another argument that is a stack-local Span or IsByRefLike type. This is to ensure the address of the local value does not escape its scope.</value>
</data>
<data name="chkNoSpanLikeVariable" xml:space="preserve">
<value>The Span or IsByRefLike variable '{0}' 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="chkNoSpanLikeValueFromExpression" xml:space="preserve">
<value>A Span or IsByRefLike value returned from the expression cannot be used at ths point. This is to ensure the address of the local value does not escape its scope.</value>
</data>
</root>
7 changes: 5 additions & 2 deletions src/fsharp/CompileOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2346,6 +2346,7 @@ type TcConfigBuilder =
/// and from which we can read the metadata. Only used when metadataOnly=true.
mutable tryGetMetadataSnapshot : ILReaderTryGetMetadataSnapshot

mutable internalTestSpanStackReferring : bool
}

static member Initial =
Expand Down Expand Up @@ -2482,6 +2483,7 @@ type TcConfigBuilder =
copyFSharpCore = CopyFSharpCoreFlag.No
shadowCopyReferences = false
tryGetMetadataSnapshot = (fun _ -> None)
internalTestSpanStackReferring = false
}

static member CreateNew(legacyReferenceResolver, defaultFSharpBinariesDir, reduceMemoryUsage, implicitIncludeDir,
Expand Down Expand Up @@ -2942,6 +2944,7 @@ type TcConfig private (data : TcConfigBuilder, validate:bool) =
member x.copyFSharpCore = data.copyFSharpCore
member x.shadowCopyReferences = data.shadowCopyReferences
member x.tryGetMetadataSnapshot = data.tryGetMetadataSnapshot
member x.internalTestSpanStackReferring = data.internalTestSpanStackReferring
static member Create(builder, validate) =
use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter
TcConfig(builder, validate)
Expand Down Expand Up @@ -5429,7 +5432,7 @@ let TypeCheckOneInputEventually (checkForErrors, tcConfig:TcConfig, tcImports:Tc

// Typecheck the signature file
let! (tcEnv, sigFileType, createsGeneratedProvidedTypes) =
TypeCheckOneSigFile (tcGlobals, tcState.tcsNiceNameGen, amap, tcState.tcsCcu, checkForErrors, tcConfig.conditionalCompilationDefines, tcSink) tcState.tcsTcSigEnv file
TypeCheckOneSigFile (tcGlobals, tcState.tcsNiceNameGen, amap, tcState.tcsCcu, checkForErrors, tcConfig.conditionalCompilationDefines, tcSink, tcConfig.internalTestSpanStackReferring) tcState.tcsTcSigEnv file

let rootSigs = Zmap.add qualNameOfFile sigFileType tcState.tcsRootSigs

Expand Down Expand Up @@ -5466,7 +5469,7 @@ let TypeCheckOneInputEventually (checkForErrors, tcConfig:TcConfig, tcImports:Tc

// Typecheck the implementation file
let! topAttrs, implFile, _implFileHiddenType, tcEnvAtEnd, createsGeneratedProvidedTypes =
TypeCheckOneImplFile (tcGlobals, tcState.tcsNiceNameGen, amap, tcState.tcsCcu, checkForErrors, tcConfig.conditionalCompilationDefines, tcSink) tcImplEnv rootSigOpt file
TypeCheckOneImplFile (tcGlobals, tcState.tcsNiceNameGen, amap, tcState.tcsCcu, checkForErrors, tcConfig.conditionalCompilationDefines, tcSink, tcConfig.internalTestSpanStackReferring) tcImplEnv rootSigOpt file

let hadSig = rootSigOpt.IsSome
let implFileSigType = SigTypeOfImplFile implFile
Expand Down
3 changes: 3 additions & 0 deletions src/fsharp/CompileOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@ type TcConfigBuilder =
/// A function to call to try to get an object that acts as a snapshot of the metadata section of a .NET binary,
/// and from which we can read the metadata. Only used when metadataOnly=true.
mutable tryGetMetadataSnapshot : ILReaderTryGetMetadataSnapshot

/// if true - 'let mutable x = Span.Empty', the value 'x' is a stack referring span. Used for internal testing purposes only until we get true stack spans.
mutable internalTestSpanStackReferring : bool
}

static member Initial: TcConfigBuilder
Expand Down
1 change: 1 addition & 0 deletions src/fsharp/CompileOptions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,7 @@ let advancedFlagsFsc tcConfigB =
let testFlag tcConfigB =
CompilerOption("test", tagString, OptionString (fun s ->
match s with
| "StackSpan" -> tcConfigB.internalTestSpanStackReferring <- true
| "ErrorRanges" -> tcConfigB.errorStyle <- ErrorStyle.TestErrors
| "MemberBodyRanges" -> PostTypeCheckSemanticChecks.testFlagMemberBody := true
| "Tracking" -> Lib.tracking := true (* general purpose on/off diagnostics flag *)
Expand Down
7 changes: 5 additions & 2 deletions src/fsharp/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1430,9 +1430,12 @@ notAFunctionButMaybeDeclaration,"This value is not a function and cannot be appl
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."
3228,chkNoByrefAddressOfValueFromExpression,"The address of a value returned from the expression cannot be used at this point. This is to ensure the address of the local value does not escape its scope."
3229,chkNoReturnOfLimitedSpan,"The Span or 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"
3235,chkNoByrefLikeFunctionCall,"The function or method call cannot be used at this point, because one argument that is a byref of a non-stack-local Span or IsByRefLike type is used with another argument that is a stack-local Span or IsByRefLike type. This is to ensure the address of the local value does not escape its scope."
3236,chkNoSpanLikeVariable,"The Span or IsByRefLike variable '%s' cannot be used at this point. This is to ensure the address of the local value does not escape its scope."
3237,chkNoSpanLikeValueFromExpression,"A Span or IsByRefLike value returned from the expression cannot be used at ths point. This is to ensure the address of the local value does not escape its scope."
Loading

0 comments on commit 8d66249

Please sign in to comment.