4
4
5
5
# Summary
6
6
7
- Feature gate the shadowing of all namespaces between ` extern crate ` , ` use ` and items in the
8
- same scope, in order to restrict the module system to something more open to experimentation
9
- and changes post 1.0.
7
+ Remove or feature gate the shadowing of view items on the same scope level, in order to have less
8
+ complicated semantic and be more future proof for module system changes or experiments.
9
+
10
+ This means the names brought in scope by ` extern crate ` and ` use ` may never collide with
11
+ each other, nor with any other item (unless they live in different namespaces).
12
+ Eg, this will no longer work:
13
+
14
+ ``` rust
15
+ extern crate foo;
16
+ use foo :: bar :: foo; // ERROR: There is already a module `foo` in scope
17
+ ```
18
+
19
+ Shadowing would still be allowed in case of lexical scoping, so this continues to work:
20
+
21
+ ``` rust
22
+ extern crate foo;
23
+
24
+ fn bar () {
25
+ use foo :: bar :: foo; // Shadows the outer foo
26
+
27
+ foo :: baz ();
28
+ }
29
+
30
+ ```
31
+ # Definitions
32
+ Due to a certain lack of official, clearly defined semantics and terminology, a list of relevant
33
+ definitions is included:
34
+
35
+ - __ Scope__
36
+ A _ scope_ in Rust is basically defined by a block, following the rules of lexical
37
+ scoping:
38
+
39
+ ```
40
+ scope 1 (visible: scope 1)
41
+ {
42
+ scope 1-1 (visible: scope 1, scope 1-1)
43
+ {
44
+ scope 1-1-1 (visible: scope 1, scope 1-1, scope 1-1-1)
45
+ }
46
+ scope 1-1
47
+ {
48
+ scope 1-1-2
49
+ }
50
+ scope 1-1
51
+ }
52
+ scope 1
53
+ ```
54
+
55
+ Blocks include block expressions, ` fn ` items and ` mod ` items, but not things like
56
+ ` extern ` , ` enum ` or ` struct ` . Additionally, ` mod ` is special in that it isolates itself from
57
+ parent scopes.
58
+ - __ Scope Level__
59
+ Anything with the same name in the example above is on the same scope level.
60
+ In a scope level, all names defined in parent scopes are visible, but can be shadowed
61
+ by a new definition with the same name, which will be in scope for that scope itself and all its
62
+ child scopes.
63
+ - __ Namespace__
64
+ Rust has different namespaces, and the scoping rules apply to each one separately.
65
+ The exact number of different namespaces is not well defined, but they are roughly
66
+ - types (` enum Foo {} ` )
67
+ - modules (` mod foo {} ` )
68
+ - item values (` static FOO: uint = 0; ` )
69
+ - local values (` let foo = 0; ` )
70
+ - lifetimes (` impl<'a> ... ` )
71
+ - macros (` macro_rules! foo {...} ` )
72
+ - __ Definition Item__
73
+ Declarations that create new entities in a crate are called (by the author)
74
+ definition items. They include ` struct ` , ` enum ` , ` mod ` , ` fn ` , etc.
75
+ Each of them creates a name in the type, module, item value or macro namespace in the same
76
+ scope level they are written in.
77
+ - __ View Item__
78
+ Declarations that just create aliases to existing declarations in a crate are called
79
+ view items. They include ` use ` and ` extern crate ` , and also create a name in the type,
80
+ module, item value or macro namespace in the same scope level they are written in.
81
+ - __ Item__
82
+ Both definition items and view items together are collectively called items.
83
+ - __ Shadowing__
84
+ While the principle of shadowing exists in all namespaces, there are different forms of it:
85
+ - item-style: Declarations shadow names from outer scopes, and are visible everywhere in their
86
+ own, including lexically before their own definition.
87
+ This requires there to be only one definition with the same name and namespace per scope level.
88
+ Types, modules, item values and lifetimes fall under these rules.
89
+ - sequentially: Declarations shadow names that are lexically before them, both in parent scopes
90
+ and their own. This means you can reuse the same name in the same scope, but a definition
91
+ will not be visibly before itself. This is how local values and macros work.
92
+ (Due to sequential code execution and parsing, respectively)
93
+ - _ view item_ :
94
+ A special case exists with view items; In the same scope level,
95
+ ` extern crate ` creates entries in the module namespace, which are shadowable by names created
96
+ with ` use ` , which are shadowable with any definition item.
97
+ __ The singular goal of this RFC is to remove this shadowing behavior of view items__
10
98
11
99
# Motivation
12
100
13
- Currently , what is visible under which namespace in a given module is determined by a
14
- somewhat complicated three step process:
101
+ As explained above , what is currently visible under which namespace in a given scope is determined
102
+ by a somewhat complicated three step process:
15
103
16
104
1 . First, every ` extern crate ` item creates a name in the module namespace.
17
- 2 . Then, every ` use ` can create a name in any of the three namespaces ,
18
- where the module ones shadow the ` extern crate ` ones.
19
- 3 . Lastly, any declaration can shadow any name brought in scope by both ` extern crate ` and ` use ` .
105
+ 2 . Then, every ` use ` can create a name in any namespace ,
106
+ shadowing the ` extern crate ` ones.
107
+ 3 . Lastly, any definition item can shadow any name brought in scope by both ` extern crate ` and ` use ` .
20
108
21
109
These rules have developed mostly in response to the older, more complicated import system, and
22
- the existence of wildcard imports (` use foo::* ` ), which can cause the problem that user code breaks
23
- if a used crate gets updated to include a definition name the user has used himself.
110
+ the existence of wildcard imports (` use foo::* ` ).
111
+ In the case of wildcard imports, this shadowing behavior prevents local code from breaking if the
112
+ source module gets updated to include new names that happen to be defined locally.
24
113
25
- However, wildcard imports are now feature gated, and name conflicts can be resolved by using the
26
- renaming feature of ` extern crate ` and ` use ` , so in the current state of the language there is no
27
- need for this shadowing behavior.
114
+ However, wildcard imports are now feature gated, and name conflicts in general can be resolved by
115
+ using the renaming feature of ` extern crate ` and ` use ` , so in the current non-gated state
116
+ of the language there is no need for this shadowing behavior.
28
117
29
118
Gating it off opens the door to remove it altogether in a backwards compatible way, or to
30
- re-enable it in case globs get enabled again.
119
+ re-enable it in case wildcard imports are officially supported again.
120
+
121
+ It also makes the mental model around items simpler: Any shadowing of items happens through
122
+ lexical scoping only, and every item can be considered unordered and mutually recursive.
123
+
124
+ If this RFC gets accepted, a possible next step would be a RFC to lift the ordering restriction
125
+ between ` extern crate ` , ` use ` and definition items, which would make them truly behave the same in
126
+ regard to shadowing and the ability to be reordered. It would also lift the weirdness of
127
+ ` use foo::bar; mod foo; ` .
128
+
129
+ Implementing this RFC would also not change anything about how name resolution works, as its just
130
+ a tightening of the existing rules.
31
131
32
132
# Drawbacks
33
133
34
134
- Feature gating import shadowing might break some code using ` #[feature(globs)] ` .
35
- - The behavior of ` libstd ` s prelude either becomes more magical if it still allows shadowing,
36
- or more restricted if it doesn't allow shadowing.
135
+ - The behavior of ` libstd ` s prelude becomes more magical if it still allows shadowing,
136
+ but this could be de-magified again by a new feature, see below in unresolved questions.
137
+ - Or the utility of ` libstd ` s prelude becomes more restricted if it doesn't allow shadowing.
37
138
38
139
# Detailed design
39
140
40
141
A new feature gate ` import_shadowing ` gets created.
41
142
42
143
During the name resolution phase of compilation, every time the compiler detects a shadowing
43
- between ` extern crate ` , ` use ` and declarations in the same scope,
44
- it bails out unless the feature gate got enabled.
144
+ between ` extern crate ` , ` use ` and definition items in the same scope level,
145
+ it bails out unless the feature gate got enabled. This amounts to two rules:
146
+
147
+ - Items in the same scope level and either the type, module, item value or lifetime namespace
148
+ may not shadow each other in the respective namespace.
149
+ - Items may shadow names from outer scopes in any namespace.
45
150
46
151
Just like for the ` globs ` feature, the ` libstd ` prelude import would be preempt from this,
47
152
and still be allowed to be shadowed.
@@ -63,7 +168,7 @@ released.
63
168
from taking the same names.
64
169
65
170
On the other hand, it is also thinkable to simply forbid shadowing of prelude items as well,
66
- as defining things with the same name as std exports is unrecommended anyway, and this would
171
+ as defining things with the same name as std exports is not recommended anyway, and this would
67
172
nicely enforce that. It would however mean that the prelude can not change without breaking
68
173
backwards compatibility, which might be too restricting.
69
174
@@ -72,23 +177,6 @@ released.
72
177
could then simply use that, and users could define and use their own preludes as well.
73
178
But that's a somewhat orthogonal feature, and should be discussed in its own RFC.
74
179
75
- - Should scoped declarations fall under these rules as well?
76
-
77
- Currently, you can also shadow declarations and imports by using lexical scopes. For example,
78
- each struct definition shadows the prior one here:
79
- ``` rust
80
- struct Foo (());
81
- fn main () {
82
- struct Foo (());
83
- static FOO : () = {
84
- struct Foo (());
85
- ()
86
- };
87
- }
88
- ```
89
- That feature will probably stay, but there might be consistency problems
90
- or interactions with this proposal, which is why it is included in the discussion here.
91
-
92
180
- Interaction with overlapping imports.
93
181
94
182
Right now its legal to write this:
0 commit comments