From cd27e8038bf38f465785153fe628151e4baf7561 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Mon, 26 Jan 2015 22:28:04 +0100 Subject: [PATCH] Show warning when Record is accessed without type but RequiredQualifiedAccess was set - relates to #95 --- src/fsharp/nameres.fs | 16 ++++++++++------ src/fsharp/nameres.fsi | 4 +++- src/fsharp/tc.fs | 10 +++++----- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/fsharp/nameres.fs b/src/fsharp/nameres.fs index 9d0a07674aa..5504df764df 100644 --- a/src/fsharp/nameres.fs +++ b/src/fsharp/nameres.fs @@ -221,6 +221,9 @@ let valRefHash (vref: ValRef) = | None -> 0 | Some v -> LanguagePrimitives.PhysicalHash v +/// Represents a record field resolution and the information if the usage is deprecated. +type FieldResolution = FieldResolution of RecdFieldRef * bool + /// Information about an extension member held in the name resolution environment type ExtensionMember = @@ -2148,7 +2151,7 @@ let rec ResolveFieldInModuleOrNamespace (ncenv:NameResolver) nenv ad (resInfo:Re if showDeprecated then let message = sprintf "The record type for the record case '%s' was defined with the RequireQualifiedAccessAttribute. Include the name of the record type ('%s') in the name you are using.'" (id.ToString()) tycon.DisplayName warning(Deprecated(message,m)) - success(modref.MkNestedRecdFieldRef tycon id, rest) + success(FieldResolution(modref.MkNestedRecdFieldRef tycon id,showDeprecated), rest) | _ -> error // search for type-qualified names, e.g. { Microsoft.FSharp.Core.Ref.contents = 1 } let tyconSearch = @@ -2158,7 +2161,7 @@ let rec ResolveFieldInModuleOrNamespace (ncenv:NameResolver) nenv ad (resInfo:Re let tcrefs = tcrefs |> List.map (fun tcref -> (ResolutionInfo.Empty,tcref)) let tyconSearch = ResolveLongIdentInTyconRefs ncenv nenv LookupKind.RecdField (depth+1) m ad rest typeNameResInfo id.idRange tcrefs // choose only fields - let tyconSearch = tyconSearch |?> List.choose (function (_,Item.RecdField(RecdFieldInfo(_,rfref)),rest) -> Some(rfref,rest) | _ -> None) + let tyconSearch = tyconSearch |?> List.choose (function (_,Item.RecdField(RecdFieldInfo(_,rfref)),rest) -> Some(FieldResolution(rfref,false),rest) | _ -> None) tyconSearch | _ -> NoResultsOrUsefulErrors @@ -2185,15 +2188,16 @@ let ResolveField (ncenv:NameResolver) nenv ad typ (mp,id:Ident) = | [] -> if isAppTy g typ then match ncenv.InfoReader.TryFindRecdOrClassFieldInfoOfType(id.idText,m,typ) with - | Some (RecdFieldInfo(_,rfref)) -> [rfref] + | Some (RecdFieldInfo(_,rfref)) -> [FieldResolution(rfref,false)] | None -> error(Error(FSComp.SR.nrTypeDoesNotContainSuchField((NicePrint.minimalStringOfType nenv.eDisplayEnv typ), id.idText),m)) else let frefs = try Map.find id.idText nenv.eFieldLabels with :? KeyNotFoundException -> error (UndefinedName(0,FSComp.SR.undefinedNameRecordLabel,id,NameMap.domainL nenv.eFieldLabels)) // Eliminate duplicates arising from multiple 'open' - let frefs = frefs |> ListSet.setify (fun fref1 fref2 -> tyconRefEq g fref1.TyconRef fref2.TyconRef) - frefs + frefs + |> ListSet.setify (fun fref1 fref2 -> tyconRefEq g fref1.TyconRef fref2.TyconRef) + |> List.map (fun x -> FieldResolution(x,false)) | _ -> let lid = (mp@[id]) @@ -2205,7 +2209,7 @@ let ResolveField (ncenv:NameResolver) nenv ad typ (mp,id:Ident) = let tcrefs = tcrefs |> List.map (fun tcref -> (ResolutionInfo.Empty,tcref)) let tyconSearch = ResolveLongIdentInTyconRefs ncenv nenv LookupKind.RecdField 1 m ad rest typeNameResInfo tn.idRange tcrefs // choose only fields - let tyconSearch = tyconSearch |?> List.choose (function (_,Item.RecdField(RecdFieldInfo(_,rfref)),rest) -> Some(rfref,rest) | _ -> None) + let tyconSearch = tyconSearch |?> List.choose (function (_,Item.RecdField(RecdFieldInfo(_,rfref)),rest) -> Some(FieldResolution(rfref,false),rest) | _ -> None) tyconSearch | _ -> NoResultsOrUsefulErrors let modulSearch ad = diff --git a/src/fsharp/nameres.fsi b/src/fsharp/nameres.fsi index 1a3e46d33cf..34172815e8f 100644 --- a/src/fsharp/nameres.fsi +++ b/src/fsharp/nameres.fsi @@ -68,6 +68,8 @@ type Item = | UnqualifiedType of TyconRef list member DisplayName : TcGlobals -> string +/// Represents a record field resolution and the information if the usage is deprecated. +type FieldResolution = FieldResolution of RecdFieldRef * bool /// Information about an extension member held in the name resolution environment [] @@ -263,7 +265,7 @@ val internal ResolveTypeLongIdentInTyconRef : TcResultsSink -> NameResol val internal ResolveTypeLongIdent : TcResultsSink -> NameResolver -> ItemOccurence -> FullyQualifiedFlag -> NameResolutionEnv -> AccessorDomain -> Ident list -> TypeNameResolutionStaticArgsInfo -> PermitDirectReferenceToGeneratedType -> ResultOrException /// Resolve a long identifier to a field -val internal ResolveField : NameResolver -> NameResolutionEnv -> AccessorDomain -> TType -> Ident list * Ident -> RecdFieldRef list +val internal ResolveField : NameResolver -> NameResolutionEnv -> AccessorDomain -> TType -> Ident list * Ident -> FieldResolution list /// Resolve a long identifier occurring in an expression position val internal ResolveExprLongIdent : TcResultsSink -> NameResolver -> range -> AccessorDomain -> NameResolutionEnv -> TypeNameResolutionInfo -> Ident list -> Item * Ident list diff --git a/src/fsharp/tc.fs b/src/fsharp/tc.fs index a17b1405587..82f6c36bf00 100644 --- a/src/fsharp/tc.fs +++ b/src/fsharp/tc.fs @@ -1828,7 +1828,7 @@ let BuildFieldMap cenv env isPartial ty flds m = let frefSet = ResolveField cenv.nameResolver env.eNameResEnv ad ty fld fld,frefSet, fldExpr) let relevantTypeSets = - frefSets |> List.map (fun (_,frefSet,_) -> frefSet |> List.choose (fun rfref -> Some rfref.TyconRef)) + frefSets |> List.map (fun (_,frefSet,_) -> frefSet |> List.choose (fun (FieldResolution(rfref,_)) -> Some rfref.TyconRef)) let tcref = match List.fold (ListSet.intersect (tyconRefEq cenv.g)) (List.head relevantTypeSets) (List.tail relevantTypeSets) with @@ -1840,13 +1840,13 @@ let BuildFieldMap cenv env isPartial ty flds m = // We're going to get an error of some kind below. // Just choose one field ref and let the error come later let (_,frefSet1,_) = List.head frefSets - let fref1 = List.head frefSet1 + let (FieldResolution(fref1,_))= List.head frefSet1 fref1.TyconRef let fldsmap,rfldsList = ((Map.empty,[]), frefSets) ||> List.fold (fun (fs,rfldsList) (fld,frefs,fldExpr) -> - match frefs |> List.filter (fun fref2 -> tyconRefEq cenv.g tcref fref2.TyconRef) with - | [fref2] -> + match frefs |> List.filter (fun (FieldResolution(fref2,_)) -> tyconRefEq cenv.g tcref fref2.TyconRef) with + | [FieldResolution(fref2,_)] -> // Record the precise resolution of the field for intellisense let item = FreshenRecdFieldRef cenv.nameResolver m fref2 @@ -1858,7 +1858,7 @@ let BuildFieldMap cenv env isPartial ty flds m = errorR (Error(FSComp.SR.tcFieldAppearsTwiceInRecord(fref2.FieldName),m)) if not (tyconRefEq cenv.g tcref fref2.TyconRef) then let (_,frefSet1,_) = List.head frefSets - let fref1 = List.head frefSet1 + let (FieldResolution(fref1,_)) = List.head frefSet1 errorR (FieldsFromDifferentTypes(env.DisplayEnv,fref1,fref2,m)) (fs,rfldsList) else (Map.add fref2.FieldName fldExpr fs,