···29293030 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
31313232+- The compiler now raises a warning for unreachable branches that are matching
3333+ on bit array segments that could never match. Consider this example:
3434+3535+ ```gleam
3636+ pub fn get_payload(packet: BitArray) -> Result(BitArray, Nil) {
3737+ case packet {
3838+ <<200, payload:bytes>> -> Ok(payload)
3939+ <<404, _:bits>> -> Error(Nil)
4040+ _ -> Ok(packet)
4141+ }
4242+ }
4343+ ```
4444+4545+ There's a subtle bug here. The second branch can never match since it's
4646+ impossible for the first byte of the bit array to have the value `404`.
4747+ The new error explains this nicely:
4848+4949+ ```text
5050+ warning: Unreachable pattern
5151+ ┌─ /src.gleam:4:5
5252+ │
5353+ 4 │ <<404, _:bits>> -> Error(Nil)
5454+ │ ^^^^^^^^^^^^^^^
5555+ │ │
5656+ │ A 1 byte unsigned integer will never match this value
5757+5858+ This pattern cannot be reached as it contains segments that will never
5959+ match.
6060+6161+ Hint: It can be safely removed.
6262+ ```
6363+6464+ ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
6565+3266- The compiler now emits a better error message for private types marked as
3367 opaque. For example, the following piece of code:
3468
···55use crate::{
66 ast::{BinOp, BitArraySegmentTruncation, Layer, SrcSpan, TodoKind},
77 build::Target,
88+ exhaustiveness::ImpossibleBitArraySegmentPattern,
89 type_::{Type, expression::ComparisonOutcome},
910};
1011···969970 location: SrcSpan,
970971 },
971972972972- AssertAssignmentOnInferredVariant {
973973+ AssertAssignmentOnImpossiblePattern {
973974 location: SrcSpan,
975975+ reason: AssertImpossiblePattern,
974976 },
975977976978 /// When a `todo` or `panic` is used as a function instead of providing the
···10751077 },
10761078}
1077107910801080+#[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
10811081+pub enum AssertImpossiblePattern {
10821082+ /// When `let assert`-ing on a variant that's different from the inferred
10831083+ /// one.
10841084+ ///
10851085+ /// ```gleam
10861086+ /// let assert Error(_) = Ok(_)
10871087+ /// ```
10881088+ ///
10891089+ InferredVariant,
10901090+10911091+ /// When `let assert`-ing on a pattern that will never match because it's
10921092+ /// matching on impossible segment(s).
10931093+ ///
10941094+ /// ```gleam
10951095+ /// let assert <<-2:unsigned>> = bit_array
10961096+ /// ```
10971097+ ///
10981098+ ImpossibleSegments {
10991099+ segments: Vec<ImpossibleBitArraySegmentPattern>,
11001100+ },
11011101+}
11021102+10781103#[derive(Debug, Eq, Copy, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
10791104pub enum FeatureKind {
10801105 LabelShorthandSyntax,
···11471172 Panic,
11481173}
1149117411501150-#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
11751175+#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
11511176pub enum UnreachablePatternReason {
11521177 /// The clause is unreachable because a previous pattern
11531178 /// matches the same case.
···11561181 /// of the custom type that we are matching on, and this matches
11571182 /// against one of the variants we know it isn't.
11581183 ImpossibleVariant,
11841184+ /// The clause is unreachable because it is matching on a pattern segment
11851185+ /// that we could tell is never going to match
11861186+ ImpossibleSegments(Vec<ImpossibleBitArraySegmentPattern>),
11591187}
1160118811611189impl Error {
···12921320 | Warning::OpaqueExternalType { location, .. }
12931321 | Warning::InternalTypeLeak { location, .. }
12941322 | Warning::RedundantAssertAssignment { location, .. }
12951295- | Warning::AssertAssignmentOnInferredVariant { location, .. }
13231323+ | Warning::AssertAssignmentOnImpossiblePattern { location, .. }
12961324 | Warning::TodoOrPanicUsedAsFunction { location, .. }
12971325 | Warning::UnreachableCodeAfterPanic { location, .. }
12981326 | Warning::RedundantPipeFunctionCapture { location, .. }
···11+---
22+source: compiler-core/src/type_/tests/warnings.rs
33+expression: "\npub fn main(x) {\n let assert <<1, -1, 2, -3>> = x\n}"
44+---
55+----- SOURCE CODE
66+77+pub fn main(x) {
88+ let assert <<1, -1, 2, -3>> = x
99+}
1010+1111+----- WARNING
1212+warning: Assertion that will always fail
1313+ ┌─ /src/warning/wrn.gleam:3:14
1414+ │
1515+3 │ let assert <<1, -1, 2, -3>> = x
1616+ │ ^^^^^^^^^^^^^^^^
1717+ │ │ │
1818+ │ │ A 1 byte unsigned integer will never match this value
1919+ │ A 1 byte unsigned integer will never match this value
2020+2121+We can tell from the code above that the value will never match this
2222+pattern and that this code will always crash.
2323+2424+Either change the pattern or use `panic` to unconditionally fail.
···11+---
22+source: compiler-core/src/type_/tests/warnings.rs
33+expression: "\npub fn main(x) {\n case x {\n <<9:size(2)>> -> True\n _ -> False\n }\n}"
44+---
55+----- SOURCE CODE
66+77+pub fn main(x) {
88+ case x {
99+ <<9:size(2)>> -> True
1010+ _ -> False
1111+ }
1212+}
1313+1414+----- WARNING
1515+warning: Unreachable pattern
1616+ ┌─ /src/warning/wrn.gleam:4:5
1717+ │
1818+4 │ <<9:size(2)>> -> True
1919+ │ ^^^^^^^^^^^^^
2020+ │ │
2121+ │ A 2 bits unsigned integer will never match this value
2222+2323+This pattern cannot be reached as it contains segments that will never
2424+match.
2525+2626+Hint: It can be safely removed.
···11+---
22+source: compiler-core/src/type_/tests/warnings.rs
33+expression: "\npub fn main(x) {\n case x {\n <<-9:unsigned>> -> True\n _ -> False\n }\n}"
44+---
55+----- SOURCE CODE
66+77+pub fn main(x) {
88+ case x {
99+ <<-9:unsigned>> -> True
1010+ _ -> False
1111+ }
1212+}
1313+1414+----- WARNING
1515+warning: Unreachable pattern
1616+ ┌─ /src/warning/wrn.gleam:4:5
1717+ │
1818+4 │ <<-9:unsigned>> -> True
1919+ │ ^^^^^^^^^^^^^^^
2020+ │ │
2121+ │ A 1 byte unsigned integer will never match this value
2222+2323+This pattern cannot be reached as it contains segments that will never
2424+match.
2525+2626+Hint: It can be safely removed.
···11+---
22+source: compiler-core/src/type_/tests/warnings.rs
33+expression: "\npub fn main(x) {\n case x {\n <<312>> -> True\n _ -> False\n }\n}"
44+---
55+----- SOURCE CODE
66+77+pub fn main(x) {
88+ case x {
99+ <<312>> -> True
1010+ _ -> False
1111+ }
1212+}
1313+1414+----- WARNING
1515+warning: Unreachable pattern
1616+ ┌─ /src/warning/wrn.gleam:4:5
1717+ │
1818+4 │ <<312>> -> True
1919+ │ ^^^^^^^
2020+ │ │
2121+ │ A 1 byte unsigned integer will never match this value
2222+2323+This pattern cannot be reached as it contains segments that will never
2424+match.
2525+2626+Hint: It can be safely removed.
···11+---
22+source: compiler-core/src/type_/tests/warnings.rs
33+expression: "\npub fn main(x) {\n case x {\n <<-1>> -> True\n _ -> False\n }\n}"
44+---
55+----- SOURCE CODE
66+77+pub fn main(x) {
88+ case x {
99+ <<-1>> -> True
1010+ _ -> False
1111+ }
1212+}
1313+1414+----- WARNING
1515+warning: Unreachable pattern
1616+ ┌─ /src/warning/wrn.gleam:4:5
1717+ │
1818+4 │ <<-1>> -> True
1919+ │ ^^^^^^
2020+ │ │
2121+ │ A 1 byte unsigned integer will never match this value
2222+2323+This pattern cannot be reached as it contains segments that will never
2424+match.
2525+2626+Hint: It can be safely removed.
···11+---
22+source: compiler-core/src/type_/tests/warnings.rs
33+expression: "\npub fn main(x) {\n case x {\n <<1, -1, 2, -3>> -> True\n _ -> False\n }\n}"
44+---
55+----- SOURCE CODE
66+77+pub fn main(x) {
88+ case x {
99+ <<1, -1, 2, -3>> -> True
1010+ _ -> False
1111+ }
1212+}
1313+1414+----- WARNING
1515+warning: Unreachable pattern
1616+ ┌─ /src/warning/wrn.gleam:4:5
1717+ │
1818+4 │ <<1, -1, 2, -3>> -> True
1919+ │ ^^^^^^^^^^^^^^^^
2020+ │ │ │
2121+ │ │ A 1 byte unsigned integer will never match this value
2222+ │ A 1 byte unsigned integer will never match this value
2323+2424+This pattern cannot be reached as it contains segments that will never
2525+match.
2626+2727+Hint: It can be safely removed.