Skip to content

Fix #7249: Search for hidden givens only at whole type #7300

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 4 commits into from
Sep 27, 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
29 changes: 18 additions & 11 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import Constants._
import ProtoTypes._
import ErrorReporting._
import reporting.diagnostic.Message
import Inferencing.fullyDefinedType
import Inferencing.{fullyDefinedType, isFullyDefined}
import Trees._
import transform.SymUtils._
import transform.TypeUtils._
Expand Down Expand Up @@ -392,7 +392,8 @@ object Implicits {
def whyNoConversion(implicit ctx: Context): String = ""
}

class NoMatchingImplicits(val expectedType: Type, val argument: Tree, constraint: Constraint = OrderingConstraint.empty) extends SearchFailureType {
class NoMatchingImplicits(val expectedType: Type, val argument: Tree, constraint: Constraint = OrderingConstraint.empty)
extends SearchFailureType {

/** Replace all type parameters in constraint by their bounds, to make it clearer
* what was expected
Expand Down Expand Up @@ -1215,15 +1216,21 @@ trait Implicits { self: Typer =>
if (ctx == NoContext) ctx
else ctx.freshOver(FindHiddenImplicitsCtx(ctx.outer)).addMode(Mode.FindHiddenImplicits)

inferImplicit(fail.expectedType, fail.argument, arg.span)(
FindHiddenImplicitsCtx(ctx)) match {
case s: SearchSuccess => hiddenImplicitNote(s)
case f: SearchFailure =>
f.reason match {
case ambi: AmbiguousImplicits => hiddenImplicitNote(ambi.alt1)
case r => ""
}
}
if (fail.expectedType eq pt) || isFullyDefined(fail.expectedType, ForceDegree.none) then
inferImplicit(fail.expectedType, fail.argument, arg.span)(
FindHiddenImplicitsCtx(ctx)) match {
case s: SearchSuccess => hiddenImplicitNote(s)
case f: SearchFailure =>
f.reason match {
case ambi: AmbiguousImplicits => hiddenImplicitNote(ambi.alt1)
case r => ""
}
}
else
// It's unsafe to search for parts of the expected type if they are not fully defined,
// since these come with nested contexts that are lost at this point. See #7249 for an
// example where searching for a nested type causes an infinite loop.
""
}
msg(userDefined.getOrElse(
em"no implicit argument of type $pt was found${location("for")}"))() ++
Expand Down
7 changes: 4 additions & 3 deletions compiler/src/dotty/tools/dotc/typer/Inferencing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,10 @@ object Inferencing {
def apply(x: Boolean, tp: Type): Boolean = tp.dealias match {
case _: WildcardType | _: ProtoType =>
false
case tvar: TypeVar
if !tvar.isInstantiated && ctx.typerState.constraint.contains(tvar) =>
force.appliesTo(tvar) && {
case tvar: TypeVar if !tvar.isInstantiated =>
force.appliesTo(tvar)
&& ctx.typerState.constraint.contains(tvar)
&& {
val direction = instDirection(tvar.origin)
def avoidBottom =
!force.allowBottom &&
Expand Down
4 changes: 4 additions & 0 deletions tests/neg/i7248.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
object Test extends App {
given f[H](given h: H): H = h
summon[Int] // error
}
9 changes: 9 additions & 0 deletions tests/neg/i7249.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Predef.{$conforms => _, _}

trait F[H, T]


object Test extends App {
given f[H, T](given h: H, t: T): F[H, T] = ???
summon[F[Int, Unit]] // error
}