diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 585dc3743dc2..39a503cecee3 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -284,8 +284,9 @@ object Types { /** Is this type produced as a repair for an error? */ final def isError(implicit ctx: Context): Boolean = stripTypeVar.isInstanceOf[ErrorType] - /** Is some part of this type produced as a repair for an error? */ - def isErroneous(implicit ctx: Context): Boolean = existsPart(_.isError, forceLazy = false) + /** Is some part of the widened version of this type produced as a repair for an error? */ + def isErroneous(implicit ctx: Context): Boolean = + widen.existsPart(_.isError, forceLazy = false) /** Does the type carry an annotation that is an instance of `cls`? */ @tailrec final def hasAnnotation(cls: ClassSymbol)(implicit ctx: Context): Boolean = stripTypeVar match { diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 474da45bb114..56923eb93cb9 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -367,7 +367,7 @@ object ProtoTypes { def isDropped: Boolean = state.toDrop override def isErroneous(implicit ctx: Context): Boolean = - state.typedArgs.tpes.exists(_.widen.isErroneous) + state.typedArgs.tpes.exists(_.isErroneous) override def toString: String = s"FunProto(${args mkString ","} => $resultType)" diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index fd6df929d16f..c0c773fcf03c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -735,7 +735,7 @@ class Typer extends Namer val ptDefined = isFullyDefined(pt, ForceDegree.none) if (ptDefined && !(avoidingType <:< pt)) avoidingType = pt val tree1 = ascribeType(tree, avoidingType) - assert(ptDefined || noLeaks(tree1) || tree1.tpe.widen.isErroneous, + assert(ptDefined || noLeaks(tree1) || tree1.tpe.isErroneous, // `ptDefined` needed because of special case of anonymous classes i"leak: ${escapingRefs(tree1, localSyms).toList}%, % in $tree1") tree1 @@ -2897,7 +2897,8 @@ class Typer extends Namer } private def checkStatementPurity(tree: tpd.Tree)(original: untpd.Tree, exprOwner: Symbol)(implicit ctx: Context): Unit = { - if (!ctx.isAfterTyper && isPureExpr(tree) && !tree.tpe.isRef(defn.UnitClass) && !isSelfOrSuperConstrCall(tree)) + if (!tree.tpe.isErroneous && !ctx.isAfterTyper && isPureExpr(tree) && + !tree.tpe.isRef(defn.UnitClass) && !isSelfOrSuperConstrCall(tree)) ctx.warning(PureExpressionInStatementPosition(original, exprOwner), original.sourcePos) } } diff --git a/tests/neg-custom-args/fatal-warnings/pureStatement.scala b/tests/neg-custom-args/fatal-warnings/pureStatement.scala index ac1a2026aae1..e05a258a9f37 100644 --- a/tests/neg-custom-args/fatal-warnings/pureStatement.scala +++ b/tests/neg-custom-args/fatal-warnings/pureStatement.scala @@ -25,4 +25,8 @@ object Test { 2 // error: pure expression does nothing in statement position doSideEffects(1) // error: pure expression does nothing in statement position + + val broken = new IDontExist("") // error // error + broken.foo // no extra error, and no pure expression warning + broken.foo() // same }