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

Skip contexts for implicit search when resolving imports #12816

Merged
merged 2 commits into from
Jun 15, 2021
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
15 changes: 14 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -976,10 +976,23 @@ trait Implicits:
then return NoMatchingImplicitsFailure

val result0 =
try ImplicitSearch(pt, argument, span).bestImplicit
// If we are searching implicits when resolving an import symbol, start the search
// in the first enclosing context that does not have the same scope and owner as the current
// context. Without that precaution, an eligible implicit in the current scope
// would cause a cyclic reference error (if the import is named) or cause a
// spurious import skip (if the import is a wildcard import). See i12802 for a test case.
var searchCtx = ctx
if ctx.owner.isImport then
while
searchCtx = searchCtx.outer
(searchCtx.scope eq ctx.scope) && (searchCtx.owner eq ctx.owner.owner)
do ()

try ImplicitSearch(pt, argument, span)(using searchCtx).bestImplicit
catch case ce: CyclicReference =>
ce.inImplicitSearch = true
throw ce
end result0

val result =
result0 match {
Expand Down
12 changes: 12 additions & 0 deletions tests/neg/i12802.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
trait M:
type X
object X:
def foo(): X = ???

transparent inline def m(using m: M): m.type = m

def Test1 =
given M = new M{}
import m.* // error: no implicit argument of type M was found
val x: X = X.foo()
println(x)
8 changes: 5 additions & 3 deletions tests/pos/i10295.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ def doSomething(body: M ?=> Unit) = body(using new M{})

def Test1 =
given M = new M{}
import m.*
val x: X = X.foo()
println(x)
locally {
import m.*
val x: X = X.foo()
println(x)
}

def Test2 =

Expand Down
9 changes: 9 additions & 0 deletions tests/pos/i12802.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import scala.quoted._

object Boo:
def foo(using Quotes): Unit =
import quotes.reflect._
given Option[Symbol] = Some[Symbol](???)
def bar(using Quotes): Unit =
import quotes.reflect.Symbol
given Option[Symbol] = Some[Symbol](???)