+//! "Late resolution" is the pass that resolves most of names in a crate beside imports and macros.
+//! It runs when the crate is fully expanded and its module structure is fully built.
+//! So it just walks through the crate and resolves all the expressions, types, etc.
+//!
+//! If you wonder why there's no `early.rs`, that's because it's split into three files -
+//! `build_reduced_graph.rs`, `macros.rs` and `resolve_imports.rs`.
+
use GenericParameters::*;
use RibKind::*;
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
}
TyKind::ImplicitSelf => {
- let self_ty = Ident::with_empty_ctxt(kw::SelfUpper);
+ let self_ty = Ident::with_dummy_span(kw::SelfUpper);
let res = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span)
.map_or(Res::Err, |d| d.res());
self.r.record_partial_res(ty.id, PartialRes::new(res));
GenericParamKind::Type { ref default, .. } => {
found_default |= default.is_some();
if found_default {
- Some((Ident::with_empty_ctxt(param.ident.name), Res::Err))
+ Some((Ident::with_dummy_span(param.ident.name), Res::Err))
} else {
None
}
false
}
})
- .map(|param| (Ident::with_empty_ctxt(param.ident.name), Res::Err)));
+ .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err)));
for param in &generics.params {
match param.kind {
}
// Allow all following defaults to refer to this type parameter.
- default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
+ default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
}
GenericParamKind::Const { ref ty } => {
self.ribs[TypeNS].push(const_ty_param_ban_rib);
fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> {
// During late resolution we only track the module component of the parent scope,
// although it may be useful to track other components as well for diagnostics.
- let parent_scope = resolver.dummy_parent_scope();
let graph_root = resolver.graph_root;
+ let parent_scope = ParentScope::module(graph_root);
LateResolutionVisitor {
r: resolver,
parent_scope,
self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
- self.r.finalize_current_module_macro_resolutions(module);
let ret = f(self);
self.parent_scope.module = orig_module;
let mut self_type_rib = Rib::new(NormalRibKind);
// Plain insert (no renaming, since types are not currently hygienic)
- self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res);
+ self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
self.ribs[TypeNS].push(self_type_rib);
f(self);
self.ribs[TypeNS].pop();
{
let self_res = Res::SelfCtor(impl_id);
let mut self_type_rib = Rib::new(NormalRibKind);
- self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res);
+ self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
self.ribs[ValueNS].push(self_type_rib);
f(self);
self.ribs[ValueNS].pop();
// Checks that all of the arms in an or-pattern have exactly the
// same set of bindings, with the same binding modes for each.
fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) {
- if pats.is_empty() {
- return;
- }
-
let mut missing_vars = FxHashMap::default();
let mut inconsistent_vars = FxHashMap::default();
- for (i, p) in pats.iter().enumerate() {
- let map_i = self.binding_mode_map(&p);
-
- for (j, q) in pats.iter().enumerate() {
- if i == j {
- continue;
- }
- let map_j = self.binding_mode_map(&q);
- for (&key, &binding_i) in &map_i {
- if map_j.is_empty() { // Account for missing bindings when
- let binding_error = missing_vars // `map_j` has none.
- .entry(key.name)
- .or_insert(BindingError {
- name: key.name,
- origin: BTreeSet::new(),
- target: BTreeSet::new(),
- });
- binding_error.origin.insert(binding_i.span);
- binding_error.target.insert(q.span);
- }
- for (&key_j, &binding_j) in &map_j {
- match map_i.get(&key_j) {
- None => { // missing binding
- let binding_error = missing_vars
- .entry(key_j.name)
- .or_insert(BindingError {
- name: key_j.name,
- origin: BTreeSet::new(),
- target: BTreeSet::new(),
- });
- binding_error.origin.insert(binding_j.span);
- binding_error.target.insert(p.span);
- }
- Some(binding_i) => { // check consistent binding
- if binding_i.binding_mode != binding_j.binding_mode {
- inconsistent_vars
- .entry(key.name)
- .or_insert((binding_j.span, binding_i.span));
- }
+ for pat_outer in pats.iter() {
+ let map_outer = self.binding_mode_map(&pat_outer);
+
+ for pat_inner in pats.iter().filter(|pat| pat.id != pat_outer.id) {
+ let map_inner = self.binding_mode_map(&pat_inner);
+
+ for (&key_inner, &binding_inner) in map_inner.iter() {
+ match map_outer.get(&key_inner) {
+ None => { // missing binding
+ let binding_error = missing_vars
+ .entry(key_inner.name)
+ .or_insert(BindingError {
+ name: key_inner.name,
+ origin: BTreeSet::new(),
+ target: BTreeSet::new(),
+ could_be_path:
+ key_inner.name.as_str().starts_with(char::is_uppercase)
+ });
+ binding_error.origin.insert(binding_inner.span);
+ binding_error.target.insert(pat_outer.span);
+ }
+ Some(binding_outer) => { // check consistent binding
+ if binding_outer.binding_mode != binding_inner.binding_mode {
+ inconsistent_vars
+ .entry(key_inner.name)
+ .or_insert((binding_inner.span, binding_outer.span));
}
}
}
}
}
}
- let mut missing_vars = missing_vars.iter().collect::<Vec<_>>();
+
+ let mut missing_vars = missing_vars.iter_mut().collect::<Vec<_>>();
missing_vars.sort();
- for (_, v) in missing_vars {
+ for (name, mut v) in missing_vars {
+ if inconsistent_vars.contains_key(name) {
+ v.could_be_path = false;
+ }
self.r.report_error(
- *v.origin.iter().next().unwrap(), ResolutionError::VariableNotBoundInPattern(v)
- );
+ *v.origin.iter().next().unwrap(),
+ ResolutionError::VariableNotBoundInPattern(v));
}
+
let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
inconsistent_vars.sort();
for (name, v) in inconsistent_vars {
self.resolve_pattern(pat, source, &mut bindings_list);
}
// This has to happen *after* we determine which pat_idents are variants
- self.check_consistent_bindings(pats);
+ if pats.len() > 1 {
+ self.check_consistent_bindings(pats);
+ }
}
fn resolve_block(&mut self, block: &Block) {
self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module)));
self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module)));
self.parent_scope.module = anonymous_module;
- self.r.finalize_current_module_macro_resolutions(anonymous_module);
} else {
self.ribs[ValueNS].push(Rib::new(NormalRibKind));
}
self.r.trait_map.insert(id, traits);
}
- let mut std_path = vec![Segment::from_ident(Ident::with_empty_ctxt(sym::std))];
+ let mut std_path = vec![Segment::from_ident(Ident::with_dummy_span(sym::std))];
std_path.extend(path);
if self.r.primitive_type_table.primitive_types.contains_key(&path[0].ident.name) {
let cl = CrateLint::No;
fn self_type_is_available(&mut self, span: Span) -> bool {
let binding = self.resolve_ident_in_lexical_scope(
- Ident::with_empty_ctxt(kw::SelfUpper),
+ Ident::with_dummy_span(kw::SelfUpper),
TypeNS,
None,
span,
let mut traits = module.traits.borrow_mut();
if traits.is_none() {
let mut collected_traits = Vec::new();
- module.for_each_child(|name, ns, binding| {
+ module.for_each_child(self.r, |_, name, ns, binding| {
if ns != TypeNS { return }
match binding.res() {
Res::Def(DefKind::Trait, _) |
impl<'a> Resolver<'a> {
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
- self.finalize_current_module_macro_resolutions(self.graph_root);
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
visit::walk_crate(&mut late_resolution_visitor, krate);
for (id, span) in late_resolution_visitor.unused_labels.iter() {