Skip to content

Commit da2e92e

Browse files
authored
Rollup merge of rust-lang#48693 - vorner:doc-name-resolution, r=petrochenkov
Some comments and documentation for name resolution crate Hello I'm trying to get a grasp of how the name resolution crate works, as part of helping with rust-lang/rustc-dev-guide#16. Not that I'd be succeeding much, but as I was reading the code, I started to put some notes into it, to help me understand. I guess I didn't get very far yet, but I'd like to share what I have, in case it might be useful for someone else. I hope these are correct (even if incomplete), but I'll be glad for a fast check in case I put something misleading there.
2 parents 184156e + 433a03e commit da2e92e

File tree

1 file changed

+58
-3
lines changed

1 file changed

+58
-3
lines changed

Diff for: src/librustc_resolve/lib.rs

+58-3
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ enum ResolutionError<'a> {
162162
ForwardDeclaredTyParam,
163163
}
164164

165+
/// Combines an error with provided span and emits it
166+
///
167+
/// This takes the error provided, combines it with the span and any additional spans inside the
168+
/// error and emits it.
165169
fn resolve_error<'sess, 'a>(resolver: &'sess Resolver,
166170
span: Span,
167171
resolution_error: ResolutionError<'a>) {
@@ -486,7 +490,7 @@ struct BindingInfo {
486490
binding_mode: BindingMode,
487491
}
488492

489-
// Map from the name in a pattern to its binding mode.
493+
/// Map from the name in a pattern to its binding mode.
490494
type BindingMap = FxHashMap<Ident, BindingInfo>;
491495

492496
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -681,13 +685,17 @@ impl<'a> PathSource<'a> {
681685
}
682686
}
683687

688+
/// Different kinds of symbols don't influence each other.
689+
///
690+
/// Therefore, they have a separate universe (namespace).
684691
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
685692
pub enum Namespace {
686693
TypeNS,
687694
ValueNS,
688695
MacroNS,
689696
}
690697

698+
/// Just a helper ‒ separate structure for each namespace.
691699
#[derive(Clone, Default, Debug)]
692700
pub struct PerNS<T> {
693701
value_ns: T,
@@ -784,6 +792,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
784792
}
785793
}
786794

795+
/// This thing walks the whole crate in DFS manner, visiting each item, resolving names as it goes.
787796
impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
788797
fn visit_item(&mut self, item: &'tcx Item) {
789798
self.resolve_item(item);
@@ -910,7 +919,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
910919
fn visit_generics(&mut self, generics: &'tcx Generics) {
911920
// For type parameter defaults, we have to ban access
912921
// to following type parameters, as the Substs can only
913-
// provide previous type parameters as they're built.
922+
// provide previous type parameters as they're built. We
923+
// put all the parameters on the ban list and then remove
924+
// them one by one as they are processed and become available.
914925
let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
915926
default_ban_rib.bindings.extend(generics.params.iter()
916927
.filter_map(|p| if let GenericParam::Type(ref tp) = *p { Some(tp) } else { None })
@@ -986,6 +997,17 @@ enum RibKind<'a> {
986997
}
987998

988999
/// One local scope.
1000+
///
1001+
/// A rib represents a scope names can live in. Note that these appear in many places, not just
1002+
/// around braces. At any place where the list of accessible names (of the given namespace)
1003+
/// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a
1004+
/// stack. This may be, for example, a `let` statement (because it introduces variables), a macro,
1005+
/// etc.
1006+
///
1007+
/// Different [rib kinds](enum.RibKind) are transparent for different names.
1008+
///
1009+
/// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When
1010+
/// resolving, the name is looked up from inside out.
9891011
#[derive(Debug)]
9901012
struct Rib<'a> {
9911013
bindings: FxHashMap<Ident, Def>,
@@ -1001,6 +1023,11 @@ impl<'a> Rib<'a> {
10011023
}
10021024
}
10031025

1026+
/// An intermediate resolution result.
1027+
///
1028+
/// This refers to the thing referred by a name. The difference between `Def` and `Item` is that
1029+
/// items are visible in their whole block, while defs only from the place they are defined
1030+
/// forward.
10041031
enum LexicalScopeBinding<'a> {
10051032
Item(&'a NameBinding<'a>),
10061033
Def(Def),
@@ -1031,7 +1058,26 @@ enum PathResult<'a> {
10311058
}
10321059

10331060
enum ModuleKind {
1061+
/// An anonymous module, eg. just a block.
1062+
///
1063+
/// ```
1064+
/// fn main() {
1065+
/// fn f() {} // (1)
1066+
/// { // This is an anonymous module
1067+
/// f(); // This resolves to (2) as we are inside the block.
1068+
/// fn f() {} // (2)
1069+
/// }
1070+
/// f(); // Resolves to (1)
1071+
/// }
1072+
/// ```
10341073
Block(NodeId),
1074+
/// Any module with a name.
1075+
///
1076+
/// This could be:
1077+
///
1078+
/// * A normal module ‒ either `mod from_file;` or `mod from_block { }`.
1079+
/// * A trait or an enum (it implicitly contains associated types, methods and variant
1080+
/// constructors).
10351081
Def(Def, Name),
10361082
}
10371083

@@ -1316,6 +1362,9 @@ impl<'a> NameBinding<'a> {
13161362
}
13171363

13181364
/// Interns the names of the primitive types.
1365+
///
1366+
/// All other types are defined somewhere and possibly imported, but the primitive ones need
1367+
/// special handling, since they have no place of origin.
13191368
struct PrimitiveTypeTable {
13201369
primitive_types: FxHashMap<Name, PrimTy>,
13211370
}
@@ -1350,6 +1399,8 @@ impl PrimitiveTypeTable {
13501399
}
13511400

13521401
/// The main resolver class.
1402+
///
1403+
/// This is the visitor that walks the whole crate.
13531404
pub struct Resolver<'a> {
13541405
session: &'a Session,
13551406
cstore: &'a CrateStore,
@@ -1481,6 +1532,7 @@ pub struct Resolver<'a> {
14811532
injected_crate: Option<Module<'a>>,
14821533
}
14831534

1535+
/// Nothing really interesting here, it just provides memory for the rest of the crate.
14841536
pub struct ResolverArenas<'a> {
14851537
modules: arena::TypedArena<ModuleData<'a>>,
14861538
local_modules: RefCell<Vec<Module<'a>>>,
@@ -1526,10 +1578,12 @@ impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> {
15261578
match id.krate {
15271579
LOCAL_CRATE => self.definitions.def_key(id.index).parent,
15281580
_ => self.cstore.def_key(id).parent,
1529-
}.map(|index| DefId { index: index, ..id })
1581+
}.map(|index| DefId { index, ..id })
15301582
}
15311583
}
15321584

1585+
/// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
1586+
/// the resolver is no longer needed as all the relevant information is inline.
15331587
impl<'a> hir::lowering::Resolver for Resolver<'a> {
15341588
fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
15351589
self.resolve_hir_path_cb(path, is_value,
@@ -1752,6 +1806,7 @@ impl<'a> Resolver<'a> {
17521806
}
17531807
}
17541808

1809+
/// Runs the function on each namespace.
17551810
fn per_ns<T, F: FnMut(&mut Self, Namespace) -> T>(&mut self, mut f: F) -> PerNS<T> {
17561811
PerNS {
17571812
type_ns: f(self, TypeNS),

0 commit comments

Comments
 (0)