Skip to content

Commit 432e635

Browse files
authored
Deprecate _ as x patterns (#4683)
1 parent 2f2e836 commit 432e635

File tree

9 files changed

+99
-3
lines changed

9 files changed

+99
-3
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@
132132

133133
([Giacomo Cavalieri](https://github.com/giacomocavalieri))
134134

135+
- Implememted rewrite of `_ as x` patterns to `x`.
136+
([eutampieri](https://github.com/eutampieri))
137+
135138
### Bug fixes
136139

137140
- Fixed a bug where `echo` could crash on JavaScript if the module contains

compiler-core/src/format.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2250,7 +2250,11 @@ impl<'comments> Formatter<'comments> {
22502250
Pattern::BitArraySize(size) => self.bit_array_size(size),
22512251

22522252
Pattern::Assign { name, pattern, .. } => {
2253-
self.pattern(pattern).append(" as ").append(name.as_str())
2253+
if pattern.is_discard() {
2254+
name.to_doc()
2255+
} else {
2256+
self.pattern(pattern).append(" as ").append(name.as_str())
2257+
}
22542258
}
22552259

22562260
Pattern::Discard { name, .. } => name.to_doc(),

compiler-core/src/format/tests.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6717,3 +6717,24 @@ fn assert_as_with_comment_before_the_as() {
67176717
"#
67186718
);
67196719
}
6720+
6721+
// https://github.com/gleam-lang/gleam/issues/4664
6722+
#[test]
6723+
fn pattern_unused_discard() {
6724+
assert_format_rewrite!(
6725+
r#"pub fn main() {
6726+
let a = 10
6727+
let _ = case a {
6728+
_ as b -> b
6729+
}
6730+
}
6731+
"#,
6732+
r#"pub fn main() {
6733+
let a = 10
6734+
let _ = case a {
6735+
b -> b
6736+
}
6737+
}
6738+
"#
6739+
);
6740+
}

compiler-core/src/type_/error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,11 @@ pub enum Warning {
884884
reason: UnreachablePatternReason,
885885
},
886886

887+
UnusedDiscardPattern {
888+
location: SrcSpan,
889+
name: EcoString,
890+
},
891+
887892
/// This happens when someone tries to write a case expression where one of
888893
/// the subjects is a literal tuple, list or bit array for example:
889894
///
@@ -1287,6 +1292,7 @@ impl Warning {
12871292
| Warning::AssertLiteralBool { location, .. }
12881293
| Warning::BitArraySegmentTruncatedValue { location, .. }
12891294
| Warning::TopLevelDefinitionShadowsImport { location, .. }
1295+
| Warning::UnusedDiscardPattern { location, .. }
12901296
| Warning::ModuleImportedTwice {
12911297
second: location, ..
12921298
}

compiler-core/src/type_/pattern.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,13 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
694694
location,
695695
} => {
696696
let pattern = self.unify(*pattern, type_, subject_variable);
697+
698+
if pattern.is_discard() {
699+
self.problems.warning(Warning::UnusedDiscardPattern {
700+
location,
701+
name: name.clone(),
702+
});
703+
}
697704
self.insert_variable(
698705
&name,
699706
pattern.type_().clone(),
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
source: compiler-core/src/type_/tests/warnings.rs
3+
assertion_line: 4195
4+
expression: "pub fn main() {\n let a = 10\n let _ = case a {\n _ as b -> b\n }\n}\n"
5+
snapshot_kind: text
6+
---
7+
----- SOURCE CODE
8+
pub fn main() {
9+
let a = 10
10+
let _ = case a {
11+
_ as b -> b
12+
}
13+
}
14+
15+
16+
----- WARNING
17+
warning: Unused discard pattern
18+
┌─ /src/warning/wrn.gleam:4:5
19+
20+
4_ as b -> b
21+
^^^^^^
22+
23+
`_ as b` can be written more concisely as `b`

compiler-core/src/type_/tests/warnings.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4211,3 +4211,16 @@ pub fn main() -> Bool {
42114211
"
42124212
);
42134213
}
4214+
4215+
#[test]
4216+
fn unused_discard_pattern() {
4217+
assert_warning!(
4218+
"pub fn main() {
4219+
let a = 10
4220+
let _ = case a {
4221+
_ as b -> b
4222+
}
4223+
}
4224+
"
4225+
);
4226+
}

compiler-core/src/warning.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,25 @@ can already tell whether it will be `True` or `False`.",
13041304
}),
13051305
},
13061306

1307+
type_::Warning::UnusedDiscardPattern { location, name } => Diagnostic {
1308+
title: "Unused discard pattern".into(),
1309+
text: format!("`_ as {name}` can be written more concisely as `{name}`"),
1310+
level: diagnostic::Level::Warning,
1311+
location: Some(Location {
1312+
src: src.clone(),
1313+
path: path.to_path_buf(),
1314+
label: diagnostic::Label {
1315+
text: None,
1316+
span: SrcSpan {
1317+
start: location.start - "_ as ".len() as u32,
1318+
end: location.end,
1319+
},
1320+
},
1321+
extra_labels: vec![],
1322+
}),
1323+
hint: None,
1324+
},
1325+
13071326
type_::Warning::TopLevelDefinitionShadowsImport { location, name } => {
13081327
let text = format!(
13091328
"Definition of {name} shadows an imported value.

docs/v2.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ Due to a bug in the parser we accept `[1, ..]` as a valid list value.
1212
This pattern doesn't make sense as one could write `a` instead. We don't want
1313
two ways of doing the same thing.
1414

15-
- [ ] Emits warning when used.
16-
- [ ] Formatter rewrites it to desired syntax.
15+
- [X] Emits warning when used.
16+
- [X] Formatter rewrites it to desired syntax.
1717

1818
## Shadowing imported values
1919

0 commit comments

Comments
 (0)