Skip to content

Commit 808818f

Browse files
som-snytttgodzik
authored andcommitted
Register nowarn when inlining
1 parent 2834aae commit 808818f

File tree

6 files changed

+82
-29
lines changed

6 files changed

+82
-29
lines changed

compiler/src/dotty/tools/dotc/Run.scala

+25-3
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ import Phases.{unfusedPhases, Phase}
1717
import sbt.interfaces.ProgressCallback
1818

1919
import util.*
20-
import reporting.{Suppression, Action, Profile, ActiveProfile, NoProfile}
21-
import reporting.Diagnostic
22-
import reporting.Diagnostic.Warning
20+
import reporting.{Suppression, Action, Profile, ActiveProfile, MessageFilter, NoProfile, WConf}
21+
import reporting.Diagnostic, Diagnostic.Warning
2322
import rewrites.Rewrites
2423
import profile.Profiler
2524
import printing.XprintMode
2625
import typer.ImplicitRunInfo
2726
import config.Feature
2827
import StdNames.nme
28+
import Spans.Span
2929

3030
import java.io.{BufferedWriter, OutputStreamWriter}
3131
import java.nio.charset.StandardCharsets
@@ -37,6 +37,8 @@ import scala.io.Codec
3737
import Run.Progress
3838
import scala.compiletime.uninitialized
3939
import dotty.tools.dotc.transform.MegaPhase
40+
import dotty.tools.dotc.util.chaining.*
41+
import java.util.{Timer, TimerTask}
4042

4143
/** A compiler run. Exports various methods to compile source files */
4244
class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with ConstraintRunInfo {
@@ -97,6 +99,26 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
9799
Action.Warning
98100
}
99101

102+
def registerNowarn(annotPos: SourcePosition, range: Span)(conf: String, pos: SrcPos)(using Context): Unit =
103+
var verbose = false
104+
val filters = conf match
105+
case "" =>
106+
List(MessageFilter.Any)
107+
case "none" =>
108+
List(MessageFilter.None)
109+
case "verbose" | "v" =>
110+
verbose = true
111+
List(MessageFilter.Any)
112+
case conf =>
113+
WConf.parseFilters(conf).left.map: parseErrors =>
114+
report.warning(s"Invalid message filter\n${parseErrors.mkString("\n")}", pos)
115+
List(MessageFilter.None)
116+
.merge
117+
addSuppression:
118+
Suppression(annotPos, filters, range.start, range.end, verbose)
119+
.tap: sup =>
120+
if filters == List(MessageFilter.None) then sup.markUsed() // invalid suppressions, don't report as unused
121+
100122
def addSuppression(sup: Suppression): Unit =
101123
val suppressions = mySuppressions.getOrElseUpdate(sup.annotPos.source, ListBuffer.empty)
102124
if sup.start != sup.end && suppressions.forall(x => x.start != sup.start || x.end != sup.end) then

compiler/src/dotty/tools/dotc/inlines/Inliner.scala

+14-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ object Inliner:
9898

9999
// InlinerMap is a TreeTypeMap with special treatment for inlined arguments:
100100
// They are generally left alone (not mapped further, and if they wrap a type
101-
// the type Inlined wrapper gets dropped
101+
// the type Inlined wrapper gets dropped.
102+
// As a side effect, register @nowarn annotations from annotated expressions.
102103
private class InlinerMap(
103104
typeMap: Type => Type,
104105
treeMap: Tree => Tree,
@@ -115,6 +116,18 @@ object Inliner:
115116
ConservativeTreeCopier()
116117
):
117118

119+
override def transform(tree: Tree)(using Context): Tree =
120+
tree match
121+
case Typed(expr, tpt) =>
122+
tpt.tpe match
123+
case AnnotatedType(_, annot) if annot.hasSymbol(defn.NowarnAnnot) =>
124+
val argPos = annot.argument(0).getOrElse(tree).sourcePos
125+
val conf = annot.argumentConstantString(0).getOrElse("")
126+
ctx.run.nn.suppressions.registerNowarn(tree.sourcePos, expr.span)(conf, argPos)
127+
case _ =>
128+
case _ =>
129+
super.transform(tree)
130+
118131
override def copy(
119132
typeMap: Type => Type,
120133
treeMap: Tree => Tree,

compiler/src/dotty/tools/dotc/inlines/Inlines.scala

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import collection.mutable
2323
import reporting.{NotConstant, trace}
2424
import util.Spans.Span
2525
import dotty.tools.dotc.core.Periods.PhaseId
26+
import dotty.tools.dotc.util.chaining.*
2627

2728
/** Support for querying inlineable methods and for inlining calls to such methods */
2829
object Inlines:
@@ -44,6 +45,11 @@ object Inlines:
4445
def bodyToInline(sym: SymDenotation)(using Context): Tree =
4546
if hasBodyToInline(sym) then
4647
sym.getAnnotation(defn.BodyAnnot).get.tree
48+
.tap: body =>
49+
for annot <- sym.getAnnotation(defn.NowarnAnnot) do
50+
val argPos = annot.argument(0).getOrElse(annot.tree).sourcePos
51+
val conf = annot.argumentConstantString(0).getOrElse("")
52+
ctx.run.nn.suppressions.registerNowarn(annot.tree.sourcePos, body.span)(conf, argPos)
4753
else
4854
EmptyTree
4955

compiler/src/dotty/tools/dotc/typer/Typer.scala

+9-25
Original file line numberDiff line numberDiff line change
@@ -2486,31 +2486,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
24862486

24872487
def registerNowarn(tree: Tree, mdef: untpd.Tree)(using Context): Unit =
24882488
val annot = Annotations.Annotation(tree)
2489-
def argPos = annot.argument(0).getOrElse(tree).sourcePos
2490-
var verbose = false
2491-
val filters = annot.argumentConstantString(0) match
2492-
case None => annot.argument(0) match
2493-
case Some(t: Select) if t.name.is(DefaultGetterName) =>
2494-
// default argument used for `@nowarn` and `@nowarn()`
2495-
List(MessageFilter.Any)
2496-
case _ =>
2497-
report.warning(s"filter needs to be a compile-time constant string", argPos)
2498-
List(MessageFilter.None)
2499-
case Some("") =>
2500-
List(MessageFilter.Any)
2501-
case Some("verbose") | Some("v") =>
2502-
verbose = true
2503-
List(MessageFilter.Any)
2504-
case Some(s) =>
2505-
WConf.parseFilters(s).left.map(parseErrors =>
2506-
report.warning (s"Invalid message filter\n${parseErrors.mkString ("\n")}", argPos)
2507-
List(MessageFilter.None)
2508-
).merge
2509-
val range = mdef.sourcePos
2510-
val sup = Suppression(tree.sourcePos, filters, range.start, range.end, verbose)
2511-
// invalid suppressions, don't report as unused
2512-
if filters == List(MessageFilter.None) then sup.markUsed()
2513-
ctx.run.nn.suppressions.addSuppression(sup)
2489+
val argPos = annot.argument(0).getOrElse(tree).sourcePos
2490+
val conf = annot.argumentConstantString(0).getOrElse:
2491+
annot.argument(0) match
2492+
case Some(t: Select) if t.name.is(DefaultGetterName) =>
2493+
"" // default argument used for `@nowarn` and `@nowarn()`
2494+
case _ =>
2495+
report.warning(s"filter needs to be a compile-time constant string", argPos)
2496+
"none" // not a -Wconf filter, mapped to MessageFilter.None by registerNowarn
2497+
ctx.run.nn.suppressions.registerNowarn(tree.sourcePos, mdef.span)(conf, argPos)
25142498

25152499
def typedValDef(vdef: untpd.ValDef, sym: Symbol)(using Context): Tree = ctx.profiler.onTypedDef(sym) {
25162500
val ValDef(name, tpt, _) = vdef

tests/warn/i22672/lib_1.scala

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
package p
3+
4+
import annotation.*
5+
6+
@deprecated("old api", since="1.0")
7+
def g = 42
8+
9+
//@deprecated("new api", since="1.0")
10+
@nowarn("cat=deprecation")
11+
inline def f =
12+
g
13+
14+
transparent inline def body =
15+
g: @nowarn

tests/warn/i22672/usage_2.scala

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
//> using options -deprecation
3+
4+
package q
5+
6+
def test = p.f // inline f is nowarn
7+
8+
def bodily = p.body // transparent inline with annotated body
9+
10+
@deprecated("do I even know how it works", since="0.1")
11+
def huh = "hello"
12+
13+
def failing = huh // warn

0 commit comments

Comments
 (0)