Skip to content

Commit dccd734

Browse files
committed
Extract branches to methods
1 parent 0826e2c commit dccd734

File tree

2 files changed

+23
-18
lines changed

2 files changed

+23
-18
lines changed

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

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,19 @@ trait Deriving { this: Typer =>
6161

6262
/** Check derived type tree `derived` for the following well-formedness conditions:
6363
* (1) It must be a class type with a stable prefix (@see checkClassTypeWithStablePrefix)
64-
* (2) It must have exactly one type parameter
65-
* If it passes the checks, enter a typeclass instance for it in the current scope.
66-
* Given
67-
*
68-
* class C[Ts] .... derives ... D ...
6964
*
70-
* where `T_1, ..., T_n` are the first-kinded type parameters in `Ts`,
71-
* the typeclass instance has the form
65+
* (2) It must belong to one of the following three categories:
66+
* (a) a single paramter type class with a parameter which matches the kind of
67+
* the deriving ADT
68+
* (b) a single parameter type class with a parameter of kind * and an ADT with
69+
* one or more type parameter of kind *
70+
* (c) the Eql type class
7271
*
73-
* implicit def derived$D(implicit ev_1: D[T_1], ..., ev_n: D[T_n]): D[C[Ts]] = D.derived
72+
* See detailed descriptions in deriveSingleParameter and deriveEql below.
7473
*
75-
* See the body of this method for how to generalize this to typeclasses with more
76-
* or less than one type parameter.
74+
* If it passes the checks, enter a typeclass instance for it in the current scope.
7775
*
78-
* See test run/typeclass-derivation2 and run/derive-multi
76+
* See test run/typeclass-derivation2, run/poly-kinded-derives and pos/derive-eq
7977
* for examples that spell out what would be generated.
8078
*
8179
* Note that the name of the derived method contains the name in the derives clause, not
@@ -86,6 +84,8 @@ trait Deriving { this: Typer =>
8684
val originalTypeClassType = typedAheadType(derived, AnyTypeConstructorProto).tpe
8785
val typeClassType = checkClassType(underlyingClassRef(originalTypeClassType), derived.sourcePos, traitReq = false, stablePrefixReq = true)
8886
val typeClass = typeClassType.classSymbol
87+
val typeClassParams = typeClass.typeParams
88+
val typeClassArity = typeClassParams.length
8989

9090
def sameParamKinds(xs: List[ParamInfo], ys: List[ParamInfo]): Boolean =
9191
xs.corresponds(ys)((x, y) => x.paramInfo.hasSameKindAs(y.paramInfo))
@@ -102,10 +102,8 @@ trait Deriving { this: Typer =>
102102
addDerivedInstance(originalTypeClassType.typeSymbol.name, derivedInfo, derived.sourcePos)
103103
}
104104

105-
val typeClassParams = typeClass.typeParams
106-
val typeClassArity = typeClassParams.length
107-
if (typeClassArity == 1) {
108-
// Primary case: single parameter type classes
105+
def deriveSingleParameter: Unit = {
106+
// Single parameter type classes ... (a) and (b) above
109107
//
110108
// (a) ADT and type class parameters overlap on the right and have the
111109
// same kinds at the overlap.
@@ -161,6 +159,7 @@ trait Deriving { this: Typer =>
161159
val alignedClsParamInfos = clsParamInfos.takeRight(instanceArity)
162160
val alignedTypeClassParamInfos = typeClassParamInfos.take(alignedClsParamInfos.length)
163161

162+
164163
if ((instanceArity == clsArity || instanceArity > 0) && sameParamKinds(alignedClsParamInfos, alignedTypeClassParamInfos)) {
165164
// case (a) ... see description above
166165
val derivedParams = clsParams.dropRight(instanceArity)
@@ -182,8 +181,10 @@ trait Deriving { this: Typer =>
182181
addInstance(clsParams, evidenceParamInfos, List(instanceType))
183182
} else
184183
cannotBeUnified
185-
} else if (typeClass == defn.EqlClass) {
186-
// Special case: derives semantics for the Eql type class
184+
}
185+
186+
def deriveEql: Unit = {
187+
// Specific derives rules for the Eql type class ... (c) above
187188
//
188189
// This has been extracted from the earlier more general multi-parameter
189190
// type class model. Modulo the assumptions below, the implied semantics
@@ -243,7 +244,11 @@ trait Deriving { this: Typer =>
243244

244245
// Eql[A[T_L, U_L, V_L], A[T_R, U_R, V_R]]
245246
addInstance(clsParamss.flatten, evidenceParamInfos, instanceTypes)
246-
} else if (typeClassArity == 0)
247+
}
248+
249+
if (typeClassArity == 1) deriveSingleParameter
250+
else if (typeClass == defn.EqlClass) deriveEql
251+
else if (typeClassArity == 0)
247252
ctx.error(i"type ${typeClass.name} in derives clause of ${cls.name} has no type parameters", derived.sourcePos)
248253
else
249254
cannotBeUnified

0 commit comments

Comments
 (0)