diff --git a/src/extension/infer.rs b/src/extension/infer.rs index bae062066..457b463b7 100644 --- a/src/extension/infer.rs +++ b/src/extension/infer.rs @@ -76,6 +76,18 @@ pub enum InferExtensionError { /// The incompatible solution that we found was already there actual: ExtensionSet, }, + #[error("Solved extensions {expected} at {expected_loc:?} and {actual} at {actual_loc:?} should be equal.")] + /// A version of the above with info about which nodes failed to unify + MismatchedConcreteWithLocations { + /// Where the solution we want to insert came from + expected_loc: (Node, Direction), + /// The solution we were trying to insert for this meta + expected: ExtensionSet, + /// Which node we're trying to add a solution for + actual_loc: (Node, Direction), + /// The incompatible solution that we found was already there + actual: ExtensionSet, + }, /// A variable went unsolved that wasn't related to a parameter #[error("Unsolved variable at location {:?}", location)] Unsolved { @@ -314,7 +326,10 @@ impl UnificationContext { } } - /// Try to turn mismatches into `ExtensionError` when possible + /// When trying to unify two metas, check if they both correspond to + /// different ends of the same wire. If so, return an `ExtensionError`. + /// Otherwise check whether they both correspond to *some* location on the + /// graph and include that info the otherwise generic `MismatchedConcrete`. fn report_mismatch( &self, m1: Meta, @@ -375,10 +390,19 @@ impl UnificationContext { } else { None }; - err.unwrap_or(InferExtensionError::MismatchedConcrete { - expected: rs1, - actual: rs2, - }) + if let (Some(loc1), Some(loc2)) = (loc1, loc2) { + err.unwrap_or(InferExtensionError::MismatchedConcreteWithLocations { + expected_loc: *loc1, + expected: rs1, + actual_loc: *loc2, + actual: rs2, + }) + } else { + err.unwrap_or(InferExtensionError::MismatchedConcrete { + expected: rs1, + actual: rs2, + }) + } } /// Take a group of equal metas and merge them into a new, single meta.