diff --git a/check/classic/classic.exp b/check/classic/classic.exp index c7d1a0aa..5406478a 100644 --- a/check/classic/classic.exp +++ b/check/classic/classic.exp @@ -269,6 +269,17 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Right ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.left +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:9: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:18: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:9: Alias.sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:17: Alias.product.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:14: constructors.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:19: constr_with_eq.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:23: record.unused diff --git a/check/classic/classic.ref b/check/classic/classic.ref index cea2bcfe..50255555 100644 --- a/check/classic/classic.ref +++ b/check/classic/classic.ref @@ -269,6 +269,17 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Right ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.left +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:9: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:18: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:9: Alias.sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:17: Alias.product.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:14: constructors.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:19: constr_with_eq.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:23: record.unused @@ -721,7 +732,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 593 -Success: 593 +Total: 603 +Success: 603 Failed: 0 Ratio: 100.% diff --git a/check/internal/internal.exp b/check/internal/internal.exp index 84a6c92a..9429beef 100644 --- a/check/internal/internal.exp +++ b/check/internal/internal.exp @@ -221,6 +221,17 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Right ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.left +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:9: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:18: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:9: Alias.sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:17: Alias.product.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:14: constructors.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:19: constr_with_eq.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:23: record.unused diff --git a/check/internal/internal.ref b/check/internal/internal.ref index a004e70d..dab000ad 100644 --- a/check/internal/internal.ref +++ b/check/internal/internal.ref @@ -221,6 +221,17 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Right ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.left +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:9: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:18: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:9: Alias.sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:17: Alias.product.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:14: constructors.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:19: constr_with_eq.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:23: record.unused @@ -673,7 +684,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 549 -Success: 549 +Total: 559 +Success: 559 Failed: 0 Ratio: 100.% diff --git a/check/threshold-1/threshold-1.exp b/check/threshold-1/threshold-1.exp index be1548ac..19a9adc4 100644 --- a/check/threshold-1/threshold-1.exp +++ b/check/threshold-1/threshold-1.exp @@ -612,6 +612,17 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Right ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.left +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:9: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:18: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:9: Alias.sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:17: Alias.product.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:14: constructors.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:19: constr_with_eq.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:23: record.unused @@ -691,6 +702,59 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Left ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.right +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:8: sum.Used_externally +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:12: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:13: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:14: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:15: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:16: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:17: product.used_externally +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:4: Alias.sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:5: Alias.sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:6: Alias.sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:7: Alias.sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:8: Alias.sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:12: Alias.product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:13: Alias.product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:14: Alias.product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:15: Alias.product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:16: Alias.product.used_directly + ./examples/using_dune/preprocessed_lib/preprocessed.mli:16: constructors.Internally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:17: constructors.Externally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:25: record.internally_used diff --git a/check/threshold-1/threshold-1.ref b/check/threshold-1/threshold-1.ref index aed84db1..45c22c84 100644 --- a/check/threshold-1/threshold-1.ref +++ b/check/threshold-1/threshold-1.ref @@ -612,6 +612,17 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Right ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.left +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:9: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:18: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:9: Alias.sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:17: Alias.product.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:14: constructors.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:19: constr_with_eq.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:23: record.unused @@ -691,6 +702,59 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Left ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.right +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:8: sum.Used_externally +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:12: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:13: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:14: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:15: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:16: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:17: product.used_externally +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:4: Alias.sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:5: Alias.sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:6: Alias.sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:7: Alias.sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:8: Alias.sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:12: Alias.product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:13: Alias.product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:14: Alias.product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:15: Alias.product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:16: Alias.product.used_directly + ./examples/using_dune/preprocessed_lib/preprocessed.mli:16: constructors.Internally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:17: constructors.Externally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:25: record.internally_used @@ -1145,7 +1209,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 939 -Success: 939 +Total: 1001 +Success: 1001 Failed: 0 Ratio: 100.% diff --git a/check/threshold-3-0.5/threshold-3-0.5.exp b/check/threshold-3-0.5/threshold-3-0.5.exp index 313bc7ea..999f0e6a 100644 --- a/check/threshold-3-0.5/threshold-3-0.5.exp +++ b/check/threshold-3-0.5/threshold-3-0.5.exp @@ -794,6 +794,17 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Right ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.left +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:9: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:18: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:9: Alias.sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:17: Alias.product.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:14: constructors.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:19: constr_with_eq.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:23: record.unused @@ -873,6 +884,59 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Left ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.right +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:8: sum.Used_externally +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:12: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:13: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:14: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:15: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:16: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:17: product.used_externally +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:4: Alias.sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:5: Alias.sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:6: Alias.sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:7: Alias.sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:8: Alias.sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:12: Alias.product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:13: Alias.product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:14: Alias.product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:15: Alias.product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:16: Alias.product.used_directly + ./examples/using_dune/preprocessed_lib/preprocessed.mli:16: constructors.Internally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:17: constructors.Externally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:25: record.internally_used diff --git a/check/threshold-3-0.5/threshold-3-0.5.ref b/check/threshold-3-0.5/threshold-3-0.5.ref index 7fed8c11..65cf15dd 100644 --- a/check/threshold-3-0.5/threshold-3-0.5.ref +++ b/check/threshold-3-0.5/threshold-3-0.5.ref @@ -794,6 +794,17 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Right ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.left +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:9: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:18: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:8: sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:16: product.unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:9: Alias.sum.Unused +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:17: Alias.product.unused + ./examples/using_dune/preprocessed_lib/preprocessed.mli:14: constructors.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:19: constr_with_eq.Unused ./examples/using_dune/preprocessed_lib/preprocessed.mli:23: record.unused @@ -873,6 +884,59 @@ Nothing else to report in this section ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:2: either.Left ./examples/docs/fields_and_constructors/code_constructs/polymorphic_type/polymorphic_type_lib.mli:3: both.right +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:8: sum.Used_externally +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:12: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:13: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:14: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:15: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:16: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli:17: product.used_externally +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:3: sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:4: sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:5: sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:6: sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:7: sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:11: product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:12: product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:13: product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:14: product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli:15: product.used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:4: Alias.sum.Used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:5: Alias.sum.Used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:6: Alias.sum.Used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:7: Alias.sum.Used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:8: Alias.sum.Used_directly +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:12: Alias.product.used_by_explicit_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:13: Alias.product.used_by_hidden_equation +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:14: Alias.product.used_by_include +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:15: Alias.product.used_by_module_alias +./examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:16: Alias.product.used_directly + ./examples/using_dune/preprocessed_lib/preprocessed.mli:16: constructors.Internally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:17: constructors.Externally_used ./examples/using_dune/preprocessed_lib/preprocessed.mli:25: record.internally_used @@ -1549,7 +1613,7 @@ Nothing else to report in this section -------------------------------------------------------------------------------- -Total: 1261 -Success: 1261 +Total: 1323 +Success: 1323 Failed: 0 Ratio: 100.% diff --git a/docs/fields_and_constructors/FIELDS_AND_CONSTRUCTORS.md b/docs/fields_and_constructors/FIELDS_AND_CONSTRUCTORS.md index 0670e55d..656fbb0f 100644 --- a/docs/fields_and_constructors/FIELDS_AND_CONSTRUCTORS.md +++ b/docs/fields_and_constructors/FIELDS_AND_CONSTRUCTORS.md @@ -10,6 +10,9 @@ + [Examples](#examples) + [Limitations](#limitations) + [Polymorphic variant](#polymorphic-variant) + + [Extensible variant](#extensible-variant) + + [Inline record](#inline-record) + + [Type equalities](#type-equalities) # Fields and constructors @@ -257,3 +260,206 @@ the [Inline record](./code_constructs/INLINE_RECORD.md) example If you have a strong need/desire for this feature, please feel free to [open an issue](https://github.com/LexiFi/dead_code_analyzer/issues/new) + +## Type equalities + +Related issues : +- [issue #79](https://github.com/LexiFi/dead_code_analyzer/issues/79); +- [issue #80](https://github.com/LexiFi/dead_code_analyzer/issues/80); +- [issue #81](https://github.com/LexiFi/dead_code_analyzer/issues/81); +- [issue #82](https://github.com/LexiFi/dead_code_analyzer/issues/82). + +When defining a variant or record type, one can constrain it to be equal +to another in 2 different ways: +- via an explicit type equation (`type t1 = t2 = ...`); +- implicitly, when the type is defined without an explicit equation in the + interface, whereas it is either explicited or implied by construction + (e.g. through includes or module aliases) in the implementation. + +Either way, the analyzer does not account for such equalities and analyzes +each type's components indepently. Thus, a use of a constructor or field in +`t1` is not considered as a use for that same component in `t2` (with +`t1 = t2`), and vice versa. +This leads to **false positives**. + +### Example + +The reference files for this example are in the +[equal\_types](../../examples/docs/fields_and_constructors/limitations/equal_types) +directory. + +The reference takes place in `/tmp/docs/fields_and_constructors/limitations`, +which is a copy of the [limitations](../../../examples/docs/fields_and_constructors/limitations) +directory. Reported locations may differ depending on the location of the +source files. + +The compilation command is : +``` +make -C equal_types build +``` + +The analysis command is : +``` +make -C equal_types analyze +``` + +The compile + analyze command is : +``` +make -C equal_types +``` + +Code: +```OCaml +(* definitions.ml *) +type sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Unused + +type product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + unused : int; +} +``` +These 2 types are re-exposed by 4 modules : `Via_explicit_equations`, +`Via_hidden_equations`, `Via_include`, and `Via_module_alias`. We will not +display all of their content here because they mostly consist in the +repetition of `Definitions`. Feel free to explore them. + +`Via_explicit_equations` is defined within a single .ml and it uses the following constructs: +```OCaml +type sum = Definitions.sum = (* constructors *) +type product = Definitions.product = (* fields *) +``` + +`Via_hidden_equations` is implemented the same as `Via_explicit_equations` +in its .ml, and its .mli is the same as `Definitions`. + +`Via_include` is implemented as below and its interface is the same as +`Definitions` : +```OCaml +(* via_include.ml *) +include Definitions +``` + +`Via_module_alias` is implented as below and its module `Alias` is defined +explicitly in the interface : +```OCaml +(* via_module_alias.ml *) +module Alias = Definitions +``` + +The different constructors and fields are used by `Equal_types`: +```OCaml +(* equal_types.ml *) +let _ = + let open Definitions in + fun {used_directly; _} -> Used_directly + +let _ = + let open Via_explicit_equations in + fun {used_by_explicit_equation; _} -> Used_by_explicit_equation + +let _ = + let open Via_hidden_equations in + fun {used_by_hidden_equation; _} -> Used_by_hidden_equation + +let _ = + let open Via_include in + fun {used_by_include; _} -> Used_by_include + +let _ = + let open Via_module_alias.Alias in + fun {used_by_module_alias; _} -> Used_by_module_alias +``` + +Compile and analyze: +``` +$ make -C equal_types/ +make: Entering directory '/tmp/docs/fields_and_constructors/limitations/equal_types' +ocamlopt -bin-annot definitions.ml via_explicit_equations.ml via_hidden_equations.mli via_hidden_equations.ml via_include.mli via_include.ml via_mod +ule_alias.mli via_module_alias.ml equal_types.ml +dead_code_analyzer --nothing -T all . +Scanning files... + [DONE] + +.> UNUSED CONSTRUCTORS/RECORD FIELDS: +==================================== +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:3: sum.Used_by_explicit_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:4: sum.Used_by_hidden_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:5: sum.Used_by_include +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:6: sum.Used_by_module_alias +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:8: sum.Unused +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:11: product.used_by_explicit_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:12: product.used_by_hidden_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:13: product.used_by_include +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:14: product.used_by_module_alias +/tmp/docs/fields_and_constructors/limitations/equal_types/definitions.ml:16: product.unused +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:3: sum.Used_by_explicit_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:5: sum.Used_by_include +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:6: sum.Used_by_module_alias +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:7: sum.Used_directly +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:8: sum.Unused +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:11: product.used_by_explicit_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:13: product.used_by_include +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:14: product.used_by_module_alias +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:15: product.used_directly +/tmp/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli:16: product.unused +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:3: sum.Used_by_explicit_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:4: sum.Used_by_hidden_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:6: sum.Used_by_module_alias +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:7: sum.Used_directly +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:8: sum.Unused +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:11: product.used_by_explicit_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:12: product.used_by_hidden_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:14: product.used_by_module_alias +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:15: product.used_directly +/tmp/docs/fields_and_constructors/limitations/equal_types/via_include.mli:16: product.unused +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:4: Alias.sum.Used_by_explicit_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:5: Alias.sum.Used_by_hidden_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:6: Alias.sum.Used_by_include +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:8: Alias.sum.Used_directly +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:9: Alias.sum.Unused +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:12: Alias.product.used_by_explicit_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:13: Alias.product.used_by_hidden_equation +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:14: Alias.product.used_by_include +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:16: Alias.product.used_directly +/tmp/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli:17: Alias.product.unused + +Nothing else to report in this section +-------------------------------------------------------------------------------- + + +make: Leaving directory '/tmp/docs/fields_and_constructors/limitations/equal_types' + +``` + +As we can see, there are a lot of reports. Most of them are false positives: +for each type, components only used by other equal types are report unused. +I.e. only components used directly via a type is considered used for that +type. + +Although the results are valid according to OCaml's typing (if there is no +type equation, the defined type is incompatible with any other type), they +are not actionable because one cannot remove a component without removing +it from all the other equal types. +In order to make the results actionable, one must be able to remove the +component from all the equal types. Thus, the expected results would only +consist of `sum.Unused`, and `product.unused`, either for each type or only +for `Definitions`' types. + +> [!NOTE] +> The type components in `Via_explicit_equations` are not reported. This +> follows OCaml's typing, and is the expected behavior. +> > The optional type equation `= typexpr` makes the defined type equivalent +> > to the type expression `typexpr`: one can be substituted for the other +> > during typing. +> +> There are no false negatives. diff --git a/examples/docs/fields_and_constructors/Makefile b/examples/docs/fields_and_constructors/Makefile index ed0a10f4..6b0a9a62 100644 --- a/examples/docs/fields_and_constructors/Makefile +++ b/examples/docs/fields_and_constructors/Makefile @@ -4,7 +4,9 @@ all: build build: make -C code_constructs + make -C limitations clean: rm -f *~ *.cm* *.o *.obj make -C code_constructs clean + make -C limitations clean diff --git a/examples/docs/fields_and_constructors/limitations/Makefile b/examples/docs/fields_and_constructors/limitations/Makefile new file mode 100644 index 00000000..2a0cd492 --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/Makefile @@ -0,0 +1,10 @@ +.PHONY: clean build + +all: build + +build: + make -C equal_types build + +clean: + rm -f *~ *.cm* *.o *.obj + make -C equal_types clean diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/Makefile b/examples/docs/fields_and_constructors/limitations/equal_types/Makefile new file mode 100644 index 00000000..c0cd3ba3 --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/Makefile @@ -0,0 +1,18 @@ +SRC:=definitions.ml \ + via_explicit_equations.ml \ + via_hidden_equations.mli via_hidden_equations.ml \ + via_include.mli via_include.ml \ + via_module_alias.mli via_module_alias.ml \ + all_internal.mli all_internal.ml \ + equal_types.ml + +all: build analyze + +build: + ocamlopt -bin-annot ${SRC} + +analyze: + dead_code_analyzer --nothing -T all . + +clean: + rm -f *.cm* *.o a.out diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/all_internal.ml b/examples/docs/fields_and_constructors/limitations/equal_types/all_internal.ml new file mode 100644 index 00000000..4e46ffeb --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/all_internal.ml @@ -0,0 +1,97 @@ +(* all_internal.mli *) +type original_sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Used_externally + | Unused + +type original_product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + used_externally : int; + unused : int; +} + +let _ : original_product -> original_sum = + fun {used_directly; _} -> Used_directly + +type explicit_eq_sum = original_sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Used_externally + | Unused + +type explicit_eq_product = original_product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + used_externally : int; + unused : int; +} + +let _ : explicit_eq_product -> explicit_eq_sum = + fun {used_by_explicit_equation; _} -> Used_by_explicit_equation + +module M : sig + type sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Used_externally + | Unused + + type product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + used_externally : int; + unused : int; + } +end = struct + type sum = explicit_eq_sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Used_externally + | Unused + + type product = explicit_eq_product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + used_externally : int; + unused : int; + } +end + +let _ : M.product -> M.sum = + fun {used_by_hidden_equation; _} -> Used_by_hidden_equation + +module Alias = M + +let _ : Alias.product -> Alias.sum = + fun {used_by_module_alias; _} -> Used_by_module_alias + +include Alias + +let _ : product -> sum = + fun {used_by_include; _} -> Used_by_include diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli b/examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli new file mode 100644 index 00000000..0462e540 --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/all_internal.mli @@ -0,0 +1,19 @@ +(* all_internal.mli *) +type sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Used_externally + | Unused + +type product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + used_externally : int; + unused : int; +} diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml b/examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml new file mode 100644 index 00000000..1ea767d5 --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/definitions.ml @@ -0,0 +1,17 @@ +(* definitions.ml *) +type sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Unused + +type product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + unused : int; +} diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/equal_types.ml b/examples/docs/fields_and_constructors/limitations/equal_types/equal_types.ml new file mode 100644 index 00000000..f122432b --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/equal_types.ml @@ -0,0 +1,24 @@ +(* equal_types.ml *) +let _ = + let open Definitions in + fun {used_directly; _} -> Used_directly + +let _ = + let open Via_explicit_equations in + fun {used_by_explicit_equation; _} -> Used_by_explicit_equation + +let _ = + let open Via_hidden_equations in + fun {used_by_hidden_equation; _} -> Used_by_hidden_equation + +let _ = + let open Via_include in + fun {used_by_include; _} -> Used_by_include + +let _ = + let open Via_module_alias.Alias in + fun {used_by_module_alias; _} -> Used_by_module_alias + +let _ = + let open All_internal in + fun {used_externally; _} -> Used_externally diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/via_explicit_equations.ml b/examples/docs/fields_and_constructors/limitations/equal_types/via_explicit_equations.ml new file mode 100644 index 00000000..334f7c30 --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/via_explicit_equations.ml @@ -0,0 +1,17 @@ +(* via_explicit_equations.ml *) +type sum = Definitions.sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Unused + +type product = Definitions.product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + unused : int; +} diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.ml b/examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.ml new file mode 100644 index 00000000..c1c73577 --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.ml @@ -0,0 +1,18 @@ +(* via_hidden_equations.ml *) +type sum = Definitions.sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Unused + +type product = Definitions.product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + unused : int; +} + diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli b/examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli new file mode 100644 index 00000000..569db26b --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/via_hidden_equations.mli @@ -0,0 +1,18 @@ +(* via_hidden_equations.mli *) +type sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Unused + +type product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + unused : int; +} + diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/via_include.ml b/examples/docs/fields_and_constructors/limitations/equal_types/via_include.ml new file mode 100644 index 00000000..9d62e576 --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/via_include.ml @@ -0,0 +1,2 @@ +(* via_include.ml *) +include Definitions diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli b/examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli new file mode 100644 index 00000000..18441a10 --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/via_include.mli @@ -0,0 +1,18 @@ +(* via_include.mli *) +type sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Unused + +type product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + unused : int; +} + diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.ml b/examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.ml new file mode 100644 index 00000000..46e2bf96 --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.ml @@ -0,0 +1,2 @@ +(* via_module_alias.ml *) +module Alias = Definitions diff --git a/examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli b/examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli new file mode 100644 index 00000000..74bab13b --- /dev/null +++ b/examples/docs/fields_and_constructors/limitations/equal_types/via_module_alias.mli @@ -0,0 +1,19 @@ +(* via_module_alias.mli *) +module Alias : sig + type sum = + | Used_by_explicit_equation + | Used_by_hidden_equation + | Used_by_include + | Used_by_module_alias + | Used_directly + | Unused + + type product = { + used_by_explicit_equation : int; + used_by_hidden_equation : int; + used_by_include : int; + used_by_module_alias : int; + used_directly : int; + unused : int; + } +end diff --git a/src/deadCode.ml b/src/deadCode.ml index 3b1e7123..f1db7188 100644 --- a/src/deadCode.ml +++ b/src/deadCode.ml @@ -105,35 +105,18 @@ let structure_item super self i = begin match i.str_desc with | Tstr_type (_, l) when Config.must_report_section sections.types -> List.iter DeadType.tstr l - | Tstr_module {mb_name = {txt = Some txt; _}; _} -> + | Tstr_module ({mb_name = {txt = Some txt; _}; _} as mb) -> mods := txt :: !mods; - DeadMod.defined := String.concat "." (List.rev !mods) :: !DeadMod.defined + DeadMod.defined := String.concat "." (List.rev !mods) :: !DeadMod.defined; + let modname = State.File_infos.get_modname state.file_infos in + let path = !mods @ [modname] in + DeadSign.collect_equivalence_from_module_alias ~path mb | Tstr_class l when Config.must_report_section sections.methods -> List.iter DeadObj.tstr l - | Tstr_include i -> - let collect_include signature = - let prev_last_loc = !last_loc in - let module_id = - State.File_infos.get_modname state.file_infos - |> Ident.create_persistent - in - let path = [module_id] in - List.iter - (DeadSign.collect_export_from_include ~path) - signature; - last_loc := prev_last_loc; - in - let rec includ mod_expr = - match mod_expr.mod_desc with - | Tmod_ident (_, _) -> collect_include (Utils.signature_of_modtype mod_expr.mod_type) - | Tmod_structure structure -> collect_include structure.str_type - | Tmod_unpack (_, mod_type) -> collect_include (Utils.signature_of_modtype mod_type) - | Tmod_functor (_, mod_expr) - | Tmod_apply (_, mod_expr, _) - | Tmod_apply_unit mod_expr - | Tmod_constraint (mod_expr, _, _, _) -> includ mod_expr - in - includ i.incl_mod + | Tstr_include incl_decl -> + let prev_last_loc = !last_loc in + DeadSign.collect_from_include incl_decl; + last_loc := prev_last_loc | _ -> () end; let r = super.Tast_mapper.structure_item self i in @@ -401,6 +384,7 @@ let eof loc_dep = end; VdNode.eof (); DeadObj.eof (); + DeadSign.eof (); DeadType.dependencies := []; Hashtbl.reset incl @@ -678,6 +662,7 @@ try in !DeadLexiFi.prepare_report DeadType.decs; + DeadType.prepare_report (); let sections = state.config.sections in if Config.must_report_section sections.exported_values then report_unused_exported (); DeadObj.report(); diff --git a/src/deadSign.ml b/src/deadSign.ml index 0f5a5d42..239610e6 100644 --- a/src/deadSign.ml +++ b/src/deadSign.ml @@ -1,6 +1,19 @@ +let exported_modules = Hashtbl.create 32 +(* types of modules exported by the current compilation unit. + This is reset when calling eof. + This is used when encountering a module alias in the .cmt because + the module type information is limited to Mty_alias there. *) + +let eof () = + Hashtbl.reset exported_modules + (* Export helpers *) +let export_module ~path mt = + let key = List.map Ident.name path in + Hashtbl.add exported_modules key mt + let export_object ~path ~comp_unit ~stock id value = (* export a value as an object *) let path = Ident.create_persistent (Ident.name id ^ "*") :: path in @@ -103,6 +116,7 @@ let collect_export_from_signature ~path ~comp_unit signature = | Tsig_module {md_id = Some id; md_type; _} -> let path = id :: path in + export_module ~path md_type.mty_type; Utils.typedtree_signature_of_modtype md_type |> Option.iter (collect_signature path); mark_modtype_elements md_type @@ -182,6 +196,7 @@ let collect_export_from_structure ~path ~comp_unit structure = | Tmod_unpack _ -> () | Tmod_structure structure -> + export_module ~path m.mod_type; collect_structure ~path structure | Tmod_functor (_, m) | Tmod_apply (m, _, _) @@ -189,6 +204,7 @@ let collect_export_from_structure ~path ~comp_unit structure = | Tmod_constraint (m, _, Tmodtype_implicit, _) -> collect_module ~path m | Tmod_constraint (_, _, Tmodtype_explicit mt, _) -> + export_module ~path mt.mty_type; Utils.typedtree_signature_of_modtype mt |> Option.iter (collect_export_from_signature ~path ~comp_unit) @@ -239,21 +255,147 @@ let collect_export_from_structure ~path ~comp_unit structure = collect_structure ~path structure - -let rec collect_export_from_include ~path sig_item = +let collect_from_include incl_decl = + (* Get incl_decl's signature and export classes and objects in + DeadCommon.incl. + If the incl_decl is an ident, then store the equivalence between its + types and those of the current compilation unit. + *) + let rec get_mod_name_and_signature mod_expr = + match mod_expr.Typedtree.mod_desc with + | Tmod_ident (_, {txt; _}) -> + let mt = + match mod_expr.mod_type with + | Mty_alias _ -> + (* find the original signature in the env *) + begin try + let env = Envaux.env_of_only_summary mod_expr.mod_env in + Env.scrape_alias env mod_expr.mod_type + with Envaux.(Error (Module_not_found _)) -> mod_expr.mod_type + end + | _ -> mod_expr.mod_type + in + let signature = Utils.signature_of_modtype mt in + (Some txt, signature) + | Tmod_structure structure -> + (None, structure.str_type) + | Tmod_unpack (_, mod_type) -> + let signature = Utils.signature_of_modtype mod_type in + (None, signature) + | Tmod_functor (_, mod_expr) + | Tmod_apply (mod_expr, _, _) + | Tmod_apply_unit mod_expr + | Tmod_constraint (mod_expr, _, _, _) -> + get_mod_name_and_signature mod_expr + in + (* incl_id is used to identify and store type equivalences *) + let incl_id, signature = + get_mod_name_and_signature incl_decl.Typedtree.incl_mod + in + (* path to the module where include happens *) + let current_path = + let state = State.get_current () in + let module_id = State.File_infos.get_modname state.file_infos in + !DeadCommon.mods @ [module_id] + |> List.map Ident.create_persistent + in + (* comp_unit = DeadCommon._include enables exports from outside the current + compilation unit *) let comp_unit = DeadCommon._include in + (* exports from include are stored in their dedicated stock*) let stock = DeadCommon.incl in - match (sig_item : Types.signature_item) with - | Sig_value (id, ({val_loc; _} as value), _) - when not val_loc.Location.loc_ghost -> - export_object ~path ~comp_unit ~stock id value - | Sig_class (id, cd, _, _) -> - export_class ~path ~comp_unit ~stock id cd - | Sig_module (id, _, {Types.md_type; _}, _, _) -> - let path = id :: path in - Utils.signature_of_modtype md_type - |> List.iter (collect_export_from_include ~path) - | _ -> () + let rec collect_from_sig_item ~path sig_item = + (* [path] is the path within the included module *) + match (sig_item : Types.signature_item) with + | Sig_value (id, ({val_loc; _} as value), _) + when not val_loc.Location.loc_ghost -> + let path = path @ current_path in + export_object ~path ~comp_unit ~stock id value + | Sig_class (id, cd, _, _) -> + let path = path @ current_path in + export_class ~path ~comp_unit ~stock id cd + | Sig_module (id, _, {Types.md_type; _}, _, _) -> + let path = id :: path in + Utils.signature_of_modtype md_type + |> List.iter (collect_from_sig_item ~path) + | Sig_type (id, t, _, _) -> + Option.iter + (fun incl_id -> + let path = List.rev_map Ident.name (id :: path) in + DeadType.collect_equivalence_from_include ~incl_id ~path t) + incl_id + | _ -> () + in + List.iter (collect_from_sig_item ~path:[]) signature + + +let collect_equivalence_from_module_alias ~path module_binding = + match (module_binding : Typedtree.module_binding) with + | {mb_id = None; _} -> () + | {mb_id = Some _; mb_expr; _} -> + let rev_alias_path = path in + let rec collect_from_sig_item + ~is_internal ~original_path ?(sub_path=[]) sig_item + = + match (sig_item : Types.signature_item) with + + | Sig_module (id, _, {Types.md_type; _}, _, _) -> + let sub_path = Ident.name id :: sub_path in + Utils.signature_of_modtype md_type + |> List.iter + (collect_from_sig_item ~is_internal ~original_path ~sub_path) + + | Sig_type (id, t, _, _) -> + let sub_path = List.rev (Ident.name id :: sub_path) in + DeadType.collect_equivalence_from_module_alias + ~is_internal + ~rev_alias_path + ~original_path + ~sub_path + t + + | _ -> () + in + let rec collect_from_module_expr mod_expr = + match mod_expr.Typedtree.mod_desc with + | Tmod_ident (mod_path, _) -> + let env = + try + Some (Envaux.env_of_only_summary mod_expr.mod_env) + with + Envaux.(Error (Module_not_found _)) -> None + in + let internal_md = + Option.bind env + (fun env -> + try + Some (Env.find_module mod_path env) + with Not_found -> None + ) + in + let mt = + match Hashtbl.find_opt exported_modules rev_alias_path with + | Some _ as mt -> mt + | None -> Option.map (fun md -> md.Types.md_type) internal_md + in + Option.iter + (fun mt -> + let original_path = Path.name mod_path in + let is_internal = Option.is_some internal_md in + Utils.signature_of_modtype mt + |> List.iter + (collect_from_sig_item ~is_internal ~original_path) + ) + mt + | Tmod_constraint (mod_expr, _, _, _) + | Tmod_functor (_, mod_expr) + | Tmod_apply (mod_expr, _, _) + | Tmod_apply_unit mod_expr -> + collect_from_module_expr mod_expr + | Tmod_structure _ + | Tmod_unpack (_, _) -> () + in + collect_from_module_expr mb_expr let correct_export sig_item = diff --git a/src/deadSign.mli b/src/deadSign.mli index 5ba44d6f..b4efe9ab 100644 --- a/src/deadSign.mli +++ b/src/deadSign.mli @@ -1,6 +1,6 @@ val collect_export_from_signature : - path:Ident.t list -> - comp_unit:string -> + path: Ident.t list -> + comp_unit: string -> Typedtree.signature -> unit (** [collect_export_from_signature ~path ~comp_unit signature] @@ -12,8 +12,8 @@ val collect_export_from_signature : *) val collect_export_from_structure : - path:Ident.t list -> - comp_unit:string -> + path: Ident.t list -> + comp_unit: string -> Typedtree.structure -> unit (** [collect_export_from_structure ~path ~comp_unit structure] @@ -22,14 +22,23 @@ val collect_export_from_structure : See {!collect_export_from_signature} above for more information. *) -val collect_export_from_include : - path:Ident.t list -> - Types.signature_item +val collect_from_include : + Typedtree.include_declaration -> unit -(** [collect_export_from_include ~path sig_item] - recursively traverse the [sig_item] and store exported elements - (values, constructors, ...) in {!DeadCommon.incl}. - See {!collect_export_from_signature} above for more information. +(** [collect_from_include incl_decl] + store exported object, class elements and type equivalences found in + [incl_decl]. +*) + +val collect_equivalence_from_module_alias : + path: string list -> + Typedtree.module_binding + -> unit +(** [collect_export_from_module_alias ~path module_binding] + links exports in the [module_binding]'s expr to the new module if it is + an alias (M1 = M2). Aliases on functor applications are included. + [path] is the current module id's path (with the new id included) in + reverse order (i.e. the new id is at the head). *) val correct_export : Types.signature_item -> unit @@ -47,3 +56,6 @@ val modtype : for [mt] agree. I.e. if the first one is explicit when the second one is. If not, then the first one is implicit and [on_mismatch] is called on the second. *) + +val eof : unit -> unit +(** To use at the end of a [.cmt]'s analysis: reset internal state *) diff --git a/src/deadType.ml b/src/deadType.ml index 668324a0..c4a2b8d6 100644 --- a/src/deadType.ml +++ b/src/deadType.ml @@ -21,6 +21,8 @@ let decs = Hashtbl.create 256 let dependencies = ref [] (* like the cmt value_dependencies but for types *) +let equivalences = ref [] (* t1 = t2 *) + (******** HELPERS ********) @@ -77,6 +79,7 @@ let collect_export path u stock t = let save id loc = if t.type_manifest = None then + (* do not export t1 when there is an explicit equation t1 = t2 *) export path u stock id loc; let path = String.concat "." @@ List.rev_map (fun id -> Ident.name id) (id::path) in Hashtbl.replace fields path loc.Location.loc_start @@ -130,37 +133,172 @@ let rec check_style t loc = | _ -> () +let add_type_eq component_path eq_type_path component_name = + (* Store t1 = t2 equivalence, with t2 assumed to be defined outside the + current compilation unit *) + let eq_path = eq_type_path ^ "." ^ component_name in + equivalences := (component_path, eq_path) :: !equivalences + +(** Attempt to find a valid path by shortening [internal_path] until + only the head is left. + [internal_path] is built in reverse: that head is equivalent to the + external path (in the right order), the end is the current compilation + unit's name, and the whole path is initially the longest to the + point of equivalence. + Thus, when only the head is left, this function is equivalent to + adding an external type_eq.. +*) +let rec add_type_eq_internal ~internal_path ~component_path ~component_name = + match internal_path with + | [] -> assert false (* There must be at least one element *) + | external_type_path :: [] -> (* external alias *) + add_type_eq component_path external_type_path component_name + | external_type_path :: rev_internal_path -> + let eq_type_path = + List.rev internal_path |> String.concat "." + in + let eq_component_path = eq_type_path ^ "." ^ component_name in + match Hashtbl.find_opt fields eq_component_path with + | Some _ -> (* internal alias *) + add_type_eq component_path eq_type_path component_name + | None -> + let internal_path = + match rev_internal_path with + | [] | _::[] -> external_type_path :: [] + | _::rev_internal_path -> external_type_path ::rev_internal_path + in + add_type_eq_internal ~internal_path ~component_path ~component_name + +let collect_equivalence_from_module_alias + ~is_internal ~rev_alias_path ~original_path ~sub_path type_decl += + let type_path = + List.rev_append rev_alias_path sub_path + |> String.concat "." + in + let original_eq_type_path = + String.concat "." (original_path :: sub_path) + in + let add_type_eq_internal = + if is_internal then + let internal_path = original_eq_type_path :: List.tl rev_alias_path in + add_type_eq_internal ~internal_path + else + fun ~component_path ~component_name -> + add_type_eq component_path original_eq_type_path component_name + in + let add_type_eq loc component_id = + let component_name = Ident.name component_id in + let component_path = type_path ^ "." ^ component_name in + if not (Hashtbl.mem fields component_path) then + Hashtbl.add fields component_path loc.Location.loc_start; + add_type_eq_internal ~component_path ~component_name + in + match type_decl.type_kind with + | Type_record (l, _) -> + List.iter (fun {Types.ld_id; ld_loc; _} -> add_type_eq ld_loc ld_id) l + | Type_variant (l, _) -> + List.iter (fun {Types.cd_id; cd_loc; _} -> add_type_eq cd_loc cd_id) l + | _ -> () + + +let collect_equivalence_from_include ~incl_id ~path type_decl = + let state = State.get_current () in + let module_id = State.File_infos.get_modname state.file_infos in + (* internal path *) + let rev_curr_path = !DeadCommon.mods @ [module_id] in + let type_path = + List.rev_append rev_curr_path path + |> String.concat "." + in + let original_eq_type_path = + Longident.flatten incl_id @ path + |> String.concat "." + in + let add_type_eq component_id = + let component_name = Ident.name component_id in + (* internal path *) + let component_path = type_path ^ "." ^ component_name in + let internal_path = original_eq_type_path :: rev_curr_path in + add_type_eq_internal ~internal_path ~component_path ~component_name + in + match type_decl.type_kind with + | Type_record (l, _) -> + List.iter (fun {Types.ld_id; _} -> add_type_eq ld_id) l + | Type_variant (l, _) -> + List.iter (fun {Types.cd_id; _} -> add_type_eq cd_id) l + | _ -> () + let tstr typ = let state = State.get_current() in let modname = State.File_infos.get_modname state.file_infos in + + (* A type equation [type t1 = t2 = ...] produces a + [typ_manifest = Some (Ttyp_constr t2)] in t1 + In this situation, we want to remember the equality between t1 and t2's + components, for later resolution of equivalence classes and merging + all their references (see {!prepare_report} below). + *) + let eq_type_path = + match typ.typ_manifest with + | Some {ctyp_desc=Ttyp_constr (_, {txt; _}, _); _} -> + let path = String.concat "." (Longident.flatten txt) in + Some path + | _ -> None + in + + let handle_external_type_eq : string -> string -> unit = + match eq_type_path with + | None -> fun _ _ -> () + | Some eq_type_path -> + fun component_path component_name -> + add_type_eq component_path eq_type_path component_name + in + + let handle_internal_type_eq : string -> string -> unit = + (* Store t1 = t2 equivalence as a dependency, with t2 defined within the + current compilation unit *) + match eq_type_path with + | None -> fun _ _ -> () + | Some eq_type_path -> + fun component_path component_name -> + let eq_type_path = String.concat "." [modname; eq_type_path] in + let eq_component_path = + String.concat "." [eq_type_path; component_name] + in + match Hashtbl.find_opt fields eq_component_path with + | None -> () (* t2 is not defined locally *) + | Some _ -> + add_type_eq component_path eq_type_path component_name + in + + let handle_type_dep loc path_loc component_path component_name = + handle_internal_type_eq component_path component_name; + if path_loc <> loc then + (* store dependency between .ml and .mli *) + dependencies := (path_loc, loc) :: !dependencies + in + let assoc name loc = + (* store the association from name to loc in fields, + the dependenicies and the equivalences *) + let component_name = name.Asttypes.txt in let path = let partial_path_rev = - name.Asttypes.txt :: typ.typ_name.Asttypes.txt :: !mods + component_name :: typ.typ_name.Asttypes.txt :: !mods in modname :: List.rev partial_path_rev |> String.concat "." in + handle_external_type_eq path component_name; match Hashtbl.find_opt fields path with - | None -> Hashtbl.add fields path loc + | None -> + Hashtbl.add fields path loc; + handle_internal_type_eq path component_name | Some path_loc -> - (match typ.typ_manifest with - (* TODO : describe what this pattern is for *) - | Some {ctyp_desc=Ttyp_constr (_, {txt; _}, _); _} -> - let constr_typ_path = - modname :: Longident.flatten txt @ (name.Asttypes.txt :: []) - |> String.concat "." - in - (match Hashtbl.find_opt fields constr_typ_path with - | None -> () - | Some constr_loc -> - dependencies := (path_loc, constr_loc) :: (constr_loc, loc) :: !dependencies - ) - | _ -> () - ); - dependencies := (path_loc, loc) :: !dependencies + (* The path is known because the current compilation unit exports it *) + handle_type_dep loc path_loc path component_name in - let assoc name loc ctyp = assoc name loc; !DeadLexiFi.tstr_type typ ctyp @@ -180,6 +318,67 @@ let tstr typ = | _ -> () +let prepare_report () = + (* implement a pseudo union-find via 2 tables : references and reprs *) + (* references hold merged references of a union class with the + representative as key.*) + let references = LocHash.create 128 in + (* reprs points to another member of the location's equivalence class. + This memeber was the representative at some point. There are no + circular references. + _The_ representative of a class points to itself. + Use get_repr to get _the_ representative of a location's class. + *) + let reprs = Hashtbl.create 128 in + let init_refs loc = + (* the initial value for a single-element class is the set of references + gathered during the analysis *) + LocHash.find_set DeadCommon.references loc + |> LocHash.replace references loc + in + let rec get_repr loc = + (* explore members of loc's class until finding the class representative *) + match Hashtbl.find_opt reprs loc with + | None -> + (* loc does not belong to a class yet. Setup its own *) + init_refs loc; + Hashtbl.add reprs loc loc; + loc + | Some repr when repr = loc -> loc (* class representative found *) + | Some repr -> get_repr repr (* class member but not the representative *) + in + let merge_references (path1, path2) = + let loc1 = Hashtbl.find_opt fields path1 in + let loc2 = Hashtbl.find_opt fields path2 in + match loc1, loc2 with + | None, _ | _, None -> () + | Some loc1, Some loc2 -> + let repr1 = get_repr loc1 in + let repr2 = get_repr loc2 in + Hashtbl.replace reprs repr1 repr2; + (* repr1 is now represented by repr2: its references are transfered *) + LocHash.merge_set references repr2 references repr1; + LocHash.remove references repr1 + in + let update_references loc = + Option.iter + (fun loc -> + let repr = get_repr loc in + let refs = LocHash.find_set references repr in + (* refs include the references gathered for loc and all the members + of its equivalence class *) + LocHash.replace DeadCommon.references loc refs + ) + loc + in + let update_references (path1, path2) = + Hashtbl.find_opt fields path1 |> update_references; + Hashtbl.find_opt fields path2 |> update_references + in + List.iter merge_references !equivalences; + List.iter update_references !equivalences + + let report () = let state = State.get_current () in report_basic diff --git a/src/deadType.mli b/src/deadType.mli index a7280fe6..1bc133fe 100644 --- a/src/deadType.mli +++ b/src/deadType.mli @@ -17,6 +17,46 @@ val to_string : Types.type_expr -> string val check_style : Types.type_expr -> Lexing.position -> unit (** Look for bad style typing. (i.e. Argument expecting an optional argument) *) +val collect_equivalence_from_module_alias : + is_internal: bool -> + rev_alias_path: string list -> + original_path: string -> + sub_path: string list -> + Types.type_declaration + -> unit +(** [collect_equivalence_from_module_alias ~rev_alias_path ~original_path ~sub_path type_decl] + stores equivalences between components of the [type_decl] defined in + the current compilation unit at [sub_path] in the module defined at + [List.rev rev_alias_path], and the same components in the same type + at [sub_path] in the aliased module at [original_path]. + [rev_alias_path] must not be empty and is represented backward + (i.e. the type name is at the head). + If [is_internal = true] then there is an attempt to find the aliased + definition in the current compilation unit (working upward from the + alias path). If not found, then the behavior is the same as if + [is_internal = false]: the aliased type is conidered external. + + E.g. the .mli declares [module M : sig type t = (* type_decl *) end] + and the .ml [module M = N] and [N] also declares + [type t = (* type_decl *)] +*) + +val collect_equivalence_from_include : + incl_id: Longident.t -> + path: string list -> + Types.type_declaration + -> unit +(** [collect_equivalence_from_include ~incl_id ~path type_decl] + stores equivalences between components of the included [type_decl] + defined in [incl_id] at [path] and the same components in the same + type at [path_at_include @ path] in the current compilation unit if it is exported. + [path] must not be empty and is represented forward (i.e. the type name + is at the end). + + E.g. the .mli declares [type t = (* type_decl *)] and the .ml + [include M] and [M] also declares [type t = (* type_decl *)] +*) + val tstr : Typedtree.type_declaration -> unit val is_unit : Types.type_expr -> bool @@ -38,4 +78,9 @@ val correct_export : Types.type_declaration -> unit val collect_references : Lexing.position -> Lexing.position -> unit +val prepare_report: unit -> unit +(** To use at the end of the codebase analysis, before reporting. + This merges all the references of equivalent types +*) + val report: unit -> unit diff --git a/src/state/file_infos.ml b/src/state/file_infos.ml index 76e03867..06202e7b 100644 --- a/src/state/file_infos.ml +++ b/src/state/file_infos.ml @@ -28,6 +28,13 @@ let empty = { sourcepath = None; } +(** Necessary for Envaux.env_of_only_summary *) +let setup_env (paths : Load_path.paths) = + Load_path.reset(); + List.iter (Load_path.add_dir ~hidden:false) paths.visible; + List.iter (Load_path.add_dir ~hidden:true) paths.hidden; + Envaux.reset_cache () + (** [init_from_all_cm_infos ~cm_file cmt_infos] creates a [t] with: - information from [cmt_infos] : [builddir], [modname], [sourcepath]; - [cm_file]; @@ -51,6 +58,7 @@ let init_from_all_cm_infos ~cm_file cmt_infos = Cmt {strc; sign = None; location_dependencies} | _ -> Neither in + setup_env cmt_infos.cmt_loadpath; {builddir; cm_file; cm_infos; modname; sourcepath} (** [init_from_cm_file cm_file] returns an [Ok t] with [t] filled with general