diff --git a/dag/test/claim/match_arm_join_disjoint_coproduct_witness_test.dag b/dag/test/claim/match_arm_join_disjoint_coproduct_witness_test.dag index aabf62b4bd6..789f840913f 100644 --- a/dag/test/claim/match_arm_join_disjoint_coproduct_witness_test.dag +++ b/dag/test/claim/match_arm_join_disjoint_coproduct_witness_test.dag @@ -1,5 +1,26 @@ module test.claim.match_arm_join_disjoint_coproduct_witness_test +import gunbc.compile_diagnostic_census { + CompileDiagnosticCensus, + CensusObserved, + CensusNotRunnable, + census_blocking_rows, + census_rows_of_class, + census_total_count +} +import std.types { String, Bool } +import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } + +data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree + +fn maj_blocking_count(source: String, wanted: String) -> Int { + match compile_dag_diagnostic_census(source) { + CensusObserved { rows: rows } => + census_total_count(rows: census_rows_of_class(rows: census_blocking_rows(rows: rows), wanted: wanted)) + CensusNotRunnable { cause: _ } => 0 - 1 + } +} + // A MATCH JOIN ANSWERED WITH ONE ARM AND NEVER JUDGED THE REST, SO THE VERDICT FLIPPED WITH ARM // ORDER. v1.compiler.infer builds a match expression's type by folding every arm's body type through // v1.compiler.infer_types prefer_specific_type, whose tie-break for two disjoint coproducts is the @@ -178,3 +199,18 @@ test fn maj_matching_ground_element_collection_arms_still_compile() -> Bool { [] ) } + +// A DISJOINT ARM IS A SOURCE TYPE ERROR, so it is a typed TypeMismatch located at the offending arm, +// never an InternalError: InternalError names a compiler defect (a state the compiler could not +// have been handed), and reading it as one sent authors looking for a bug in a correct compiler. +// Both the scalar and the collection ground relations are asserted by CLASS, and the InternalError +// count is pinned to zero so the reclassification cannot silently revert. +test fn maj_kernel_arm_mismatch_is_a_typed_mismatch() -> Bool { + maj_blocking_count(source: maj_kernel_arm_mismatch_fixture_source(), wanted: "TypeMismatch") == 1 + && maj_blocking_count(source: maj_kernel_arm_mismatch_fixture_source(), wanted: "InternalError") == 0 +} + +test fn maj_collection_arm_mismatch_is_a_typed_mismatch() -> Bool { + maj_blocking_count(source: maj_ground_element_collection_mismatch_fixture_source(), wanted: "TypeMismatch") >= 1 + && maj_blocking_count(source: maj_ground_element_collection_mismatch_fixture_source(), wanted: "InternalError") == 0 +} diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index 0fc07cbcaeb..ed4bfba9aa2 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -3081,13 +3081,9 @@ fn match_arm_join_diagnostics(unified_arm_type: Node, arm: ArmInferResult, scope arm_type: arm.body_type, scope: scope ) { - [inference_error( - message: concat( - "match arms produce proven-disjoint types: ", - node_type_shape(n: unified_arm_type, source_indices: scope.type_env.source_indices), - " vs ", - node_type_shape(n: arm.body_type, source_indices: scope.type_env.source_indices) - ), + [type_mismatch_error( + expected: node_type_shape(n: unified_arm_type, source_indices: scope.type_env.source_indices), + got: node_type_shape(n: arm.body_type, source_indices: scope.type_env.source_indices), span: arm_body(n: arm.typed_arm).span, module_name: scope.module_name )] diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index 1b84f5114e5..120321ba6bb 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -4312,22 +4312,14 @@ pub fn match_arm_join_diagnostics( arm.body_type.clone(), scope.clone(), ) { - Rc::new(vec![inference_error( - v1_rt::concat( - v1_rt::concat( - v1_rt::concat( - "match arms produce proven-disjoint types: ".to_string(), - crate::v1_compiler_infer_types::node_type_shape( - unified_arm_type.clone(), - scope.type_env.clone().source_indices.clone(), - ), - ), - " vs ".to_string(), - ), - crate::v1_compiler_infer_types::node_type_shape( - arm.body_type.clone(), - scope.type_env.clone().source_indices.clone(), - ), + Rc::new(vec![type_mismatch_error( + crate::v1_compiler_infer_types::node_type_shape( + unified_arm_type.clone(), + scope.type_env.clone().source_indices.clone(), + ), + crate::v1_compiler_infer_types::node_type_shape( + arm.body_type.clone(), + scope.type_env.clone().source_indices.clone(), ), crate::v1_std_core::arm_body(arm.typed_arm.clone()) .span