Skip to content

Commit c8e7b2a

Browse files
Rename *product* methods and update scaladoc
1 parent 2bab140 commit c8e7b2a

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
@@ -768,14 +768,17 @@ class Definitions {
768768
TupleType(elems.size).appliedTo(elems)
769769
}
770770

771-
def isProductSubType(tp: Type)(implicit ctx: Context) =
771+
/** Is this type eligible for name based pattern matching?
772+
*
773+
* That means either extending `scala.ProductN` or `NameBasedPattern`.
774+
* Ideally only the second condition should be used, first on is kept
775+
* for compatibility with scala2 compiled case classes.
776+
*/
777+
def isNameBasedPatternSubType(tp: Type)(implicit ctx: Context) =
772778
(tp.derivesFrom(ProductType.symbol) && tp.baseClasses.exists(isProductClass)) ||
773779
tp.derivesFrom(NameBasedPatternType.symbol)
774780

775-
def productArity(tp: Type)(implicit ctx: Context) =
776-
if (isProductSubType(tp)) typer.Applications.productSelectorTypes(tp).size else -1
777-
778-
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN ? */
781+
/** Is `tp` (an alias) of either a scala.FunctionN or a scala.ImplicitFunctionN? */
779782
def isFunctionType(tp: Type)(implicit ctx: Context) = {
780783
val arity = functionArity(tp)
781784
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
@@ -235,8 +235,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
235235
// next: MatchMonad[U]
236236
// returns MatchMonad[U]
237237
def flatMap(prev: Tree, b: Symbol, next: Tree): Tree = {
238-
val resultArity = defn.productArity(b.info)
239-
if (isProductMatch(prev.tpe, resultArity)) {
238+
val resultArity = productArity(b.info)
239+
if (isNameBasedMatch(prev.tpe, resultArity)) {
240240
val nullCheck: Tree = prev.select(defn.Object_ne).appliedTo(Literal(Constant(null)))
241241
ifThenElseZero(
242242
nullCheck,
@@ -1430,7 +1430,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
14301430

14311431
def resultInMonad =
14321432
if (aligner.isBool) defn.UnitType
1433-
else if (isProductMatch(resultType, aligner.prodArity)) resultType
1433+
else if (isNameBasedMatch(resultType, aligner.prodArity)) resultType
14341434
else if (isGetMatch(resultType)) extractorMemberType(resultType, nme.get)
14351435
else resultType
14361436

@@ -1474,7 +1474,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
14741474
protected def seqTree(binder: Symbol) = tupleSel(binder)(firstIndexingBinder + 1)
14751475
protected def tupleSel(binder: Symbol)(i: Int): Tree = {
14761476
val accessors =
1477-
if (defn.isProductSubType(binder.info))
1477+
if (defn.isNameBasedPatternSubType(binder.info))
14781478
productSelectors(binder.info)
14791479
else binder.caseAccessors
14801480
val res =
@@ -1631,7 +1631,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
16311631
ref(binder) :: Nil
16321632
}
16331633
else if ((aligner.isSingle && aligner.extractor.prodArity == 1) &&
1634-
!isProductMatch(binderTypeTested, aligner.prodArity) && isGetMatch(binderTypeTested))
1634+
!isNameBasedMatch(binderTypeTested, aligner.prodArity) && isGetMatch(binderTypeTested))
16351635
List(ref(binder))
16361636
else
16371637
subPatRefs(binder)
@@ -1882,11 +1882,11 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
18821882

18831883
val expanded: List[Type] = /*(
18841884
if (result =:= defn.BooleanType) Nil
1885-
else if (defn.isProductSubType(result)) productSelectorTypes(result)
1885+
else if (defn.isNameBasedPatternSubType(result)) productSelectorTypes(result)
18861886
else if (result.classSymbol is Flags.CaseClass) result.decls.filter(x => x.is(Flags.CaseAccessor) && x.is(Flags.Method)).map(_.info).toList
18871887
else result.select(nme.get) :: Nil
18881888
)*/
1889-
if (isProductMatch(resultType, args.length)) productSelectorTypes(resultType)
1889+
if (isNameBasedMatch(resultType, args.length)) productSelectorTypes(resultType)
18901890
else if (isGetMatch(resultType)) getUnapplySelectors(resultOfGet, args)
18911891
else if (resultType isRef defn.BooleanClass) Nil
18921892
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
@@ -747,7 +747,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
747747
/** Is `formal` a product type which is elementwise compatible with `params`? */
748748
def ptIsCorrectProduct(formal: Type) = {
749749
isFullyDefined(formal, ForceDegree.noBottom) &&
750-
defn.isProductSubType(formal) &&
750+
defn.isNameBasedPatternSubType(formal) &&
751751
Applications.productSelectorTypes(formal).corresponds(params) {
752752
(argType, param) =>
753753
param.tpt.isEmpty || argType <:< typedAheadType(param.tpt).tpe

0 commit comments

Comments
 (0)