Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

Always generate type definitions for private types

author
Gears
committer
Louis Pilfold
date (Nov 23, 2025, 8:26 PM UTC) commit a05ef3b8 parent 6e1a0c26 change-id wvnsoksq
+124 -40
+4
CHANGELOG.md
··· 281 281 - Typos in the error message shown when trying to install a non-existent package 282 282 have been fixed. 283 283 ([Ioan Clarke](https://github.com/ioanclarke)) 284 + 285 + - Fixed a bug where the compiler would generate invalid Erlang and TypeScript 286 + code for unused opaque types referencing private types. 287 + ([Surya Rose](https://github.com/GearsDatapacks))
-7
compiler-core/src/erlang.rs
··· 181 181 &mut type_defs, 182 182 &module.name, 183 183 &overridden_publicity, 184 - &module.unused_definition_positions, 185 184 ); 186 185 } 187 186 ··· 303 302 type_defs: &mut Vec<Document<'_>>, 304 303 module_name: &str, 305 304 overridden_publicity: &im::HashSet<EcoString>, 306 - unused_definition_positions: &HashSet<u32>, 307 305 ) { 308 - // Do not generate any code for unused items 309 - if unused_definition_positions.contains(&definition.location().start) { 310 - return; 311 - } 312 - 313 306 match definition { 314 307 Definition::Function(Function { 315 308 publicity,
+16
compiler-core/src/erlang/tests/custom_types.rs
··· 27 27 "# 28 28 ); 29 29 } 30 + 31 + // https://github.com/gleam-lang/gleam/issues/5127 32 + #[test] 33 + fn unused_opaque_constructor_is_generated_correctly() { 34 + assert_erl!( 35 + " 36 + type Wibble { 37 + Wibble 38 + } 39 + 40 + pub opaque type Wobble { 41 + Wobble(Wibble) 42 + } 43 + " 44 + ); 45 + }
+24
compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__custom_types__unused_opaque_constructor_is_generated_correctly.snap
··· 1 + --- 2 + source: compiler-core/src/erlang/tests/custom_types.rs 3 + expression: "\ntype Wibble {\n Wibble\n}\n\npub opaque type Wobble {\n Wobble(Wibble)\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + 7 + type Wibble { 8 + Wibble 9 + } 10 + 11 + pub opaque type Wobble { 12 + Wobble(Wibble) 13 + } 14 + 15 + 16 + ----- COMPILED ERLANG 17 + -module(my@mod). 18 + -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). 19 + -define(FILEPATH, "project/test/my/mod.gleam"). 20 + -export_type([wibble/0, wobble/0]). 21 + 22 + -type wibble() :: wibble. 23 + 24 + -opaque wobble() :: {wobble, wibble()}.
+5 -1
compiler-core/src/erlang/tests/snapshots/gleam_core__erlang__tests__records__private_unused_records.snap
··· 18 18 -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). 19 19 -define(FILEPATH, "project/test/my/mod.gleam"). 20 20 -export([main/1]). 21 - -export_type([a/0]). 21 + -export_type([a/0, b/0, c/0]). 22 22 23 23 -type a() :: {a, integer()}. 24 + 25 + -type b() :: {b, binary()}. 26 + 27 + -type c() :: {c, integer()}. 24 28 25 29 -file("project/test/my/mod.gleam", 5). 26 30 -spec main(integer()) -> integer().
+16
compiler-core/src/javascript/tests/custom_types.rs
··· 960 960 "# 961 961 ); 962 962 } 963 + 964 + // https://github.com/gleam-lang/gleam/issues/5127 965 + #[test] 966 + fn unused_opaque_constructor_is_generated_correctly() { 967 + assert_ts_def!( 968 + " 969 + type Wibble { 970 + Wibble 971 + } 972 + 973 + pub opaque type Wobble { 974 + Wobble(Wibble) 975 + } 976 + " 977 + ); 978 + }
+30
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__custom_types__unused_opaque_constructor_is_generated_correctly.snap
··· 1 + --- 2 + source: compiler-core/src/javascript/tests/custom_types.rs 3 + expression: "\ntype Wibble {\n Wibble\n}\n\npub opaque type Wobble {\n Wobble(Wibble)\n}\n" 4 + --- 5 + ----- SOURCE CODE 6 + 7 + type Wibble { 8 + Wibble 9 + } 10 + 11 + pub opaque type Wobble { 12 + Wobble(Wibble) 13 + } 14 + 15 + 16 + ----- TYPESCRIPT DEFINITIONS 17 + import type * as _ from "../gleam.d.mts"; 18 + 19 + declare class Wibble extends _.CustomType {} 20 + 21 + type Wibble$ = Wibble; 22 + 23 + declare class Wobble extends _.CustomType { 24 + /** @deprecated */ 25 + constructor(argument$0: Wibble$); 26 + /** @deprecated */ 27 + 0: Wibble$; 28 + } 29 + 30 + export type Wobble$ = Wobble;
+4
compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__type_alias__private_type_in_opaque_type.snap
··· 16 16 ----- TYPESCRIPT DEFINITIONS 17 17 import type * as _ from "../gleam.d.mts"; 18 18 19 + declare class PrivateType extends _.CustomType {} 20 + 21 + type PrivateType$ = PrivateType; 22 + 19 23 declare class OpaqueType extends _.CustomType { 20 24 /** @deprecated */ 21 25 constructor(argument$0: PrivateType$);
+22 -32
compiler-core/src/javascript/typescript.rs
··· 11 11 //! <https://www.typescriptlang.org/> 12 12 //! <https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html> 13 13 14 - use crate::ast::{AssignName, Publicity, SrcSpan}; 14 + use crate::ast::{AssignName, Publicity, TypedCustomType}; 15 15 use crate::javascript::import::Member; 16 16 use crate::type_::{PRELUDE_MODULE_NAME, RecordAccessor, is_prelude_module}; 17 17 use crate::{ ··· 380 380 381 381 Definition::Import(Import { .. }) => vec![], 382 382 383 - Definition::CustomType(CustomType { 384 - publicity, 385 - constructors, 386 - opaque, 387 - name, 388 - typed_parameters, 389 - external_javascript, 390 - .. 391 - }) if publicity.is_importable() => self.custom_type_definition( 392 - name, 393 - typed_parameters, 394 - constructors, 395 - *opaque, 396 - external_javascript, 397 - imports, 398 - ), 399 - Definition::CustomType(CustomType { .. }) => vec![], 383 + Definition::CustomType(type_) => self.custom_type_definition(type_, imports), 400 384 401 385 Definition::ModuleConstant(ModuleConstant { 402 386 publicity, ··· 439 423 /// 440 424 fn custom_type_definition( 441 425 &mut self, 442 - name: &'a str, 443 - typed_parameters: &'a [Arc<Type>], 444 - constructors: &'a [TypedRecordConstructor], 445 - opaque: bool, 446 - external: &'a Option<(EcoString, EcoString, SrcSpan)>, 426 + type_: &'a TypedCustomType, 447 427 imports: &mut Imports<'_>, 448 428 ) -> Vec<Document<'a>> { 429 + let CustomType { 430 + publicity, 431 + constructors, 432 + opaque, 433 + name, 434 + typed_parameters, 435 + external_javascript, 436 + .. 437 + } = type_; 438 + 449 439 // Constructors for opaque and private types are not exported 450 - let constructor_publicity = if opaque { 440 + let constructor_publicity = if publicity.is_private() || *opaque { 451 441 Publicity::Private 452 442 } else { 453 443 Publicity::Public ··· 469 459 .collect_vec(); 470 460 471 461 let definition = if constructors.is_empty() { 472 - if let Some((module, external_name, _location)) = external { 462 + if let Some((module, external_name, _location)) = external_javascript { 473 463 let member = Member { 474 464 name: external_name.to_doc(), 475 465 alias: Some(eco_format!("{name}$").to_doc()), ··· 491 481 join(constructors, break_("| ", " | ")) 492 482 }; 493 483 494 - definitions.push(docvec![ 495 - "export type ", 496 - type_name.clone(), 497 - " = ", 498 - definition, 499 - ";", 500 - ]); 484 + let head = if publicity.is_private() { 485 + "type " 486 + } else { 487 + "export type " 488 + }; 489 + 490 + definitions.push(docvec![head, type_name.clone(), " = ", definition, ";",]); 501 491 502 492 // Generate getters for fields shared between variants 503 493 if let Some(accessors_map) = self.module.type_info.accessors.get(name)
+3
test-package-compiler/src/snapshots/test_package_compiler__generated_tests__import_shadowed_name_warning.snap
··· 36 36 -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). 37 37 -define(FILEPATH, "src/two.gleam"). 38 38 -export([use_type/1]). 39 + -export_type([shadowing/0]). 39 40 40 41 -if(?OTP_RELEASE >= 27). 41 42 -define(MODULEDOC(Str), -moduledoc(Str)). ··· 46 47 -endif. 47 48 48 49 ?MODULEDOC(" https://github.com/gleam-lang/otp/pull/22\n"). 50 + 51 + -type shadowing() :: port. 49 52 50 53 -file("src/two.gleam", 14). 51 54 -spec use_type(one:port_()) -> nil.