Skip to content

Commit c8e0ae7

Browse files
committed
Alternatively, make export method synthetic & handle that
1 parent 08aae95 commit c8e0ae7

File tree

8 files changed

+72
-57
lines changed

8 files changed

+72
-57
lines changed

compiler/src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,6 @@ object Symbols extends SymUtils {
341341
}
342342
else if (denot.isPrimaryConstructor)
343343
denot.owner.sourceSymbol
344-
else if denot.is(Exported) then
345-
denot.info.finalResultType match
346-
case TypeAlias(target: NamedType) => target.symbol.sourceSymbol // exported type
347-
case target: NamedType => target.symbol.sourceSymbol // exported term
348-
case info => this
349344
else this
350345

351346
/** The position of this symbol, or NoSpan if the symbol was not loaded

compiler/src/dotty/tools/dotc/interactive/SourceTree.scala

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,7 @@ case class SourceTree(tree: tpd.Import | tpd.NameTree, source: SourceFile) {
4242
(treeSpan.end - nameLength, treeSpan.end)
4343
Span(start, end, start)
4444
}
45-
// Don't widen the span, only narrow.
46-
// E.g. The star in a wildcard export is 1 character,
47-
// and that is the span of the type alias that results from it
48-
// but the name may very well be larger, which we don't want.
49-
val span1 = if treeSpan.contains(position) then position else treeSpan
50-
source.atSpan(span1)
45+
source.atSpan(position)
5146
}
5247
case _ =>
5348
NoSourcePosition

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1239,7 +1239,7 @@ class Namer { typer: Typer =>
12391239
(EmptyFlags, mbrInfo)
12401240
var flagMask = RetainedExportFlags
12411241
if sym.isTerm then flagMask |= HasDefaultParams | NoDefaultParams
1242-
var mbrFlags = Exported | Method | Final | maybeStable | sym.flags & flagMask
1242+
var mbrFlags = Exported | Synthetic | Method | Final | maybeStable | sym.flags & flagMask
12431243
if sym.is(ExtensionMethod) || pathMethod.exists then
12441244
mbrFlags |= ExtensionMethod
12451245
val forwarderName = checkNoConflict(alias, isPrivate = false, span)

presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import dotty.tools.dotc.core.Flags.*
1010
import dotty.tools.dotc.core.Names.Name
1111
import dotty.tools.dotc.core.StdNames
1212
import dotty.tools.dotc.core.Symbols.*
13-
import dotty.tools.dotc.core.Types.Type
13+
import dotty.tools.dotc.core.Types.*
1414
import dotty.tools.dotc.interactive.SourceTree
1515
import dotty.tools.dotc.util.SourceFile
1616
import dotty.tools.dotc.util.SourcePosition
@@ -109,14 +109,15 @@ object MetalsInteractive:
109109
* Returns the list of tuple enclosing symbol and
110110
* the symbol's expression type if possible.
111111
*/
112+
@tailrec
112113
def enclosingSymbolsWithExpressionType(
113114
path: List[Tree],
114115
pos: SourcePosition,
115116
indexed: IndexedContext,
116117
skipCheckOnName: Boolean = false
117118
): List[(Symbol, Type)] =
118119
import indexed.ctx
119-
@tailrec def go(path: List[Tree]): List[(Symbol, Type)] = path match
120+
path match
120121
// For a named arg, find the target `DefDef` and jump to the param
121122
case NamedArg(name, _) :: Apply(fn, _) :: _ =>
122123
val funSym = fn.symbol
@@ -204,8 +205,24 @@ object MetalsInteractive:
204205
Nil
205206

206207
case path @ head :: tail =>
207-
if head.symbol.is(Synthetic) then
208-
go(tail)
208+
if head.symbol.is(Exported) then
209+
head.symbol.info match
210+
case TypeAlias(target: NamedType) =>
211+
val ss = target.symbol.sourceSymbol // exported type
212+
List((ss, ss.info))
213+
case info => info.finalResultType match
214+
case target: NamedType =>
215+
val ss = target.symbol.sourceSymbol // exported term
216+
List((ss, ss.info))
217+
case _ =>
218+
enclosingSymbolsWithExpressionType(tail, pos, indexed, skipCheckOnName)
219+
else if head.symbol.is(Synthetic) then
220+
enclosingSymbolsWithExpressionType(
221+
tail,
222+
pos,
223+
indexed,
224+
skipCheckOnName
225+
)
209226
else if head.symbol != NoSymbol then
210227
if skipCheckOnName ||
211228
MetalsInteractive.isOnName(
@@ -219,24 +236,21 @@ object MetalsInteractive:
219236
* https://github.com/lampepfl/dotty/issues/15937
220237
*/
221238
else if head.isInstanceOf[TypeTree] then
222-
go(tail)
239+
enclosingSymbolsWithExpressionType(tail, pos, indexed)
223240
else Nil
224241
else
225242
val recovered = recoverError(head, indexed)
226243
if recovered.isEmpty then
227-
go(tail)
244+
enclosingSymbolsWithExpressionType(
245+
tail,
246+
pos,
247+
indexed,
248+
skipCheckOnName
249+
)
228250
else recovered.map(sym => (sym, sym.info))
229251
end if
230252
case Nil => Nil
231-
end go
232-
go(path).map { (sym, tp) =>
233-
if sym.is(Synthetic) && sym.name == StdNames.nme.apply then
234-
(sym, tp) // return synthetic apply, rather than the apply's owner
235-
else if sym.isClassConstructor && sym.isPrimaryConstructor then
236-
(sym, tp) // return the class constructor, rather than the class (so skip trait constructors)
237-
else
238-
(sym.sourceSymbol, tp)
239-
}
253+
end match
240254
end enclosingSymbolsWithExpressionType
241255

242256
import dotty.tools.pc.utils.MtagsEnrichments.*

tests/neg/export-leaks.check

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-- [E006] Not Found Error: tests/neg/export-leaks.scala:24:13 ----------------------------------------------------------
2+
24 | val t1 = bar // error: Not found: bar
3+
| ^^^
4+
| Not found: bar
5+
|
6+
| longer explanation available when compiling with `-explain`
7+
-- [E006] Not Found Error: tests/neg/export-leaks.scala:25:13 ----------------------------------------------------------
8+
25 | val t2 = foo // error: Not found: foo
9+
| ^^^
10+
| Not found: foo
11+
|
12+
| longer explanation available when compiling with `-explain`

tests/neg/export-leaks.scala

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,20 @@ object Signature {
66
object O1 {
77
private[Signature] def bar: T = ???
88
}
9-
export O1._ // error: non-private method bar refers to private type T
9+
export O1._
1010

1111
object O2 {
1212
private[Signature] val foo: T = ???
1313
}
14-
export O2._ // error: non-private method foo refers to private type T
15-
}
14+
export O2._
15+
16+
object PosTest:
17+
def main(args: Array[String]): Unit =
18+
val t1 = bar // ok
19+
val t2 = foo // ok
20+
}
21+
22+
object Test:
23+
def main(args: Array[String]): Unit =
24+
val t1 = bar // error: Not found: bar
25+
val t2 = foo // error: Not found: foo

tests/neg/exports.check

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,21 @@
77
| ^^^^^^^^^^^^^^
88
| no eligible member scanAll at this.scanUnit
99
| this.scanUnit.scanAll cannot be exported because it is not accessible
10-
-- Error: tests/neg/exports.scala:25:21 --------------------------------------------------------------------------------
11-
25 | export printUnit.bitmap // error: no eligible member
12-
| ^
13-
| non-private given instance bitmap in class Copier refers to private value printUnit
14-
| in its type signature => object Copier.this.printUnit.bitmap
10+
-- [E120] Naming Error: tests/neg/exports.scala:28:8 -------------------------------------------------------------------
11+
28 | def status: List[String] = printUnit.status ++ scanUnit.status // error: double definition w/ printUnit.status
12+
| ^
13+
| Double definition:
14+
| final def status: List[String] in class Copier at line 23 and
15+
| def status: List[String] in class Copier at line 28
16+
| have the same type after erasure.
17+
|
18+
| Consider adding a @targetName annotation to one of the conflicting definitions
19+
| for disambiguation.
1520
-- [E120] Naming Error: tests/neg/exports.scala:23:33 ------------------------------------------------------------------
1621
23 | export printUnit.{stat => _, _} // error: double definition
1722
| ^
1823
| Double definition:
19-
| def status: List[String] in class Copier at line 28 and
24+
| final def status: List[String] in class Copier at line 24 and
2025
| final def status: List[String] in class Copier at line 23
2126
| have the same type after erasure.
2227
|
@@ -26,22 +31,12 @@
2631
24 | export scanUnit._ // error: double definition
2732
| ^
2833
| Double definition:
29-
| final def status: List[String] in class Copier at line 23 and
34+
| final def status: List[String] in class Copier at line 26 and
3035
| final def status: List[String] in class Copier at line 24
3136
| have the same type after erasure.
3237
|
3338
| Consider adding a @targetName annotation to one of the conflicting definitions
3439
| for disambiguation.
35-
-- [E120] Naming Error: tests/neg/exports.scala:26:21 ------------------------------------------------------------------
36-
26 | export printUnit.status // error: double definition
37-
| ^
38-
| Double definition:
39-
| final def status: List[String] in class Copier at line 24 and
40-
| final def status: List[String] in class Copier at line 26
41-
| have the same type after erasure.
42-
|
43-
| Consider adding a @targetName annotation to one of the conflicting definitions
44-
| for disambiguation.
4540
-- Error: tests/neg/exports.scala:35:24 --------------------------------------------------------------------------------
4641
35 | export this.{concat => ++} // error: no eligible member
4742
| ^^^^^^^^^^^^
@@ -52,12 +47,6 @@
5247
| ^^^
5348
| no eligible member foo at this.foo
5449
| this.foo.foo cannot be exported because it is already a member of class Foo
55-
-- [E120] Naming Error: tests/neg/exports.scala:46:15 ------------------------------------------------------------------
56-
46 | export bar._ // error: double definition
57-
| ^
58-
| Double definition:
59-
| val bar: Bar in class Baz at line 45 and
60-
| final def bar: (Baz.this.bar.bar : => (Baz.this.bar.baz.bar : Bar)) in class Baz at line 46
6150
-- [E083] Type Error: tests/neg/exports.scala:57:11 --------------------------------------------------------------------
6251
57 | export printer.* // error: not stable
6352
| ^^^^^^^

tests/neg/exports.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
export scanUnit.{scanAll => foo} // error: no eligible member
2323
export printUnit.{stat => _, _} // error: double definition
2424
export scanUnit._ // error: double definition
25-
export printUnit.bitmap // error: no eligible member
26-
export printUnit.status // error: double definition
25+
export printUnit.bitmap
26+
export printUnit.status
2727

28-
def status: List[String] = printUnit.status ++ scanUnit.status
28+
def status: List[String] = printUnit.status ++ scanUnit.status // error: double definition w/ printUnit.status
2929
}
3030

3131
trait IterableOps[+A, +CC[_], +C] {
@@ -43,7 +43,7 @@
4343

4444
class Baz {
4545
val bar: Bar = new Bar
46-
export bar._ // error: double definition
46+
export bar._
4747
}
4848
class Bar {
4949
val baz: Baz = new Baz

0 commit comments

Comments
 (0)