Skip to content

Commit 7a6c230

Browse files
authored
Merge branch 'main' into fix-19530
2 parents b23da16 + fb50b1e commit 7a6c230

File tree

11 files changed

+114
-27
lines changed

11 files changed

+114
-27
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,15 +1602,17 @@ object desugar {
16021602
* skipping elements that are not convertible.
16031603
*/
16041604
def patternsToParams(elems: List[Tree])(using Context): List[ValDef] =
1605-
def toParam(elem: Tree, tpt: Tree): Tree =
1605+
def toParam(elem: Tree, tpt: Tree, span: Span): Tree =
16061606
elem match
1607-
case Annotated(elem1, _) => toParam(elem1, tpt)
1608-
case Typed(elem1, tpt1) => toParam(elem1, tpt1)
1609-
case Ident(id: TermName) => ValDef(id, tpt, EmptyTree).withFlags(Param)
1607+
case Annotated(elem1, _) => toParam(elem1, tpt, span)
1608+
case Typed(elem1, tpt1) => toParam(elem1, tpt1, span)
1609+
case Ident(id: TermName) => ValDef(id, tpt, EmptyTree).withFlags(Param).withSpan(span)
16101610
case _ => EmptyTree
1611-
elems.map(param => toParam(param, TypeTree()).withSpan(param.span)).collect {
1612-
case vd: ValDef => vd
1613-
}
1611+
elems
1612+
.map: param =>
1613+
toParam(param, TypeTree(), param.span)
1614+
.collect:
1615+
case vd: ValDef => vd
16141616

16151617
def makeContextualFunction(formals: List[Tree], paramNamesOrNil: List[TermName], body: Tree, erasedParams: List[Boolean])(using Context): Function = {
16161618
val mods = Given

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1074,7 +1074,7 @@ trait Implicits:
10741074
if (argument.isEmpty) i"missing implicit parameter of type $pt after typer at phase ${ctx.phase.phaseName}"
10751075
else i"type error: ${argument.tpe} does not conform to $pt${err.whyNoMatchStr(argument.tpe, pt)}")
10761076

1077-
val usableForInference = !pt.unusableForInference
1077+
val usableForInference = pt.exists && !pt.unusableForInference
10781078
&& (argument.isEmpty || !argument.tpe.unusableForInference)
10791079

10801080
val result0 = if usableForInference then

compiler/src/dotty/tools/dotc/typer/Inferencing.scala

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -383,17 +383,20 @@ object Inferencing {
383383
def isSkolemFree(tp: Type)(using Context): Boolean =
384384
!tp.existsPart(_.isInstanceOf[SkolemType])
385385

386-
/** The list of uninstantiated type variables bound by some prefix of type `T` which
387-
* occur in at least one formal parameter type of a prefix application.
386+
/** The list of uninstantiated type variables bound by some prefix of type `T` or
387+
* by arguments of an application prefix, which occur at least once as a formal type parameter
388+
* of an application either from a prefix or an argument of an application node.
388389
* Considered prefixes are:
389390
* - The function `f` of an application node `f(e1, .., en)`
390391
* - The function `f` of a type application node `f[T1, ..., Tn]`
391392
* - The prefix `p` of a selection `p.f`.
392393
* - The result expression `e` of a block `{s1; .. sn; e}`.
393394
*/
394395
def tvarsInParams(tree: Tree, locked: TypeVars)(using Context): List[TypeVar] = {
395-
@tailrec def boundVars(tree: Tree, acc: List[TypeVar]): List[TypeVar] = tree match {
396-
case Apply(fn, _) => boundVars(fn, acc)
396+
def boundVars(tree: Tree, acc: List[TypeVar]): List[TypeVar] = tree match {
397+
case Apply(fn, args) =>
398+
val argTpVars = args.flatMap(boundVars(_, Nil))
399+
boundVars(fn, acc ++ argTpVars)
397400
case TypeApply(fn, targs) =>
398401
val tvars = targs.filter(_.isInstanceOf[InferredTypeTree]).tpes.collect {
399402
case tvar: TypeVar
@@ -406,16 +409,18 @@ object Inferencing {
406409
case Block(_, expr) => boundVars(expr, acc)
407410
case _ => acc
408411
}
409-
@tailrec def occurring(tree: Tree, toTest: List[TypeVar], acc: List[TypeVar]): List[TypeVar] =
412+
def occurring(tree: Tree, toTest: List[TypeVar], acc: List[TypeVar]): List[TypeVar] =
410413
if (toTest.isEmpty) acc
411414
else tree match {
412-
case Apply(fn, _) =>
415+
case Apply(fn, args) =>
416+
val argsOcc = args.flatMap(occurring(_, toTest, Nil))
417+
val argsNocc = toTest.filterNot(argsOcc.contains)
413418
fn.tpe.widen match {
414419
case mtp: MethodType =>
415-
val (occ, nocc) = toTest.partition(tvar => mtp.paramInfos.exists(tvar.occursIn))
416-
occurring(fn, nocc, occ ::: acc)
420+
val (occ, nocc) = argsNocc.partition(tvar => mtp.paramInfos.exists(tvar.occursIn))
421+
occurring(fn, nocc, occ ::: argsOcc ::: acc)
417422
case _ =>
418-
occurring(fn, toTest, acc)
423+
occurring(fn, argsNocc, argsOcc ::: acc)
419424
}
420425
case TypeApply(fn, targs) => occurring(fn, toTest, acc)
421426
case Select(pre, _) => occurring(pre, toTest, acc)

compiler/test/dotty/tools/vulpix/ParallelTesting.scala

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -290,15 +290,25 @@ trait ParallelTesting extends RunnerOrchestration { self =>
290290

291291
/** This callback is executed once the compilation of this test source finished */
292292
private final def onComplete(testSource: TestSource, reportersOrCrash: Try[Seq[TestReporter]], logger: LoggedRunnable): Unit =
293-
reportersOrCrash match {
294-
case TryFailure(exn) => onFailure(testSource, Nil, logger, Some(s"Fatal compiler crash when compiling: ${testSource.title}:\n${exn.getMessage}${exn.getStackTrace.map("\n\tat " + _).mkString}"))
295-
case TrySuccess(reporters) if !reporters.exists(_.skipped) =>
296-
maybeFailureMessage(testSource, reporters) match {
297-
case Some(msg) => onFailure(testSource, reporters, logger, Option(msg).filter(_.nonEmpty))
298-
case None => onSuccess(testSource, reporters, logger)
293+
try
294+
reportersOrCrash match
295+
case TryFailure(exn) => onFailure(testSource, Nil, logger, Some(s"Fatal compiler crash when compiling: ${testSource.title}:\n${exn.getMessage}${exn.getStackTrace.map("\n\tat " + _).mkString}"))
296+
case TrySuccess(reporters) if !reporters.exists(_.skipped) =>
297+
maybeFailureMessage(testSource, reporters) match {
298+
case Some(msg) => onFailure(testSource, reporters, logger, Option(msg).filter(_.nonEmpty))
299+
case None => onSuccess(testSource, reporters, logger)
300+
}
301+
case _ =>
302+
catch case ex: Throwable =>
303+
echo(s"Exception thrown onComplete (probably by a reporter) in $testSource: ${ex.getClass}")
304+
Try(ex.printStackTrace())
305+
.recover{ _ =>
306+
val trace = ex.getStackTrace.map(_.toString) // compute this first in case getStackTrace throws an exception
307+
echo(s"${ex.getClass.getName} message could not be printed due to an exception while computing the message.")
308+
if trace.nonEmpty then trace.foreach(echo) else echo(s"${ex.getClass.getName} stack trace is empty.")
299309
}
300-
case _ =>
301-
}
310+
.getOrElse(echo(s"${ex.getClass.getName} stack trace could not be printed due to an exception while printing the stack trace."))
311+
failTestSource(testSource)
302312

303313
/**
304314
* Based on the reporters obtained after the compilation, determines if this test has failed.
File renamed without changes.
File renamed without changes.

tests/neg/i19320.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//> using scala "3.3.1"
2+
//> using dep org.http4s::http4s-ember-client:1.0.0-M40
3+
//> using dep org.http4s::http4s-ember-server:1.0.0-M40
4+
//> using dep org.http4s::http4s-dsl:1.0.0-M40
5+
6+
//import cats.effect.*
7+
//import cats.implicits.*
8+
9+
class Concurrent[F[_]]
10+
11+
class Test[F[_]: Concurren]: // error
12+
def hello = ???
13+
14+
object Test:
15+
def apply[F[_]: Concurrent] = new Test[F]

tests/neg/i19506.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//> using options -source 3.4-migration
1+
//> using options "-source:3.4-migration"
22

33
trait Reader[T]
44
def read[T: Reader](s: String, trace: Boolean = false): T = ???

tests/pos/i18578.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
trait Animal
3+
class Dog extends Animal
4+
5+
trait Ev[T]
6+
7+
given Ev[Dog] = ???
8+
given Ev[Animal] = ???
9+
given[T: Ev]: Ev[Set[T]] = ???
10+
11+
def f[T: Ev](v: T): Unit = ???
12+
13+
def main =
14+
val s = Set(new Dog)
15+
f(s) // Ok
16+
f(Set(new Dog)) // Error before changes: Ambiguous given instances: both given instance given_Ev_Dog and given instance given_Ev_Animal match type Ev[T]
17+

tests/pos/i7586.scala

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
trait Nat
3+
case object Z extends Nat
4+
case class S[N <: Nat](pred: N) extends Nat
5+
6+
type Z = Z.type
7+
given zero: Z = Z
8+
given succ[N <: Nat](using n: N): S[N] = S(n)
9+
10+
case class Sum[N <: Nat, M <: Nat, R <: Nat](result: R)
11+
12+
given sumZ[N <: Nat](using n: N): Sum[Z, N, N] = Sum(n)
13+
given sumS[N <: Nat, M <: Nat, R <: Nat](
14+
using sum: Sum[N, M, R]
15+
): Sum[S[N], M, S[R]] = Sum(S(sum.result))
16+
17+
def add[N <: Nat, M <: Nat, R <: Nat](n: N, m: M)(
18+
using sum: Sum[N, M, R]
19+
): R = sum.result
20+
21+
case class Prod[N <: Nat, M <: Nat, R <: Nat](result: R)
22+
23+
24+
@main def Test: Unit =
25+
26+
val n1: S[Z] = add(Z, S(Z))
27+
summon[n1.type <:< S[Z]] // OK
28+
29+
val n3: S[S[S[Z]]] = add(S(S(Z)), S(Z))
30+
summon[n3.type <:< S[S[S[Z]]]] // Ok
31+
32+
val m3_2 = add(S(Z), S(S(Z)))
33+
summon[m3_2.type <:< S[S[S[Z]]]] // Error before changes: Cannot prove that (m3_2 : S[S[Nat]]) <:< S[S[S[Z]]]
34+
35+
val m4_2 = add(S(Z), S(S(S(Z))))
36+
summon[m4_2.type <:< S[S[S[S[Z]]]]]
37+
38+

0 commit comments

Comments
 (0)