Skip to content

Commit 7cf15bc

Browse files
committed
Fallback from A to new A
1 parent 54441d6 commit 7cf15bc

File tree

2 files changed

+99
-1
lines changed

2 files changed

+99
-1
lines changed

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

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2272,8 +2272,37 @@ class Typer extends Namer
22722272
else try adapt(simplify(sel, pt1, locked), pt1, locked) finally sel.removeAttachment(InsertedApply)
22732273
}
22742274

2275+
def tryNew(fallBack: => Tree): Tree = {
2276+
2277+
def tryNewWithType(tpt: untpd.Tree): Tree =
2278+
tryEither { implicit ctx =>
2279+
val tycon = typed(tpt.withSpan(tree.span))
2280+
if (ctx.reporter.hasErrors)
2281+
EmptyTree // signal that we should return the error in fallBack
2282+
else
2283+
typed(untpd.Select(untpd.New(untpd.TypedSplice(tycon)), nme.CONSTRUCTOR), pt)
2284+
} { (nu, nuState) =>
2285+
if (nu.isEmpty) fallBack
2286+
else {
2287+
// we found a type constructor, signal the error in its application instead of the original one
2288+
nuState.commit()
2289+
nu
2290+
}
2291+
}
2292+
2293+
tree match {
2294+
case Ident(name) =>
2295+
tryNewWithType(untpd.Ident(name.toTypeName))
2296+
case Select(qual, name) =>
2297+
tryNewWithType(untpd.Select(untpd.TypedSplice(qual), name.toTypeName))
2298+
case _ =>
2299+
fallBack
2300+
}
2301+
}
2302+
22752303
def tryImplicit(fallBack: => Tree) =
2276-
tryInsertImplicitOnQualifier(tree, pt.withContext(ctx), locked).getOrElse(fallBack)
2304+
tryInsertImplicitOnQualifier(tree, pt.withContext(ctx), locked)
2305+
.getOrElse(tryNew(fallBack))
22772306

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

tests/run/creator-applys.scala

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
object Test extends App {
2+
class A {
3+
def run = "A"
4+
}
5+
object A
6+
class B[T] {
7+
def run = "B"
8+
}
9+
object B
10+
class C[S, T](x: S, y: T) {
11+
def run = s"C $x $y"
12+
}
13+
object C
14+
15+
val x1 = Test.A()
16+
assert(x1.run == "A")
17+
18+
val x2 = B[String]()
19+
assert(x2.run == "B")
20+
21+
val x3: B[String] = B()
22+
assert(x3.run == "B")
23+
24+
val x4: C[String, Int] = C("a", 1)
25+
assert(x4.run == "C a 1")
26+
27+
val x5 = C[String, Int]("a", 1)
28+
assert(x5.run == "C a 1")
29+
30+
val x6 = C("a", 1)
31+
assert((x6: C[String, Int]).run == "C a 1")
32+
/*
33+
val x7 = C[S = String]("a", 1)
34+
assert((x7: C[String, Int]).run == "C a 1")
35+
36+
val x8 = C[T = Int]("a", 1)
37+
assert((x8: C[String, Int]).run == "C a 1")
38+
*/
39+
}
40+
/*
41+
object Test2 {
42+
class A {
43+
def run = "A"
44+
}
45+
class B[T] {
46+
def run = "B"
47+
}
48+
class C[S, T](x: S, y: T) {
49+
def run = s"C $x $y"
50+
}
51+
52+
val x1 = Test.A()
53+
assert(x1.run == "A")
54+
55+
val x2 = B[String]()
56+
assert(x2.run == "B")
57+
58+
val x3: B[String] = B()
59+
assert(x3.run == "B")
60+
61+
val x4: C[String, Int] = C("a", 1)
62+
assert(x4.run == "C a 1")
63+
64+
val x5 = C[String, Int]("a", 1)
65+
assert(x5.run == "C a 1")
66+
67+
val x6 = C("a", 1)
68+
assert((x6: C[String, Int]).run == "C a 1")
69+
}*/

0 commit comments

Comments
 (0)