diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md index 067a9d56800..f5d0628ae75 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md @@ -1,3 +1,6 @@ +### Added +* Add opt-in warning attribute not valid for union case with fields [PR #18532](https://github.com/dotnet/fsharp/pull/18532)) + ### Fixed * Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543)) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 7d8a0e0764e..1877e892f4f 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -576,22 +576,33 @@ module TcRecdUnionAndEnumDeclarations = let checkXmlDocs = cenv.diagnosticOptions.CheckXmlDocs let xmlDoc = xmldoc.ToXmlDoc(checkXmlDocs, Some names) - let attrs = - (* - The attributes of a union case decl get attached to the generated "static factory" method. - Enforce union-cases AttributeTargets: - - AttributeTargets.Method - type SomeUnion = - | Case1 of int // Compiles down to a static method - - AttributeTargets.Property - type SomeUnion = - | Case1 // Compiles down to a static property - *) - if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) then - let target = if rfields.IsEmpty then AttributeTargets.Property else AttributeTargets.Method - TcAttributes cenv env target synAttrs - else - TcAttributes cenv env AttributeTargets.UnionCaseDecl synAttrs + let attrs = TcAttributes cenv env AttributeTargets.UnionCaseDecl synAttrs + (* + The attributes of a union case decl get attached to the generated "static factory" method. + Enforce union-cases AttributeTargets: + - AttributeTargets.Method + type SomeUnion = + | Case1 of int // Compiles down to a static method + - AttributeTargets.Property + type SomeUnion = + | Case1 // Compiles down to a static property + *) + if g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) then + let attrTargets = + attrs + |> List.collect (fun attr -> + attr.TyconRef.Attribs + |> List.choose (fun attr -> + match attr with + | Attrib(unnamedArgs = [ AttribInt32Arg validOn ]) -> Some validOn + | _ -> None)) + + attrTargets + |> List.iter (fun target -> + // If the union case has fields, and the target is not AttributeTargets.Method || AttributeTargets.All. Then we raise a separate opt-in warning + let hasNotMethodTarget = (enum target &&& AttributeTargets.Method) = enum 0 + if hasNotMethodTarget then + warning(Error(FSComp.SR.tcAttributeIsNotValidForUnionCaseWithFields(), id.idRange))) Construct.NewUnionCase id rfields recordTy attrs xmlDoc vis diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 1e0d3edc889..4ce2fb1700b 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -11288,6 +11288,75 @@ and TcNonRecursiveBinding declKind cenv env tpenv ty binding = let explicitTyparInfo, tpenv = TcNonrecBindingTyparDecls cenv env tpenv binding TcNormalizedBinding declKind cenv env tpenv ty None NoSafeInitInfo ([], explicitTyparInfo) binding +and ResolveAttributeType (cenv: cenv) (env: TcEnv) (mAttr: range) (tycon: Ident list) = + let tpenv = emptyUnscopedTyparEnv + let ad = env.eAccessRights + + let tyPath, tyId = List.frontAndBack tycon + + let try1 n = + let tyid = mkSynId tyId.idRange n + let tycon = (tyPath @ [tyid]) + + match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurrence.UseInAttribute OpenQualified env.eNameResEnv ad tycon TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No with + | Exception err -> raze err + | Result(tinstEnclosing, tcref, inst) -> success(TcTypeApp cenv NoNewTypars CheckCxs ItemOccurrence.UseInAttribute env tpenv mAttr tcref tinstEnclosing [] inst) + + ForceRaise ((try1 (tyId.idText + "Attribute")) |> otherwise (fun () -> (try1 tyId.idText))) + +and CheckAttributeUsage (g: TcGlobals) (mAttr: range) (tcref: TyconRef) (attrTgt: AttributeTargets) (targetIndicator: Ident option) (attrEx: AttributeTargets) = + // REVIEW: take notice of inherited? + let validOn, _inherited = + let validOnDefault = 0x7fff + let inheritedDefault = true + if tcref.IsILTycon then + let tdef = tcref.ILTyconRawMetadata + let tref = g.attrib_AttributeUsageAttribute.TypeRef + + match TryDecodeILAttribute tref tdef.CustomAttrs with + | Some ([ILAttribElem.Int32 validOn ], named) -> + let inherited = + match List.tryPick (function "Inherited", _, _, ILAttribElem.Bool res -> Some res | _ -> None) named with + | None -> inheritedDefault + | Some x -> x + (validOn, inherited) + | Some ([ILAttribElem.Int32 validOn; ILAttribElem.Bool _allowMultiple; ILAttribElem.Bool inherited ], _) -> + (validOn, inherited) + | _ -> + (validOnDefault, inheritedDefault) + else + match (TryFindFSharpAttribute g g.attrib_AttributeUsageAttribute tcref.Attribs) with + | Some(Attrib(unnamedArgs = [ AttribInt32Arg validOn ])) -> + validOn, inheritedDefault + | Some(Attrib(unnamedArgs = [ AttribInt32Arg validOn; AttribBoolArg(_allowMultiple); AttribBoolArg inherited])) -> + validOn, inherited + | Some _ -> + warning(Error(FSComp.SR.tcUnexpectedConditionInImportedAssembly(), mAttr)) + validOnDefault, inheritedDefault + | _ -> + validOnDefault, inheritedDefault + + // Determine valid attribute targets + let attributeTargets = enum validOn &&& attrTgt + let directedTargets = + match targetIndicator with + | LongFormAttrTarget attrTarget -> attrTarget + | UnrecognizedLongAttrTarget attrTarget -> + errorR(Error(FSComp.SR.tcUnrecognizedAttributeTarget(), attrTarget.idRange)) + attributeTargets + | ShortFormAttributeTarget -> attributeTargets &&& ~~~ attrEx + + let constrainedTargets = attributeTargets &&& directedTargets + + // Check if attribute is valid for the target + if constrainedTargets = enum 0 then + if (directedTargets = AttributeTargets.Assembly || directedTargets = AttributeTargets.Module) then + errorR(Error(FSComp.SR.tcAttributeIsNotValidForLanguageElementUseDo(), mAttr)) + else + warning(Error(FSComp.SR.tcAttributeIsNotValidForLanguageElement(), mAttr)) + + constrainedTargets + //------------------------------------------------------------------------- // TcAttribute* // *Ex means the function accepts attribute targets that must be explicit @@ -11302,24 +11371,13 @@ and TcAttributeEx canFail (cenv: cenv) (env: TcEnv) attrTgt attrEx (synAttr: Syn let targetIndicator = synAttr.Target let isAppliedToGetterOrSetter = synAttr.AppliesToGetterAndSetter let mAttr = synAttr.Range - let typath, tyid = List.frontAndBack tycon - let tpenv = emptyUnscopedTyparEnv + let _, tyId = List.frontAndBack tycon let ad = env.eAccessRights // if we're checking an attribute that was applied directly to a getter or a setter, then // what we're really checking against is a method, not a property let attrTgt = if isAppliedToGetterOrSetter then ((attrTgt ^^^ AttributeTargets.Property) ||| AttributeTargets.Method) else attrTgt - let ty, tpenv = - let try1 n = - let tyid = mkSynId tyid.idRange n - let tycon = (typath @ [tyid]) - - match ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurrence.UseInAttribute OpenQualified env.eNameResEnv ad tycon TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No with - | Exception err -> raze err - | Result(tinstEnclosing, tcref, inst) -> success(TcTypeApp cenv NoNewTypars CheckCxs ItemOccurrence.UseInAttribute env tpenv mAttr tcref tinstEnclosing [] inst) - - ForceRaise ((try1 (tyid.idText + "Attribute")) |> otherwise (fun () -> (try1 tyid.idText))) - + let ty, tpenv = ResolveAttributeType cenv env mAttr tycon if not (IsTypeAccessible g cenv.amap mAttr ad ty) then errorR(Error(FSComp.SR.tcTypeIsInaccessible(), mAttr)) let tcref = tcrefOfAppTy g ty @@ -11330,53 +11388,7 @@ and TcAttributeEx canFail (cenv: cenv) (env: TcEnv) attrTgt attrEx (synAttr: Syn | Some d, Some defines when not (List.contains d defines) -> [], false | _ -> - // REVIEW: take notice of inherited? - let validOn, _inherited = - let validOnDefault = 0x7fff - let inheritedDefault = true - if tcref.IsILTycon then - let tdef = tcref.ILTyconRawMetadata - let tref = g.attrib_AttributeUsageAttribute.TypeRef - - match TryDecodeILAttribute tref tdef.CustomAttrs with - | Some ([ILAttribElem.Int32 validOn ], named) -> - let inherited = - match List.tryPick (function "Inherited", _, _, ILAttribElem.Bool res -> Some res | _ -> None) named with - | None -> inheritedDefault - | Some x -> x - (validOn, inherited) - | Some ([ILAttribElem.Int32 validOn; ILAttribElem.Bool _allowMultiple; ILAttribElem.Bool inherited ], _) -> - (validOn, inherited) - | _ -> - (validOnDefault, inheritedDefault) - else - match (TryFindFSharpAttribute g g.attrib_AttributeUsageAttribute tcref.Attribs) with - | Some(Attrib(_, _, [ AttribInt32Arg validOn ], _, _, _, _)) -> - (validOn, inheritedDefault) - | Some(Attrib(_, _, [ AttribInt32Arg validOn - AttribBoolArg(_allowMultiple) - AttribBoolArg inherited], _, _, _, _)) -> - (validOn, inherited) - | Some _ -> - warning(Error(FSComp.SR.tcUnexpectedConditionInImportedAssembly(), mAttr)) - (validOnDefault, inheritedDefault) - | _ -> - (validOnDefault, inheritedDefault) - let attributeTargets = enum validOn &&& attrTgt - let directedTargets = - match targetIndicator with - | LongFormAttrTarget attrTarget -> attrTarget - | UnrecognizedLongAttrTarget attrTarget -> - errorR(Error(FSComp.SR.tcUnrecognizedAttributeTarget(), attrTarget.idRange)) - attributeTargets - | ShortFormAttributeTarget -> attributeTargets &&& ~~~ attrEx - - let constrainedTargets = attributeTargets &&& directedTargets - if constrainedTargets = enum 0 then - if (directedTargets = AttributeTargets.Assembly || directedTargets = AttributeTargets.Module) then - error(Error(FSComp.SR.tcAttributeIsNotValidForLanguageElementUseDo(), mAttr)) - else - warning(Error(FSComp.SR.tcAttributeIsNotValidForLanguageElement(), mAttr)) + let constrainedTargets = CheckAttributeUsage g mAttr tcref attrTgt targetIndicator attrEx match ResolveObjectConstructor cenv.nameResolver env.DisplayEnv mAttr ad ty with | Exception _ when canFail = TcCanFail.IgnoreAllErrors || canFail = TcCanFail.IgnoreMemberResoutionError -> [ ], true @@ -11391,7 +11403,7 @@ and TcAttributeEx canFail (cenv: cenv) (env: TcEnv) attrTgt attrEx (synAttr: Syn match item with | Item.CtorGroup(methodName, minfos) -> let meths = minfos |> List.map (fun minfo -> minfo, None) - let afterResolution = ForNewConstructors cenv.tcSink env tyid.idRange methodName minfos + let afterResolution = ForNewConstructors cenv.tcSink env tyId.idRange methodName minfos let (expr, attributeAssignedNamedItems, _), _ = TcMethodApplication true cenv env tpenv None [] mAttr mAttr methodName None ad PossiblyMutates false meths afterResolution NormalValUse [arg] (MustEqual ty) None [] diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fsi b/src/Compiler/Checking/Expressions/CheckExpressions.fsi index ed18b07a58a..5992a4afc95 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fsi +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fsi @@ -955,6 +955,8 @@ module AttributeTargets = val FieldDeclRestricted: AttributeTargets /// The allowed attribute targets for an F# union case declaration + /// - AttributeTargets.Method: union case with fields + /// - AttributeTargets.Property: union case with no fields val UnionCaseDecl: AttributeTargets /// The allowed attribute targets for an F# type declaration diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 5f96b1f58c8..c43b23c99c2 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -402,6 +402,7 @@ type PhasedDiagnostic with | 3579 -> false // alwaysUseTypedStringInterpolation - off by default | 3582 -> false // infoIfFunctionShadowsUnionCase - off by default | 3570 -> false // tcAmbiguousDiscardDotLambda - off by default + | 3878 -> false // tcAttributeIsNotValidForUnionCaseWithFields - off by default | _ -> match x.Exception with | DiagnosticEnabledWithLanguageFeature(_, _, _, enabled) -> enabled diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index f1c65d5771e..78dde5bd148 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1806,4 +1806,5 @@ featureAllowLetOrUseBangTypeAnnotationWithoutParens,"Allow let! and use! type an 3874,lexWarnDirectiveMustBeFirst,"#nowarn/#warnon directives must appear as the first non-whitespace characters on a line" 3875,lexWarnDirectiveMustHaveArgs,"Warn directives must have warning number(s) as argument(s)" 3876,lexWarnDirectivesMustMatch,"There is another %s for this warning already in line %d." -3877,lexLineDirectiveMappingIsNotUnique,"The file '%s' was also pointed to in a line directive in '%s'. Proper warn directive application may not be possible." \ No newline at end of file +3877,lexLineDirectiveMappingIsNotUnique,"The file '%s' was also pointed to in a line directive in '%s'. Proper warn directive application may not be possible." +3878,tcAttributeIsNotValidForUnionCaseWithFields,"This attribute is not valid for use on union cases with fields." \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 397f1269c6d..bcd1c3fb0bd 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -1397,6 +1397,11 @@ Pole {0} se v tomto anonymním typu záznamu vyskytuje vícekrát. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. Atributy nejde použít pro rozšíření typů. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index ca308ca9b13..0886b9ec60b 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -1397,6 +1397,11 @@ Das Feld "{0}" ist in diesem anonymen Datensatztyp mehrmals vorhanden. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. Attribute können nicht auf Typerweiterungen angewendet werden. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 4b82afb40de..bdb43c5e1af 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -1397,6 +1397,11 @@ El campo "{0}" aparece varias veces en este tipo de registro anónimo. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. Los atributos no se pueden aplicar a las extensiones de tipo. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 88b5c2c8f11..5344354b3ab 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -1397,6 +1397,11 @@ Le champ '{0}' apparaît plusieurs fois dans ce type d'enregistrement anonyme. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. Impossible d'appliquer des attributs aux extensions de type. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index dc03b73e98a..ec472ee00b9 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -1397,6 +1397,11 @@ Il campo '{0}' viene visualizzato più volte in questo tipo di record anonimo. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. Gli attributi non possono essere applicati a estensioni di tipo. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 99644e44b11..8db04ab1625 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -1397,6 +1397,11 @@ この匿名レコードの種類に、フィールド '{0}' が複数回出現します。 + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. 属性を型拡張に適用することはできません。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index cd439a93768..a17460ee156 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -1397,6 +1397,11 @@ '{0}' 필드가 이 익명 레코드 형식에서 여러 번 나타납니다. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. 형식 확장에 특성을 적용할 수 없습니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index f50063b24f1..94416cfb231 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -1397,6 +1397,11 @@ Pole „{0}” występuje wielokrotnie w tym anonimowym typie rekordu. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. Atrybutów nie można stosować do rozszerzeń typu. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 1e60a4d33b3..99709def4e0 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -1397,6 +1397,11 @@ O campo '{0}' aparece várias vezes nesse tipo de registro anônimo. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. Os atributos não podem ser aplicados às extensões de tipo. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index b1592085f5c..e1e97fdf67e 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -1397,6 +1397,11 @@ Поле "{0}" появляется несколько раз в этом типе анонимной записи. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. Атрибуты не могут быть применены к расширениям типа. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 3ea96d4b85e..cff0f89ef17 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -1397,6 +1397,11 @@ '{0}' alanı bu anonim kayıt türünde birden fazla yerde görünüyor. + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. Öznitelikler tür uzantılarına uygulanamaz. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index cdc91d51daa..5ce3ac9c822 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -1397,6 +1397,11 @@ 字段“{0}”在此匿名记录类型中多次出现。 + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. 属性不可应用于类型扩展。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 99dd36c34bc..ae4eeed6b13 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -1397,6 +1397,11 @@ 欄位 '{0}' 在這個匿名記錄類型中出現多次。 + + This attribute is not valid for use on union cases with fields. + This attribute is not valid for use on union cases with fields. + + Attributes cannot be applied to type extensions. 屬性無法套用到類型延伸模組。 diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs index f027745b73e..b0fa891d2b7 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/CustomAttributes/AttributeUsage/AttributeUsage.fs @@ -64,6 +64,7 @@ module CustomAttributes_AttributeUsage = let ``AttributeTargetsIsMethod01_fs 8.0`` compilation = compilation |> withLangVersion80 + |> withWarnOn 3878 |> verifyCompileAndRun |> shouldSucceed @@ -74,6 +75,15 @@ module CustomAttributes_AttributeUsage = |> verifyCompileAndRun |> shouldSucceed + // SOURCE=AttributeTargetsIsMethod01.fs # AttributeTargetsIsMethod01.fs + [] + let ``Preview: AttributeTargetsIsMethod01_fs opt-in warning`` compilation = + compilation + |> withLangVersionPreview + |> withWarnOn 3878 + |> verifyCompileAndRun + |> shouldSucceed + // SOURCE=AttributeTargetsIsProperty.fs # AttributeTargetsIsProperty.fs [] let ``AttributeTargetsIsProperty_fs 8.0`` compilation = @@ -483,6 +493,18 @@ module CustomAttributes_AttributeUsage = |> withDiagnostics [ (Warning 842, Line 14, Col 5, Line 14, Col 15, "This attribute is not valid for use on this language element") ] + + // SOURCE=E_AttributeTargetIsField03.fs # E_AttributeTargetIsField03.fs + [] + let ``E_AttributeTargetIsField03_fs opt-in warning`` compilation = + compilation + |> withLangVersion90 + |> withWarnOn 3878 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Warning 842, Line 14, Col 5, Line 14, Col 15, "This attribute is not valid for use on this language element") + ] // SOURCE=E_AttributeTargetIsField03.fs # E_AttributeTargetIsField03.fs [] @@ -493,7 +515,20 @@ module CustomAttributes_AttributeUsage = |> shouldFail |> withDiagnostics [ (Warning 842, Line 14, Col 5, Line 14, Col 15, "This attribute is not valid for use on this language element") - (Warning 842, Line 15, Col 5, Line 15, Col 25, "This attribute is not valid for use on this language element") + ] + + // SOURCE=E_AttributeTargetIsField03.fs # E_AttributeTargetIsField03.fs + [] + let ``Preview: E_AttributeTargetIsField03_fs opt-in warning`` compilation = + compilation + |> withLangVersionPreview + |> withWarnOn 3878 + |> verifyCompile + |> shouldFail + |> withDiagnostics [ + (Warning 842, Line 14, Col 5, Line 14, Col 15, "This attribute is not valid for use on this language element"); + (Warning 3878, Line 14, Col 18, Line 14, Col 23, "This attribute is not valid for use on union cases with fields."); + (Warning 3878, Line 15, Col 28, Line 15, Col 33, "This attribute is not valid for use on union cases with fields.") ] // SOURCE=E_AttributeTargetIsProperty01.fs # E_AttributeTargetIsField03.fs @@ -510,11 +545,7 @@ module CustomAttributes_AttributeUsage = compilation |> withLangVersionPreview |> verifyCompile - |> shouldFail - |> withDiagnostics [ - (Warning 842, Line 14, Col 5, Line 14, Col 18, "This attribute is not valid for use on this language element") - (Warning 842, Line 15, Col 5, Line 15, Col 25, "This attribute is not valid for use on this language element") - ] + |> shouldSucceed // SOURCE=E_AttributeTargetIsCtor01.fs # E_AttributeTargetIsCtor01.fs []