Skip to content

Commit b9fd3f7

Browse files
committed
Merge pull request scala#1343 from namin/dynamic-sig
Fixes SI-6354: improved error messages for Dynamic signature mismatches.
2 parents eb49e81 + 08e5fd2 commit b9fd3f7

File tree

5 files changed

+95
-5
lines changed

5 files changed

+95
-5
lines changed

src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala

+7
Original file line numberDiff line numberDiff line change
@@ -515,9 +515,16 @@ trait ContextErrors {
515515
def ApplyWithoutArgsError(tree: Tree, fun: Tree) =
516516
NormalTypeError(tree, fun.tpe+" does not take parameters")
517517

518+
// Dynamic
518519
def DynamicVarArgUnsupported(tree: Tree, name: String) =
519520
issueNormalTypeError(tree, name+ " does not support passing a vararg parameter")
520521

522+
def DynamicRewriteError(tree: Tree, err: AbsTypeError) = {
523+
issueTypeError(PosAndMsgTypeError(err.errPos, err.errMsg +
524+
s"\nerror after rewriting to $tree\npossible cause: maybe a wrong Dynamic method signature?"))
525+
setError(tree)
526+
}
527+
521528
//checkClassType
522529
def TypeNotAStablePrefixError(tpt: Tree, pre: Type) = {
523530
issueNormalTypeError(tpt, "type "+pre+" is not a stable prefix")

src/compiler/scala/tools/nsc/typechecker/Typers.scala

+14-3
Original file line numberDiff line numberDiff line change
@@ -3806,7 +3806,8 @@ trait Typers extends Modes with Adaptations with Tags {
38063806
case AssignOrNamedArg(Ident(name), rhs) => gen.mkTuple(List(CODE.LIT(name.toString), rhs))
38073807
case _ => gen.mkTuple(List(CODE.LIT(""), arg))
38083808
}
3809-
typed(treeCopy.Apply(orig, fun, args map argToBinding), mode, pt)
3809+
val t = treeCopy.Apply(orig, fun, args map argToBinding)
3810+
wrapErrors(t, _.typed(t, mode, pt))
38103811
}
38113812

38123813
/** Translate selection that does not typecheck according to the normal rules into a selectDynamic/applyDynamic.
@@ -3874,6 +3875,13 @@ trait Typers extends Modes with Adaptations with Tags {
38743875
atPos(qual.pos)(Apply(tappSel, List(Literal(Constant(name.decode)))))
38753876
}
38763877
}
3878+
3879+
def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = {
3880+
silent(typeTree) match {
3881+
case SilentResultValue(r) => r
3882+
case SilentTypeError(err) => DynamicRewriteError(tree, err)
3883+
}
3884+
}
38773885
}
38783886

38793887
@inline final def deindentTyping() = context.typingIndentLevel -= 2
@@ -4067,7 +4075,8 @@ trait Typers extends Modes with Adaptations with Tags {
40674075
}
40684076
else if(dyna.isDynamicallyUpdatable(lhs1)) {
40694077
val rhs1 = typed(rhs, EXPRmode | BYVALmode, WildcardType)
4070-
typed1(Apply(lhs1, List(rhs1)), mode, pt)
4078+
val t = Apply(lhs1, List(rhs1))
4079+
dyna.wrapErrors(t, _.typed1(t, mode, pt))
40714080
}
40724081
else fail()
40734082
}
@@ -4535,7 +4544,9 @@ trait Typers extends Modes with Adaptations with Tags {
45354544
* @return ...
45364545
*/
45374546
def typedSelect(tree: Tree, qual: Tree, name: Name): Tree = {
4538-
def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map (typed1(_, mode, pt))
4547+
def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map { t =>
4548+
dyna.wrapErrors(t, (_.typed1(t, mode, pt)))
4549+
}
45394550

45404551
val sym = tree.symbol orElse member(qual, name) orElse {
45414552
// symbol not found? --> try to convert implicitly to a type that does have the required

test/files/neg/applydynamic_sip.check

+49-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,52 @@ applydynamic_sip.scala:8: error: applyDynamicNamed does not support passing a va
77
applydynamic_sip.scala:9: error: applyDynamicNamed does not support passing a vararg parameter
88
qual.sel(arg, arg2 = "a2", a2: _*)
99
^
10-
three errors found
10+
applydynamic_sip.scala:18: error: type mismatch;
11+
found : String("sel")
12+
required: Int
13+
error after rewriting to Test.this.bad1.selectDynamic("sel")
14+
possible cause: maybe a wrong Dynamic method signature?
15+
bad1.sel
16+
^
17+
applydynamic_sip.scala:19: error: type mismatch;
18+
found : String("sel")
19+
required: Int
20+
error after rewriting to Test.this.bad1.applyDynamic("sel")
21+
possible cause: maybe a wrong Dynamic method signature?
22+
bad1.sel(1)
23+
^
24+
applydynamic_sip.scala:20: error: type mismatch;
25+
found : String("sel")
26+
required: Int
27+
error after rewriting to Test.this.bad1.applyDynamicNamed("sel")
28+
possible cause: maybe a wrong Dynamic method signature?
29+
bad1.sel(a = 1)
30+
^
31+
applydynamic_sip.scala:21: error: type mismatch;
32+
found : String("sel")
33+
required: Int
34+
error after rewriting to Test.this.bad1.updateDynamic("sel")
35+
possible cause: maybe a wrong Dynamic method signature?
36+
bad1.sel = 1
37+
^
38+
applydynamic_sip.scala:29: error: Int does not take parameters
39+
error after rewriting to Test.this.bad2.selectDynamic("sel")
40+
possible cause: maybe a wrong Dynamic method signature?
41+
bad2.sel
42+
^
43+
applydynamic_sip.scala:30: error: Int does not take parameters
44+
error after rewriting to Test.this.bad2.applyDynamic("sel")
45+
possible cause: maybe a wrong Dynamic method signature?
46+
bad2.sel(1)
47+
^
48+
applydynamic_sip.scala:31: error: Int does not take parameters
49+
error after rewriting to Test.this.bad2.applyDynamicNamed("sel")
50+
possible cause: maybe a wrong Dynamic method signature?
51+
bad2.sel(a = 1)
52+
^
53+
applydynamic_sip.scala:32: error: Int does not take parameters
54+
error after rewriting to Test.this.bad2.updateDynamic("sel")
55+
possible cause: maybe a wrong Dynamic method signature?
56+
bad2.sel = 1
57+
^
58+
11 errors found

test/files/neg/applydynamic_sip.flags

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-language:dynamics

test/files/neg/applydynamic_sip.scala

+24-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,27 @@ object Test extends App {
77
qual.sel(a, a2: _*)
88
qual.sel(arg = a, a2: _*)
99
qual.sel(arg, arg2 = "a2", a2: _*)
10-
}
10+
11+
val bad1 = new Dynamic {
12+
def selectDynamic(n: Int) = n
13+
def applyDynamic(n: Int) = n
14+
def applyDynamicNamed(n: Int) = n
15+
def updateDynamic(n: Int) = n
16+
17+
}
18+
bad1.sel
19+
bad1.sel(1)
20+
bad1.sel(a = 1)
21+
bad1.sel = 1
22+
23+
val bad2 = new Dynamic {
24+
def selectDynamic = 1
25+
def applyDynamic = 1
26+
def applyDynamicNamed = 1
27+
def updateDynamic = 1
28+
}
29+
bad2.sel
30+
bad2.sel(1)
31+
bad2.sel(a = 1)
32+
bad2.sel = 1
33+
}

0 commit comments

Comments
 (0)