Skip to content

Commit

Permalink
Show warning when DU is access without type but RequiredQualifiedAcce…
Browse files Browse the repository at this point in the history
…ss was set - closes dotnet#95
  • Loading branch information
forki committed Jan 25, 2015
1 parent 11ede75 commit 1ae292c
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 15 deletions.
9 changes: 6 additions & 3 deletions src/fsharp/infos.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1526,13 +1526,16 @@ type RecdFieldInfo =
/// Describes an F# use of a union case
[<NoComparison; NoEquality>]
type UnionCaseInfo =
| UnionCaseInfo of TypeInst * Tast.UnionCaseRef
| UnionCaseInfo of TypeInst * Tast.UnionCaseRef * bool

/// Get the generic instantiation of the declaring type of the union case
member x.TypeInst = let (UnionCaseInfo(tinst,_)) = x in tinst
member x.TypeInst = let (UnionCaseInfo(tinst,_,_)) = x in tinst

/// Determines if the union case usage is deprecated
member x.ShowDeprecated = let (UnionCaseInfo(_,_,showDeprecated)) = x in showDeprecated

/// Get a reference to the F# metadata for the uninstantiated union case
member x.UnionCaseRef = let (UnionCaseInfo(_,ucref)) = x in ucref
member x.UnionCaseRef = let (UnionCaseInfo(_,ucref,_)) = x in ucref

/// Get the F# metadata for the uninstantiated union case
member x.UnionCase = x.UnionCaseRef.UnionCase
Expand Down
18 changes: 10 additions & 8 deletions src/fsharp/nameres.fs
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ let AddActivePatternResultTagsToNameEnv (apinfo: PrettyNaming.ActivePatternInfo)

/// Generalize a union case, from Cons --> List<T>.Cons
let GeneralizeUnionCaseRef (ucref:UnionCaseRef) =
UnionCaseInfo (fst (generalizeTyconRef ucref.TyconRef), ucref)
UnionCaseInfo (fst (generalizeTyconRef ucref.TyconRef), ucref, false)


/// Add type definitions to the sub-table of the environment indexed by name and arity
Expand Down Expand Up @@ -747,14 +747,14 @@ let FreshenTycon (ncenv: NameResolver) m (tcref:TyconRef) =

/// Convert a reference to a union case into a UnionCaseInfo that includes
/// a fresh set of inference type variables for the type parameters of the union type.
let FreshenUnionCaseRef (ncenv: NameResolver) m (ucref:UnionCaseRef) =
let FreshenUnionCaseRef showDeprecated (ncenv: NameResolver) m (ucref:UnionCaseRef) =
let tinst = ncenv.InstantiationGenerator m (ucref.TyconRef.Typars m)
UnionCaseInfo(tinst,ucref)
UnionCaseInfo(tinst,ucref,showDeprecated)

/// This must be called after fetching unqualified items that may need to be freshened
let FreshenUnqualifiedItem (ncenv: NameResolver) m res =
match res with
| Item.UnionCase (UnionCaseInfo(_,ucref)) -> Item.UnionCase (FreshenUnionCaseRef ncenv m ucref)
| Item.UnionCase (UnionCaseInfo(_,ucref,_)) -> Item.UnionCase (FreshenUnionCaseRef false ncenv m ucref)
| _ -> res


Expand Down Expand Up @@ -1496,7 +1496,7 @@ let TryFindUnionCaseOfType g typ nm =
let tcref,tinst = destAppTy g typ
match tcref.GetUnionCaseByName nm with
| None -> None
| Some ucase -> Some(UnionCaseInfo(tinst,mkNestedUnionCaseRef tcref ucase))
| Some ucase -> Some(UnionCaseInfo(tinst,mkNestedUnionCaseRef tcref ucase,false))
else
None

Expand Down Expand Up @@ -1652,7 +1652,8 @@ let rec ResolveExprLongIdentInModuleOrNamespace (ncenv:NameResolver) nenv (typeN
match TryFindTypeWithUnionCase modref id with
| Some tycon when IsTyconReprAccessible ncenv.amap m ad (modref.MkNestedTyconRef tycon) ->
let ucref = mkUnionCaseRef (modref.MkNestedTyconRef tycon) id.idText
let ucinfo = FreshenUnionCaseRef ncenv m ucref
let showDeprecated = HasFSharpAttribute ncenv.g ncenv.g.attrib_RequireQualifiedAccessAttribute tycon.Attribs
let ucinfo = FreshenUnionCaseRef showDeprecated ncenv m ucref
success (resInfo,Item.UnionCase ucinfo,rest)
| _ ->
match mty.ExceptionDefinitionsByDemangledName.TryFind(id.idText) with
Expand Down Expand Up @@ -1854,7 +1855,8 @@ let rec ResolvePatternLongIdentInModuleOrNamespace (ncenv:NameResolver) nenv num
| Some tycon when IsTyconReprAccessible ncenv.amap m ad (modref.MkNestedTyconRef tycon) ->
let tcref = modref.MkNestedTyconRef tycon
let ucref = mkUnionCaseRef tcref id.idText
let ucinfo = FreshenUnionCaseRef ncenv m ucref
let showDeprecated = HasFSharpAttribute ncenv.g ncenv.g.attrib_RequireQualifiedAccessAttribute tycon.Attribs
let ucinfo = FreshenUnionCaseRef showDeprecated ncenv m ucref
success (resInfo,Item.UnionCase ucinfo,rest)
| _ ->
match mty.ExceptionDefinitionsByDemangledName.TryFind(id.idText) with
Expand Down Expand Up @@ -2466,7 +2468,7 @@ let ResolveCompletionsInType (ncenv: NameResolver) nenv isApplicableMeth m ad st
let tc,tinst = destAppTy g typ
tc.UnionCasesAsRefList
|> List.filter (IsUnionCaseUnseen ad g ncenv.amap m >> not)
|> List.map (fun ucref -> Item.UnionCase(UnionCaseInfo(tinst,ucref)))
|> List.map (fun ucref -> Item.UnionCase(UnionCaseInfo(tinst,ucref,false)))
else []

let einfos =
Expand Down
8 changes: 6 additions & 2 deletions src/fsharp/tc.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1877,6 +1877,10 @@ let rec ApplyUnionCaseOrExn (makerForUnionCase,makerForExnTag) m cenv env overal
mkf,recdFieldTysOfExnDefRef ecref, [ for f in (recdFieldsOfExnDefRef ecref) -> f.Name ]

| Item.UnionCase ucinfo ->
if ucinfo.ShowDeprecated then
let message = sprintf "The union type for union case '%s' was definded with the RequireQualifiedAccessAttribute. Include the name of the union type ('%s') in the name you are using.'" ucinfo.Name ucinfo.Tycon.DisplayName
warning(Deprecated(message,m))

let ucref = ucinfo.UnionCaseRef
CheckUnionCaseAttributes cenv.g ucref m |> CommitOperationResult
CheckUnionCaseAccessible cenv.amap m ad ucref |> ignore
Expand Down Expand Up @@ -7870,7 +7874,7 @@ and TcItemThen cenv overallTy env tpenv (item,mItem,rest,afterOverloadResolution
| _ ->
let ucref = mkChoiceCaseRef cenv.g mItem aparity n
let _,_,tinst,_ = infoOfTyconRef mItem ucref.TyconRef
let ucinfo = UnionCaseInfo(tinst,ucref)
let ucinfo = UnionCaseInfo(tinst,ucref,false)
ApplyUnionCaseOrExnTypes mItem cenv env ucaseAppTy (Item.UnionCase ucinfo)
| _ ->
ApplyUnionCaseOrExnTypes mItem cenv env ucaseAppTy item
Expand Down Expand Up @@ -14020,7 +14024,7 @@ module EstablishTypeDefinitionCores = begin
let nenv = envinner.NameEnv
// Constructors should be visible from IntelliSense, so add fake names for them
for unionCase in unionCases do
let info = UnionCaseInfo(thisTyInst,mkUnionCaseRef thisTyconRef unionCase.Id.idText)
let info = UnionCaseInfo(thisTyInst,mkUnionCaseRef thisTyconRef unionCase.Id.idText,false)
let nenv' = AddFakeNameToNameEnv unionCase.Id.idText nenv (Item.UnionCase info)
// Report to both - as in previous function
let item = Item.UnionCase info
Expand Down
4 changes: 2 additions & 2 deletions src/fsharp/vs/ServiceDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ module internal ItemDescriptionsImpl =
| Wrap(Item.Value vref1 | Item.CustomBuilder (_,vref1)), Wrap(Item.Value vref2 | Item.CustomBuilder (_,vref2)) -> valRefEq g vref1 vref2
| Wrap(Item.ActivePatternCase(APElemRef(_apinfo1, vref1, idx1))), Wrap(Item.ActivePatternCase(APElemRef(_apinfo2, vref2, idx2))) ->
idx1 = idx2 && valRefEq g vref1 vref2
| Wrap(Item.UnionCase(UnionCaseInfo(_, ur1))), Wrap(Item.UnionCase(UnionCaseInfo(_, ur2))) -> g.unionCaseRefEq ur1 ur2
| Wrap(Item.UnionCase(UnionCaseInfo(_, ur1,_))), Wrap(Item.UnionCase(UnionCaseInfo(_, ur2,false))) -> g.unionCaseRefEq ur1 ur2
| Wrap(Item.RecdField(RecdFieldInfo(_, RFRef(tcref1, n1)))), Wrap(Item.RecdField(RecdFieldInfo(_, RFRef(tcref2, n2)))) ->
(tyconRefEq g tcref1 tcref2) && (n1 = n2) // there is no direct function as in the previous case
| Wrap(Item.Property(_, pi1s)), Wrap(Item.Property(_, pi2s)) ->
Expand Down Expand Up @@ -542,7 +542,7 @@ module internal ItemDescriptionsImpl =
| Wrap(Item.Value vref | Item.CustomBuilder (_,vref)) -> hash vref.LogicalName
| Wrap(Item.ActivePatternCase(APElemRef(_apinfo, vref, idx))) -> hash (vref.LogicalName, idx)
| Wrap(Item.ExnCase(tcref)) -> hash tcref.Stamp
| Wrap(Item.UnionCase(UnionCaseInfo(_, UCRef(tcref, n)))) -> hash(tcref.Stamp, n)
| Wrap(Item.UnionCase(UnionCaseInfo(_, UCRef(tcref, n),false))) -> hash(tcref.Stamp, n)
| Wrap(Item.RecdField(RecdFieldInfo(_, RFRef(tcref, n)))) -> hash(tcref.Stamp, n)
| Wrap(Item.Event evt) -> evt.ComputeHashCode()
| Wrap(Item.Property(_name, pis)) -> hash (pis |> List.map (fun pi -> pi.ComputeHashCode()))
Expand Down

0 comments on commit 1ae292c

Please sign in to comment.