Skip to content

Commit 5545b67

Browse files
committed
Apply leftover changes from office hours
1 parent f145355 commit 5545b67

File tree

3 files changed

+169
-38
lines changed

3 files changed

+169
-38
lines changed

src/macros-by-example.md

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,23 +330,33 @@ r[macro.decl.scope.textual.shadow.path-based]
330330
Textual scope name bindings for macros shadow path-based scope bindings to macros.
331331

332332
```rust
333-
#[macro_export]
334333
macro_rules! m2 {
335334
() => {
336335
println!("m2");
337336
};
338337
}
339338

339+
// Resolves to path-based candidate from use declaration below.
340340
m!(); // prints "m2\n"
341341

342+
// Introduce second candidate for `m` with textual scope.
343+
//
344+
// This shadows path-based candidate from below for the rest of this
345+
// example.
342346
macro_rules! m {
343347
() => {
344348
println!("m");
345349
};
346350
}
347351

352+
// Introduce m2 macro as path-based candidate.
353+
//
354+
// This item is in scope for this entire example, not just below the
355+
// use declaration.
348356
use crate::m2 as m;
349357

358+
// Resolves to the textual macro candidate from above the use
359+
// declaration.
350360
m!(); // prints "m\n"
351361
```
352362

@@ -370,31 +380,52 @@ Macros can be re-exported to give them path-based scope from a module other than
370380
mac::m!(); // OK: Path-based lookup finds m in the mac module.
371381

372382
mod mac {
383+
// Introduce macro m with textual scope.
373384
macro_rules! m {
374385
() => {};
375386
}
387+
388+
// Re-export with path-based scope from within m's textual scope.
376389
pub(crate) use m;
377390
}
378391
```
379392

380393
r[macro.decl.scope.path-based.visibility]
381394
Macros have an implicit visibility of `pub(crate)`. `#[macro_export]` changes the implicit visibility to `pub`.
382395

383-
```rust,compile_fail,E0364
396+
```rust
397+
// Implicit visibility is `pub(crate)`.
384398
macro_rules! private_m {
385399
() => {};
386400
}
387401

402+
// Implicit visibility is `pub`.
388403
#[macro_export]
389404
macro_rules! pub_m {
390405
() => {};
391406
}
392407

393-
pub(crate) use private_m as private_macro; // OK
394-
pub use pub_m as pub_macro; // OK
408+
pub(crate) use private_m as private_macro; // OK.
409+
pub use pub_m as pub_macro; // OK.
410+
```
395411

412+
```rust,compile_fail,E0364
413+
# // Implicit visibility is `pub(crate)`.
414+
# macro_rules! private_m {
415+
# () => {};
416+
# }
417+
#
418+
# // Implicit visibility is `pub`.
419+
# #[macro_export]
420+
# macro_rules! pub_m {
421+
# () => {};
422+
# }
423+
#
424+
# pub(crate) use private_m as private_macro; // OK.
425+
# pub use pub_m as pub_macro; // OK.
426+
#
396427
pub use private_m; // ERROR: `private_m` is only public within
397-
// the crate and cannot be re-exported outside
428+
// the crate and cannot be re-exported outside.
398429
```
399430

400431
<!-- template:attributes -->

src/names/name-resolution.md

Lines changed: 132 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,7 @@ r[names.resolution.expansion.imports.ambiguity]
147147
#### Ambiguities
148148

149149
r[names.resolution.expansion.imports.ambiguity.intro]
150-
Some situations are an error when there is an ambiguity as to which macro definition, `use` declaration, or module an import or macro invocation's name refers to. This happens when there are two name candidates that do not resolve to the same entity where neither candidate is [permitted] to shadow the other.
151-
152-
TODO rewrite
150+
There are certain situations during expansion-time resolution where there are multiple macro definitions, `use` declarations, or modules an import or macro invocation's name could refer to where the compiler cannot consistently determine which candidate should shadow the other. Shadowing cannot be permitted in these situations and the compiler instead emits ambiguity errors.
153151

154152
r[names.resolution.expansion.imports.ambiguity.glob-vs-glob]
155153
Names may not be resolved through ambiguous glob imports. Glob imports are allowed to import conflicting names in the same namespace as long as the name is not used. Names with conflicting candidates from ambiguous glob imports may still be shadowed by non-glob imports and used without producing an error. The errors occur at time of use, not time of import.
@@ -165,11 +163,13 @@ mod m2 {
165163
pub struct Ambig;
166164
}
167165
166+
// OK: This brings conficting names into scope and namespace
167+
// but they have not been used yet.
168168
use m1::*;
169-
use m2::*; // OK: No name conflict.
169+
use m2::*;
170170
171171
fn ambiguous_use() {
172-
let x = Ambig; // ERROR: `Ambig` is ambiguous
172+
let x = Ambig; // ERROR: `Ambig` is ambiguous.
173173
}
174174
```
175175

@@ -199,38 +199,44 @@ mod m1 {
199199
}
200200

201201
mod m2 {
202+
// This re-exports the same `Ambig` item through a second module.
202203
pub use super::m1::Ambig;
203204
}
204205

205-
// These both import the same `Ambig`. The visibility of `Ambig` is
206-
// `pub` because that is the maximum visibility between these two `use`
207-
// declarations.
208-
pub use m2::*;
209-
use m1::*;
206+
// These both import the same `Ambig`.
207+
//
208+
// The visibility of `Ambig` is `pub` because that is the
209+
// maximum visibility between these two `use` declarations.
210+
mod m3 {
211+
pub use super::m1::*;
212+
use super::m2::*;
213+
}
210214

211215
fn main() {
212-
let _: Ambig = Ambig;
216+
// `Ambig` can be used through the m3
217+
// globs and still has `pub` visibility.
218+
let _ = m3::Ambig;
213219
}
214220
```
215-
// TODO update example to rely upon visibilty for compilation success
216221

217222
r[names.resolution.expansion.imports.ambiguity.glob-vs-outer]
218-
Names may not be resolved through glob imports when there is another candidate available in an [outer scope].
223+
Names in imports and macro invocations may not be resolved through glob imports when there is another candidate available in an [outer scope].
219224

220225
```rust,compile_fail,E0659
221226
mod glob {
222227
pub mod ambig {
223-
// ^-- glob `ambig` candidate
224228
pub struct Name;
225229
}
226230
}
227231
232+
// Outer `ambig` candidate.
228233
pub mod ambig {
229-
// ^-- outer `ambig` candidate
230234
pub struct Name;
231235
}
232236
233237
const _: () = {
238+
// Cannot resolve `ambig` through this glob
239+
// because of the outer `ambig` candidate above.
234240
use glob::*;
235241
use ambig::Name; // ERROR: `ambig` is ambiguous.
236242
};
@@ -258,7 +264,7 @@ const _: () = {
258264
```
259265

260266
> [!NOTE]
261-
> These ambiguity errors are specific to imports, even though they are only observed when those imports are used. Having multiple candidates available for a given name during later stages of resolution is not considered an error. So long as none of the imports themselves are ambiguous, there will always be a single unambiguous closest resolution.
267+
> These ambiguity errors are specific to expansion-time resolution. Having multiple candidates available for a given name during later stages of resolution is not considered an error. So long as none of the imports themselves are ambiguous, there will always be a single unambiguous closest resolution.
262268
>
263269
> ```rust
264270
> mod glob {
@@ -282,26 +288,29 @@ r[names.resolution.expansion.imports.ambiguity.path-vs-textual-macro]
282288
Names may not be resolved through ambiguous macro re-exports. Macro re-exports are ambiguous when they would shadow a textual macro candidate for the same name in an [outer scope].
283289
284290
```rust,compile_fail,E0659
291+
// Textual macro candidate.
285292
macro_rules! ambig {
286-
// ^---- textual macro candidate
287293
() => {}
288294
}
289295
296+
// Path-based macro candidate.
290297
macro_rules! path_based {
291-
// ^--- path-based macro candidate
292298
() => {}
293299
}
294300
295301
pub fn f() {
302+
// This re-export of the `path_based` macro definition
303+
// as `ambig` may not shadow the `ambig` macro definition
304+
// which is resolved via textual macro scope.
305+
use path_based as ambig;
296306
ambig!(); // ERROR: `ambig` is ambiguous.
297-
use path_based as ambig; // In scope for entire function body.
298307
}
299308
```
300309
301-
// [!NOTE]
302-
// This restriction is needed due to implementation details in the compiler,
303-
// specifically the current scope visitation logic and the complexity of supporting
304-
// this behavior. This ambiguity error may be removed in the future.
310+
> [!NOTE]
311+
> This restriction is needed due to implementation details in the compiler,
312+
> specifically the current scope visitation logic and the complexity of supporting
313+
> this behavior. This ambiguity error may be removed in the future.
305314
306315
r[names.resolution.expansion.macros]
307316
### Macros
@@ -345,25 +354,118 @@ r[names.resolution.expansion.macros.ambiguity]
345354
#### Ambiguities
346355

347356
r[names.resolution.expansion.macros.ambiguity.more-expanded-vs-outer]
348-
Name bindings from macro expansions may not shadow name bindings from outside of those expansions.
357+
Names may not be resolved through ambiguous candidates inside of macro expansions. Candidates inside of macro expansions are ambiguous when they would shadow a candidate for the same name from outside of the first candidate's macro expansion and the invocation of the name being resolved is also from outside of the first candidate's macro expansion.
349358

350359
```rust,compile_fail,E0659
351-
macro_rules! name {
360+
macro_rules! define_ambig {
361+
() => {
362+
macro_rules! ambig {
363+
() => {}
364+
}
365+
}
366+
}
367+
368+
// Introduce outer candidate definition for `ambig` macro invocation.
369+
macro_rules! ambig {
370+
() => {}
371+
}
372+
373+
// Introduce a second candidate definition for `ambig` inside of a macro
374+
// expansion.
375+
define_ambig!();
376+
377+
// The definition of `ambig` from the second invocation
378+
// of `define_ambig` is the innermost canadidate.
379+
//
380+
// The definition of `ambig` from the first invocation of `define_ambig`
381+
// is the second candidate.
382+
//
383+
// The compiler checks that the first candidate is inside of a macro
384+
// expansion, that the second candidate is not from within the same
385+
// macro expansion, and that the name being resolved is not from
386+
// within the same macro expansion.
387+
ambig!(); // ERROR: `ambig` is ambiguous.
388+
```
389+
390+
The reverse is not considered ambiguous.
391+
392+
```rust
393+
# macro_rules! define_ambig {
394+
# () => {
395+
# macro_rules! ambig {
396+
# () => {}
397+
# }
398+
# }
399+
# }
400+
// Swap order of definitions.
401+
define_ambig!();
402+
macro_rules! ambig {
352403
() => {}
353404
}
405+
// The innermost candidate is now less expanded so it may shadow more
406+
// the macro expanded definition above it.
407+
ambig!();
408+
```
409+
410+
Nor is it ambiguous if the invocation being resolved is within the innermost candidate's expansion.
354411

355-
macro_rules! define_name {
412+
```rust
413+
macro_rules! ambig {
414+
() => {}
415+
}
416+
417+
macro_rules! define_and_invoke_ambig {
356418
() => {
357-
macro_rules! name {
419+
// Define innermost candidate.
420+
macro_rules! ambig {
358421
() => {}
359422
}
423+
424+
// Invocation of `ambig` is in the same expansion as the
425+
// innermost candidate.
426+
ambig!(); // OK
360427
}
361428
}
362429

363-
fn f() {
364-
define_name!();
365-
name!(); // ERROR: `name` is ambiguous.
430+
define_and_invoke_ambig!();
431+
```
432+
433+
It doesn't matter if both definitions come from invocations of the same macro, the outermost candidate is still considered "less expanded" because it is not within the expansion containing the innermost candidate's definition.
434+
435+
```rust,compile_fail,E0659
436+
# macro_rules! define_ambig {
437+
# () => {
438+
# macro_rules! ambig {
439+
# () => {}
440+
# }
441+
# }
442+
# }
443+
define_ambig!();
444+
define_ambig!();
445+
ambig!(); // ERROR: `ambig` is ambiguous.
446+
```
447+
448+
This also applies to imports, so long as the innermost candidate for the invocation of name is from within a macro expansion.
449+
450+
```rust,compile_fail,E0659
451+
macro_rules! define_ambig {
452+
() => {
453+
mod ambig {
454+
pub struct Name;
455+
}
456+
}
457+
}
458+
459+
mod ambig {
460+
pub struct Name;
366461
}
462+
463+
const _: () = {
464+
// Introduce innermost candidate for
465+
// `ambig` mod in this macro expansion.
466+
define_ambig!();
467+
use ambig::Name; // ERROR: `ambig` is ambiguous.
468+
};
367469
```
368470

369471
r[names.resolution.expansion.macros.ambiguity.builtin-attr]
@@ -373,7 +475,6 @@ User defined attributes or derive macros may not shadow builtin non-macro attrib
373475
```rust,ignore
374476
// with-helper/src/lib.rs
375477
# use proc_macro::TokenStream;
376-
#
377478
#[proc_macro_derive(WithHelperAttr, attributes(non_exhaustive))]
378479
// ^------------- user attr candidate
379480
...
@@ -446,7 +547,6 @@ r[names.resolution.type-relative]
446547
[namespaces]: ../names/namespaces.md
447548
[outer scope]: #r-names.resolution.general.scopes
448549
[path-based scope]: ../macros.md#r-macro.invocation.name-resolution
449-
[permitted]: name-resolution.md#r-names.resolution.expansion.imports.shadowing
450550
[scope]: ../names/scopes.md
451551
[sub-namespace]: ../names/namespaces.md#r-names.namespaces.sub-namespaces
452552
[type-relative paths]: names.resolution.type-relative

src/names/namespaces.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ For example, the [`cfg` attribute] and the [`cfg` macro] are two different entit
127127
> () => {};
128128
> }
129129
>
130-
> use myattr::mymac; // error[E0252]: the name `mymac` is defined multiple times
130+
> use myattr::mymac; // error[E0252]: the name `mymac` is defined multiple times.
131131
> ```
132132
133133
[Associated const declarations]: ../items/associated-items.md#associated-constants

0 commit comments

Comments
 (0)