Fix a panic when checking the call graph for an extractor with type errors in its definition

This commit is contained in:
Nick Fitzgerald
2021-10-05 16:35:07 -07:00
committed by Chris Fallin
parent 9af23bf061
commit fddff6ee2d
2 changed files with 26 additions and 6 deletions

View File

@@ -128,10 +128,10 @@ impl Pattern {
} }
/// Call `f` for each of the terms in this pattern. /// Call `f` for each of the terms in this pattern.
pub fn terms(&self, f: &mut dyn FnMut(&Ident)) { pub fn terms(&self, f: &mut dyn FnMut(Pos, &Ident)) {
match self { match self {
Pattern::Term { sym, args, .. } => { Pattern::Term { sym, args, pos } => {
f(sym); f(*pos, sym);
for arg in args { for arg in args {
if let TermArgPattern::Pattern(p) = arg { if let TermArgPattern::Pattern(p) = arg {
p.terms(f); p.terms(f);

View File

@@ -847,17 +847,29 @@ impl TermEnv {
return; return;
} }
}; };
let termdata = &mut self.terms[term.index()];
let template = ext.template.make_macro_template(&ext.args[..]); let template = ext.template.make_macro_template(&ext.args[..]);
log::trace!("extractor def: {:?} becomes template {:?}", def, template); log::trace!("extractor def: {:?} becomes template {:?}", def, template);
let mut callees = HashSet::new(); let mut callees = HashSet::new();
template.terms(&mut |t| { template.terms(&mut |pos, t| {
let t = tyenv.intern_mut(t); let t = tyenv.intern_mut(t);
callees.insert(t); callees.insert(t);
if !self.term_map.contains_key(&t) {
tyenv.report_error(
pos,
format!(
"`{}` extractor definition references unknown term `{}`",
ext.term.0,
tyenv.syms[t.index()]
),
);
}
}); });
extractor_call_graph.insert(sym, callees); extractor_call_graph.insert(sym, callees);
let termdata = &mut self.terms[term.index()];
match &termdata.kind { match &termdata.kind {
&TermKind::Declared => { &TermKind::Declared => {
termdata.kind = TermKind::InternalExtractor { template }; termdata.kind = TermKind::InternalExtractor { template };
@@ -892,7 +904,15 @@ impl TermEnv {
})); }));
} }
} else { } else {
let term = self.term_map[&caller]; let term = match self.term_map.get(&caller) {
Some(t) => t,
None => {
// Some other error must have already been recorded
// if we don't have the caller's term data.
assert!(!tyenv.errors.is_empty());
continue 'outer;
}
};
let pos = match &self.terms[term.index()].kind { let pos = match &self.terms[term.index()].kind {
TermKind::InternalExtractor { template } => template.pos(), TermKind::InternalExtractor { template } => template.pos(),
_ => unreachable!(), _ => unreachable!(),