Skip to content

Commit 1ec8041

Browse files
authored
Merge pull request #10670 from dotty-staging/parametric-top
Add Matchable trait
2 parents 15a25e7 + 7fad5c7 commit 1ec8041

File tree

34 files changed

+348
-71
lines changed

34 files changed

+348
-71
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -397,17 +397,14 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
397397
case TypeApply(fn, _) =>
398398
if (fn.symbol.is(Erased) || fn.symbol == defn.QuotedTypeModule_of || fn.symbol == defn.Predef_classOf) Pure else exprPurity(fn)
399399
case Apply(fn, args) =>
400-
def isKnownPureOp(sym: Symbol) =
401-
sym.owner.isPrimitiveValueClass
402-
|| sym.owner == defn.StringClass
403-
|| defn.pureMethods.contains(sym)
404-
if (tree.tpe.isInstanceOf[ConstantType] && isKnownPureOp(tree.symbol) // A constant expression with pure arguments is pure.
405-
|| (fn.symbol.isStableMember && !fn.symbol.is(Lazy))) // constructors of no-inits classes are stable
400+
if isPureApply(tree, fn) then
406401
minOf(exprPurity(fn), args.map(exprPurity)) `min` Pure
407-
else if (fn.symbol.is(Erased)) Pure
408-
else if (fn.symbol.isStableMember) /* && fn.symbol.is(Lazy) */
402+
else if fn.symbol.is(Erased) then
403+
Pure
404+
else if fn.symbol.isStableMember /* && fn.symbol.is(Lazy) */ then
409405
minOf(exprPurity(fn), args.map(exprPurity)) `min` Idempotent
410-
else Impure
406+
else
407+
Impure
411408
case Typed(expr, _) =>
412409
exprPurity(expr)
413410
case Block(stats, expr) =>
@@ -440,6 +437,17 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
440437

441438
def isPureBinding(tree: Tree)(using Context): Boolean = statPurity(tree) >= Pure
442439

440+
/** Is the application `tree` with function part `fn` known to be pure?
441+
* Function value and arguments can still be impure.
442+
*/
443+
def isPureApply(tree: Tree, fn: Tree)(using Context): Boolean =
444+
def isKnownPureOp(sym: Symbol) =
445+
sym.owner.isPrimitiveValueClass
446+
|| sym.owner == defn.StringClass
447+
|| defn.pureMethods.contains(sym)
448+
tree.tpe.isInstanceOf[ConstantType] && isKnownPureOp(tree.symbol) // A constant expression with pure arguments is pure.
449+
|| fn.symbol.isStableMember && !fn.symbol.is(Lazy) // constructors of no-inits classes are stable
450+
443451
/** The purity level of this reference.
444452
* @return
445453
* PurePath if reference is (nonlazy and stable)

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,19 @@ class Definitions {
259259
*/
260260
@tu lazy val AnyClass: ClassSymbol = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.Any, Abstract, Nil), ensureCtor = false)
261261
def AnyType: TypeRef = AnyClass.typeRef
262-
@tu lazy val AnyValClass: ClassSymbol = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.AnyVal, Abstract, List(AnyClass.typeRef)))
262+
@tu lazy val MatchableClass: ClassSymbol = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.Matchable, Trait, AnyType :: Nil), ensureCtor = false)
263+
def MatchableType: TypeRef = MatchableClass.typeRef
264+
@tu lazy val AnyValClass: ClassSymbol =
265+
val res = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.AnyVal, Abstract, List(AnyType, MatchableType)))
266+
// Mark companion as absent, so that class does not get re-completed
267+
val companion = ScalaPackageVal.info.decl(nme.AnyVal).symbol
268+
companion.moduleClass.markAbsent()
269+
companion.markAbsent()
270+
res
271+
263272
def AnyValType: TypeRef = AnyValClass.typeRef
264273

265-
@tu lazy val Any_== : TermSymbol = enterMethod(AnyClass, nme.EQ, methOfAny(BooleanType), Final)
274+
@tu lazy val Any_== : TermSymbol = enterMethod(AnyClass, nme.EQ, methOfAny(BooleanType), Final)
266275
@tu lazy val Any_!= : TermSymbol = enterMethod(AnyClass, nme.NE, methOfAny(BooleanType), Final)
267276
@tu lazy val Any_equals: TermSymbol = enterMethod(AnyClass, nme.equals_, methOfAny(BooleanType))
268277
@tu lazy val Any_hashCode: TermSymbol = enterMethod(AnyClass, nme.hashCode_, MethodType(Nil, IntType))
@@ -288,7 +297,7 @@ class Definitions {
288297
@tu lazy val ObjectClass: ClassSymbol = {
289298
val cls = requiredClass("java.lang.Object")
290299
assert(!cls.isCompleted, "race for completing java.lang.Object")
291-
cls.info = ClassInfo(cls.owner.thisType, cls, AnyClass.typeRef :: Nil, newScope)
300+
cls.info = ClassInfo(cls.owner.thisType, cls, List(AnyType, MatchableType), newScope)
292301
cls.setFlag(NoInits | JavaDefined)
293302

294303
// The companion object doesn't really exist, so it needs to be marked as
@@ -444,7 +453,7 @@ class Definitions {
444453
MethodType(List(ThrowableType), NothingType))
445454

446455
@tu lazy val NothingClass: ClassSymbol = enterCompleteClassSymbol(
447-
ScalaPackageClass, tpnme.Nothing, AbstractFinal, List(AnyClass.typeRef))
456+
ScalaPackageClass, tpnme.Nothing, AbstractFinal, List(AnyType))
448457
def NothingType: TypeRef = NothingClass.typeRef
449458
@tu lazy val NullClass: ClassSymbol = {
450459
val parent = if (ctx.explicitNulls) AnyType else ObjectType
@@ -520,7 +529,7 @@ class Definitions {
520529
// but does not define it as an explicit class.
521530
enterCompleteClassSymbol(
522531
ScalaPackageClass, tpnme.Singleton, PureInterfaceCreationFlags | Final,
523-
List(AnyClass.typeRef), EmptyScope)
532+
List(AnyType), EmptyScope)
524533
@tu lazy val SingletonType: TypeRef = SingletonClass.typeRef
525534

526535
@tu lazy val CollectionSeqType: TypeRef = requiredClassRef("scala.collection.Seq")
@@ -1144,6 +1153,8 @@ class Definitions {
11441153

11451154
// ----- Symbol sets ---------------------------------------------------
11461155

1156+
@tu lazy val topClasses: Set[Symbol] = Set(AnyClass, MatchableClass, ObjectClass, AnyValClass)
1157+
11471158
@tu lazy val AbstractFunctionType: Array[TypeRef] = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0)
11481159
val AbstractFunctionClassPerRun: PerRun[Array[Symbol]] = new PerRun(AbstractFunctionType.map(_.symbol.asClass))
11491160
def AbstractFunctionClass(n: Int)(using Context): Symbol = AbstractFunctionClassPerRun()(using ctx)(n)
@@ -1372,7 +1383,7 @@ class Definitions {
13721383
@tu lazy val ShadowableImportNames: Set[TermName] = Set("Predef".toTermName)
13731384

13741385
/** Class symbols for which no class exist at runtime */
1375-
@tu lazy val NotRuntimeClasses: Set[Symbol] = Set(AnyClass, AnyValClass, NullClass, NothingClass)
1386+
@tu lazy val NotRuntimeClasses: Set[Symbol] = Set(AnyClass, MatchableClass, AnyValClass, NullClass, NothingClass)
13761387

13771388
@tu lazy val SpecialClassTagClasses: Set[Symbol] = Set(UnitClass, AnyClass, AnyValClass)
13781389

@@ -1672,6 +1683,7 @@ class Definitions {
16721683
@tu lazy val specialErasure: SimpleIdentityMap[Symbol, ClassSymbol] =
16731684
SimpleIdentityMap.empty[Symbol]
16741685
.updated(AnyClass, ObjectClass)
1686+
.updated(MatchableClass, ObjectClass)
16751687
.updated(AnyValClass, ObjectClass)
16761688
.updated(SingletonClass, ObjectClass)
16771689
.updated(TupleClass, ProductClass)
@@ -1683,6 +1695,7 @@ class Definitions {
16831695
@tu lazy val syntheticScalaClasses: List[TypeSymbol] = {
16841696
val synth = List(
16851697
AnyClass,
1698+
MatchableClass,
16861699
AnyRefAlias,
16871700
AnyKindClass,
16881701
andType,

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,7 @@ object Mode {
116116

117117
/** Are we typechecking the rhs of an extension method? */
118118
val InExtensionMethod: Mode = newMode(26, "InExtensionMethod")
119+
120+
/** Are we resolving a TypeTest node? */
121+
val InTypeTest: Mode = newMode(27, "InTypeTest")
119122
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
297297
/** If `inst` is a TypeBounds, make sure it does not contain toplevel
298298
* references to `param` (see `Constraint#occursAtToplevel` for a definition
299299
* of "toplevel").
300-
* Any such references are replace by `Nothing` in the lower bound and `Any`
300+
* Any such references are replaced by `Nothing` in the lower bound and `Any`
301301
* in the upper bound.
302302
* References can be direct or indirect through instantiations of other
303303
* parameters in the constraint.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ object StdNames {
371371
val Import: N = "Import"
372372
val Literal: N = "Literal"
373373
val LiteralAnnotArg: N = "LiteralAnnotArg"
374+
val Matchable: N = "Matchable"
374375
val MatchCase: N = "MatchCase"
375376
val MirroredElemTypes: N = "MirroredElemTypes"
376377
val MirroredElemLabels: N = "MirroredElemLabels"

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2246,9 +2246,7 @@ object SymDenotations {
22462246
if (pcls.isCompleting) recur(pobjs1, acc)
22472247
else
22482248
val pobjMembers = pcls.nonPrivateMembersNamed(name).filterWithPredicate { d =>
2249-
// Drop members of `Any` and `Object`
2250-
val owner = d.symbol.maybeOwner
2251-
(owner ne defn.AnyClass) && (owner ne defn.ObjectClass)
2249+
!defn.topClasses.contains(d.symbol.maybeOwner) // Drop members of top classes
22522250
}
22532251
recur(pobjs1, acc.union(pobjMembers))
22542252
case nil =>

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ object Types {
209209
def isAnyRef(using Context): Boolean = isRef(defn.ObjectClass, skipRefined = false)
210210
def isAnyKind(using Context): Boolean = isRef(defn.AnyKindClass, skipRefined = false)
211211

212+
def isTopType(using Context): Boolean = dealias match
213+
case tp: TypeRef => defn.topClasses.contains(tp.symbol)
214+
case _ => false
215+
212216
/** Is this type exactly Nothing (no vars, aliases, refinements etc allowed)? */
213217
def isExactlyNothing(using Context): Boolean = this match {
214218
case tp: TypeRef =>
@@ -512,6 +516,20 @@ object Types {
512516
case _ =>
513517
false
514518

519+
/** Same as hasClassSmbol(MatchableClass), except that we also follow the constraint
520+
* bounds of type variables in the constraint.
521+
*/
522+
def isMatchableBound(using Context): Boolean = dealias match
523+
case tp: TypeRef => tp.symbol == defn.MatchableClass
524+
case tp: TypeParamRef =>
525+
ctx.typerState.constraint.entry(tp) match
526+
case bounds: TypeBounds => bounds.hi.isMatchableBound
527+
case _ => false
528+
case tp: TypeProxy => tp.underlying.isMatchableBound
529+
case tp: AndType => tp.tp1.isMatchableBound || tp.tp2.isMatchableBound
530+
case tp: OrType => tp.tp1.isMatchableBound && tp.tp2.isMatchableBound
531+
case _ => false
532+
515533
/** The term symbol associated with the type */
516534
@tailrec final def termSymbol(using Context): Symbol = this match {
517535
case tp: TermRef => tp.symbol
@@ -3812,10 +3830,6 @@ object Types {
38123830

38133831
def unapply(tl: PolyType): Some[(List[LambdaParam], Type)] =
38143832
Some((tl.typeParams, tl.resType))
3815-
3816-
def any(n: Int)(using Context): PolyType =
3817-
apply(syntheticParamNames(n))(
3818-
pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType)
38193833
}
38203834

38213835
private object DepStatus {

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,7 @@ import transform.SymUtils._
266266
val postScript = addenda.find(!_.isEmpty) match
267267
case Some(p) => p
268268
case None =>
269-
if expected.isAny
270-
|| expected.isAnyRef
271-
|| expected.isRef(defn.AnyValClass)
272-
|| found.isBottomType
269+
if expected.isTopType || found.isBottomType
273270
then ""
274271
else ctx.typer.importSuggestionAddendum(ViewProto(found.widen, expected))
275272
val (where, printCtx) = Formatting.disambiguateTypes(found2, expected2)

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ class Erasure extends Phase with DenotTransformer {
6161
// After erasure, all former Any members are now Object members
6262
val ClassInfo(pre, _, ps, decls, selfInfo) = ref.info
6363
val extendedScope = decls.cloneScope
64-
for (decl <- defn.AnyClass.classInfo.decls)
65-
if (!decl.isConstructor) extendedScope.enter(decl)
64+
for decl <- defn.AnyClass.classInfo.decls do
65+
if !decl.isConstructor then extendedScope.enter(decl)
6666
ref.copySymDenotation(
6767
info = transformInfo(ref.symbol,
6868
ClassInfo(pre, defn.ObjectClass, ps, extendedScope, selfInfo))
@@ -71,11 +71,12 @@ class Erasure extends Phase with DenotTransformer {
7171
else {
7272
val oldSymbol = ref.symbol
7373
val newSymbol =
74-
if ((oldSymbol.owner eq defn.AnyClass) && oldSymbol.isConstructor)
74+
if ((oldSymbol.owner eq defn.AnyClass) && oldSymbol.isConstructor) then
75+
//assert(false)
7576
defn.ObjectClass.primaryConstructor
7677
else oldSymbol
7778
val oldOwner = ref.owner
78-
val newOwner = if (oldOwner eq defn.AnyClass) defn.ObjectClass else oldOwner
79+
val newOwner = if oldOwner == defn.AnyClass then defn.ObjectClass else oldOwner
7980
val oldName = ref.name
8081
val newName = ref.targetName
8182
val oldInfo = ref.info

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,8 @@ trait Applications extends Compatibility {
11581158
def typedUnApply(tree: untpd.Apply, selType: Type)(using Context): Tree = {
11591159
record("typedUnApply")
11601160
val Apply(qual, args) = tree
1161+
if !ctx.mode.is(Mode.InTypeTest) then
1162+
checkMatchable(selType, tree.srcPos, pattern = true)
11611163

11621164
def notAnExtractor(tree: Tree): Tree =
11631165
// prefer inner errors

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,13 @@ trait Checking {
12461246
if preExisting.exists || seen.contains(tname) then
12471247
report.error(em"@targetName annotation ${'"'}$tname${'"'} clashes with other definition in same scope", stat.srcPos)
12481248
if stat.isDef then seen += tname
1249+
1250+
def checkMatchable(tp: Type, pos: SrcPos, pattern: Boolean)(using Context): Unit =
1251+
if !tp.derivesFrom(defn.MatchableClass) && sourceVersion.isAtLeast(`3.1-migration`) then
1252+
val kind = if pattern then "pattern selector" else "value"
1253+
report.warning(
1254+
em"""${kind} should be an instance of Matchable,
1255+
|but it has unmatchable type $tp instead""", pos)
12491256
}
12501257

12511258
trait ReChecking extends Checking {
@@ -1256,6 +1263,7 @@ trait ReChecking extends Checking {
12561263
override def checkFullyAppliedType(tree: Tree)(using Context): Unit = ()
12571264
override def checkEnumCaseRefsLegal(cdef: TypeDef, enumCtx: Context)(using Context): Unit = ()
12581265
override def checkAnnotApplicable(annot: Tree, sym: Symbol)(using Context): Boolean = true
1266+
override def checkMatchable(tp: Type, pos: SrcPos, pattern: Boolean)(using Context): Unit = ()
12591267
}
12601268

12611269
trait NoChecking extends ReChecking {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,8 @@ trait Implicits:
898898
case TypeBounds(lo, hi) if lo.ne(hi) && !t.symbol.is(Opaque) => apply(hi)
899899
case _ => t
900900
}
901+
case t: SingletonType =>
902+
apply(t.widen)
901903
case t: RefinedType =>
902904
apply(t.parent)
903905
case _ =>

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -545,10 +545,6 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
545545
case TypeApply(fn, _) =>
546546
if (fn.symbol.is(Erased) || fn.symbol == defn.QuotedTypeModule_of) true else apply(fn)
547547
case Apply(fn, args) =>
548-
def isKnownPureOp(sym: Symbol) =
549-
sym.owner.isPrimitiveValueClass
550-
|| sym.owner == defn.StringClass
551-
|| defn.pureMethods.contains(sym)
552548
val isCaseClassApply = {
553549
val cls = tree.tpe.classSymbol
554550
val meth = fn.symbol
@@ -557,8 +553,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
557553
meth.owner.linkedClass.is(Case) &&
558554
cls.isNoInitsRealClass
559555
}
560-
if (tree.tpe.isInstanceOf[ConstantType] && isKnownPureOp(tree.symbol) // A constant expression with pure arguments is pure.
561-
|| (fn.symbol.isStableMember && !fn.symbol.is(Lazy))) // constructors of no-inits classes are stable
556+
if isPureApply(tree, fn) then
562557
apply(fn) && args.forall(apply)
563558
else if (isCaseClassApply)
564559
args.forall(apply)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
6262
val arg :: Nil = args
6363
val t = arg.tpe & tp2
6464
If(
65-
arg.select(defn.Any_isInstanceOf).appliedToType(tp2),
65+
arg.isInstance(tp2),
6666
ref(defn.SomeClass.companionModule.termRef).select(nme.apply)
6767
.appliedToType(t)
6868
.appliedTo(arg.select(nme.asInstanceOf_).appliedToType(t)),

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

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,10 @@ class Typer extends Namer
682682
case templ: untpd.Template =>
683683
import untpd._
684684
var templ1 = templ
685-
def isEligible(tp: Type) = tp.exists && !tp.typeSymbol.is(Final) && !tp.isRef(defn.AnyClass)
685+
def isEligible(tp: Type) =
686+
tp.exists
687+
&& !tp.typeSymbol.is(Final)
688+
&& (!tp.isTopType || tp.isAnyRef) // Object is the only toplevel class that can be instantiated
686689
if (templ1.parents.isEmpty &&
687690
isFullyDefined(pt, ForceDegree.flipBottom) &&
688691
isSkolemFree(pt) &&
@@ -768,12 +771,20 @@ class Typer extends Namer
768771
def typedTpt = checkSimpleKinded(typedType(tree.tpt))
769772
def handlePattern: Tree = {
770773
val tpt1 = typedTpt
771-
if (!ctx.isAfterTyper && pt != defn.ImplicitScrutineeTypeRef)
774+
if !ctx.isAfterTyper && pt != defn.ImplicitScrutineeTypeRef then
772775
withMode(Mode.GadtConstraintInference) {
773776
TypeComparer.constrainPatternType(tpt1.tpe, pt)
774777
}
778+
val matched = ascription(tpt1, isWildcard = true)
775779
// special case for an abstract type that comes with a class tag
776-
tryWithTypeTest(ascription(tpt1, isWildcard = true), pt)
780+
val result = tryWithTypeTest(matched, pt)
781+
if (result eq matched)
782+
&& pt != defn.ImplicitScrutineeTypeRef
783+
&& !(pt <:< tpt1.tpe)
784+
then
785+
// no check for matchability if TestTest was applied
786+
checkMatchable(pt, tree.srcPos, pattern = true)
787+
result
777788
}
778789
cases(
779790
ifPat = handlePattern,
@@ -794,13 +805,15 @@ class Typer extends Namer
794805
inferImplicit(tpe, EmptyTree, tree.tpt.span)
795806
) match
796807
case SearchSuccess(clsTag, _, _) =>
797-
Some(typed(untpd.Apply(untpd.TypedSplice(clsTag), untpd.TypedSplice(tree.expr)), pt))
808+
withMode(Mode.InTypeTest) {
809+
Some(typed(untpd.Apply(untpd.TypedSplice(clsTag), untpd.TypedSplice(tree.expr)), pt))
810+
}
798811
case _ =>
799812
None
800813
}
801814
val tag = withTag(defn.TypeTestClass.typeRef.appliedTo(pt, tref))
802-
.orElse(withTag(defn.ClassTagClass.typeRef.appliedTo(tref)))
803-
.getOrElse(tree)
815+
.orElse(withTag(defn.ClassTagClass.typeRef.appliedTo(tref)))
816+
.getOrElse(tree)
804817
if tag.symbol.owner == defn.ClassTagClass && config.Feature.sourceVersion.isAtLeast(config.SourceVersion.`3.1`) then
805818
report.warning("Use of `scala.reflect.ClassTag` for type testing may be unsound. Consider using `scala.reflect.TypeTest` instead.", tree.srcPos)
806819
tag
@@ -1320,7 +1333,7 @@ class Typer extends Namer
13201333
typed(desugar.makeCaseLambda(tree.cases, checkMode, protoFormals.length).withSpan(tree.span), pt)
13211334
}
13221335
case _ =>
1323-
if (tree.isInline) checkInInlineContext("inline match", tree.srcPos)
1336+
if tree.isInline then checkInInlineContext("inline match", tree.srcPos)
13241337
val sel1 = typedExpr(tree.selector)
13251338
val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.span).widen
13261339

@@ -3529,6 +3542,13 @@ class Typer extends Namer
35293542
case _ =>
35303543
}
35313544

3545+
// try an Any -> Matchable conversion
3546+
if pt.isMatchableBound && !wtp.derivesFrom(defn.MatchableClass) then
3547+
checkMatchable(wtp, tree.srcPos, pattern = false)
3548+
val target = AndType(tree.tpe.widenExpr, defn.MatchableType)
3549+
if target <:< pt then
3550+
return readapt(tree.cast(target))
3551+
35323552
// try an implicit conversion
35333553
val prevConstraint = ctx.typerState.constraint
35343554
def recover(failure: SearchFailureType) =

compiler/src/dotty/tools/repl/ReplDriver.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,7 @@ class ReplDriver(settings: Array[String],
291291
info.bounds.hi.finalResultType
292292
.membersBasedOnFlags(required = Method, excluded = Accessor | ParamAccessor | Synthetic | Private)
293293
.filterNot { denot =>
294-
denot.symbol.owner == defn.AnyClass ||
295-
denot.symbol.owner == defn.ObjectClass ||
296-
denot.symbol.isConstructor
294+
defn.topClasses.contains(denot.symbol.owner) || denot.symbol.isConstructor
297295
}
298296

299297
val vals =

0 commit comments

Comments
 (0)