From 2e4bc0abb8a374d78fe1aac383f3208b5efb5eb1 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Thu, 26 Jun 2025 17:36:21 +0200 Subject: [PATCH] Fix regressions in asSeenFrom introduced in 3.7 The body of isLegalPrefix used to read: pre.isStable || !ctx.phase.isTyper but was changed to drop the second condition in #21954 (originally included in 3.6.4-RC1, reverted from 3.6.4 final but back in 3.7). This has led to a number of regressions, the last ones discussed in #23423. To make the testcases added in #21594 pass, this PR proposes a less drastic change: relax isLegalPrefix as before, unless we're doing an implicit search. This should dramatically reduce the possibility for regressions. Fixes #23423. Fixes #22676. --- compiler/src/dotty/tools/dotc/core/TypeOps.scala | 4 +++- tests/neg-custom-args/captures/lazylist.check | 2 +- tests/neg/6314-6.check | 4 ++-- tests/pos-macros/i23423/A_1.scala | 16 ++++++++++++++++ tests/pos-macros/i23423/B_2.scala | 6 ++++++ tests/pos/i22676.scala | 11 +++++++++++ 6 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 tests/pos-macros/i23423/A_1.scala create mode 100644 tests/pos-macros/i23423/B_2.scala create mode 100644 tests/pos/i22676.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 4909602915d3..cf03273b4805 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -125,7 +125,9 @@ object TypeOps: } def isLegalPrefix(pre: Type)(using Context): Boolean = - pre.isStable + // isLegalPrefix is relaxed after typer unless we're doing an implicit + // search (this matters when doing summonInline in an inline def like in tests/pos/i17222.8.scala). + pre.isStable || !ctx.phase.isTyper && ctx.mode.is(Mode.ImplicitsEnabled) /** Implementation of Types#simplified */ def simplify(tp: Type, theMap: SimplifyMap | Null)(using Context): Type = { diff --git a/tests/neg-custom-args/captures/lazylist.check b/tests/neg-custom-args/captures/lazylist.check index 455d72e9fd37..0959f1a082fb 100644 --- a/tests/neg-custom-args/captures/lazylist.check +++ b/tests/neg-custom-args/captures/lazylist.check @@ -29,7 +29,7 @@ -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazylist.scala:41:42 ------------------------------------- 41 | val ref4c: LazyList[Int]^{cap1, ref3} = ref4 // error | ^^^^ - | Found: (ref4 : lazylists.LazyList[Int]^{cap3, ref1, ref2}) + | Found: (ref4 : lazylists.LazyList[Int]^{cap3, cap1, cap2}) | Required: lazylists.LazyList[Int]^{cap1, ref3} | | longer explanation available when compiling with `-explain` diff --git a/tests/neg/6314-6.check b/tests/neg/6314-6.check index df988f1db9dd..7d6bd182173d 100644 --- a/tests/neg/6314-6.check +++ b/tests/neg/6314-6.check @@ -4,7 +4,7 @@ |object creation impossible, since def apply(fa: String): Int in trait XX in object Test3 is not defined |(Note that | parameter String in def apply(fa: String): Int in trait XX in object Test3 does not match - | parameter Test3.Bar[X & (X & Y)] in def apply(fa: Test3.Bar[X & YY.this.Foo]): Test3.Bar[Y & YY.this.Foo] in trait YY in object Test3 + | parameter Test3.Bar[X & Object with Test3.YY {...}#Foo] in def apply(fa: Test3.Bar[X & YY.this.Foo]): Test3.Bar[Y & YY.this.Foo] in trait YY in object Test3 | ) -- Error: tests/neg/6314-6.scala:52:3 ---------------------------------------------------------------------------------- 52 | (new YY {}).boom // error: object creation impossible @@ -12,5 +12,5 @@ |object creation impossible, since def apply(fa: String): Int in trait XX in object Test4 is not defined |(Note that | parameter String in def apply(fa: String): Int in trait XX in object Test4 does not match - | parameter Test4.Bar[X & (X & Y)] in def apply(fa: Test4.Bar[X & YY.this.FooAlias]): Test4.Bar[Y & YY.this.FooAlias] in trait YY in object Test4 + | parameter Test4.Bar[X & Object with Test4.YY {...}#FooAlias] in def apply(fa: Test4.Bar[X & YY.this.FooAlias]): Test4.Bar[Y & YY.this.FooAlias] in trait YY in object Test4 | ) diff --git a/tests/pos-macros/i23423/A_1.scala b/tests/pos-macros/i23423/A_1.scala new file mode 100644 index 000000000000..62455c74eed0 --- /dev/null +++ b/tests/pos-macros/i23423/A_1.scala @@ -0,0 +1,16 @@ +package pkg + +import scala.quoted.* + +trait HasElem { + type Elem + type Alias = Elem +} + +object Macro: + inline def foo: Unit = ${fooImpl} + def fooImpl(using Quotes): Expr[Unit] = + '{ + val lll: (he: HasElem) => he.Alias = + (hx: HasElem) => ??? + } diff --git a/tests/pos-macros/i23423/B_2.scala b/tests/pos-macros/i23423/B_2.scala new file mode 100644 index 000000000000..144eaf4ce1da --- /dev/null +++ b/tests/pos-macros/i23423/B_2.scala @@ -0,0 +1,6 @@ +object Test: + def test: Unit = pkg.Macro.foo + // used to be error: + // Found: (hx: pkg.HasElem) => hx.Elem + // Required: (he: pkg.HasElem) => he.Elem + diff --git a/tests/pos/i22676.scala b/tests/pos/i22676.scala new file mode 100644 index 000000000000..5654559b133f --- /dev/null +++ b/tests/pos/i22676.scala @@ -0,0 +1,11 @@ +package example + +trait Example { + class Input + + type Output[A] = A match { + case Input => Int + } +} + +class Ref(ref: Example#Input)