Skip to content

Commit

Permalink
Do not generate Def::Err in bindings
Browse files Browse the repository at this point in the history
Instead of Def::Err erroneous bindings can get usual definitions that doesn't require special cases later on and have less chances to generate ICE.
  • Loading branch information
petrochenkov committed Jul 8, 2016
1 parent 4d4c7be commit eb32440
Showing 1 changed file with 13 additions and 19 deletions.
32 changes: 13 additions & 19 deletions src/librustc_resolve/lib.rs
Expand Up @@ -2180,7 +2180,8 @@ impl<'a> Resolver<'a> {
// because that breaks the assumptions later
// passes make about or-patterns.)
let renamed = mtwt::resolve(ident.node);
let def = match bindings.get(&renamed).cloned() {
let mut def = Def::Local(self.definitions.local_def_id(pat_id), pat_id);
match bindings.get(&renamed).cloned() {
Some(id) if id == outer_pat_id => {
// `Variant(a, a)`, error
resolve_error(
Expand All @@ -2189,7 +2190,6 @@ impl<'a> Resolver<'a> {
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
&ident.node.name.as_str())
);
Def::Err
}
Some(..) if pat_src == PatternSource::FnParam => {
// `fn f(a: u8, a: u8)`, error
Expand All @@ -2199,29 +2199,24 @@ impl<'a> Resolver<'a> {
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
&ident.node.name.as_str())
);
Def::Err
}
Some(..) if pat_src == PatternSource::Match => {
// `Variant1(a) | Variant2(a)`, ok
// Reuse definition from the first `a`.
self.value_ribs.last_mut().unwrap().bindings[&renamed]
def = self.value_ribs.last_mut().unwrap().bindings[&renamed];
}
Some(..) => {
span_bug!(ident.span, "two bindings with the same name from \
unexpected pattern source {:?}", pat_src);
}
None => {
// A completely fresh binding, add to the lists.
// FIXME: Later stages are not ready to deal with `Def::Err` here yet, so
// define `Invalid` bindings as `Def::Local`, just don't add them to the lists.
let def = Def::Local(self.definitions.local_def_id(pat_id), pat_id);
// A completely fresh binding, add to the lists if it's valid.
if ident.node.name != keywords::Invalid.name() {
bindings.insert(renamed, outer_pat_id);
self.value_ribs.last_mut().unwrap().bindings.insert(renamed, def);
}
def
}
};
}

PathResolution::new(def)
}
Expand Down Expand Up @@ -2287,15 +2282,16 @@ impl<'a> Resolver<'a> {
PatKind::Ident(bmode, ref ident, ref opt_pat) => {
// First try to resolve the identifier as some existing
// entity, then fall back to a fresh binding.
let local_def = self.resolve_identifier(ident.node, ValueNS, true);
let resolution = if let Some(LocalDef { def, .. }) = local_def {
let resolution = self.resolve_identifier(ident.node, ValueNS, true)
.map(|local_def| PathResolution::new(local_def.def))
.and_then(|resolution| {
let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
bmode != BindingMode::ByValue(Mutability::Immutable);
match def {
Def::Struct(..) | Def::Variant(..) |
Def::Const(..) | Def::AssociatedConst(..) if !always_binding => {
// A constant, unit variant, etc pattern.
PathResolution::new(def)
Some(resolution)
}
Def::Struct(..) | Def::Variant(..) |
Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => {
Expand All @@ -2307,23 +2303,21 @@ impl<'a> Resolver<'a> {
ResolutionError::BindingShadowsSomethingUnacceptable(
pat_src.descr(), kind_name, ident.node.name)
);
err_path_resolution()
None
}
Def::Local(..) | Def::Upvar(..) | Def::Fn(..) => {
// These entities are explicitly allowed
// to be shadowed by fresh bindings.
self.fresh_binding(ident, pat.id, outer_pat_id,
pat_src, bindings)
None
}
def => {
span_bug!(ident.span, "unexpected definition for an \
identifier in pattern {:?}", def);
}
}
} else {
// Fall back to a fresh binding.
}).unwrap_or_else(|| {
self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
};
});

self.record_def(pat.id, resolution);
}
Expand Down

0 comments on commit eb32440

Please sign in to comment.