aboutsummaryrefslogtreecommitdiff
path: root/syntax/toposort.rs
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2020-11-03 18:32:27 -0800
committerDavid Tolnay <dtolnay@gmail.com>2020-11-03 18:41:47 -0800
commitacae7a6aaedf5af8fd49095a8def69a9f538cbd4 (patch)
tree7b7f3e8a300242c7430c24a3ced457e4c66b3ac4 /syntax/toposort.rs
parent8b483096e627c36e8fcde025664fde09072dd6ec (diff)
downloadcxx-acae7a6aaedf5af8fd49095a8def69a9f538cbd4.tar.gz
Emit diagnostic on cyclic structs
Diffstat (limited to 'syntax/toposort.rs')
-rw-r--r--syntax/toposort.rs13
1 files changed, 8 insertions, 5 deletions
diff --git a/syntax/toposort.rs b/syntax/toposort.rs
index 918d939c..7c210f23 100644
--- a/syntax/toposort.rs
+++ b/syntax/toposort.rs
@@ -12,7 +12,7 @@ pub fn sort<'a>(cx: &mut Errors, apis: &'a [Api], types: &Types<'a>) -> Vec<&'a
let ref mut marks = Map::new();
for api in apis {
if let Api::Struct(strct) = api {
- visit(cx, strct, &mut sorted, marks, types);
+ let _ = visit(cx, strct, &mut sorted, marks, types);
}
}
sorted
@@ -24,11 +24,11 @@ fn visit<'a>(
sorted: &mut Vec<&'a Struct>,
marks: &mut Map<*const Struct, Mark>,
types: &Types<'a>,
-) {
+) -> Result<(), ()> {
match marks.entry(strct) {
Entry::Occupied(entry) => match entry.get() {
- Mark::Visiting => panic!("not a DAG"), // FIXME
- Mark::Visited => return,
+ Mark::Visiting => return Err(()), // not a DAG
+ Mark::Visited => return Ok(()),
},
Entry::Vacant(entry) => {
entry.insert(Mark::Visiting);
@@ -37,10 +37,13 @@ fn visit<'a>(
for field in &strct.fields {
if let Type::Ident(ident) = &field.ty {
if let Some(inner) = types.structs.get(&ident.rust) {
- visit(cx, inner, sorted, marks, types);
+ if visit(cx, inner, sorted, marks, types).is_err() {
+ cx.error(field, "unsupported cyclic data structure");
+ }
}
}
}
marks.insert(strct, Mark::Visited);
sorted.push(strct);
+ Ok(())
}