Skip to content

Deprecate _ as x patterns #4683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c8e5793
Emit a warning for `_ as x`
eutampieri Jun 13, 2025
9a1b44b
Have the formatter rewrite _ as y to y
eutampieri Jun 13, 2025
9e56bf7
Emit a warning for the deprecation of `_ as a` syntax
eutampieri Jun 13, 2025
3baa55b
Revert whitespace removal
eutampieri Jun 13, 2025
c0e10dc
Add test for unused discard pattern
eutampieri Jun 13, 2025
14ce722
Add test for the rewrite of unused discard patterns
eutampieri Jun 13, 2025
efa5575
Add newline at the end of the test string for the unused_discard_patt…
eutampieri Jun 13, 2025
dc22a52
Update CHANGELOG
eutampieri Jun 14, 2025
44a02cb
Move changelog item to the relevant section
eutampieri Jun 14, 2025
2ed16df
Address review comment: better diagnostics
eutampieri Jun 18, 2025
1123e1c
Remove dead code
eutampieri Jun 26, 2025
6b3457b
Run cargo fmt
eutampieri Jun 28, 2025
27445f9
Update snapshot for unused discard pattern test
eutampieri Jun 28, 2025
85c4f9a
Various fixes
eutampieri Jul 7, 2025
8c76d8b
Fix CHANGELOG formatting
eutampieri Jul 7, 2025
68cf50e
Update snapshot for unused discard pattern warning test
eutampieri Jul 30, 2025
751cf45
Unused discard pattern: extend the span to the end of the pattern
eutampieri Jul 30, 2025
eda20a3
Be a bit more explicit on unused discard pattern end location calcula…
eutampieri Jul 30, 2025
8312ee8
Unused discard pattern warning: fix label position
eutampieri Jul 30, 2025
74b0713
Fix unused discard pattern snapshot
eutampieri Jul 30, 2025
127b73e
Revert bad merge resolution
eutampieri Jul 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,9 @@

([Louis Pilfold](https://github.com/lpil))

- A warning is now emitted when the now deprecated `_ as x` pattern is used.
([eutampieri](https://github.com/eutampieri))

- The compiler now allows using bit array options to specify endianness when
constructing or pattern matching on UTF codepoints in bit arrays.
([Surya Rose](https://github.com/GearsDatapacks))
Expand Down Expand Up @@ -603,6 +606,9 @@

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

- Implememted rewrite of `_ as x` patterns to `x`.
([eutampieri](https://github.com/eutampieri))

### Bug fixes

- Fixed a bug where the language server would not show type-related code actions
Expand Down
6 changes: 5 additions & 1 deletion compiler-core/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2250,7 +2250,11 @@ impl<'comments> Formatter<'comments> {
Pattern::BitArraySize(size) => self.bit_array_size(size),

Pattern::Assign { name, pattern, .. } => {
self.pattern(pattern).append(" as ").append(name.as_str())
if pattern.is_discard() {
name.to_doc()
} else {
self.pattern(pattern).append(" as ").append(name.as_str())
}
}

Pattern::Discard { name, .. } => name.to_doc(),
Expand Down
21 changes: 21 additions & 0 deletions compiler-core/src/format/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6685,3 +6685,24 @@ fn assert_as_with_comment_before_the_as() {
"#
);
}

// https://github.com/gleam-lang/gleam/issues/4664
#[test]
fn pattern_unused_discard() {
assert_format_rewrite!(
r#"pub fn main() {
let a = 10
let _ = case a {
_ as b -> b
}
}
"#,
r#"pub fn main() {
let a = 10
let _ = case a {
b -> b
}
}
"#
);
}
6 changes: 6 additions & 0 deletions compiler-core/src/type_/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,11 @@ pub enum Warning {
reason: UnreachablePatternReason,
},

UnusedDiscardPattern {
location: SrcSpan,
name: EcoString,
},

/// This happens when someone tries to write a case expression where one of
/// the subjects is a literal tuple, list or bit array for example:
///
Expand Down Expand Up @@ -1272,6 +1277,7 @@ impl Warning {
| Warning::AssertLiteralBool { location, .. }
| Warning::BitArraySegmentTruncatedValue { location, .. }
| Warning::TopLevelDefinitionShadowsImport { location, .. }
| Warning::UnusedDiscardPattern { location, .. }
| Warning::ModuleImportedTwice {
second: location, ..
}
Expand Down
7 changes: 7 additions & 0 deletions compiler-core/src/type_/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,13 @@ impl<'a, 'b> PatternTyper<'a, 'b> {
location,
} => {
let pattern = self.unify(*pattern, type_, subject_variable);

if pattern.is_discard() {
self.problems.warning(Warning::UnusedDiscardPattern {
location,
name: name.clone(),
});
}
self.insert_variable(
&name,
pattern.type_().clone(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
source: compiler-core/src/type_/tests/warnings.rs
assertion_line: 4195
expression: "pub fn main() {\n let a = 10\n let _ = case a {\n _ as b -> b\n }\n}\n"
snapshot_kind: text
---
----- SOURCE CODE
pub fn main() {
let a = 10
let _ = case a {
_ as b -> b
}
}


----- WARNING
warning: Unused discard pattern
┌─ /src/warning/wrn.gleam:4:5
4 │ _ as b -> b
│ ^^^^^^

`_ as b` can be written more concisely as `b`
13 changes: 13 additions & 0 deletions compiler-core/src/type_/tests/warnings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4189,3 +4189,16 @@ pub fn main() -> Bool {
"
);
}

#[test]
fn unused_discard_pattern() {
assert_warning!(
"pub fn main() {
let a = 10
let _ = case a {
_ as b -> b
}
}
"
);
}
19 changes: 19 additions & 0 deletions compiler-core/src/warning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,25 @@ can already tell whether it will be `True` or `False`.",
}),
},

type_::Warning::UnusedDiscardPattern { location, name } => Diagnostic {
title: "Unused discard pattern".into(),
text: format!("`_ as {name}` can be written more concisely as `{name}`"),
level: diagnostic::Level::Warning,
location: Some(Location {
src: src.clone(),
path: path.to_path_buf(),
label: diagnostic::Label {
text: None,
span: SrcSpan {
start: location.start - "_ as ".len() as u32,
end: location.end,
},
},
extra_labels: vec![],
}),
hint: None,
},

type_::Warning::TopLevelDefinitionShadowsImport { location, name } => {
let text = format!(
"Definition of {name} shadows an imported value.
Expand Down
4 changes: 2 additions & 2 deletions docs/v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ Due to a bug in the parser we accept `[1, ..]` as a valid list value.
This pattern doesn't make sense as one could write `a` instead. We don't want
two ways of doing the same thing.

- [ ] Emits warning when used.
- [ ] Formatter rewrites it to desired syntax.
- [X] Emits warning when used.
- [X] Formatter rewrites it to desired syntax.

## Shadowing imported values

Expand Down