Skip to content

Commit

Permalink
Merge pull request #13361 from dotty-staging/proto-implicit
Browse files Browse the repository at this point in the history
wildApprox: also approximate FunProto arguments
  • Loading branch information
smarter authored Aug 27, 2021
2 parents bf7009e + bee299e commit 427d313
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 8 deletions.
11 changes: 4 additions & 7 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,6 @@ trait ImplicitRunInfo:

object collectParts extends TypeTraverser:

private var provisional: Boolean = _
private var parts: mutable.LinkedHashSet[Type] = _
private val partSeen = util.HashSet[Type]()

Expand All @@ -587,19 +586,18 @@ trait ImplicitRunInfo:
case t: ConstantType =>
traverse(t.underlying)
case t: TypeParamRef =>
assert(!ctx.typerState.constraint.contains(t), i"`wildApprox` failed to remove uninstantiated $t")
traverse(t.underlying)
if ctx.typerState.constraint.contains(t) then provisional = true
case t: TermParamRef =>
traverse(t.underlying)
case t =>
traverseChildren(t)

def apply(tp: Type): (collection.Set[Type], Boolean) =
provisional = false
def apply(tp: Type): collection.Set[Type] =
parts = mutable.LinkedHashSet()
partSeen.clear()
traverse(tp)
(parts, provisional)
parts
end collectParts

val seen = util.HashSet[Type]()
Expand Down Expand Up @@ -674,12 +672,11 @@ trait ImplicitRunInfo:
end collectCompanions

def recur(tp: Type): OfTypeImplicits =
val (parts, provisional) = collectParts(tp)
val parts = collectParts(tp)
val companions = collectCompanions(tp, parts)
val result = OfTypeImplicits(tp, companions)(runContext)
if Config.cacheImplicitScopes
&& tp.hash != NotCached
&& !provisional
&& (tp eq rootTp) // first type traversed is always cached
|| !incomplete.contains(tp) // other types are cached if they are not incomplete
then implicitScopeCache(tp) = result
Expand Down
16 changes: 15 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,10 @@ object ProtoTypes {
// `protoTyperState` committable we must ensure that it does not
// contain any type variable which don't already exist in the passed
// TyperState. This is achieved by instantiating any such type
// variable.
// variable. NOTE: this does not suffice to discard type variables
// in ancestors of `protoTyperState`, if this situation ever
// comes up, an assertion in TyperState will trigger and this code
// will need to be generalized.
if protoTyperState.isCommittable then
val passedConstraint = passedTyperState.constraint
val newLambdas = newConstraint.domainLambdas.filter(tl =>
Expand Down Expand Up @@ -822,6 +825,17 @@ object ProtoTypes {
tp.derivedViewProto(
wildApprox(tp.argType, theMap, seen, internal),
wildApprox(tp.resultType, theMap, seen, internal))
case tp: FunProto =>
val args = tp.args.mapconserve(arg =>
val argTp = tp.typeOfArg(arg) match
case NoType => WildcardType
case tp => wildApprox(tp, theMap, seen, internal)
arg.withType(argTp))
val resTp = wildApprox(tp.resultType, theMap, seen, internal)
if (args eq tp.args) && (resTp eq tp.resultType) then
tp
else
FunProtoTyped(args, resTp)(ctx.typer, tp.applyKind)
case tp: IgnoredProto =>
WildcardType
case _: ThisType | _: BoundType => // default case, inlined for speed
Expand Down
3 changes: 3 additions & 0 deletions tests/neg/i13340.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
case class Field(name: String, subQuery: Option[Query] = None)
case class Query(fields: Seq[Field])
val x = Query(Seq(Field("a", subQuery=Some(Query(Seq(Field("b")), Nil)))), Nil) // error

0 comments on commit 427d313

Please sign in to comment.