···304304305305 ([Surya Rose](https://github.com/GearsDatapacks))
306306307307-- The "Add type annotations" and "Generate function" code actions now ignore type
308308- variables defined in other functions, improving the generated code. For example:
307307+- The "Add type annotations" and "Generate function" code actions now ignore
308308+ type variables defined in other functions, improving the generated code.
309309+ For example:
309310310311 ```gleam
311312 fn something(a: a, b: b, c: c) -> d { todo }
···369370370371### Bug fixes
371372372372-- Fixed a bug where literals using `\u{XXXX}` syntax in bit array pattern segments were not
373373- translated to Erlang's `\x{XXXX}` syntax correctly.
373373+- Fixed a bug where literals using `\u{XXXX}` syntax in bit array pattern
374374+ segments were not translated to Erlang's `\x{XXXX}` syntax correctly.
374375 ([Benjamin Peinhardt](https://github.com/bcpeinhardt))
375376376377- Fixed a bug where `echo` could crash on JavaScript if the module contains
···433434- Fixed a bug where the compiler would reference a redeclared variable in a let
434435 assert message, instead of the original variable, on the Erlang target.
435436 ([Danielle Maywood](https://github.com/DanielleMaywood))
437437+438438+- Fixed a bug where the compiler would report an imported module as unused if it
439439+ were used by private functions only.
440440+ ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
···11-use std::collections::HashMap;
11+use std::collections::{HashMap, HashSet};
2233use crate::ast::{Publicity, SrcSpan};
44use bimap::{BiMap, Overwritten};
···8484 graph: StableGraph<(), (), Directed>,
8585 entities: BiMap<Entity, NodeIndex>,
8686 current_node: NodeIndex,
8787- public_entities: Vec<Entity>,
8787+ public_entities: HashSet<Entity>,
8888 entity_information: HashMap<Entity, EntityInformation>,
89899090 /// The locations of the references to each value in this module, used for
···193193 self.create_node_and_maybe_shadow(entity.clone(), self.current_node);
194194 match publicity {
195195 Publicity::Public | Publicity::Internal { .. } => {
196196- self.public_entities.push(entity.clone());
196196+ let _ = self.public_entities.insert(entity.clone());
197197 }
198198 Publicity::Private => {}
199199 }
···223223 };
224224 match publicity {
225225 Publicity::Public | Publicity::Internal { .. } => {
226226- self.public_entities.push(entity.clone());
226226+ let _ = self.public_entities.insert(entity.clone());
227227 }
228228 Publicity::Private => {}
229229 }
···257257 };
258258 match publicity {
259259 Publicity::Public | Publicity::Internal { .. } => {
260260- self.public_entities.push(entity.clone());
260260+ let _ = self.public_entities.insert(entity.clone());
261261 }
262262 Publicity::Private => {}
263263 }
···423423 }
424424 }
425425426426+ for (entity, _) in self.entities.iter() {
427427+ let Some(index) = self.entities.get_by_left(entity) else {
428428+ continue;
429429+ };
430430+431431+ if self.public_entities.contains(entity) {
432432+ self.mark_entity_as_used(&mut unused_values, entity, *index);
433433+ } else {
434434+ // If the entity is not public, we still want to mark referenced
435435+ // imports as used.
436436+ self.mark_referenced_imports_as_used(&mut unused_values, entity, *index);
437437+ }
438438+ }
439439+426440 unused_values
427441 }
428442···437451 if let Some(entity) = self.entities.get_by_right(&node) {
438452 self.mark_entity_as_used(unused, entity, node);
439453 }
454454+ }
455455+ }
456456+ }
457457+458458+ fn mark_referenced_imports_as_used(
459459+ &self,
460460+ unused: &mut HashMap<Entity, EntityInformation>,
461461+ entity: &Entity,
462462+ index: NodeIndex,
463463+ ) {
464464+ // If the entity is a module there's no way it can reference other
465465+ // modules so we just ignore it.
466466+ // This also means that module aliases do not count as using a module!
467467+ if entity.layer == EntityLayer::Module {
468468+ return;
469469+ }
470470+471471+ for node in self.graph.neighbors_directed(index, Direction::Outgoing) {
472472+ // We only want to mark referenced modules as used, so if the node
473473+ // is not a module we just skip it.
474474+ let Some(
475475+ module @ Entity {
476476+ layer: EntityLayer::Module,
477477+ ..
478478+ },
479479+ ) = self.entities.get_by_right(&node)
480480+ else {
481481+ continue;
482482+ };
483483+484484+ // If the value appears in the module import list, it doesn't count
485485+ // as using it!
486486+ let is_imported_type = self
487487+ .type_references
488488+ .contains_key(&(module.name.clone(), entity.name.clone()));
489489+ let is_imported_value = self
490490+ .value_references
491491+ .contains_key(&(module.name.clone(), entity.name.clone()));
492492+ let appears_in_module_import_list = is_imported_type || is_imported_value;
493493+ if !(appears_in_module_import_list) {
494494+ self.mark_entity_as_used(unused, module, node);
440495 }
441496 }
442497 }
···202021212222----- WARNING
2323-warning: Unused imported module
2424- ┌─ /src/warning/wrn.gleam:2:1
2525- │
2626-2 │ import wibble as wobble
2727- │ ^^^^^^^^^^^^^^^^^^^^^^^ This imported module is never used
2828-2929-Hint: You can safely remove it.
3030-3123warning: Unused private function
3224 ┌─ /src/warning/wrn.gleam:4:1
3325 │
···242425252626----- WARNING
2727-warning: Unused imported module alias
2828- ┌─ /src/warning/wrn.gleam:2:29
2929- │
3030-2 │ import wibble.{type Wibble} as wobble
3131- │ ^^^^^^^^^ This alias is never used
3232-3333-Hint: You can safely remove it.
3434-3535- import wibble as _
3636-3737-3827warning: Unused private function
3928 ┌─ /src/warning/wrn.gleam:4:1
4029 │
···202021212222----- WARNING
2323-warning: Unused imported module
2424- ┌─ /src/warning/wrn.gleam:2:1
2525- │
2626-2 │ import wibble
2727- │ ^^^^^^^^^^^^^ This imported module is never used
2828-2929-Hint: You can safely remove it.
3030-3123warning: Unused private function
3224 ┌─ /src/warning/wrn.gleam:4:1
3325 │