Skip to content

Commit 98cdec8

Browse files
committed
feat: add a new test and check the keyword in the library aliases
1 parent f6be739 commit 98cdec8

7 files changed

Lines changed: 159 additions & 90 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ copy_iterator = "warn"
7171
default_trait_access = "warn"
7272
doc_link_with_quotes = "warn"
7373
doc_markdown = "warn"
74-
empty_enum = "warn"
74+
empty_enums = "warn"
7575
enum_glob_use = "allow"
7676
expl_impl_clone_on_copy = "warn"
7777
explicit_deref_methods = "warn"

src/driver.rs

Lines changed: 70 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ pub struct Program {
5252
}
5353

5454
impl Program {
55-
pub fn from_parse(parsed: &parse::Program, source: SourceFile, handler: &mut ErrorCollector) -> Option<Self> {
55+
pub fn from_parse(
56+
parsed: &parse::Program,
57+
source: SourceFile,
58+
handler: &mut ErrorCollector,
59+
) -> Option<Self> {
5660
let root_path = source.name().without_extension();
5761

5862
let mut items: Vec<Item> = Vec::new();
@@ -145,7 +149,7 @@ impl Item {
145149
pub fn from_parse(parsed: &parse::Item, file_id: usize) -> Result<Self, RichError> {
146150
match parsed {
147151
parse::Item::TypeAlias(alias) => {
148-
let driver_alias = TypeAlias::from_parse(alias, file_id);
152+
let driver_alias = TypeAlias::from_parse(alias);
149153
Ok(Item::TypeAlias(driver_alias))
150154
}
151155
parse::Item::Function(func) => {
@@ -229,7 +233,6 @@ impl_eq_hash!(Function; file_id, name, params, ret, body);
229233
#[derive(Clone, Debug)]
230234
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
231235
pub struct TypeAlias {
232-
file_id: usize, // NOTE: Maybe don't need
233236
name: AliasName,
234237
ty: AliasedType,
235238
span: Span,
@@ -240,20 +243,14 @@ impl TypeAlias {
240243
///
241244
/// We explicitly pass `file_id` here because the `parse::Function`
242245
/// doesn't know which file it came from.
243-
pub fn from_parse(parsed: &parse::TypeAlias, file_id: usize) -> Self {
246+
pub fn from_parse(parsed: &parse::TypeAlias) -> Self {
244247
Self {
245-
file_id,
246248
name: parsed.name().clone(),
247249
ty: parsed.ty().clone(),
248250
span: *parsed.as_ref(),
249251
}
250252
}
251253

252-
/// Access the visibility of the alias.
253-
pub fn file_id(&self) -> usize {
254-
self.file_id
255-
}
256-
257254
/// Access the name of the alias.
258255
pub fn name(&self) -> &AliasName {
259256
&self.name
@@ -273,12 +270,25 @@ impl TypeAlias {
273270
}
274271
}
275272

276-
impl_eq_hash!(TypeAlias; file_id, name, ty);
273+
impl_eq_hash!(TypeAlias; name, ty);
277274

278275
#[derive(Debug)]
279276
pub enum C3Error {
280-
CycleDetected(Vec<usize>),
281-
InconsistentLinearization { module: usize },
277+
CycleDetected(Vec<String>),
278+
InconsistentLinearization { module: String },
279+
}
280+
281+
impl fmt::Display for C3Error {
282+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
283+
match self {
284+
C3Error::CycleDetected(cycle) => {
285+
write!(f, "Circular dependency detected: {:?}", cycle.join(" -> "))
286+
}
287+
C3Error::InconsistentLinearization { module } => {
288+
write!(f, "Inconsistent resolution order for module '{:?}'", module)
289+
}
290+
}
291+
}
282292
}
283293

284294
impl ProjectGraph {
@@ -289,29 +299,22 @@ impl ProjectGraph {
289299
handler: &mut ErrorCollector,
290300
) -> Option<Module> {
291301
let dep_key = SourceName::Real(Arc::from(full_path.with_extension("")));
292-
let content = match std::fs::read_to_string(&full_path) {
293-
Ok(c) => c,
294-
Err(_) => {
295-
let err = RichError::new(Error::FileNotFound(PathBuf::from(full_path)), span)
296-
.with_source(importer_source.clone());
297-
298-
handler.push(err);
299-
return None;
300-
}
302+
let Ok(content) = std::fs::read_to_string(full_path) else {
303+
let err = RichError::new(Error::FileNotFound(PathBuf::from(full_path)), span)
304+
.with_source(importer_source.clone());
305+
306+
handler.push(err);
307+
return None;
301308
};
302309

303310
let dep_source_file = SourceFile::new(dep_key.clone(), Arc::from(content.clone()));
304311

305-
if let Some(parsed_program) =
306-
parse::Program::parse_from_str_with_errors(&content, dep_source_file.clone(), handler)
307-
{
308-
Some(Module {
312+
parse::Program::parse_from_str_with_errors(&content, dep_source_file.clone(), handler).map(
313+
|parsed_program| Module {
309314
source: dep_source_file,
310315
parsed_program,
311-
})
312-
} else {
313-
None
314-
}
316+
},
317+
)
315318
}
316319

317320
pub fn new(
@@ -374,14 +377,12 @@ impl ProjectGraph {
374377
continue;
375378
}
376379

377-
let module = if let Some(module) = ProjectGraph::parse_and_get_program(
380+
let Some(module) = ProjectGraph::parse_and_get_program(
378381
&full_path,
379382
importer_source.clone(),
380-
import_span.clone(),
383+
import_span,
381384
handler,
382-
) {
383-
module
384-
} else {
385+
) else {
385386
continue;
386387
};
387388

@@ -432,7 +433,11 @@ impl ProjectGraph {
432433

433434
if visiting.contains(&module) {
434435
let cycle_start = visiting.iter().position(|m| *m == module).unwrap();
435-
return Err(C3Error::CycleDetected(visiting[cycle_start..].to_vec()));
436+
let cycle_names: Vec<String> = visiting[cycle_start..]
437+
.iter()
438+
.map(|&id| self.modules[id].source.name().to_string())
439+
.collect();
440+
return Err(C3Error::CycleDetected(cycle_names));
436441
}
437442

438443
visiting.push(module);
@@ -442,14 +447,16 @@ impl ProjectGraph {
442447
let mut seqs: Vec<Vec<usize>> = Vec::new();
443448

444449
for parent in &parents {
445-
let lin = self.linearize_rec(*parent, memo, visiting)?;
446-
seqs.push(lin);
450+
let line = self.linearize_rec(*parent, memo, visiting)?;
451+
seqs.push(line);
447452
}
448453

449454
seqs.push(parents.clone());
450455

451456
let mut result = vec![module];
452-
let merged = merge(seqs).ok_or(C3Error::InconsistentLinearization { module })?;
457+
let merged = merge(seqs).ok_or(C3Error::InconsistentLinearization {
458+
module: self.modules[module].source.name().to_string(),
459+
})?;
453460

454461
result.extend(merged);
455462

@@ -466,19 +473,17 @@ impl ProjectGraph {
466473
elem: &Identifier,
467474
use_decl: &parse::UseDecl,
468475
) -> Option<RichError> {
469-
let resolution = if let Some(res) = resolutions[ind].get(elem) {
470-
res
471-
} else {
476+
let Some(resolution) = resolutions[ind].get(elem) else {
472477
return Some(RichError::new(
473478
Error::UnresolvedItem(elem.as_inner().to_string()),
474-
*use_decl.span()
479+
*use_decl.span(),
475480
));
476481
};
477-
482+
478483
if matches!(resolution.visibility, parse::Visibility::Private) {
479484
return Some(RichError::new(
480485
Error::PrivateItem(elem.as_inner().to_string()),
481-
*use_decl.span()
486+
*use_decl.span(),
482487
));
483488
}
484489

@@ -512,7 +517,7 @@ impl ProjectGraph {
512517
visibility: vis.clone(),
513518
},
514519
);
515-
520+
516521
None
517522
}
518523

@@ -597,11 +602,17 @@ impl ProjectGraph {
597602
}
598603
}
599604

600-
pub fn resolve_complication_order(&self, handler: &mut ErrorCollector) -> Option<Program> {
601-
// TODO: @LesterEvSe, Resolve errors more appropriately
602-
let mut order = self.c3_linearize().unwrap();
605+
pub fn resolve_complication_order(
606+
&self,
607+
handler: &mut ErrorCollector,
608+
) -> Result<Option<Program>, String> {
609+
let mut order = match self.c3_linearize() {
610+
Ok(order) => order,
611+
Err(err) => return Err(err.to_string()),
612+
};
603613
order.reverse();
604-
self.build_program(&order, handler)
614+
615+
Ok(self.build_program(&order, handler))
605616
}
606617
}
607618

@@ -687,13 +698,7 @@ impl fmt::Display for Item {
687698

688699
impl fmt::Display for TypeAlias {
689700
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
690-
write!(
691-
f,
692-
"type {} [file_id: {}] = {};",
693-
self.name(),
694-
self.file_id(),
695-
self.ty()
696-
)
701+
write!(f, "type {} = {};", self.name(), self.ty())
697702
}
698703
}
699704

@@ -809,9 +814,11 @@ pub(crate) mod tests {
809814
parse::Program::parse_from_str_with_errors(&content, source.clone(), &mut handler);
810815

811816
// 5. Check results
812-
if handler.has_errors() {
813-
panic!("Test Setup Failed: Root file syntax error: {}", ErrorCollector::to_string(&handler));
814-
}
817+
assert!(
818+
!handler.has_errors(),
819+
"Test Setup Failed: Root file syntax error: {}",
820+
ErrorCollector::to_string(&handler)
821+
);
815822

816823
(program.expect("Root parsing failed internally"), source)
817824
}
@@ -872,7 +879,7 @@ pub(crate) mod tests {
872879
let root_id = *ids.get("main").unwrap();
873880
let order = vec![root_id]; // Only one file
874881

875-
let mut error_handler= ErrorCollector::new();
882+
let mut error_handler = ErrorCollector::new();
876883
let program = graph
877884
.build_program(&order, &mut error_handler)
878885
.expect("Failed to build program");
@@ -964,8 +971,8 @@ pub(crate) mod tests {
964971

965972
// Order: A -> B -> Root
966973
let order = vec![id_a, id_b, id_root];
967-
968-
let mut error_handler= ErrorCollector::new();
974+
975+
let mut error_handler = ErrorCollector::new();
969976
let result = graph.build_program(&order, &mut error_handler);
970977

971978
assert!(

src/error.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl<T> WithSource<T> for Result<T, RichError> {
137137
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
138138
pub struct RichError {
139139
/// The error that occurred.
140-
error: Error,
140+
error: Box<Error>,
141141
/// Area that the error spans inside the file.
142142
span: Span,
143143
/// File context in which the error occurred.
@@ -150,7 +150,7 @@ impl RichError {
150150
/// Create a new error with context.
151151
pub fn new(error: Error, span: Span) -> RichError {
152152
RichError {
153-
error,
153+
error: Box::new(error),
154154
span,
155155
source: None,
156156
}
@@ -171,7 +171,7 @@ impl RichError {
171171
/// a problem on the parsing side.
172172
pub fn parsing_error(reason: &str) -> Self {
173173
Self {
174-
error: Error::CannotParse(reason.to_string()),
174+
error: Box::new(Error::CannotParse(reason.to_string())),
175175
span: Span::new(0, 0),
176176
source: None,
177177
}
@@ -263,7 +263,7 @@ impl std::error::Error for RichError {}
263263

264264
impl From<RichError> for Error {
265265
fn from(error: RichError) -> Self {
266-
error.error
266+
*error.error
267267
}
268268
}
269269

@@ -279,7 +279,7 @@ where
279279
I: ValueInput<'tokens, Token = Token<'src>, Span = Span>,
280280
{
281281
fn merge(self, other: Self) -> Self {
282-
match (&self.error, &other.error) {
282+
match (&*self.error, &*other.error) {
283283
(Error::Grammar(_), Error::Grammar(_)) => other,
284284
(Error::Grammar(_), _) => other,
285285
(_, Error::Grammar(_)) => self,
@@ -315,11 +315,11 @@ where
315315
let found_string = found.map(|t| t.to_string());
316316

317317
Self {
318-
error: Error::Syntax {
318+
error: Box::new(Error::Syntax {
319319
expected: expected_tokens,
320320
label: None,
321321
found: found_string,
322-
},
322+
}),
323323
span,
324324
source: None,
325325
}
@@ -342,11 +342,11 @@ where
342342
let found_string = found.map(|t| t.to_string());
343343

344344
Self {
345-
error: Error::Syntax {
345+
error: Box::new(Error::Syntax {
346346
expected: expected_strings,
347347
label: None,
348348
found: found_string,
349-
},
349+
}),
350350
span,
351351
source: None,
352352
}
@@ -355,7 +355,7 @@ where
355355
fn label_with(&mut self, label: &'tokens str) {
356356
if let Error::Syntax {
357357
label: ref mut l, ..
358-
} = &mut self.error
358+
} = &mut *self.error
359359
{
360360
*l = Some(label.to_string());
361361
}
@@ -368,13 +368,19 @@ pub struct ErrorCollector {
368368
errors: Vec<RichError>,
369369
}
370370

371+
impl Default for ErrorCollector {
372+
fn default() -> Self {
373+
Self::new()
374+
}
375+
}
376+
371377
impl ErrorCollector {
372378
pub fn new() -> Self {
373379
Self { errors: Vec::new() }
374380
}
375381

376-
/// Exend existing errors with concrete RichError.
377-
/// We assume that RichError contains SourceFile.
382+
/// Extend existing errors with concrete `RichError`.
383+
/// We assume that `RichError` contains `SourceFile`.
378384
pub fn push(&mut self, error: RichError) {
379385
self.errors.push(error);
380386
}

0 commit comments

Comments
 (0)