Skip to content

Commit

Permalink
SI-2458 Clarify spec for package syms (scala#5151)
Browse files Browse the repository at this point in the history
Package definitions are priority 4.

Update the big example to be cut/pastable.
  • Loading branch information
som-snytt authored and lrytz committed May 17, 2016
1 parent eac1af3 commit 061acd3
Showing 1 changed file with 54 additions and 37 deletions.
91 changes: 54 additions & 37 deletions spec/02-identifiers-names-and-scopes.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ which are collectively called _bindings_.
Bindings of different kinds have a precedence defined on them:

1. Definitions and declarations that are local, inherited, or made
available by a package clause in the same compilation unit where the
definition occurs have highest precedence.
available by a package clause and also defined in the same compilation unit
as the reference, have highest precedence.
1. Explicit imports have next highest precedence.
1. Wildcard imports have next highest precedence.
1. Definitions made available by a package clause not in the
compilation unit where the definition occurs have lowest precedence.
1. Definitions made available by a package clause, but not also defined in the
same compilation unit as the reference, have lowest precedence.

There are two different name spaces, one for [types](03-types.html#types)
and one for [terms](06-expressions.html#expressions). The same name may designate a
Expand All @@ -34,22 +34,18 @@ in some inner scope _shadows_ bindings of lower precedence in the
same scope as well as bindings of the same or lower precedence in outer
scopes.

<!-- TODO: either the example, the spec, or the compiler is wrong
Note that shadowing is only a partial order. In a situation like
Note that shadowing is only a partial order. In the following example,
neither binding of `x` shadows the other. Consequently, the
reference to `x` in the last line of the block is ambiguous.

```scala
val x = 1
{
import p.x
locally {
import p.X.x
x
}
```

neither binding of `x` shadows the other. Consequently, the
reference to `x` in the last line of the block above would be ambiguous.
-->

A reference to an unqualified (type- or term-) identifier $x$ is bound
by the unique binding, which

Expand All @@ -69,43 +65,64 @@ the member of the type $T$ of $e$ which has the name $x$ in the same
namespace as the identifier. It is an error if $T$ is not a [value type](03-types.html#value-types).
The type of $e.x$ is the member type of the referenced entity in $T$.

Binding precedence implies that the way source is bundled in files affects name resolution.
In particular, imported names have higher precedence than names, defined in other files,
that might otherwise be visible because they are defined in
either the current package or an enclosing package.

Note that a package definition is taken as lowest precedence, since packages
are open and can be defined across arbitrary compilation units.

```scala
package util {
import scala.util
class Random
object Test extends App {
println(new util.Random) // scala.util.Random
}
}
```

###### Example

Assume the following two definitions of objects named `X` in packages `P` and `Q`.
Assume the following two definitions of objects named `X` in packages `p` and `q`
in separate compilation units.

```scala
package P {
package p {
object X { val x = 1; val y = 2 }
}

package Q {
object X { val x = true; val y = "" }
package q {
object X { val x = true; val y = false }
}
```

The following program illustrates different kinds of bindings and
precedences between them.

```scala
package P { // `X' bound by package clause
import Console._ // `println' bound by wildcard import
object A {
println("L4: "+X) // `X' refers to `P.X' here
object B {
import Q._ // `X' bound by wildcard import
println("L7: "+X) // `X' refers to `Q.X' here
import X._ // `x' and `y' bound by wildcard import
println("L8: "+x) // `x' refers to `Q.X.x' here
object C {
val x = 3 // `x' bound by local definition
println("L12: "+x) // `x' refers to constant `3' here
{ import Q.X._ // `x' and `y' bound by wildcard import
// println("L14: "+x) // reference to `x' is ambiguous here
import X.y // `y' bound by explicit import
println("L16: "+y) // `y' refers to `Q.X.y' here
{ val x = "abc" // `x' bound by local definition
import P.X._ // `x' and `y' bound by wildcard import
// println("L19: "+y) // reference to `y' is ambiguous here
println("L20: "+x) // `x' refers to string "abc" here
package p { // `X' bound by package clause
import Console._ // `println' bound by wildcard import
object Y {
println(s"L4: $X") // `X' refers to `p.X' here
locally {
import q._ // `X' bound by wildcard import
println(s"L7: $X") // `X' refers to `q.X' here
import X._ // `x' and `y' bound by wildcard import
println(s"L9: $x") // `x' refers to `q.X.x' here
locally {
val x = 3 // `x' bound by local definition
println(s"L12: $x") // `x' refers to constant `3' here
locally {
import q.X._ // `x' and `y' bound by wildcard import
// println(s"L15: $x") // reference to `x' is ambiguous here
import X.y // `y' bound by explicit import
println(s"L17: $y") // `y' refers to `q.X.y' here
locally {
val x = "abc" // `x' bound by local definition
import p.X._ // `x' and `y' bound by wildcard import
// println(s"L21: $y") // reference to `y' is ambiguous here
println(s"L22: $x") // `x' refers to string "abc" here
}}}}}}
```

0 comments on commit 061acd3

Please sign in to comment.