Skip to content
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
66 changes: 36 additions & 30 deletions src/Compiler/Checking/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7011,31 +7011,34 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI

TcRecordConstruction cenv objTy true env tpenv None objTy fldsList mWholeExpr
else
let item = ForceRaise (ResolveObjectConstructor cenv.nameResolver env.DisplayEnv mObjTy ad objTy)
let ctorCall, baseIdOpt, tpenv =
if isInterfaceTy g objTy then
match argopt with
| None ->
BuildObjCtorCall g mWholeExpr, None, tpenv
| Some _ ->
error(Error(FSComp.SR.tcConstructorForInterfacesDoNotTakeArguments(), mNewExpr))
else
let item = ForceRaise (ResolveObjectConstructor cenv.nameResolver env.DisplayEnv mObjTy ad objTy)

if isFSharpObjModelTy g objTy && GetCtorShapeCounter env = 1 then
error(Error(FSComp.SR.tcObjectsMustBeInitializedWithObjectExpression(), mNewExpr))
if isFSharpObjModelTy g objTy && GetCtorShapeCounter env = 1 then
error(Error(FSComp.SR.tcObjectsMustBeInitializedWithObjectExpression(), mNewExpr))

let ctorCall, baseIdOpt, tpenv =
match item, argopt with
| Item.CtorGroup(methodName, minfos), Some (arg, baseIdOpt) ->
let meths = minfos |> List.map (fun minfo -> minfo, None)
let afterResolution = ForNewConstructors cenv.tcSink env mObjTy methodName minfos
let ad = env.AccessRights

let expr, tpenv = TcMethodApplicationThen cenv env (MustEqual objTy) None tpenv None [] mWholeExpr mObjTy methodName ad PossiblyMutates false meths afterResolution CtorValUsedAsSuperInit [arg] ExprAtomicFlag.Atomic None []
// The 'base' value is always bound
let baseIdOpt = (match baseIdOpt with None -> Some(ident("base", mObjTy)) | Some id -> Some id)
expr, baseIdOpt, tpenv
| Item.FakeInterfaceCtor intfTy, None ->
UnifyTypes cenv env mWholeExpr objTy intfTy
let expr = BuildObjCtorCall g mWholeExpr
expr, None, tpenv
| Item.FakeInterfaceCtor _, Some _ ->
error(Error(FSComp.SR.tcConstructorForInterfacesDoNotTakeArguments(), mNewExpr))
| Item.CtorGroup _, None ->
error(Error(FSComp.SR.tcConstructorRequiresArguments(), mNewExpr))
| _ -> error(Error(FSComp.SR.tcNewRequiresObjectConstructor(), mNewExpr))
match item, argopt with
| Item.CtorGroup(methodName, minfos), Some (arg, baseIdOpt) ->
let meths = minfos |> List.map (fun minfo -> minfo, None)
let afterResolution = ForNewConstructors cenv.tcSink env mObjTy methodName minfos
let ad = env.AccessRights

let expr, tpenv = TcMethodApplicationThen cenv env (MustEqual objTy) None tpenv None [] mWholeExpr mObjTy methodName ad PossiblyMutates false meths afterResolution CtorValUsedAsSuperInit [arg] ExprAtomicFlag.Atomic None []
// The 'base' value is always bound
let baseIdOpt = (match baseIdOpt with None -> Some(ident("base", mObjTy)) | Some id -> Some id)
expr, baseIdOpt, tpenv

| Item.CtorGroup _, None ->
error(Error(FSComp.SR.tcConstructorRequiresArguments(), mNewExpr))

| _ -> error(Error(FSComp.SR.tcNewRequiresObjectConstructor(), mNewExpr))

let baseValOpt = MakeAndPublishBaseVal cenv env baseIdOpt objTy
let env = Option.foldBack (AddLocalVal g cenv.tcSink mNewExpr) baseValOpt env
Expand Down Expand Up @@ -8141,8 +8144,11 @@ and TcNameOfExpr (cenv: cenv) env tpenv (synArg: SynExpr) =
when
(match item with
| Item.DelegateCtor _
| Item.CtorGroup _
| Item.FakeInterfaceCtor _ -> false
| Item.CtorGroup _ -> false
| Item.Types _ when delayed.IsEmpty ->
match delayed with
| [] | [DelayedTypeApp _] -> false
| _ -> true
| _ -> true) ->
let overallTy = match overallTyOpt with None -> MustEqual (NewInferenceType g) | Some t -> t
let _, _ = TcItemThen cenv overallTy env tpenv res None delayed
Expand Down Expand Up @@ -8374,9 +8380,6 @@ and TcItemThen (cenv: cenv) (overallTy: OverallTy) env tpenv (tinstEnclosing, it
| Item.CtorGroup(nm, minfos) ->
TcCtorItemThen cenv overallTy env item nm minfos tinstEnclosing tpenv mItem afterResolution delayed

| Item.FakeInterfaceCtor _ ->
error(Error(FSComp.SR.tcInvalidUseOfInterfaceType(), mItem))

| Item.ImplicitOp(id, sln) ->
TcImplicitOpItemThen cenv overallTy env id sln tpenv mItem delayed

Expand Down Expand Up @@ -8614,7 +8617,10 @@ and TcTypeItemThen (cenv: cenv) overallTy env nm ty tpenv mItem tinstEnclosing d
// In this case the type is not generic, and indeed we should never have returned Item.Types.
// That's because ResolveTypeNamesToCtors should have been set at the original
// call to ResolveLongIdentAsExprAndComputeRange
error(Error(FSComp.SR.tcInvalidUseOfTypeName(), mItem))
if isInterfaceTy g ty then
error(Error(FSComp.SR.tcInvalidUseOfInterfaceType(), mItem))
else
error(Error(FSComp.SR.tcInvalidUseOfTypeName(), mItem))

and TcMethodItemThen (cenv: cenv) overallTy env item methodName minfos tpenv mItem afterResolution staticTyOpt delayed =
let ad = env.eAccessRights
Expand Down Expand Up @@ -9305,7 +9311,7 @@ and TcLookupItemThen cenv overallTy env tpenv mObjExpr objExpr objExprTy delayed
| Item.Trait traitInfo ->
TcTraitItemThen cenv overallTy env (Some objExpr) traitInfo tpenv mItem delayed

| Item.FakeInterfaceCtor _ | Item.DelegateCtor _ -> error (Error (FSComp.SR.tcConstructorsCannotBeFirstClassValues(), mItem))
| Item.DelegateCtor _ -> error (Error (FSComp.SR.tcConstructorsCannotBeFirstClassValues(), mItem))

// These items are not expected here - they can't be the result of a instance member dot-lookup "expr.Ident"
| Item.ActivePatternResult _
Expand Down
97 changes: 59 additions & 38 deletions src/Compiler/Checking/NameResolution.fs
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,6 @@ type Item =
/// Represents the resolution of a name to a constructor
| CtorGroup of string * MethInfo list

/// Represents the resolution of a name to the fake constructor simulated for an interface type.
| FakeInterfaceCtor of TType

/// Represents the resolution of a name to a delegate
| DelegateCtor of TType

Expand Down Expand Up @@ -276,8 +273,7 @@ type Item =
| ValueSome tcref -> tcref.DisplayNameCore
| _ -> nm
|> DemangleGenericTypeName
| Item.CtorGroup(nm, _) -> nm |> DemangleGenericTypeName
| Item.FakeInterfaceCtor ty
| Item.CtorGroup(nm, _) -> nm |> DemangleGenericTypeName
| Item.DelegateCtor ty ->
match ty with
| AbbrevOrAppTy tcref -> tcref.DisplayNameCore
Expand Down Expand Up @@ -1713,6 +1709,8 @@ type ItemOccurence =
| RelatedText
/// This is a usage of a module or namespace name in open statement
| Open
/// Not permitted item uses like interface names used as expressions
| InvalidUse

type FormatStringCheckContext =
{ SourceText: ISourceText
Expand Down Expand Up @@ -1786,8 +1784,7 @@ let (|EntityUse|_|) (item: Item) =
| Item.UnqualifiedType (tcref :: _) -> Some tcref
| Item.ExnCase tcref -> Some tcref
| Item.Types(_, [AbbrevOrAppTy tcref])
| Item.DelegateCtor(AbbrevOrAppTy tcref)
| Item.FakeInterfaceCtor(AbbrevOrAppTy tcref) -> Some tcref
| Item.DelegateCtor(AbbrevOrAppTy tcref) -> Some tcref
| Item.CtorGroup(_, ctor :: _) ->
match ctor.ApparentEnclosingType with
| AbbrevOrAppTy tcref -> Some tcref
Expand Down Expand Up @@ -2229,7 +2226,6 @@ let CheckAllTyparsInferrable amap m item =

| Item.Trait _
| Item.CtorGroup _
| Item.FakeInterfaceCtor _
| Item.DelegateCtor _
| Item.Types _
| Item.ModuleOrNamespaces _
Expand Down Expand Up @@ -2470,7 +2466,8 @@ let private ResolveObjectConstructorPrim (ncenv: NameResolver) edenv resInfo m a
else
let ctorInfos = GetIntrinsicConstructorInfosOfType ncenv.InfoReader m ty
if isNil ctorInfos && isInterfaceTy g ty then
success (resInfo, Item.FakeInterfaceCtor ty)
let tcref = tcrefOfAppTy g ty
success (resInfo, Item.Types(tcref.DisplayName, [ty]))
else
let defaultStructCtorInfo =
if (not (ctorInfos |> List.exists (fun x -> x.IsNullary)) &&
Expand Down Expand Up @@ -3070,33 +3067,49 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified
match AtMostOneResult m innerSearch with
| Result _ as res -> res
| _ ->
let failingCase =
match typeError with
| Some e -> raze e
| _ ->
let suggestNamesAndTypes (addToBuffer: string -> unit) =
for e in nenv.eUnqualifiedItems do
if canSuggestThisItem e.Value then
addToBuffer e.Value.DisplayName

for e in nenv.TyconsByDemangledNameAndArity fullyQualified do
if IsEntityAccessible ncenv.amap m ad e.Value then
addToBuffer e.Value.DisplayName

for kv in nenv.ModulesAndNamespaces fullyQualified do
for modref in kv.Value do
if IsEntityAccessible ncenv.amap m ad modref then
addToBuffer modref.DisplayName

// check if the user forgot to use qualified access
for e in nenv.eTyconsByDemangledNameAndArity do
let hasRequireQualifiedAccessAttribute = HasFSharpAttribute ncenv.g ncenv.g.attrib_RequireQualifiedAccessAttribute e.Value.Attribs
if hasRequireQualifiedAccessAttribute then
if e.Value.IsUnionTycon && e.Value.UnionCasesArray |> Array.exists (fun c -> c.LogicalName = id.idText) then
addToBuffer (e.Value.DisplayName + "." + id.idText)

raze (UndefinedName(0, FSComp.SR.undefinedNameValueOfConstructor, id, suggestNamesAndTypes))
failingCase

match typeError with
| Some e -> raze e
| _ ->

let tyconSearch () =
let tcrefs = LookupTypeNameInEnvNoArity fullyQualified id.idText nenv
if isNil tcrefs then NoResultsOrUsefulErrors else

let tcrefs = ResolveUnqualifiedTyconRefs nenv tcrefs
let typeNameResInfo = TypeNameResolutionInfo.ResolveToTypeRefs typeNameResInfo.StaticArgsInfo
CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities (tcrefs, typeNameResInfo, PermitDirectReferenceToGeneratedType.No, unionRanges m id.idRange)
|> CollectResults success

match tyconSearch () with
| Result ((resInfo, tcref) :: _) ->
let item = Item.Types(id.idText, [ generalizedTyconRef ncenv.g tcref ])
success (resInfo, item)
| _ ->

let suggestNamesAndTypes (addToBuffer: string -> unit) =
for e in nenv.eUnqualifiedItems do
if canSuggestThisItem e.Value then
addToBuffer e.Value.DisplayName

for e in nenv.TyconsByDemangledNameAndArity fullyQualified do
if IsEntityAccessible ncenv.amap m ad e.Value then
addToBuffer e.Value.DisplayName

for kv in nenv.ModulesAndNamespaces fullyQualified do
for modref in kv.Value do
if IsEntityAccessible ncenv.amap m ad modref then
addToBuffer modref.DisplayName

// check if the user forgot to use qualified access
for e in nenv.eTyconsByDemangledNameAndArity do
let hasRequireQualifiedAccessAttribute = HasFSharpAttribute ncenv.g ncenv.g.attrib_RequireQualifiedAccessAttribute e.Value.Attribs
if hasRequireQualifiedAccessAttribute then
if e.Value.IsUnionTycon && e.Value.UnionCasesArray |> Array.exists (fun c -> c.LogicalName = id.idText) then
addToBuffer (e.Value.DisplayName + "." + id.idText)

raze (UndefinedName(0, FSComp.SR.undefinedNameValueOfConstructor, id, suggestNamesAndTypes))

match res with
| Exception e -> raze e
| Result (resInfo, item) ->
Expand Down Expand Up @@ -3997,6 +4010,11 @@ let NeedsWorkAfterResolution namedItem =
| Item.ActivePatternCase apref -> not (List.isEmpty apref.ActivePatternVal.Typars)
| _ -> false

let isWrongItemInExpr item =
match item with
| Item.Types _ -> true
| _ -> false

/// Specifies additional work to do after an item has been processed further in type checking.
[<RequireQualifiedAccess>]
type AfterResolution =
Expand Down Expand Up @@ -4059,6 +4077,11 @@ let ResolveLongIdentAsExprAndComputeRange (sink: TcResultsSink) (ncenv: NameReso
| Some _ ->
if NeedsWorkAfterResolution item then
AfterResolution.RecordResolution(None, (fun tpinst -> callSink(item, tpinst)), callSinkWithSpecificOverload, (fun () -> callSink (item, emptyTyparInst)))

elif isWrongItemInExpr item then
CallNameResolutionSink sink (itemRange, nenv, item, emptyTyparInst, ItemOccurence.InvalidUse, ad)
AfterResolution.DoNothing

else
callSink (item, emptyTyparInst)
AfterResolution.DoNothing
Expand Down Expand Up @@ -4500,7 +4523,6 @@ let InfosForTyconConstructors (ncenv: NameResolver) m ad (tcref: TyconRef) =
match ResolveObjectConstructor ncenv (DisplayEnv.Empty g) m ad ty with
| Result item ->
match item with
| Item.FakeInterfaceCtor _ -> None
| Item.CtorGroup(nm, ctorInfos) ->
let ctors =
ctorInfos
Expand Down Expand Up @@ -5301,7 +5323,6 @@ let rec GetCompletionForItem (ncenv: NameResolver) (nenv: NameResolutionEnv) m a
| _ -> ()

| Item.DelegateCtor _
| Item.FakeInterfaceCtor _
| Item.CtorGroup _
| Item.UnqualifiedType _ ->
for tcref in nenv.TyconsByDemangledNameAndArity(OpenQualified).Values do
Expand Down
4 changes: 1 addition & 3 deletions src/Compiler/Checking/NameResolution.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,6 @@ type Item =
/// Represents the resolution of a name to a constructor
| CtorGroup of string * MethInfo list

/// Represents the resolution of a name to the fake constructor simulated for an interface type.
| FakeInterfaceCtor of TType

/// Represents the resolution of a name to a delegate
| DelegateCtor of TType

Expand Down Expand Up @@ -385,6 +382,7 @@ type internal ItemOccurence =
| Implemented
| RelatedText
| Open
| InvalidUse

/// Check for equality, up to signature matching
val ItemsAreEffectivelyEqual: TcGlobals -> Item -> Item -> bool
Expand Down
5 changes: 2 additions & 3 deletions src/Compiler/Service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@ type internal TypeCheckInfo
//
// If we're looking for members using a residue, we'd expect only
// a single item (pick the first one) and we need the residue (which may be "")
| CNR(_, ItemOccurence.InvalidUse, _, _, _, _) :: _, _ -> NameResResult.Empty

| CNR(Item.Types(_, ty :: _), _, denv, nenv, ad, m) :: _, Some _ ->
let targets =
ResolveCompletionTargets.All(ConstraintSolver.IsApplicableMethApprox g amap m)
Expand Down Expand Up @@ -891,7 +893,6 @@ type internal TypeCheckInfo
let CompletionItem (ty: TyconRef voption) (assemblySymbol: AssemblySymbol voption) (item: ItemWithInst) =
let kind =
match item.Item with
| Item.FakeInterfaceCtor _
| Item.DelegateCtor _
| Item.CtorGroup _ -> CompletionItemKind.Method false
| Item.MethodGroup(_, minfos, _) ->
Expand Down Expand Up @@ -1802,7 +1803,6 @@ type internal TypeCheckInfo
match d.Item with
| Item.Types(_, AbbrevOrAppTy tcref :: _) -> 1 + tcref.TyparsNoRange.Length
// Put delegate ctors after types, sorted by #typars. RemoveDuplicateItems will remove FakeInterfaceCtor and DelegateCtor if an earlier type is also reported with this name
| Item.FakeInterfaceCtor(AbbrevOrAppTy tcref)
| Item.DelegateCtor(AbbrevOrAppTy tcref) -> 1000 + tcref.TyparsNoRange.Length
// Put type ctors after types, sorted by #typars. RemoveDuplicateItems will remove DefaultStructCtors if a type is also reported with this name
| Item.CtorGroup(_, cinfo :: _) -> 1000 + 10 * cinfo.DeclaringTyconRef.TyparsNoRange.Length
Expand All @@ -1822,7 +1822,6 @@ type internal TypeCheckInfo
| Item.Types(_, AbbrevOrAppTy tcref :: _)
| Item.ExnCase tcref -> tcref.LogicalName
| Item.UnqualifiedType(tcref :: _)
| Item.FakeInterfaceCtor(AbbrevOrAppTy tcref)
| Item.DelegateCtor(AbbrevOrAppTy tcref) -> tcref.CompiledName
| Item.CtorGroup(_, cinfo :: _) -> cinfo.ApparentEnclosingTyconRef.CompiledName
| _ -> d.Item.DisplayName)
Expand Down
1 change: 0 additions & 1 deletion src/Compiler/Service/ItemKey.fs
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,6 @@ and [<Sealed>] ItemKeyStoreBuilder(tcGlobals: TcGlobals) =

// We should consider writing ItemKey for each of these
| Item.OtherName _ -> ()
| Item.FakeInterfaceCtor _ -> ()
| Item.CustomOperation _ -> ()
| Item.CustomBuilder _ -> ()
| Item.ImplicitOp _ -> ()
Expand Down
2 changes: 0 additions & 2 deletions src/Compiler/Service/SemanticClassification.fs
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,6 @@ module TcResolutionsExtensions =

| Item.DelegateCtor _, _, m -> add m SemanticClassificationType.ConstructorForReferenceType

| Item.FakeInterfaceCtor _, _, m -> add m SemanticClassificationType.ConstructorForReferenceType

| Item.MethodGroup(_, minfos, _), _, m ->
match minfos with
| [] -> add m SemanticClassificationType.Method
Expand Down
Loading