Skip to content

Commit

Permalink
Allow lower-case DU cases when RequireQualifiedAccess is specified (#…
Browse files Browse the repository at this point in the history
…13432)

* Allow lower-case DU cases when RequireQualifiedAccess is specified

* Fix PR suggestions and Add more testing

* Protect feature under preview version

* Add a NotUpperCaseConstructorWithoutRQA warning to be raised in lang version preview

* Fix formatting
  • Loading branch information
edgarfgp committed Jul 11, 2022
1 parent 9df7080 commit b8aaf2d
Show file tree
Hide file tree
Showing 36 changed files with 289 additions and 10 deletions.
30 changes: 20 additions & 10 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@ let ImplicitlyOpenOwnNamespace tcSink g amap scopem enclosingNamespacePath (env:

exception NotUpperCaseConstructor of range: range

exception NotUpperCaseConstructorWithoutRQA of range: range

let CheckNamespaceModuleOrTypeName (g: TcGlobals) (id: Ident) =
// type names '[]' etc. are used in fslib
if not g.compilingFSharpCore && id.idText.IndexOfAny IllegalCharactersInTypeAndNamespaceNames <> -1 then
Expand Down Expand Up @@ -453,16 +455,21 @@ module TcRecdUnionAndEnumDeclarations =
// Bind other elements of type definitions (constructors etc.)
//-------------------------------------------------------------------------

let CheckUnionCaseName (cenv: cenv) (id: Ident) =
let CheckUnionCaseName (cenv: cenv) (id: Ident) hasRQAAttribute =
let g = cenv.g
let name = id.idText
if name = "Tags" then
errorR(Error(FSComp.SR.tcUnionCaseNameConflictsWithGeneratedType(name, "Tags"), id.idRange))

CheckNamespaceModuleOrTypeName g id

if not (String.isLeadingIdentifierCharacterUpperCase name) && name <> opNameCons && name <> opNameNil then
errorR(NotUpperCaseConstructor(id.idRange))
if g.langVersion.SupportsFeature(LanguageFeature.LowercaseDUWhenRequireQualifiedAccess) then

if not (String.isLeadingIdentifierCharacterUpperCase name) && not hasRQAAttribute && name <> opNameCons && name <> opNameNil then
errorR(NotUpperCaseConstructorWithoutRQA(id.idRange))
else
if not (String.isLeadingIdentifierCharacterUpperCase name) && name <> opNameCons && name <> opNameNil then
errorR(NotUpperCaseConstructor(id.idRange))

let ValidateFieldNames (synFields: SynField list, tastFields: RecdField list) =
let seen = Dictionary()
Expand All @@ -479,13 +486,13 @@ module TcRecdUnionAndEnumDeclarations =
| _ ->
seen.Add(f.LogicalName, sf))

let TcUnionCaseDecl (cenv: cenv) env parent thisTy thisTyInst tpenv (SynUnionCase(Attributes synAttrs, SynIdent(id, _), args, xmldoc, vis, m, _)) =
let TcUnionCaseDecl (cenv: cenv) env parent thisTy thisTyInst tpenv hasRQAAttribute (SynUnionCase(Attributes synAttrs, SynIdent(id, _), args, xmldoc, vis, m, _)) =
let g = cenv.g
let attrs = TcAttributes cenv env AttributeTargets.UnionCaseDecl synAttrs // the attributes of a union case decl get attached to the generated "static factory" method
let vis, _ = ComputeAccessAndCompPath env None m vis None parent
let vis = CombineReprAccess parent vis

CheckUnionCaseName cenv id
CheckUnionCaseName cenv id hasRQAAttribute

let rfields, recordTy =
match args with
Expand Down Expand Up @@ -526,8 +533,8 @@ module TcRecdUnionAndEnumDeclarations =
let xmlDoc = xmldoc.ToXmlDoc(true, Some names)
Construct.NewUnionCase id rfields recordTy attrs xmlDoc vis

let TcUnionCaseDecls cenv env parent (thisTy: TType) thisTyInst tpenv unionCases =
let unionCasesR = unionCases |> List.map (TcUnionCaseDecl cenv env parent thisTy thisTyInst tpenv)
let TcUnionCaseDecls (cenv: cenv) env (parent: ParentRef) (thisTy: TType) (thisTyInst: TypeInst) hasRQAAttribute tpenv unionCases =
let unionCasesR = unionCases |> List.map (TcUnionCaseDecl cenv env parent thisTy thisTyInst tpenv hasRQAAttribute)
unionCasesR |> CheckDuplicates (fun uc -> uc.Id) "union case"

let TcEnumDecl cenv env parent thisTy fieldTy (SynEnumCase(attributes=Attributes synAttrs; ident= SynIdent(id,_); value=v; xmlDoc=xmldoc; range=m)) =
Expand Down Expand Up @@ -3188,7 +3195,9 @@ module EstablishTypeDefinitionCores =

structLayoutAttributeCheck false
noAllowNullLiteralAttributeCheck()
TcRecdUnionAndEnumDeclarations.CheckUnionCaseName cenv unionCaseName

let hasRQAAttribute = HasFSharpAttribute cenv.g cenv.g.attrib_RequireQualifiedAccessAttribute tycon.Attribs
TcRecdUnionAndEnumDeclarations.CheckUnionCaseName cenv unionCaseName hasRQAAttribute
let unionCase = Construct.NewUnionCase unionCaseName [] thisTy [] XmlDoc.Empty tycon.Accessibility
writeFakeUnionCtorsToSink [ unionCase ]
Construct.MakeUnionRepr [ unionCase ], None, NoSafeInitInfo
Expand Down Expand Up @@ -3219,8 +3228,9 @@ module EstablishTypeDefinitionCores =
noAbstractClassAttributeCheck()
noAllowNullLiteralAttributeCheck()
structLayoutAttributeCheck false
let unionCases = TcRecdUnionAndEnumDeclarations.TcUnionCaseDecls cenv envinner innerParent thisTy thisTyInst tpenv unionCases


let hasRQAAttribute = HasFSharpAttribute cenv.g cenv.g.attrib_RequireQualifiedAccessAttribute tycon.Attribs
let unionCases = TcRecdUnionAndEnumDeclarations.TcUnionCaseDecls cenv envinner innerParent thisTy thisTyInst hasRQAAttribute tpenv unionCases
if tycon.IsStructRecordOrUnionTycon && unionCases.Length > 1 then
let fieldNames = [ for uc in unionCases do for ft in uc.FieldTable.TrueInstanceFieldsAsList do yield ft.LogicalName ]
if fieldNames |> List.distinct |> List.length <> fieldNames.Length then
Expand Down
2 changes: 2 additions & 0 deletions src/Compiler/Checking/CheckDeclarations.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,5 @@ val CheckOneSigFile:
Cancellable<TcEnv * ModuleOrNamespaceType * bool>

exception NotUpperCaseConstructor of range: range

exception NotUpperCaseConstructorWithoutRQA of range: range
5 changes: 5 additions & 0 deletions src/Compiler/Driver/CompilerDiagnostics.fs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ let GetRangeOfDiagnostic (diagnostic: PhasedDiagnostic) =
| LetRecCheckedAtRuntime m
| UpperCaseIdentifierInPattern m
| NotUpperCaseConstructor m
| NotUpperCaseConstructorWithoutRQA m
| RecursiveUseCheckedAtRuntime (_, _, m)
| LetRecEvaluatedOutOfOrder (_, _, _, m)
| DiagnosticWithText (_, _, m)
Expand Down Expand Up @@ -270,6 +271,7 @@ let GetDiagnosticNumber (diagnostic: PhasedDiagnostic) =
| UseOfAddressOfOperator _ -> 51
| DefensiveCopyWarning _ -> 52
| NotUpperCaseConstructor _ -> 53
| NotUpperCaseConstructorWithoutRQA _ -> 53
| TypeIsImplicitlyAbstract _ -> 54
// 55 cannot be reused
| DeprecatedThreadStaticBindingWarning _ -> 56
Expand Down Expand Up @@ -435,6 +437,7 @@ let ErrorFromApplyingDefault2E () = Message("ErrorFromApplyingDefault2", "")
let ErrorsFromAddingSubsumptionConstraintE () = Message("ErrorsFromAddingSubsumptionConstraint", "%s%s%s")
let UpperCaseIdentifierInPatternE () = Message("UpperCaseIdentifierInPattern", "")
let NotUpperCaseConstructorE () = Message("NotUpperCaseConstructor", "")
let NotUpperCaseConstructorWithoutRQAE () = Message("NotUpperCaseConstructorWithoutRQA", "")
let FunctionExpectedE () = Message("FunctionExpected", "")
let BakedInMemberConstraintNameE () = Message("BakedInMemberConstraintName", "%s")
let BadEventTransformationE () = Message("BadEventTransformation", "")
Expand Down Expand Up @@ -771,6 +774,8 @@ let OutputPhasedErrorR (os: StringBuilder) (diagnostic: PhasedDiagnostic) (canSu

| NotUpperCaseConstructor _ -> os.AppendString(NotUpperCaseConstructorE().Format)

| NotUpperCaseConstructorWithoutRQA _ -> os.AppendString(NotUpperCaseConstructorWithoutRQAE().Format)

| ErrorFromAddingConstraint (_, e, _) -> OutputExceptionR os e

#if !NO_TYPEPROVIDERS
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,7 @@ featureStructActivePattern,"struct representation for active patterns"
featureRelaxWhitespace2,"whitespace relaxation v2"
featureReallyLongList,"list literals of any size"
featureErrorOnDeprecatedRequireQualifiedAccess,"give error on deprecated access of construct with RequireQualifiedAccess attribute"
featureLowercaseDUWhenRequireQualifiedAccess,"Allow lowercase DU when RequireQualifiedAccess attribute"
3353,fsiInvalidDirective,"Invalid directive '#%s %s'"
3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation."
Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/FSStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1107,4 +1107,7 @@
<data name="TargetInvocationExceptionWrapper" xml:space="preserve">
<value>internal error: {0}</value>
</data>
<data name="NotUpperCaseConstructorWithoutRQA" xml:space="preserve">
<value>Lowercase discriminated union cases are only allowed when using RequireQualifiedAccess attribute</value>
</data>
</root>
3 changes: 3 additions & 0 deletions src/Compiler/Facilities/LanguageFeatures.fs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type LanguageFeature =
| DelegateTypeNameResolutionFix
| ReallyLongLists
| ErrorOnDeprecatedRequireQualifiedAccess
| LowercaseDUWhenRequireQualifiedAccess

/// LanguageVersion management
type LanguageVersion(versionText) =
Expand Down Expand Up @@ -111,6 +112,7 @@ type LanguageVersion(versionText) =
LanguageFeature.BetterExceptionPrinting, previewVersion
LanguageFeature.ReallyLongLists, previewVersion
LanguageFeature.ErrorOnDeprecatedRequireQualifiedAccess, previewVersion
LanguageFeature.LowercaseDUWhenRequireQualifiedAccess, previewVersion
]

static let defaultLanguageVersion = LanguageVersion("default")
Expand Down Expand Up @@ -210,6 +212,7 @@ type LanguageVersion(versionText) =
| LanguageFeature.DelegateTypeNameResolutionFix -> FSComp.SR.featureDelegateTypeNameResolutionFix ()
| LanguageFeature.ReallyLongLists -> FSComp.SR.featureReallyLongList ()
| LanguageFeature.ErrorOnDeprecatedRequireQualifiedAccess -> FSComp.SR.featureErrorOnDeprecatedRequireQualifiedAccess ()
| LanguageFeature.LowercaseDUWhenRequireQualifiedAccess -> FSComp.SR.featureLowercaseDUWhenRequireQualifiedAccess ()

/// Get a version string associated with the given feature.
member _.GetFeatureVersionString feature =
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/Facilities/LanguageFeatures.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type LanguageFeature =
| DelegateTypeNameResolutionFix
| ReallyLongLists
| ErrorOnDeprecatedRequireQualifiedAccess
| LowercaseDUWhenRequireQualifiedAccess

/// LanguageVersion management
type LanguageVersion =
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">rozhraní s vícenásobným obecným vytvářením instancí</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">Revize kompatibility ML</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">Schnittstellen mit mehrfacher generischer Instanziierung</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">ML-Kompatibilitätsrevisionen</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">interfaces con creación de instancias genéricas múltiples</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">Revisiones de compatibilidad de ML</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">interfaces avec plusieurs instanciations génériques</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">Réviseurs de compatibilité ML</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">interfacce con più creazioni di istanze generiche</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">Revisioni della compatibilità di Ml</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">複数のジェネリックのインスタンス化を含むインターフェイス</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">ML 互換性のリビジョン</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">여러 제네릭 인스턴스화가 포함된 인터페이스</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">ML 호환성 개정</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">interfejsy z wieloma ogólnymi wystąpieniami</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">Poprawki dotyczące zgodności Machine Learning</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">interfaces com várias instanciações genéricas</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">Revisões de compatibilidade de ML</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ru.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">интерфейсы с множественным универсальным созданием экземпляра</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">Редакции совместимости ML</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.tr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">birden çok genel örnek oluşturma içeren arabirimler</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">ML uyumluluk düzeltmeleri</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.zh-Hans.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">具有多个泛型实例化的接口</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">ML 兼容性修订</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.zh-Hant.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@
<target state="translated">具有多個泛型具現化的介面</target>
<note />
</trans-unit>
<trans-unit id="featureLowercaseDUWhenRequireQualifiedAccess">
<source>Allow lowercase DU when RequireQualifiedAccess attribute</source>
<target state="new">Allow lowercase DU when RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="featureMLCompatRevisions">
<source>ML compatibility revisions</source>
<target state="translated">ML 相容性修訂</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSStrings.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Nejméně jedna informační zpráva v načteném souboru\n</target>
<note />
</trans-unit>
<trans-unit id="NotUpperCaseConstructorWithoutRQA">
<source>Lowercase discriminated union cases are only allowed when using RequireQualifiedAccess attribute</source>
<target state="new">Lowercase discriminated union cases are only allowed when using RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="Parser.TOKEN.DOT.DOT.HAT">
<source>symbol '..^'</source>
<target state="translated">symbol ..^</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSStrings.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Mindestens eine Informationsmeldung in der geladenen Datei.\n</target>
<note />
</trans-unit>
<trans-unit id="NotUpperCaseConstructorWithoutRQA">
<source>Lowercase discriminated union cases are only allowed when using RequireQualifiedAccess attribute</source>
<target state="new">Lowercase discriminated union cases are only allowed when using RequireQualifiedAccess attribute</target>
<note />
</trans-unit>
<trans-unit id="Parser.TOKEN.DOT.DOT.HAT">
<source>symbol '..^'</source>
<target state="translated">Symbol "..^"</target>
Expand Down
Loading

0 comments on commit b8aaf2d

Please sign in to comment.