Do not generate Def::Err in bindings

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.
This commit is contained in:
Vadim Petrochenkov 2016-06-11 18:47:47 +03:00
parent 4d4c7be19e
commit eb32440d45
1 changed files with 13 additions and 19 deletions

View File

@ -2180,7 +2180,8 @@ impl<'a> Resolver<'a> {
// because that breaks the assumptions later // because that breaks the assumptions later
// passes make about or-patterns.) // passes make about or-patterns.)
let renamed = mtwt::resolve(ident.node); 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 => { Some(id) if id == outer_pat_id => {
// `Variant(a, a)`, error // `Variant(a, a)`, error
resolve_error( resolve_error(
@ -2189,7 +2190,6 @@ impl<'a> Resolver<'a> {
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
&ident.node.name.as_str()) &ident.node.name.as_str())
); );
Def::Err
} }
Some(..) if pat_src == PatternSource::FnParam => { Some(..) if pat_src == PatternSource::FnParam => {
// `fn f(a: u8, a: u8)`, error // `fn f(a: u8, a: u8)`, error
@ -2199,29 +2199,24 @@ impl<'a> Resolver<'a> {
ResolutionError::IdentifierBoundMoreThanOnceInParameterList( ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
&ident.node.name.as_str()) &ident.node.name.as_str())
); );
Def::Err
} }
Some(..) if pat_src == PatternSource::Match => { Some(..) if pat_src == PatternSource::Match => {
// `Variant1(a) | Variant2(a)`, ok // `Variant1(a) | Variant2(a)`, ok
// Reuse definition from the first `a`. // Reuse definition from the first `a`.
self.value_ribs.last_mut().unwrap().bindings[&renamed] def = self.value_ribs.last_mut().unwrap().bindings[&renamed];
} }
Some(..) => { Some(..) => {
span_bug!(ident.span, "two bindings with the same name from \ span_bug!(ident.span, "two bindings with the same name from \
unexpected pattern source {:?}", pat_src); unexpected pattern source {:?}", pat_src);
} }
None => { None => {
// A completely fresh binding, add to the lists. // A completely fresh binding, add to the lists if it's valid.
// 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);
if ident.node.name != keywords::Invalid.name() { if ident.node.name != keywords::Invalid.name() {
bindings.insert(renamed, outer_pat_id); bindings.insert(renamed, outer_pat_id);
self.value_ribs.last_mut().unwrap().bindings.insert(renamed, def); self.value_ribs.last_mut().unwrap().bindings.insert(renamed, def);
} }
def
} }
}; }
PathResolution::new(def) PathResolution::new(def)
} }
@ -2287,15 +2282,16 @@ impl<'a> Resolver<'a> {
PatKind::Ident(bmode, ref ident, ref opt_pat) => { PatKind::Ident(bmode, ref ident, ref opt_pat) => {
// First try to resolve the identifier as some existing // First try to resolve the identifier as some existing
// entity, then fall back to a fresh binding. // entity, then fall back to a fresh binding.
let local_def = self.resolve_identifier(ident.node, ValueNS, true); let resolution = self.resolve_identifier(ident.node, ValueNS, true)
let resolution = if let Some(LocalDef { def, .. }) = local_def { .map(|local_def| PathResolution::new(local_def.def))
.and_then(|resolution| {
let always_binding = !pat_src.is_refutable() || opt_pat.is_some() || let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
bmode != BindingMode::ByValue(Mutability::Immutable); bmode != BindingMode::ByValue(Mutability::Immutable);
match def { match def {
Def::Struct(..) | Def::Variant(..) | Def::Struct(..) | Def::Variant(..) |
Def::Const(..) | Def::AssociatedConst(..) if !always_binding => { Def::Const(..) | Def::AssociatedConst(..) if !always_binding => {
// A constant, unit variant, etc pattern. // A constant, unit variant, etc pattern.
PathResolution::new(def) Some(resolution)
} }
Def::Struct(..) | Def::Variant(..) | Def::Struct(..) | Def::Variant(..) |
Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => { Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => {
@ -2307,23 +2303,21 @@ impl<'a> Resolver<'a> {
ResolutionError::BindingShadowsSomethingUnacceptable( ResolutionError::BindingShadowsSomethingUnacceptable(
pat_src.descr(), kind_name, ident.node.name) pat_src.descr(), kind_name, ident.node.name)
); );
err_path_resolution() None
} }
Def::Local(..) | Def::Upvar(..) | Def::Fn(..) => { Def::Local(..) | Def::Upvar(..) | Def::Fn(..) => {
// These entities are explicitly allowed // These entities are explicitly allowed
// to be shadowed by fresh bindings. // to be shadowed by fresh bindings.
self.fresh_binding(ident, pat.id, outer_pat_id, None
pat_src, bindings)
} }
def => { def => {
span_bug!(ident.span, "unexpected definition for an \ span_bug!(ident.span, "unexpected definition for an \
identifier in pattern {:?}", def); identifier in pattern {:?}", def);
} }
} }
} else { }).unwrap_or_else(|| {
// Fall back to a fresh binding.
self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings) self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
}; });
self.record_def(pat.id, resolution); self.record_def(pat.id, resolution);
} }