compiler-core
src
ast
language_server
parse
type_
···
6
6
use crate::build::{ExpressionPosition, Origin, Target};
7
7
use crate::config::PackageConfig;
8
8
use crate::line_numbers::LineNumbers;
9
9
-
use crate::type_::error::{VariableDeclarationKind, VariableOrigin};
9
9
+
use crate::type_::error::{VariableDeclaration, VariableOrigin, VariableSyntax};
10
10
use crate::type_::expression::{FunctionDefinition, Purity};
11
11
use crate::type_::{Deprecation, PRELUDE_MODULE_NAME, Problems};
12
12
use crate::warning::WarningEmitter;
···
327
327
publicity: Publicity::Private,
328
328
variant: ValueConstructorVariant::LocalVariable {
329
329
location: SrcSpan { start: 5, end: 11 },
330
330
-
origin: VariableOrigin::Variable {
331
331
-
name: "wibble".into(),
332
332
-
kind: VariableDeclarationKind::LetPattern,
330
330
+
origin: VariableOrigin {
331
331
+
syntax: VariableSyntax::Variable("wibble".into()),
332
332
+
declaration: VariableDeclaration::LetPattern,
333
333
},
334
334
},
335
335
type_: type_::int(),
···
19
19
strings::to_snake_case,
20
20
type_::{
21
21
self, FieldMap, ModuleValueConstructor, Type, TypeVar, TypedCallArg, ValueConstructor,
22
22
-
error::{ModuleSuggestion, VariableDeclarationKind, VariableOrigin},
22
22
+
error::{ModuleSuggestion, VariableDeclaration, VariableOrigin},
23
23
printer::{Names, Printer},
24
24
},
25
25
};
···
5968
5968
return;
5969
5969
};
5970
5970
5971
5971
-
// We can only inline it if it comes from a regular variable pattern,
5972
5972
-
// not a complex pattern or generated assignment. We can also only inline
5973
5973
-
// variables assigned by `let` statements, as it doesn't make sense to do
5974
5974
-
// so with any other kind of variable.
5975
5975
-
match origin {
5976
5976
-
VariableOrigin::Variable {
5977
5977
-
kind: VariableDeclarationKind::LetPattern,
5978
5978
-
..
5979
5979
-
} => {}
5980
5980
-
VariableOrigin::Variable { .. }
5981
5981
-
| VariableOrigin::LabelShorthand(_)
5982
5982
-
| VariableOrigin::AssignmentPattern
5983
5983
-
| VariableOrigin::Generated => return,
5971
5971
+
// We can only inline variables assigned by `let` statements, as it
5972
5972
+
//doesn't make sense to do so with any other kind of variable.
5973
5973
+
match origin.declaration {
5974
5974
+
VariableDeclaration::LetPattern => {}
5975
5975
+
VariableDeclaration::UsePattern
5976
5976
+
| VariableDeclaration::ClausePattern
5977
5977
+
| VariableDeclaration::FunctionParameter
5978
5978
+
| VariableDeclaration::Generated => return,
5984
5979
}
5985
5980
5986
5981
self.maybe_inline(*location);
···
5993
5988
_type: &'ast Arc<Type>,
5994
5989
origin: &'ast VariableOrigin,
5995
5990
) {
5996
5996
-
// We can only inline it if it is a regular variable pattern
5997
5997
-
match origin {
5998
5998
-
VariableOrigin::Variable {
5999
5999
-
kind: VariableDeclarationKind::LetPattern,
6000
6000
-
..
6001
6001
-
} => {}
6002
6002
-
VariableOrigin::Variable { .. }
6003
6003
-
| VariableOrigin::LabelShorthand(_)
6004
6004
-
| VariableOrigin::AssignmentPattern
6005
6005
-
| VariableOrigin::Generated => return,
5991
5991
+
// We can only inline variables assigned by `let` statements, as it
5992
5992
+
//doesn't make sense to do so with any other kind of variable.
5993
5993
+
match origin.declaration {
5994
5994
+
VariableDeclaration::LetPattern => {}
5995
5995
+
VariableDeclaration::UsePattern
5996
5996
+
| VariableDeclaration::ClausePattern
5997
5997
+
| VariableDeclaration::FunctionParameter
5998
5998
+
| VariableDeclaration::Generated => return,
6006
5999
}
6007
6000
6008
6001
let range = self.edits.src_span_to_lsp_range(*location);
···
19
19
type_::{
20
20
self, Deprecation, ModuleInterface, Type, TypeConstructor, ValueConstructor,
21
21
ValueConstructorVariant,
22
22
-
error::{Named, VariableOrigin},
22
22
+
error::{Named, VariableSyntax},
23
23
printer::Printer,
24
24
},
25
25
};
···
637
637
Ok(match reference_for_ast_node(found, ¤t_module.name) {
638
638
Some(Referenced::LocalVariable {
639
639
location, origin, ..
640
640
-
}) if location.contains(byte_index) => match origin {
641
641
-
Some(VariableOrigin::Generated) => None,
640
640
+
}) if location.contains(byte_index) => match origin.map(|origin| origin.syntax) {
641
641
+
Some(VariableSyntax::Generated) => None,
642
642
Some(
643
643
-
VariableOrigin::Variable { .. }
644
644
-
| VariableOrigin::AssignmentPattern
645
645
-
| VariableOrigin::LabelShorthand(_),
643
643
+
VariableSyntax::Variable { .. }
644
644
+
| VariableSyntax::AssignmentPattern
645
645
+
| VariableSyntax::LabelShorthand(_),
646
646
)
647
647
| None => success_response(location),
648
648
},
···
695
695
definition_location,
696
696
..
697
697
}) => {
698
698
-
let rename_kind = match origin {
699
699
-
Some(VariableOrigin::Generated) => return Ok(None),
700
700
-
Some(VariableOrigin::LabelShorthand(_)) => {
698
698
+
let rename_kind = match origin.map(|origin| origin.syntax) {
699
699
+
Some(VariableSyntax::Generated) => return Ok(None),
700
700
+
Some(VariableSyntax::LabelShorthand(_)) => {
701
701
VariableReferenceKind::LabelShorthand
702
702
}
703
703
Some(
704
704
-
VariableOrigin::AssignmentPattern | VariableOrigin::Variable { .. },
704
704
+
VariableSyntax::AssignmentPattern | VariableSyntax::Variable { .. },
705
705
)
706
706
| None => VariableReferenceKind::Variable,
707
707
};
···
774
774
origin,
775
775
definition_location,
776
776
location,
777
777
-
}) if location.contains(byte_index) => match origin {
778
778
-
Some(VariableOrigin::Generated) => None,
777
777
+
}) if location.contains(byte_index) => match origin.map(|origin| origin.syntax) {
778
778
+
Some(VariableSyntax::Generated) => None,
779
779
Some(
780
780
-
VariableOrigin::LabelShorthand(_)
781
781
-
| VariableOrigin::AssignmentPattern
782
782
-
| VariableOrigin::Variable { .. },
780
780
+
VariableSyntax::LabelShorthand(_)
781
781
+
| VariableSyntax::AssignmentPattern
782
782
+
| VariableSyntax::Variable { .. },
783
783
)
784
784
| None => {
785
785
let variable_references =
···
72
72
use crate::exhaustiveness::CompiledCase;
73
73
use crate::parse::extra::ModuleExtra;
74
74
use crate::type_::Deprecation;
75
75
-
use crate::type_::error::{VariableDeclarationKind, VariableOrigin};
75
75
+
use crate::type_::error::{VariableDeclaration, VariableOrigin, VariableSyntax};
76
76
use crate::type_::expression::{Implementations, Purity};
77
77
use crate::warning::{DeprecatedSyntaxWarning, WarningEmitter};
78
78
use camino::Utf8PathBuf;
···
1214
1214
SrcSpan { start, end },
1215
1215
);
1216
1216
}
1217
1217
-
_ => {
1218
1218
-
let kind = match position {
1219
1219
-
PatternPosition::LetAssignment => {
1220
1220
-
VariableDeclarationKind::LetPattern
1221
1221
-
}
1222
1222
-
PatternPosition::CaseClause => {
1223
1223
-
VariableDeclarationKind::ClausePattern
1224
1224
-
}
1225
1225
-
PatternPosition::UsePattern => VariableDeclarationKind::UsePattern,
1226
1226
-
};
1227
1227
-
Pattern::Variable {
1228
1228
-
origin: VariableOrigin::Variable {
1229
1229
-
name: name.clone(),
1230
1230
-
kind,
1231
1231
-
},
1232
1232
-
location: SrcSpan { start, end },
1233
1233
-
name,
1234
1234
-
type_: (),
1235
1235
-
}
1236
1236
-
}
1217
1217
+
_ => Pattern::Variable {
1218
1218
+
origin: VariableOrigin {
1219
1219
+
syntax: VariableSyntax::Variable(name.clone()),
1220
1220
+
declaration: position.to_declaration(),
1221
1221
+
},
1222
1222
+
location: SrcSpan { start, end },
1223
1223
+
name,
1224
1224
+
type_: (),
1225
1225
+
},
1237
1226
}
1238
1227
}
1239
1228
}
···
1913
1902
location: SrcSpan { start, end },
1914
1903
label: Some(name.clone()),
1915
1904
value: UntypedPattern::Variable {
1916
1916
-
origin: VariableOrigin::LabelShorthand(name.clone()),
1905
1905
+
origin: VariableOrigin {
1906
1906
+
syntax: VariableSyntax::LabelShorthand(name.clone()),
1907
1907
+
declaration: position.to_declaration(),
1908
1908
+
},
1917
1909
name,
1918
1910
location: SrcSpan { start, end },
1919
1911
type_: (),
···
4417
4409
}
4418
4410
4419
4411
#[derive(Debug, Clone, Copy)]
4420
4420
-
enum PatternPosition {
4412
4412
+
pub enum PatternPosition {
4421
4413
LetAssignment,
4422
4414
CaseClause,
4423
4415
UsePattern,
4424
4416
}
4417
4417
+
4418
4418
+
impl PatternPosition {
4419
4419
+
pub fn to_declaration(&self) -> VariableDeclaration {
4420
4420
+
match self {
4421
4421
+
PatternPosition::LetAssignment => VariableDeclaration::LetPattern,
4422
4422
+
PatternPosition::CaseClause => VariableDeclaration::ClausePattern,
4423
4423
+
PatternPosition::UsePattern => VariableDeclaration::UsePattern,
4424
4424
+
}
4425
4425
+
}
4426
4426
+
}
···
42
42
},
43
43
name: "x",
44
44
type_: (),
45
45
-
origin: Variable(
46
46
-
"x",
47
47
-
),
45
45
+
origin: VariableOrigin {
46
46
+
syntax: Variable(
47
47
+
"x",
48
48
+
),
49
49
+
declaration: ClausePattern,
50
50
+
},
48
51
},
49
52
Variable {
50
53
location: SrcSpan {
···
53
56
},
54
57
name: "y",
55
58
type_: (),
56
56
-
origin: Variable(
57
57
-
"y",
58
58
-
),
59
59
+
origin: VariableOrigin {
60
60
+
syntax: Variable(
61
61
+
"y",
62
62
+
),
63
63
+
declaration: ClausePattern,
64
64
+
},
59
65
},
60
66
],
61
67
alternative_patterns: [],
···
56
56
},
57
57
name: "tup",
58
58
type_: (),
59
59
-
origin: Variable(
60
60
-
"tup",
61
61
-
),
59
59
+
origin: VariableOrigin {
60
60
+
syntax: Variable(
61
61
+
"tup",
62
62
+
),
63
63
+
declaration: LetPattern,
64
64
+
},
62
65
},
63
66
kind: Let,
64
67
compiled_case: CompiledCase {
···
56
56
},
57
57
name: "tup",
58
58
type_: (),
59
59
-
origin: Variable(
60
60
-
"tup",
61
61
-
),
59
59
+
origin: VariableOrigin {
60
60
+
syntax: Variable(
61
61
+
"tup",
62
62
+
),
63
63
+
declaration: LetPattern,
64
64
+
},
62
65
},
63
66
kind: Let,
64
67
compiled_case: CompiledCase {
···
23
23
},
24
24
name: "a",
25
25
type_: (),
26
26
-
origin: Variable(
27
27
-
"a",
28
28
-
),
26
26
+
origin: VariableOrigin {
27
27
+
syntax: Variable(
28
28
+
"a",
29
29
+
),
30
30
+
declaration: LetPattern,
31
31
+
},
29
32
},
30
33
kind: Let,
31
34
compiled_case: CompiledCase {
···
48
48
},
49
49
name: "tup",
50
50
type_: (),
51
51
-
origin: Variable(
52
52
-
"tup",
53
53
-
),
51
51
+
origin: VariableOrigin {
52
52
+
syntax: Variable(
53
53
+
"tup",
54
54
+
),
55
55
+
declaration: LetPattern,
56
56
+
},
54
57
},
55
58
kind: Let,
56
59
compiled_case: CompiledCase {
···
48
48
},
49
49
name: "tup",
50
50
type_: (),
51
51
-
origin: Variable(
52
52
-
"tup",
53
53
-
),
51
51
+
origin: VariableOrigin {
52
52
+
syntax: Variable(
53
53
+
"tup",
54
54
+
),
55
55
+
declaration: LetPattern,
56
56
+
},
54
57
},
55
58
kind: Let,
56
59
compiled_case: CompiledCase {
···
1
1
---
2
2
source: compiler-core/src/parse/tests.rs
3
3
-
assertion_line: 440
4
3
expression: "let assert [x] = [2]"
5
5
-
snapshot_kind: text
6
4
---
7
5
[
8
6
Assignment(
···
41
39
},
42
40
name: "x",
43
41
type_: (),
44
44
-
origin: Variable(
45
45
-
"x",
46
46
-
),
42
42
+
origin: VariableOrigin {
43
43
+
syntax: Variable(
44
44
+
"x",
45
45
+
),
46
46
+
declaration: LetPattern,
47
47
+
},
47
48
},
48
49
],
49
50
tail: None,
···
1
1
---
2
2
source: compiler-core/src/parse/tests.rs
3
3
-
assertion_line: 445
4
3
expression: "let assert [x]: List(Int) = [2]"
5
5
-
snapshot_kind: text
6
4
---
7
5
[
8
6
Assignment(
···
41
39
},
42
40
name: "x",
43
41
type_: (),
44
44
-
origin: Variable(
45
45
-
"x",
46
46
-
),
42
42
+
origin: VariableOrigin {
43
43
+
syntax: Variable(
44
44
+
"x",
45
45
+
),
46
46
+
declaration: LetPattern,
47
47
+
},
47
48
},
48
49
],
49
50
tail: None,
···
789
789
#[must_use]
790
790
pub fn is_generated_variable(&self) -> bool {
791
791
match self {
792
792
-
ValueConstructorVariant::LocalVariable {
793
793
-
origin: VariableOrigin::Generated,
794
794
-
..
795
795
-
} => true,
796
796
-
ValueConstructorVariant::LocalVariable { .. } => false,
792
792
+
ValueConstructorVariant::LocalVariable { origin, .. } => {
793
793
+
matches!(origin.syntax, VariableSyntax::Generated)
794
794
+
}
797
795
ValueConstructorVariant::ModuleConstant { .. }
798
796
| ValueConstructorVariant::LocalConstant { .. }
799
797
| ValueConstructorVariant::ModuleFn { .. }
···
709
709
}
710
710
711
711
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
712
712
-
/// The origin of a variable. Used to determine how it can be ignored when unused.
713
713
-
pub enum VariableOrigin {
712
712
+
pub struct VariableOrigin {
713
713
+
pub syntax: VariableSyntax,
714
714
+
pub declaration: VariableDeclaration,
715
715
+
}
716
716
+
717
717
+
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
718
718
+
/// The syntax used to define a variable. Used to determine how it can be ignored
719
719
+
/// when unused.
720
720
+
pub enum VariableSyntax {
714
721
/// A variable that can be ignored by prefixing with an underscore, `_name`
715
715
-
Variable {
716
716
-
name: EcoString,
717
717
-
kind: VariableDeclarationKind,
718
718
-
},
722
722
+
Variable(EcoString),
719
723
/// A variable from label shorthand syntax, which can be ignored with an underscore: `label: _`
720
724
LabelShorthand(EcoString),
721
725
/// A variable from an assignment pattern, which can be ignored by removing `as name`,
···
725
729
}
726
730
727
731
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
728
728
-
pub enum VariableDeclarationKind {
732
732
+
/// The source of a variable, such as a `let` assignment, or function parameter.
733
733
+
pub enum VariableDeclaration {
729
734
LetPattern,
730
735
UsePattern,
731
736
ClausePattern,
732
737
FunctionParameter,
733
733
-
Implicit,
738
738
+
Generated,
734
739
}
735
740
736
741
impl VariableOrigin {
737
742
pub fn how_to_ignore(&self) -> Option<String> {
738
738
-
match self {
739
739
-
VariableOrigin::Variable { name, .. } => {
743
743
+
match &self.syntax {
744
744
+
VariableSyntax::Variable(name) => {
740
745
Some(format!("You can ignore it with an underscore: `_{name}`."))
741
746
}
742
742
-
VariableOrigin::LabelShorthand(label) => Some(format!(
747
747
+
VariableSyntax::LabelShorthand(label) => Some(format!(
743
748
"You can ignore it with an underscore: `{label}: _`."
744
749
)),
745
745
-
VariableOrigin::AssignmentPattern => Some("You can safely remove it.".to_string()),
746
746
-
VariableOrigin::Generated => None,
750
750
+
VariableSyntax::AssignmentPattern => Some("You can safely remove it.".to_string()),
751
751
+
VariableSyntax::Generated => None,
752
752
+
}
753
753
+
}
754
754
+
755
755
+
pub fn generated() -> Self {
756
756
+
Self {
757
757
+
syntax: VariableSyntax::Generated,
758
758
+
declaration: VariableDeclaration::Generated,
747
759
}
748
760
}
749
761
}
···
15
15
},
16
16
build::Target,
17
17
exhaustiveness::{self, CompileCaseResult, CompiledCase, Reachability},
18
18
+
parse::PatternPosition,
18
19
reference::ReferenceKind,
19
20
};
20
21
use hexpm::version::Version;
···
1760
1761
&self.current_function_definition,
1761
1762
&self.hydrator,
1762
1763
self.problems,
1764
1764
+
PatternPosition::LetAssignment,
1763
1765
);
1764
1766
1765
1767
let pattern = pattern_typer.infer_single_pattern(pattern, &value);
···
2111
2113
&self.current_function_definition,
2112
2114
&self.hydrator,
2113
2115
self.problems,
2116
2116
+
PatternPosition::CaseClause,
2114
2117
);
2115
2118
2116
2119
let typed_pattern = pattern_typer.infer_multi_pattern(pattern, subjects, location);
···
2977
2980
location: record_location,
2978
2981
name: RECORD_UPDATE_VARIABLE.into(),
2979
2982
type_: record_type.clone(),
2980
2980
-
origin: VariableOrigin::Generated,
2983
2983
+
origin: VariableOrigin::generated(),
2981
2984
},
2982
2985
annotation: None,
2983
2986
compiled_case: CompiledCase::failure(),
···
2993
2996
type_: record_type,
2994
2997
variant: ValueConstructorVariant::LocalVariable {
2995
2998
location: record_location,
2996
2996
-
origin: VariableOrigin::Generated,
2999
2999
+
origin: VariableOrigin::generated(),
2997
3000
},
2998
3001
},
2999
3002
name: RECORD_UPDATE_VARIABLE.into(),
···
4266
4269
});
4267
4270
}
4268
4271
4269
4269
-
let origin = if name == CAPTURE_VARIABLE {
4270
4270
-
VariableOrigin::Generated
4272
4272
+
let syntax = if name == CAPTURE_VARIABLE {
4273
4273
+
VariableSyntax::Generated
4271
4274
} else {
4272
4272
-
VariableOrigin::Variable {
4273
4273
-
name: name.clone(),
4274
4274
-
kind: VariableDeclarationKind::FunctionParameter,
4275
4275
-
}
4275
4275
+
VariableSyntax::Variable(name.clone())
4276
4276
+
};
4277
4277
+
4278
4278
+
let origin = VariableOrigin {
4279
4279
+
syntax,
4280
4280
+
declaration: VariableDeclaration::FunctionParameter,
4276
4281
};
4277
4282
4278
4283
// Insert a variable for the argument into the environment
···
12
12
ast::{
13
13
AssignName, BitArrayOption, ImplicitCallArgOrigin, Layer, UntypedPatternBitArraySegment,
14
14
},
15
15
+
parse::PatternPosition,
15
16
reference::ReferenceKind,
16
17
type_::expression::FunctionDefinition,
17
18
};
···
45
46
/// keeps track of whether it is in scope, so that we can correctly detect
46
47
/// valid/invalid uses.
47
48
variables: HashMap<EcoString, LocalVariable>,
49
49
+
50
50
+
/// What kind of pattern we are typing
51
51
+
position: PatternPosition,
48
52
}
49
53
50
54
#[derive(Debug)]
···
96
100
current_function: &'a FunctionDefinition,
97
101
hydrator: &'a Hydrator,
98
102
problems: &'a mut Problems,
103
103
+
position: PatternPosition,
99
104
) -> Self {
100
105
Self {
101
106
environment,
···
109
114
problems,
110
115
error_encountered: false,
111
116
variables: HashMap::new(),
117
117
+
position,
112
118
}
113
119
}
114
120
···
209
215
let _ = self
210
216
.inferred_variant_variables
211
217
.insert(name.clone(), variant_index);
218
218
+
219
219
+
let origin = match &variable.variant {
220
220
+
ValueConstructorVariant::LocalVariable { origin, .. } => origin.clone(),
221
221
+
ValueConstructorVariant::ModuleConstant { .. }
222
222
+
| ValueConstructorVariant::LocalConstant { .. }
223
223
+
| ValueConstructorVariant::ModuleFn { .. }
224
224
+
| ValueConstructorVariant::Record { .. } => VariableOrigin::generated(),
225
225
+
};
226
226
+
212
227
// This variable is only inferred in this branch of the case expression
213
228
self.environment.insert_local_variable(
214
229
name.clone(),
215
230
variable.definition_location().span,
216
216
-
VariableOrigin::Variable {
217
217
-
name,
218
218
-
kind: VariableDeclarationKind::Implicit,
219
219
-
},
231
231
+
origin,
220
232
type_,
221
233
);
222
234
}
···
663
675
left,
664
676
string(),
665
677
*left_location,
666
666
-
VariableOrigin::AssignmentPattern,
678
678
+
VariableOrigin {
679
679
+
syntax: VariableSyntax::AssignmentPattern,
680
680
+
declaration: self.position.to_declaration(),
681
681
+
},
667
682
);
668
683
}
669
684
···
674
689
right,
675
690
string(),
676
691
right_location,
677
677
-
VariableOrigin::Variable {
678
678
-
name: right.clone(),
679
679
-
kind: VariableDeclarationKind::ClausePattern,
692
692
+
VariableOrigin {
693
693
+
syntax: VariableSyntax::Variable(right.clone()),
694
694
+
declaration: self.position.to_declaration(),
680
695
},
681
696
);
682
697
}
···
707
722
&name,
708
723
pattern.type_().clone(),
709
724
location,
710
710
-
VariableOrigin::AssignmentPattern,
725
725
+
VariableOrigin {
726
726
+
syntax: VariableSyntax::AssignmentPattern,
727
727
+
declaration: self.position.to_declaration(),
728
728
+
},
711
729
);
712
730
Pattern::Assign {
713
731
name,
···
252
252
name: PIPE_VARIABLE.into(),
253
253
constructor: ValueConstructor::local_variable(
254
254
self.argument_location,
255
255
-
VariableOrigin::Generated,
255
255
+
VariableOrigin::generated(),
256
256
self.argument_type.clone(),
257
257
),
258
258
}
···
443
443
expr_typer.environment.insert_local_variable(
444
444
PIPE_VARIABLE.into(),
445
445
location,
446
446
-
VariableOrigin::Generated,
446
446
+
VariableOrigin::generated(),
447
447
expression.type_(),
448
448
);
449
449
TypedPipelineAssignment {