diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 13d70408d7db..0296ca8c11bf 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -1028,7 +1028,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** The current tree applied to given type argument list: `tree[targs(0), ..., targs(targs.length - 1)]` */ def appliedToTypeTrees(targs: List[Tree])(using Context): Tree = - if targs.isEmpty then tree else TypeApply(tree, targs) + if targs.isEmpty then tree else tree match + case Block(stmts, expr) if stmts.nonEmpty => Block(stmts, TypeApply(expr, targs)) + case _ => TypeApply(tree, targs) /** Apply to `()` unless tree's widened type is parameterless */ def ensureApplied(using Context): Tree = diff --git a/tests/pos/26238-min.scala b/tests/pos/26238-min.scala new file mode 100644 index 000000000000..65c65d1d9eb5 --- /dev/null +++ b/tests/pos/26238-min.scala @@ -0,0 +1,20 @@ +trait Thing[T] +trait G + +object Outer: + + def thing: Thing[Int] = ??? + + extension[T1](t: Thing[T1])(using g: G = new G { }) + def map[T2](m: T1 => T2): Thing[T2] = ??? + def flatMap[T2](m: T1 => Thing[T2]): Thing[T2] = ??? + + // `y` requires a `flatMap`, and that one requires getting the default value for the `g` argument, + // and getting that default value requires the `t` argument (since default values can depend on previous args), + // which means we end up with a block; + // and since the whole thing is generic, we must apply a generic type argument to that block + for + x <- thing + y <- thing + yield + 1 diff --git a/tests/pos/26238.scala b/tests/pos/26238.scala new file mode 100644 index 000000000000..136c27b3cbb7 --- /dev/null +++ b/tests/pos/26238.scala @@ -0,0 +1,65 @@ +object toplevel { + +@deprecated("pls work this out") +def ??? = scala.Predef.`???` + +import util.ChainingOps.{*, given} + +object S { + +trait AllocatedNodeTypeFamily: + type Node + +trait Parser[+A] private[S] () : + type SpcNd + +type OutliningParser[+A, +Node] += Parser[A] { type SpcNd <: Node } + +extension [R1] (g1: Parser[R1] ) + (using pfmoIspcndi: ParserFlatMapOp.ISpcNdInvariant = new ParserFlatMapOp.ISpcNdInvariant {}.asInstanceOf[ParserFlatMapOp.ISpcNdInvariant { type SpcNdObj = g1.SpcNd } ] ) + + def map[R2] (m: R1 => ( R2 ) ): OutliningParser[R2, g1.SpcNd] = new Parser[Any] {}.asInstanceOf + def flatMap[R2] (m: R1 => (Parser[R2] ) ): OutliningParser[R2, g1.SpcNd] = new Parser[Any] {}.asInstanceOf + +object ParserFlatMapOp { + + given given_ISpcNdInvariant_PModAllocatedNodeTypeFamily + : (x: AllocatedNodeTypeFamily ) => (ISpcNdInvariant { type SpcNdObj = x.Node }) + = new ISpcNdInvariant {}.asInstanceOf + + trait ISpcNdInvariant : + type SpcNdObj + +} // ParserFlatMapOp. + +def defaultIntParser + : Parser[Int] += new Parser[Any] {}.asInstanceOf + +} // S. + +System.err.println(Math.random() ) + +System.err.println(Math.random() ) + +locally : + System.err.println(Math.random() ) + + // given S.ParserFlatMapOp.ISpcNdInvariant + // = (new S.ParserFlatMapOp.ISpcNdInvariant {}).asInstanceOf + + /* run locally you might see something like say "unexpected tree for type application" or the like.. 😒 */ + /* commented out, the whole code would compile and run like it should.. */ + locally : + for + r1 <- S.defaultIntParser + r2 <- S.defaultIntParser + yield { 5 } + .toString() + +System.err.println(s"done.") + +System.err.println(Math.random() ) + +}