Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge main to release/dev17.11 #17095

Merged
merged 3 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/Compiler/Checking/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10625,6 +10625,11 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt
| NormalizedBinding(vis, kind, isInline, isMutable, attrs, xmlDoc, _, valSynData, pat, NormalizedBindingRhs(spatsL, rtyOpt, rhsExpr), mBinding, debugPoint) ->
let (SynValData(memberFlags = memberFlagsOpt)) = valSynData

let isClassLetBinding =
match declKind, kind with
| ClassLetBinding _, SynBindingKind.Normal -> true
| _ -> false

let callerName =
match declKind, kind, pat with
| ExpressionBinding, _, _ -> envinner.eCallerMemberName
Expand Down Expand Up @@ -10880,14 +10885,14 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt
errorR(Error(FSComp.SR.tcLiteralCannotHaveGenericParameters(), mBinding))

if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) && memberFlagsOpt.IsNone && not attrs.IsEmpty then
TcAttributeTargetsOnLetBindings cenv env attrs overallPatTy overallExprTy (not declaredTypars.IsEmpty)
TcAttributeTargetsOnLetBindings cenv env attrs overallPatTy overallExprTy (not declaredTypars.IsEmpty) isClassLetBinding

CheckedBindingInfo(inlineFlag, valAttribs, xmlDoc, tcPatPhase2, explicitTyparInfo, nameToPrelimValSchemeMap, rhsExprChecked, argAndRetAttribs, overallPatTy, mBinding, debugPoint, isCompGen, literalValue, isFixed), tpenv

// Note:
// - Let bound values can only have attributes that uses AttributeTargets.Field ||| AttributeTargets.Property ||| AttributeTargets.ReturnValue
// - Let function bindings can only have attributes that uses AttributeTargets.Method ||| AttributeTargets.ReturnValue
and TcAttributeTargetsOnLetBindings (cenv: cenv) env attrs overallPatTy overallExprTy areTyparsDeclared =
and TcAttributeTargetsOnLetBindings (cenv: cenv) env attrs overallPatTy overallExprTy areTyparsDeclared isClassLetBinding =
let attrTgt =
if
// It's a type function:
Expand All @@ -10899,7 +10904,11 @@ and TcAttributeTargetsOnLetBindings (cenv: cenv) env attrs overallPatTy overallE
|| isFunTy cenv.g overallPatTy
|| isFunTy cenv.g overallExprTy
then
AttributeTargets.ReturnValue ||| AttributeTargets.Method
// Class let bindings are a special case, they can have attributes that target fields and properties, since they might be lifted to those and contain lambdas/functions.
if isClassLetBinding then
AttributeTargets.ReturnValue ||| AttributeTargets.Method ||| AttributeTargets.Field ||| AttributeTargets.Property
else
AttributeTargets.ReturnValue ||| AttributeTargets.Method
else
AttributeTargets.ReturnValue ||| AttributeTargets.Field ||| AttributeTargets.Property

Expand Down
4 changes: 3 additions & 1 deletion src/Compiler/Utilities/illib.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ open System.Runtime.CompilerServices
[<Class>]
type InterruptibleLazy<'T> private (value, valueFactory: unit -> 'T) =
let syncObj = obj ()

[<VolatileField>]
let mutable valueFactory = valueFactory

let mutable value = value

new(valueFactory: unit -> 'T) = InterruptibleLazy(Unchecked.defaultof<_>, valueFactory)
Expand All @@ -28,7 +31,6 @@ type InterruptibleLazy<'T> private (value, valueFactory: unit -> 'T) =
match box valueFactory with
| null -> value
| _ ->

Monitor.Enter(syncObj)

try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,27 +171,7 @@ module CustomAttributes_AttributeUsage =
|> withLangVersionPreview
|> withOptions ["--nowarn:25"]
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 842, Line 11, Col 6, Line 11, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 14, Col 6, Line 14, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 17, Col 6, Line 17, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 19, Col 10, Line 19, Col 19, "This attribute is not valid for use on this language element")
(Error 842, Line 21, Col 6, Line 21, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 24, Col 6, Line 24, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 27, Col 6, Line 27, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 30, Col 6, Line 30, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 33, Col 6, Line 33, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 36, Col 6, Line 36, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 39, Col 6, Line 39, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 42, Col 6, Line 42, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 45, Col 6, Line 45, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 49, Col 6, Line 49, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 56, Col 6, Line 56, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 64, Col 6, Line 64, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 66, Col 10, Line 66, Col 19, "This attribute is not valid for use on this language element")
(Error 842, Line 68, Col 6, Line 68, Col 15, "This attribute is not valid for use on this language element")
]
|> shouldSucceed

// SOURCE=E_AttributeTargetIsMethod02.fs # E_AttributeTargetIsMethod02.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"E_AttributeTargetIsMethod02.fs"|])>]
Expand Down Expand Up @@ -591,4 +571,16 @@ module CustomAttributes_AttributeUsage =
(Error 842, Line 20, Col 3, Line 20, Col 15, "This attribute is not valid for use on this language element")
(Error 842, Line 21, Col 3, Line 21, Col 18, "This attribute is not valid for use on this language element")
(Error 842, Line 22, Col 3, Line 22, Col 13, "This attribute is not valid for use on this language element")
]
]

[<Fact>]
let ``Type-level let bindings allowed to use attribute with Field target`` () =
FSharp"""
module Foo
type InterruptibleLazy<'T> private (valueFactory: unit -> 'T) =
[<VolatileField>]
let mutable valueFactory = valueFactory
"""
|> withLangVersionPreview
|> compile
|> shouldSucceed
Original file line number Diff line number Diff line change
Expand Up @@ -8,62 +8,62 @@ type FieldOnlyAttribute() =
inherit Attribute()

type TestClass() =
[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
static let func1() = "someFunction"

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
static let rec func2() = "someFunction"

[<FieldOnly>]// Should fail
[<FieldOnly>]// Should succeed (special exception when function can be lifted to a field)
static let rec func3() = "someFunction"
and [<FieldOnly>] fun4() = "someFunction" // Should fail
and [<FieldOnly>] fun4() = "someFunction" // Should succeed (special exception when function can be lifted to a field)

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let func5 () = "someFunction"

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let func6 a = a + 1

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let func7 (a, b) = a + b

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let func8 (a: int) : int = a + 1

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let func9 a b = [ a; b ]

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let func10 = fun x -> x

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let func11 = id

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let (|Bool|_|) = function "true" -> Some true | "false" -> Some false | _ -> None

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
[<return: Struct>]
let (|BoolExpr2|_|) = function "true" -> ValueSome true | "false" -> ValueSome false | _ -> ValueNone

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let (|BoolExpr3|_|) x =
match x with
| "true" -> Some true
| "false" -> Some false
| _ -> None

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
[<return: Struct>]
let (|BoolExpr4|_|) x =
match x with
| "true" -> ValueSome true
| "false" -> ValueSome false
| _ -> ValueNone

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let rec func12() = 0
and [<FieldOnly>] func13() = [] // Should fail
and [<FieldOnly>] func13() = [] // Should succeed (special exception when function can be lifted to a field)

[<FieldOnly>] // Should fail
[<FieldOnly>] // Should succeed (special exception when function can be lifted to a field)
let rec func14() = 0
Loading