Skip to content

Avoid nonsensical error message in processByNameArgs #7830

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ object ErrorReporting {
if (tree.tpe.widen.exists)
i"${exprStr(tree)} does not take ${kind}parameters"
else {
if (ctx.settings.Ydebug.value) new FatalError("").printStackTrace()
i"undefined: $tree # ${tree.uniqueId}: ${tree.tpe.toString} at ${ctx.phase}"
}

Expand Down
12 changes: 8 additions & 4 deletions compiler/src/dotty/tools/dotc/typer/Nullables.scala
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,8 @@ object Nullables with
*/
def postProcessByNameArgs(fn: TermRef, app: Tree)(given ctx: Context): Tree =
fn.widen match
case mt: MethodType if mt.paramInfos.exists(_.isInstanceOf[ExprType]) =>
case mt: MethodType
if mt.paramInfos.exists(_.isInstanceOf[ExprType]) && !fn.symbol.is(Inline) =>
app match
case Apply(fn, args) =>
val dropNotNull = new TreeMap with
Expand All @@ -487,10 +488,10 @@ object Nullables with
case _ => super.typedUnadapted(t, pt, locked)

def postProcess(formal: Type, arg: Tree): Tree =
val arg1 = dropNotNull.transform(arg)
val nestedCtx = ctx.fresh.setNewTyperState()
val arg1 = dropNotNull.transform(arg)(given nestedCtx)
if arg1 eq arg then arg
else
val nestedCtx = ctx.fresh.setNewTyperState()
val arg2 = retyper.typed(arg1, formal)(given nestedCtx)
if nestedCtx.reporter.hasErrors || !(arg2.tpe <:< formal) then
ctx.error(em"""This argument was typed using flow assumptions about mutable variables
Expand All @@ -506,7 +507,10 @@ object Nullables with

def recur(formals: List[Type], args: List[Tree]): List[Tree] = (formals, args) match
case (formal :: formalsRest, arg :: argsRest) =>
val arg1 = postProcess(formal.widenExpr.repeatedToSingle, arg)
val arg1 =
if formal.isInstanceOf[ExprType]
then postProcess(formal.widenExpr.repeatedToSingle, arg)
else arg
val argsRest1 = recur(
if formal.isRepeatedParam then formals else formalsRest,
argsRest)
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ trait TypeAssigner {
else
errorType(i"wrong number of arguments at ${ctx.phase.prev} for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.sourcePos)
case t =>
if (ctx.settings.Ydebug.value) new FatalError("").printStackTrace()
errorType(err.takesNoParamsStr(fn, ""), tree.sourcePos)
}
ConstFold(tree.withType(ownType))
Expand Down
8 changes: 8 additions & 0 deletions tests/neg-custom-args/explicit-nulls/byname-nullables1.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- Error: tests/neg-custom-args/explicit-nulls/byname-nullables1.scala:10:6 --------------------------------------------
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a test that uses the byName method referred to here.

10 | f(x.fld != null) // error
| ^^^^^^^^^^^^^
| This argument was typed using flow assumptions about mutable variables
| but it is passed to a by-name parameter where such flow assumptions are unsound.
| Wrapping the argument in `byName(...)` fixes the problem by disabling the flow assumptions.
|
| `byName` needs to be imported from the `scala.compiletime` package.
11 changes: 11 additions & 0 deletions tests/neg-custom-args/explicit-nulls/byname-nullables1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
def f(op: => Boolean): Unit = ()
def f(op: Int): Unit = ()

class C with
var fld: String | Null = null

def test() =
var x: C | Null = C()
if x != null then
f(x.fld != null) // error
require(x.fld != null, "error") // ok