Skip to content

Commit a4656b1

Browse files
committed
Disallow class parent refinements other than refinements of tracked parameters
1 parent 2bd0c96 commit a4656b1

File tree

6 files changed

+42
-4
lines changed

6 files changed

+42
-4
lines changed

compiler/src/dotty/tools/dotc/core/Flags.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ object Flags {
470470
Scala2SpecialFlags, MutableOrOpen, Opaque, Touched, JavaStatic,
471471
OuterOrCovariant, LabelOrContravariant, CaseAccessor,
472472
Extension, NonMember, Implicit, Given, Permanent, Synthetic, Exported,
473-
SuperParamAliasOrScala2x, Inline, Macro, ConstructorProxy, Invisible, Tracked)
473+
SuperParamAliasOrScala2x, Inline, Macro, ConstructorProxy, Invisible)
474474

475475
/** Flags that are not (re)set when completing the denotation, or, if symbol is
476476
* a top-level class or object, when completing the denotation once the class
@@ -479,7 +479,7 @@ object Flags {
479479
*/
480480
val AfterLoadFlags: FlagSet = commonFlags(
481481
FromStartFlags, AccessFlags, Final, AccessorOrSealed,
482-
Abstract, LazyOrTrait, SelfName, JavaDefined, JavaAnnotation, Transparent)
482+
Abstract, LazyOrTrait, SelfName, JavaDefined, JavaAnnotation, Transparent, Tracked)
483483

484484
/** A value that's unstable unless complemented with a Stable flag */
485485
val UnstableValueFlags: FlagSet = Mutable | Method

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
111111
protected def refinementNameString(tp: RefinedType): String = nameString(tp.refinedName)
112112

113113
/** String representation of a refinement */
114-
protected def toTextRefinement(rt: RefinedType): Text =
114+
def toTextRefinement(rt: RefinedType): Text =
115115
val keyword = rt.refinedInfo match {
116116
case _: ExprType | _: MethodOrPoly => "def "
117117
case _: TypeBounds => "type "

compiler/src/dotty/tools/dotc/printing/Printer.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package printing
44

55
import core.*
66
import Texts.*, ast.Trees.*
7-
import Types.{Type, SingletonType, LambdaParam, NamedType},
7+
import Types.{Type, SingletonType, LambdaParam, NamedType, RefinedType},
88
Symbols.Symbol, Scopes.Scope, Constants.Constant,
99
Names.Name, Denotations._, Annotations.Annotation, Contexts.Context
1010
import typer.Implicits.*
@@ -104,6 +104,9 @@ abstract class Printer {
104104
/** Textual representation of a prefix of some reference, ending in `.` or `#` */
105105
def toTextPrefixOf(tp: NamedType): Text
106106

107+
/** textual representation of a refinement, with no enclosing {...} */
108+
def toTextRefinement(rt: RefinedType): Text
109+
107110
/** Textual representation of a reference in a capture set */
108111
def toTextCaptureRef(tp: Type): Text
109112

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,20 @@ trait Checking {
11971197
}
11981198
}
11991199

1200+
/** Check that all refinements in class parent come from tracked parameters */
1201+
def checkOnlyDependentRefinements(cls: ClassSymbol, parent: Tree)(using Context): Unit =
1202+
def recur(ptype: Type): Unit = ptype.dealias match
1203+
case rt @ RefinedType(ptype1, rname, rinfo) =>
1204+
val ok = rname.isTermName && cls.info.member(rname).hasAltWith(_.symbol.is(Tracked))
1205+
if !ok then
1206+
report.error(
1207+
em"""Illegal refinement { ${ctx.printer.toTextRefinement(rt).show} } in parent type of $cls;
1208+
|only val refinements of tracked parameters are allowed.""",
1209+
parent.srcPos)
1210+
recur(ptype1)
1211+
case _ =>
1212+
recur(parent.tpe)
1213+
12001214
/** Check that `tpt` does not define a higher-kinded type */
12011215
def checkSimpleKinded(tpt: Tree)(using Context): Tree =
12021216
if (!tpt.tpe.hasSimpleKind && !ctx.isJava)
@@ -1592,6 +1606,7 @@ trait ReChecking extends Checking {
15921606
override def checkCanThrow(tp: Type, span: Span)(using Context): Tree = EmptyTree
15931607
override def checkCatch(pat: Tree, guard: Tree)(using Context): Unit = ()
15941608
override def checkNoContextFunctionType(tree: Tree)(using Context): Unit = ()
1609+
override def checkOnlyDependentRefinements(cls: ClassSymbol, parent: Tree)(using Context): Unit = ()
15951610
override def checkFeature(name: TermName, description: => String, featureUseSite: Symbol, pos: SrcPos)(using Context): Unit = ()
15961611
}
15971612

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,6 +2704,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
27042704
ensureAccessible(constr.termRef, superAccess = true, tree.srcPos)
27052705
else
27062706
checkParentCall(result, cls)
2707+
if !cls.isRefinementClass then
2708+
checkOnlyDependentRefinements(cls, parent)
27072709
if cls is Case then
27082710
checkCaseInheritance(psym, cls, tree.srcPos)
27092711
result

tests/neg/i0248-inherit-refined.check

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-- Error: tests/neg/i0248-inherit-refined.scala:4:18 -------------------------------------------------------------------
2+
4 | class B extends X // error
3+
| ^
4+
| Illegal refinement { type T = Int } in parent type of class B;
5+
| only val refinements of tracked parameters are allowed.
6+
-- [E170] Type Error: tests/neg/i0248-inherit-refined.scala:6:18 -------------------------------------------------------
7+
6 | class C extends Y // error
8+
| ^
9+
| test.A & test.B is not a class type
10+
-- [E170] Type Error: tests/neg/i0248-inherit-refined.scala:8:18 -------------------------------------------------------
11+
8 | class D extends Z // error
12+
| ^
13+
| test.A | test.B is not a class type
14+
-- Error: tests/neg/i0248-inherit-refined.scala:9:28 -------------------------------------------------------------------
15+
9 | abstract class E extends ({ val x: Int }) // error
16+
| ^^^^^^^^^^^^^^
17+
| Illegal refinement { val x: Int } in parent type of class E;
18+
| only val refinements of tracked parameters are allowed.

0 commit comments

Comments
 (0)