Skip to content

Commit a9c5550

Browse files
Sdoba16LesterEvSe
authored andcommitted
Error test cases, multifile error case
1 parent 9426812 commit a9c5550

File tree

5 files changed

+229
-14
lines changed

5 files changed

+229
-14
lines changed
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: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,4 +1513,158 @@ 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+
#[ignore = "TODO(Error_Formatting): The compiler currently strips the .simf extension from file paths during graph construction. This test expects the extension to be preserved."]
1561+
fn test_display_error_in_imported_dependency() {
1562+
let temp_dir = TempDir::new().unwrap();
1563+
let root_path = create_simf_file(temp_dir.path(), "main.simf", "use lib::math::add;");
1564+
1565+
create_simf_file(
1566+
temp_dir.path(),
1567+
"libs/lib/math.simf",
1568+
"pub fn add(a: u32 b: u32) {}",
1569+
);
1570+
1571+
let mut lib_map = HashMap::new();
1572+
lib_map.insert("lib".to_string(), temp_dir.path().join("libs/lib"));
1573+
1574+
let (root_program, root_source) = parse_root(&root_path);
1575+
let mut handler = ErrorCollector::new();
1576+
1577+
let result =
1578+
ProjectGraph::new(root_source, Arc::from(lib_map), &root_program, &mut handler);
1579+
1580+
assert!(
1581+
result.is_none(),
1582+
"Graph construction should fail due to syntax error in dependency"
1583+
);
1584+
assert!(
1585+
handler.has_errors(),
1586+
"Handler should contain the imported module's error"
1587+
);
1588+
1589+
let err_msg = ErrorCollector::to_string(&handler);
1590+
1591+
assert!(
1592+
err_msg.contains("math.simf:1"),
1593+
"Error should correctly display the file name math.simf and line number. Got:\n{}",
1594+
err_msg
1595+
);
1596+
assert!(
1597+
err_msg.contains("pub fn add(a: u32 b: u32) {}"),
1598+
"Error should print the snippet from the imported file. Got:\n{}",
1599+
err_msg
1600+
);
1601+
}
1602+
1603+
#[test]
1604+
#[ignore = "TODO(Error_Formatting): The compiler currently strips the .simf extension from file paths during graph construction. This test expects the extension to be preserved."]
1605+
fn test_display_unresolved_item_in_dependency() {
1606+
let (graph, ids, _dir) = setup_graph(vec![
1607+
("libs/lib/B.simf", "pub fn real() {}"),
1608+
("libs/lib/A.simf", "use lib::B::ghost;\npub fn foo() {}"),
1609+
("main.simf", "use lib::A::foo;"),
1610+
]);
1611+
1612+
let id_a = *ids.get("A").unwrap();
1613+
let id_b = *ids.get("B").unwrap();
1614+
let id_root = *ids.get("main").unwrap();
1615+
let order = vec![id_b, id_a, id_root];
1616+
1617+
let mut handler = ErrorCollector::new();
1618+
let _ = graph.build_program(&order, &mut handler);
1619+
1620+
let err_msg = ErrorCollector::to_string(&handler);
1621+
1622+
assert!(
1623+
err_msg.contains("A.simf:1"),
1624+
"Error should point to A.simf where the bad import happened. Got:\n{}",
1625+
err_msg
1626+
);
1627+
assert!(
1628+
err_msg.contains("use lib::B::ghost;"),
1629+
"Error should print the snippet from A.simf"
1630+
);
1631+
assert!(
1632+
err_msg.contains("Unknown item `ghost`"),
1633+
"Error should correctly identify the missing item"
1634+
);
1635+
}
1636+
1637+
#[test]
1638+
#[ignore = "TODO(Error_Formatting): The compiler currently strips the .simf extension from file paths during graph construction. This test expects the extension to be preserved."]
1639+
fn test_display_private_item_access_in_dependency() {
1640+
let (graph, ids, _dir) = setup_graph(vec![
1641+
("libs/lib/B.simf", "fn secret() {}"),
1642+
("libs/lib/A.simf", "use lib::B::secret;\npub fn foo() {}"),
1643+
("main.simf", "use lib::A::foo;"),
1644+
]);
1645+
1646+
let id_a = *ids.get("A").unwrap();
1647+
let id_b = *ids.get("B").unwrap();
1648+
let id_root = *ids.get("main").unwrap();
1649+
let order = vec![id_b, id_a, id_root];
1650+
1651+
let mut handler = ErrorCollector::new();
1652+
let _ = graph.build_program(&order, &mut handler);
1653+
1654+
let err_msg = ErrorCollector::to_string(&handler);
1655+
1656+
assert!(
1657+
err_msg.contains("A.simf:1"),
1658+
"Error should point to A.simf where the privacy violation happened. Got:\n{}",
1659+
err_msg
1660+
);
1661+
assert!(
1662+
err_msg.contains("use lib::B::secret;"),
1663+
"Error should print the snippet from A.simf"
1664+
);
1665+
assert!(
1666+
err_msg.contains("Item `secret` is private"),
1667+
"Error should correctly identify the privacy violation"
1668+
);
1669+
}
15161670
}

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)