@@ -26,7 +26,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
26
26
/** Handlers to synthesize implicits for special types */
27
27
type SpecialHandler = (Type , Span ) => Context ?=> TreeWithErrors
28
28
private type SpecialHandlers = List [(ClassSymbol , SpecialHandler )]
29
-
29
+
30
30
val synthesizedClassTag : SpecialHandler = (formal, span) =>
31
31
formal.argInfos match
32
32
case arg :: Nil =>
@@ -240,11 +240,11 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
240
240
* <parent> {
241
241
* MirroredMonoType = <monoType>
242
242
* MirroredType = <mirroredType>
243
- * MirroredLabel = <label> }
243
+ * MirroredLabel = <label>
244
244
* }
245
245
*/
246
- private def mirrorCore (parentClass : ClassSymbol , monoType : Type , mirroredType : Type , label : Name , formal : Type )(using Context ) =
247
- formal & parentClass.typeRef
246
+ private def mirrorCore (parentClass : ClassSymbol , monoType : Type , mirroredType : Type , label : Name )(using Context ) =
247
+ parentClass.typeRef
248
248
.refinedWith(tpnme.MirroredMonoType , TypeAlias (monoType))
249
249
.refinedWith(tpnme.MirroredType , TypeAlias (mirroredType))
250
250
.refinedWith(tpnme.MirroredLabel , TypeAlias (ConstantType (Constant (label.toString))))
@@ -269,6 +269,13 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
269
269
then report.error(
270
270
em " $name mismatch, expected: $expected, found: $actual. " , ctx.source.atSpan(span))
271
271
272
+ extension (formal : Type )
273
+ /** `tp := op; tp <:< formal; formal & tp` */
274
+ private def constrained_& (op : Context ?=> Type )(using Context ): Type =
275
+ val tp = op
276
+ tp <:< formal
277
+ formal & tp
278
+
272
279
private def mkMirroredMonoType (mirroredType : HKTypeLambda )(using Context ): Type =
273
280
val monoMap = new TypeMap :
274
281
def apply (t : Type ) = t match
@@ -313,22 +320,23 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
313
320
val elemsLabels = TypeOps .nestedPairs(elemLabels)
314
321
checkRefinement(formal, tpnme.MirroredElemTypes , elemsType, span)
315
322
checkRefinement(formal, tpnme.MirroredElemLabels , elemsLabels, span)
316
- val mirrorType =
317
- mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, cls.name, formal )
323
+ val mirrorType = formal.constrained_& {
324
+ mirrorCore(defn.Mirror_ProductClass , monoType, mirroredType, cls.name)
318
325
.refinedWith(tpnme.MirroredElemTypes , TypeAlias (elemsType))
319
326
.refinedWith(tpnme.MirroredElemLabels , TypeAlias (elemsLabels))
327
+ }
320
328
val mirrorRef =
321
329
if (genAnonyousMirror(cls)) anonymousMirror(monoType, ExtendsProductMirror , span)
322
330
else companionPath(mirroredType, span)
323
331
withNoErrors(mirrorRef.cast(mirrorType))
324
332
end makeProductMirror
325
333
326
- def getError (cls : Symbol ): String =
334
+ def getError (cls : Symbol ): String =
327
335
val reason = if ! cls.isGenericProduct then
328
336
i " because ${cls.whyNotGenericProduct}"
329
337
else if ! canAccessCtor(cls) then
330
338
i " because the constructor of $cls is innaccessible from the calling scope. "
331
- else
339
+ else
332
340
" "
333
341
i " $cls is not a generic product $reason"
334
342
end getError
@@ -341,11 +349,15 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
341
349
val module = mirroredType.termSymbol
342
350
val modulePath = pathFor(mirroredType).withSpan(span)
343
351
if module.info.classSymbol.is(Scala2x ) then
344
- val mirrorType = mirrorCore(defn.Mirror_SingletonProxyClass , mirroredType, mirroredType, module.name, formal)
352
+ val mirrorType = formal.constrained_& {
353
+ mirrorCore(defn.Mirror_SingletonProxyClass , mirroredType, mirroredType, module.name)
354
+ }
345
355
val mirrorRef = New (defn.Mirror_SingletonProxyClass .typeRef, modulePath :: Nil )
346
356
withNoErrors(mirrorRef.cast(mirrorType))
347
357
else
348
- val mirrorType = mirrorCore(defn.Mirror_SingletonClass , mirroredType, mirroredType, module.name, formal)
358
+ val mirrorType = formal.constrained_& {
359
+ mirrorCore(defn.Mirror_SingletonClass , mirroredType, mirroredType, module.name)
360
+ }
349
361
withNoErrors(modulePath.cast(mirrorType))
350
362
else
351
363
val cls = mirroredType.classSymbol
@@ -419,16 +431,19 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
419
431
(mirroredType, elems)
420
432
421
433
val mirrorType =
422
- mirrorCore(defn.Mirror_SumClass , monoType, mirroredType, cls.name, formal)
434
+ val labels = TypeOps .nestedPairs(elemLabels)
435
+ formal.constrained_& {
436
+ mirrorCore(defn.Mirror_SumClass , monoType, mirroredType, cls.name)
423
437
.refinedWith(tpnme.MirroredElemTypes , TypeAlias (elemsType))
424
- .refinedWith(tpnme.MirroredElemLabels , TypeAlias (TypeOps .nestedPairs(elemLabels)))
438
+ .refinedWith(tpnme.MirroredElemLabels , TypeAlias (labels))
439
+ }
425
440
val mirrorRef =
426
441
if useCompanion then companionPath(mirroredType, span)
427
442
else anonymousMirror(monoType, ExtendsSumMirror , span)
428
443
withNoErrors(mirrorRef.cast(mirrorType))
429
444
else if ! clsIsGenericSum then
430
445
(EmptyTree , List (i " $cls is not a generic sum because ${cls.whyNotGenericSum(declScope)}" ))
431
- else
446
+ else
432
447
EmptyTreeNoError
433
448
end sumMirror
434
449
@@ -595,7 +610,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
595
610
tp.baseType(cls)
596
611
val base = baseWithRefinements(formal)
597
612
val result =
598
- if (base <:< formal.widenExpr)
613
+ if (base <:< formal.widenExpr)
599
614
// With the subtype test we enforce that the searched type `formal` is of the right form
600
615
handler(base, span)
601
616
else EmptyTreeNoError
@@ -609,19 +624,19 @@ end Synthesizer
609
624
610
625
object Synthesizer :
611
626
612
- /** Tuple used to store the synthesis result with a list of errors. */
627
+ /** Tuple used to store the synthesis result with a list of errors. */
613
628
type TreeWithErrors = (Tree , List [String ])
614
629
private def withNoErrors (tree : Tree ): TreeWithErrors = (tree, List .empty)
615
630
616
631
private val EmptyTreeNoError : TreeWithErrors = withNoErrors(EmptyTree )
617
632
618
633
private def orElse (treeWithErrors1 : TreeWithErrors , treeWithErrors2 : => TreeWithErrors ): TreeWithErrors = treeWithErrors1 match
619
- case (tree, errors) if tree eq genericEmptyTree =>
634
+ case (tree, errors) if tree eq genericEmptyTree =>
620
635
val (tree2, errors2) = treeWithErrors2
621
636
(tree2, errors ::: errors2)
622
637
case _ => treeWithErrors1
623
638
624
- private def clearErrorsIfNotEmpty (treeWithErrors : TreeWithErrors ) = treeWithErrors match
639
+ private def clearErrorsIfNotEmpty (treeWithErrors : TreeWithErrors ) = treeWithErrors match
625
640
case (tree, _) if tree eq genericEmptyTree => treeWithErrors
626
641
case (tree, _) => withNoErrors(tree)
627
642
0 commit comments