From 4be07aec78fdc6f94a05dc101b39352b9067e492 Mon Sep 17 00:00:00 2001 From: Ameen Radwan Date: Sat, 24 Aug 2024 12:54:04 -0700 Subject: [PATCH 1/5] first pass at usage refactor lints tests fix private constructor case add test for 3552 --- compiler-core/src/analyse.rs | 72 +-- compiler-core/src/analyse/imports.rs | 35 +- ...re__erlang__tests__integration_test13.snap | 3 +- ...re__erlang__tests__integration_test16.snap | 3 +- ...ore__erlang__tests__integration_test2.snap | 3 +- ...re__erlang__tests__integration_test22.snap | 3 +- ...ore__erlang__tests__integration_test9.snap | 2 +- ..._tests__operator_pipe_right_hand_side.snap | 3 +- ...m_core__erlang__tests__recursive_type.snap | 5 +- ...lang__tests__consts__const_generalise.snap | 3 +- ...__pub_const_equal_to_private_function.snap | 3 +- ...rd_with_nested_private_function_field.snap | 7 +- ...to_record_with_private_function_field.snap | 5 +- ...ests__consts__use_private_in_internal.snap | 5 +- ...g__tests__consts__use_private_in_list.snap | 3 +- ...__tests__consts__use_private_in_tuple.snap | 3 +- ...to_record_with_private_function_field.snap | 5 +- ...d_pub_const_equal_to_private_function.snap | 3 +- ...to_record_with_private_function_field.snap | 5 +- ..._erlang__tests__custom_types__phantom.snap | 2 +- ...g__tests__pipes__block_expr_into_pipe.snap | 3 +- ...__tests__pipes__clever_pipe_rewriting.snap | 3 +- ..._tests__pipes__clever_pipe_rewriting1.snap | 3 +- ...e__erlang__tests__pipes__pipe_in_call.snap | 3 +- ...g__tests__pipes__pipe_in_case_subject.snap | 3 +- ...ore__erlang__tests__pipes__pipe_in_eq.snap | 3 +- ...e__erlang__tests__pipes__pipe_in_list.snap | 3 +- ..._erlang__tests__pipes__pipe_in_spread.snap | 3 +- ...__erlang__tests__pipes__pipe_in_tuple.snap | 3 +- ...__tests__records__pipe_update_subject.snap | 3 +- ...__erlang__tests__strings__pipe_concat.snap | 3 +- ...ms__custom_type_named_args_count_once.snap | 5 +- ...tom_type_nested_named_args_count_once.snap | 5 +- ...om_type_nested_result_type_count_once.snap | 2 +- ...om_type_tuple_type_params_count_twice.snap | 5 +- ...rams__result_type_inferred_count_once.snap | 2 +- ...am_core__erlang__tests__use___arity_1.snap | 3 +- ...am_core__erlang__tests__use___arity_2.snap | 3 +- ...am_core__erlang__tests__use___arity_3.snap | 3 +- ...ng__tests__variables__shadow_and_call.snap | 3 +- ...rlang__tests__variables__shadow_param.snap | 3 +- ...erlang__tests__variables__shadow_pipe.snap | 3 +- ...__externals__external_type_typescript.snap | 2 +- ...sts__generics__fn_generics_typescript.snap | 2 +- ..._generics__record_generics_typescript.snap | 14 +- ...t__tests__generics__result_typescript.snap | 6 +- ...ipt__tests__generics__task_typescript.snap | 2 +- ...__generics__tuple_generics_typescript.snap | 2 +- compiler-core/src/type_/environment.rs | 429 +++++++++--------- compiler-core/src/type_/expression.rs | 50 +- compiler-core/src/type_/hydrator.rs | 9 +- compiler-core/src/type_/pattern.rs | 23 +- ...ted_construct_same_name_in_type_alias.snap | 12 + ...s__unused_private_type_warnings_test6.snap | 8 + compiler-core/src/type_/tests/warnings.rs | 19 + ...rated_tests__alias_unqualified_import.snap | 3 +- ...iler__generated_tests__erlang_bug_752.snap | 4 +- ..._generated_tests__erlang_escape_names.snap | 7 +- 58 files changed, 377 insertions(+), 458 deletions(-) create mode 100644 compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__imported_construct_same_name_in_type_alias.snap diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index 74a5ce49c51..fbb8af3876b 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -286,7 +286,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { // server, but are filtered out when type checking to prevent using private // items. env.module_types - .retain(|_, info| info.module == self.module_name); + .retain(|_, (_, info)| info.module == self.module_name); // Ensure no exported values have private types in their type signature for value in env.module_values.values() { @@ -294,13 +294,22 @@ impl<'a, A> ModuleAnalyzer<'a, A> { } let Environment { - module_types: types, + module_types, module_types_constructors: types_constructors, module_values: values, accessors, .. } = env; + let types = module_types + .iter() + .map( + |(name, (_, type_)): (&EcoString, &(u64, TypeConstructor))| { + (name.clone(), type_.clone()) + }, + ) + .collect(); + let is_internal = self .package_config .is_internal_module(self.module_name.as_str()); @@ -413,15 +422,6 @@ impl<'a, A> ModuleAnalyzer<'a, A> { ); environment.insert_module_value(name.clone(), variant); - if publicity.is_private() { - environment.init_usage( - name.clone(), - EntityKind::PrivateConstant, - location, - &mut self.problems, - ); - } - Definition::ModuleConstant(ModuleConstant { documentation: doc, location, @@ -463,7 +463,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { let target = environment.target; let body_location = body.last().location(); let preregistered_fn = environment - .get_variable(&name) + .get_variable(&name, &location) .expect("Could not find preregistered type for function"); let field_map = preregistered_fn.field_map().cloned(); let preregistered_type = preregistered_fn.type_.clone(); @@ -833,7 +833,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { self.check_name_case(name_location, &name, Named::CustomTypeVariant); let preregistered_fn = environment - .get_variable(&name) + .get_variable(&name, &location) .expect("Could not find preregistered type for function"); let preregistered_type = preregistered_fn.type_.clone(); @@ -870,7 +870,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { ) .collect(); let typed_parameters = environment - .get_type_constructor(&None, &name) + .get_type_constructor(&None, &name, &location) .expect("Could not find preregistered type constructor ") .parameters .clone(); @@ -915,6 +915,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { .module_types .get(name) .expect("Type for custom type not found in register_values") + .1 .type_ .clone(); if let Some(accessors) = @@ -1017,15 +1018,6 @@ impl<'a, A> ModuleAnalyzer<'a, A> { }, ); - if value_constructor_publicity.is_private() { - environment.init_usage( - constructor.name.clone(), - EntityKind::PrivateTypeConstructor(name.clone()), - constructor.location, - &mut self.problems, - ); - } - constructors_data.push(TypeValueConstructor { name: constructor.name.clone(), parameters: fields, @@ -1131,14 +1123,6 @@ impl<'a, A> ModuleAnalyzer<'a, A> { }); } - if publicity.is_private() { - environment.init_usage( - name.clone(), - EntityKind::PrivateType, - *location, - &mut self.problems, - ); - }; Ok(()) } @@ -1198,16 +1182,6 @@ impl<'a, A> ModuleAnalyzer<'a, A> { }; let result = tryblock(); self.record_if_error(result); - - // Register the type for detection of dead code. - if publicity.is_private() { - environment.init_usage( - name.clone(), - EntityKind::PrivateType, - *location, - &mut self.problems, - ); - }; } fn make_type_vars( @@ -1312,14 +1286,6 @@ impl<'a, A> ModuleAnalyzer<'a, A> { *publicity, deprecation.clone(), ); - if publicity.is_private() { - environment.init_usage( - name.clone(), - EntityKind::PrivateFunction, - *location, - &mut self.problems, - ); - }; Ok(()) } @@ -1422,7 +1388,7 @@ fn analyse_type_alias(t: UntypedTypeAlias, environment: &mut Environment<'_>) -> // analysis aims to be fault tolerant to get the best possible feedback for // the programmer in the language server, so the analyser gets here even // though there was previously errors. - let type_ = match environment.get_type_constructor(&None, &alias) { + let type_ = match environment.get_type_constructor(&None, &alias, &location) { Ok(constructor) => constructor.type_.clone(), Err(_) => environment.new_generic_var(), }; @@ -1529,6 +1495,10 @@ fn generalise_module_constant( module: module_name.clone(), implementations, }; + // HACK: We insert the same constant twice. Once on definition and once on generalization + // This means that they appear as 2 separate variables for usage + // We do a get on the replaced constant to force a usage of it + let _ = environment.get_variable(&name, &location); environment.insert_variable( name.clone(), variant.clone(), @@ -1586,7 +1556,7 @@ fn generalise_function( // Lookup the inferred function information let function = environment - .get_variable(&name) + .get_variable(&name, &location) .expect("Could not find preregistered type for function"); let field_map = function.field_map().cloned(); let type_ = function.type_.clone(); diff --git a/compiler-core/src/analyse/imports.rs b/compiler-core/src/analyse/imports.rs index 9309450939b..c26b43d135e 100644 --- a/compiler-core/src/analyse/imports.rs +++ b/compiler-core/src/analyse/imports.rs @@ -4,8 +4,7 @@ use crate::{ ast::{SrcSpan, UnqualifiedImport, UntypedImport}, build::Origin, type_::{ - EntityKind, Environment, Error, ModuleInterface, Problems, UnusedModuleAlias, - ValueConstructorVariant, + Environment, Error, ModuleInterface, Problems, UnusedModuleAlias, ValueConstructorVariant, }, }; @@ -100,15 +99,7 @@ impl<'context, 'problems> Importer<'context, 'problems> { .insert_type_constructor(imported_name.clone(), type_info) { self.problems.error(e); - return; } - - self.environment.init_usage( - imported_name.clone(), - EntityKind::ImportedType, - import.location, - self.problems, - ); } fn register_unqualified_value(&mut self, import: &UnqualifiedImport, module: &ModuleInterface) { @@ -151,26 +142,12 @@ impl<'context, 'problems> Importer<'context, 'problems> { } }; - match variant { - ValueConstructorVariant::Record { name, module, .. } => { - self.environment.init_usage( - used_name.clone(), - EntityKind::ImportedConstructor, - location, - self.problems, - ); - self.environment.value_names.named_constructor_in_scope( - module.clone(), - name.clone(), - used_name.clone(), - ); - } - _ => self.environment.init_usage( + if let ValueConstructorVariant::Record { name, module, .. } = variant { + self.environment.value_names.named_constructor_in_scope( + module.clone(), + name.clone(), used_name.clone(), - EntityKind::ImportedValue, - location, - self.problems, - ), + ); }; // Check if value already was imported diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap index 792063daafe..3aad30111ca 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests.rs -assertion_line: 275 expression: "pub type State{ Start(Int) End(Int) }\n pub fn build(constructor : fn(Int) -> a) -> a { constructor(1) }\n pub fn main() { build(End) }" --- -module(my@mod). @@ -12,7 +11,7 @@ expression: "pub type State{ Start(Int) End(Int) }\n pub fn build(con -type state() :: {start, integer()} | {'end', integer()}. -file("/root/project/test/my/mod.gleam", 2). --spec build(fun((integer()) -> I)) -> I. +-spec build(fun((integer()) -> X)) -> X. build(Constructor) -> Constructor(1). diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap index 92e4d87def2..5dc610b12fe 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests.rs -assertion_line: 284 expression: "fn go(x xx, y yy) { xx }\npub fn x() { go(x: 1, y: 2) go(y: 3, x: 4) }" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "fn go(x xx, y yy) { xx }\npub fn x() { go(x: 1, y: 2) go(y: 3, x: 4 -export([x/0]). -file("/root/project/test/my/mod.gleam", 1). --spec go(I, any()) -> I. +-spec go(W, any()) -> W. go(Xx, Yy) -> Xx. diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap index 8b9efe5ed94..8be1699cfd1 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests.rs -assertion_line: 208 expression: "pub fn second(list) { case list { [x, y] -> y z -> 1 } }\npub fn tail(list) { case list { [x, ..xs] -> xs z -> list } }\n " --- -module(my@mod). @@ -20,7 +19,7 @@ second(List) -> end. -file("/root/project/test/my/mod.gleam", 2). --spec tail(list(P)) -> list(P). +-spec tail(list(AM)) -> list(AM). tail(List) -> case List of [X | Xs] -> diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap index 2bcfd32d1b1..5cde245056e 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests.rs -assertion_line: 343 expression: "\npub fn factory(f, i) {\n f(i)\n}\n\npub type Box {\n Box(i: Int)\n}\n\npub fn main() {\n factory(Box, 0)\n}\n" --- -module(my@mod). @@ -12,7 +11,7 @@ expression: "\npub fn factory(f, i) {\n f(i)\n}\n\npub type Box {\n Box(i: Int -type box() :: {box, integer()}. -file("/root/project/test/my/mod.gleam", 2). --spec factory(fun((J) -> N), J) -> N. +-spec factory(fun((Y) -> AH), Y) -> AH. factory(F, I) -> F(I). diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap index 95df7f37695..b7843732743 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap @@ -9,7 +9,7 @@ expression: "pub type Pair(x, y) { Pair(x: x, y: y) } pub fn x() { Pair(1, 2) Pa -export([x/0]). -export_type([pair/2]). --type pair(I, J) :: {pair, I, J}. +-type pair(W, X) :: {pair, W, X}. -file("/root/project/test/my/mod.gleam", 1). -spec x() -> pair(float(), float()). diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap index ed5a8cf3036..8e79ad4005c 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests.rs -assertion_line: 516 expression: "fn id(x) {\n x\n}\n\npub fn bool_expr(x, y) {\n y || x |> id\n}" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "fn id(x) {\n x\n}\n\npub fn bool_expr(x, y) {\n y || x |> id\n}" -export([bool_expr/2]). -file("/root/project/test/my/mod.gleam", 1). --spec id(I) -> I. +-spec id(W) -> W. id(X) -> X. diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap index 2c05ae54f2b..25e63b60118 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests.rs -assertion_line: 444 expression: "\nfn id(x) {\n x\n}\n\npub fn main() {\n id(id)\n}\n" --- -module(my@mod). @@ -9,11 +8,11 @@ expression: "\nfn id(x) {\n x\n}\n\npub fn main() {\n id(id)\n}\n" -export([main/0]). -file("/root/project/test/my/mod.gleam", 2). --spec id(I) -> I. +-spec id(W) -> W. id(X) -> X. -file("/root/project/test/my/mod.gleam", 6). --spec main() -> fun((M) -> M). +-spec main() -> fun((AF) -> AF). main() -> id(fun id/1). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap index cec62a33ed3..83ff908fc85 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 53 expression: "\nfn identity(a: a) -> a {\na\n}\n\nconst id = identity\n\npub fn main(){\n let num = id(1)\n let word = id(\"Word\")\n}" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\nfn identity(a: a) -> a {\na\n}\n\nconst id = identity\n\npub fn -export([main/0]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(I) -> I. +-spec identity(W) -> W. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap index 1381f705334..349682f202c 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 70 expression: "\n fn identity(a) {\n a\n }\n\n pub const id = identity\n " --- -module(my@mod). @@ -9,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(I) -> I. +-spec identity(W) -> W. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap index e69833d7b9e..da08e3201ae 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 100 expression: "\n fn identity(a) {\n a\n }\n\n pub type Mapper(b) {\n Mapper(fn(b) -> b)\n }\n\n pub type Funcs(b) {\n Funcs(mapper: Mapper(b))\n }\n\n pub const id_mapper = Funcs(Mapper(identity))\n " --- -module(my@mod). @@ -9,11 +8,11 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -export_type([mapper/1, funcs/1]). --type mapper(I) :: {mapper, fun((I) -> I)}. +-type mapper(W) :: {mapper, fun((W) -> W)}. --type funcs(J) :: {funcs, mapper(J)}. +-type funcs(Y) :: {funcs, mapper(Y)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(K) -> K. +-spec identity(AA) -> AA. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap index f8bbba83bd9..6ec871c06c2 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 83 expression: "\n fn identity(a) {\n a\n }\n\n pub type Mapper(b) {\n Mapper(fn(b) -> b)\n }\n\n pub const id_mapper = Mapper(identity)\n " --- -module(my@mod). @@ -9,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -export_type([mapper/1]). --type mapper(I) :: {mapper, fun((I) -> I)}. +-type mapper(W) :: {mapper, fun((W) -> W)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(J) -> J. +-spec identity(Y) -> Y. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap index 86c5917193c..661fe7882b3 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 168 expression: "\n fn identity(a) {\n a\n }\n\n pub type Mapper(b) {\n Mapper(fn(b) -> b)\n }\n\n @internal\n pub const id_mapper = Mapper(identity)\n " --- -module(my@mod). @@ -9,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -export_type([mapper/1]). --type mapper(I) :: {mapper, fun((I) -> I)}. +-type mapper(W) :: {mapper, fun((W) -> W)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(J) -> J. +-spec identity(Y) -> Y. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap index 2c3a9812bbd..2524755c454 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 186 expression: "\n fn identity(a) {\n a\n }\n\n pub const funcs = [identity]\n " --- -module(my@mod). @@ -9,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(I) -> I. +-spec identity(W) -> W. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap index 0baace7ac09..86eb27aa87e 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 199 expression: "\n fn identity(a) {\n a\n }\n\n pub const funcs = #(identity)\n " --- -module(my@mod). @@ -9,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(I) -> I. +-spec identity(W) -> W. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap index 6c323db2f8e..a4afb94c4e1 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 151 expression: "\n fn identity(a) {\n a\n }\n\n pub type Mapper(b) {\n Mapper(fn(b) -> b)\n }\n\n pub const id_mapper = Mapper(identity)\n " --- -module(my@mod). @@ -9,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -export_type([mapper/1]). --type mapper(I) :: {mapper, fun((I) -> I)}. +-type mapper(W) :: {mapper, fun((W) -> W)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(J) -> J. +-spec identity(Y) -> Y. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap index 6062f45d43a..4a4ce0db9ae 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 121 expression: "\n fn identity(a) {\n a\n }\n\n pub const id = identity\n " --- -module(my@mod). @@ -9,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(I) -> I. +-spec identity(W) -> W. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap index fe015935595..a4afb94c4e1 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/consts.rs -assertion_line: 134 expression: "\n fn identity(a) {\n a\n }\n\n pub type Mapper(b) {\n Mapper(fn(b) -> b)\n }\n\n pub const id_mapper = Mapper(identity)\n " --- -module(my@mod). @@ -9,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -export_type([mapper/1]). --type mapper(I) :: {mapper, fun((I) -> I)}. +-type mapper(W) :: {mapper, fun((W) -> W)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(J) -> J. +-spec identity(Y) -> Y. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap index 6ed77dfbfb0..0d49862a484 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap @@ -7,4 +7,4 @@ expression: "pub type Map(k, v)" -export_type([map_/2]). --type map_(I, J) :: any() | {gleam_phantom, I, J}. +-type map_(W, X) :: any() | {gleam_phantom, W, X}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap index b387507a3bb..02a855307da 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/pipes.rs -assertion_line: 26 expression: "fn id(a) { a }\npub fn main() {\n {\n let x = 1\n x\n }\n |> id\n}" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "fn id(a) { a }\npub fn main() {\n {\n let x = 1\n x\n }\n -export([main/0]). -file("/root/project/test/my/mod.gleam", 1). --spec id(I) -> I. +-spec id(W) -> W. id(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap index 43b5a666978..6f5b7a55f69 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/pipes.rs -assertion_line: 6 expression: "\npub fn apply(f: fn(a) -> b, a: a) { a |> f }\n" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\npub fn apply(f: fn(a) -> b, a: a) { a |> f }\n" -export([apply/2]). -file("/root/project/test/my/mod.gleam", 2). --spec apply(fun((I) -> J), I) -> J. +-spec apply(fun((W) -> X), W) -> X. apply(F, A) -> _pipe = A, F(_pipe). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap index f1ca2262fae..2f61e116676 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/pipes.rs -assertion_line: 16 expression: "\npub fn apply(f: fn(a, Int) -> b, a: a) { a |> f(1) }\n" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\npub fn apply(f: fn(a, Int) -> b, a: a) { a |> f(1) }\n" -export([apply/2]). -file("/root/project/test/my/mod.gleam", 2). --spec apply(fun((I, integer()) -> J), I) -> J. +-spec apply(fun((W, integer()) -> X), W) -> X. apply(F, A) -> _pipe = A, F(_pipe, 1). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap index 7ce7152065a..c0b0d0ed2d5 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/pipes.rs -assertion_line: 122 expression: "\npub fn main() {\n 123\n |> two(\n 1 |> two(2),\n _,\n )\n}\n\npub fn two(a, b) {\n a\n}\n" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\npub fn main() {\n 123\n |> two(\n 1 |> two(2),\n _,\n )\ -export([two/2, main/0]). -file("/root/project/test/my/mod.gleam", 10). --spec two(J, any()) -> J. +-spec two(Y, any()) -> Y. two(A, B) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap index d6cb2344b6a..44f5416ed40 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/pipes.rs -assertion_line: 62 expression: "pub fn x(f) {\n case 1 |> f {\n x -> x\n }\n}" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "pub fn x(f) {\n case 1 |> f {\n x -> x\n }\n}" -export([x/1]). -file("/root/project/test/my/mod.gleam", 1). --spec x(fun((integer()) -> L)) -> L. +-spec x(fun((integer()) -> AC)) -> AC. x(F) -> case begin _pipe = 1, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap index 664774ff2ff..d2b8436dee0 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/pipes.rs -assertion_line: 92 expression: "fn id(x) {\n x\n}\n \npub fn main() {\n 1 == 1 |> id\n}" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "fn id(x) {\n x\n}\n \npub fn main() {\n 1 == 1 |> id\n}" -export([main/0]). -file("/root/project/test/my/mod.gleam", 1). --spec id(I) -> I. +-spec id(W) -> W. id(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap index 4d29bd11eb6..bca27b1591f 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/pipes.rs -assertion_line: 40 expression: "pub fn x(f) {\n [\n 1 |> f\n ]\n}" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "pub fn x(f) {\n [\n 1 |> f\n ]\n}" -export([x/1]). -file("/root/project/test/my/mod.gleam", 1). --spec x(fun((integer()) -> L)) -> list(L). +-spec x(fun((integer()) -> AC)) -> list(AC). x(F) -> [begin _pipe = 1, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap index cb0d772af8f..f4d271a7f7e 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/pipes.rs -assertion_line: 74 expression: "pub type X {\n X(a: Int, b: Int)\n}\n\nfn id(x) {\n x\n}\n \npub fn main(x) {\n X(..x, a: 1 |> id)\n}" --- -module(my@mod). @@ -12,7 +11,7 @@ expression: "pub type X {\n X(a: Int, b: Int)\n}\n\nfn id(x) {\n x\n}\n -type x() :: {x, integer(), integer()}. -file("/root/project/test/my/mod.gleam", 5). --spec id(I) -> I. +-spec id(X) -> X. id(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap index 34f4e008386..888c72cf198 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/pipes.rs -assertion_line: 51 expression: "pub fn x(f) {\n #(\n 1 |> f\n )\n}" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "pub fn x(f) {\n #(\n 1 |> f\n )\n}" -export([x/1]). -file("/root/project/test/my/mod.gleam", 1). --spec x(fun((integer()) -> K)) -> {K}. +-spec x(fun((integer()) -> AB)) -> {AB}. x(F) -> {begin _pipe = 1, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap index 1534388e7e9..744c8d7eef4 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/records.rs -assertion_line: 324 expression: "pub type Thing {\n Thing(a: Int, b: Int)\n}\n\npub fn identity(x) { x }\n\npub fn main() {\n let thing = Thing(1, 2)\n Thing(..thing |> identity, b: 1000)\n}" --- -module(my@mod). @@ -12,7 +11,7 @@ expression: "pub type Thing {\n Thing(a: Int, b: Int)\n}\n\npub fn identity(x) -type thing() :: {thing, integer(), integer()}. -file("/root/project/test/my/mod.gleam", 5). --spec identity(I) -> I. +-spec identity(X) -> X. identity(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap index 26a7f19ed62..b190c7d1fc6 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/strings.rs -assertion_line: 406 expression: "\nfn id(x) {\n x\n}\n\npub fn main() {\n { \"\" |> id } <> { \"\" |> id }\n}\n" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\nfn id(x) {\n x\n}\n\npub fn main() {\n { \"\" |> id } <> { \"\" -export([main/0]). -file("/root/project/test/my/mod.gleam", 2). --spec id(I) -> I. +-spec id(W) -> W. id(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap index 88f7a317d18..9f71c3a6512 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/type_params.rs -assertion_line: 72 expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n }\n\n pub fn wibble() -> Wibble(a, a) {\n todo\n }\n " --- -module(my@mod). @@ -9,10 +8,10 @@ expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n -export([wibble/0]). -export_type([wibble/2]). --type wibble(I, J) :: {wibble, I, J}. +-type wibble(W, X) :: {wibble, W, X}. -file("/root/project/test/my/mod.gleam", 6). --spec wibble() -> wibble(K, K). +-spec wibble() -> wibble(Z, Z). wibble() -> erlang:error(#{gleam_error => todo, message => <<"`todo` expression evaluated. This code has not yet been implemented."/utf8>>, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap index 3d249be3ca1..0b725481566 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/type_params.rs -assertion_line: 87 expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n }\n\n pub fn wibble() -> Wibble(a, Wibble(a, b)) {\n todo\n }\n " --- -module(my@mod). @@ -9,10 +8,10 @@ expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n -export([wibble/0]). -export_type([wibble/2]). --type wibble(I, J) :: {wibble, I, J}. +-type wibble(W, X) :: {wibble, W, X}. -file("/root/project/test/my/mod.gleam", 6). --spec wibble() -> wibble(K, wibble(K, any())). +-spec wibble() -> wibble(Z, wibble(Z, any())). wibble() -> erlang:error(#{gleam_error => todo, message => <<"`todo` expression evaluated. This code has not yet been implemented."/utf8>>, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap index a879bc98abc..d4e34e65792 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap @@ -9,7 +9,7 @@ expression: "\n pub type Wibble(a) {\n Oops\n }\n\n -export([wibble/0]). -export_type([wibble/1]). --type wibble(I) :: oops | {gleam_phantom, I}. +-type wibble(W) :: oops | {gleam_phantom, W}. -file("/root/project/test/my/mod.gleam", 6). -spec wibble() -> {ok, any()} | {error, wibble(any())}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap index 308afdc67d3..8cf6a5e08e8 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/type_params.rs -assertion_line: 102 expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n }\n\n pub fn wibble() -> #(a, Wibble(a, b)) {\n todo\n }\n " --- -module(my@mod). @@ -9,10 +8,10 @@ expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n -export([wibble/0]). -export_type([wibble/2]). --type wibble(I, J) :: {wibble, I, J}. +-type wibble(W, X) :: {wibble, W, X}. -file("/root/project/test/my/mod.gleam", 6). --spec wibble() -> {K, wibble(K, any())}. +-spec wibble() -> {Z, wibble(Z, any())}. wibble() -> erlang:error(#{gleam_error => todo, message => <<"`todo` expression evaluated. This code has not yet been implemented."/utf8>>, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap index e4f932c71da..94580625664 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap @@ -8,7 +8,7 @@ expression: "\n fn wibble() {\n let assert Ok(_) = wobble()\n -export_type([wobble/1]). --type wobble(I) :: wobble | {gleam_phantom, I}. +-type wobble(W) :: wobble | {gleam_phantom, W}. -file("/root/project/test/my/mod.gleam", 10). -spec wobble() -> {ok, any()} | {error, wobble(any())}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap index 6ae209697d4..c260bd6999c 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/use_.rs -assertion_line: 5 expression: "\npub fn main() {\n use <- pair()\n 123\n}\n\nfn pair(f) {\n let x = f()\n #(x, x)\n}\n" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\npub fn main() {\n use <- pair()\n 123\n}\n\nfn pair(f) {\n let -export([main/0]). -file("/root/project/test/my/mod.gleam", 7). --spec pair(fun(() -> L)) -> {L, L}. +-spec pair(fun(() -> AC)) -> {AC, AC}. pair(F) -> X = F(), {X, X}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap index faea9ed0ded..4e89d540995 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/use_.rs -assertion_line: 22 expression: "\npub fn main() {\n use <- pair(1.0)\n 123\n}\n\nfn pair(x, f) {\n let y = f()\n #(x, y)\n}\n" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\npub fn main() {\n use <- pair(1.0)\n 123\n}\n\nfn pair(x, f) {\ -export([main/0]). -file("/root/project/test/my/mod.gleam", 7). --spec pair(J, fun(() -> M)) -> {J, M}. +-spec pair(Y, fun(() -> AE)) -> {Y, AE}. pair(X, F) -> Y = F(), {X, Y}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap index b1da7d3f694..b57f2ab3535 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/use_.rs -assertion_line: 39 expression: "\npub fn main() {\n use <- trip(1.0, \"\")\n 123\n}\n\nfn trip(x, y, f) {\n let z = f()\n #(x, y, z)\n}\n" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\npub fn main() {\n use <- trip(1.0, \"\")\n 123\n}\n\nfn trip(x, -export([main/0]). -file("/root/project/test/my/mod.gleam", 7). --spec trip(J, K, fun(() -> N)) -> {J, K, N}. +-spec trip(Y, Z, fun(() -> AG)) -> {Y, Z, AG}. trip(X, Y, F) -> Z = F(), {X, Y, Z}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap index e6fc5cc748b..6f11bbf537d 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/variables.rs -assertion_line: 34 expression: "\npub fn main(x) {\n fn(x) { x }(x)\n}\n" --- -module(my@mod). @@ -9,6 +8,6 @@ expression: "\npub fn main(x) {\n fn(x) { x }(x)\n}\n" -export([main/1]). -file("/root/project/test/my/mod.gleam", 2). --spec main(K) -> K. +-spec main(AA) -> AA. main(X) -> (fun(X@1) -> X@1 end)(X). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap index da428383fb0..749fc26b2d4 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/variables.rs -assertion_line: 23 expression: "pub fn main(board) {\nfn(board) { board }\n board\n}" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "pub fn main(board) {\nfn(board) { board }\n board\n}" -export([main/1]). -file("/root/project/test/my/mod.gleam", 1). --spec main(I) -> I. +-spec main(W) -> W. main(Board) -> fun(Board@1) -> Board@1 end, Board. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap index 811193b9dbb..a9cf2b910e2 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/variables.rs -assertion_line: 45 expression: "\npub fn main(x) {\n x\n |> fn(x) { x }\n}\n" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\npub fn main(x) {\n x\n |> fn(x) { x }\n}\n" -export([main/1]). -file("/root/project/test/my/mod.gleam", 2). --spec main(K) -> K. +-spec main(AB) -> AB. main(X) -> _pipe = X, (fun(X@1) -> X@1 end)(_pipe). diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap index 8acae99539d..6605ed09c5e 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap @@ -2,6 +2,6 @@ source: compiler-core/src/javascript/tests/externals.rs expression: "pub type Queue(a)\n\n@external(javascript, \"queue\", \"new\")\npub fn new() -> Queue(a)\n" --- -export type Queue$ = any; +export type Queue$ = any; export function new$(): Queue$; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap index da1ff1bffc7..c97b777f357 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap @@ -2,4 +2,4 @@ source: compiler-core/src/javascript/tests/generics.rs expression: "pub fn identity(a) -> a {\n a\n}\n" --- -export function identity(a: J): J; +export function identity(a: X): X; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap index 01f078bcdc7..87539e2a9c0 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap @@ -4,18 +4,18 @@ expression: "pub type Animal(t) {\n Cat(type_: t)\n Dog(type_: t)\n}\n\npub fn --- import type * as _ from "../gleam.d.mts"; -export class Cat extends _.CustomType { - constructor(type_: I); +export class Cat extends _.CustomType { + constructor(type_: W); - type_: I; + type_: W; } -export class Dog extends _.CustomType { - constructor(type_: I); +export class Dog extends _.CustomType { + constructor(type_: W); - type_: I; + type_: W; } -export type Animal$ = Cat | Dog; +export type Animal$ = Cat | Dog; export function main(): Animal$; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap index d2b3bdfa3d3..95ea2e9f317 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap @@ -4,7 +4,7 @@ expression: "pub fn map(result, fun) {\n case result {\n --- import type * as _ from "../gleam.d.mts"; -export function map(result: _.Result, fun: (x0: T) => V): _.Result< - V, - S +export function map(result: _.Result, fun: (x0: AL) => AO): _.Result< + AO, + AK >; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap index 05ad14e61da..eaca3b361cc 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap @@ -2,6 +2,6 @@ source: compiler-core/src/javascript/tests/generics.rs expression: "pub type Promise(value)\n pub type Task(a) = fn() -> Promise(a)" --- -export type Promise$ = any; +export type Promise$ = any; export type Task = () => Promise$; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap index 73ff2755f1e..d9ac156abeb 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap @@ -2,4 +2,4 @@ source: compiler-core/src/javascript/tests/generics.rs expression: "pub fn make_tuple(x: t) -> #(Int, t, Int) {\n #(0, x, 1)\n}\n" --- -export function make_tuple(x: I): [number, I, number]; +export function make_tuple(x: W): [number, W, number]; diff --git a/compiler-core/src/type_/environment.rs b/compiler-core/src/type_/environment.rs index eeb1393ca8e..1aa8806c843 100644 --- a/compiler-core/src/type_/environment.rs +++ b/compiler-core/src/type_/environment.rs @@ -1,3 +1,4 @@ +use ecow::eco_format; use pubgrub::range::Range; use crate::{ @@ -40,10 +41,12 @@ pub struct Environment<'a> { pub unused_module_aliases: HashMap, /// Values defined in the current function (or the prelude) - pub scope: im::HashMap, + pub scope: im::HashMap, + pub value_usage_graph: HashMap)>, /// Types defined in the current module (or the prelude) - pub module_types: HashMap, + pub module_types: HashMap, + pub type_usage_graph: HashMap)>, /// Mapping from types to constructor names in the current module (or the prelude) pub module_types_constructors: HashMap, @@ -54,12 +57,6 @@ pub struct Environment<'a> { /// Accessors defined in the current module pub accessors: HashMap, - /// entity_usages is a stack of scopes. When an entity is created it is - /// added to the top scope. When an entity is used we crawl down the scope - /// stack for an entity with that name and mark it as used. - /// NOTE: The bool in the tuple here tracks if the entity has been used - pub entity_usages: Vec>, - /// Used to determine if all functions/constants need to support the current /// compilation target. pub target_support: TargetSupport, @@ -94,9 +91,13 @@ impl<'a> Environment<'a> { current_package: current_package.clone(), gleam_version, previous_id: ids.next(), - ids, target, - module_types: prelude.types.clone(), + module_types: prelude + .types + .iter() + .map(|(name, type_)| (name.clone(), (ids.next(), type_.clone()))) + .collect(), + type_usage_graph: HashMap::new(), module_types_constructors: prelude.types_value_constructors.clone(), module_values: HashMap::new(), imported_modules: HashMap::new(), @@ -104,12 +105,17 @@ impl<'a> Environment<'a> { unqualified_imported_names: HashMap::new(), unqualified_imported_types: HashMap::new(), accessors: prelude.accessors.clone(), - scope: prelude.values.clone().into(), + scope: prelude + .values + .iter() + .map(|(name, value)| (name.clone(), (ids.next(), value.clone()))) + .collect(), + value_usage_graph: HashMap::new(), + ids, importable_modules, imported_module_aliases: HashMap::new(), unused_module_aliases: HashMap::new(), current_module, - entity_usages: vec![HashMap::new()], target_support, value_names, } @@ -122,26 +128,9 @@ pub struct UnusedModuleAlias { pub module_name: EcoString, } -/// For Keeping track of entity usages and knowing which error to display. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum EntityKind { - PrivateConstant, - // String here is the type constructor's type name - PrivateTypeConstructor(EcoString), - PrivateFunction, - ImportedConstructor, - ImportedType, - ImportedValue, - PrivateType, - Variable { - /// How the variable could be rewritten to ignore it when unused - how_to_ignore: Option, - }, -} - #[derive(Debug)] pub struct ScopeResetData { - local_values: im::HashMap, + local_values: im::HashMap, } impl<'a> Environment<'a> { @@ -156,7 +145,7 @@ impl<'a> Environment<'a> { // Process scope let result = process_scope(self, problems); - self.close_scope(initial, result.is_ok(), problems); + self.close_scope(initial); // Return result of typing the scope result @@ -164,28 +153,10 @@ impl<'a> Environment<'a> { pub fn open_new_scope(&mut self) -> ScopeResetData { let local_values = self.scope.clone(); - self.entity_usages.push(HashMap::new()); ScopeResetData { local_values } } - pub fn close_scope( - &mut self, - data: ScopeResetData, - was_successful: bool, - problems: &mut Problems, - ) { - let unused = self - .entity_usages - .pop() - .expect("There was no top entity scope."); - - // We only check for unused entities if the scope was successfully - // processed. If it was not then any seemingly unused entities may have - // been used beyond the point where the error occurred, so we don't want - // to incorrectly warn about them. - if was_successful { - self.handle_unused(unused, problems); - } + pub fn close_scope(&mut self, data: ScopeResetData) { self.scope = data.local_values; } @@ -215,34 +186,19 @@ impl<'a> Environment<'a> { /// Insert a variable in the current scope. /// pub fn insert_local_variable(&mut self, name: EcoString, location: SrcSpan, type_: Arc) { - let _ = self.scope.insert( - name, - ValueConstructor { - deprecation: Deprecation::NotDeprecated, - publicity: Publicity::Private, - variant: ValueConstructorVariant::LocalVariable { location }, - type_, - }, - ); - } - - /// Insert a constant in the current scope - pub fn insert_local_constant( - &mut self, - name: EcoString, - literal: Constant, EcoString>, - ) { - let _ = self.scope.insert( - name, - ValueConstructor { - deprecation: Deprecation::NotDeprecated, - publicity: Publicity::Private, - variant: ValueConstructorVariant::LocalConstant { - literal: literal.clone(), - }, - type_: literal.type_(), - }, - ); + let id = self.ids.next(); + let val = ValueConstructor { + deprecation: Deprecation::NotDeprecated, + publicity: Publicity::Private, + variant: ValueConstructorVariant::LocalVariable { location }, + type_, + }; + if name != PIPE_VARIABLE { + let _ = self + .value_usage_graph + .insert(id, (val.clone(), name.clone(), Vec::new())); + } + let _ = self.scope.insert(name, (id, val)); } /// Insert a variable in the current scope. @@ -255,15 +211,19 @@ impl<'a> Environment<'a> { publicity: Publicity, deprecation: Deprecation, ) { - let _ = self.scope.insert( - name, - ValueConstructor { - publicity, - deprecation, - variant, - type_, - }, - ); + let id = self.ids.next(); + let val = ValueConstructor { + deprecation, + publicity, + variant, + type_, + }; + if name != PIPE_VARIABLE { + let _ = self + .value_usage_graph + .insert(id, (val.clone(), name.clone(), Vec::new())); + } + let _ = self.scope.insert(name, (id, val)); } /// Insert (or overwrites) a value into the current module. @@ -274,19 +234,37 @@ impl<'a> Environment<'a> { /// Lookup a variable in the current scope. /// - pub fn get_variable(&self, name: &EcoString) -> Option<&ValueConstructor> { - self.scope.get(name) - } - - /// Lookup a module constant in the current scope. - /// - pub fn get_module_const(&mut self, name: &EcoString) -> Option<&ValueConstructor> { - self.increment_usage(name); - self.module_values - .get(name) - .filter(|ValueConstructor { variant, .. }| { - matches!(variant, ValueConstructorVariant::ModuleConstant { .. }) - }) + pub fn get_variable( + &mut self, + name: &EcoString, + location: &SrcSpan, + ) -> Option<&ValueConstructor> { + self.scope.get(name).map(|(id, v)| { + if let Some((_, _, usages)) = self.value_usage_graph.get_mut(id) { + match v.variant.clone() { + // Do not register usage of constructor during constructor instantiation + ValueConstructorVariant::Record { + location: record_location, + .. + } if *location == record_location => (), + _ => { + usages.push(*location); + // If a private constructor is used then its type is also used + if v.publicity.is_private() { + if let Some((_, type_name)) = v.type_.named_type_name() { + let _ = self.module_types.get(&type_name).map(|(id, _)| { + let _ = self + .type_usage_graph + .get_mut(id) + .map(|(_, _, usages)| usages.push(*location)); + }); + } + } + } + } + } + v + }) } /// Map a type in the current scope. @@ -300,10 +278,14 @@ impl<'a> Environment<'a> { ) -> Result<(), Error> { let name = type_name.clone(); let location = info.origin; - match self.module_types.insert(type_name, info) { + let id = self.ids.next(); + let _ = self + .type_usage_graph + .insert(id, (info.clone(), name.clone(), Vec::new())); + match self.module_types.insert(type_name, (id, info)) { None => Ok(()), - Some(prelude_type) if is_prelude_module(&prelude_type.module) => Ok(()), - Some(previous) => Err(Error::DuplicateTypeName { + Some((_, prelude_type)) if is_prelude_module(&prelude_type.module) => Ok(()), + Some((_, previous)) => Err(Error::DuplicateTypeName { name, location, previous_location: previous.origin, @@ -318,8 +300,8 @@ impl<'a> Environment<'a> { ) -> Result<(), Error> { match self.module_types.get(name) { None => Ok(()), - Some(prelude_type) if is_prelude_module(&prelude_type.module) => Ok(()), - Some(previous) => Err(Error::DuplicateTypeName { + Some((_, prelude_type)) if is_prelude_module(&prelude_type.module) => Ok(()), + Some((_, previous)) => Err(Error::DuplicateTypeName { name: name.clone(), location, previous_location: previous.origin, @@ -345,11 +327,20 @@ impl<'a> Environment<'a> { &mut self, module_alias: &Option<(EcoString, SrcSpan)>, name: &EcoString, + location: &SrcSpan, ) -> Result<&TypeConstructor, UnknownTypeConstructorError> { let t = match module_alias { None => self .module_types .get(name) + .map(|(id, t)| { + if let Some((_, _, usages)) = self.type_usage_graph.get_mut(id) { + if *location != t.origin { + usages.push(*location) + } + } + t + }) .ok_or_else(|| UnknownTypeConstructorError::Type { name: name.clone(), hint: self.unknown_type_hint(name), @@ -432,16 +423,38 @@ impl<'a> Environment<'a> { &mut self, module: Option<&EcoString>, name: &EcoString, + location: &SrcSpan, ) -> Result<&ValueConstructor, UnknownValueConstructorError> { match module { - None => self.scope.get(name).ok_or_else(|| { - let type_with_name_in_scope = self.module_types.keys().any(|type_| type_ == name); - UnknownValueConstructorError::Variable { - name: name.clone(), - variables: self.local_value_names(), - type_with_name_in_scope, - } - }), + None => self + .scope + .get(name) + .map(|(id, v)| { + if let Some((_, _, usages)) = self.value_usage_graph.get_mut(id) { + usages.push(*location); + // If a private constructor is used then its type is also used + if v.publicity.is_private() { + if let Some((_, type_name)) = v.type_.named_type_name() { + let _ = self.module_types.get(&type_name).map(|(id, _)| { + let _ = self + .type_usage_graph + .get_mut(id) + .map(|(_, _, usages)| usages.push(*location)); + }); + } + } + } + v + }) + .ok_or_else(|| { + let type_with_name_in_scope = + self.module_types.keys().any(|type_| type_ == name); + UnknownValueConstructorError::Variable { + name: name.clone(), + variables: self.local_value_names(), + type_with_name_in_scope, + } + }), Some(module_name) => { let (_, module) = self.imported_modules.get(module_name).ok_or_else(|| { @@ -543,70 +556,98 @@ impl<'a> Environment<'a> { } } - /// Inserts an entity at the current scope for usage tracking. - pub fn init_usage( - &mut self, - name: EcoString, - kind: EntityKind, - location: SrcSpan, - problems: &mut Problems, - ) { - use EntityKind::*; - - match self - .entity_usages - .last_mut() - .expect("Attempted to access non-existent entity usages scope") - .insert(name.clone(), (kind, location, false)) - { - // Private types can be shadowed by a constructor with the same name - // - // TODO: Improve this so that we can tell if an imported overridden - // type is actually used or not by tracking whether usages apply to - // the value or type scope - Some((ImportedType | PrivateType, _, _)) => {} - - Some((kind, location, false)) => { - // an entity was overwritten in the top most scope without being used - let mut unused = HashMap::with_capacity(1); - let _ = unused.insert(name, (kind, location, false)); - self.handle_unused(unused, problems); - } - - _ => {} - } - } - - /// Increments an entity's usage in the current or nearest enclosing scope - pub fn increment_usage(&mut self, name: &EcoString) { - let mut name = name.clone(); - - while let Some((kind, _, used)) = self - .entity_usages - .iter_mut() - .rev() - .find_map(|scope| scope.get_mut(&name)) - { - *used = true; - - match kind { - // If a type constructor is used, we consider its type also used - EntityKind::PrivateTypeConstructor(type_name) if *type_name != name => { - name = type_name.clone(); + /// Converts entities with a usage count of 0 to warnings. + /// Returns the list of unused imported module location for the removed unused lsp action. + pub fn convert_unused_to_warnings(&mut self, problems: &mut Problems) { + for (_, (type_constructor, name, usages)) in self.type_usage_graph.iter() { + if usages.is_empty() { + let imported = type_constructor.module != self.current_module; + if !imported && type_constructor.publicity != Publicity::Private { + continue; } - _ => break, + let warning = Warning::UnusedType { + location: type_constructor.origin, + imported, + name: name.clone(), + }; + problems.warning(warning); } } - } - /// Converts entities with a usage count of 0 to warnings. - /// Returns the list of unused imported module location for the removed unused lsp action. - pub fn convert_unused_to_warnings(&mut self, problems: &mut Problems) { - let unused = self - .entity_usages - .pop() - .expect("Expected a bottom level of entity usages."); - self.handle_unused(unused, problems); + for (_, (value_constructor, name, usages)) in self.value_usage_graph.iter() { + if usages.is_empty() { + let warning = match (&value_constructor.variant, &value_constructor.publicity) { + (ValueConstructorVariant::LocalVariable { location }, _) => { + Warning::UnusedVariable { + location: *location, + how_to_ignore: Some(eco_format!("_{name}")), + } + } + (ValueConstructorVariant::LocalConstant { literal }, Publicity::Private) => { + Warning::UnusedLiteral { + location: literal.location(), + } + } + ( + ValueConstructorVariant::Record { + name, + location, + module, + .. + }, + Publicity::Private, + ) => Warning::UnusedConstructor { + location: *location, + imported: *module != self.current_module, + name: name.clone(), + }, + ( + ValueConstructorVariant::ModuleFn { name, location, .. }, + Publicity::Private, + ) => Warning::UnusedPrivateFunction { + location: *location, + name: name.clone(), + }, + ( + ValueConstructorVariant::ModuleFn { + name, + module, + location, + implementations, + .. + }, + _, + ) if *module != self.current_module && implementations.gleam => { + let location = self + .unqualified_imported_names + .get(name) + .unwrap_or(location); + Warning::UnusedImportedValue { + location: *location, + name: name.clone(), + } + } + ( + ValueConstructorVariant::ModuleConstant { location, .. }, + Publicity::Private, + ) => Warning::UnusedPrivateModuleConstant { + location: *location, + name: name.clone(), + }, + ( + ValueConstructorVariant::ModuleConstant { + module, location, .. + }, + _, + ) if *module != self.current_module => Warning::UnusedImportedValue { + location: *location, + name: name.clone(), + }, + _ => continue, + }; + problems.warning(warning); + }; + } for (name, location) in self.unused_modules.clone().into_iter() { problems.warning(Warning::UnusedImportedModule { @@ -626,48 +667,6 @@ impl<'a> Environment<'a> { } } - fn handle_unused( - &mut self, - unused: HashMap, - problems: &mut Problems, - ) { - for (name, (kind, location, _)) in unused.into_iter().filter(|(_, (_, _, used))| !used) { - let warning = match kind { - EntityKind::ImportedType => Warning::UnusedType { - name, - imported: true, - location, - }, - EntityKind::ImportedConstructor => Warning::UnusedConstructor { - name, - imported: true, - location, - }, - EntityKind::PrivateConstant => { - Warning::UnusedPrivateModuleConstant { name, location } - } - EntityKind::PrivateTypeConstructor(_) => Warning::UnusedConstructor { - name, - imported: false, - location, - }, - EntityKind::PrivateFunction => Warning::UnusedPrivateFunction { name, location }, - EntityKind::PrivateType => Warning::UnusedType { - name, - imported: false, - location, - }, - EntityKind::ImportedValue => Warning::UnusedImportedValue { name, location }, - EntityKind::Variable { how_to_ignore } => Warning::UnusedVariable { - location, - how_to_ignore, - }, - }; - - problems.warning(warning); - } - } - pub fn local_value_names(&self) -> Vec { self.scope .keys() diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index cadda7b4956..8c484edb8ef 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -264,8 +264,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let result = process_scope(self); // Close scope, discarding any scope local state - self.environment - .close_scope(environment_reset_data, result.is_ok(), self.problems); + self.environment.close_scope(environment_reset_data); self.hydrator.close_scope(hydrator_reset_data); result } @@ -2319,7 +2318,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let value_constructor = self .environment - .get_value_constructor(module.as_ref().map(|(module, _)| module), &name) + .get_value_constructor(module.as_ref().map(|(module, _)| module), &name, &location) .map_err(|e| { convert_get_value_constructor_error( e, @@ -2433,18 +2432,11 @@ impl<'a, 'b> ExprTyper<'a, 'b> { ) -> Result { let constructor = match module { // Look in the current scope for a binding with this name - None => { - let constructor = self - .environment - .get_variable(name) - .cloned() - .ok_or_else(|| self.report_name_error(name, location))?; - - // Register the value as seen for detection of unused values - self.environment.increment_usage(name); - - constructor - } + None => self + .environment + .get_variable(name, location) + .cloned() + .ok_or_else(|| self.report_name_error(name, location))?, // Look in an imported module for a binding with this name Some((module_name, module_location)) => { @@ -2895,21 +2887,26 @@ impl<'a, 'b> ExprTyper<'a, 'b> { &mut self, constructor: &TypedExpr, ) -> Result, UnknownValueConstructorError> { - let (module, name) = match constructor { + let (module, name, location) = match constructor { TypedExpr::ModuleSelect { module_alias, label, + location, .. - } => (Some(EcoString::from(module_alias.as_str())), label), + } => ( + Some(EcoString::from(module_alias.as_str())), + label, + location, + ), - TypedExpr::Var { name, .. } => (None, name), + TypedExpr::Var { name, location, .. } => (None, name, location), _ => return Ok(None), }; Ok(self .environment - .get_value_constructor(module.as_ref(), name)? + .get_value_constructor(module.as_ref(), name, location)? .field_map()) } @@ -3308,21 +3305,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> { }); } - // Insert a variable for the argument into the environment - body_typer - .environment - .insert_local_variable(name.clone(), arg.location, t); - if !body.first().is_placeholder() { - // Register the variable in the usage tracker so that we - // can identify if it is unused - body_typer.environment.init_usage( + // Insert a variable for the argument into the environment + body_typer.environment.insert_local_variable( name.clone(), - EntityKind::Variable { - how_to_ignore: Some(format!("_{name}").into()), - }, arg.location, - body_typer.problems, + t, ); } } diff --git a/compiler-core/src/type_/hydrator.rs b/compiler-core/src/type_/hydrator.rs index f73f9b39861..05cfff68ba2 100644 --- a/compiler-core/src/type_/hydrator.rs +++ b/compiler-core/src/type_/hydrator.rs @@ -131,7 +131,7 @@ impl Hydrator { deprecation, .. } = environment - .get_type_constructor(module, name) + .get_type_constructor(module, name, location) .map_err(|e| { convert_get_type_constructor_error( e, @@ -152,13 +152,6 @@ impl Hydrator { } } - // Register the type constructor as being used if it is unqualified. - // We do not track use of qualified type constructors as they may be - // used in another module. - if module.is_none() { - environment.increment_usage(name); - } - // Ensure that the correct number of arguments have been given to the constructor if args.len() != parameters.len() { return Err(Error::IncorrectTypeArity { diff --git a/compiler-core/src/type_/pattern.rs b/compiler-core/src/type_/pattern.rs index 7d172fc9c15..4c595af6957 100644 --- a/compiler-core/src/type_/pattern.rs +++ b/compiler-core/src/type_/pattern.rs @@ -56,15 +56,6 @@ impl<'a, 'b> PatternTyper<'a, 'b> { match &mut self.mode { PatternMode::Initial => { - // Register usage for the unused variable detection - self.environment.init_usage( - name.into(), - EntityKind::Variable { - how_to_ignore: Some(format!("_{name}").into()), - }, - location, - self.problems, - ); // Ensure there are no duplicate variable names in the pattern if self.initial_pattern_vars.contains(name) { return Err(UnifyError::DuplicateVarInPattern { name: name.into() }); @@ -83,7 +74,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { PatternMode::Alternative(assigned) => { match self.environment.scope.get(name) { // This variable was defined in the Initial multi-pattern - Some(initial) if self.initial_pattern_vars.contains(name) => { + Some((_, initial)) if self.initial_pattern_vars.contains(name) => { assigned.push(name.into()); let initial_typ = initial.type_.clone(); unify(initial_typ, type_) @@ -264,7 +255,7 @@ impl<'a, 'b> PatternTyper<'a, 'b> { Pattern::VarUsage { name, location, .. } => { let vc = self .environment - .get_variable(&name) + .get_variable(&name, &location) .cloned() .ok_or_else(|| Error::UnknownVariable { location, @@ -276,7 +267,6 @@ impl<'a, 'b> PatternTyper<'a, 'b> { .keys() .any(|type_| type_ == &name), })?; - self.environment.increment_usage(&name); let type_ = self.environment .instantiate(vc.type_.clone(), &mut hashmap![], self.hydrator); @@ -462,12 +452,13 @@ impl<'a, 'b> PatternTyper<'a, 'b> { spread, .. } => { - // Register the value as seen for detection of unused values - self.environment.increment_usage(&name); - let cons = self .environment - .get_value_constructor(module.as_ref().map(|(module, _)| module), &name) + .get_value_constructor( + module.as_ref().map(|(module, _)| module), + &name, + &location, + ) .map_err(|e| { convert_get_value_constructor_error( e, diff --git a/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__imported_construct_same_name_in_type_alias.snap b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__imported_construct_same_name_in_type_alias.snap new file mode 100644 index 00000000000..42faa3f8b23 --- /dev/null +++ b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__imported_construct_same_name_in_type_alias.snap @@ -0,0 +1,12 @@ +--- +source: compiler-core/src/type_/tests/warnings.rs +expression: "\nimport wibble.{Wibble}\n\ntype Wibble =\n Int\n\npub fn main() {\n let _ = Wibble\n 1\n}\n\n" +--- +warning: Unused private type + ┌─ /src/warning/wrn.gleam:4:1 + │ +4 │ ╭ type Wibble = +5 │ │ Int + │ ╰─────^ This private type is never used + +Hint: You can safely remove it. diff --git a/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_private_type_warnings_test6.snap b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_private_type_warnings_test6.snap index 3002d1481c3..190217701ac 100644 --- a/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_private_type_warnings_test6.snap +++ b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_private_type_warnings_test6.snap @@ -2,6 +2,14 @@ source: compiler-core/src/type_/tests/warnings.rs expression: "type X { X }" --- +warning: Unused private type + ┌─ /src/warning/wrn.gleam:1:1 + │ +1 │ type X { X } + │ ^^^^^^ This private type is never used + +Hint: You can safely remove it. + warning: Unused private constructor ┌─ /src/warning/wrn.gleam:1:10 │ diff --git a/compiler-core/src/type_/tests/warnings.rs b/compiler-core/src/type_/tests/warnings.rs index 2a3172f6ae4..b09db330118 100644 --- a/compiler-core/src/type_/tests/warnings.rs +++ b/compiler-core/src/type_/tests/warnings.rs @@ -458,6 +458,25 @@ pub const make_two = one.Two ); } +#[test] +fn imported_construct_same_name_in_type_alias() { + assert_warning!( + ("thepackage", "wibble", "pub type Wibble { Wibble(String) }"), + " +import wibble.{Wibble} + +type Wibble = + Int + +pub fn main() { + let _ = Wibble + 1 +} + +" + ); +} + // https://github.com/gleam-lang/gleam/issues/2050 #[test] fn double_unary_integer_literal() { diff --git a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap index fdcb22afa7b..bf5a98302c4 100644 --- a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap +++ b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap @@ -1,6 +1,5 @@ --- source: test-package-compiler/src/generated_tests.rs -assertion_line: 8 expression: "./cases/alias_unqualified_import" --- //// /out/lib/the_package/_gleam_artefacts/one.cache @@ -19,7 +18,7 @@ expression: "./cases/alias_unqualified_import" -type empty() :: empty. -file("src/one.gleam", 2). --spec id(I) -> I. +-spec id(X) -> X. id(X) -> X. diff --git a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap index ceb2c58b67a..9d4671acd22 100644 --- a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap +++ b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap @@ -14,7 +14,7 @@ expression: "./cases/erlang_bug_752" -export_type([one/1]). --type one(I) :: {one, I}. +-type one(W) :: {one, W}. @@ -31,7 +31,7 @@ expression: "./cases/erlang_bug_752" -export_type([two/1]). --type two(K) :: {two, one:one(integer())} | {gleam_phantom, K}. +-type two(AP) :: {two, one:one(integer())} | {gleam_phantom, AP}. diff --git a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap index 8ec302b788d..14911675ed5 100644 --- a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap +++ b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap @@ -1,6 +1,5 @@ --- source: test-package-compiler/src/generated_tests.rs -assertion_line: 63 expression: "./cases/erlang_escape_names" --- //// /out/lib/the_package/_gleam_artefacts/one.cache @@ -16,7 +15,7 @@ expression: "./cases/erlang_escape_names" -export(['receive'/1]). -file("src/one.gleam", 2). --spec 'receive'(I) -> I. +-spec 'receive'(W) -> W. 'receive'(X) -> X. @@ -39,7 +38,7 @@ qualified_call() -> one:'receive'(1). -file("src/two.gleam", 8). --spec qualified_value() -> fun((Q) -> Q). +-spec qualified_value() -> fun((BD) -> BD). qualified_value() -> fun one:'receive'/1. @@ -49,7 +48,7 @@ unqualified_call() -> one:'receive'(1). -file("src/two.gleam", 16). --spec unqualified_value() -> fun((S) -> S). +-spec unqualified_value() -> fun((BJ) -> BJ). unqualified_value() -> fun one:'receive'/1. From e1578de2c8d88ca7ccbbdc7b5c4244a87fefc9db Mon Sep 17 00:00:00 2001 From: Ace Date: Sat, 14 Sep 2024 11:01:45 -0700 Subject: [PATCH 2/5] switch to stable graph --- compiler-core/src/analyse.rs | 37 ++- compiler-core/src/analyse/imports.rs | 2 + compiler-core/src/ast/tests.rs | 2 + ...re__erlang__tests__integration_test13.snap | 2 +- ...re__erlang__tests__integration_test16.snap | 2 +- ...ore__erlang__tests__integration_test2.snap | 2 +- ...re__erlang__tests__integration_test22.snap | 2 +- ...ore__erlang__tests__integration_test9.snap | 3 +- ..._tests__operator_pipe_right_hand_side.snap | 2 +- ...m_core__erlang__tests__recursive_type.snap | 4 +- ...lang__tests__consts__const_generalise.snap | 2 +- ...__pub_const_equal_to_private_function.snap | 2 +- ...rd_with_nested_private_function_field.snap | 6 +- ...to_record_with_private_function_field.snap | 4 +- ...ests__consts__use_private_in_internal.snap | 4 +- ...g__tests__consts__use_private_in_list.snap | 2 +- ...__tests__consts__use_private_in_tuple.snap | 2 +- ...to_record_with_private_function_field.snap | 4 +- ...d_pub_const_equal_to_private_function.snap | 2 +- ...to_record_with_private_function_field.snap | 4 +- ..._erlang__tests__custom_types__phantom.snap | 2 +- ...g__tests__pipes__block_expr_into_pipe.snap | 2 +- ...__tests__pipes__clever_pipe_rewriting.snap | 2 +- ..._tests__pipes__clever_pipe_rewriting1.snap | 2 +- ...e__erlang__tests__pipes__pipe_in_call.snap | 2 +- ...g__tests__pipes__pipe_in_case_subject.snap | 2 +- ...ore__erlang__tests__pipes__pipe_in_eq.snap | 2 +- ...e__erlang__tests__pipes__pipe_in_list.snap | 2 +- ..._erlang__tests__pipes__pipe_in_spread.snap | 2 +- ...__erlang__tests__pipes__pipe_in_tuple.snap | 2 +- ...__tests__records__pipe_update_subject.snap | 2 +- ...__erlang__tests__strings__pipe_concat.snap | 2 +- ...ms__custom_type_named_args_count_once.snap | 4 +- ...tom_type_nested_named_args_count_once.snap | 4 +- ...om_type_nested_result_type_count_once.snap | 3 +- ...om_type_tuple_type_params_count_twice.snap | 4 +- ...rams__result_type_inferred_count_once.snap | 3 +- ...am_core__erlang__tests__use___arity_1.snap | 2 +- ...am_core__erlang__tests__use___arity_2.snap | 2 +- ...am_core__erlang__tests__use___arity_3.snap | 2 +- ...ng__tests__variables__shadow_and_call.snap | 2 +- ...rlang__tests__variables__shadow_param.snap | 2 +- ...erlang__tests__variables__shadow_pipe.snap | 2 +- ...__externals__external_type_typescript.snap | 2 +- ...sts__generics__fn_generics_typescript.snap | 2 +- ..._generics__record_generics_typescript.snap | 14 +- ...t__tests__generics__result_typescript.snap | 6 +- ...ipt__tests__generics__task_typescript.snap | 2 +- ...__generics__tuple_generics_typescript.snap | 2 +- compiler-core/src/type_/environment.rs | 228 +++++++++--------- compiler-core/src/type_/expression.rs | 8 + compiler-core/src/type_/pattern.rs | 9 +- compiler-core/src/type_/pipe.rs | 1 + ...rated_tests__alias_unqualified_import.snap | 2 +- ...iler__generated_tests__erlang_bug_752.snap | 4 +- ..._generated_tests__erlang_escape_names.snap | 6 +- 56 files changed, 240 insertions(+), 190 deletions(-) diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index fbb8af3876b..e3963c7dd8f 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -378,6 +378,10 @@ impl<'a, A> ModuleAnalyzer<'a, A> { has_erlang_external: false, has_javascript_external: false, }; + + let variable_index = environment.register_variable(); + let old_referencing_source = environment.referencing_source_indices.clone(); + environment.referencing_source_indices = vec![variable_index]; let mut expr_typer = ExprTyper::new(environment, definition, &mut self.problems); let typed_expr = expr_typer.infer_const(&annotation, *value); let type_ = typed_expr.type_(); @@ -419,7 +423,9 @@ impl<'a, A> ModuleAnalyzer<'a, A> { type_.clone(), publicity, Deprecation::NotDeprecated, + Some(variable_index), ); + environment.referencing_source_indices = old_referencing_source; environment.insert_module_value(name.clone(), variant); Definition::ModuleConstant(ModuleConstant { @@ -508,6 +514,15 @@ impl<'a, A> ModuleAnalyzer<'a, A> { .map(|(a, t)| a.set_type(t.clone())) .collect_vec(); + let variable_index = environment + .scope + .get(&name) + .expect("function already registered") + .0 + .expect("function already registered"); + let old_referencing_source = environment.referencing_source_indices.clone(); + environment.referencing_source_indices = vec![variable_index]; + // Infer the type using the preregistered args + return types as a starting point let result = environment.in_new_scope(&mut self.problems, |environment, problems| { let mut expr_typer = ExprTyper::new(environment, definition, problems); @@ -624,7 +639,9 @@ impl<'a, A> ModuleAnalyzer<'a, A> { preregistered_type.clone(), publicity, deprecation.clone(), + Some(variable_index), ); + environment.referencing_source_indices = old_referencing_source; Definition::Function(Function { documentation: doc, @@ -1022,12 +1039,14 @@ impl<'a, A> ModuleAnalyzer<'a, A> { name: constructor.name.clone(), parameters: fields, }); + let variable_index = environment.register_variable(); environment.insert_variable( constructor.name.clone(), constructor_info, type_, value_constructor_publicity, deprecation.clone(), + Some(variable_index), ); environment.value_names.named_constructor_in_scope( @@ -1279,12 +1298,14 @@ impl<'a, A> ModuleAnalyzer<'a, A> { location: *location, implementations: *implementations, }; + let variable_index = environment.register_variable(); environment.insert_variable( name.clone(), variant, type_, *publicity, deprecation.clone(), + Some(variable_index), ); Ok(()) } @@ -1495,16 +1516,18 @@ fn generalise_module_constant( module: module_name.clone(), implementations, }; - // HACK: We insert the same constant twice. Once on definition and once on generalization - // This means that they appear as 2 separate variables for usage - // We do a get on the replaced constant to force a usage of it - let _ = environment.get_variable(&name, &location); + let variable_index = environment + .scope + .get(&name) + .expect("constant already exists") + .0; environment.insert_variable( name.clone(), variant.clone(), type_.clone(), publicity, deprecation.clone(), + variable_index, ); environment.insert_module_value( @@ -1579,12 +1602,18 @@ fn generalise_function( location, implementations, }; + let variable_index = environment + .scope + .get(&name) + .expect("function already exists") + .0; environment.insert_variable( name.clone(), variant.clone(), type_.clone(), publicity, deprecation.clone(), + variable_index, ); environment.insert_module_value( name.clone(), diff --git a/compiler-core/src/analyse/imports.rs b/compiler-core/src/analyse/imports.rs index c26b43d135e..45140b8b151 100644 --- a/compiler-core/src/analyse/imports.rs +++ b/compiler-core/src/analyse/imports.rs @@ -121,12 +121,14 @@ impl<'context, 'problems> Importer<'context, 'problems> { }) } + let variable_index = self.environment.register_variable(); self.environment.insert_variable( used_name.clone(), value.variant.clone(), value.type_.clone(), value.publicity, value.deprecation.clone(), + Some(variable_index), ); &value.variant } diff --git a/compiler-core/src/ast/tests.rs b/compiler-core/src/ast/tests.rs index 1e85b6bbd81..caa743614ed 100644 --- a/compiler-core/src/ast/tests.rs +++ b/compiler-core/src/ast/tests.rs @@ -105,12 +105,14 @@ fn compile_expression(src: &str) -> TypedStatement { module: "mymod".into(), constructor_index: 0, }; + let variable_index = environment.register_variable(); environment.insert_variable( "Cat".into(), variant, type_::fn_(vec![type_::string(), type_::int()], cat_type.clone()), Publicity::Public, Deprecation::NotDeprecated, + Some(variable_index), ); environment.insert_accessors( diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap index 3aad30111ca..cfa79701192 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap @@ -11,7 +11,7 @@ expression: "pub type State{ Start(Int) End(Int) }\n pub fn build(con -type state() :: {start, integer()} | {'end', integer()}. -file("/root/project/test/my/mod.gleam", 2). --spec build(fun((integer()) -> X)) -> X. +-spec build(fun((integer()) -> S)) -> S. build(Constructor) -> Constructor(1). diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap index 5dc610b12fe..fb5baf38707 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap @@ -8,7 +8,7 @@ expression: "fn go(x xx, y yy) { xx }\npub fn x() { go(x: 1, y: 2) go(y: 3, x: 4 -export([x/0]). -file("/root/project/test/my/mod.gleam", 1). --spec go(W, any()) -> W. +-spec go(R, any()) -> R. go(Xx, Yy) -> Xx. diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap index 8be1699cfd1..8069974f3ac 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap @@ -19,7 +19,7 @@ second(List) -> end. -file("/root/project/test/my/mod.gleam", 2). --spec tail(list(AM)) -> list(AM). +-spec tail(list(Y)) -> list(Y). tail(List) -> case List of [X | Xs] -> diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap index 5cde245056e..d97662c1f3b 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap @@ -11,7 +11,7 @@ expression: "\npub fn factory(f, i) {\n f(i)\n}\n\npub type Box {\n Box(i: Int -type box() :: {box, integer()}. -file("/root/project/test/my/mod.gleam", 2). --spec factory(fun((Y) -> AH), Y) -> AH. +-spec factory(fun((T) -> X), T) -> X. factory(F, I) -> F(I). diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap index b7843732743..d397a4930f7 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests.rs -assertion_line: 241 expression: "pub type Pair(x, y) { Pair(x: x, y: y) } pub fn x() { Pair(1, 2) Pair(3., 4.) }" --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "pub type Pair(x, y) { Pair(x: x, y: y) } pub fn x() { Pair(1, 2) Pa -export([x/0]). -export_type([pair/2]). --type pair(W, X) :: {pair, W, X}. +-type pair(R, S) :: {pair, R, S}. -file("/root/project/test/my/mod.gleam", 1). -spec x() -> pair(float(), float()). diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap index 8e79ad4005c..63055767c8a 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap @@ -8,7 +8,7 @@ expression: "fn id(x) {\n x\n}\n\npub fn bool_expr(x, y) {\n y || x |> id\n}" -export([bool_expr/2]). -file("/root/project/test/my/mod.gleam", 1). --spec id(W) -> W. +-spec id(R) -> R. id(X) -> X. diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap index 25e63b60118..f22dcd85423 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap @@ -8,11 +8,11 @@ expression: "\nfn id(x) {\n x\n}\n\npub fn main() {\n id(id)\n}\n" -export([main/0]). -file("/root/project/test/my/mod.gleam", 2). --spec id(W) -> W. +-spec id(R) -> R. id(X) -> X. -file("/root/project/test/my/mod.gleam", 6). --spec main() -> fun((AF) -> AF). +-spec main() -> fun((V) -> V). main() -> id(fun id/1). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap index 83ff908fc85..b583a9d8503 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap @@ -8,7 +8,7 @@ expression: "\nfn identity(a: a) -> a {\na\n}\n\nconst id = identity\n\npub fn -export([main/0]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(W) -> W. +-spec identity(R) -> R. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap index 349682f202c..e86e2db047d 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap @@ -8,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(W) -> W. +-spec identity(R) -> R. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap index da08e3201ae..ab704f51ce7 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap @@ -8,11 +8,11 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -export_type([mapper/1, funcs/1]). --type mapper(W) :: {mapper, fun((W) -> W)}. +-type mapper(R) :: {mapper, fun((R) -> R)}. --type funcs(Y) :: {funcs, mapper(Y)}. +-type funcs(T) :: {funcs, mapper(T)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(AA) -> AA. +-spec identity(V) -> V. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap index 6ec871c06c2..ec57b038492 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap @@ -8,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -export_type([mapper/1]). --type mapper(W) :: {mapper, fun((W) -> W)}. +-type mapper(R) :: {mapper, fun((R) -> R)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(Y) -> Y. +-spec identity(T) -> T. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap index 661fe7882b3..d49ad4979bc 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap @@ -8,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -export_type([mapper/1]). --type mapper(W) :: {mapper, fun((W) -> W)}. +-type mapper(R) :: {mapper, fun((R) -> R)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(Y) -> Y. +-spec identity(T) -> T. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap index 2524755c454..810cd6c0a2e 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap @@ -8,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(W) -> W. +-spec identity(R) -> R. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap index 86eb27aa87e..6189e7fd177 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap @@ -8,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(W) -> W. +-spec identity(R) -> R. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap index a4afb94c4e1..af31b64582e 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap @@ -8,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -export_type([mapper/1]). --type mapper(W) :: {mapper, fun((W) -> W)}. +-type mapper(R) :: {mapper, fun((R) -> R)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(Y) -> Y. +-spec identity(T) -> T. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap index 4a4ce0db9ae..8fb5f3b092d 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap @@ -8,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(W) -> W. +-spec identity(R) -> R. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap index a4afb94c4e1..af31b64582e 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap @@ -8,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -export_type([mapper/1]). --type mapper(W) :: {mapper, fun((W) -> W)}. +-type mapper(R) :: {mapper, fun((R) -> R)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(Y) -> Y. +-spec identity(T) -> T. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap index 0d49862a484..b96bce899e0 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap @@ -7,4 +7,4 @@ expression: "pub type Map(k, v)" -export_type([map_/2]). --type map_(W, X) :: any() | {gleam_phantom, W, X}. +-type map_(R, S) :: any() | {gleam_phantom, R, S}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap index 02a855307da..c54f6344628 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap @@ -8,7 +8,7 @@ expression: "fn id(a) { a }\npub fn main() {\n {\n let x = 1\n x\n }\n -export([main/0]). -file("/root/project/test/my/mod.gleam", 1). --spec id(W) -> W. +-spec id(R) -> R. id(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap index 6f5b7a55f69..b42bdd12616 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap @@ -8,7 +8,7 @@ expression: "\npub fn apply(f: fn(a) -> b, a: a) { a |> f }\n" -export([apply/2]). -file("/root/project/test/my/mod.gleam", 2). --spec apply(fun((W) -> X), W) -> X. +-spec apply(fun((R) -> S), R) -> S. apply(F, A) -> _pipe = A, F(_pipe). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap index 2f61e116676..fa8f1396ae2 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap @@ -8,7 +8,7 @@ expression: "\npub fn apply(f: fn(a, Int) -> b, a: a) { a |> f(1) }\n" -export([apply/2]). -file("/root/project/test/my/mod.gleam", 2). --spec apply(fun((W, integer()) -> X), W) -> X. +-spec apply(fun((R, integer()) -> S), R) -> S. apply(F, A) -> _pipe = A, F(_pipe, 1). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap index c0b0d0ed2d5..1f680e00d7f 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap @@ -8,7 +8,7 @@ expression: "\npub fn main() {\n 123\n |> two(\n 1 |> two(2),\n _,\n )\ -export([two/2, main/0]). -file("/root/project/test/my/mod.gleam", 10). --spec two(Y, any()) -> Y. +-spec two(S, any()) -> S. two(A, B) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap index 44f5416ed40..d6e54d45bbb 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap @@ -8,7 +8,7 @@ expression: "pub fn x(f) {\n case 1 |> f {\n x -> x\n }\n}" -export([x/1]). -file("/root/project/test/my/mod.gleam", 1). --spec x(fun((integer()) -> AC)) -> AC. +-spec x(fun((integer()) -> U)) -> U. x(F) -> case begin _pipe = 1, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap index d2b8436dee0..8a29c8a42c1 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap @@ -8,7 +8,7 @@ expression: "fn id(x) {\n x\n}\n \npub fn main() {\n 1 == 1 |> id\n}" -export([main/0]). -file("/root/project/test/my/mod.gleam", 1). --spec id(W) -> W. +-spec id(R) -> R. id(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap index bca27b1591f..290e5e71bac 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap @@ -8,7 +8,7 @@ expression: "pub fn x(f) {\n [\n 1 |> f\n ]\n}" -export([x/1]). -file("/root/project/test/my/mod.gleam", 1). --spec x(fun((integer()) -> AC)) -> list(AC). +-spec x(fun((integer()) -> U)) -> list(U). x(F) -> [begin _pipe = 1, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap index f4d271a7f7e..3730ba7d5ed 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap @@ -11,7 +11,7 @@ expression: "pub type X {\n X(a: Int, b: Int)\n}\n\nfn id(x) {\n x\n}\n -type x() :: {x, integer(), integer()}. -file("/root/project/test/my/mod.gleam", 5). --spec id(X) -> X. +-spec id(S) -> S. id(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap index 888c72cf198..f22275cd8ee 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap @@ -8,7 +8,7 @@ expression: "pub fn x(f) {\n #(\n 1 |> f\n )\n}" -export([x/1]). -file("/root/project/test/my/mod.gleam", 1). --spec x(fun((integer()) -> AB)) -> {AB}. +-spec x(fun((integer()) -> T)) -> {T}. x(F) -> {begin _pipe = 1, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap index 744c8d7eef4..3ed584895a3 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap @@ -11,7 +11,7 @@ expression: "pub type Thing {\n Thing(a: Int, b: Int)\n}\n\npub fn identity(x) -type thing() :: {thing, integer(), integer()}. -file("/root/project/test/my/mod.gleam", 5). --spec identity(X) -> X. +-spec identity(S) -> S. identity(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap index b190c7d1fc6..89fcf21ab73 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap @@ -8,7 +8,7 @@ expression: "\nfn id(x) {\n x\n}\n\npub fn main() {\n { \"\" |> id } <> { \"\" -export([main/0]). -file("/root/project/test/my/mod.gleam", 2). --spec id(W) -> W. +-spec id(R) -> R. id(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap index 9f71c3a6512..48b55eb6041 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap @@ -8,10 +8,10 @@ expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n -export([wibble/0]). -export_type([wibble/2]). --type wibble(W, X) :: {wibble, W, X}. +-type wibble(R, S) :: {wibble, R, S}. -file("/root/project/test/my/mod.gleam", 6). --spec wibble() -> wibble(Z, Z). +-spec wibble() -> wibble(U, U). wibble() -> erlang:error(#{gleam_error => todo, message => <<"`todo` expression evaluated. This code has not yet been implemented."/utf8>>, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap index 0b725481566..138ebdfb397 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap @@ -8,10 +8,10 @@ expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n -export([wibble/0]). -export_type([wibble/2]). --type wibble(W, X) :: {wibble, W, X}. +-type wibble(R, S) :: {wibble, R, S}. -file("/root/project/test/my/mod.gleam", 6). --spec wibble() -> wibble(Z, wibble(Z, any())). +-spec wibble() -> wibble(U, wibble(U, any())). wibble() -> erlang:error(#{gleam_error => todo, message => <<"`todo` expression evaluated. This code has not yet been implemented."/utf8>>, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap index d4e34e65792..1c311adcd09 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/type_params.rs -assertion_line: 46 expression: "\n pub type Wibble(a) {\n Oops\n }\n\n pub fn wibble() -> Result(a, Wibble(a)) {\n todo\n }\n " --- -module(my@mod). @@ -9,7 +8,7 @@ expression: "\n pub type Wibble(a) {\n Oops\n }\n\n -export([wibble/0]). -export_type([wibble/1]). --type wibble(W) :: oops | {gleam_phantom, W}. +-type wibble(R) :: oops | {gleam_phantom, R}. -file("/root/project/test/my/mod.gleam", 6). -spec wibble() -> {ok, any()} | {error, wibble(any())}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap index 8cf6a5e08e8..2e34eaf37cf 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap @@ -8,10 +8,10 @@ expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n -export([wibble/0]). -export_type([wibble/2]). --type wibble(W, X) :: {wibble, W, X}. +-type wibble(R, S) :: {wibble, R, S}. -file("/root/project/test/my/mod.gleam", 6). --spec wibble() -> {Z, wibble(Z, any())}. +-spec wibble() -> {U, wibble(U, any())}. wibble() -> erlang:error(#{gleam_error => todo, message => <<"`todo` expression evaluated. This code has not yet been implemented."/utf8>>, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap index 94580625664..6b289a1ecc4 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap @@ -1,6 +1,5 @@ --- source: compiler-core/src/erlang/tests/type_params.rs -assertion_line: 5 expression: "\n fn wibble() {\n let assert Ok(_) = wobble()\n }\n\n type Wobble(a) {\n Wobble\n }\n\n fn wobble() -> Result(a, Wobble(a)) {\n todo\n }\n " --- -module(my@mod). @@ -8,7 +7,7 @@ expression: "\n fn wibble() {\n let assert Ok(_) = wobble()\n -export_type([wobble/1]). --type wobble(W) :: wobble | {gleam_phantom, W}. +-type wobble(R) :: wobble | {gleam_phantom, R}. -file("/root/project/test/my/mod.gleam", 10). -spec wobble() -> {ok, any()} | {error, wobble(any())}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap index c260bd6999c..362a1758764 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap @@ -8,7 +8,7 @@ expression: "\npub fn main() {\n use <- pair()\n 123\n}\n\nfn pair(f) {\n let -export([main/0]). -file("/root/project/test/my/mod.gleam", 7). --spec pair(fun(() -> AC)) -> {AC, AC}. +-spec pair(fun(() -> U)) -> {U, U}. pair(F) -> X = F(), {X, X}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap index 4e89d540995..b3120bf6255 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap @@ -8,7 +8,7 @@ expression: "\npub fn main() {\n use <- pair(1.0)\n 123\n}\n\nfn pair(x, f) {\ -export([main/0]). -file("/root/project/test/my/mod.gleam", 7). --spec pair(Y, fun(() -> AE)) -> {Y, AE}. +-spec pair(S, fun(() -> V)) -> {S, V}. pair(X, F) -> Y = F(), {X, Y}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap index b57f2ab3535..58da6069b52 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap @@ -8,7 +8,7 @@ expression: "\npub fn main() {\n use <- trip(1.0, \"\")\n 123\n}\n\nfn trip(x, -export([main/0]). -file("/root/project/test/my/mod.gleam", 7). --spec trip(Y, Z, fun(() -> AG)) -> {Y, Z, AG}. +-spec trip(S, T, fun(() -> W)) -> {S, T, W}. trip(X, Y, F) -> Z = F(), {X, Y, Z}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap index 6f11bbf537d..ba1103e177b 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap @@ -8,6 +8,6 @@ expression: "\npub fn main(x) {\n fn(x) { x }(x)\n}\n" -export([main/1]). -file("/root/project/test/my/mod.gleam", 2). --spec main(AA) -> AA. +-spec main(T) -> T. main(X) -> (fun(X@1) -> X@1 end)(X). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap index 749fc26b2d4..8ce2bb2444c 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap @@ -8,7 +8,7 @@ expression: "pub fn main(board) {\nfn(board) { board }\n board\n}" -export([main/1]). -file("/root/project/test/my/mod.gleam", 1). --spec main(W) -> W. +-spec main(R) -> R. main(Board) -> fun(Board@1) -> Board@1 end, Board. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap index a9cf2b910e2..96944f6bf59 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap @@ -8,7 +8,7 @@ expression: "\npub fn main(x) {\n x\n |> fn(x) { x }\n}\n" -export([main/1]). -file("/root/project/test/my/mod.gleam", 2). --spec main(AB) -> AB. +-spec main(T) -> T. main(X) -> _pipe = X, (fun(X@1) -> X@1 end)(_pipe). diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap index 6605ed09c5e..d5bb7e645ad 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap @@ -2,6 +2,6 @@ source: compiler-core/src/javascript/tests/externals.rs expression: "pub type Queue(a)\n\n@external(javascript, \"queue\", \"new\")\npub fn new() -> Queue(a)\n" --- -export type Queue$ = any; +export type Queue$ = any; export function new$(): Queue$; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap index c97b777f357..51d5627c350 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap @@ -2,4 +2,4 @@ source: compiler-core/src/javascript/tests/generics.rs expression: "pub fn identity(a) -> a {\n a\n}\n" --- -export function identity(a: X): X; +export function identity(a: S): S; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap index 87539e2a9c0..9e5053ea3eb 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap @@ -4,18 +4,18 @@ expression: "pub type Animal(t) {\n Cat(type_: t)\n Dog(type_: t)\n}\n\npub fn --- import type * as _ from "../gleam.d.mts"; -export class Cat extends _.CustomType { - constructor(type_: W); +export class Cat extends _.CustomType { + constructor(type_: R); - type_: W; + type_: R; } -export class Dog extends _.CustomType { - constructor(type_: W); +export class Dog extends _.CustomType { + constructor(type_: R); - type_: W; + type_: R; } -export type Animal$ = Cat | Dog; +export type Animal$ = Cat | Dog; export function main(): Animal$; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap index 95ea2e9f317..44169938743 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap @@ -4,7 +4,7 @@ expression: "pub fn map(result, fun) {\n case result {\n --- import type * as _ from "../gleam.d.mts"; -export function map(result: _.Result, fun: (x0: AL) => AO): _.Result< - AO, - AK +export function map(result: _.Result, fun: (x0: AC) => AE): _.Result< + AE, + AB >; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap index eaca3b361cc..1a62448759d 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap @@ -2,6 +2,6 @@ source: compiler-core/src/javascript/tests/generics.rs expression: "pub type Promise(value)\n pub type Task(a) = fn() -> Promise(a)" --- -export type Promise$ = any; +export type Promise$ = any; export type Task = () => Promise$; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap index d9ac156abeb..9e3bdba0269 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap @@ -2,4 +2,4 @@ source: compiler-core/src/javascript/tests/generics.rs expression: "pub fn make_tuple(x: t) -> #(Int, t, Int) {\n #(0, x, 1)\n}\n" --- -export function make_tuple(x: W): [number, W, number]; +export function make_tuple(x: R): [number, R, number]; diff --git a/compiler-core/src/type_/environment.rs b/compiler-core/src/type_/environment.rs index 1aa8806c843..db0c98182c2 100644 --- a/compiler-core/src/type_/environment.rs +++ b/compiler-core/src/type_/environment.rs @@ -1,4 +1,5 @@ use ecow::eco_format; +use petgraph::{graph::NodeIndex, prelude::StableGraph, Directed}; use pubgrub::range::Range; use crate::{ @@ -41,8 +42,15 @@ pub struct Environment<'a> { pub unused_module_aliases: HashMap, /// Values defined in the current function (or the prelude) - pub scope: im::HashMap, - pub value_usage_graph: HashMap)>, + pub scope: im::HashMap>, ValueConstructor)>, + /// Call graph connecting value dependencies. + /// Nodes are the value constructor definitions. + /// They are options because we need placeholder values when creating a new variable. + /// Edges are the locations of the value usages. + /// Value constructors are stored for convenience of creating unused warnings. + /// When stored in cache should be transformed into just locations. + pub value_usage_graph: StableGraph, SrcSpan, Directed>, + pub referencing_source_indices: Vec>, /// Types defined in the current module (or the prelude) pub module_types: HashMap, @@ -108,9 +116,10 @@ impl<'a> Environment<'a> { scope: prelude .values .iter() - .map(|(name, value)| (name.clone(), (ids.next(), value.clone()))) + .map(|(name, value)| (name.clone(), (None, value.clone()))) .collect(), - value_usage_graph: HashMap::new(), + value_usage_graph: StableGraph::new(), + referencing_source_indices: Vec::new(), ids, importable_modules, imported_module_aliases: HashMap::new(), @@ -130,7 +139,7 @@ pub struct UnusedModuleAlias { #[derive(Debug)] pub struct ScopeResetData { - local_values: im::HashMap, + local_values: im::HashMap>, ValueConstructor)>, } impl<'a> Environment<'a> { @@ -185,20 +194,29 @@ impl<'a> Environment<'a> { /// Insert a variable in the current scope. /// - pub fn insert_local_variable(&mut self, name: EcoString, location: SrcSpan, type_: Arc) { - let id = self.ids.next(); - let val = ValueConstructor { - deprecation: Deprecation::NotDeprecated, - publicity: Publicity::Private, - variant: ValueConstructorVariant::LocalVariable { location }, + pub fn insert_local_variable( + &mut self, + name: EcoString, + location: SrcSpan, + type_: Arc, + node_index: Option, + ) { + self.insert_variable( + name, + ValueConstructorVariant::LocalVariable { location }, type_, - }; - if name != PIPE_VARIABLE { - let _ = self - .value_usage_graph - .insert(id, (val.clone(), name.clone(), Vec::new())); - } - let _ = self.scope.insert(name, (id, val)); + Publicity::Private, + Deprecation::NotDeprecated, + node_index, + ) + } + + /// Registers the existence of a variable to be put in scope. + /// Called as a prerequisite to insert_variable so that + /// the variable can be added to the usage graph while being created. + /// + pub fn register_variable(&mut self) -> NodeIndex { + self.value_usage_graph.add_node(None) } /// Insert a variable in the current scope. @@ -210,20 +228,22 @@ impl<'a> Environment<'a> { type_: Arc, publicity: Publicity, deprecation: Deprecation, + node_index: Option, ) { - let id = self.ids.next(); let val = ValueConstructor { deprecation, publicity, variant, type_, }; - if name != PIPE_VARIABLE { + + if let Some(ind) = node_index { let _ = self .value_usage_graph - .insert(id, (val.clone(), name.clone(), Vec::new())); - } - let _ = self.scope.insert(name, (id, val)); + .node_weight_mut(ind) + .and_then(|w| w.replace((name.clone(), val.clone()))); + }; + let _ = self.scope.insert(name, (node_index, val)); } /// Insert (or overwrites) a value into the current module. @@ -240,7 +260,7 @@ impl<'a> Environment<'a> { location: &SrcSpan, ) -> Option<&ValueConstructor> { self.scope.get(name).map(|(id, v)| { - if let Some((_, _, usages)) = self.value_usage_graph.get_mut(id) { + if let Some(node_index) = id { match v.variant.clone() { // Do not register usage of constructor during constructor instantiation ValueConstructorVariant::Record { @@ -248,7 +268,9 @@ impl<'a> Environment<'a> { .. } if *location == record_location => (), _ => { - usages.push(*location); + self.referencing_source_indices.iter_mut().for_each(|i| { + let _ = self.value_usage_graph.add_edge(*i, *node_index, *location); + }); // If a private constructor is used then its type is also used if v.publicity.is_private() { if let Some((_, type_name)) = v.type_.named_type_name() { @@ -426,35 +448,17 @@ impl<'a> Environment<'a> { location: &SrcSpan, ) -> Result<&ValueConstructor, UnknownValueConstructorError> { match module { - None => self - .scope - .get(name) - .map(|(id, v)| { - if let Some((_, _, usages)) = self.value_usage_graph.get_mut(id) { - usages.push(*location); - // If a private constructor is used then its type is also used - if v.publicity.is_private() { - if let Some((_, type_name)) = v.type_.named_type_name() { - let _ = self.module_types.get(&type_name).map(|(id, _)| { - let _ = self - .type_usage_graph - .get_mut(id) - .map(|(_, _, usages)| usages.push(*location)); - }); - } - } - } - v - }) - .ok_or_else(|| { - let type_with_name_in_scope = - self.module_types.keys().any(|type_| type_ == name); + None => { + let type_with_name_in_scope = self.module_types.keys().any(|type_| type_ == name); + let variables = self.local_value_names(); + self.get_variable(name, location).ok_or_else(|| { UnknownValueConstructorError::Variable { name: name.clone(), - variables: self.local_value_names(), + variables, type_with_name_in_scope, } - }), + }) + } Some(module_name) => { let (_, module) = self.imported_modules.get(module_name).ok_or_else(|| { @@ -574,79 +578,81 @@ impl<'a> Environment<'a> { } } - for (_, (value_constructor, name, usages)) in self.value_usage_graph.iter() { - if usages.is_empty() { - let warning = match (&value_constructor.variant, &value_constructor.publicity) { - (ValueConstructorVariant::LocalVariable { location }, _) => { - Warning::UnusedVariable { - location: *location, - how_to_ignore: Some(eco_format!("_{name}")), - } + let usage_graph_copy = self.value_usage_graph.clone(); + for node_index in usage_graph_copy.externals(petgraph::Direction::Incoming) { + let (name, value_constructor) = usage_graph_copy + .node_weight(node_index) + .expect("node must exist in graph") + .as_ref() + .expect("variable constructor must not be none"); + let warning = match (&value_constructor.variant, &value_constructor.publicity) { + (ValueConstructorVariant::LocalVariable { location }, _) => { + Warning::UnusedVariable { + location: *location, + how_to_ignore: Some(eco_format!("_{name}")), } - (ValueConstructorVariant::LocalConstant { literal }, Publicity::Private) => { - Warning::UnusedLiteral { - location: literal.location(), - } + } + (ValueConstructorVariant::LocalConstant { literal }, Publicity::Private) => { + Warning::UnusedLiteral { + location: literal.location(), } - ( - ValueConstructorVariant::Record { - name, - location, - module, - .. - }, - Publicity::Private, - ) => Warning::UnusedConstructor { - location: *location, - imported: *module != self.current_module, - name: name.clone(), + } + ( + ValueConstructorVariant::Record { + name, + location, + module, + .. }, - ( - ValueConstructorVariant::ModuleFn { name, location, .. }, - Publicity::Private, - ) => Warning::UnusedPrivateFunction { + Publicity::Private, + ) => Warning::UnusedConstructor { + location: *location, + imported: *module != self.current_module, + name: name.clone(), + }, + (ValueConstructorVariant::ModuleFn { name, location, .. }, Publicity::Private) => { + Warning::UnusedPrivateFunction { location: *location, name: name.clone(), - }, - ( - ValueConstructorVariant::ModuleFn { - name, - module, - location, - implementations, - .. - }, - _, - ) if *module != self.current_module && implementations.gleam => { - let location = self - .unqualified_imported_names - .get(name) - .unwrap_or(location); - Warning::UnusedImportedValue { - location: *location, - name: name.clone(), - } } - ( - ValueConstructorVariant::ModuleConstant { location, .. }, - Publicity::Private, - ) => Warning::UnusedPrivateModuleConstant { + } + ( + ValueConstructorVariant::ModuleFn { + name, + module, + location, + implementations, + .. + }, + _, + ) if *module != self.current_module && implementations.gleam => { + let location = self + .unqualified_imported_names + .get(name) + .unwrap_or(location); + Warning::UnusedImportedValue { location: *location, name: name.clone(), - }, - ( - ValueConstructorVariant::ModuleConstant { - module, location, .. - }, - _, - ) if *module != self.current_module => Warning::UnusedImportedValue { + } + } + (ValueConstructorVariant::ModuleConstant { location, .. }, Publicity::Private) => { + Warning::UnusedPrivateModuleConstant { location: *location, name: name.clone(), + } + } + ( + ValueConstructorVariant::ModuleConstant { + module, location, .. }, - _ => continue, - }; - problems.warning(warning); + _, + ) if *module != self.current_module => Warning::UnusedImportedValue { + location: *location, + name: name.clone(), + }, + _ => continue, }; + problems.warning(warning); } for (name, location) in self.unused_modules.clone().into_iter() { diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index 8c484edb8ef..6245c07ee76 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -1292,6 +1292,10 @@ impl<'a, 'b> ExprTyper<'a, 'b> { annotation, location, } = assignment; + let old_referencing_source = self.environment.referencing_source_indices.clone(); + // self.environment.referencing_source_indices = vec![]; + // TODO: actually register referencing source indices + let value_location = value.location(); let value = match self.in_new_scope(|value_typer| value_typer.infer(*value)) { Ok(value) => value, @@ -1318,6 +1322,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> { } }; + self.environment.referencing_source_indices = old_referencing_source; + // Check that any type annotation is accurate. if let Some(annotation) = &annotation { match self @@ -3307,10 +3313,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> { if !body.first().is_placeholder() { // Insert a variable for the argument into the environment + let variable_index = body_typer.environment.register_variable(); body_typer.environment.insert_local_variable( name.clone(), arg.location, t, + Some(variable_index), ); } } diff --git a/compiler-core/src/type_/pattern.rs b/compiler-core/src/type_/pattern.rs index 4c595af6957..60f59960f6b 100644 --- a/compiler-core/src/type_/pattern.rs +++ b/compiler-core/src/type_/pattern.rs @@ -66,8 +66,13 @@ impl<'a, 'b> PatternTyper<'a, 'b> { let _ = self.initial_pattern_vars.insert(name.into()); // And now insert the variable for use in the code that comes // after the pattern. - self.environment - .insert_local_variable(name.into(), location, type_); + let variable_index = self.environment.register_variable(); + self.environment.insert_local_variable( + name.into(), + location, + type_, + Some(variable_index), + ); Ok(()) } diff --git a/compiler-core/src/type_/pipe.rs b/compiler-core/src/type_/pipe.rs index 7f055e28974..81219315e8e 100644 --- a/compiler-core/src/type_/pipe.rs +++ b/compiler-core/src/type_/pipe.rs @@ -203,6 +203,7 @@ impl<'a, 'b, 'c> PipeTyper<'a, 'b, 'c> { PIPE_VARIABLE.into(), location, expression.type_(), + None, ); // Add the assignment to the AST let assignment = Assignment { diff --git a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap index bf5a98302c4..5c7eba10c02 100644 --- a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap +++ b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap @@ -18,7 +18,7 @@ expression: "./cases/alias_unqualified_import" -type empty() :: empty. -file("src/one.gleam", 2). --spec id(X) -> X. +-spec id(S) -> S. id(X) -> X. diff --git a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap index 9d4671acd22..867255897c5 100644 --- a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap +++ b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap @@ -14,7 +14,7 @@ expression: "./cases/erlang_bug_752" -export_type([one/1]). --type one(W) :: {one, W}. +-type one(R) :: {one, R}. @@ -31,7 +31,7 @@ expression: "./cases/erlang_bug_752" -export_type([two/1]). --type two(AP) :: {two, one:one(integer())} | {gleam_phantom, AP}. +-type two(AE) :: {two, one:one(integer())} | {gleam_phantom, AE}. diff --git a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap index 14911675ed5..c32d96a370b 100644 --- a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap +++ b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap @@ -15,7 +15,7 @@ expression: "./cases/erlang_escape_names" -export(['receive'/1]). -file("src/one.gleam", 2). --spec 'receive'(W) -> W. +-spec 'receive'(R) -> R. 'receive'(X) -> X. @@ -38,7 +38,7 @@ qualified_call() -> one:'receive'(1). -file("src/two.gleam", 8). --spec qualified_value() -> fun((BD) -> BD). +-spec qualified_value() -> fun((AI) -> AI). qualified_value() -> fun one:'receive'/1. @@ -48,7 +48,7 @@ unqualified_call() -> one:'receive'(1). -file("src/two.gleam", 16). --spec unqualified_value() -> fun((BJ) -> BJ). +-spec unqualified_value() -> fun((AK) -> AK). unqualified_value() -> fun one:'receive'/1. From b6dd237d12cbbfed38b9efde9a022282bc2e208f Mon Sep 17 00:00:00 2001 From: Ace Date: Sat, 14 Sep 2024 12:04:40 -0700 Subject: [PATCH 3/5] proof of concept for dependent unused values --- compiler-core/src/type_/environment.rs | 10 ++++-- compiler-core/src/type_/expression.rs | 5 ++- ...gs__unused_private_alias_warning_test.snap | 31 +++++++++++++++++++ ...gs__unused_public_alias_warning_test.snap} | 11 +------ compiler-core/src/type_/tests/warnings.rs | 15 ++++++++- 5 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_private_alias_warning_test.snap rename compiler-core/src/type_/tests/snapshots/{gleam_core__type___tests__warnings__unused_alias_warning_test.snap => gleam_core__type___tests__warnings__unused_public_alias_warning_test.snap} (61%) diff --git a/compiler-core/src/type_/environment.rs b/compiler-core/src/type_/environment.rs index db0c98182c2..497a1036bb8 100644 --- a/compiler-core/src/type_/environment.rs +++ b/compiler-core/src/type_/environment.rs @@ -578,8 +578,11 @@ impl<'a> Environment<'a> { } } - let usage_graph_copy = self.value_usage_graph.clone(); - for node_index in usage_graph_copy.externals(petgraph::Direction::Incoming) { + let mut usage_graph_copy = self.value_usage_graph.clone(); + let mut unused_vars = self + .value_usage_graph + .externals(petgraph::Direction::Incoming); + while let Some(node_index) = unused_vars.next() { let (name, value_constructor) = usage_graph_copy .node_weight(node_index) .expect("node must exist in graph") @@ -653,6 +656,9 @@ impl<'a> Environment<'a> { _ => continue, }; problems.warning(warning); + // Removing node here so that in cases where we need to continue we don't remove the node + let _ = usage_graph_copy.remove_node(node_index); + unused_vars = usage_graph_copy.externals(petgraph::Direction::Incoming); } for (name, location) in self.unused_modules.clone().into_iter() { diff --git a/compiler-core/src/type_/expression.rs b/compiler-core/src/type_/expression.rs index 6245c07ee76..e52e6e39fef 100644 --- a/compiler-core/src/type_/expression.rs +++ b/compiler-core/src/type_/expression.rs @@ -1294,7 +1294,10 @@ impl<'a, 'b> ExprTyper<'a, 'b> { } = assignment; let old_referencing_source = self.environment.referencing_source_indices.clone(); // self.environment.referencing_source_indices = vec![]; - // TODO: actually register referencing source indices + // TODO: currently local variables are "referenced" by the function they are in. Ideally + // they should be referenced from the assignment they are used for so we can properly follow + // unused reference chains. + // This requires moving pattern variable registration to be separate from unification. let value_location = value.location(); let value = match self.in_new_scope(|value_typer| value_typer.infer(*value)) { diff --git a/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_private_alias_warning_test.snap b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_private_alias_warning_test.snap new file mode 100644 index 00000000000..d310ebdf22c --- /dev/null +++ b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_private_alias_warning_test.snap @@ -0,0 +1,31 @@ +--- +source: compiler-core/src/type_/tests/warnings.rs +expression: "\n import gleam/wibble.{one} as wobble\n // Since the import is only used for unused private variables\n // It is also considered unused\n const one = one\n " +--- +warning: Unused imported value + ┌─ /src/warning/wrn.gleam:1:1 + │ +1 │ ╭ +2 │ │ import gleam/wibble.{one} as wobble + │ ╰────────────^ This imported value is never used + +Hint: You can safely remove it. + +warning: Unused imported module alias + ┌─ /src/warning/wrn.gleam:2:39 + │ +2 │ import gleam/wibble.{one} as wobble + │ ^^^^^^^^^ This alias is never used + +Hint: You can safely remove it. + + import gleam/wibble as _ + + +warning: Unused private constant + ┌─ /src/warning/wrn.gleam:5:13 + │ +5 │ const one = one + │ ^^^^^^^^^ This private constant is never used + +Hint: You can safely remove it. diff --git a/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_alias_warning_test.snap b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_public_alias_warning_test.snap similarity index 61% rename from compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_alias_warning_test.snap rename to compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_public_alias_warning_test.snap index 5bb6b73a58c..cb248904cd8 100644 --- a/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_alias_warning_test.snap +++ b/compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__unused_public_alias_warning_test.snap @@ -1,6 +1,6 @@ --- source: compiler-core/src/type_/tests/warnings.rs -expression: "\n import gleam/wibble.{one} as wobble\n const one = one\n " +expression: "\n import gleam/wibble.{one} as wobble\n pub const one = one\n " --- warning: Unused imported module alias ┌─ /src/warning/wrn.gleam:2:39 @@ -11,12 +11,3 @@ warning: Unused imported module alias Hint: You can safely remove it. import gleam/wibble as _ - - -warning: Unused private constant - ┌─ /src/warning/wrn.gleam:3:13 - │ -3 │ const one = one - │ ^^^^^^^^^ This private constant is never used - -Hint: You can safely remove it. diff --git a/compiler-core/src/type_/tests/warnings.rs b/compiler-core/src/type_/tests/warnings.rs index b09db330118..ed1b855a4b1 100644 --- a/compiler-core/src/type_/tests/warnings.rs +++ b/compiler-core/src/type_/tests/warnings.rs @@ -1002,16 +1002,29 @@ fn unused_module_wuth_alias_warning_test() { } #[test] -fn unused_alias_warning_test() { +fn unused_private_alias_warning_test() { assert_warnings_with_imports!( ("gleam/wibble", "pub const one = 1"); r#" import gleam/wibble.{one} as wobble + // Since the import is only used for unused private variables + // It is also considered unused const one = one "#, ); } +#[test] +fn unused_public_alias_warning_test() { + assert_warnings_with_imports!( + ("gleam/wibble", "pub const one = 1"); + r#" + import gleam/wibble.{one} as wobble + pub const one = one + "#, + ); +} + #[test] fn used_type_with_import_alias_no_warning_test() { assert_no_warnings!( From 5a224521dfe84cb4a9b3dd34ad7d976c982533b1 Mon Sep 17 00:00:00 2001 From: Ace Date: Sat, 14 Sep 2024 15:07:49 -0700 Subject: [PATCH 4/5] remove ids for types --- compiler-core/src/analyse.rs | 14 +------ ...re__erlang__tests__integration_test13.snap | 2 +- ...re__erlang__tests__integration_test16.snap | 2 +- ...ore__erlang__tests__integration_test2.snap | 2 +- ...re__erlang__tests__integration_test22.snap | 2 +- ...ore__erlang__tests__integration_test9.snap | 2 +- ..._tests__operator_pipe_right_hand_side.snap | 2 +- ...m_core__erlang__tests__recursive_type.snap | 4 +- ...lang__tests__consts__const_generalise.snap | 2 +- ...__pub_const_equal_to_private_function.snap | 2 +- ...rd_with_nested_private_function_field.snap | 6 +-- ...to_record_with_private_function_field.snap | 4 +- ...ests__consts__use_private_in_internal.snap | 4 +- ...g__tests__consts__use_private_in_list.snap | 2 +- ...__tests__consts__use_private_in_tuple.snap | 2 +- ...to_record_with_private_function_field.snap | 4 +- ...d_pub_const_equal_to_private_function.snap | 2 +- ...to_record_with_private_function_field.snap | 4 +- ..._erlang__tests__custom_types__phantom.snap | 2 +- ...g__tests__pipes__block_expr_into_pipe.snap | 2 +- ...__tests__pipes__clever_pipe_rewriting.snap | 2 +- ..._tests__pipes__clever_pipe_rewriting1.snap | 2 +- ...e__erlang__tests__pipes__pipe_in_call.snap | 2 +- ...g__tests__pipes__pipe_in_case_subject.snap | 2 +- ...ore__erlang__tests__pipes__pipe_in_eq.snap | 2 +- ...e__erlang__tests__pipes__pipe_in_list.snap | 2 +- ..._erlang__tests__pipes__pipe_in_spread.snap | 2 +- ...__erlang__tests__pipes__pipe_in_tuple.snap | 2 +- ...__tests__records__pipe_update_subject.snap | 2 +- ...__erlang__tests__strings__pipe_concat.snap | 2 +- ...ms__custom_type_named_args_count_once.snap | 4 +- ...tom_type_nested_named_args_count_once.snap | 4 +- ...om_type_nested_result_type_count_once.snap | 2 +- ...om_type_tuple_type_params_count_twice.snap | 4 +- ...rams__result_type_inferred_count_once.snap | 2 +- ...am_core__erlang__tests__use___arity_1.snap | 2 +- ...am_core__erlang__tests__use___arity_2.snap | 2 +- ...am_core__erlang__tests__use___arity_3.snap | 2 +- ...ng__tests__variables__shadow_and_call.snap | 2 +- ...rlang__tests__variables__shadow_param.snap | 2 +- ...erlang__tests__variables__shadow_pipe.snap | 2 +- ...__externals__external_type_typescript.snap | 2 +- ...sts__generics__fn_generics_typescript.snap | 2 +- ..._generics__record_generics_typescript.snap | 14 +++---- ...t__tests__generics__result_typescript.snap | 6 +-- ...ipt__tests__generics__task_typescript.snap | 2 +- ...__generics__tuple_generics_typescript.snap | 2 +- compiler-core/src/type_/environment.rs | 39 ++++++++----------- ...rated_tests__alias_unqualified_import.snap | 2 +- ...iler__generated_tests__erlang_bug_752.snap | 4 +- ..._generated_tests__erlang_escape_names.snap | 6 +-- 51 files changed, 88 insertions(+), 105 deletions(-) diff --git a/compiler-core/src/analyse.rs b/compiler-core/src/analyse.rs index e3963c7dd8f..70465b61fc2 100644 --- a/compiler-core/src/analyse.rs +++ b/compiler-core/src/analyse.rs @@ -286,7 +286,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> { // server, but are filtered out when type checking to prevent using private // items. env.module_types - .retain(|_, (_, info)| info.module == self.module_name); + .retain(|_, info| info.module == self.module_name); // Ensure no exported values have private types in their type signature for value in env.module_values.values() { @@ -294,22 +294,13 @@ impl<'a, A> ModuleAnalyzer<'a, A> { } let Environment { - module_types, + module_types: types, module_types_constructors: types_constructors, module_values: values, accessors, .. } = env; - let types = module_types - .iter() - .map( - |(name, (_, type_)): (&EcoString, &(u64, TypeConstructor))| { - (name.clone(), type_.clone()) - }, - ) - .collect(); - let is_internal = self .package_config .is_internal_module(self.module_name.as_str()); @@ -932,7 +923,6 @@ impl<'a, A> ModuleAnalyzer<'a, A> { .module_types .get(name) .expect("Type for custom type not found in register_values") - .1 .type_ .clone(); if let Some(accessors) = diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap index cfa79701192..dbc3391f1aa 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test13.snap @@ -11,7 +11,7 @@ expression: "pub type State{ Start(Int) End(Int) }\n pub fn build(con -type state() :: {start, integer()} | {'end', integer()}. -file("/root/project/test/my/mod.gleam", 2). --spec build(fun((integer()) -> S)) -> S. +-spec build(fun((integer()) -> I)) -> I. build(Constructor) -> Constructor(1). diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap index fb5baf38707..ecf79a01632 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test16.snap @@ -8,7 +8,7 @@ expression: "fn go(x xx, y yy) { xx }\npub fn x() { go(x: 1, y: 2) go(y: 3, x: 4 -export([x/0]). -file("/root/project/test/my/mod.gleam", 1). --spec go(R, any()) -> R. +-spec go(I, any()) -> I. go(Xx, Yy) -> Xx. diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap index 8069974f3ac..7545678af1c 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test2.snap @@ -19,7 +19,7 @@ second(List) -> end. -file("/root/project/test/my/mod.gleam", 2). --spec tail(list(Y)) -> list(Y). +-spec tail(list(P)) -> list(P). tail(List) -> case List of [X | Xs] -> diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap index d97662c1f3b..1d9004792f8 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test22.snap @@ -11,7 +11,7 @@ expression: "\npub fn factory(f, i) {\n f(i)\n}\n\npub type Box {\n Box(i: Int -type box() :: {box, integer()}. -file("/root/project/test/my/mod.gleam", 2). --spec factory(fun((T) -> X), T) -> X. +-spec factory(fun((J) -> N), J) -> N. factory(F, I) -> F(I). diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap index d397a4930f7..7b0fde52584 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__integration_test9.snap @@ -8,7 +8,7 @@ expression: "pub type Pair(x, y) { Pair(x: x, y: y) } pub fn x() { Pair(1, 2) Pa -export([x/0]). -export_type([pair/2]). --type pair(R, S) :: {pair, R, S}. +-type pair(I, J) :: {pair, I, J}. -file("/root/project/test/my/mod.gleam", 1). -spec x() -> pair(float(), float()). diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap index 63055767c8a..2f322d45ed1 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__operator_pipe_right_hand_side.snap @@ -8,7 +8,7 @@ expression: "fn id(x) {\n x\n}\n\npub fn bool_expr(x, y) {\n y || x |> id\n}" -export([bool_expr/2]). -file("/root/project/test/my/mod.gleam", 1). --spec id(R) -> R. +-spec id(I) -> I. id(X) -> X. diff --git a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap index f22dcd85423..b19e697c555 100644 --- a/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap +++ b/compiler-core/src/erlang/snapshots/gleam_core__erlang__tests__recursive_type.snap @@ -8,11 +8,11 @@ expression: "\nfn id(x) {\n x\n}\n\npub fn main() {\n id(id)\n}\n" -export([main/0]). -file("/root/project/test/my/mod.gleam", 2). --spec id(R) -> R. +-spec id(I) -> I. id(X) -> X. -file("/root/project/test/my/mod.gleam", 6). --spec main() -> fun((V) -> V). +-spec main() -> fun((M) -> M). main() -> id(fun id/1). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap index b583a9d8503..70d040cb560 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__const_generalise.snap @@ -8,7 +8,7 @@ expression: "\nfn identity(a: a) -> a {\na\n}\n\nconst id = identity\n\npub fn -export([main/0]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(R) -> R. +-spec identity(I) -> I. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap index e86e2db047d..f36f606087f 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_private_function.snap @@ -8,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(R) -> R. +-spec identity(I) -> I. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap index ab704f51ce7..63b4c38bab3 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_nested_private_function_field.snap @@ -8,11 +8,11 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -export_type([mapper/1, funcs/1]). --type mapper(R) :: {mapper, fun((R) -> R)}. +-type mapper(I) :: {mapper, fun((I) -> I)}. --type funcs(T) :: {funcs, mapper(T)}. +-type funcs(J) :: {funcs, mapper(J)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(V) -> V. +-spec identity(K) -> K. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap index ec57b038492..c2fe2c6e476 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__pub_const_equal_to_record_with_private_function_field.snap @@ -8,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -export_type([mapper/1]). --type mapper(R) :: {mapper, fun((R) -> R)}. +-type mapper(I) :: {mapper, fun((I) -> I)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(T) -> T. +-spec identity(J) -> J. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap index d49ad4979bc..e37e2bc77e8 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_internal.snap @@ -8,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -export_type([mapper/1]). --type mapper(R) :: {mapper, fun((R) -> R)}. +-type mapper(I) :: {mapper, fun((I) -> I)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(T) -> T. +-spec identity(J) -> J. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap index 810cd6c0a2e..5ff48bdd918 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_list.snap @@ -8,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(R) -> R. +-spec identity(I) -> I. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap index 6189e7fd177..47864c93ec7 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_private_in_tuple.snap @@ -8,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n }\n\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(R) -> R. +-spec identity(I) -> I. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap index af31b64582e..882c6c3d23b 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_qualified_pub_const_equal_to_record_with_private_function_field.snap @@ -8,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -export_type([mapper/1]). --type mapper(R) :: {mapper, fun((R) -> R)}. +-type mapper(I) :: {mapper, fun((I) -> I)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(T) -> T. +-spec identity(J) -> J. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap index 8fb5f3b092d..de21c87e652 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_private_function.snap @@ -8,6 +8,6 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -file("/root/project/test/my/mod.gleam", 2). --spec identity(R) -> R. +-spec identity(I) -> I. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap index af31b64582e..882c6c3d23b 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__consts__use_unqualified_pub_const_equal_to_record_with_private_function_field.snap @@ -8,9 +8,9 @@ expression: "\n fn identity(a) {\n a\n -export([identity/1]). -export_type([mapper/1]). --type mapper(R) :: {mapper, fun((R) -> R)}. +-type mapper(I) :: {mapper, fun((I) -> I)}. -file("/root/project/test/my/mod.gleam", 2). --spec identity(T) -> T. +-spec identity(J) -> J. identity(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap index b96bce899e0..6ed77dfbfb0 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__phantom.snap @@ -7,4 +7,4 @@ expression: "pub type Map(k, v)" -export_type([map_/2]). --type map_(R, S) :: any() | {gleam_phantom, R, S}. +-type map_(I, J) :: any() | {gleam_phantom, I, J}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap index c54f6344628..343e552b7a1 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__block_expr_into_pipe.snap @@ -8,7 +8,7 @@ expression: "fn id(a) { a }\npub fn main() {\n {\n let x = 1\n x\n }\n -export([main/0]). -file("/root/project/test/my/mod.gleam", 1). --spec id(R) -> R. +-spec id(I) -> I. id(A) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap index b42bdd12616..d3ebe0a2c71 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting.snap @@ -8,7 +8,7 @@ expression: "\npub fn apply(f: fn(a) -> b, a: a) { a |> f }\n" -export([apply/2]). -file("/root/project/test/my/mod.gleam", 2). --spec apply(fun((R) -> S), R) -> S. +-spec apply(fun((I) -> J), I) -> J. apply(F, A) -> _pipe = A, F(_pipe). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap index fa8f1396ae2..3db4415b26e 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__clever_pipe_rewriting1.snap @@ -8,7 +8,7 @@ expression: "\npub fn apply(f: fn(a, Int) -> b, a: a) { a |> f(1) }\n" -export([apply/2]). -file("/root/project/test/my/mod.gleam", 2). --spec apply(fun((R, integer()) -> S), R) -> S. +-spec apply(fun((I, integer()) -> J), I) -> J. apply(F, A) -> _pipe = A, F(_pipe, 1). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap index 1f680e00d7f..0add3773bb4 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_call.snap @@ -8,7 +8,7 @@ expression: "\npub fn main() {\n 123\n |> two(\n 1 |> two(2),\n _,\n )\ -export([two/2, main/0]). -file("/root/project/test/my/mod.gleam", 10). --spec two(S, any()) -> S. +-spec two(J, any()) -> J. two(A, B) -> A. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap index d6e54d45bbb..a20d150d435 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_case_subject.snap @@ -8,7 +8,7 @@ expression: "pub fn x(f) {\n case 1 |> f {\n x -> x\n }\n}" -export([x/1]). -file("/root/project/test/my/mod.gleam", 1). --spec x(fun((integer()) -> U)) -> U. +-spec x(fun((integer()) -> L)) -> L. x(F) -> case begin _pipe = 1, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap index 8a29c8a42c1..76bd33c4107 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_eq.snap @@ -8,7 +8,7 @@ expression: "fn id(x) {\n x\n}\n \npub fn main() {\n 1 == 1 |> id\n}" -export([main/0]). -file("/root/project/test/my/mod.gleam", 1). --spec id(R) -> R. +-spec id(I) -> I. id(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap index 290e5e71bac..e23f09367ae 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_list.snap @@ -8,7 +8,7 @@ expression: "pub fn x(f) {\n [\n 1 |> f\n ]\n}" -export([x/1]). -file("/root/project/test/my/mod.gleam", 1). --spec x(fun((integer()) -> U)) -> list(U). +-spec x(fun((integer()) -> L)) -> list(L). x(F) -> [begin _pipe = 1, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap index 3730ba7d5ed..9798886178d 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_spread.snap @@ -11,7 +11,7 @@ expression: "pub type X {\n X(a: Int, b: Int)\n}\n\nfn id(x) {\n x\n}\n -type x() :: {x, integer(), integer()}. -file("/root/project/test/my/mod.gleam", 5). --spec id(S) -> S. +-spec id(I) -> I. id(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap index f22275cd8ee..80b9bf8f600 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__pipes__pipe_in_tuple.snap @@ -8,7 +8,7 @@ expression: "pub fn x(f) {\n #(\n 1 |> f\n )\n}" -export([x/1]). -file("/root/project/test/my/mod.gleam", 1). --spec x(fun((integer()) -> T)) -> {T}. +-spec x(fun((integer()) -> K)) -> {K}. x(F) -> {begin _pipe = 1, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap index 3ed584895a3..16443dbcf76 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__pipe_update_subject.snap @@ -11,7 +11,7 @@ expression: "pub type Thing {\n Thing(a: Int, b: Int)\n}\n\npub fn identity(x) -type thing() :: {thing, integer(), integer()}. -file("/root/project/test/my/mod.gleam", 5). --spec identity(S) -> S. +-spec identity(I) -> I. identity(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap index 89fcf21ab73..6e7199beef6 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__strings__pipe_concat.snap @@ -8,7 +8,7 @@ expression: "\nfn id(x) {\n x\n}\n\npub fn main() {\n { \"\" |> id } <> { \"\" -export([main/0]). -file("/root/project/test/my/mod.gleam", 2). --spec id(R) -> R. +-spec id(I) -> I. id(X) -> X. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap index 48b55eb6041..9dfa7e04889 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_named_args_count_once.snap @@ -8,10 +8,10 @@ expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n -export([wibble/0]). -export_type([wibble/2]). --type wibble(R, S) :: {wibble, R, S}. +-type wibble(I, J) :: {wibble, I, J}. -file("/root/project/test/my/mod.gleam", 6). --spec wibble() -> wibble(U, U). +-spec wibble() -> wibble(K, K). wibble() -> erlang:error(#{gleam_error => todo, message => <<"`todo` expression evaluated. This code has not yet been implemented."/utf8>>, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap index 138ebdfb397..3d052779179 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_named_args_count_once.snap @@ -8,10 +8,10 @@ expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n -export([wibble/0]). -export_type([wibble/2]). --type wibble(R, S) :: {wibble, R, S}. +-type wibble(I, J) :: {wibble, I, J}. -file("/root/project/test/my/mod.gleam", 6). --spec wibble() -> wibble(U, wibble(U, any())). +-spec wibble() -> wibble(K, wibble(K, any())). wibble() -> erlang:error(#{gleam_error => todo, message => <<"`todo` expression evaluated. This code has not yet been implemented."/utf8>>, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap index 1c311adcd09..78e67dc6b78 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_nested_result_type_count_once.snap @@ -8,7 +8,7 @@ expression: "\n pub type Wibble(a) {\n Oops\n }\n\n -export([wibble/0]). -export_type([wibble/1]). --type wibble(R) :: oops | {gleam_phantom, R}. +-type wibble(I) :: oops | {gleam_phantom, I}. -file("/root/project/test/my/mod.gleam", 6). -spec wibble() -> {ok, any()} | {error, wibble(any())}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap index 2e34eaf37cf..a19508f445b 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__custom_type_tuple_type_params_count_twice.snap @@ -8,10 +8,10 @@ expression: "\n pub type Wibble(a, b) {\n Wibble(a, b)\n -export([wibble/0]). -export_type([wibble/2]). --type wibble(R, S) :: {wibble, R, S}. +-type wibble(I, J) :: {wibble, I, J}. -file("/root/project/test/my/mod.gleam", 6). --spec wibble() -> {U, wibble(U, any())}. +-spec wibble() -> {K, wibble(K, any())}. wibble() -> erlang:error(#{gleam_error => todo, message => <<"`todo` expression evaluated. This code has not yet been implemented."/utf8>>, diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap index 6b289a1ecc4..c1fbce57282 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__type_params__result_type_inferred_count_once.snap @@ -7,7 +7,7 @@ expression: "\n fn wibble() {\n let assert Ok(_) = wobble()\n -export_type([wobble/1]). --type wobble(R) :: wobble | {gleam_phantom, R}. +-type wobble(I) :: wobble | {gleam_phantom, I}. -file("/root/project/test/my/mod.gleam", 10). -spec wobble() -> {ok, any()} | {error, wobble(any())}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap index 362a1758764..3487b8b1d95 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_1.snap @@ -8,7 +8,7 @@ expression: "\npub fn main() {\n use <- pair()\n 123\n}\n\nfn pair(f) {\n let -export([main/0]). -file("/root/project/test/my/mod.gleam", 7). --spec pair(fun(() -> U)) -> {U, U}. +-spec pair(fun(() -> L)) -> {L, L}. pair(F) -> X = F(), {X, X}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap index b3120bf6255..f2e16fd81db 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_2.snap @@ -8,7 +8,7 @@ expression: "\npub fn main() {\n use <- pair(1.0)\n 123\n}\n\nfn pair(x, f) {\ -export([main/0]). -file("/root/project/test/my/mod.gleam", 7). --spec pair(S, fun(() -> V)) -> {S, V}. +-spec pair(J, fun(() -> M)) -> {J, M}. pair(X, F) -> Y = F(), {X, Y}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap index 58da6069b52..347bc662ac2 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__use___arity_3.snap @@ -8,7 +8,7 @@ expression: "\npub fn main() {\n use <- trip(1.0, \"\")\n 123\n}\n\nfn trip(x, -export([main/0]). -file("/root/project/test/my/mod.gleam", 7). --spec trip(S, T, fun(() -> W)) -> {S, T, W}. +-spec trip(J, K, fun(() -> N)) -> {J, K, N}. trip(X, Y, F) -> Z = F(), {X, Y, Z}. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap index ba1103e177b..6f1e72f813c 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_and_call.snap @@ -8,6 +8,6 @@ expression: "\npub fn main(x) {\n fn(x) { x }(x)\n}\n" -export([main/1]). -file("/root/project/test/my/mod.gleam", 2). --spec main(T) -> T. +-spec main(K) -> K. main(X) -> (fun(X@1) -> X@1 end)(X). diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap index 8ce2bb2444c..c7b24f13e19 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_param.snap @@ -8,7 +8,7 @@ expression: "pub fn main(board) {\nfn(board) { board }\n board\n}" -export([main/1]). -file("/root/project/test/my/mod.gleam", 1). --spec main(R) -> R. +-spec main(I) -> I. main(Board) -> fun(Board@1) -> Board@1 end, Board. diff --git a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap index 96944f6bf59..9d95255ab3f 100644 --- a/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap +++ b/compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__variables__shadow_pipe.snap @@ -8,7 +8,7 @@ expression: "\npub fn main(x) {\n x\n |> fn(x) { x }\n}\n" -export([main/1]). -file("/root/project/test/my/mod.gleam", 2). --spec main(T) -> T. +-spec main(K) -> K. main(X) -> _pipe = X, (fun(X@1) -> X@1 end)(_pipe). diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap index d5bb7e645ad..8acae99539d 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__externals__external_type_typescript.snap @@ -2,6 +2,6 @@ source: compiler-core/src/javascript/tests/externals.rs expression: "pub type Queue(a)\n\n@external(javascript, \"queue\", \"new\")\npub fn new() -> Queue(a)\n" --- -export type Queue$ = any; +export type Queue$ = any; export function new$(): Queue$; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap index 51d5627c350..da1ff1bffc7 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__fn_generics_typescript.snap @@ -2,4 +2,4 @@ source: compiler-core/src/javascript/tests/generics.rs expression: "pub fn identity(a) -> a {\n a\n}\n" --- -export function identity(a: S): S; +export function identity(a: J): J; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap index 9e5053ea3eb..01f078bcdc7 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__record_generics_typescript.snap @@ -4,18 +4,18 @@ expression: "pub type Animal(t) {\n Cat(type_: t)\n Dog(type_: t)\n}\n\npub fn --- import type * as _ from "../gleam.d.mts"; -export class Cat extends _.CustomType { - constructor(type_: R); +export class Cat extends _.CustomType { + constructor(type_: I); - type_: R; + type_: I; } -export class Dog extends _.CustomType { - constructor(type_: R); +export class Dog extends _.CustomType { + constructor(type_: I); - type_: R; + type_: I; } -export type Animal$ = Cat | Dog; +export type Animal$ = Cat | Dog; export function main(): Animal$; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap index 44169938743..d2b3bdfa3d3 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__result_typescript.snap @@ -4,7 +4,7 @@ expression: "pub fn map(result, fun) {\n case result {\n --- import type * as _ from "../gleam.d.mts"; -export function map(result: _.Result, fun: (x0: AC) => AE): _.Result< - AE, - AB +export function map(result: _.Result, fun: (x0: T) => V): _.Result< + V, + S >; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap index 1a62448759d..05ad14e61da 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__task_typescript.snap @@ -2,6 +2,6 @@ source: compiler-core/src/javascript/tests/generics.rs expression: "pub type Promise(value)\n pub type Task(a) = fn() -> Promise(a)" --- -export type Promise$ = any; +export type Promise$ = any; export type Task = () => Promise$; diff --git a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap index 9e3bdba0269..73ff2755f1e 100644 --- a/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap +++ b/compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__generics__tuple_generics_typescript.snap @@ -2,4 +2,4 @@ source: compiler-core/src/javascript/tests/generics.rs expression: "pub fn make_tuple(x: t) -> #(Int, t, Int) {\n #(0, x, 1)\n}\n" --- -export function make_tuple(x: R): [number, R, number]; +export function make_tuple(x: I): [number, I, number]; diff --git a/compiler-core/src/type_/environment.rs b/compiler-core/src/type_/environment.rs index 497a1036bb8..4fa97f2ec05 100644 --- a/compiler-core/src/type_/environment.rs +++ b/compiler-core/src/type_/environment.rs @@ -53,8 +53,8 @@ pub struct Environment<'a> { pub referencing_source_indices: Vec>, /// Types defined in the current module (or the prelude) - pub module_types: HashMap, - pub type_usage_graph: HashMap)>, + pub module_types: HashMap, + pub type_usage_graph: HashMap)>, /// Mapping from types to constructor names in the current module (or the prelude) pub module_types_constructors: HashMap, @@ -100,11 +100,7 @@ impl<'a> Environment<'a> { gleam_version, previous_id: ids.next(), target, - module_types: prelude - .types - .iter() - .map(|(name, type_)| (name.clone(), (ids.next(), type_.clone()))) - .collect(), + module_types: prelude.types.clone(), type_usage_graph: HashMap::new(), module_types_constructors: prelude.types_value_constructors.clone(), module_values: HashMap::new(), @@ -274,12 +270,10 @@ impl<'a> Environment<'a> { // If a private constructor is used then its type is also used if v.publicity.is_private() { if let Some((_, type_name)) = v.type_.named_type_name() { - let _ = self.module_types.get(&type_name).map(|(id, _)| { - let _ = self - .type_usage_graph - .get_mut(id) - .map(|(_, _, usages)| usages.push(*location)); - }); + let _ = self + .type_usage_graph + .get_mut(&type_name) + .map(|(_, usages)| usages.push(*location)); } } } @@ -300,14 +294,13 @@ impl<'a> Environment<'a> { ) -> Result<(), Error> { let name = type_name.clone(); let location = info.origin; - let id = self.ids.next(); let _ = self .type_usage_graph - .insert(id, (info.clone(), name.clone(), Vec::new())); - match self.module_types.insert(type_name, (id, info)) { + .insert(name.clone(), (info.clone(), Vec::new())); + match self.module_types.insert(type_name, info) { None => Ok(()), - Some((_, prelude_type)) if is_prelude_module(&prelude_type.module) => Ok(()), - Some((_, previous)) => Err(Error::DuplicateTypeName { + Some(prelude_type) if is_prelude_module(&prelude_type.module) => Ok(()), + Some(previous) => Err(Error::DuplicateTypeName { name, location, previous_location: previous.origin, @@ -322,8 +315,8 @@ impl<'a> Environment<'a> { ) -> Result<(), Error> { match self.module_types.get(name) { None => Ok(()), - Some((_, prelude_type)) if is_prelude_module(&prelude_type.module) => Ok(()), - Some((_, previous)) => Err(Error::DuplicateTypeName { + Some(prelude_type) if is_prelude_module(&prelude_type.module) => Ok(()), + Some(previous) => Err(Error::DuplicateTypeName { name: name.clone(), location, previous_location: previous.origin, @@ -355,8 +348,8 @@ impl<'a> Environment<'a> { None => self .module_types .get(name) - .map(|(id, t)| { - if let Some((_, _, usages)) = self.type_usage_graph.get_mut(id) { + .map(|t| { + if let Some((_, usages)) = self.type_usage_graph.get_mut(name) { if *location != t.origin { usages.push(*location) } @@ -563,7 +556,7 @@ impl<'a> Environment<'a> { /// Converts entities with a usage count of 0 to warnings. /// Returns the list of unused imported module location for the removed unused lsp action. pub fn convert_unused_to_warnings(&mut self, problems: &mut Problems) { - for (_, (type_constructor, name, usages)) in self.type_usage_graph.iter() { + for (name, (type_constructor, usages)) in self.type_usage_graph.iter() { if usages.is_empty() { let imported = type_constructor.module != self.current_module; if !imported && type_constructor.publicity != Publicity::Private { diff --git a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap index 5c7eba10c02..c86ee2fdc42 100644 --- a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap +++ b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__alias_unqualified_import.snap @@ -18,7 +18,7 @@ expression: "./cases/alias_unqualified_import" -type empty() :: empty. -file("src/one.gleam", 2). --spec id(S) -> S. +-spec id(I) -> I. id(X) -> X. diff --git a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap index 867255897c5..ceb2c58b67a 100644 --- a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap +++ b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_bug_752.snap @@ -14,7 +14,7 @@ expression: "./cases/erlang_bug_752" -export_type([one/1]). --type one(R) :: {one, R}. +-type one(I) :: {one, I}. @@ -31,7 +31,7 @@ expression: "./cases/erlang_bug_752" -export_type([two/1]). --type two(AE) :: {two, one:one(integer())} | {gleam_phantom, AE}. +-type two(K) :: {two, one:one(integer())} | {gleam_phantom, K}. diff --git a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap index c32d96a370b..e78455ffbf8 100644 --- a/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap +++ b/test-package-compiler/src/snapshots/test_package_compiler__generated_tests__erlang_escape_names.snap @@ -15,7 +15,7 @@ expression: "./cases/erlang_escape_names" -export(['receive'/1]). -file("src/one.gleam", 2). --spec 'receive'(R) -> R. +-spec 'receive'(I) -> I. 'receive'(X) -> X. @@ -38,7 +38,7 @@ qualified_call() -> one:'receive'(1). -file("src/two.gleam", 8). --spec qualified_value() -> fun((AI) -> AI). +-spec qualified_value() -> fun((Q) -> Q). qualified_value() -> fun one:'receive'/1. @@ -48,7 +48,7 @@ unqualified_call() -> one:'receive'(1). -file("src/two.gleam", 16). --spec unqualified_value() -> fun((AK) -> AK). +-spec unqualified_value() -> fun((S) -> S). unqualified_value() -> fun one:'receive'/1. From 7deca60f3cbdaef5dcd7c8fab8341c61661e4f53 Mon Sep 17 00:00:00 2001 From: Ace Date: Sat, 14 Sep 2024 15:36:15 -0700 Subject: [PATCH 5/5] lint --- compiler-core/src/type_/environment.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler-core/src/type_/environment.rs b/compiler-core/src/type_/environment.rs index 4fa97f2ec05..c3762c04833 100644 --- a/compiler-core/src/type_/environment.rs +++ b/compiler-core/src/type_/environment.rs @@ -348,13 +348,12 @@ impl<'a> Environment<'a> { None => self .module_types .get(name) - .map(|t| { + .inspect(|t| { if let Some((_, usages)) = self.type_usage_graph.get_mut(name) { if *location != t.origin { usages.push(*location) } } - t }) .ok_or_else(|| UnknownTypeConstructorError::Type { name: name.clone(),