alpha
Login
or
Join now
nandi.uk
/
gleam
Star
2
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Fork of daniellemaywood.uk/gleam — Wasm codegen work
Star
2
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Overview
Issues
Pulls
Pipelines
remove record tag from constants
author
Giacomo Cavalieri
committer
Louis Pilfold
date
2 months ago
(May 21, 2026, 12:59 PM +0100)
commit
761e961e
761e961e333006501a56d58e24c3a3b0d0d23dfa
parent
43465204
4346520460cb69b32ab6ac948093e380bb71d54a
change-id
zxrtnsok
zxrtnsokknwmvzqrznrqwptwzunplskm
+132
-162
24 changed files
Expand all
Collapse all
Unified
Split
compiler-core
src
analyse.rs
ast
constant.rs
typed.rs
untyped.rs
visit.rs
ast.rs
ast_folder.rs
call_graph.rs
erlang.rs
format.rs
javascript
expression.rs
metadata
tests.rs
metadata.rs
parse
snapshots
gleam_core__parse__tests__byte_order_mark_module.snap
gleam_core__parse__tests__const_record_update_all_fields.snap
gleam_core__parse__tests__const_record_update_basic.snap
gleam_core__parse__tests__const_record_update_only.snap
gleam_core__parse__tests__const_record_update_with_module.snap
parse.rs
type_
expression.rs
type_.rs
language-server
src
code_action.rs
engine.rs
reference.rs
+1
-1
compiler-core/src/analyse.rs
View file
Reviewed
···
1848
1848
}
1849
1849
1850
1850
fn generalise_module_constant(
1851
1851
-
constant: ModuleConstant<Arc<Type>, EcoString>,
1851
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
View file
Reviewed
···
1031
1031
}
1032
1032
}
1033
1033
1034
1034
-
pub type UntypedModuleConstant = ModuleConstant<(), ()>;
1035
1035
-
pub type TypedModuleConstant = ModuleConstant<Arc<Type>, EcoString>;
1034
1034
+
pub type UntypedModuleConstant = ModuleConstant<()>;
1035
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
1046
-
pub struct ModuleConstant<T, ConstantRecordTag> {
1046
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
1055
-
pub value: Box<Constant<T, ConstantRecordTag>>,
1055
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
1198
-
pub type UntypedDefinition = Definition<(), UntypedExpr, (), ()>;
1198
1198
+
pub type UntypedDefinition = Definition<(), UntypedExpr, ()>;
1199
1199
1200
1200
#[derive(Debug, Clone, PartialEq, Eq)]
1201
1201
-
pub enum Definition<T, Expr, ConstantRecordTag, PackageName> {
1201
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
1206
-
ModuleConstant(ModuleConstant<T, ConstantRecordTag>),
1206
1206
+
ModuleConstant(ModuleConstant<T>),
1207
1207
}
1208
1208
1209
1209
-
impl<A, B, C, E> Definition<A, B, C, E> {
1209
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
1866
-
pub type TypedClause = Clause<TypedExpr, Arc<Type>, EcoString>;
1866
1866
+
pub type TypedClause = Clause<TypedExpr, Arc<Type>>;
1867
1867
1868
1868
-
pub type UntypedClause = Clause<UntypedExpr, (), ()>;
1868
1868
+
pub type UntypedClause = Clause<UntypedExpr, ()>;
1869
1869
1870
1870
#[derive(Debug, Clone, PartialEq, Eq)]
1871
1871
-
pub struct Clause<Expr, Type, RecordTag> {
1871
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
1875
-
pub guard: Option<ClauseGuard<Type, RecordTag>>,
1875
1875
+
pub guard: Option<ClauseGuard<Type>>,
1876
1876
pub then: Expr,
1877
1877
}
1878
1878
1879
1879
-
impl<A, B, C> Clause<A, B, C> {
1879
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
2279
-
pub type UntypedClauseGuard = ClauseGuard<(), ()>;
2280
2280
-
pub type TypedClauseGuard = ClauseGuard<Arc<Type>, EcoString>;
2279
2279
+
pub type UntypedClauseGuard = ClauseGuard<()>;
2280
2280
+
pub type TypedClauseGuard = ClauseGuard<Arc<Type>>;
2281
2281
2282
2282
#[derive(Debug, Clone, PartialEq, Eq)]
2283
2283
-
pub enum ClauseGuard<Type, RecordTag> {
2283
2283
+
pub enum ClauseGuard<Type> {
2284
2284
Block {
2285
2285
location: SrcSpan,
2286
2286
-
value: Box<ClauseGuard<Type, RecordTag>>,
2286
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
2338
-
literal: Constant<Type, RecordTag>,
2338
2338
+
literal: Constant<Type>,
2339
2339
},
2340
2340
2341
2341
-
Constant(Constant<Type, RecordTag>),
2341
2341
+
Constant(Constant<Type>),
2342
2342
2343
2343
Invalid {
2344
2344
location: SrcSpan,
···
2346
2346
},
2347
2347
}
2348
2348
2349
2349
-
impl<A, B> ClauseGuard<A, B> {
2349
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
View file
Reviewed
···
2
2
use crate::analyse::Inferred;
3
3
use crate::type_::{FieldMap, HasType};
4
4
5
5
-
pub type TypedConstant = Constant<Arc<Type>, EcoString>;
6
6
-
pub type UntypedConstant = Constant<(), ()>;
5
5
+
pub type TypedConstant = Constant<Arc<Type>>;
6
6
+
pub type UntypedConstant = Constant<()>;
7
7
8
8
-
// TODO: remove RecordTag paramter
9
8
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
10
10
-
pub enum Constant<T, RecordTag> {
9
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
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
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
476
+
477
477
+
/// If the constant is a record or record update this returns its tag.
478
478
+
/// It might return `None` if the record constructor couldn't be inferred.
479
479
+
pub(crate) fn constant_record_tag(&self) -> Option<EcoString> {
480
480
+
if let Constant::Record {
481
481
+
record_constructor: Some(constructor),
482
482
+
..
483
483
+
} = self
484
484
+
&& let ValueConstructorVariant::Record { name, .. } = &constructor.variant
485
485
+
{
486
486
+
Some(name.clone())
487
487
+
} else if let Constant::RecordUpdate { name, .. } = self {
488
488
+
Some(name.clone())
489
489
+
} else {
490
490
+
None
491
491
+
}
492
492
+
}
479
493
}
480
494
481
495
impl HasType for TypedConstant {
···
484
498
}
485
499
}
486
500
487
487
-
impl<A, B> Constant<A, B> {
501
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
525
-
impl<A, B> HasLocation for Constant<A, B> {
539
539
+
impl<A> HasLocation for Constant<A> {
526
540
fn location(&self) -> SrcSpan {
527
541
self.location()
528
542
}
529
543
}
530
544
531
531
-
impl<A, B> bit_array::GetLiteralValue for Constant<A, B> {
545
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
View file
Reviewed
···
94
94
location: SrcSpan,
95
95
type_: Arc<Type>,
96
96
subjects: Vec<Self>,
97
97
-
clauses: Vec<Clause<Self, Arc<Type>, EcoString>>,
97
97
+
clauses: Vec<Clause<Self, Arc<Type>>>,
98
98
compiled_case: CompiledCase,
99
99
},
100
100
+1
-1
compiler-core/src/ast/untyped.rs
View file
Reviewed
···
75
75
location: SrcSpan,
76
76
subjects: Vec<Self>,
77
77
// None if the case expression is missing a body.
78
78
-
clauses: Option<Vec<Clause<Self, (), ()>>>,
78
78
+
clauses: Option<Vec<Clause<Self, ()>>>,
79
79
},
80
80
81
81
FieldAccess {
-10
compiler-core/src/ast/visit.rs
View file
Reviewed
···
741
741
module: &'ast Option<(EcoString, SrcSpan)>,
742
742
name: &'ast EcoString,
743
743
arguments: &'ast Vec<CallArg<TypedConstant>>,
744
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
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
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
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
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
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
1180
-
tag,
1181
1174
type_,
1182
1175
field_map,
1183
1176
record_constructor,
···
1186
1179
module,
1187
1180
name,
1188
1181
arguments,
1189
1189
-
tag,
1190
1182
type_,
1191
1183
field_map,
1192
1184
record_constructor,
···
1198
1190
name,
1199
1191
record,
1200
1192
arguments,
1201
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
1211
-
tag,
1212
1202
type_,
1213
1203
field_map,
1214
1204
),
-8
compiler-core/src/ast_folder.rs
View file
Reviewed
···
993
993
module,
994
994
name,
995
995
arguments,
996
996
-
tag: (),
997
996
type_: (),
998
997
field_map: _,
999
998
record_constructor: _,
···
1006
1005
name,
1007
1006
record,
1008
1007
arguments,
1009
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
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
1150
-
tag: (),
1151
1147
type_: (),
1152
1148
field_map: Inferred::Unknown,
1153
1149
}
···
1236
1232
module,
1237
1233
name,
1238
1234
arguments,
1239
1239
-
tag,
1240
1235
type_,
1241
1236
field_map,
1242
1237
record_constructor,
···
1253
1248
module,
1254
1249
name,
1255
1250
arguments,
1256
1256
-
tag,
1257
1251
type_,
1258
1252
field_map,
1259
1253
record_constructor,
···
1267
1261
name,
1268
1262
record,
1269
1263
arguments,
1270
1270
-
tag,
1271
1264
type_,
1272
1265
field_map,
1273
1266
} => {
···
1290
1283
name,
1291
1284
record,
1292
1285
arguments,
1293
1293
-
tag,
1294
1286
type_,
1295
1287
field_map,
1296
1288
}
+2
-2
compiler-core/src/call_graph.rs
View file
Reviewed
···
8
8
Result,
9
9
ast::{
10
10
AssignName, AssignmentKind, BitArrayOption, BitArraySize, ClauseGuard, Constant, Pattern,
11
11
-
SrcSpan, Statement, UntypedClauseGuard, UntypedExpr, UntypedFunction,
11
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
456
-
fn constant(&mut self, constant: &'a Constant<(), ()>) {
456
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
View file
Reviewed
···
1797
1797
),
1798
1798
1799
1799
Constant::Record {
1800
1800
-
tag,
1801
1801
-
type_,
1802
1802
-
arguments,
1803
1803
-
..
1804
1804
-
} if arguments.is_empty() => match type_.deref() {
1805
1805
-
Type::Fn { arguments, .. } => record_constructor_function(tag, arguments.len()),
1806
1806
-
Type::Named { .. } | Type::Var { .. } | Type::Tuple { .. } => {
1807
1807
-
atom_string(to_snake_case(tag))
1800
1800
+
type_, arguments, ..
1801
1801
+
} if arguments.is_empty() => {
1802
1802
+
let tag = literal
1803
1803
+
.constant_record_tag()
1804
1804
+
.expect("record without inferred constructor made it to code generation");
1805
1805
+
1806
1806
+
match type_.deref() {
1807
1807
+
Type::Fn { arguments, .. } => record_constructor_function(tag, arguments.len()),
1808
1808
+
Type::Named { .. } | Type::Var { .. } | Type::Tuple { .. } => {
1809
1809
+
atom_string(to_snake_case(&tag))
1810
1810
+
}
1808
1811
}
1809
1809
-
},
1812
1812
+
}
1810
1813
1811
1811
-
Constant::Record { tag, arguments, .. } => {
1814
1814
+
Constant::Record { arguments, .. } => {
1815
1815
+
let tag = literal
1816
1816
+
.constant_record_tag()
1817
1817
+
.expect("record without inferred constructor made it to code generation");
1818
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
1816
-
let tag = atom_string(to_snake_case(tag));
1823
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
1840
-
fn record_constructor_function(tag: &EcoString, arity: usize) -> Document<'_> {
1847
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
1846
-
.append(atom_string(to_snake_case(tag)))
1853
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
2575
-
} => record_constructor_function(name, *arity as usize),
2582
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
View file
Reviewed
···
469
469
}
470
470
}
471
471
472
472
-
fn const_expr<'a, A, B>(&mut self, value: &'a Constant<A, B>) -> Document<'a> {
472
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
596
-
fn const_list<'a, A, B>(
596
596
+
fn const_list<'a, A>(
597
597
&mut self,
598
598
-
elements: &'a [Constant<A, B>],
598
598
+
elements: &'a [Constant<A>],
599
599
location: &SrcSpan,
600
600
-
tail: &'a Option<Box<Constant<A, B>>>,
600
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
695
-
pub fn const_tuple<'a, A, B>(
695
695
+
pub fn const_tuple<'a, A>(
696
696
&mut self,
697
697
-
elements: &'a [Constant<A, B>],
697
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
1543
-
pub fn const_record_update<'a, A, B>(
1543
1543
+
pub fn const_record_update<'a, A>(
1544
1544
&mut self,
1545
1545
module: &Option<(EcoString, SrcSpan)>,
1546
1546
name: &'a EcoString,
1547
1547
-
record: &'a RecordBeingUpdated<Constant<A, B>>,
1548
1548
-
arguments: &'a [RecordUpdateArg<Constant<A, B>>],
1547
1547
+
record: &'a RecordBeingUpdated<Constant<A>>,
1548
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
2723
-
fn constant_call_arg<'a, A, B>(
2724
2724
-
&mut self,
2725
2725
-
argument: &'a CallArg<Constant<A, B>>,
2726
2726
-
) -> Document<'a> {
2723
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
3183
-
fn append_as_message_constant<'a, A, B>(
3180
3180
+
fn append_as_message_constant<'a, A>(
3184
3181
&mut self,
3185
3182
doc: Document<'a>,
3186
3186
-
message: Option<&'a Constant<A, B>>,
3183
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
3672
-
fn constant_call_arg_formatting<A, B>(
3673
3673
-
argument: &CallArg<Constant<A, B>>,
3674
3674
-
) -> CallArgFormatting<'_, Constant<A, B>> {
3669
3669
+
fn constant_call_arg_formatting<A>(
3670
3670
+
argument: &CallArg<Constant<A>>,
3671
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
View file
Reviewed
···
2109
2109
arguments,
2110
2110
module,
2111
2111
name,
2112
2112
-
tag,
2113
2112
type_,
2114
2113
..
2115
2114
} => {
2115
2115
+
let tag = expression
2116
2116
+
.constant_record_tag()
2117
2117
+
.expect("record without inferred constructor made it to code generation");
2118
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
2482
-
tag,
2483
2485
type_,
2484
2486
..
2485
2487
} => {
2488
2488
+
let tag = expression
2489
2489
+
.constant_record_tag()
2490
2490
+
.expect("record without inferred constructor made it to code generation");
2491
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
View file
Reviewed
···
335
335
module,
336
336
name,
337
337
arguments,
338
338
-
tag,
339
338
type_,
340
339
field_map,
341
340
record_constructor,
···
359
358
},
360
359
)
361
360
.collect(),
362
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
379
-
tag,
380
377
type_,
381
378
field_map,
382
379
} => Constant::RecordUpdate {
···
402
399
},
403
400
)
404
401
.collect(),
405
405
-
tag,
406
402
type_: self.type_(type_),
407
403
field_map,
408
404
},
-1
compiler-core/src/metadata/tests.rs
View file
Reviewed
···
1191
1191
},
1192
1192
},
1193
1193
],
1194
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
View file
Reviewed
···
204
204
// Test Interface
205
205
//
206
206
#[cfg(test)]
207
207
-
pub fn parse_const_value(src: &str) -> Result<Constant<(), ()>, ParseError> {
207
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
3563
-
tag: (),
3564
3563
type_: (),
3565
3564
field_map: Inferred::Unknown,
3566
3565
}))
···
3588
3587
module,
3589
3588
name,
3590
3589
arguments,
3591
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
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
View file
Reviewed
···
85
85
},
86
86
},
87
87
],
88
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
View file
Reviewed
···
222
222
implicit: None,
223
223
},
224
224
],
225
225
-
tag: (),
226
225
type_: (),
227
226
field_map: Unknown,
228
227
record_constructor: None,
···
327
326
},
328
327
},
329
328
],
330
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
View file
Reviewed
···
173
173
implicit: None,
174
174
},
175
175
],
176
176
-
tag: (),
177
176
type_: (),
178
177
field_map: Unknown,
179
178
record_constructor: None,
···
249
248
},
250
249
},
251
250
],
252
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
View file
Reviewed
···
173
173
implicit: None,
174
174
},
175
175
],
176
176
-
tag: (),
177
176
type_: (),
178
177
field_map: Unknown,
179
178
record_constructor: None,
···
234
233
},
235
234
},
236
235
arguments: [],
237
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
View file
Reviewed
···
85
85
},
86
86
},
87
87
],
88
88
-
tag: (),
89
88
type_: (),
90
89
field_map: Unknown,
91
90
},
+1
-1
compiler-core/src/type_.rs
View file
Reviewed
···
714
714
location: SrcSpan,
715
715
module: EcoString,
716
716
name: EcoString,
717
717
-
literal: Constant<Arc<Type>, EcoString>,
717
717
+
literal: Constant<Arc<Type>>,
718
718
implementations: Implementations,
719
719
},
720
720
+33
-41
compiler-core/src/type_/expression.rs
View file
Reviewed
···
3958
3958
}
3959
3959
};
3960
3960
3961
3961
-
let (tag, field_map) = match &constructor.variant {
3961
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
4035
-
let (base_arguments, base_tag) =
4036
4036
-
if let Constant::Record { arguments, tag, .. } = resolved_record {
4037
4037
-
(arguments, tag)
4038
4038
-
} else {
4039
4039
-
self.problems.error(convert_unify_error(
4040
4040
-
UnifyError::CouldNotUnify {
4041
4041
-
expected: expected_type.clone(),
4042
4042
-
given: typed_record_type,
4043
4043
-
situation: None,
4044
4044
-
},
4045
4045
-
record.base.location(),
4046
4046
-
));
4047
4047
-
return self.new_invalid_constant(location);
4048
4048
-
};
4035
4035
+
let (base_arguments, updated_record_tag) = if let Constant::Record {
4036
4036
+
arguments,
4037
4037
+
record_constructor: Some(resolved_record_constructor),
4038
4038
+
..
4039
4039
+
} = resolved_record
4040
4040
+
&& let ValueConstructorVariant::Record { name, .. } =
4041
4041
+
resolved_record_constructor.variant
4042
4042
+
{
4043
4043
+
(arguments, name)
4044
4044
+
} else {
4045
4045
+
self.problems.error(convert_unify_error(
4046
4046
+
UnifyError::CouldNotUnify {
4047
4047
+
expected: expected_type.clone(),
4048
4048
+
given: typed_record_type,
4049
4049
+
situation: None,
4050
4050
+
},
4051
4051
+
record.base.location(),
4052
4052
+
));
4053
4053
+
return self.new_invalid_constant(location);
4054
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
4052
-
if tag != base_tag {
4058
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
4056
-
constructed_variant: tag,
4057
4057
-
spread_variant: base_tag,
4062
4062
+
constructed_variant: constructor_tag,
4063
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
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
4208
-
let (tag, field_map) = match &constructor.variant {
4209
4209
-
ValueConstructorVariant::Record {
4210
4210
-
name, field_map, ..
4211
4211
-
} => (
4212
4212
-
name.clone(),
4213
4213
-
match field_map {
4214
4214
-
Some(field_map) => Inferred::Known(field_map.clone()),
4215
4215
-
None => Inferred::Unknown,
4216
4216
-
},
4217
4217
-
),
4213
4213
+
let field_map = match &constructor.variant {
4214
4214
+
ValueConstructorVariant::Record { field_map, .. } => match field_map {
4215
4215
+
Some(field_map) => Inferred::Known(field_map.clone()),
4216
4216
+
None => Inferred::Unknown,
4217
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
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
4364
-
mut arguments: Vec<CallArg<Constant<(), ()>>>,
4365
4365
-
) -> Constant<Arc<Type>, EcoString> {
4363
4363
+
mut arguments: Vec<CallArg<UntypedConstant>>,
4364
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
4386
-
let (tag, field_map) = match &constructor.variant {
4387
4387
-
ValueConstructorVariant::Record {
4388
4388
-
name, field_map, ..
4389
4389
-
} => (name.clone(), field_map.clone()),
4385
4385
+
let field_map = match &constructor.variant {
4386
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
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
5534
-
tag,
5535
5530
type_: _,
5536
5531
field_map,
5537
5532
record_constructor,
···
5540
5535
module,
5541
5536
name,
5542
5537
arguments,
5543
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
5556
-
tag,
5557
5550
type_: _,
5558
5551
field_map,
5559
5552
} => Constant::RecordUpdate {
···
5563
5556
name,
5564
5557
record,
5565
5558
arguments,
5566
5566
-
tag,
5567
5559
type_: new_type,
5568
5560
field_map,
5569
5561
},
+4
-12
language-server/src/code_action.rs
View file
Reviewed
···
1916
1916
module: &'ast Option<(EcoString, SrcSpan)>,
1917
1917
name: &'ast EcoString,
1918
1918
arguments: &'ast Vec<CallArg<ast::TypedConstant>>,
1919
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
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
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
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
2393
-
_tag: &'ast EcoString,
2394
2394
-
_type_: &'ast Arc<Type>,
2395
2395
-
_field_map: &'ast Inferred<FieldMap>,
2389
2389
+
type_: &'ast Arc<Type>,
2390
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
2420
-
_tag,
2421
2421
-
_type_,
2422
2422
-
_field_map,
2415
2415
+
type_,
2416
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
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
2649
-
tag,
2650
2642
type_,
2651
2643
field_map,
2652
2644
record_constructor,
+1
-1
language-server/src/engine.rs
View file
Reviewed
···
1571
1571
}
1572
1572
1573
1573
fn hover_for_module_constant(
1574
1574
-
constant: &ModuleConstant<Arc<Type>, EcoString>,
1574
1574
+
constant: &ModuleConstant<Arc<Type>>,
1575
1575
line_numbers: LineNumbers,
1576
1576
module: &Module,
1577
1577
) -> Hover {
-4
language-server/src/reference.rs
View file
Reviewed
···
944
944
module: &'ast Option<(EcoString, SrcSpan)>,
945
945
name: &'ast EcoString,
946
946
arguments: &'ast Vec<ast::CallArg<ast::TypedConstant>>,
947
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
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
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
1003
-
tag,
1004
1000
type_,
1005
1001
field_map,
1006
1002
)