Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -513,11 +513,11 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
ctx.typer.checkClassType(tpe, tree.srcPos,
traitReq = false, stablePrefixReq = stablePrefixReq,
refinementOK = Feature.enabled(Feature.modularity))
checkClassType(tree.tpe, true)
checkClassType(tree.tpe, stablePrefixReq = true)
if !nu.tpe.isLambdaSub then
// Check the constructor type as well; it could be an illegal singleton type
// which would not be reflected as `tree.tpe`
checkClassType(nu.tpe, false)
checkClassType(nu.tpe, stablePrefixReq = false)
Checking.checkInstantiable(tree.tpe, nu.tpe, nu.srcPos)
withNoCheckNews(nu :: Nil)(app1)
case _ =>
Expand Down
20 changes: 14 additions & 6 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import ast.desugar, ast.desugar.*
import ProtoTypes.*
import util.Spans.*
import util.Property
import collection.mutable
import collection.mutable, mutable.ListBuffer
import tpd.tpes
import Variances.alwaysInvariant
import config.{Config, Feature}
Expand Down Expand Up @@ -1183,7 +1183,7 @@ class Namer { typer: Typer =>
* extension method.
*/
private def exportForwarders(exp: Export, pathMethod: Symbol)(using Context): List[tpd.MemberDef] =
val buf = new mutable.ListBuffer[tpd.MemberDef]
val buf = ListBuffer.empty[tpd.MemberDef]
val Export(expr, selectors) = exp
if expr.isEmpty then
report.error(em"Export selector must have prefix and `.`", exp.srcPos)
Expand Down Expand Up @@ -1509,12 +1509,17 @@ class Namer { typer: Typer =>
forwarders
end exportForwarders

/** Add forwarders as required by the export statements in this class */
private def processExports(using Context): Unit =
/** Add forwarders as required by the export statements in this class.
* @return true if forwarders were added
*/
private def processExports(using Context): Boolean =

var exported = false

def processExport(exp: Export, pathSym: Symbol)(using Context): Unit =
for forwarder <- exportForwarders(exp, pathSym) do
forwarder.symbol.entered
exported = true

def exportPathSym(path: Tree, ext: ExtMethods)(using Context): Symbol =
def fail(msg: String): Symbol =
Expand Down Expand Up @@ -1557,6 +1562,8 @@ class Namer { typer: Typer =>
// import contexts for nothing.
if hasExport(rest) then
process(rest)
// was a forwarder entered for an export
exported
end processExports

/** Ensure constructor is completed so that any parameter accessors
Expand Down Expand Up @@ -1778,8 +1785,9 @@ class Namer { typer: Typer =>
cls.setNoInitsFlags(parentsKind(parents), untpd.bodyKind(rest))
cls.setStableConstructor()
enterParentRefinementSyms(parentRefinements.toList)
processExports(using localCtx)
addConstructorProxies(cls)
if processExports(using localCtx) then
addConstructorProxies(cls)
cleanup()
}
}
Expand All @@ -1788,7 +1796,7 @@ class Namer { typer: Typer =>
private enum CanForward:
case Yes
case No(whyNot: String)
case Skip // for members that have never forwarders
case Skip // for members that never have forwarders

class SuspendCompleter extends LazyType, SymbolLoaders.SecondCompleter {

Expand Down
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5055,7 +5055,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
if qual.symbol.isAllOf(SyntheticMethod | Exported) then
qual.symbol.owner.info.memberBasedOnFlags(qual.symbol.name.toTypeName, required = Exported)
else NoDenotation
if exported.exists then exported.symbol.typeRef
if exported.exists then
qual.tpe match
case tp: NamedType =>
exported.symbol.typeRef.asSeenFrom(tp.prefix, exported.symbol.owner)
case _ =>
exported.symbol.typeRef
else ctorResultType.underlyingClassRef(refinementOK = Feature.enabled(modularity))
typed(
untpd.Select(
Expand Down
8 changes: 8 additions & 0 deletions tests/neg/i24879.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class C:
class D

class Baz:
val c = C()
export c.*

@main def Test = Baz().D() // error (Baz#c : C) is not a valid class prefix, since it is not an immutable path
44 changes: 44 additions & 0 deletions tests/pos/i15944.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
object Foo:
class Wrap(a: String):
def wow = s"$a - WOW!"
extension (s: String)
//private def wrap: Wrap = Wrap(s) // works
private def wrap = Wrap(s) // Not found: Wrap
export wrap.* // comment this line and it works

class Bar:
class Wrap(a: String):
def wow = s"$a - WOW!"
val wrap = Wrap("string") // Not found: Wrap
export wrap.*

object WorkingAlternative:
object Foo:
class Wrap(a: String):
def wow = s"$a - WOW!"

object Bar:
import Foo.Wrap
extension (s: String)
private def wrap = Wrap(s) // works when not a member of enclosing element
export wrap.*

class C:
class D

class Baz:
val c = new C
export c.*

class Bah:
val c = new C
type D = c.D

@main def Test =
val bah = Bah()
println:
new bah.D

val baz = Baz()
println:
baz.D()
12 changes: 12 additions & 0 deletions tests/warn/i24562.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,15 @@ package aliased:
import Wrap.* // warn! not a naming error because a benign alias
val localBar = Bar() // not Wrap.Bar!
val localNewBar = new Bar

package i24879:
class C:
class D

class Baz:
val c = new C
export c.*

def test =
val baz = Baz()
baz.D() // no warn and no crash