diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index f6aba763da4e..d4a1126c5df7 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -442,7 +442,9 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => /** The purity level of this reference. * @return - * PurePath if reference is (nonlazy and stable) or to a parameterized function + * PurePath if reference is (nonlazy and stable) + * or to a parameterized function + * or its type is a constant type * IdempotentPath if reference is lazy and stable * Impure otherwise * @DarkDimius: need to make sure that lazy accessor methods have Lazy and Stable @@ -452,6 +454,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => val sym = tree.symbol if (!tree.hasType) Impure else if (!tree.tpe.widen.isParameterless || sym.isEffectivelyErased) PurePath + else if tree.tpe.isInstanceOf[ConstantType] then PurePath else if (!sym.isStableMember) Impure else if (sym.is(Module)) if (sym.moduleClass.isNoInitsClass) PurePath else IdempotentPath diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 8729abe877a8..73380bd7bbfd 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -727,7 +727,7 @@ object SymDenotations { */ final def isStableMember(implicit ctx: Context): Boolean = { def isUnstableValue = isOneOf(UnstableValueFlags) || info.isInstanceOf[ExprType] - isType || is(StableRealizable) || !isUnstableValue + isType || is(StableRealizable) || exists && !isUnstableValue } /** Is this a denotation of a class that does not have - either direct or inherited - diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index e51ad56e8a88..4d789c05ba85 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1082,7 +1082,7 @@ object Types { /** Widen type if it is unstable (i.e. an ExprType, or TermRef to unstable symbol */ final def widenIfUnstable(implicit ctx: Context): Type = stripTypeVar match { case tp: ExprType => tp.resultType.widenIfUnstable - case tp: TermRef if !tp.symbol.isStableMember => tp.underlying.widenIfUnstable + case tp: TermRef if tp.symbol.exists && !tp.symbol.isStableMember => tp.underlying.widenIfUnstable case _ => this } diff --git a/tests/run/i8058.scala b/tests/run/i8058.scala new file mode 100644 index 000000000000..b9ad34ba7282 --- /dev/null +++ b/tests/run/i8058.scala @@ -0,0 +1,10 @@ +extension on (x: Array[Char]): + inline def swap(i: Int, j: Int) : Unit = + val v = x(i) + x(i) = x(j) + x(j) = v + +@main def Test = + val a = Array('A','B') + a.swap(0, 1) + assert(a.toList == List('B', 'A')) \ No newline at end of file