Skip to content

Commit 1d3d0c4

Browse files
committed
Move warning to RefCheck
1 parent c46c9bf commit 1d3d0c4

File tree

4 files changed

+66
-58
lines changed

4 files changed

+66
-58
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,18 @@ object RefChecks {
11941194
report.warning(ExtensionNullifiedByMember(sym, target), sym.srcPos)
11951195
end checkExtensionMethods
11961196

1197+
/** Check that public (and protected) methods/fields do not expose flexible types. */
1198+
def checkPublicFlexibleTypes(sym: Symbol)(using Context): Unit =
1199+
if ctx.explicitNulls && !ctx.isJava
1200+
&& sym.exists && !sym.is(Private) && sym.owner.isClass
1201+
&& !sym.isOneOf(Synthetic | InlineProxy | Param) then
1202+
val resTp = sym.info.finalResultType
1203+
if resTp.existsPart(_.isInstanceOf[FlexibleType], StopAt.Static) then
1204+
report.warning(
1205+
em"${sym.show} exposes a flexible type in its inferred result type ${resTp}. Consider annotating the type explicitly",
1206+
sym.srcPos
1207+
)
1208+
11971209
/** Verify that references in the user-defined `@implicitNotFound` message are valid.
11981210
* (i.e. they refer to a type variable that really occurs in the signature of the annotated symbol.)
11991211
*/
@@ -1330,6 +1342,7 @@ class RefChecks extends MiniPhase { thisPhase =>
13301342
val sym = tree.symbol
13311343
checkNoPrivateOverrides(sym)
13321344
checkVolatile(sym)
1345+
checkPublicFlexibleTypes(sym)
13331346
if (sym.exists && sym.owner.isTerm) {
13341347
tree.rhs match {
13351348
case Ident(nme.WILDCARD) => report.error(UnboundPlaceholderParameter(), sym.srcPos)
@@ -1345,6 +1358,7 @@ class RefChecks extends MiniPhase { thisPhase =>
13451358
checkImplicitNotFoundAnnotation.defDef(sym.denot)
13461359
checkUnaryMethods(sym)
13471360
checkExtensionMethods(sym)
1361+
checkPublicFlexibleTypes(sym)
13481362
tree
13491363
}
13501364

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

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3089,32 +3089,13 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
30893089
//todo: make sure dependent method types do not depend on implicits or by-name params
30903090
}
30913091

3092-
/** (1) Check that the signature of the class member does not return a repeated parameter type.
3093-
* (2) Check that the signature of the public class member does not expose a flexible type.
3094-
* (3) Make sure the definition's symbol is `sym`.
3095-
* (4) Set the `defTree` of `sym` to be `mdef`.
3092+
/** (1) Check that the signature of the class member does not return a repeated parameter type
3093+
* (2) Make sure the definition's symbol is `sym`.
3094+
* (3) Set the `defTree` of `sym` to be `mdef`.
30963095
*/
30973096
private def postProcessInfo(mdef: MemberDef, sym: Symbol)(using Context): MemberDef =
30983097
if (!sym.isOneOf(Synthetic | InlineProxy | Param) && sym.info.finalResultType.isRepeatedParam)
30993098
report.error(em"Cannot return repeated parameter type ${sym.info.finalResultType}", sym.srcPos)
3100-
3101-
// Warn if a public method/field exposes FlexibleType in its result type under explicit nulls
3102-
// and encourage explicit annotation.
3103-
if ctx.phase.isTyper && ctx.explicitNulls && !ctx.isJava
3104-
&& sym.exists && sym.isPublic && sym.owner.isClass
3105-
&& !sym.isOneOf(Synthetic | InlineProxy | Param) then
3106-
val resTp = sym.info.finalResultType
3107-
if resTp.existsPart(_.isInstanceOf[FlexibleType], StopAt.Static) then
3108-
val suggestion = resTp match
3109-
case ft: FlexibleType =>
3110-
val hi = ft.hi
3111-
i"Consider annotating the type as ${hi} or ${hi} | Null explicitly"
3112-
case _ => "Consider annotating the type explicitly"
3113-
report.warning(
3114-
em"Public ${sym.show} exposes a flexible type ${resTp} in its inferred signature. $suggestion",
3115-
sym.srcPos
3116-
)
3117-
31183099
mdef.ensureHasSym(sym)
31193100
mdef.setDefTree
31203101

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,56 @@
1-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:2:6 --------------------------------------------------
2-
2 | def f = s.trim // warn
1+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:4:6 --------------------------------------------------
2+
4 | def f = s.trim // warn
33
| ^
4-
|Public method f exposes a flexible type (String)? in its inferred signature. Consider annotating the type as String or String | Null explicitly
5-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:6:6 --------------------------------------------------
6-
6 | def h = (s.trim, s.length) // warn
7-
| ^
8-
|Public method h exposes a flexible type ((String)?, Int) in its inferred signature. Consider annotating the type explicitly
9-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:7:6 --------------------------------------------------
10-
7 | val ss = s.replace("a", "A") // warn
11-
| ^
12-
|Public value ss exposes a flexible type (String)? in its inferred signature. Consider annotating the type as String or String | Null explicitly
4+
| method f exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly
135
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:8:6 --------------------------------------------------
14-
8 | val ss2 = Seq(s.trim) // warn
6+
8 | def h = (s.trim, s.length) // warn
157
| ^
16-
|Public value ss2 exposes a flexible type Seq[(String)?] in its inferred signature. Consider annotating the type explicitly
17-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:16:6 -------------------------------------------------
18-
16 | def f = s2.trim // warn
8+
|method h exposes a flexible type in its inferred result type ((String)?, Int). Consider annotating the type explicitly
9+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:9:16 -------------------------------------------------
10+
9 | protected def i = s.trim // warn
11+
| ^
12+
| method i exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly
13+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:11:19 ------------------------------------------------
14+
11 | private[foo] def k = s.trim // warn
15+
| ^
16+
| method k exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly
17+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:12:6 -------------------------------------------------
18+
12 | val ss = s.replace("a", "A") // warn
1919
| ^
20-
|Public method f exposes a flexible type (String)? in its inferred signature. Consider annotating the type as String or String | Null explicitly
21-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:20:6 -------------------------------------------------
22-
20 | def h = (s2.trim, s2.length) // warn
20+
| value ss exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly
21+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:13:6 -------------------------------------------------
22+
13 | val ss2 = Seq(s.trim) // warn
2323
| ^
24-
|Public method h exposes a flexible type ((String)?, Int) in its inferred signature. Consider annotating the type explicitly
24+
|value ss2 exposes a flexible type in its inferred result type Seq[(String)?]. Consider annotating the type explicitly
2525
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:21:6 -------------------------------------------------
26-
21 | val ss = s2.replace("a", "A") // warn
26+
21 | def f = s2.trim // warn
27+
| ^
28+
| method f exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly
29+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:25:6 -------------------------------------------------
30+
25 | def h = (s2.trim, s2.length) // warn
2731
| ^
28-
|Public value ss exposes a flexible type (String)? in its inferred signature. Consider annotating the type as String or String | Null explicitly
29-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:22:6 -------------------------------------------------
30-
22 | val ss2 = Seq(s2.trim) // warn
32+
|method h exposes a flexible type in its inferred result type ((String)?, Int). Consider annotating the type explicitly
33+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:26:6 -------------------------------------------------
34+
26 | val ss = s2.replace("a", "A") // warn
3135
| ^
32-
|Public value ss2 exposes a flexible type Seq[(String)?] in its inferred signature. Consider annotating the type explicitly
33-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:27:4 -------------------------------------------------
34-
27 |def f = s2.trim // warn
36+
| value ss exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly
37+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:27:6 -------------------------------------------------
38+
27 | val ss2 = Seq(s2.trim) // warn
39+
| ^
40+
|value ss2 exposes a flexible type in its inferred result type Seq[(String)?]. Consider annotating the type explicitly
41+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:32:4 -------------------------------------------------
42+
32 |def f = s2.trim // warn
3543
| ^
36-
|Public method f exposes a flexible type (String)? in its inferred signature. Consider annotating the type as String or String | Null explicitly
37-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:31:4 -------------------------------------------------
38-
31 |def h = (s2.trim, s2.length) // warn
44+
| method f exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly
45+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:36:4 -------------------------------------------------
46+
36 |def h = (s2.trim, s2.length) // warn
3947
| ^
40-
|Public method h exposes a flexible type ((String)?, Int) in its inferred signature. Consider annotating the type explicitly
41-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:32:4 -------------------------------------------------
42-
32 |val ss = s2.replace("a", "A") // warn
48+
|method h exposes a flexible type in its inferred result type ((String)?, Int). Consider annotating the type explicitly
49+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:37:4 -------------------------------------------------
50+
37 |val ss = s2.replace("a", "A") // warn
4351
| ^
44-
|Public value ss exposes a flexible type (String)? in its inferred signature. Consider annotating the type as String or String | Null explicitly
45-
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:33:4 -------------------------------------------------
46-
33 |val ss2 = Seq(s2.trim) // warn
52+
| value ss exposes a flexible type in its inferred result type (String)?. Consider annotating the type explicitly
53+
-- Warning: tests/explicit-nulls/warn/expose-flexible-types.scala:38:4 -------------------------------------------------
54+
38 |val ss2 = Seq(s2.trim) // warn
4755
| ^
48-
|Public value ss2 exposes a flexible type Seq[(String)?] in its inferred signature. Consider annotating the type explicitly
56+
|value ss2 exposes a flexible type in its inferred result type Seq[(String)?]. Consider annotating the type explicitly

tests/explicit-nulls/warn/expose-flexible-types.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
package foo
2+
13
class C(s: String):
24
def f = s.trim // warn
35
def g: String =
46
val s2 = s.trim
57
s2
68
def h = (s.trim, s.length) // warn
9+
protected def i = s.trim // warn
10+
private def j = s.trim
11+
private[foo] def k = s.trim // warn
712
val ss = s.replace("a", "A") // warn
813
val ss2 = Seq(s.trim) // warn
914
val ss3: Seq[String] =

0 commit comments

Comments
 (0)