Skip to content

Commit 6284181

Browse files
committed
Error test cases, multifile error case
1 parent a2e29d5 commit 6284181

5 files changed

Lines changed: 226 additions & 14 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn add(a: u32, b: u32) -> (bool, u32) {
2+
jet::add_32(a, b)
3+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pub fn add(a: u32, b: u32) -> (bool, u32) {
2+
let (_, c): (bool, u32) = jet::add_32(a, b);
3+
jet::add_32(c, 1)
4+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use lib::groups::add;
2+
use lib::math::add;
3+
4+
fn main() {
5+
let x: u32 = 5;
6+
let y: u32 = 10;
7+
let (_, result): (bool, u32) = add(x, y);
8+
assert!(jet::eq_32(result, 16));
9+
}

src/driver.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,4 +1513,155 @@ pub(crate) mod tests {
15131513
"Compiler must catch infinite alias cycles"
15141514
);
15151515
}
1516+
1517+
// --- C3 Error Display Tests ---
1518+
1519+
#[test]
1520+
fn display_c3_cycle_detected() {
1521+
let cycle = vec![
1522+
"main.simf".to_string(),
1523+
"libs/lib/A.simf".to_string(),
1524+
"libs/lib/B.simf".to_string(),
1525+
"main.simf".to_string(),
1526+
];
1527+
1528+
let error = C3Error::CycleDetected(cycle);
1529+
1530+
let expected = r#"Circular dependency detected: "main.simf -> libs/lib/A.simf -> libs/lib/B.simf -> main.simf""#;
1531+
1532+
assert_eq!(error.to_string(), expected);
1533+
}
1534+
1535+
#[test]
1536+
fn display_c3_inconsistent_linearization() {
1537+
let conflicts = vec![
1538+
vec!["lib/x".to_string(), "lib/y".to_string()],
1539+
vec!["lib/y".to_string(), "lib/x".to_string()],
1540+
];
1541+
1542+
let error = C3Error::InconsistentLinearization {
1543+
module: "main".to_string(),
1544+
conflicts,
1545+
};
1546+
1547+
let expected = r#"Inconsistent resolution order for module 'main'
1548+
The compiler could not resolve the following conflicting import constraints:
1549+
[lib/x, lib/y]
1550+
[lib/y, lib/x]
1551+
Try reordering your `use` statements to avoid cross-wiring."#
1552+
.to_string();
1553+
1554+
assert_eq!(error.to_string(), expected);
1555+
}
1556+
1557+
// --- Dependent File Error Display Tests ---
1558+
1559+
#[test]
1560+
fn test_display_error_in_imported_dependency() {
1561+
let temp_dir = TempDir::new().unwrap();
1562+
let root_path = create_simf_file(temp_dir.path(), "main.simf", "use lib::math::add;");
1563+
1564+
create_simf_file(
1565+
temp_dir.path(),
1566+
"libs/lib/math.simf",
1567+
"pub fn add(a: u32 b: u32) {}",
1568+
);
1569+
1570+
let mut lib_map = HashMap::new();
1571+
lib_map.insert("lib".to_string(), temp_dir.path().join("libs/lib"));
1572+
1573+
let (root_program, root_source) = parse_root(&root_path);
1574+
let mut handler = ErrorCollector::new();
1575+
1576+
let result =
1577+
ProjectGraph::new(root_source, Arc::from(lib_map), &root_program, &mut handler);
1578+
1579+
assert!(
1580+
result.is_none(),
1581+
"Graph construction should fail due to syntax error in dependency"
1582+
);
1583+
assert!(
1584+
handler.has_errors(),
1585+
"Handler should contain the imported module's error"
1586+
);
1587+
1588+
let err_msg = ErrorCollector::to_string(&handler);
1589+
1590+
assert!(
1591+
err_msg.contains("math:1"),
1592+
"Error should correctly display the file name (without .simf) and line number. Got:\n{}",
1593+
err_msg
1594+
);
1595+
assert!(
1596+
err_msg.contains("pub fn add(a: u32 b: u32) {}"),
1597+
"Error should print the snippet from the imported file. Got:\n{}",
1598+
err_msg
1599+
);
1600+
}
1601+
1602+
#[test]
1603+
fn test_display_unresolved_item_in_dependency() {
1604+
let (graph, ids, _dir) = setup_graph(vec![
1605+
("libs/lib/B.simf", "pub fn real() {}"),
1606+
("libs/lib/A.simf", "use lib::B::ghost;\npub fn foo() {}"),
1607+
("main.simf", "use lib::A::foo;"),
1608+
]);
1609+
1610+
let id_a = *ids.get("A").unwrap();
1611+
let id_b = *ids.get("B").unwrap();
1612+
let id_root = *ids.get("main").unwrap();
1613+
let order = vec![id_b, id_a, id_root];
1614+
1615+
let mut handler = ErrorCollector::new();
1616+
let _ = graph.build_program(&order, &mut handler);
1617+
1618+
let err_msg = ErrorCollector::to_string(&handler);
1619+
1620+
assert!(
1621+
err_msg.contains("A:1"),
1622+
"Error should point to A (without .simf) where the bad import happened. Got:\n{}",
1623+
err_msg
1624+
);
1625+
assert!(
1626+
err_msg.contains("use lib::B::ghost;"),
1627+
"Error should print the snippet from A.simf"
1628+
);
1629+
assert!(
1630+
err_msg.contains("Unknown item `ghost`"),
1631+
"Error should correctly identify the missing item"
1632+
);
1633+
}
1634+
1635+
#[test]
1636+
fn test_display_private_item_access_in_dependency() {
1637+
let (graph, ids, _dir) = setup_graph(vec![
1638+
("libs/lib/B.simf", "fn secret() {}"),
1639+
("libs/lib/A.simf", "use lib::B::secret;\npub fn foo() {}"),
1640+
("main.simf", "use lib::A::foo;"),
1641+
]);
1642+
1643+
let id_a = *ids.get("A").unwrap();
1644+
let id_b = *ids.get("B").unwrap();
1645+
let id_root = *ids.get("main").unwrap();
1646+
let order = vec![id_b, id_a, id_root];
1647+
1648+
let mut handler = ErrorCollector::new();
1649+
let _ = graph.build_program(&order, &mut handler);
1650+
1651+
let err_msg = ErrorCollector::to_string(&handler);
1652+
1653+
assert!(
1654+
err_msg.contains("A:1"),
1655+
"Error should point to A (without .simf) where the privacy violation happened. Got:\n{}",
1656+
err_msg
1657+
);
1658+
assert!(
1659+
err_msg.contains("use lib::B::secret;"),
1660+
"Error should print the snippet from A.simf"
1661+
);
1662+
assert!(
1663+
err_msg.contains("Item `secret` is private"),
1664+
"Error should correctly identify the privacy violation"
1665+
);
1666+
}
15161667
}

src/error.rs

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,6 @@ pub enum Error {
443443
FileNotFound(PathBuf),
444444
UnresolvedItem(Identifier),
445445
PrivateItem(String),
446-
NameCollision(String),
447446
MainNoInputs,
448447
MainNoOutput,
449448
MainRequired,
@@ -564,10 +563,6 @@ impl fmt::Display for Error {
564563
f,
565564
"Item `{name}` is private"
566565
),
567-
Error::NameCollision(name) => write!(
568-
f,
569-
"The name `{name}` is defined multiple times in this scope"
570-
),
571566
Error::InvalidNumberOfArguments(expected, found) => write!(
572567
f,
573568
"Expected {expected} arguments, found {found} arguments"
@@ -774,18 +769,68 @@ let x: u32 = Left(
774769
}
775770

776771
#[test]
777-
fn display_private_item() {
778-
let source = SourceFile::new(SourceName::Virtual(Arc::from(FILENAME)), Arc::from(FILE));
779-
let error = Error::PrivateItem("SecretType".to_string())
780-
.with_span(Span::new(8, 20))
772+
fn display_error_inside_imported_module() {
773+
let module_name = "libs/math.simf";
774+
let module_content = "pub fn add(a: u32, b: u32) -> u64 {\n a + b\n}";
775+
let source = SourceFile::new(
776+
SourceName::Virtual(Arc::from(module_name)),
777+
Arc::from(module_content),
778+
);
779+
780+
let error = Error::InvalidNumberOfArguments(2, 1)
781+
.with_span(Span::new(40, 45))
781782
.with_source(source);
782-
let expected = format!(
783-
r#"
784-
--> {FILENAME}:1:9
783+
784+
let expected = r#"
785+
--> libs/math.simf:2:6
785786
|
786-
1 | let a1: List<u32, 5> = None;
787-
| ^^^^^^^^^^^^ Item `SecretType` is private"#
787+
2 | a + b
788+
| ^^^^^ Expected 2 arguments, found 1 arguments"#
789+
.to_string();
790+
assert_eq!(&expected[1..], &error.to_string());
791+
}
792+
793+
#[test]
794+
fn display_unresolved_import_in_main_file() {
795+
let main_name = "main.simf";
796+
let main_content = "use libs::math::multiply;\n\nfn main() {}";
797+
let source = SourceFile::new(
798+
SourceName::Virtual(Arc::from(main_name)),
799+
Arc::from(main_content),
788800
);
801+
802+
let error = Error::UnresolvedItem("multiply".into())
803+
.with_span(Span::new(16, 24))
804+
.with_source(source);
805+
806+
let expected = r#"
807+
--> main.simf:1:17
808+
|
809+
1 | use libs::math::multiply;
810+
| ^^^^^^^^ Unknown item `multiply`"#
811+
.to_string();
812+
assert_eq!(&expected[1..], &error.to_string());
813+
}
814+
815+
#[test]
816+
fn display_private_item_import_across_modules() {
817+
let main_name = "src/auth_test.simf";
818+
let main_content = "use libs::auth::SecretToken;\n\nfn main() {}";
819+
let source = SourceFile::new(
820+
SourceName::Virtual(Arc::from(main_name)),
821+
Arc::from(main_content),
822+
);
823+
824+
let error = Error::PrivateItem("SecretToken".into())
825+
.with_span(Span::new(16, 27))
826+
.with_source(source);
827+
828+
let expected = r#"
829+
--> src/auth_test.simf:1:17
830+
|
831+
1 | use libs::auth::SecretToken;
832+
| ^^^^^^^^^^^ Item `SecretToken` is private"#
833+
.to_string();
789834
assert_eq!(&expected[1..], &error.to_string());
790835
}
791836
}

0 commit comments

Comments
 (0)