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

Configure Feed

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

remove record tag from constants

author
Giacomo Cavalieri
committer
Louis Pilfold
date (May 21, 2026, 12:59 PM +0100) commit 761e961e parent 43465204 change-id zxrtnsok
+132 -162
+1 -1
compiler-core/src/analyse.rs
··· 1848 1848 } 1849 1849 1850 1850 fn generalise_module_constant( 1851 - constant: ModuleConstant<Arc<Type>, EcoString>, 1851 + constant: ModuleConstant<Arc<Type>>, 1852 1852 environment: &mut Environment<'_>, 1853 1853 module_name: &EcoString, 1854 1854 ) -> TypedModuleConstant {
+20 -20
compiler-core/src/ast.rs
··· 1031 1031 } 1032 1032 } 1033 1033 1034 - pub type UntypedModuleConstant = ModuleConstant<(), ()>; 1035 - pub type TypedModuleConstant = ModuleConstant<Arc<Type>, EcoString>; 1034 + pub type UntypedModuleConstant = ModuleConstant<()>; 1035 + pub type TypedModuleConstant = ModuleConstant<Arc<Type>>; 1036 1036 1037 1037 #[derive(Debug, Clone, PartialEq, Eq)] 1038 1038 /// A certain fixed value that can be used in multiple places ··· 1043 1043 /// pub const start_year = 2101 1044 1044 /// pub const end_year = 2111 1045 1045 /// ``` 1046 - pub struct ModuleConstant<T, ConstantRecordTag> { 1046 + pub struct ModuleConstant<T> { 1047 1047 pub documentation: Option<(u32, EcoString)>, 1048 1048 /// The location of the constant, starting at the "(pub) const" keywords and 1049 1049 /// ending after the ": Type" annotation, or (without an annotation) after its name. ··· 1052 1052 pub name: EcoString, 1053 1053 pub name_location: SrcSpan, 1054 1054 pub annotation: Option<TypeAst>, 1055 - pub value: Box<Constant<T, ConstantRecordTag>>, 1055 + pub value: Box<Constant<T>>, 1056 1056 pub type_: T, 1057 1057 pub deprecation: Deprecation, 1058 1058 pub implementations: Implementations, ··· 1195 1195 } 1196 1196 } 1197 1197 1198 - pub type UntypedDefinition = Definition<(), UntypedExpr, (), ()>; 1198 + pub type UntypedDefinition = Definition<(), UntypedExpr, ()>; 1199 1199 1200 1200 #[derive(Debug, Clone, PartialEq, Eq)] 1201 - pub enum Definition<T, Expr, ConstantRecordTag, PackageName> { 1201 + pub enum Definition<T, Expr, PackageName> { 1202 1202 Function(Function<T, Expr>), 1203 1203 TypeAlias(TypeAlias<T>), 1204 1204 CustomType(CustomType<T>), 1205 1205 Import(Import<PackageName>), 1206 - ModuleConstant(ModuleConstant<T, ConstantRecordTag>), 1206 + ModuleConstant(ModuleConstant<T>), 1207 1207 } 1208 1208 1209 - impl<A, B, C, E> Definition<A, B, C, E> { 1209 + impl<A, B, C> Definition<A, B, C> { 1210 1210 pub fn location(&self) -> SrcSpan { 1211 1211 match self { 1212 1212 Definition::Function(Function { location, .. }) ··· 1863 1863 pub type UntypedMultiPattern = MultiPattern<()>; 1864 1864 pub type TypedMultiPattern = MultiPattern<Arc<Type>>; 1865 1865 1866 - pub type TypedClause = Clause<TypedExpr, Arc<Type>, EcoString>; 1866 + pub type TypedClause = Clause<TypedExpr, Arc<Type>>; 1867 1867 1868 - pub type UntypedClause = Clause<UntypedExpr, (), ()>; 1868 + pub type UntypedClause = Clause<UntypedExpr, ()>; 1869 1869 1870 1870 #[derive(Debug, Clone, PartialEq, Eq)] 1871 - pub struct Clause<Expr, Type, RecordTag> { 1871 + pub struct Clause<Expr, Type> { 1872 1872 pub location: SrcSpan, 1873 1873 pub pattern: MultiPattern<Type>, 1874 1874 pub alternative_patterns: Vec<MultiPattern<Type>>, 1875 - pub guard: Option<ClauseGuard<Type, RecordTag>>, 1875 + pub guard: Option<ClauseGuard<Type>>, 1876 1876 pub then: Expr, 1877 1877 } 1878 1878 1879 - impl<A, B, C> Clause<A, B, C> { 1879 + impl<A, B> Clause<A, B> { 1880 1880 pub fn pattern_count(&self) -> usize { 1881 1881 1 + self.alternative_patterns.len() 1882 1882 } ··· 2276 2276 } 2277 2277 } 2278 2278 2279 - pub type UntypedClauseGuard = ClauseGuard<(), ()>; 2280 - pub type TypedClauseGuard = ClauseGuard<Arc<Type>, EcoString>; 2279 + pub type UntypedClauseGuard = ClauseGuard<()>; 2280 + pub type TypedClauseGuard = ClauseGuard<Arc<Type>>; 2281 2281 2282 2282 #[derive(Debug, Clone, PartialEq, Eq)] 2283 - pub enum ClauseGuard<Type, RecordTag> { 2283 + pub enum ClauseGuard<Type> { 2284 2284 Block { 2285 2285 location: SrcSpan, 2286 - value: Box<ClauseGuard<Type, RecordTag>>, 2286 + value: Box<ClauseGuard<Type>>, 2287 2287 }, 2288 2288 2289 2289 BinaryOperator { ··· 2335 2335 label: EcoString, 2336 2336 module_name: EcoString, 2337 2337 module_alias: EcoString, 2338 - literal: Constant<Type, RecordTag>, 2338 + literal: Constant<Type>, 2339 2339 }, 2340 2340 2341 - Constant(Constant<Type, RecordTag>), 2341 + Constant(Constant<Type>), 2342 2342 2343 2343 Invalid { 2344 2344 location: SrcSpan, ··· 2346 2346 }, 2347 2347 } 2348 2348 2349 - impl<A, B> ClauseGuard<A, B> { 2349 + impl<A> ClauseGuard<A> { 2350 2350 pub fn location(&self) -> SrcSpan { 2351 2351 match self { 2352 2352 ClauseGuard::Constant(constant) => constant.location(),
+23 -9
compiler-core/src/ast/constant.rs
··· 2 2 use crate::analyse::Inferred; 3 3 use crate::type_::{FieldMap, HasType}; 4 4 5 - pub type TypedConstant = Constant<Arc<Type>, EcoString>; 6 - pub type UntypedConstant = Constant<(), ()>; 5 + pub type TypedConstant = Constant<Arc<Type>>; 6 + pub type UntypedConstant = Constant<()>; 7 7 8 - // TODO: remove RecordTag paramter 9 8 #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] 10 - pub enum Constant<T, RecordTag> { 9 + pub enum Constant<T> { 11 10 Int { 12 11 location: SrcSpan, 13 12 value: EcoString, ··· 43 42 module: Option<(EcoString, SrcSpan)>, 44 43 name: EcoString, 45 44 arguments: Vec<CallArg<Self>>, 46 - tag: RecordTag, 47 45 type_: T, 48 46 field_map: Inferred<FieldMap>, 49 47 record_constructor: Option<Box<ValueConstructor>>, ··· 56 54 name: EcoString, 57 55 record: RecordBeingUpdated<Self>, 58 56 arguments: Vec<RecordUpdateArg<Self>>, 59 - tag: RecordTag, 60 57 type_: T, 61 58 field_map: Inferred<FieldMap>, 62 59 }, ··· 476 473 | Constant::Invalid { .. } => None, 477 474 } 478 475 } 476 + 477 + /// If the constant is a record or record update this returns its tag. 478 + /// It might return `None` if the record constructor couldn't be inferred. 479 + pub(crate) fn constant_record_tag(&self) -> Option<EcoString> { 480 + if let Constant::Record { 481 + record_constructor: Some(constructor), 482 + .. 483 + } = self 484 + && let ValueConstructorVariant::Record { name, .. } = &constructor.variant 485 + { 486 + Some(name.clone()) 487 + } else if let Constant::RecordUpdate { name, .. } = self { 488 + Some(name.clone()) 489 + } else { 490 + None 491 + } 492 + } 479 493 } 480 494 481 495 impl HasType for TypedConstant { ··· 484 498 } 485 499 } 486 500 487 - impl<A, B> Constant<A, B> { 501 + impl<A> Constant<A> { 488 502 pub fn location(&self) -> SrcSpan { 489 503 match self { 490 504 Constant::Int { location, .. } ··· 522 536 } 523 537 } 524 538 525 - impl<A, B> HasLocation for Constant<A, B> { 539 + impl<A> HasLocation for Constant<A> { 526 540 fn location(&self) -> SrcSpan { 527 541 self.location() 528 542 } 529 543 } 530 544 531 - impl<A, B> bit_array::GetLiteralValue for Constant<A, B> { 545 + impl<A> bit_array::GetLiteralValue for Constant<A> { 532 546 fn as_int_literal(&self) -> Option<BigInt> { 533 547 if let Constant::Int { int_value, .. } = self { 534 548 Some(int_value.clone())
+1 -1
compiler-core/src/ast/typed.rs
··· 94 94 location: SrcSpan, 95 95 type_: Arc<Type>, 96 96 subjects: Vec<Self>, 97 - clauses: Vec<Clause<Self, Arc<Type>, EcoString>>, 97 + clauses: Vec<Clause<Self, Arc<Type>>>, 98 98 compiled_case: CompiledCase, 99 99 }, 100 100
+1 -1
compiler-core/src/ast/untyped.rs
··· 75 75 location: SrcSpan, 76 76 subjects: Vec<Self>, 77 77 // None if the case expression is missing a body. 78 - clauses: Option<Vec<Clause<Self, (), ()>>>, 78 + clauses: Option<Vec<Clause<Self, ()>>>, 79 79 }, 80 80 81 81 FieldAccess {
-10
compiler-core/src/ast/visit.rs
··· 741 741 module: &'ast Option<(EcoString, SrcSpan)>, 742 742 name: &'ast EcoString, 743 743 arguments: &'ast Vec<CallArg<TypedConstant>>, 744 - tag: &'ast EcoString, 745 744 type_: &'ast Arc<Type>, 746 745 field_map: &'ast Inferred<FieldMap>, 747 746 record_constructor: &'ast Option<Box<ValueConstructor>>, ··· 752 751 module, 753 752 name, 754 753 arguments, 755 - tag, 756 754 type_, 757 755 field_map, 758 756 record_constructor, ··· 768 766 name: &'ast EcoString, 769 767 record: &'ast RecordBeingUpdated<TypedConstant>, 770 768 arguments: &'ast [RecordUpdateArg<TypedConstant>], 771 - tag: &'ast EcoString, 772 769 type_: &'ast Arc<Type>, 773 770 field_map: &'ast Inferred<FieldMap>, 774 771 ) { ··· 780 777 name, 781 778 record, 782 779 arguments, 783 - tag, 784 780 type_, 785 781 field_map, 786 782 ) ··· 869 865 _module: &'a Option<(EcoString, SrcSpan)>, 870 866 _name: &'a EcoString, 871 867 arguments: &'a Vec<CallArg<TypedConstant>>, 872 - _tag: &'a EcoString, 873 868 _type_: &'a Arc<Type>, 874 869 _field_map: &'a Inferred<FieldMap>, 875 870 _record_constructor: &'a Option<Box<ValueConstructor>>, ··· 888 883 _name: &'a EcoString, 889 884 record: &'a RecordBeingUpdated<TypedConstant>, 890 885 arguments: &'a [RecordUpdateArg<TypedConstant>], 891 - _tag: &'a EcoString, 892 886 _type_: &'a Arc<Type>, 893 887 _field_map: &'a Inferred<FieldMap>, 894 888 ) { ··· 1177 1171 module, 1178 1172 name, 1179 1173 arguments, 1180 - tag, 1181 1174 type_, 1182 1175 field_map, 1183 1176 record_constructor, ··· 1186 1179 module, 1187 1180 name, 1188 1181 arguments, 1189 - tag, 1190 1182 type_, 1191 1183 field_map, 1192 1184 record_constructor, ··· 1198 1190 name, 1199 1191 record, 1200 1192 arguments, 1201 - tag, 1202 1193 type_, 1203 1194 field_map, 1204 1195 } => v.visit_typed_constant_record_update( ··· 1208 1199 name, 1209 1200 record, 1210 1201 arguments, 1211 - tag, 1212 1202 type_, 1213 1203 field_map, 1214 1204 ),
-8
compiler-core/src/ast_folder.rs
··· 993 993 module, 994 994 name, 995 995 arguments, 996 - tag: (), 997 996 type_: (), 998 997 field_map: _, 999 998 record_constructor: _, ··· 1006 1005 name, 1007 1006 record, 1008 1007 arguments, 1009 - tag: (), 1010 1008 type_: (), 1011 1009 field_map: _, 1012 1010 } => self.fold_constant_record_update( ··· 1124 1122 module, 1125 1123 name, 1126 1124 arguments, 1127 - tag: (), 1128 1125 type_: (), 1129 1126 field_map: Inferred::Unknown, 1130 1127 record_constructor: None, ··· 1147 1144 name, 1148 1145 record, 1149 1146 arguments, 1150 - tag: (), 1151 1147 type_: (), 1152 1148 field_map: Inferred::Unknown, 1153 1149 } ··· 1236 1232 module, 1237 1233 name, 1238 1234 arguments, 1239 - tag, 1240 1235 type_, 1241 1236 field_map, 1242 1237 record_constructor, ··· 1253 1248 module, 1254 1249 name, 1255 1250 arguments, 1256 - tag, 1257 1251 type_, 1258 1252 field_map, 1259 1253 record_constructor, ··· 1267 1261 name, 1268 1262 record, 1269 1263 arguments, 1270 - tag, 1271 1264 type_, 1272 1265 field_map, 1273 1266 } => { ··· 1290 1283 name, 1291 1284 record, 1292 1285 arguments, 1293 - tag, 1294 1286 type_, 1295 1287 field_map, 1296 1288 }
+2 -2
compiler-core/src/call_graph.rs
··· 8 8 Result, 9 9 ast::{ 10 10 AssignName, AssignmentKind, BitArrayOption, BitArraySize, ClauseGuard, Constant, Pattern, 11 - SrcSpan, Statement, UntypedClauseGuard, UntypedExpr, UntypedFunction, 11 + SrcSpan, Statement, UntypedClauseGuard, UntypedConstant, UntypedExpr, UntypedFunction, 12 12 UntypedModuleConstant, UntypedPattern, UntypedStatement, 13 13 }, 14 14 type_::Error, ··· 453 453 } 454 454 } 455 455 456 - fn constant(&mut self, constant: &'a Constant<(), ()>) { 456 + fn constant(&mut self, constant: &'a UntypedConstant) { 457 457 match constant { 458 458 Constant::Int { .. } 459 459 | Constant::Float { .. }
+21 -14
compiler-core/src/erlang.rs
··· 1797 1797 ), 1798 1798 1799 1799 Constant::Record { 1800 - tag, 1801 - type_, 1802 - arguments, 1803 - .. 1804 - } if arguments.is_empty() => match type_.deref() { 1805 - Type::Fn { arguments, .. } => record_constructor_function(tag, arguments.len()), 1806 - Type::Named { .. } | Type::Var { .. } | Type::Tuple { .. } => { 1807 - atom_string(to_snake_case(tag)) 1800 + type_, arguments, .. 1801 + } if arguments.is_empty() => { 1802 + let tag = literal 1803 + .constant_record_tag() 1804 + .expect("record without inferred constructor made it to code generation"); 1805 + 1806 + match type_.deref() { 1807 + Type::Fn { arguments, .. } => record_constructor_function(tag, arguments.len()), 1808 + Type::Named { .. } | Type::Var { .. } | Type::Tuple { .. } => { 1809 + atom_string(to_snake_case(&tag)) 1810 + } 1808 1811 } 1809 - }, 1812 + } 1810 1813 1811 - Constant::Record { tag, arguments, .. } => { 1814 + Constant::Record { arguments, .. } => { 1815 + let tag = literal 1816 + .constant_record_tag() 1817 + .expect("record without inferred constructor made it to code generation"); 1818 + 1812 1819 // Record updates are fully expanded during type checking, so we just handle arguments 1813 1820 let arguments_doc = arguments 1814 1821 .iter() 1815 1822 .map(|argument| const_inline(&argument.value, env)); 1816 - let tag = atom_string(to_snake_case(tag)); 1823 + let tag = atom_string(to_snake_case(&tag)); 1817 1824 tuple(std::iter::once(tag).chain(arguments_doc)) 1818 1825 } 1819 1826 ··· 1837 1844 } 1838 1845 } 1839 1846 1840 - fn record_constructor_function(tag: &EcoString, arity: usize) -> Document<'_> { 1847 + fn record_constructor_function<'a>(tag: EcoString, arity: usize) -> Document<'a> { 1841 1848 let chars = incrementing_arguments_list(arity); 1842 1849 "fun(" 1843 1850 .to_doc() 1844 1851 .append(chars.clone()) 1845 1852 .append(") -> {") 1846 - .append(atom_string(to_snake_case(tag))) 1853 + .append(atom_string(to_snake_case(&tag))) 1847 1854 .append(", ") 1848 1855 .append(chars) 1849 1856 .append("} end") ··· 2572 2579 TypedExpr::ModuleSelect { 2573 2580 constructor: ModuleValueConstructor::Record { name, arity, .. }, 2574 2581 .. 2575 - } => record_constructor_function(name, *arity as usize), 2582 + } => record_constructor_function(name.clone(), *arity as usize), 2576 2583 2577 2584 TypedExpr::ModuleSelect { 2578 2585 type_,
+15 -18
compiler-core/src/format.rs
··· 469 469 } 470 470 } 471 471 472 - fn const_expr<'a, A, B>(&mut self, value: &'a Constant<A, B>) -> Document<'a> { 472 + fn const_expr<'a, A>(&mut self, value: &'a Constant<A>) -> Document<'a> { 473 473 let comments = self.pop_comments(value.location().start); 474 474 let document = match value { 475 475 Constant::Todo { message, .. } => { ··· 593 593 commented(document, comments) 594 594 } 595 595 596 - fn const_list<'a, A, B>( 596 + fn const_list<'a, A>( 597 597 &mut self, 598 - elements: &'a [Constant<A, B>], 598 + elements: &'a [Constant<A>], 599 599 location: &SrcSpan, 600 - tail: &'a Option<Box<Constant<A, B>>>, 600 + tail: &'a Option<Box<Constant<A>>>, 601 601 ) -> Document<'a> { 602 602 if elements.is_empty() { 603 603 // We take all comments that come _before_ the end of the list, ··· 692 692 } 693 693 } 694 694 695 - pub fn const_tuple<'a, A, B>( 695 + pub fn const_tuple<'a, A>( 696 696 &mut self, 697 - elements: &'a [Constant<A, B>], 697 + elements: &'a [Constant<A>], 698 698 location: &SrcSpan, 699 699 ) -> Document<'a> { 700 700 if elements.is_empty() { ··· 1540 1540 ) 1541 1541 } 1542 1542 1543 - pub fn const_record_update<'a, A, B>( 1543 + pub fn const_record_update<'a, A>( 1544 1544 &mut self, 1545 1545 module: &Option<(EcoString, SrcSpan)>, 1546 1546 name: &'a EcoString, 1547 - record: &'a RecordBeingUpdated<Constant<A, B>>, 1548 - arguments: &'a [RecordUpdateArg<Constant<A, B>>], 1547 + record: &'a RecordBeingUpdated<Constant<A>>, 1548 + arguments: &'a [RecordUpdateArg<Constant<A>>], 1549 1549 location: &SrcSpan, 1550 1550 ) -> Document<'a> { 1551 1551 let constructor_doc = match module { ··· 2720 2720 } 2721 2721 } 2722 2722 2723 - fn constant_call_arg<'a, A, B>( 2724 - &mut self, 2725 - argument: &'a CallArg<Constant<A, B>>, 2726 - ) -> Document<'a> { 2723 + fn constant_call_arg<'a, A>(&mut self, argument: &'a CallArg<Constant<A>>) -> Document<'a> { 2727 2724 self.format_call_arg(argument, constant_call_arg_formatting, |this, value| { 2728 2725 this.const_expr(value) 2729 2726 }) ··· 3180 3177 doc.group() 3181 3178 } 3182 3179 3183 - fn append_as_message_constant<'a, A, B>( 3180 + fn append_as_message_constant<'a, A>( 3184 3181 &mut self, 3185 3182 doc: Document<'a>, 3186 - message: Option<&'a Constant<A, B>>, 3183 + message: Option<&'a Constant<A>>, 3187 3184 ) -> Document<'a> { 3188 3185 let Some(message) = message else { return doc }; 3189 3186 ··· 3669 3666 } 3670 3667 } 3671 3668 3672 - fn constant_call_arg_formatting<A, B>( 3673 - argument: &CallArg<Constant<A, B>>, 3674 - ) -> CallArgFormatting<'_, Constant<A, B>> { 3669 + fn constant_call_arg_formatting<A>( 3670 + argument: &CallArg<Constant<A>>, 3671 + ) -> CallArgFormatting<'_, Constant<A>> { 3675 3672 match argument { 3676 3673 // An argument supplied using label shorthand syntax. 3677 3674 _ if argument.uses_label_shorthand() => CallArgFormatting::ShorthandLabelled(
+8 -2
compiler-core/src/javascript/expression.rs
··· 2109 2109 arguments, 2110 2110 module, 2111 2111 name, 2112 - tag, 2113 2112 type_, 2114 2113 .. 2115 2114 } => { 2115 + let tag = expression 2116 + .constant_record_tag() 2117 + .expect("record without inferred constructor made it to code generation"); 2118 + 2116 2119 if module.is_none() && type_.is_result() { 2117 2120 if tag == "Ok" { 2118 2121 self.tracker.ok_used = true; ··· 2479 2482 arguments, 2480 2483 module, 2481 2484 name, 2482 - tag, 2483 2485 type_, 2484 2486 .. 2485 2487 } => { 2488 + let tag = expression 2489 + .constant_record_tag() 2490 + .expect("record without inferred constructor made it to code generation"); 2491 + 2486 2492 if module.is_none() && type_.is_result() { 2487 2493 if tag == "Ok" { 2488 2494 self.tracker.ok_used = true;
-4
compiler-core/src/metadata.rs
··· 335 335 module, 336 336 name, 337 337 arguments, 338 - tag, 339 338 type_, 340 339 field_map, 341 340 record_constructor, ··· 359 358 }, 360 359 ) 361 360 .collect(), 362 - tag, 363 361 type_: self.type_(type_), 364 362 field_map, 365 363 record_constructor: record_constructor ··· 376 374 location: record_location, 377 375 }, 378 376 arguments, 379 - tag, 380 377 type_, 381 378 field_map, 382 379 } => Constant::RecordUpdate { ··· 402 399 }, 403 400 ) 404 401 .collect(), 405 - tag, 406 402 type_: self.type_(type_), 407 403 field_map, 408 404 },
-1
compiler-core/src/metadata/tests.rs
··· 1191 1191 }, 1192 1192 }, 1193 1193 ], 1194 - tag: "thetag".into(), 1195 1194 type_: type_::int(), 1196 1195 field_map: Inferred::Unknown, 1197 1196 record_constructor: None,
+1 -4
compiler-core/src/parse.rs
··· 204 204 // Test Interface 205 205 // 206 206 #[cfg(test)] 207 - pub fn parse_const_value(src: &str) -> Result<Constant<(), ()>, ParseError> { 207 + pub fn parse_const_value(src: &str) -> Result<UntypedConstant, ParseError> { 208 208 let lex = lexer::make_tokenizer(src); 209 209 let mut parser = Parser::new(lex); 210 210 let expr = parser.parse_const_value(); ··· 3560 3560 name, 3561 3561 record, 3562 3562 arguments: update_arguments, 3563 - tag: (), 3564 3563 type_: (), 3565 3564 field_map: Inferred::Unknown, 3566 3565 })) ··· 3588 3587 module, 3589 3588 name, 3590 3589 arguments, 3591 - tag: (), 3592 3590 type_: (), 3593 3591 field_map: Inferred::Unknown, 3594 3592 record_constructor: None, ··· 3600 3598 module, 3601 3599 name, 3602 3600 arguments: vec![], 3603 - tag: (), 3604 3601 type_: (), 3605 3602 field_map: Inferred::Unknown, 3606 3603 record_constructor: None,
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__byte_order_mark_module.snap
··· 85 85 }, 86 86 }, 87 87 ], 88 - tag: (), 89 88 type_: (), 90 89 field_map: Unknown, 91 90 },
-2
compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_record_update_all_fields.snap
··· 222 222 implicit: None, 223 223 }, 224 224 ], 225 - tag: (), 226 225 type_: (), 227 226 field_map: Unknown, 228 227 record_constructor: None, ··· 327 326 }, 328 327 }, 329 328 ], 330 - tag: (), 331 329 type_: (), 332 330 field_map: Unknown, 333 331 },
-2
compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_record_update_basic.snap
··· 173 173 implicit: None, 174 174 }, 175 175 ], 176 - tag: (), 177 176 type_: (), 178 177 field_map: Unknown, 179 178 record_constructor: None, ··· 249 248 }, 250 249 }, 251 250 ], 252 - tag: (), 253 251 type_: (), 254 252 field_map: Unknown, 255 253 },
-2
compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_record_update_only.snap
··· 173 173 implicit: None, 174 174 }, 175 175 ], 176 - tag: (), 177 176 type_: (), 178 177 field_map: Unknown, 179 178 record_constructor: None, ··· 234 233 }, 235 234 }, 236 235 arguments: [], 237 - tag: (), 238 236 type_: (), 239 237 field_map: Unknown, 240 238 },
-1
compiler-core/src/parse/snapshots/gleam_core__parse__tests__const_record_update_with_module.snap
··· 85 85 }, 86 86 }, 87 87 ], 88 - tag: (), 89 88 type_: (), 90 89 field_map: Unknown, 91 90 },
+1 -1
compiler-core/src/type_.rs
··· 714 714 location: SrcSpan, 715 715 module: EcoString, 716 716 name: EcoString, 717 - literal: Constant<Arc<Type>, EcoString>, 717 + literal: Constant<Arc<Type>>, 718 718 implementations: Implementations, 719 719 }, 720 720
+33 -41
compiler-core/src/type_/expression.rs
··· 3958 3958 } 3959 3959 }; 3960 3960 3961 - let (tag, field_map) = match &constructor.variant { 3961 + let (constructor_tag, field_map) = match &constructor.variant { 3962 3962 ValueConstructorVariant::Record { 3963 3963 name, 3964 3964 field_map: Some(field_map), ··· 4032 4032 }; 4033 4033 4034 4034 // Get the field arguments from the record that we'll use as the base. 4035 - let (base_arguments, base_tag) = 4036 - if let Constant::Record { arguments, tag, .. } = resolved_record { 4037 - (arguments, tag) 4038 - } else { 4039 - self.problems.error(convert_unify_error( 4040 - UnifyError::CouldNotUnify { 4041 - expected: expected_type.clone(), 4042 - given: typed_record_type, 4043 - situation: None, 4044 - }, 4045 - record.base.location(), 4046 - )); 4047 - return self.new_invalid_constant(location); 4048 - }; 4035 + let (base_arguments, updated_record_tag) = if let Constant::Record { 4036 + arguments, 4037 + record_constructor: Some(resolved_record_constructor), 4038 + .. 4039 + } = resolved_record 4040 + && let ValueConstructorVariant::Record { name, .. } = 4041 + resolved_record_constructor.variant 4042 + { 4043 + (arguments, name) 4044 + } else { 4045 + self.problems.error(convert_unify_error( 4046 + UnifyError::CouldNotUnify { 4047 + expected: expected_type.clone(), 4048 + given: typed_record_type, 4049 + situation: None, 4050 + }, 4051 + record.base.location(), 4052 + )); 4053 + return self.new_invalid_constant(location); 4054 + }; 4049 4055 4050 4056 // Check that the variant being spread matches the constructor variant 4051 4057 // For multi-variant custom types, you can't spread Dog to create Cat 4052 - if tag != base_tag { 4058 + if constructor_tag != updated_record_tag { 4053 4059 self.problems.error(Error::UnsafeRecordUpdate { 4054 4060 location: record.base.location(), 4055 4061 reason: UnsafeRecordUpdateReason::WrongVariant { 4056 - constructed_variant: tag, 4057 - spread_variant: base_tag, 4062 + constructed_variant: constructor_tag, 4063 + spread_variant: updated_record_tag, 4058 4064 }, 4059 4065 }); 4060 4066 return self.new_invalid_constant(location); ··· 4179 4185 name, 4180 4186 arguments: final_arguments, 4181 4187 type_: expected_type, 4182 - tag, 4183 4188 field_map: Inferred::Known(field_map), 4184 4189 record_constructor: Some(Box::new(constructor)), 4185 4190 } ··· 4205 4210 } 4206 4211 }; 4207 4212 4208 - let (tag, field_map) = match &constructor.variant { 4209 - ValueConstructorVariant::Record { 4210 - name, field_map, .. 4211 - } => ( 4212 - name.clone(), 4213 - match field_map { 4214 - Some(field_map) => Inferred::Known(field_map.clone()), 4215 - None => Inferred::Unknown, 4216 - }, 4217 - ), 4213 + let field_map = match &constructor.variant { 4214 + ValueConstructorVariant::Record { field_map, .. } => match field_map { 4215 + Some(field_map) => Inferred::Known(field_map.clone()), 4216 + None => Inferred::Unknown, 4217 + }, 4218 4218 4219 4219 ValueConstructorVariant::ModuleFn { .. } 4220 4220 | ValueConstructorVariant::LocalVariable { .. } => { ··· 4235 4235 name, 4236 4236 arguments: vec![], 4237 4237 type_: constructor.type_.clone(), 4238 - tag, 4239 4238 field_map, 4240 4239 record_constructor: Some(Box::new(constructor)), 4241 4240 } ··· 4361 4360 module: Option<(EcoString, SrcSpan)>, 4362 4361 location: SrcSpan, 4363 4362 name: EcoString, 4364 - mut arguments: Vec<CallArg<Constant<(), ()>>>, 4365 - ) -> Constant<Arc<Type>, EcoString> { 4363 + mut arguments: Vec<CallArg<UntypedConstant>>, 4364 + ) -> Constant<Arc<Type>> { 4366 4365 // We start by inferring the value constructor. If we can't do that we 4367 4366 // immediately fail and return an invalid node. 4368 4367 // TODO: in future we might want to make this more fault tolerant and ··· 4383 4382 } 4384 4383 }; 4385 4384 4386 - let (tag, field_map) = match &constructor.variant { 4387 - ValueConstructorVariant::Record { 4388 - name, field_map, .. 4389 - } => (name.clone(), field_map.clone()), 4385 + let field_map = match &constructor.variant { 4386 + ValueConstructorVariant::Record { field_map, .. } => field_map.clone(), 4390 4387 4391 4388 ValueConstructorVariant::ModuleFn { .. } 4392 4389 | ValueConstructorVariant::LocalVariable { .. } => { ··· 4482 4479 name, 4483 4480 arguments, 4484 4481 type_: return_type, 4485 - tag, 4486 4482 field_map: match field_map { 4487 4483 Some(field_map) => Inferred::Known(field_map), 4488 4484 None => Inferred::Unknown, ··· 5531 5527 module, 5532 5528 name, 5533 5529 arguments, 5534 - tag, 5535 5530 type_: _, 5536 5531 field_map, 5537 5532 record_constructor, ··· 5540 5535 module, 5541 5536 name, 5542 5537 arguments, 5543 - tag, 5544 5538 type_: new_type, 5545 5539 field_map, 5546 5540 record_constructor, ··· 5553 5547 name, 5554 5548 record, 5555 5549 arguments, 5556 - tag, 5557 5550 type_: _, 5558 5551 field_map, 5559 5552 } => Constant::RecordUpdate { ··· 5563 5556 name, 5564 5557 record, 5565 5558 arguments, 5566 - tag, 5567 5559 type_: new_type, 5568 5560 field_map, 5569 5561 },
+4 -12
language-server/src/code_action.rs
··· 1916 1916 module: &'ast Option<(EcoString, SrcSpan)>, 1917 1917 name: &'ast EcoString, 1918 1918 arguments: &'ast Vec<CallArg<ast::TypedConstant>>, 1919 - tag: &'ast EcoString, 1920 1919 type_: &'ast Arc<Type>, 1921 1920 field_map: &'ast Inferred<FieldMap>, 1922 1921 record_constructor: &'ast Option<Box<ValueConstructor>>, ··· 1939 1938 module, 1940 1939 name, 1941 1940 arguments, 1942 - tag, 1943 1941 type_, 1944 1942 field_map, 1945 1943 record_constructor, ··· 2153 2151 module: &'ast Option<(EcoString, SrcSpan)>, 2154 2152 name: &'ast EcoString, 2155 2153 arguments: &'ast Vec<CallArg<ast::TypedConstant>>, 2156 - tag: &'ast EcoString, 2157 2154 type_: &'ast Arc<Type>, 2158 2155 field_map: &'ast Inferred<FieldMap>, 2159 2156 record_constructor: &'ast Option<Box<ValueConstructor>>, ··· 2176 2173 module, 2177 2174 name, 2178 2175 arguments, 2179 - tag, 2180 2176 type_, 2181 2177 field_map, 2182 2178 record_constructor, ··· 2390 2386 module: &'ast Option<(EcoString, SrcSpan)>, 2391 2387 name: &'ast EcoString, 2392 2388 arguments: &'ast Vec<CallArg<ast::TypedConstant>>, 2393 - _tag: &'ast EcoString, 2394 - _type_: &'ast Arc<Type>, 2395 - _field_map: &'ast Inferred<FieldMap>, 2389 + type_: &'ast Arc<Type>, 2390 + field_map: &'ast Inferred<FieldMap>, 2396 2391 record_constructor: &'ast Option<Box<ValueConstructor>>, 2397 2392 ) { 2398 2393 if module.is_none() ··· 2417 2412 module, 2418 2413 name, 2419 2414 arguments, 2420 - _tag, 2421 - _type_, 2422 - _field_map, 2415 + type_, 2416 + field_map, 2423 2417 record_constructor, 2424 2418 ); 2425 2419 } ··· 2625 2619 module: &'ast Option<(EcoString, SrcSpan)>, 2626 2620 name: &'ast EcoString, 2627 2621 arguments: &'ast Vec<CallArg<ast::TypedConstant>>, 2628 - tag: &'ast EcoString, 2629 2622 type_: &'ast Arc<Type>, 2630 2623 field_map: &'ast Inferred<FieldMap>, 2631 2624 record_constructor: &'ast Option<Box<ValueConstructor>>, ··· 2646 2639 module, 2647 2640 name, 2648 2641 arguments, 2649 - tag, 2650 2642 type_, 2651 2643 field_map, 2652 2644 record_constructor,
+1 -1
language-server/src/engine.rs
··· 1571 1571 } 1572 1572 1573 1573 fn hover_for_module_constant( 1574 - constant: &ModuleConstant<Arc<Type>, EcoString>, 1574 + constant: &ModuleConstant<Arc<Type>>, 1575 1575 line_numbers: LineNumbers, 1576 1576 module: &Module, 1577 1577 ) -> Hover {
-4
language-server/src/reference.rs
··· 944 944 module: &'ast Option<(EcoString, SrcSpan)>, 945 945 name: &'ast EcoString, 946 946 arguments: &'ast Vec<ast::CallArg<ast::TypedConstant>>, 947 - tag: &'ast EcoString, 948 947 type_: &'ast std::sync::Arc<Type>, 949 948 field_map: &'ast analyse::Inferred<gleam_core::type_::FieldMap>, 950 949 record_constructor: &'ast Option<Box<ValueConstructor>>, ··· 964 963 module, 965 964 name, 966 965 arguments, 967 - tag, 968 966 type_, 969 967 field_map, 970 968 record_constructor, ··· 979 977 name: &'ast EcoString, 980 978 record: &'ast ast::RecordBeingUpdated<ast::TypedConstant>, 981 979 arguments: &'ast [ast::RecordUpdateArg<ast::TypedConstant>], 982 - tag: &'ast EcoString, 983 980 type_: &'ast std::sync::Arc<Type>, 984 981 field_map: &'ast analyse::Inferred<gleam_core::type_::FieldMap>, 985 982 ) { ··· 1000 997 name, 1001 998 record, 1002 999 arguments, 1003 - tag, 1004 1000 type_, 1005 1001 field_map, 1006 1002 )