Skip to content

Commit 8f3ed5e

Browse files
Courtcircuitslpil
authored andcommitted
added warning on empty clause in the compiler
Signed-off-by: Courtcircuits <[email protected]>
1 parent d3bd6d3 commit 8f3ed5e

File tree

6 files changed

+91
-6
lines changed

6 files changed

+91
-6
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,3 +408,6 @@
408408
- Fixed a bug where the compiler would suggest to use a discarded value defined
409409
in a different function.
410410
([Giacomo Cavalieri](https://github.com/giacomocavalieri))
411+
412+
- Fixed a bug where the compiler allowed to write a guard with an empty clause.
413+
([Tristan-Mihai Radulescu][https://github.com/Courtcircuits])

compiler-core/src/parse.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,11 +1622,19 @@ where
16221622
// if a < b
16231623
// if a < b || b < c
16241624
fn parse_case_clause_guard(&mut self) -> Result<Option<UntypedClauseGuard>, ParseError> {
1625-
if self.maybe_one(&Token::If).is_some() {
1626-
self.parse_clause_guard_inner()
1627-
} else {
1628-
Ok(None)
1625+
let Some((start, end)) = self.maybe_one(&Token::If) else {
1626+
return Ok(None);
1627+
};
1628+
let guard_clause_result = self.parse_clause_guard_inner();
1629+
// if inner clause is none, a warning should be thrown to prevent that this behaviour
1630+
// is deprecated
1631+
if let Ok(None) = guard_clause_result {
1632+
self.warnings
1633+
.push(DeprecatedSyntaxWarning::DeprecatedEmptyGuardClause {
1634+
location: SrcSpan { start, end },
1635+
});
16291636
}
1637+
guard_clause_result
16301638
}
16311639

16321640
fn parse_clause_guard_inner(&mut self) -> Result<Option<UntypedClauseGuard>, ParseError> {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
source: compiler-core/src/type_/tests/warnings.rs
3+
expression: "\npub fn main() {\n let wibble = 10\n case wibble {\n 10 if -> True\n _ -> False\n }\n\n}"
4+
---
5+
----- SOURCE CODE
6+
7+
pub fn main() {
8+
let wibble = 10
9+
case wibble {
10+
10 if -> True
11+
_ -> False
12+
}
13+
14+
}
15+
16+
----- WARNING
17+
warning: Deprecated empty guard clause syntax
18+
┌─ test/path:5:12
19+
20+
510 if -> True
21+
^^ This should be followed by a guard or removed!!
22+
23+
24+
Empty clause within a guard is deprecated.
25+
To keep its behaviour, either remove the guard or fill the clause with
26+
`True` instead.

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4314,3 +4314,18 @@ pub fn wibble() { x }
43144314
"
43154315
);
43164316
}
4317+
4318+
#[test]
4319+
fn empty_guard_clause() {
4320+
assert_warning!(
4321+
"
4322+
pub fn main() {
4323+
let wibble = 10
4324+
case wibble {
4325+
10 if -> True
4326+
_ -> False
4327+
}
4328+
4329+
}"
4330+
);
4331+
}

compiler-core/src/warning.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,17 @@ pub enum DeprecatedSyntaxWarning {
242242
location: SrcSpan,
243243
},
244244

245+
/// If a guard has an empty clause :
246+
/// ```gleam
247+
/// case wibble {
248+
/// big if -> True
249+
/// ^^ this should be followed by a guard or removed!!
250+
/// }
251+
/// ```
252+
DeprecatedEmptyGuardClause {
253+
location: SrcSpan,
254+
},
255+
245256
DeprecatedTargetShorthand {
246257
target: Target,
247258
location: SrcSpan,
@@ -355,7 +366,29 @@ To match on all possible lists, use the `_` catch-all pattern instead.",
355366
extra_labels: vec![],
356367
}),
357368
},
358-
369+
Warning::DeprecatedSyntax {
370+
path,
371+
src,
372+
warning: DeprecatedSyntaxWarning::DeprecatedEmptyGuardClause { location },
373+
} => Diagnostic {
374+
title: "Deprecated empty guard clause syntax".into(),
375+
text: wrap(
376+
"Empty clause within a guard is deprecated.
377+
To keep its behaviour, either remove the guard or fill the clause with `True` instead.",
378+
),
379+
hint: None,
380+
level: diagnostic::Level::Warning,
381+
location: Some(Location {
382+
label: diagnostic::Label {
383+
text: Some("This should be followed by a guard or removed!!
384+
".into()),
385+
span: *location,
386+
},
387+
path: path.clone(),
388+
src: src.clone(),
389+
extra_labels: vec![],
390+
}),
391+
},
359392
Warning::DeprecatedSyntax {
360393
path,
361394
src,

docs/v2.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,5 @@ compatibility.
4040
It doesn't make sense to have an `if` guard followed by no condition, but the
4141
compiler allows this: `case wibble { big if -> True }`
4242

43-
- [ ] Emits warning when used.
43+
- [x] Emits warning when used.
4444
- [x] Formatter rewrites it to desired syntax.

0 commit comments

Comments
 (0)