diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala b/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala index c57ad639783c..44d5e2cf4b88 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala @@ -158,9 +158,13 @@ sealed abstract class CaptureSet extends Showable: * as frozen. */ def accountsFor(x: CaptureRef)(using Context): Boolean = - reporting.trace(i"$this accountsFor $x, ${x.captureSetOfInfo}?", show = true): + def debugInfo(using Context) = i"$this accountsFor $x, which has capture set ${x.captureSetOfInfo}" + def test(using Context) = reporting.trace(debugInfo): elems.exists(_.subsumes(x)) || !x.isMaxCapability && x.captureSetOfInfo.subCaptures(this, frozen = true).isOK + comparer match + case comparer: ExplainingTypeComparer => comparer.traceIndented(debugInfo)(test) + case _ => test /** A more optimistic version of accountsFor, which does not take variable supersets * of the `x` reference into account. A set might account for `x` if it accounts diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 0d8801b646ee..bfda613d0586 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -691,20 +691,18 @@ object TypeOps: val hiBound = instantiate(bounds.hi, skolemizedArgTypes) val loBound = instantiate(bounds.lo, skolemizedArgTypes) - def check(tp1: Type, tp2: Type, which: String, bound: Type)(using Context) = { - val isSub = TypeComparer.explaining { cmp => - val isSub = cmp.isSubType(tp1, tp2) - if !isSub then - if !ctx.typerState.constraint.domainLambdas.isEmpty then - typr.println(i"${ctx.typerState.constraint}") - if !ctx.gadt.symbols.isEmpty then - typr.println(i"${ctx.gadt}") - typr.println(cmp.lastTrace(i"checkOverlapsBounds($lo, $hi, $arg, $bounds)($which)")) - //trace.dumpStack() - isSub - }//(using ctx.fresh.setSetting(ctx.settings.verbose, true)) // uncomment to enable moreInfo in ExplainingTypeComparer recur - if !isSub then violations += ((arg, which, bound)) - } + def check(tp1: Type, tp2: Type, which: String, bound: Type)(using Context) = + val isSub = TypeComparer.isSubType(tp1, tp2) + if !isSub then + // inContext(ctx.fresh.setSetting(ctx.settings.verbose, true)): // uncomment to enable moreInfo in ExplainingTypeComparer + TypeComparer.explaining: cmp => + if !ctx.typerState.constraint.domainLambdas.isEmpty then + typr.println(i"${ctx.typerState.constraint}") + if !ctx.gadt.symbols.isEmpty then + typr.println(i"${ctx.gadt}") + typr.println(cmp.lastTrace(i"checkOverlapsBounds($lo, $hi, $arg, $bounds)($which)")) + violations += ((arg, which, bound)) + check(lo, hiBound, "upper", hiBound)(using checkCtx) check(loBound, hi, "lower", loBound)(using checkCtx) } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index ce5743f69d0c..901e27a2f1a1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1903,9 +1903,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if knownFormal then formal0 else errorType(AnonymousFunctionMissingParamType(param, tree, inferredType = formal, expectedType = pt), param.srcPos) ) + val untpdTpt = formal match + case _: WildcardType => + // In this case we have a situation like f(_), where we expand in the end to + // (x: T) => f(x) and `T` is taken from `f`'s declared parameters. In this case + // we treat the type as declared instead of inferred. InferredType is used for + // types that are inferred from the context. + untpd.TypeTree() + case _ => InferredTypeTree() val paramTpt = untpd.TypedSplice( - (if knownFormal then InferredTypeTree() else untpd.TypeTree()) - .withType(paramType.translateFromRepeated(toArray = false)) + untpdTpt.withType(paramType.translateFromRepeated(toArray = false)) .withSpan(param.span.endPos) ) val param0 = cpy.ValDef(param)(tpt = paramTpt) diff --git a/tests/pos-custom-args/captures/i21347.scala b/tests/pos-custom-args/captures/i21347.scala new file mode 100644 index 000000000000..e74c15bff8c1 --- /dev/null +++ b/tests/pos-custom-args/captures/i21347.scala @@ -0,0 +1,11 @@ +//> using scala 3.6.0-RC1-bin-SNAPSHOT + +import language.experimental.captureChecking + +class Box[Cap^] {} + +def run[Cap^](f: Box[Cap]^{Cap^} => Unit): Box[Cap]^{Cap^} = ??? + +def main() = + val b = run(_ => ()) + // val b = run[caps.CapSet](_ => ()) // this compiles \ No newline at end of file