diff --git a/compiler/src/dotty/tools/dotc/transform/CheckLoopingImplicits.scala b/compiler/src/dotty/tools/dotc/transform/CheckLoopingImplicits.scala index 4818153e00e6..21b994a6d1b8 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckLoopingImplicits.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckLoopingImplicits.scala @@ -46,7 +46,10 @@ class CheckLoopingImplicits extends MiniPhase: case Apply(fn, args) => checkNotLooping(fn) fn.tpe.widen match - case mt: MethodType => + case mt: MethodType + // Boolean && and || aren't defined with by-name parameters + // and therefore their type isn't an ExprType, so we exempt them by symbol name + if t.symbol != defn.Boolean_&& && t.symbol != defn.Boolean_|| => args.lazyZip(mt.paramInfos).foreach { (arg, pinfo) => if !pinfo.isInstanceOf[ExprType] then checkNotLooping(arg) } @@ -80,8 +83,8 @@ class CheckLoopingImplicits extends MiniPhase: checkNotLooping(t.rhs) case _ => - if sym.isOneOf(GivenOrImplicit | Lazy) then + if sym.isOneOf(GivenOrImplicit | Lazy | ExtensionMethod) then checkNotLooping(mdef.rhs) mdef end transform -end CheckLoopingImplicits \ No newline at end of file +end CheckLoopingImplicits diff --git a/tests/neg-custom-args/fatal-warnings/i9880.scala b/tests/neg-custom-args/fatal-warnings/i9880.scala new file mode 100644 index 000000000000..d9d857110543 --- /dev/null +++ b/tests/neg-custom-args/fatal-warnings/i9880.scala @@ -0,0 +1,30 @@ +opaque type Bytes = Array[Byte] +object Bytes: + extension (self: Bytes) + def size: Int = (self: Array[Byte]).size // error + +// + +object Module1: + opaque type State[S, +A] = S => (S, A) + object State: + extension [S, A](self: State[S, A]) + def map[B](f: A => B): State[S, B] = + s => { val (s2, a) = self(s); (s2, f(a)) } +object Module2: + import Module1.State + trait RNG + opaque type Gen[+A] = State[RNG, A] + object Gen: + extension [A](self: Gen[A]) + def map[B](f: A => B): Gen[B] = + self.map(f) // error + +// + +class Sym(val owner: Sym) + +extension (sym: Sym) + def isSomething: Boolean = false + def isFoo: Boolean = sym.isSomething && sym.owner.isFoo // was: Infinite loop in function body + def isBar: Boolean = sym.isSomething || sym.owner.isBar // was: Infinite loop in function body