Skip to content

Commit 96be092

Browse files
authored
Preserve select of exported member in newExpr (#24570)
Fixes #24562 by improving the fidelity of the rewrite of constructor proxy call to `new`, just for references to exported members.
2 parents a9b1e15 + 7cfdda5 commit 96be092

File tree

4 files changed

+49
-12
lines changed

4 files changed

+49
-12
lines changed

compiler/src/dotty/tools/dotc/core/NamerOps.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,9 @@ object NamerOps:
223223
companion
224224

225225
def typeConstructorCompanion(tsym: Symbol, prefix: Type, proxy: Symbol)(using Context): TermSymbol =
226-
newSymbol(tsym.owner, tsym.name.toTermName,
227-
ConstructorCompanionFlags | StableRealizable | Method, ExprType(prefix.select(proxy)), coord = tsym.coord)
226+
inline def core = ConstructorCompanionFlags | StableRealizable | Method
227+
inline def flags = if tsym.is(Exported) then core | Exported else core
228+
newSymbol(tsym.owner, tsym.name.toTermName, flags, ExprType(prefix.select(proxy)), coord = tsym.coord)
228229

229230
/** Add all necessary constructor proxy symbols for members of class `cls`. This means:
230231
*

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,8 +1262,8 @@ class Namer { typer: Typer =>
12621262
n += 1
12631263

12641264
/** Add a forwarder with name `alias` or its type name equivalent to `mbr`,
1265-
* provided `mbr` is accessible and of the right implicit/non-implicit kind.
1266-
*/
1265+
* provided `mbr` is accessible and of the right implicit/non-implicit kind.
1266+
*/
12671267
def addForwarder(alias: TermName, mbr: SingleDenotation, span: Span): Unit =
12681268

12691269
def adaptForwarderParams(acc: List[List[tpd.Tree]], tp: Type, prefss: List[List[tpd.Tree]])

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,10 +1258,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
12581258
pt)
12591259
case _ =>
12601260
var tpt1 = typedType(tree.tpt)
1261-
val tsym = tpt1.tpe.underlyingClassRef(refinementOK = false).typeSymbol
12621261
if ctx.mode.isQuotedPattern && tpt1.tpe.typeSymbol.isAllOf(Synthetic | Case) then
12631262
val errorTp = errorType(CannotInstantiateQuotedTypeVar(tpt1.tpe.typeSymbol), tpt1.srcPos)
12641263
return cpy.New(tree)(tpt1).withType(errorTp)
1264+
val tsym = tpt1.tpe.underlyingClassRef(refinementOK = false).typeSymbol
12651265
if tsym.is(Package) then
12661266
report.error(em"$tsym cannot be instantiated", tpt1.srcPos)
12671267
tpt1 = tpt1.withType(ensureAccessible(tpt1.tpe, superAccess = false, tpt1.srcPos))
@@ -1271,7 +1271,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
12711271
report.error(WildcardOnTypeArgumentNotAllowedOnNew(), targ.srcPos)
12721272
case _ =>
12731273
}
1274-
12751274
assignType(cpy.New(tree)(tpt1), tpt1)
12761275
}
12771276

@@ -5025,7 +5024,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
50255024
case _ =>
50265025
}
50275026

5028-
/** If `tree` is a constructor proxy reference, convert it to a `new` expression,
5027+
/** If `tree` is a constructor proxy reference, convert it to a `new` expression;
5028+
* check if it is a reference to an exported type/companion pair;
50295029
* otherwise return EmptyTree.
50305030
*/
50315031
def newExpr(tree: Tree): Tree =
@@ -5041,13 +5041,19 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
50415041
cpy.Ident(qual)(qual.symbol.name.sourceModuleName.toTypeName)
50425042
case _ =>
50435043
errorTree(tree, em"cannot convert from $tree to an instance creation expression")
5044-
val tycon = ctorResultType.underlyingClassRef(refinementOK = Feature.enabled(modularity))
5044+
val tycon =
5045+
val exported =
5046+
if qual.symbol.isAllOf(SyntheticMethod | Exported) then
5047+
qual.symbol.owner.info.memberBasedOnFlags(qual.symbol.name.toTypeName, required = Exported)
5048+
else NoDenotation
5049+
if exported.exists then exported.symbol.typeRef
5050+
else ctorResultType.underlyingClassRef(refinementOK = Feature.enabled(modularity))
50455051
typed(
50465052
untpd.Select(
50475053
untpd.New(untpd.TypedSplice(tpt.withType(tycon))),
50485054
nme.CONSTRUCTOR),
5049-
pt)
5050-
.showing(i"convert creator $tree -> $result", typr)
5055+
pt
5056+
).showing(i"convert creator $tree -> $result", typr)
50515057

50525058
/** If `tree` is a constructor proxy reference, return the type it constructs,
50535059
* otherwise return NoType.
@@ -5066,7 +5072,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
50665072
// begin adapt1
50675073
tree match {
50685074
case _: MemberDef | _: PackageDef | _: Import | _: WithoutTypeOrPos[?] | _: Closure => tree
5069-
case _ => tree.tpe.widen match {
5075+
case _ =>
5076+
tree.tpe.widen match
50705077
case tp: FlexType =>
50715078
ensureReported(tp)
50725079
tree
@@ -5128,7 +5135,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
51285135
if (ctx.mode is Mode.Type) adaptType(tree.tpe)
51295136
else adaptNoArgs(wtp)
51305137
}
5131-
}
51325138
}
51335139
}
51345140

tests/warn/i24562.scala

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//> using options -Wunused:imports
2+
3+
package util:
4+
class Random(s: String):
5+
def this() = this("")
6+
7+
package bar:
8+
export util.Random
9+
10+
package foo:
11+
import bar.Random
12+
def test = Random(null)
13+
14+
package baz:
15+
import bar.*
16+
def test = Random(null)
17+
18+
// cf tests/pos/i12299a.scala
19+
package aliased:
20+
object Outer:
21+
22+
object Wrap:
23+
export Outer.Bar
24+
25+
class Bar
26+
27+
def test =
28+
import Wrap.* // warn! not a naming error because a benign alias
29+
val localBar = Bar() // not Wrap.Bar!
30+
val localNewBar = new Bar

0 commit comments

Comments
 (0)