Skip to content

Commit 1e0ebc5

Browse files
committed
Allow new conversion only for paths
Also, some refactorings to shorten and simplify
1 parent 220703b commit 1e0ebc5

File tree

4 files changed

+60
-52
lines changed

4 files changed

+60
-52
lines changed

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
106106
case _ => Nil
107107
}
108108

109+
/** Is tree a path? */
110+
def isPath(tree: Tree): Boolean = unsplice(tree) match {
111+
case Ident(_) | This(_) | Super(_, _) => true
112+
case Select(qual, _) => isPath(qual)
113+
case _ => false
114+
}
115+
109116
/** Is tree a self constructor call this(...)? I.e. a call to a constructor of the
110117
* same object?
111118
*/

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

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -791,16 +791,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
791791
tstate.commit()
792792
result
793793
}
794-
fn match {
795-
case Ident(name) =>
796-
tryNewWithType(cpy.Ident(fn)(name.toTypeName), pt, fallBack)
797-
case Select(qual, name) =>
798-
tryNewWithType(cpy.Select(fn)(qual, name.toTypeName), pt, fallBack)
799-
// TODO: try to keep as much as possible from typed `qual` in order to avoid
800-
// combinatorial explosion
801-
case _ =>
802-
fallBack
803-
}
794+
if (untpd.isPath(fn)) tryNew(untpd)(fn, pt, fallBack)
795+
else fallBack
804796
}
805797

806798
/** Typecheck application. Result could be an `Apply` node,

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import Symbols._
88
import StdNames._
99
import Decorators._
1010
import typer.ProtoTypes._
11-
import ast.{tpd, untpd}
11+
import ast.{tpd, untpd, Trees}
12+
import Trees._
1213
import scala.util.control.NonFatal
1314
import util.Spans.Span
1415

@@ -96,7 +97,8 @@ class ReTyper extends Typer with ReChecking {
9697
override def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType, locked: TypeVars)(fallBack: => Tree)(implicit ctx: Context): Tree =
9798
fallBack
9899

99-
override def tryNewWithType(tpt: untpd.Tree, pt: Type, fallBack: => Tree)(implicit ctx: Context): Tree = fallBack
100+
override def tryNew[T >: Untyped <: Type]
101+
(treesInst: Instance[T])(tree: Trees.Tree[T], pt: Type, fallBack: => Tree)(implicit ctx: Context): Tree = fallBack
100102

101103
override def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(implicit ctx: Context): Unit = ()
102104

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

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -441,25 +441,25 @@ class Typer extends Namer
441441
tree
442442
}
443443

444-
private def typedSelect(tree: untpd.Select, pt: Type, qual: Tree)(implicit ctx: Context): Select =
445-
Applications.handleMeta(checkValue(assignType(cpy.Select(tree)(qual, tree.name), qual), pt))
444+
def typedSelect(tree: untpd.Select, pt: Type, qual: Tree)(implicit ctx: Context): Tree = qual match {
445+
case qual @ IntegratedTypeArgs(app) =>
446+
pt.revealIgnored match {
447+
case _: PolyProto => qual // keep the IntegratedTypeArgs to strip at next typedTypeApply
448+
case _ => app
449+
}
450+
case qual =>
451+
if (tree.name.isTypeName) checkStable(qual.tpe, qual.sourcePos)
452+
val select = Applications.handleMeta(
453+
checkValue(assignType(cpy.Select(tree)(qual, tree.name), qual), pt))
454+
if (select.tpe ne TryDynamicCallType) ConstFold(checkStableIdentPattern(select, pt))
455+
else if (pt.isInstanceOf[FunOrPolyProto] || pt == AssignProto) select
456+
else typedDynamicSelect(tree, Nil, pt)
457+
}
446458

447459
def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = track("typedSelect") {
448460

449461
def typeSelectOnTerm(implicit ctx: Context): Tree =
450-
typedExpr(tree.qualifier, selectionProto(tree.name, pt, this)) match {
451-
case qual1 @ IntegratedTypeArgs(app) =>
452-
pt.revealIgnored match {
453-
case _: PolyProto => qual1 // keep the IntegratedTypeArgs to strip at next typedTypeApply
454-
case _ => app
455-
}
456-
case qual1 =>
457-
if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.sourcePos)
458-
val select = typedSelect(tree, pt, qual1)
459-
if (select.tpe ne TryDynamicCallType) ConstFold(checkStableIdentPattern(select, pt))
460-
else if (pt.isInstanceOf[FunOrPolyProto] || pt == AssignProto) select
461-
else typedDynamicSelect(tree, Nil, pt)
462-
}
462+
typedSelect(tree, pt, typedExpr(tree.qualifier, selectionProto(tree.name, pt, this)))
463463

464464
def typeSelectOnType(qual: untpd.Tree)(implicit ctx: Context) =
465465
typedSelect(untpd.cpy.Select(tree)(qual, tree.name.toTypeName), pt)
@@ -2221,21 +2221,39 @@ class Typer extends Namer
22212221

22222222
/** Try to rename `tpt` to a type `T` and typecheck `new T` with given expected type `pt`.
22232223
*/
2224-
def tryNewWithType(tpt: untpd.Tree, pt: Type, fallBack: => Tree)(implicit ctx: Context): Tree =
2225-
tryEither { implicit ctx =>
2226-
val tycon = typed(tpt)
2227-
if (ctx.reporter.hasErrors)
2228-
EmptyTree // signal that we should return the error in fallBack
2229-
else
2230-
typed(untpd.Select(untpd.New(untpd.TypedSplice(tycon)), nme.CONSTRUCTOR), pt)
2231-
} { (nu, nuState) =>
2232-
if (nu.isEmpty) fallBack
2233-
else {
2234-
// we found a type constructor, signal the error in its application instead of the original one
2235-
nuState.commit()
2236-
nu
2224+
2225+
def tryNew[T >: Untyped <: Type]
2226+
(treesInst: Instance[T])(tree: Trees.Tree[T], pt: Type, fallBack: => Tree)(implicit ctx: Context): Tree = {
2227+
2228+
def tryWithType(tpt: untpd.Tree): Tree =
2229+
tryEither { implicit ctx =>
2230+
val tycon = typed(tpt)
2231+
if (ctx.reporter.hasErrors)
2232+
EmptyTree // signal that we should return the error in fallBack
2233+
else
2234+
typed(untpd.Select(untpd.New(untpd.TypedSplice(tycon)), nme.CONSTRUCTOR), pt)
2235+
} { (nu, nuState) =>
2236+
if (nu.isEmpty) fallBack
2237+
else {
2238+
// we found a type constructor, signal the error in its application instead of the original one
2239+
nuState.commit()
2240+
nu
2241+
}
22372242
}
2243+
2244+
tree match {
2245+
case Ident(name) =>
2246+
tryWithType(cpy.Ident(tree)(name.toTypeName))
2247+
case Select(qual, name) =>
2248+
val qual1 = treesInst match {
2249+
case `tpd` => untpd.TypedSplice(qual)
2250+
case `untpd` => qual
2251+
}
2252+
tryWithType(cpy.Select(tree)(qual1, name.toTypeName))
2253+
case _ =>
2254+
fallBack
22382255
}
2256+
}
22392257

22402258
/** Potentially add apply node or implicit conversions. Before trying either,
22412259
* if the function is applied to an empty parameter list (), we try
@@ -2277,20 +2295,9 @@ class Typer extends Namer
22772295
else try adapt(simplify(sel, pt1, locked), pt1, locked) finally sel.removeAttachment(InsertedApply)
22782296
}
22792297

2280-
def tryNew(fallBack: => Tree): Tree = {
2281-
tree match {
2282-
case Ident(name) =>
2283-
tryNewWithType(cpy.Ident(tree)(name.toTypeName), pt, fallBack)
2284-
case Select(qual, name) =>
2285-
tryNewWithType(cpy.Select(tree)(untpd.TypedSplice(qual), name.toTypeName), pt, fallBack)
2286-
case _ =>
2287-
fallBack
2288-
}
2289-
}
2290-
22912298
def tryImplicit(fallBack: => Tree) =
22922299
tryInsertImplicitOnQualifier(tree, pt.withContext(ctx), locked)
2293-
.getOrElse(tryNew(fallBack))
2300+
.getOrElse(tryNew(tpd)(tree, pt, fallBack))
22942301

22952302
if (ctx.mode.is(Mode.SynthesizeExtMethodReceiver))
22962303
// Suppress insertion of apply or implicit conversion on extension method receiver

0 commit comments

Comments
 (0)