From a12538b69f28b5de8dd2d05e820f52f28090fb85 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Fri, 11 Feb 2022 07:04:23 +0100 Subject: [PATCH] Merge pull request #1238 from joroKr21/default-access Access nested defaults through this to avoid stack overflow --- core/src/main/scala/shapeless/default.scala | 21 ++++++++++++--------- core/src/test/scala/shapeless/default.scala | 10 ++++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/core/src/main/scala/shapeless/default.scala b/core/src/main/scala/shapeless/default.scala index 0d06b3c4b..8de95db9f 100644 --- a/core/src/main/scala/shapeless/default.scala +++ b/core/src/main/scala/shapeless/default.scala @@ -240,15 +240,18 @@ class DefaultMacros(val c: whitebox.Context) extends CaseClassMacros { alt => alt.isMethod && hasDefaultParams(alt.asMethod) } - def defaultsFor(fields: List[(TermName, Type)]) = for { - ((_, argTpe), i) <- fields.zipWithIndex - default = tpe.companion.member(TermName(s"apply$$default$$${i + 1}")) orElse - altCompanion.member(TermName(s"$$lessinit$$greater$$default$$${i + 1}")) - } yield if (default.isTerm) { - val defaultTpe = appliedType(someTpe, devarargify(argTpe)) - val defaultVal = some(q"$companion.$default") - (defaultTpe, defaultVal) - } else (noneTpe, none) + def defaultsFor(fields: List[(TermName, Type)]) = { + lazy val enclosing = ownerChain(c.internal.enclosingOwner) + for (((_, argTpe), i) <- fields.zipWithIndex) yield { + val default = tpe.companion.member(TermName(s"apply$$default$$${i + 1}")) orElse + altCompanion.member(TermName(s"$$lessinit$$greater$$default$$${i + 1}")) + if (default.isTerm) { + val owner = default.owner + val qualifier = if (!owner.isStatic && enclosing.contains(owner)) This(owner) else companion + (appliedType(someTpe, devarargify(argTpe)), some(q"$qualifier.$default")) + } else (noneTpe, none) + } + } def mkDefault(defaults: List[(Type, Tree)]) = { val (types, values) = defaults.unzip diff --git a/core/src/test/scala/shapeless/default.scala b/core/src/test/scala/shapeless/default.scala index f1de92fd5..2d7075389 100644 --- a/core/src/test/scala/shapeless/default.scala +++ b/core/src/test/scala/shapeless/default.scala @@ -240,4 +240,14 @@ class DefaultTests { } assert(thrownException, "Expected DefaultRun to be thrown") } + + @Test + def testInCompanion: Unit = + assertEquals(InCompanion.default, Some(9) :: HNil) + + // Note: this has to be inside a class, not an object + case class InCompanion(a: Int = 9) + object InCompanion { + val default = Default[InCompanion].apply() + } }