Skip to content

Commit 2d3eceb

Browse files
Rename *product* methods and update scaladoc
1 parent 165fba8 commit 2d3eceb

File tree

4 files changed

+29
-20
lines changed

4 files changed

+29
-20
lines changed

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -841,14 +841,17 @@ class Definitions {
841841
TupleType(elems.size).appliedTo(elems)
842842
}
843843

844-
def isProductSubType(tp: Type)(implicit ctx: Context) =
844+
/** Is this type eligible for name based pattern matching?
845+
*
846+
* That means either extending `scala.ProductN` or `NameBasedPattern`.
847+
* Ideally only the second condition should be used, first on is kept
848+
* for compatibility with scala2 compiled case classes.
849+
*/
850+
def isNameBasedPatternSubType(tp: Type)(implicit ctx: Context) =
845851
(tp.derivesFrom(ProductType.symbol) && tp.baseClasses.exists(isProductClass)) ||
846852
tp.derivesFrom(NameBasedPatternType.symbol)
847853

848-
def productArity(tp: Type)(implicit ctx: Context) =
849-
if (isProductSubType(tp)) typer.Applications.productSelectorTypes(tp).size else -1
850-
851-
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN ? */
854+
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN? */
852855
def isFunctionType(tp: Type)(implicit ctx: Context) = {
853856
val arity = functionArity(tp)
854857
val sym = tp.dealias.typeSymbol

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
233233
// next: MatchMonad[U]
234234
// returns MatchMonad[U]
235235
def flatMap(prev: Tree, b: Symbol, next: Tree): Tree = {
236-
val resultArity = defn.productArity(b.info)
237-
if (isProductMatch(prev.tpe, resultArity)) {
236+
val resultArity = productArity(b.info)
237+
if (isNameBasedMatch(prev.tpe, resultArity)) {
238238
val nullCheck: Tree = prev.select(defn.Object_ne).appliedTo(Literal(Constant(null)))
239239
ifThenElseZero(
240240
nullCheck,
@@ -1426,7 +1426,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
14261426

14271427
def resultInMonad =
14281428
if (aligner.isBool) defn.UnitType
1429-
else if (isProductMatch(resultType, aligner.prodArity)) resultType
1429+
else if (isNameBasedMatch(resultType, aligner.prodArity)) resultType
14301430
else if (isGetMatch(resultType)) extractorMemberType(resultType, nme.get)
14311431
else resultType
14321432

@@ -1470,7 +1470,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
14701470
protected def seqTree(binder: Symbol) = tupleSel(binder)(firstIndexingBinder + 1)
14711471
protected def tupleSel(binder: Symbol)(i: Int): Tree = {
14721472
val accessors =
1473-
if (defn.isProductSubType(binder.info))
1473+
if (defn.isNameBasedPatternSubType(binder.info))
14741474
productSelectors(binder.info)
14751475
else binder.caseAccessors
14761476
val res =
@@ -1627,7 +1627,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
16271627
ref(binder) :: Nil
16281628
}
16291629
else if ((aligner.isSingle && aligner.extractor.prodArity == 1) &&
1630-
!isProductMatch(binderTypeTested, aligner.prodArity) && isGetMatch(binderTypeTested))
1630+
!isNameBasedMatch(binderTypeTested, aligner.prodArity) && isGetMatch(binderTypeTested))
16311631
List(ref(binder))
16321632
else
16331633
subPatRefs(binder)
@@ -1878,11 +1878,11 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
18781878

18791879
val expanded: List[Type] = /*(
18801880
if (result =:= defn.BooleanType) Nil
1881-
else if (defn.isProductSubType(result)) productSelectorTypes(result)
1881+
else if (defn.isNameBasedPatternSubType(result)) productSelectorTypes(result)
18821882
else if (result.classSymbol is Flags.CaseClass) result.decls.filter(x => x.is(Flags.CaseAccessor) && x.is(Flags.Method)).map(_.info).toList
18831883
else result.select(nme.get) :: Nil
18841884
)*/
1885-
if (isProductMatch(resultType, args.length)) productSelectorTypes(resultType)
1885+
if (isNameBasedMatch(resultType, args.length)) productSelectorTypes(resultType)
18861886
else if (isGetMatch(resultType)) getUnapplySelectors(resultOfGet, args)
18871887
else if (resultType isRef defn.BooleanClass) Nil
18881888
else {

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,15 @@ object Applications {
4747
ref.info.widenExpr.dealias
4848
}
4949

50-
/** Does `tp` fit the "product match" conditions as an unapply result type
51-
* for a pattern with `numArgs` subpatterns>
52-
* This is the case of `tp` is a subtype of the Product<numArgs> class.
50+
/** Does `tp` fit the "name based pattern match" conditions as an unapply result
51+
* type for a pattern with `numArgs` subpatterns.
52+
*
53+
* This is the case if:
54+
* - `tp` is a subtype of the Product<numArgs> class or `NameBasedPattern` trait
55+
* - `tp` has members `_1` to `_N` where `N == numArgs`
5356
*/
54-
def isProductMatch(tp: Type, numArgs: Int)(implicit ctx: Context) =
55-
0 <= numArgs && defn.isProductSubType(tp) &&
57+
def isNameBasedMatch(tp: Type, numArgs: Int)(implicit ctx: Context) =
58+
0 <= numArgs && defn.isNameBasedPatternSubType(tp) &&
5659
productSelectorTypes(tp).size == numArgs
5760

5861
/** Does `tp` fit the "get match" conditions as an unapply result type?
@@ -68,6 +71,9 @@ object Applications {
6871
sels.takeWhile(_.exists).toList
6972
}
7073

74+
def productArity(tp: Type)(implicit ctx: Context) =
75+
if (defn.isNameBasedPatternSubType(tp)) productSelectorTypes(tp).size else -1
76+
7177
def productSelectors(tp: Type)(implicit ctx: Context): List[Symbol] = {
7278
val sels = for (n <- Iterator.from(0)) yield tp.member(nme.selectorName(n)).symbol
7379
sels.takeWhile(_.exists).toList
@@ -102,13 +108,13 @@ object Applications {
102108
}
103109
else {
104110
assert(unapplyName == nme.unapply)
105-
if (isProductMatch(unapplyResult, args.length))
111+
if (isNameBasedMatch(unapplyResult, args.length))
106112
productSelectorTypes(unapplyResult)
107113
else if (isGetMatch(unapplyResult, pos))
108114
getUnapplySelectors(getTp, args, pos)
109115
else if (unapplyResult isRef defn.BooleanClass)
110116
Nil
111-
else if (defn.isProductSubType(unapplyResult))
117+
else if (defn.isNameBasedPatternSubType(unapplyResult))
112118
productSelectorTypes(unapplyResult)
113119
// this will cause a "wrong number of arguments in pattern" error later on,
114120
// which is better than the message in `fail`.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
762762
/** Is `formal` a product type which is elementwise compatible with `params`? */
763763
def ptIsCorrectProduct(formal: Type) = {
764764
isFullyDefined(formal, ForceDegree.noBottom) &&
765-
defn.isProductSubType(formal) &&
765+
defn.isNameBasedPatternSubType(formal) &&
766766
Applications.productSelectorTypes(formal).corresponds(params) {
767767
(argType, param) =>
768768
param.tpt.isEmpty || argType <:< typedAheadType(param.tpt).tpe

0 commit comments

Comments
 (0)