Skip to content

Commit

Permalink
Merge pull request #14051 from dotty-staging/fix-14020
Browse files Browse the repository at this point in the history
Retain HasDefaultParams flag on export.
  • Loading branch information
bishabosha authored Dec 17, 2021
2 parents 351cb05 + cbff98d commit b3ab102
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 22 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,7 @@ object SymDenotations {
def hasDefaultParams(using Context): Boolean =
if ctx.erasedTypes then false
else if is(HasDefaultParams) then true
else if is(NoDefaultParams) then false
else if is(NoDefaultParams) || !is(Method) then false
else
val result =
rawParamss.nestedExists(_.is(HasDefault))
Expand Down
59 changes: 38 additions & 21 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,17 @@ class Namer { typer: Typer =>
else Yes
}

def foreachDefaultGetterOf(sym: TermSymbol, op: TermSymbol => Unit): Unit =
var n = 0
for params <- sym.paramSymss; param <- params do
if param.isTerm then
if param.is(HasDefault) then
val getterName = DefaultGetterName(sym.name, n)
val getter = path.tpe.member(DefaultGetterName(sym.name, n)).symbol
assert(getter.exists, i"$path does not have a default getter named $getterName")
op(getter.asTerm)
n += 1

/** Add a forwarder with name `alias` or its type name equivalent to `mbr`,
* provided `mbr` is accessible and of the right implicit/non-implicit kind.
*/
Expand All @@ -1118,6 +1129,7 @@ class Namer { typer: Typer =>

if canForward(mbr) == CanForward.Yes then
val sym = mbr.symbol
val hasDefaults = sym.hasDefaultParams // compute here to ensure HasDefaultParams and NoDefaultParams flags are set
val forwarder =
if mbr.isType then
val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false, span)
Expand All @@ -1142,28 +1154,29 @@ class Namer { typer: Typer =>
(StableRealizable, ExprType(path.tpe.select(sym)))
else
(EmptyFlags, mbr.info.ensureMethodic)
var mbrFlags = Exported | Method | Final | maybeStable | sym.flags & RetainedExportFlags
var flagMask = RetainedExportFlags
if sym.isTerm then flagMask |= HasDefaultParams | NoDefaultParams
var mbrFlags = Exported | Method | Final | maybeStable | sym.flags & flagMask
if sym.is(ExtensionMethod) then mbrFlags |= ExtensionMethod
val forwarderName = checkNoConflict(alias, isPrivate = false, span)
newSymbol(cls, forwarderName, mbrFlags, mbrInfo, coord = span)

forwarder.info = avoidPrivateLeaks(forwarder)
forwarder.addAnnotations(sym.annotations)

val forwarderDef =
if (forwarder.isType) tpd.TypeDef(forwarder.asType)
else {
import tpd._
val ref = path.select(sym.asTerm)
val ddef = tpd.DefDef(forwarder.asTerm, prefss =>
ref.appliedToArgss(adaptForwarderParams(Nil, sym.info, prefss))
)
if forwarder.isInlineMethod then
PrepareInlineable.registerInlineInfo(forwarder, ddef.rhs)
ddef
}
forwarder.addAnnotations(sym.annotations.filterConserve(_.symbol != defn.BodyAnnot))

buf += forwarderDef.withSpan(span)
if forwarder.isType then
buf += tpd.TypeDef(forwarder.asType).withSpan(span)
else
import tpd._
val ref = path.select(sym.asTerm)
val ddef = tpd.DefDef(forwarder.asTerm, prefss =>
ref.appliedToArgss(adaptForwarderParams(Nil, sym.info, prefss)))
if forwarder.isInlineMethod then
PrepareInlineable.registerInlineInfo(forwarder, ddef.rhs)
buf += ddef.withSpan(span)
if hasDefaults then
foreachDefaultGetterOf(sym.asTerm,
getter => addForwarder(getter.name.asTermName, getter, span))
end addForwarder

def addForwardersNamed(name: TermName, alias: TermName, span: Span): Unit =
Expand All @@ -1187,11 +1200,15 @@ class Namer { typer: Typer =>
def isCaseClassSynthesized(mbr: Symbol) =
fromCaseClass && defn.caseClassSynthesized.contains(mbr)
for mbr <- path.tpe.membersBasedOnFlags(required = EmptyFlags, excluded = PrivateOrSynthetic) do
if !mbr.symbol.isSuperAccessor && !isCaseClassSynthesized(mbr.symbol) then
// Scala 2 superaccessors have neither Synthetic nor Artfact set, so we
// need to filter them out here (by contrast, Scala 3 superaccessors are Artifacts)
// Symbols from base traits of case classes that will get synthesized implementations
// at PostTyper are also excluded.
if !mbr.symbol.isSuperAccessor
// Scala 2 superaccessors have neither Synthetic nor Artfact set, so we
// need to filter them out here (by contrast, Scala 3 superaccessors are Artifacts)
// Symbols from base traits of case classes that will get synthesized implementations
// at PostTyper are also excluded.
&& !isCaseClassSynthesized(mbr.symbol)
&& !mbr.symbol.name.is(DefaultGetterName)
// default getters are exported with the members they belong to
then
val alias = mbr.name.toTermName
if mbr.symbol.is(Given) then
if !seen.contains(alias) && mbr.matchesImportBound(givenBound) then
Expand Down
7 changes: 7 additions & 0 deletions tests/run/i14020.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Hello you
Hello John
Hello you
Hello you
Hello John
Hello you
bark: Woof!
39 changes: 39 additions & 0 deletions tests/run/i14020.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
class A:
def greeting(name: String = "you") = s"Hello $name"

class A2:
inline def greeting(name: String = "you") = s"Hello $name"

class B:
val a = A()
export a.*

class C:
val a = A2()
export a.greeting

@main def Test =
val b = B()

println(b.a.greeting()) // works
println(b.greeting("John")) // works
println(b.greeting()) // nope !

val c = C()

println(c.a.greeting()) // works
println(c.greeting("John")) // works
println(c.greeting()) // nope !

val w = Wolf()
import w.given

println(summon[String]) // error: I found: w.bark(/* missing */summon[String])


class Dog:
given bark(using msg: String = "Woof!"): String = s"bark: $msg"

class Wolf:
private val dog = Dog()
export dog.given // needs to be `export dog.{given, *}` to export the default arguments

0 comments on commit b3ab102

Please sign in to comment.