Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better ranges for implicit inherit error reporting. #17893

Merged
merged 15 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 10 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
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/9.0.200.md
edgarfgp marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@
* Better ranges for CE `use` error reporting. ([PR #17811](https://github.com/dotnet/fsharp/pull/17811))
* Better ranges for `inherit` error reporting. ([PR #17879](https://github.com/dotnet/fsharp/pull/17879))
* Better ranges for `inherit` `struct` error reporting. ([PR #17886](https://github.com/dotnet/fsharp/pull/17886))
* Better ranges for `inherit` objects error reporting. ([PR #17893](https://github.com/dotnet/fsharp/pull/17893))

### Breaking Changes
26 changes: 14 additions & 12 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ module MutRecBindingChecking =

[Phase2AIncrClassCtor (staticCtorInfo, Some incrCtorInfo)], innerState

| Some (SynMemberDefn.ImplicitInherit (ty, arg, _baseIdOpt, m)), _ ->
| Some (SynMemberDefn.ImplicitInherit (ty, arg, _baseIdOpt, m, _)), _ ->
if tcref.TypeOrMeasureKind = TyparKind.Measure then
error(Error(FSComp.SR.tcMeasureDeclarationsRequireStaticMembers(), m))

Expand Down Expand Up @@ -3324,7 +3324,6 @@ module EstablishTypeDefinitionCores =
else None
| SynTypeDefnSimpleRepr.General (kind, inherits, slotsigs, fields, isConcrete, _, _, _) ->
let kind = InferTyconKind g (kind, attrs, slotsigs, fields, inSig, isConcrete, m)

match inheritedTys with
| [] ->
match kind with
Expand All @@ -3335,21 +3334,25 @@ module EstablishTypeDefinitionCores =

| [(ty, m)] ->
let inheritRange =
match inherits with
| [] -> m
| (synType, _, _) :: _ -> synType.Range
match inherits with
| [] -> m
| (synType, _, _) :: _ -> synType.Range
if not firstPass && not (match kind with SynTypeDefnKind.Class -> true | _ -> false) then
errorR (Error(FSComp.SR.tcStructsInterfacesEnumsDelegatesMayNotInheritFromOtherTypes(), inheritRange))
CheckSuperType cenv ty inheritRange
if isTyparTy g ty then
if firstPass then
errorR(Error(FSComp.SR.tcCannotInheritFromVariableType(), inheritRange))
Some g.obj_ty_noNulls // a "super" that is a variable type causes grief later
else

else
Some ty
| _ ->
error(Error(FSComp.SR.tcTypesCannotInheritFromMultipleConcreteTypes(), m))
| _ ->
match inherits with
| [] -> ()
| _ :: inherits ->
for synType, _, _ in inherits do
errorR(Error(FSComp.SR.tcTypesCannotInheritFromMultipleConcreteTypes(), synType.Range))
None

| SynTypeDefnSimpleRepr.Enum _ ->
Some(g.system_Enum_ty)
Expand Down Expand Up @@ -4290,7 +4293,7 @@ module TcDeclarations =
// Skip over 'let' and 'do' bindings
let _, ds = ds |> List.takeUntil (function SynMemberDefn.LetBindings _ -> false | _ -> true)

// Skip over 'let' and 'do' bindings
// Skip over member bindings, abstract slots, interfaces and auto properties
let _, ds = ds |> List.takeUntil (allFalse [isMember;isAbstractSlot;isInterface;isAutoProperty])

match ds with
Expand All @@ -4299,7 +4302,6 @@ module TcDeclarations =
| SynMemberDefn.Interface (range=m) :: _ -> errorR(InternalError("List.takeUntil is wrong, have interface", m))
| SynMemberDefn.ImplicitCtor (range=m) :: _ -> errorR(InternalError("implicit class construction with two implicit constructions", m))
| SynMemberDefn.AutoProperty (range=m) :: _ -> errorR(InternalError("List.takeUntil is wrong, have auto property", m))
| SynMemberDefn.ImplicitInherit (range=m) :: _ -> errorR(Error(FSComp.SR.tcTypeDefinitionsWithImplicitConstructionMustHaveOneInherit(), m))
| SynMemberDefn.LetBindings (range=m) :: _ -> errorR(Error(FSComp.SR.tcTypeDefinitionsWithImplicitConstructionMustHaveLocalBindingsBeforeMembers(), m))
| SynMemberDefn.Inherit (trivia= { InheritKeyword = m }) :: _ -> errorR(Error(FSComp.SR.tcInheritDeclarationMissingArguments(), m))
| SynMemberDefn.NestedType (range=m) :: _ -> errorR(Error(FSComp.SR.tcTypesCannotContainNestedTypes(), m))
Expand Down Expand Up @@ -4474,7 +4476,7 @@ module TcDeclarations =
let inherits =
members |> List.choose (function
| SynMemberDefn.Inherit (ty, idOpt, m, _) -> Some(ty, m, idOpt)
| SynMemberDefn.ImplicitInherit (ty, _, idOpt, m) -> Some(ty, m, idOpt)
| SynMemberDefn.ImplicitInherit (ty, _, idOpt, m, _) -> Some(ty, m, idOpt)
| _ -> None)

//let nestedTycons = cspec |> List.choose (function SynMemberDefn.NestedType (x, _, _) -> Some x | _ -> None)
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Driver/GraphChecking/FileContentMapping.fs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ let visitSynMemberDefn (md: SynMemberDefn) : FileContentEntry list =
yield! collectFromOption visitBinding memberDefnForGet
yield! collectFromOption visitBinding memberDefnForSet
| SynMemberDefn.ImplicitCtor(ctorArgs = pat) -> yield! visitPat pat
| SynMemberDefn.ImplicitInherit(inheritType, inheritArgs, _, _) ->
| SynMemberDefn.ImplicitInherit(inheritType, inheritArgs, _, _, _) ->
yield! visitSynType inheritType
yield! visitSynExpr inheritArgs
| SynMemberDefn.LetBindings(bindings = bindings) -> yield! List.collect visitBinding bindings
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Service/FSharpParseFileResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
| SynMemberDefn.Inherit(range = m) ->
// can break on the "inherit" clause
yield! checkRange m
| SynMemberDefn.ImplicitInherit(_, arg, _, m) ->
| SynMemberDefn.ImplicitInherit(_, arg, _, m, _) ->
// can break on the "inherit" clause
yield! checkRange m
yield! walkExpr true arg
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Service/ServiceInterfaceStubGenerator.fs
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ module InterfaceStubGenerator =
| SynMemberDefn.Open _
| SynMemberDefn.ImplicitCtor _
| SynMemberDefn.Inherit _ -> None
| SynMemberDefn.ImplicitInherit(_, expr, _, _) -> walkExpr expr
| SynMemberDefn.ImplicitInherit(_, expr, _, _, _) -> walkExpr expr

and walkBinding (SynBinding(expr = expr)) = walkExpr expr

Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Service/ServiceParseTreeWalk.fs
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,7 @@ module SyntaxTraversal =

| SynMemberDefn.ImplicitCtor(ctorArgs = pat) -> traverseSynSimplePats path pat

| SynMemberDefn.ImplicitInherit(synType, synExpr, _identOption, range) ->
| SynMemberDefn.ImplicitInherit(synType, synExpr, _identOption, range, _) ->
[
dive () synType.Range (fun () ->
match traverseInherit (synType, range) with
Expand Down
4 changes: 2 additions & 2 deletions src/Compiler/Service/ServiceParsedInputOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ module ParsedInput =
| SynMemberDefn.ImplicitCtor(attributes = Attributes attrs; ctorArgs = pat) ->
List.tryPick walkAttribute attrs |> Option.orElseWith (fun _ -> walkPat pat)

| SynMemberDefn.ImplicitInherit(t, e, _, _) -> walkType t |> Option.orElseWith (fun () -> walkExpr e)
| SynMemberDefn.ImplicitInherit(t, e, _, _, _) -> walkType t |> Option.orElseWith (fun () -> walkExpr e)

| SynMemberDefn.LetBindings(bindings, _, _, _) -> List.tryPick walkBinding bindings

Expand Down Expand Up @@ -2233,7 +2233,7 @@ module ParsedInput =
| SynMemberDefn.ImplicitCtor(attributes = Attributes attrs; ctorArgs = pat) ->
List.iter walkAttribute attrs
walkPat pat
| SynMemberDefn.ImplicitInherit(t, e, _, _) ->
| SynMemberDefn.ImplicitInherit(t, e, _, _, _) ->
walkType t
walkExpr e
| SynMemberDefn.LetBindings(bindings, _, _, _) -> List.iter walkBinding bindings
Expand Down
7 changes: 6 additions & 1 deletion src/Compiler/SyntaxTree/SyntaxTree.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1488,7 +1488,12 @@ type SynMemberDefn =
range: range *
trivia: SynMemberDefnImplicitCtorTrivia

| ImplicitInherit of inheritType: SynType * inheritArgs: SynExpr * inheritAlias: Ident option * range: range
| ImplicitInherit of
inheritType: SynType *
inheritArgs: SynExpr *
inheritAlias: Ident option *
range: range *
trivia: SynMemberDefnInheritTrivia

| LetBindings of bindings: SynBinding list * isStatic: bool * isRecursive: bool * range: range

Expand Down
7 changes: 6 additions & 1 deletion src/Compiler/SyntaxTree/SyntaxTree.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -1654,7 +1654,12 @@ type SynMemberDefn =
trivia: SynMemberDefnImplicitCtorTrivia

/// An implicit inherit definition, 'inherit <typ>(args...) as base'
| ImplicitInherit of inheritType: SynType * inheritArgs: SynExpr * inheritAlias: Ident option * range: range
| ImplicitInherit of
inheritType: SynType *
inheritArgs: SynExpr *
inheritAlias: Ident option *
range: range *
trivia: SynMemberDefnInheritTrivia

/// A 'let' definition within a class
| LetBindings of bindings: SynBinding list * isStatic: bool * isRecursive: bool * range: range
Expand Down
3 changes: 2 additions & 1 deletion src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -2321,7 +2321,8 @@ inheritsDefn:

| INHERIT atomTypeNonAtomicDeprecated opt_HIGH_PRECEDENCE_APP atomicExprAfterType optBaseSpec
{ let mDecl = unionRanges (rhs parseState 1) $4.Range
SynMemberDefn.ImplicitInherit($2, $4, $5, mDecl) }
let trivia = { InheritKeyword = rhs parseState 1 }
SynMemberDefn.ImplicitInherit($2, $4, $5, mDecl, trivia) }

| INHERIT ends_coming_soon_or_recover
{ let mDecl = (rhs parseState 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -849,4 +849,37 @@ type C5 = class inherit System.MulticastDelegate override x.ToString() = "" end
(Error 771, Line 4, Col 25, Line 4, Col 36, "The types System.ValueType, System.Enum, System.Delegate, System.MulticastDelegate and System.Array cannot be used as super types in an object expression or class")
(Error 771, Line 5, Col 25, Line 5, Col 40, "The types System.ValueType, System.Enum, System.Delegate, System.MulticastDelegate and System.Array cannot be used as super types in an object expression or class");
(Error 771, Line 6, Col 25, Line 6, Col 49, "The types System.ValueType, System.Enum, System.Delegate, System.MulticastDelegate and System.Array cannot be used as super types in an object expression or class")
]


[<Fact>]
let ``Types can inherit from a single concrete type`` () =
Fsx """
type ClassA() = class end

type Class() =
inherit ClassA()
"""
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Types cannot inherit from multiple concrete types.`` () =
Fsx """
type ClassA() = class end

type ClassB() = class end

type ClassC() = class end

type Class() =
inherit ClassA()
inherit ClassB()
inherit ClassC()
"""
|> typecheck
|> shouldFail
|> withDiagnostics [
(Error 932, Line 10, Col 13, Line 10, Col 19, "Types cannot inherit from multiple concrete types")
(Error 932, Line 11, Col 13, Line 11, Col 19, "Types cannot inherit from multiple concrete types")
]
Original file line number Diff line number Diff line change
Expand Up @@ -8150,7 +8150,9 @@ FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAb
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAutoProperty(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynType], FSharp.Compiler.Syntax.SynMemberKind, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Syntax.SynValSigAccess, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnAutoPropertyTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewGetSetMember(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitCtor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynPat, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitInherit(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynMemberDefn+ImplicitInherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia get_trivia()
FSharp.Compiler.Syntax.SynMemberDefn+ImplicitInherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia trivia
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitInherit(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia)
FSharp.Compiler.Syntax.SynMemberDefn+Inherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia get_trivia()
FSharp.Compiler.Syntax.SynMemberDefn+Inherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia trivia
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInherit(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8150,7 +8150,9 @@ FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAb
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewAutoProperty(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynType], FSharp.Compiler.Syntax.SynMemberKind, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Syntax.SynMemberFlags, FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Syntax.SynValSigAccess, FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnAutoPropertyTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewGetSetMember(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBinding], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberGetSetTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitCtor(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Syntax.SynPat, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnImplicitCtorTrivia)
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitInherit(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range)
FSharp.Compiler.Syntax.SynMemberDefn+ImplicitInherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia get_trivia()
FSharp.Compiler.Syntax.SynMemberDefn+ImplicitInherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia trivia
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewImplicitInherit(FSharp.Compiler.Syntax.SynType, FSharp.Compiler.Syntax.SynExpr, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia)
FSharp.Compiler.Syntax.SynMemberDefn+Inherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia get_trivia()
FSharp.Compiler.Syntax.SynMemberDefn+Inherit: FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia trivia
FSharp.Compiler.Syntax.SynMemberDefn: FSharp.Compiler.Syntax.SynMemberDefn NewInherit(FSharp.Compiler.Syntax.SynType, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident], FSharp.Compiler.Text.Range, FSharp.Compiler.SyntaxTrivia.SynMemberDefnInheritTrivia)
Expand Down
10 changes: 5 additions & 5 deletions tests/service/data/SyntaxTree/Member/Inherit 02.fs.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ ImplFile
(Unspecified,
[ImplicitInherit
(LongIdent (SynLongIdent ([T2], [], [None])),
Const (Unit, (4,14--4,16)), None, (4,4--4,16))],
(4,4--4,16)), [], None, (3,5--4,16),
{ LeadingKeyword = Type (3,0--3,4)
EqualsRange = Some (3,8--3,9)
WithKeyword = None })], (3,0--4,16))],
Const (Unit, (4,14--4,16)), None, (4,4--4,16),
{ InheritKeyword = (4,4--4,11) })], (4,4--4,16)), [],
None, (3,5--4,16), { LeadingKeyword = Type (3,0--3,4)
EqualsRange = Some (3,8--3,9)
WithKeyword = None })], (3,0--4,16))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,16), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
Expand Down
Loading