diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 19f7ee238d99..9644313e925d 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -592,7 +592,7 @@ object SymDenotations { def seesOpaques(implicit ctx: Context): Boolean = containsOpaques || - is(Module, butNot = Package) && owner.containsOpaques + is(Module, butNot = Package) && owner.seesOpaques /** Is this the denotation of a self symbol of some class? * This is the case if one of two conditions holds: diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index fd000257c75c..7c194b3a7283 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -2463,9 +2463,9 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) { if (skipped) op else { indent += 2 - b append "\n" append (" " * indent) append "==> " append str + b.append("\n").append(" " * indent).append("==> ").append(str) val res = op - b append "\n" append (" " * indent) append "<== " append str append " = " append show(res) + b.append("\n").append(" " * indent).append("<== ").append(str).append(" = ").append(show(res)) indent -= 2 res } diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 6246b4ef1636..3108e4d2f98c 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -244,7 +244,10 @@ object TypeErasure { !classify(tp).derivesFrom(defn.ObjectClass) && !tp.binder.resultType.isJavaMethod case tp: TypeAlias => isUnboundedGeneric(tp.alias) - case tp: TypeBounds => !classify(tp.hi).derivesFrom(defn.ObjectClass) + case tp: TypeBounds => + val upper = classify(tp.hi) + !upper.derivesFrom(defn.ObjectClass) && + !upper.isPrimitiveValueType case tp: TypeProxy => isUnboundedGeneric(tp.translucentSuperType) case tp: AndType => isUnboundedGeneric(tp.tp1) && isUnboundedGeneric(tp.tp2) case tp: OrType => isUnboundedGeneric(tp.tp1) || isUnboundedGeneric(tp.tp2) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 2452081bf98c..968d93537d70 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -201,7 +201,10 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { private val (methPart, callTypeArgs, callValueArgss) = decomposeCall(call) private val inlinedMethod = methPart.symbol - private val inlineCallPrefix = qualifier(methPart) + private val inlineCallPrefix = + qualifier(methPart).orElse(This(inlinedMethod.enclosingClass.asClass)) + + inlining.println("-----------------------\nInlining $call\nWith RHS $rhsToInline") // Make sure all type arguments to the call are fully determined for (targ <- callTypeArgs) fullyDefinedType(targ.tpe, "inlined type argument", targ.span) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 9f2a64d555f8..17842ee8b63f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -803,6 +803,8 @@ class Namer { typer: Typer => private def addInlineInfo(sym: Symbol) = original match { case original: untpd.DefDef if sym.isInlineMethod => + if (sym.owner.isClass && sym.owner.seesOpaques) + ctx.error(em"Implementation restriction: No inline methods allowed where opaque type aliases are in scope", sym.sourcePos) PrepareInlineable.registerInlineInfo( sym, implicit ctx => typedAheadExpr(original).asInstanceOf[tpd.DefDef].rhs diff --git a/library/src-bootstrapped/scala/IArray.scala b/library/src-bootstrapped/scala/IArray.scala index 98697f41121b..16d92077b9ad 100644 --- a/library/src-bootstrapped/scala/IArray.scala +++ b/library/src-bootstrapped/scala/IArray.scala @@ -15,12 +15,28 @@ implicit object arrayOps { * @param n the index of the element to select * @return the element of the array at the given index */ - inline def (arr: IArray[T]) apply[T] (n: Int): T = arr.asInstanceOf[Array[T]].apply(n) + def (arr: IArray[Byte]) apply (n: Int): Byte = arr.asInstanceOf[Array[Byte]].apply(n) + def (arr: IArray[Short]) apply (n: Int): Short = arr.asInstanceOf[Array[Short]].apply(n) + def (arr: IArray[Char]) apply (n: Int): Char = arr.asInstanceOf[Array[Char]].apply(n) + def (arr: IArray[Int]) apply (n: Int): Int = arr.asInstanceOf[Array[Int]].apply(n) + def (arr: IArray[Long]) apply (n: Int): Long = arr.asInstanceOf[Array[Long]].apply(n) + def (arr: IArray[Float]) apply (n: Int): Float = arr.asInstanceOf[Array[Float]].apply(n) + def (arr: IArray[Double]) apply (n: Int): Double = arr.asInstanceOf[Array[Double]].apply(n) + def (arr: IArray[T]) apply[T <: Object] (n: Int): T = arr.asInstanceOf[Array[T]].apply(n) + def (arr: IArray[T]) apply[T] (n: Int): T = arr.asInstanceOf[Array[T]].apply(n) /** The number of elements in an immutable array * @param arr the immutable array */ - inline def (arr: IArray[T]) length[T] : Int = arr.asInstanceOf[Array[T]].length + def (arr: IArray[Byte]) length: Int = arr.asInstanceOf[Array[Byte]].length + def (arr: IArray[Short]) length: Int = arr.asInstanceOf[Array[Short]].length + def (arr: IArray[Char]) length: Int = arr.asInstanceOf[Array[Char]].length + def (arr: IArray[Int]) length: Int = arr.asInstanceOf[Array[Int]].length + def (arr: IArray[Long]) length: Int = arr.asInstanceOf[Array[Long]].length + def (arr: IArray[Float]) length: Int = arr.asInstanceOf[Array[Float]].length + def (arr: IArray[Double]) length: Int = arr.asInstanceOf[Array[Double]].length + def (arr: IArray[Object]) length: Int = arr.asInstanceOf[Array[Object]].length + def (arr: IArray[T]) length[T] : Int = arr.asInstanceOf[Array[T]].length } object IArray { diff --git a/tests/neg/inline3.scala b/tests/neg/inline3.scala new file mode 100644 index 000000000000..90a8ea9bb788 --- /dev/null +++ b/tests/neg/inline3.scala @@ -0,0 +1,28 @@ +object K0 { + + type T = String + + opaque type ProductInstances[F[_], T] = ErasedProductInstances[F[T]] + + inline def summonAsArray[F[_], T]: Array[Any] = ??? // error: Implementation restriction: No inline methods allowed + + inline def mkProductInstances[F[_], T]: ProductInstances[F, T] = // error: Implementation restriction: No inline methods allowed + new ErasedProductInstances(summonAsArray[F, T]).asInstanceOf[ProductInstances[F, T]] + + val x: T = "" + + inline def foo(x: T): T = "foo".asInstanceOf[T] // error: Implementation restriction: No inline methods allowed + +} + +final class ErasedProductInstances[FT](is0: => Array[Any]) + +trait Monoid[A] +case class ISB(i: Int) + +object Test { + //val K0 = new K0 + K0.foo(K0.x) + K0.mkProductInstances[Monoid, ISB] + +} \ No newline at end of file diff --git a/tests/run/opaque-immutable-array-xm.scala b/tests/run/opaque-immutable-array-xm.scala index ffd07c59047e..0052c7330d06 100644 --- a/tests/run/opaque-immutable-array-xm.scala +++ b/tests/run/opaque-immutable-array-xm.scala @@ -6,7 +6,7 @@ object Test extends App { opaque type IArray[A1] = Array[A1] implicit object IArray { - inline def initialize[A](body: => Array[A]): IArray[A] = body + def initialize[A](body: => Array[A]): IArray[A] = body def apply[A: ClassTag](xs: A*): IArray[A] = initialize(Array(xs: _*)) // These should be inline but that does not work currently. Try again