Skip to main content

macroonz_compiler/relation/
type_contract.rs

1//! The relation home's trait surface: how each refusal reads and preserves its concrete cause.
2
3use super::{
4    KeyedRosterRowsError, ReachabilityError, RepeatedRelationPairs, SameRosterRequired,
5    StructuralMismatch,
6};
7use core::error::Error;
8use core::fmt::{self, Display, Formatter};
9
10impl<const N: usize> fmt::Debug for super::RepeatedRelationPair<N> {
11    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
12        formatter
13            .debug_struct("RepeatedRelationPair")
14            .field("left_position", &self.left_position())
15            .field("right_position", &self.right_position())
16            .field("first", &self.first_position())
17            .field("repeated", self.repeated_positions())
18            .finish()
19    }
20}
21
22impl<LeftKey, RightKey, const N: usize> Display for KeyedRosterRowsError<LeftKey, RightKey, N> {
23    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
24        match self {
25            Self::Overflow(overflow) => Display::fmt(overflow, formatter),
26            Self::ForeignLeft(foreign) if foreign.count() == 1 => {
27                formatter.write_str("one relation row references a key outside the left roster")
28            }
29            Self::ForeignLeft(foreign) => write!(
30                formatter,
31                "{} relation rows reference keys outside the left roster",
32                foreign.count()
33            ),
34            Self::ForeignRight(foreign) if foreign.count() == 1 => {
35                formatter.write_str("one relation row references a key outside the right roster")
36            }
37            Self::ForeignRight(foreign) => write!(
38                formatter,
39                "{} relation rows reference keys outside the right roster",
40                foreign.count()
41            ),
42        }
43    }
44}
45
46impl<LeftKey: fmt::Debug, RightKey: fmt::Debug, const N: usize> Error
47    for KeyedRosterRowsError<LeftKey, RightKey, N>
48{
49    fn source(&self) -> Option<&(dyn Error + 'static)> {
50        match self {
51            Self::Overflow(overflow) => Some(overflow),
52            Self::ForeignLeft(_) | Self::ForeignRight(_) => None,
53        }
54    }
55}
56
57impl<const N: usize> Display for RepeatedRelationPairs<N> {
58    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
59        if self.count() == 1 {
60            formatter.write_str("one relation endpoint pair occurs more than once")
61        } else {
62            write!(
63                formatter,
64                "{} relation endpoint pairs occur more than once",
65                self.count()
66            )
67        }
68    }
69}
70
71impl<const N: usize> Error for RepeatedRelationPairs<N> {}
72
73impl<Answer> Display for StructuralMismatch<Answer> {
74    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
75        formatter
76            .write_str("the computed structural answer differs from the caller-required answer")
77    }
78}
79
80impl<Answer: fmt::Debug> Error for StructuralMismatch<Answer> {}
81
82impl Display for SameRosterRequired {
83    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
84        formatter.write_str(
85            "the structural question requires both relation sides to borrow one roster instance",
86        )
87    }
88}
89
90impl Error for SameRosterRequired {}
91
92impl<Key> Display for ReachabilityError<Key> {
93    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
94        match self {
95            Self::DifferentRosters(cause) => Display::fmt(cause, formatter),
96            Self::RootOutsideRoster { .. } => {
97                formatter.write_str("the reachability root is outside the shared roster")
98            }
99        }
100    }
101}
102
103impl<Key: fmt::Debug> Error for ReachabilityError<Key> {
104    fn source(&self) -> Option<&(dyn Error + 'static)> {
105        match self {
106            Self::DifferentRosters(cause) => Some(cause),
107            Self::RootOutsideRoster { .. } => None,
108        }
109    }
110}