Skip to content

Disallow inline methods and opaque types in same scope #6853

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Inliner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 18 additions & 2 deletions library/src-bootstrapped/scala/IArray.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
28 changes: 28 additions & 0 deletions tests/neg/inline3.scala
Original file line number Diff line number Diff line change
@@ -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]

}
2 changes: 1 addition & 1 deletion tests/run/opaque-immutable-array-xm.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down