Skip to content
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

String interpolation: error spawned by ambiguous implicit leads to an SO #6436

Closed
scabug opened this issue Sep 27, 2012 · 8 comments
Closed
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Sep 27, 2012

object quasiquotes {
  implicit def foo1(ctx: StringContext) = new { def q = ??? }
  implicit def foo2(ctx: StringContext) = new { def q = ??? }
}

object Test extends App {
  import quasiquotes._
  // new StringContext().q => doesn't crash
  println(q"hello") // => crashes
}
myke compile C:\Projects\Kepler\sandbox\Test.scala -Ydebug
git: branch = 2.10.x, commit = 1d072fcb41 Merge pull request #1408 from scalamacros/topic/direct-test (Paul Phillips, 26.09.2012 22:54:01 -07:00)
psi: filename = cmd.exe, arguments = /C c:\PROGRA~1\Java\JDK\bin\java.exe -cp "C:\Projects\Kepler\test\files\codelib\code.jar;C:\Projects\Kepler\lib\jline.jar;C:\Projects\Kepler\build\locker\lib\scala-partest.jar;C:\Projects\Kepler\lib\fjbg.jar;C:\Projects\Kepler\build\locker\classes\compiler;C:\Projects\Kepler\build\asm\classes;C:\Projects\Kepler\build\libs\forkjoin.jar;C:\Projects\Kepler\build\locker\classes\reflect;C:\Projects\Kepler\build\locker\classes\library" -Dscala.usejavacp=true -Dscala.repl.vids=1 -Dscala.repl.autoruncode=C:\Users\xeno.by/.scala_autorun -Dscala.repl.maxprintstring=0 scala.tools.nsc.Main -language:experimental.macros -Ydebug Test.scala, home = C:\Projects\Kepler\sandbox
[running phase parser on Test.scala]
[running phase namer on Test.scala]
[running phase packageobjects on Test.scala]
[running phase typer on Test.scala]
warning: issue error: type mismatch;
 found   : scala.this.StringContext
 required: ?{<method> def q: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method foo1 in module class quasiquotes of type (<param> ctx: scala.this.StringContext)lang.this.Object{<method> def q: scala.this.Nothing}
 and method foo2 in module class quasiquotes of type (<param> ctx: scala.this.StringContext)lang.this.Object{<method> def q: scala.this.Nothing}
 are possible conversion functions from scala.this.StringContext to ?{<method> def q: ?}
warning: update buffer: Set(scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError)
warning: issue error: type mismatch;
 found   : scala.this.StringContext
 required: ?{<method> def q: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method foo1 in module class quasiquotes of type (<param> ctx: scala.this.StringContext)lang.this.Object{<method> def q: scala.this.Nothing}
 and method foo2 in module class quasiquotes of type (<param> ctx: scala.this.StringContext)lang.this.Object{<method> def q: scala.this.Nothing}
 are possible conversion functions from scala.this.StringContext to ?{<method> def q: ?}
warning: issue error: type mismatch;
 found   : scala.this.StringContext
 required: ?{<method> def q: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method foo1 in module class quasiquotes of type (<param> ctx: scala.this.StringContext)lang.this.Object{<method> def q: scala.this.Nothing}
 and method foo2 in module class quasiquotes of type (<param> ctx: scala.this.StringContext)lang.this.Object{<method> def q: scala.this.Nothing}
 are possible conversion functions from scala.this.StringContext to ?{<method> def q: ?}
warning: update buffer: Set(scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError)
..............
..............
..............
***snip***
..............
..............
..............
warning: issue error: type mismatch;
 found   : scala.this.StringContext
 required: ?{<method> def q: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method foo1 in module class quasiquotes of type (<param> ctx: scala.this.StringContext)lang.this.Object{<method> def q: scala.this.Nothing}
 and method foo2 in module class quasiquotes of type (<param> ctx: scala.this.StringContext)lang.this.Object{<method> def q: scala.this.Nothing}
 are possible conversion functions from scala.this.StringContext to ?{<method> def q: ?}
error:
     while compiling: Test.scala
        during phase: typer
     library version: version 2.10.0-20120926-202924-e1485dbea5
    compiler version: version 2.10.0-20120926-202924-e1485dbea5
  reconstructed args: -Ydebug -language:experimental.macros

  last tree to typer: Ident(foo2)
              symbol: <none> (flags: )
   symbol definition: <none>
       symbol owners:
      context owners: value <local Test> -> module class Test -> package <empty>

== Enclosing template or block ==

Import( // val <import>: ImportType(quasiquotes)
  "quasiquotes" // <module> <triedcooking> object quasiquotes, tree.tpe=<empty>.this.quasiquotes.type
  List(
    ImportSelector(_,195,null,-1)
  )
)

== Current unit body ==

<empty>


uncaught exception during compilation: java.lang.StackOverflowError
error: java.lang.StackOverflowError
  at scala.reflect.internal.Trees$TreeContextApiImpl.<init>(Trees.scala:76)
  at scala.reflect.internal.Trees$Tree.<init>(Trees.scala:17)
  at scala.reflect.internal.Trees$SymTree.<init>(Trees.scala:212)
  at scala.reflect.internal.Trees$Ident.<init>(Trees.scala:432)
  at scala.reflect.internal.Trees$StrictTreeCopier.Ident(Trees.scala:587)
  at scala.reflect.internal.Trees$StrictTreeCopier.Ident(Trees.scala:516)
  at scala.reflect.internal.Trees$class.itransform(Trees.scala:1173)
  at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:12)
  at scala.reflect.internal.SymbolTable.itransform(SymbolTable.scala:12)
  at scala.reflect.api.Trees$Transformer.transform(Trees.scala:1910)
  at scala.reflect.internal.Trees$$anon$1.transform(Trees.scala:1459)
  at scala.reflect.internal.Trees$$anon$1.transform(Trees.scala:1456)
  at scala.reflect.internal.Trees$Tree.duplicate(Trees.scala:73)
  at scala.tools.nsc.typechecker.Typers$Typer.typedIdent$1(Typers.scala:4916)
  at scala.tools.nsc.typechecker.Typers$Typer.typedIdentOrWildcard$1(Typers.scala:4980)
  at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5311)
  at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5390)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$87.apply(Typers.scala:4389)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$87.apply(Typers.scala:4389)
  at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:727)
  at scala.tools.nsc.typechecker.Typers$Typer.normalTypedApply$1(Typers.scala:4389)
  at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:4440)
  at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5313)
  at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit1(Implicits.scala:586)
  at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.typedImplicit0(Implicits.scala:554)
  at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.liftedTree1$1(Implicits.scala:406)
  at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$typedImplicit(Implicits.scala:403)
  at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.tryImplicitInfo$1(Implicits.scala:830)
  at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.rankImplicits(Implicits.scala:833)
  at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.findBest(Implicits.scala:868)
  at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:927)
  at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1378)
  at scala.tools.nsc.typechecker.Implicits$class.inferImplicit(Implicits.scala:82)
  at scala.tools.nsc.Global$$anon$1.inferImplicit(Global.scala:490)
  at scala.tools.nsc.typechecker.Implicits$class.inferImplicit(Implicits.scala:40)
  at scala.tools.nsc.Global$$anon$1.inferImplicit(Global.scala:490)
  at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$wrapImplicit$1(Typers.scala:197)
  at scala.tools.nsc.typechecker.Typers$Typer.inferView(Typers.scala:204)
  at scala.tools.nsc.typechecker.Typers$Typer.adaptToMember(Typers.scala:1305)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$17.apply(Typers.scala:1365)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$17.apply(Typers.scala:1365)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$silent$2.apply(Typers.scala:738)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$silent$2.apply(Typers.scala:737)
  at scala.tools.nsc.typechecker.Typers$Typer.withSavedContext(Typers.scala:520)
  at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:737)
  at scala.tools.nsc.typechecker.Typers$Typer.adaptToMemberWithArgs(Typers.scala:1365)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$93.apply(Typers.scala:4580)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$93.apply(Typers.scala:4575)
  at scala.reflect.internal.Symbols$Symbol.orElse(Symbols.scala:2170)
  at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedSelect$1(Typers.scala:4575)
  at scala.tools.nsc.typechecker.Typers$Typer.typedSelectOrSuperCall$1(Typers.scala:4713)
  at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5312)
  at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5390)
  at scala.tools.nsc.typechecker.Typers$Typer.typedQualifier(Typers.scala:5463)
  at scala.tools.nsc.typechecker.Typers$Typer.typedQualifier(Typers.scala:5469)
  at scala.tools.nsc.typechecker.Typers$Typer.typedSelectOrSuperCall$1(Typers.scala:4693)
  at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5312)
  at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5390)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$93.apply(Typers.scala:4582)
  at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$93.apply(Typers.scala:4575)
  at scala.reflect.internal.Symbols$Symbol.orElse(Symbols.scala:2170)
  at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedSelect$1(Typers.scala:4575)
  at scala.tools.nsc.typechecker.Typers$Typer.typedSelectOrSuperCall$1(Typers.scala:4713)
  ***snip***
@scabug
Copy link
Author

scabug commented Sep 27, 2012

Imported From: https://issues.scala-lang.org/browse/SI-6436?orig=1
Reporter: @densh
Other Milestones: 2.10.0

@scabug
Copy link
Author

scabug commented Oct 1, 2012

@retronym said:
I'm working on a fix for this, we need to refine:

if (name != nme.CONSTRUCTOR && inExprModeOr(mode, PATTERNmode)) {
  val qual1 = adaptToMemberWithArgs(tree, qual, name, mode, true, true)
  if (qual1 ne qual)
    return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}

https://github.com/scala/scala/blob/886c40/src/compiler/scala/tools/nsc/typechecker/Typers.scala#L4603

To something like:

if (qual1 ne tree)

or

if (!qual1.isErrorTyped)

I haven't pinpointed why a formatted literal spins into an infinite loop, whereas the desugared expression recovers with a sensible type error.

I might not be able to submit a PR for this for a day or two.

@scabug
Copy link
Author

scabug commented Oct 1, 2012

@hubertp said:
Indeed. I noticed it while working on scala/scala#1406 and the fix is there (although this is for master).

@scabug
Copy link
Author

scabug commented Oct 1, 2012

@retronym said (edited on Oct 1, 2012 11:32:07 AM UTC):
In addition, I believe that adaptToMemberWithArgs should return qual, not tree, when it encounters an error.

https://github.com/scala/scala/blob/886c406/src/compiler/scala/tools/nsc/typechecker/Typers.scala#L1367

This would be the same as adaptToMember.

@scabug
Copy link
Author

scabug commented Oct 2, 2012

@gkossakowski said (edited on Oct 2, 2012 3:45:35 PM UTC):
Jason: assigning to you. Any estimates how long will it take for you to address it?

Also, do you think it's critical (means: blocking 2.10.0)?

@scabug
Copy link
Author

scabug commented Oct 2, 2012

@retronym said:
I'll submit a PR tonight. I would definitely include the fix in 2.10.0 (it is trivial and zero-risk).

I don't know yet why the problem only manifests in such a specific and limited case; it looks like it ought to break more often.

@scabug
Copy link
Author

scabug commented Oct 2, 2012

@retronym said:
scala/scala#1446

@scabug
Copy link
Author

scabug commented Oct 3, 2012

@gkossakowski said:
Fixed in scala/scala#1446

@scabug scabug closed this as completed Oct 3, 2012
@scabug scabug added the critical label Apr 7, 2017
@scabug scabug added this to the 2.10.0-M7 milestone Apr 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants