1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
//! Every refusal the resolution report contract produces.
//!
//! One error type covers both writer boundaries — the builder and custom
//! deserialization — because both reach the same validator, and a consumer
//! comparing a builder refusal with a wire refusal should compare one value.
use std::fmt;
use thiserror::Error;
use crate::Language;
use super::ResolutionGap;
/// Which report collection a structural rule names.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ReportCollection {
/// The report's resolution units.
Units,
/// The report's symbol definitions.
Definitions,
/// The report's symbol references.
References,
/// The report's resolution records.
Resolutions,
}
impl fmt::Display for ReportCollection {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(match self {
Self::Units => "units",
Self::Definitions => "definitions",
Self::References => "references",
Self::Resolutions => "resolutions",
})
}
}
/// A rejected resolution report, or a rejected write into one.
#[derive(Clone, Debug, Error, PartialEq, Eq)]
pub enum ResolutionReportError {
/// A unit handle another builder issued.
#[error("the unit handle belongs to another builder")]
ForeignUnitHandle,
/// A definition handle another builder issued.
#[error("the definition handle belongs to another builder")]
ForeignDefinitionHandle,
/// A reference handle another builder issued.
#[error("the reference handle belongs to another builder")]
ForeignReferenceHandle,
/// The configured or fixed-width unit capacity is reached.
#[error("the report already holds its limit of {limit} units")]
UnitCapacityExceeded {
/// The capacity that refused the insertion.
limit: u32,
},
/// The configured or fixed-width definition capacity is reached.
#[error("the report already holds its limit of {limit} definitions")]
DefinitionCapacityExceeded {
/// The capacity that refused the insertion.
limit: u32,
},
/// The configured or fixed-width reference capacity is reached.
#[error("the report already holds its limit of {limit} references")]
ReferenceCapacityExceeded {
/// The capacity that refused the insertion.
limit: u32,
},
/// The configured or fixed-width resolution-record capacity is reached.
///
/// A document may state more records than it states references, so this
/// ceiling is reached by a decoded report rather than by a writer.
#[error("the report already holds its limit of {limit} resolution records")]
ResolutionCapacityExceeded {
/// The capacity that refused the record.
limit: u32,
},
/// More than one record names one reference.
#[error("reference {reference} already carries a resolution record")]
DuplicateResolution {
/// The reference named twice.
reference: u32,
},
/// A definition or reference names a unit the report does not contain.
#[error("unit {unit} is not in the report")]
UnknownUnit {
/// The absent unit identifier.
unit: u32,
},
/// A parent, enclosing definition, or candidate names an absent definition.
#[error("definition {definition} is not in the report")]
UnknownDefinition {
/// The absent definition identifier.
definition: u32,
},
/// A record names a reference the report does not contain.
#[error("reference {reference} is not in the report")]
UnknownReference {
/// The absent reference identifier.
reference: u32,
},
/// An identifier does not equal its own sorted slice position.
#[error("{collection} position {position} carries identifier {id}")]
NonDenseId {
/// The collection holding the entry.
collection: ReportCollection,
/// The entry's position in the collection.
position: u32,
/// The identifier the entry carried.
id: u32,
},
/// A collection is not in its stable structural order.
#[error("{collection} position {position} breaks the structural order")]
UnsortedEntries {
/// The collection holding the entry.
collection: ReportCollection,
/// The position that follows a greater predecessor.
position: u32,
},
/// Two units share one stable key.
#[error("two units share the key `{key}`")]
DuplicateUnitKey {
/// The repeated key.
key: Box<str>,
},
/// A definition or reference contradicts its unit's language.
///
/// The offender is named by its own coordinates, so a bad definition and a
/// bad reference at two positions never produce one value.
#[error("{collection} position {position} claims {claimed:?} in {unit_language:?} unit {unit}")]
UnitLanguageMismatch {
/// The collection holding the offending record.
collection: ReportCollection,
/// The offender's position in that collection.
position: u32,
/// The unit whose language was contradicted.
unit: u32,
/// The language the record claimed.
claimed: Language,
/// The language the unit states.
unit_language: Language,
},
/// A parent definition belongs to another unit.
#[error("definition {definition} has parent {parent} from another unit")]
ForeignParentDefinition {
/// The child definition.
definition: u32,
/// The parent in the other unit.
parent: u32,
},
/// An enclosing definition belongs to another unit.
#[error("reference {reference} is enclosed by definition {enclosing} from another unit")]
ForeignEnclosingDefinition {
/// The reference.
reference: u32,
/// The enclosing definition in the other unit.
enclosing: u32,
},
/// The definition-parent relation contains a cycle.
#[error("definition {definition} is its own ancestor")]
DefinitionParentCycle {
/// A definition on the cycle.
definition: u32,
},
/// A reference carries no resolution record.
#[error("reference {reference} carries no resolution record")]
MissingResolution {
/// The unrecorded reference.
reference: u32,
},
/// One record names one definition twice.
#[error("reference {reference} names candidate definition {definition} twice")]
DuplicateCandidate {
/// The record's reference.
reference: u32,
/// The repeated candidate definition.
definition: u32,
},
/// A record's candidates are out of order.
#[error("reference {reference} carries candidates out of order at position {position}")]
UnsortedCandidates {
/// The record's reference.
reference: u32,
/// The position that follows a greater predecessor.
position: u32,
},
/// One record names one gap twice.
#[error("reference {reference} names the gap {gap:?} twice")]
DuplicateGap {
/// The record's reference.
reference: u32,
/// The repeated gap.
gap: ResolutionGap,
},
/// A record's gaps are out of order.
#[error("reference {reference} carries gaps out of order at position {position}")]
UnsortedGaps {
/// The record's reference.
reference: u32,
/// The position that follows a greater predecessor.
position: u32,
},
/// A record mixes resolved and possible candidates.
#[error("reference {reference} mixes resolved and possible candidates")]
MixedCandidateCertainty {
/// The record's reference.
reference: u32,
},
/// A resolved record does not name exactly one definition.
#[error("reference {reference} is resolved to {candidates} candidates")]
ResolvedCandidateCount {
/// The record's reference.
reference: u32,
/// How many candidates the record carried.
candidates: u32,
},
/// A resolved record carries a gap.
#[error("reference {reference} is resolved and still carries a gap")]
ResolvedWithGaps {
/// The record's reference.
reference: u32,
},
/// A candidate-free record carries no gap.
#[error("reference {reference} has neither a candidate nor a gap")]
EmptyResolution {
/// The record's reference.
reference: u32,
},
/// A span names a path that is not normalized repository-relative.
#[error("`{path}` is not a normalized repository-relative path")]
InvalidSourcePath {
/// The rejected path.
path: Box<str>,
},
/// A span ends before it starts.
#[error("a span in `{path}` ends before it starts")]
ReversedSiteSpan {
/// The span's path.
path: Box<str>,
},
/// A span covers no source.
#[error("a span in `{path}` is zero width")]
EmptySiteSpan {
/// The span's path.
path: Box<str>,
},
}