@@ -3303,7 +3303,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
33033303 traverse(xtree :: rest)
33043304 case stat :: rest =>
33053305 val stat1 = typed(stat)(using ctx.exprContext(stat, exprOwner))
3306- if ! checkInterestingResultInStatement (stat1) then checkStatementPurity(stat1)(stat, exprOwner)
3306+ if ! Linter .warnOnInterestingResultInStatement (stat1) then checkStatementPurity(stat1)(stat, exprOwner)
33073307 buf += stat1
33083308 traverse(rest)(using stat1.nullableContext)
33093309 case nil =>
@@ -4361,123 +4361,18 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
43614361 tree match
43624362 case _ : RefTree | _ : Literal
43634363 if ! isVarPattern(tree) && ! (pt <:< tree.tpe) =>
4364- withMode(Mode .GadtConstraintInference ) {
4364+ withMode(Mode .GadtConstraintInference ):
43654365 TypeComparer .constrainPatternType(tree.tpe, pt)
4366- }
43674366
4368- // approximate type params with bounds
4369- def approx = new ApproximatingTypeMap {
4370- var alreadyExpanding : List [TypeRef ] = Nil
4371- def apply (tp : Type ) = tp.dealias match
4372- case tp : TypeRef if ! tp.symbol.isClass =>
4373- if alreadyExpanding contains tp then tp else
4374- val saved = alreadyExpanding
4375- alreadyExpanding ::= tp
4376- val res = expandBounds(tp.info.bounds)
4377- alreadyExpanding = saved
4378- res
4379- case _ =>
4380- mapOver(tp)
4381- }
4367+ Linter .warnOnImplausiblePattern(tree, pt)
43824368
4383- // Is it possible that a value of `clsA` is equal to a value of `clsB`?
4384- // This ignores user-defined equals methods, but makes an exception
4385- // for numeric classes.
4386- def canOverlap (clsA : ClassSymbol , clsB : ClassSymbol ): Boolean =
4387- clsA.mayHaveCommonChild(clsB)
4388- || clsA.isNumericValueClass // this is quite coarse, but matches to what was done before
4389- || clsB.isNumericValueClass
4390-
4391- // Can type `a` possiblly have a common instance with type `b`?
4392- def canEqual (a : Type , b : Type ): Boolean = trace(i " canEqual $a $b" ):
4393- b match
4394- case _ : TypeRef | _ : AppliedType if b.typeSymbol.isClass =>
4395- a match
4396- case a : TermRef if a.symbol.isOneOf(Module | Enum ) =>
4397- (a frozen_<:< b) // fast track
4398- || (a frozen_<:< approx(b))
4399- case _ : TypeRef | _ : AppliedType if a.typeSymbol.isClass =>
4400- if a.isNullType then ! b.isNotNull
4401- else canOverlap(a.typeSymbol.asClass, b.typeSymbol.asClass)
4402- case a : TypeProxy =>
4403- canEqual(a.superType, b)
4404- case a : AndOrType =>
4405- canEqual(a.tp1, b) || canEqual(a.tp2, b)
4406- case b : TypeProxy =>
4407- canEqual(a, b.superType)
4408- case b : AndOrType =>
4409- // we lose precision with and/or types, but it's hard to do better and
4410- // still compute `canEqual(A & B, B & A) = true`.
4411- canEqual(a, b.tp1) || canEqual(a, b.tp2)
4412-
4413- if ! canEqual(tree.tpe, pt) then
4414- // We could check whether `equals` is overridden.
4415- // Reasons for not doing so:
4416- // - it complicates the protocol
4417- // - such code patterns usually implies hidden errors in the code
4418- // - it's safe/sound to reject the code
4419- report.error(TypeMismatch (tree.tpe, pt, Some (tree), " \n pattern type is incompatible with expected type" ), tree.srcPos)
4420- else
4421- val cmp =
4422- untpd.Apply (
4423- untpd.Select (untpd.TypedSplice (tree), nme.EQ ),
4424- untpd.TypedSplice (dummyTreeOfType(pt)))
4425- typedExpr(cmp, defn.BooleanType )
4369+ val cmp =
4370+ untpd.Apply (
4371+ untpd.Select (untpd.TypedSplice (tree), nme.EQ ),
4372+ untpd.TypedSplice (dummyTreeOfType(pt)))
4373+ typedExpr(cmp, defn.BooleanType )
44264374 case _ =>
44274375
4428- private def checkInterestingResultInStatement (t : Tree )(using Context ): Boolean = {
4429- def isUninterestingSymbol (sym : Symbol ): Boolean =
4430- sym == NoSymbol ||
4431- sym.isConstructor ||
4432- sym.is(Package ) ||
4433- sym.isPackageObject ||
4434- sym == defn.BoxedUnitClass ||
4435- sym == defn.AnyClass ||
4436- sym == defn.AnyRefAlias ||
4437- sym == defn.AnyValClass
4438- def isUninterestingType (tpe : Type ): Boolean =
4439- tpe == NoType ||
4440- tpe.typeSymbol == defn.UnitClass ||
4441- defn.isBottomClass(tpe.typeSymbol) ||
4442- tpe =:= defn.UnitType ||
4443- tpe.typeSymbol == defn.BoxedUnitClass ||
4444- tpe =:= defn.AnyValType ||
4445- tpe =:= defn.AnyType ||
4446- tpe =:= defn.AnyRefType
4447- def isJavaApplication (t : Tree ): Boolean = t match {
4448- case Apply (f, _) => f.symbol.is(JavaDefined ) && ! defn.ObjectClass .isSubClass(f.symbol.owner)
4449- case _ => false
4450- }
4451- def checkInterestingShapes (t : Tree ): Boolean = t match {
4452- case If (_, thenpart, elsepart) => checkInterestingShapes(thenpart) || checkInterestingShapes(elsepart)
4453- case Block (_, res) => checkInterestingShapes(res)
4454- case Match (_, cases) => cases.exists(k => checkInterestingShapes(k.body))
4455- case _ => checksForInterestingResult(t)
4456- }
4457- def checksForInterestingResult (t : Tree ): Boolean = (
4458- ! t.isDef // ignore defs
4459- && ! isUninterestingSymbol(t.symbol) // ctors, package, Unit, Any
4460- && ! isUninterestingType(t.tpe) // bottom types, Unit, Any
4461- && ! isThisTypeResult(t) // buf += x
4462- && ! isSuperConstrCall(t) // just a thing
4463- && ! isJavaApplication(t) // Java methods are inherently side-effecting
4464- // && !treeInfo.hasExplicitUnit(t) // suppressed by explicit expr: Unit // TODO Should explicit `: Unit` be added as warning suppression?
4465- )
4466- if ctx.settings.WNonUnitStatement .value && ! ctx.isAfterTyper && checkInterestingShapes(t) then
4467- val where = t match {
4468- case Block (_, res) => res
4469- case If (_, thenpart, Literal (Constant (()))) =>
4470- thenpart match {
4471- case Block (_, res) => res
4472- case _ => thenpart
4473- }
4474- case _ => t
4475- }
4476- report.warning(UnusedNonUnitValue (where.tpe), t.srcPos)
4477- true
4478- else false
4479- }
4480-
44814376 private def checkStatementPurity (tree : tpd.Tree )(original : untpd.Tree , exprOwner : Symbol )(using Context ): Unit =
44824377 if ! tree.tpe.isErroneous
44834378 && ! ctx.isAfterTyper
0 commit comments