Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
edgarfgp committed Jul 29, 2024
1 parent cb28092 commit 860efd1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
21 changes: 8 additions & 13 deletions src/Compiler/Checking/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6857,8 +6857,8 @@ and TcRecordConstruction (cenv: cenv) (overallTy: TType) isObjExpr env tpenv wit
UnifyTypes cenv env m overallTy objTy

// Types with implicit constructors can't use record or object syntax: all constructions must go through the implicit constructor
// let supportsObjectExpressionWithoutOverrides = isObjExpr && g.langVersion.SupportsFeature(LanguageFeature.AllowObjectExpressionWithoutOverrides)
if tycon.MembersOfFSharpTyconByName |> NameMultiMap.existsInRange (fun v -> v.IsIncrClassConstructor) then
let supportsObjectExpressionWithoutOverrides = isObjExpr && g.langVersion.SupportsFeature(LanguageFeature.AllowObjectExpressionWithoutOverrides)
if tycon.MembersOfFSharpTyconByName |> NameMultiMap.existsInRange (fun v -> v.IsIncrClassConstructor) && not supportsObjectExpressionWithoutOverrides then
errorR(Error(FSComp.SR.tcConstructorRequiresCall(tycon.DisplayName), m))

let fspecs = tycon.TrueInstanceFieldsAsList
Expand Down Expand Up @@ -7223,11 +7223,9 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI

if argopt.IsSome then error(Error(FSComp.SR.tcNoArgumentsForRecordValue(), mWholeExpr))
if not (isNil extraImpls) then error(Error(FSComp.SR.tcNoInterfaceImplementationForConstructionExpression(), mNewExpr))
// let supportsObjectExpressionWithoutOverrides = g.langVersion.SupportsFeature(LanguageFeature.AllowObjectExpressionWithoutOverrides)

let supportsObjectExpressionWithoutOverrides = g.langVersion.SupportsFeature(LanguageFeature.AllowObjectExpressionWithoutOverrides)

let requiresConstructor = GetCtorShapeCounter env <> 1
if isFSharpObjModelTy g objTy && requiresConstructor then
if isFSharpObjModelTy g objTy && GetCtorShapeCounter env <> 1 && not supportsObjectExpressionWithoutOverrides then
error(Error(FSComp.SR.tcObjectConstructionCanOnlyBeUsedInClassTypes(), mNewExpr))
let fldsList =
binds |> List.map (fun b ->
Expand Down Expand Up @@ -7283,20 +7281,17 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI
match tryTcrefOfAppTy g objTy with
| ValueNone -> false
| ValueSome tcref -> HasFSharpAttribute g g.attrib_AbstractClassAttribute tcref.Attribs
if overrideSpecs.IsEmpty && not (isInterfaceTy g objTy) then
errorR (Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm (), mWholeExpr))

if overrideSpecs.IsEmpty && not isOverallTyAbstract && not (isInterfaceTy g objTy) then
errorR (Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm (), mObjTy))

if hasStaticMembers then
errorR(Error(FSComp.SR.chkStaticMembersOnObjectExpressions(), mObjTy))

DispatchSlotChecking.CheckOverridesAreAllUsedOnce (env.DisplayEnv, g, cenv.infoReader, true, implTy, dispatchSlotsKeyed, availPriorOverrides, overrideSpecs)

if not hasStaticMembers then
DispatchSlotChecking.CheckDispatchSlotsAreImplemented (env.DisplayEnv, cenv.infoReader, m, env.NameEnv, cenv.tcSink, isAbstractClass, implTy, dispatchSlots, availPriorOverrides, overrideSpecs) |> ignore

if not hasStaticMembers then
DispatchSlotChecking.CheckDispatchSlotsAreImplemented (env.DisplayEnv, cenv.infoReader, m, env.NameEnv, cenv.tcSink, isOverallTyAbstract, true, implTy, dispatchSlots, availPriorOverrides, overrideSpecs) |> ignore
)

// 3. create the specs of overrides
let allTypeImpls =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ let implSomeDU someDu =
type Foo() = class end
let foo = { new Foo() }
let foo = { new Foo() } // Approved suggestion to allow this https://github.com/fsharp/fslang-suggestions/issues/632
let foo1 = new Foo()
Expand All @@ -75,7 +74,26 @@ let foo2 = { new Foo() with member __.ToString() = base.ToString() }
|> typecheck
|> shouldFail
|> withDiagnostics [
(Error 738, Line 5, Col 11, Line 5, Col 24, "Invalid object expression. Objects without overrides or interfaces should use the expression form 'new Type(args)' without braces.")
(Error 759, Line 7, Col 12, Line 7, Col 21, "Instances of this type cannot be created since it has been marked abstract or not all methods have been given implementations. Consider using an object expression '{ new ... with ... }' instead.")
]

[<Fact>]
let ``Object expression can implement an abstract class having no abstract members.`` () =
Fsx """
[<AbstractClass>]
type Foo() = class end
let foo = { new Foo() }
let foo1 = new Foo()
// hacky workaround
let foo2 = { new Foo() with member __.ToString() = base.ToString() }
"""
|> withLangVersionPreview
|> typecheck
|> shouldFail
|> withDiagnostics [
(Error 759, Line 7, Col 12, Line 7, Col 21, "Instances of this type cannot be created since it has been marked abstract or not all methods have been given implementations. Consider using an object expression '{ new ... with ... }' instead.")
]

Expand Down Expand Up @@ -408,4 +426,4 @@ Please restrict it to one of the following:
(Error 358, Line 8, Col 19, Line 8, Col 29, "The override for 'Overloaded: int -> bool' was ambiguous")
(Error 358, Line 8, Col 19, Line 8, Col 29, "The override for 'Overloaded: string -> bool' was ambiguous")
(Error 783, Line 7, Col 11, Line 7, Col 19, "At least one override did not correctly implement its corresponding abstract member")
]
]

0 comments on commit 860efd1

Please sign in to comment.