Skip to content

Commit 235fdeb

Browse files
committed
Allow new conversion only for paths
Also, some refactorings to shorten and simplify
1 parent 9debedd commit 235fdeb

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
@@ -814,16 +814,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
814814
tstate.commit()
815815
result
816816
}
817-
fn match {
818-
case Ident(name) =>
819-
tryNewWithType(cpy.Ident(fn)(name.toTypeName), pt, fallBack)
820-
case Select(qual, name) =>
821-
tryNewWithType(cpy.Select(fn)(qual, name.toTypeName), pt, fallBack)
822-
// TODO: try to keep as much as possible from typed `qual` in order to avoid
823-
// combinatorial explosion
824-
case _ =>
825-
fallBack
826-
}
817+
if (untpd.isPath(fn)) tryNew(untpd)(fn, pt, fallBack)
818+
else fallBack
827819
}
828820

829821
/** 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)
@@ -2234,21 +2234,39 @@ class Typer extends Namer
22342234

22352235
/** Try to rename `tpt` to a type `T` and typecheck `new T` with given expected type `pt`.
22362236
*/
2237-
def tryNewWithType(tpt: untpd.Tree, pt: Type, fallBack: => Tree)(implicit ctx: Context): Tree =
2238-
tryEither { implicit ctx =>
2239-
val tycon = typed(tpt)
2240-
if (ctx.reporter.hasErrors)
2241-
EmptyTree // signal that we should return the error in fallBack
2242-
else
2243-
typed(untpd.Select(untpd.New(untpd.TypedSplice(tycon)), nme.CONSTRUCTOR), pt)
2244-
} { (nu, nuState) =>
2245-
if (nu.isEmpty) fallBack
2246-
else {
2247-
// we found a type constructor, signal the error in its application instead of the original one
2248-
nuState.commit()
2249-
nu
2237+
2238+
def tryNew[T >: Untyped <: Type]
2239+
(treesInst: Instance[T])(tree: Trees.Tree[T], pt: Type, fallBack: => Tree)(implicit ctx: Context): Tree = {
2240+
2241+
def tryWithType(tpt: untpd.Tree): Tree =
2242+
tryEither { implicit ctx =>
2243+
val tycon = typed(tpt)
2244+
if (ctx.reporter.hasErrors)
2245+
EmptyTree // signal that we should return the error in fallBack
2246+
else
2247+
typed(untpd.Select(untpd.New(untpd.TypedSplice(tycon)), nme.CONSTRUCTOR), pt)
2248+
} { (nu, nuState) =>
2249+
if (nu.isEmpty) fallBack
2250+
else {
2251+
// we found a type constructor, signal the error in its application instead of the original one
2252+
nuState.commit()
2253+
nu
2254+
}
22502255
}
2256+
2257+
tree match {
2258+
case Ident(name) =>
2259+
tryWithType(cpy.Ident(tree)(name.toTypeName))
2260+
case Select(qual, name) =>
2261+
val qual1 = treesInst match {
2262+
case `tpd` => untpd.TypedSplice(qual)
2263+
case `untpd` => qual
2264+
}
2265+
tryWithType(cpy.Select(tree)(qual1, name.toTypeName))
2266+
case _ =>
2267+
fallBack
22512268
}
2269+
}
22522270

22532271
/** Potentially add apply node or implicit conversions. Before trying either,
22542272
* if the function is applied to an empty parameter list (), we try
@@ -2290,20 +2308,9 @@ class Typer extends Namer
22902308
else try adapt(simplify(sel, pt1, locked), pt1, locked) finally sel.removeAttachment(InsertedApply)
22912309
}
22922310

2293-
def tryNew(fallBack: => Tree): Tree = {
2294-
tree match {
2295-
case Ident(name) =>
2296-
tryNewWithType(cpy.Ident(tree)(name.toTypeName), pt, fallBack)
2297-
case Select(qual, name) =>
2298-
tryNewWithType(cpy.Select(tree)(untpd.TypedSplice(qual), name.toTypeName), pt, fallBack)
2299-
case _ =>
2300-
fallBack
2301-
}
2302-
}
2303-
23042311
def tryImplicit(fallBack: => Tree) =
23052312
tryInsertImplicitOnQualifier(tree, pt.withContext(ctx), locked)
2306-
.getOrElse(tryNew(fallBack))
2313+
.getOrElse(tryNew(tpd)(tree, pt, fallBack))
23072314

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

0 commit comments

Comments
 (0)