Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start documenting name resolution. #937

Merged
merged 7 commits into from
Jan 21, 2021
Merged

Start documenting name resolution. #937

merged 7 commits into from
Jan 21, 2021

Conversation

ehuss
Copy link
Contributor

@ehuss ehuss commented Jan 17, 2021

This is a very small start to making progress on documenting name resolution (#568). This PR focuses on:

  • Create the "names" chapter, with an introduction, and list of all things that introduce names.
  • Document namespaces.
  • Consolidate and extend preludes.
  • Move the "Paths" chapter underneath the names chapter.
  • Move the "Visibility" chapter underneath the names chapter.

Closes #924.

@ehuss
Copy link
Contributor Author

ehuss commented Jan 17, 2021

I tried hard to make this accurate, but there are almost certainly some mistakes (or things people would present differently). Please be gentle. 😄

I explicitly did not update the rest of the reference to specify how things are introduced into different namespaces. For example, the struct item page should indicate that it introduces the struct name into the type namespace, and the constructor in the value namespace (and constructors generally aren't documented at all). I plan to follow up with that separately, as I think it will touch a large number of places, and I'm uncertain exactly how I'm going to integrate it. Another big part of this is to document use and how it introduces things into various namespaces, which I think is a big topic on its own when considering globs and such.

Other uncertainties:

  • I documented lifetimes and labels as separate namespaces, but I'm not sure if that's the best way to present it. I think it could consider the lifetimes as part of the type namespace, and labels as part of the value namespace (since they are syntactically incapable of clashing with anything else). Or, they could be considered part of a combined lifetime/label namespace (since #21633 intended to reject shadowing), but in practice they are still treated independently.

Terminology

This introduces a new term "entity" to refer to types/items/values/macros/lifetimes/etc. I'd like to defend that choice, as I think it is useful to have a single term to refer to that soup of things. Also, I find that term is used in several other language specs and programming literature.

I waffled a bit on using "name" as an explicit term. There is a bit of a vague overlap between "name", "identifier", "label", and "path". I think "name" is very commonly used in other language specs and literature (and follows more naturally with "namespaces" and "name resolution", and is how rustc internally refers to them as "name bindings"). I'm not sure if how I presented it is entirely clear, though.

@petrochenkov
Copy link
Contributor

I'll look at this tomorrow.

Copy link
Contributor

@Havvy Havvy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, overall, I like what I'm seeing. This is a huge chunk of language that makes describing other parts of the language a lot more precise. Like, I could gleefully work on expressions/path-expr.md using this terminology.


Except, I don't like saying that the things that introduce names are entities themselves. I rather think that items introduce entities and names separately. The entity stands alone in some abstract entity space where names don't exist while the name is attached to a scope in a specified namespace that points to the element in entity space. I'm probably missing some subtlety in my definition even; this stuff is hard to think about. But by separating it out like this, it lets us:

  • separate the lexical element (e.g. an item) from what the lexical element introduces
  • say that a single lexical element introduces multiple entities and names
  • say the crate root is an entity, and if you think it is not, one can create an alias to it

I have some half-finished thoughts in my head that a name can also be attached to an entity. For example, mod foo { struct Bar; } would have Bar attached to Foo, and that this attachment is what lets foo::Bar work. Then the preludes can introduce the names into module scope but without attaching them. This also lets us attach associated items to the item they associate to.


I'm also not sure how non-static method names fit in all of this.

src/SUMMARY.md Show resolved Hide resolved
src/glossary.md Outdated
@@ -61,6 +61,11 @@ through a mechanism called ‘trait objects’.

A dynamically sized type (DST) is a type without a statically known size or alignment.

### Entity

An [*entity*] is a [type], [item], [generic parameter], [variable binding],
Copy link
Contributor

@Havvy Havvy Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not gonna sugar coat this, so: this definition is atrocious. Anybody reading it will be "but why combine these things into one group?"

I'd offer a suggestion for a better definition, but I have opinions on the current definition anyways.

Copy link
Contributor Author

@ehuss ehuss Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, yea, it is difficult to define "entity" since it is a bit of a nebulous concept that is only defined by the list of things it encompasses. Some examples of how others handle it:

C++: "An entity is a value, object, reference, structured binding, function, enumerator, type, class member, bit-field,template, template specialization, namespace, or parameter pack."
Ada: Doesn't directly say what an "entity" is, other than "A declaration is a language construct that associates a name with (a view of) an entity."
Java: Defines entity as the list (similar to how I did): "A declared entity (§6.1) is a package, class type (normal or enum), …". It tends to be use the term "declared entity" more formally.
ECMA 334 (C#): Doesn't seem to ever define it, but uses it all over such as "The scope of a name is the region of program text within which it is possible to refer to the entity declared by the name without qualification of the name."
Go: Doesn't define it, but uses it offhand like "While the identifier of the inner declaration is in scope, it denotes the entity declared by the inner declaration."
Haskell 2010: "We use the term entity to refer to a value, type, or class defined in, imported into, or perhaps exported from a module"
Typescript: Uses the term "entity" all over without explicitly defining it.
IEEE 24765: "in computer programming, any item that can be named or denoted in a program." (among several other more vague definitions)

I took another stab at making it more explicit, though I think defining it as a list of things is also valid.

@@ -0,0 +1,148 @@
# Namespaces

Entity names are segregated into separate *namespaces* based on the kind of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't actually define what a namespace is. How about something like...

A *namespace* is a set of names where each name unambiguously refers to a specific entity.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If two glob imports import the same name inside the value namespace, that it is still a namespace despite ambiguity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow the point about glob imports. A conflict with two glob imports like that is an error (that is, an invalid program). Other valid circumstances have rules that disambiguate what name is introduced. I wouldn't consider that to be ambiguous when there are rules on which name is used.

src/names.md Outdated

Entities that explicitly introduce a name in the source code are:

* [Items]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit.

Suggested change
* [Items]
* [Items]:

Copy link
Contributor Author

@ehuss ehuss Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I think I had that originally, but removed it due to the risk that markdown would "eat" it. For example, if you have a single word after the colon, like * [Boolean type]: `bool`, it just disappears since it is interpreted as a link reference. It should be safe otherwise, though.

src/names.md Outdated
* [External block items]
* [`macro_rules` declarations] and [matcher metavariables]
* [Implementation] associated items
* [Expressions]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit.

Suggested change
* [Expressions]
* [Expressions]:

@ehuss
Copy link
Contributor Author

ehuss commented Jan 18, 2021

I'm also not sure how non-static method names fit in all of this.

I believe this is #23, correct? I think method-call-expr doesn't do a horrible job of covering it.

@petrochenkov
Copy link
Contributor

I documented lifetimes and labels as separate namespaces, but I'm not sure if that's the best way to present it.

+1
This is mostly a philosophical question due to the lexical separation of identifier and lifetime tokens, but it would be better to treat them separately.
Yes, lifetimes behave kind of like type parameters from type namespace (but also like const parameters from value namespace), and labels use same hygiene rules as local variables, but they still share zero common resolution code with regular types and values in the compiler, for example, can't form paths, can't be imported. I think that makes them sufficiently different.

src/glossary.md Outdated
A [*namespace*] is a set of [names](#name) where each name unambiguously
refers to a specific [entity](#entity). Namespaces are organized in a
hierarchy, where each level of the hierarchy has its own collection of named
entities.
Copy link
Contributor

@petrochenkov petrochenkov Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is what is called "scope" in the compiler (https://github.com/rust-lang/rust/blob/master/compiler/rustc_resolve/src/lib.rs#L102-L115)? ("Scope" in the compiler is also overloaded and used for other things.)
"Namespace" in the compiler is one of "type", "value" and "macro" (+ perhaps "lifetime" and "label", but they are separate).

Copy link
Contributor

@petrochenkov petrochenkov Jan 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok, it's not a "scope", but the wording is confusing.

set of names where each name unambiguously
refers to a specific entity

This is plain indecipherable.

Namespaces are organized in a hierarchy

And this should somehow highlight that the hierarchies exist inside the namespaces, and not between them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I'm struggling to define it clearly. Lexicography is not my strong suit. I took another stab at it.

I suspect this will receive updates and clarifications once I start working on the "scopes" chapter.

# Preludes

A *prelude* is a collection of names that are automatically brought into scope
of every module in a crate.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, originally "prelude" meant simply a piece of code inserted by the compiler at the start of the crate, like

#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std;

, not a set of names.

Then I used it as a temporary name / analogy for built-in types ("language prelude") and extern crates ("extern prelude"), because they behaved similarly to the actual prelude import, and then it stuck.

I still have no idea whether the name "prelude" sounds reasonable in the meaning "set of names" to native speakers, or to users of languages from which this term originally came.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm personally comfortable with it. I think the behavior is similar enough ("importing these things into every module"). I think it will help later when talking about behaviors in how names are resolved.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still have no idea whether the name "prelude" sounds reasonable in the meaning "set of names" to native speakers, or to users of languages from which this term originally came.

As a native speaker, I think of "prelude" as a jargon term the same way "macro" or "scope" is. Those words all have meanings outside programming, but the connection to the jargon term is tenuous at best. I think "prelude" is useful as an existing jargon term that's used in other languages, though.

library prelude], [extern prelude], or [tool prelude] into scope for that
module or any of its descendants.

This attribute does not affect the [language prelude] or [`macro_use` prelude].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It affects macro_use prelude on >=2018 edition.
The plan was to exclude macro_use prelude on both editions (rust-lang/rust#55630), but I never got to it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, sorry I missed that. For various reasons, I do all my testing in 2015, and I didn't think to try 2018. I even saw that code, and somehow forgot to double-check it. I thought it was weird that it didn't affect macro_use.

ehuss added 2 commits January 18, 2021 17:13
* Fix: no_implicit_prelude behaves differently in 2015.
* Try to make it clearer how standard library stuff is injected into
  the crate.
src/names.md Outdated Show resolved Hide resolved
src/names.md Outdated Show resolved Hide resolved
Copy link
Contributor

@Havvy Havvy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see nothing further I'd like to see changed. This comment is to remove my "needs change" mark on the PR.

@petrochenkov can you approve and merge once you're satisfied yourself?

@petrochenkov
Copy link
Contributor

@Havvy
I have no power in this repo, I can neither assign myself nor approve the PR.

@ehuss ehuss mentioned this pull request Jan 20, 2021
29 tasks
@Havvy Havvy merged commit 1f78215 into rust-lang:master Jan 21, 2021
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Jan 26, 2021
Update books

## nomicon

7 commits in a8584998eacdea7106a1dfafcbf6c1c06fcdf925..bbf06ad39d1f45654047e9596b750cc6e6d1b693
2021-01-06 12:49:49 -0500 to 2021-01-22 07:07:31 -0800
- Fix alloc link in exotic-sizes for local docs (rust-lang/nomicon#255)
- Remove TODO
- Fix small punctuation error
- Arc revisions (Clone atomic explanation) (pt2/3(+?))
- Fix Arc Clone
- Arc revisions (pt1/2(+?))
- Simple Arc implementation (without Weak refs)

## reference

5 commits in 50af691f838937c300b47812d0507c6d88c14f97..f02b09eb6e8af340ad1256a54adb7aae2ff3163e
2021-01-12 21:19:20 -0800 to 2021-01-22 01:53:02 -0800
- Fix missing space (rust-lang/reference#941)
- Start documenting name resolution. (rust-lang/reference#937)
- Fix plural and delete spurious words in comparison ops (rust-lang/reference#932)
- Document execution order (rust-lang/reference#888)
- Compound operator expressions (rust-lang/reference#915)

## book

3 commits in ac57a0ddd23d173b26731ccf939f3ba729753275..e724bd826580ff95df48a8533af7dec1080693d4
2021-01-09 14:18:45 -0500 to 2021-01-20 08:19:49 -0600
- Fixes rust-lang/book#2417. Get the index from user input instead of a const. (rust-lang/book#2566)
- Turn off the playground in a bunch more lib.rs inclusions (rust-lang/book#2569)
- Merge pull request rust-lang/book#2567 from rust-lang/rust-1.49

## rust-by-example

1 commits in 03e23af01f0b4f83a3a513da280e1ca92587f2ec..f633769acef68574427a6fae6c06f13bc2199573
2021-01-09 10:20:28 -0300 to 2021-01-13 20:58:25 -0300
- Fixed styling on closure example (rust-lang/rust-by-example#1405)
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Jan 26, 2021
Update books

## nomicon

7 commits in a8584998eacdea7106a1dfafcbf6c1c06fcdf925..bbf06ad39d1f45654047e9596b750cc6e6d1b693
2021-01-06 12:49:49 -0500 to 2021-01-22 07:07:31 -0800
- Fix alloc link in exotic-sizes for local docs (rust-lang/nomicon#255)
- Remove TODO
- Fix small punctuation error
- Arc revisions (Clone atomic explanation) (pt2/3(+?))
- Fix Arc Clone
- Arc revisions (pt1/2(+?))
- Simple Arc implementation (without Weak refs)

## reference

5 commits in 50af691f838937c300b47812d0507c6d88c14f97..f02b09eb6e8af340ad1256a54adb7aae2ff3163e
2021-01-12 21:19:20 -0800 to 2021-01-22 01:53:02 -0800
- Fix missing space (rust-lang/reference#941)
- Start documenting name resolution. (rust-lang/reference#937)
- Fix plural and delete spurious words in comparison ops (rust-lang/reference#932)
- Document execution order (rust-lang/reference#888)
- Compound operator expressions (rust-lang/reference#915)

## book

3 commits in ac57a0ddd23d173b26731ccf939f3ba729753275..e724bd826580ff95df48a8533af7dec1080693d4
2021-01-09 14:18:45 -0500 to 2021-01-20 08:19:49 -0600
- Fixes rust-lang/book#2417. Get the index from user input instead of a const. (rust-lang/book#2566)
- Turn off the playground in a bunch more lib.rs inclusions (rust-lang/book#2569)
- Merge pull request rust-lang/book#2567 from rust-lang/rust-1.49

## rust-by-example

1 commits in 03e23af01f0b4f83a3a513da280e1ca92587f2ec..f633769acef68574427a6fae6c06f13bc2199573
2021-01-09 10:20:28 -0300 to 2021-01-13 20:58:25 -0300
- Fixed styling on closure example (rust-lang/rust-by-example#1405)
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Feb 15, 2021
Update link for extern prelude.

There was some reorganization in the reference as part of rust-lang/reference#937.
bors added a commit to rust-lang/cargo that referenced this pull request Feb 16, 2021
Update link for no_std attribute.

There was some reorganization in the reference as part of rust-lang/reference#937.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Document Namespaces
5 participants