+1
-9
compiler-core/src/ast/typed.rs
+1
-9
compiler-core/src/ast/typed.rs
···
913
913
}
914
914
915
915
#[must_use]
916
+
// TODO)) is this the same as is_record_builder
916
917
pub fn is_record_constructor(&self) -> bool {
917
918
match self {
918
919
TypedExpr::Var {
···
1048
1049
pub(crate) fn is_invalid(&self) -> bool {
1049
1050
match self {
1050
1051
TypedExpr::Invalid { .. } => true,
1051
-
_ => false,
1052
-
}
1053
-
}
1054
-
1055
-
pub(crate) fn is_literal_bool(&self) -> bool {
1056
-
match self {
1057
-
TypedExpr::Var {
1058
-
constructor, name, ..
1059
-
} if name == "True" || name == "False" => constructor.type_.is_bool(),
1060
1052
_ => false,
1061
1053
}
1062
1054
}
+259
-131
compiler-core/src/type_/expression.rs
+259
-131
compiler-core/src/type_/expression.rs
···
1761
1761
right: &TypedExpr,
1762
1762
location: SrcSpan,
1763
1763
) {
1764
-
let outcome = match (left, right) {
1765
-
// Numbers are a bit trickier as we might have more kinds of
1766
-
// comparisons that we can tell are never right.
1767
-
(TypedExpr::Int { int_value: n, .. }, TypedExpr::Int { int_value: m, .. }) => {
1768
-
match binop {
1769
-
BinOp::Eq if n == m => Some(ComparisonOutcome::AlwaysSucceeds),
1770
-
BinOp::Eq => Some(ComparisonOutcome::AlwaysFails),
1771
-
1772
-
BinOp::NotEq if n != m => Some(ComparisonOutcome::AlwaysSucceeds),
1773
-
BinOp::NotEq => Some(ComparisonOutcome::AlwaysFails),
1774
-
1775
-
BinOp::LtInt if n < m => Some(ComparisonOutcome::AlwaysSucceeds),
1776
-
BinOp::LtInt => Some(ComparisonOutcome::AlwaysFails),
1777
-
1778
-
BinOp::LtEqInt if n <= m => Some(ComparisonOutcome::AlwaysSucceeds),
1779
-
BinOp::LtEqInt => Some(ComparisonOutcome::AlwaysFails),
1780
-
1781
-
BinOp::GtInt if n > m => Some(ComparisonOutcome::AlwaysSucceeds),
1782
-
BinOp::GtInt => Some(ComparisonOutcome::AlwaysFails),
1783
-
1784
-
BinOp::GtEqInt if n >= m => Some(ComparisonOutcome::AlwaysSucceeds),
1785
-
BinOp::GtEqInt => Some(ComparisonOutcome::AlwaysFails),
1786
-
1787
-
_ => None,
1788
-
}
1789
-
}
1790
-
1791
-
// For other types of simple values we can only check for redundant
1792
-
// equality checks.
1793
-
(TypedExpr::String { value: one, .. }, TypedExpr::String { value: other, .. }) => {
1794
-
match binop {
1795
-
BinOp::Eq if one == other => Some(ComparisonOutcome::AlwaysSucceeds),
1796
-
BinOp::Eq => Some(ComparisonOutcome::AlwaysFails),
1797
-
BinOp::NotEq if one != other => Some(ComparisonOutcome::AlwaysSucceeds),
1798
-
BinOp::NotEq => Some(ComparisonOutcome::AlwaysFails),
1799
-
_ => None,
1800
-
}
1801
-
}
1802
-
1803
-
// If two variables are the same then we know that the comparison
1804
-
// will always succeed, but the opposite is not true: if the two
1805
-
// variables are different we can't be sure the comparison will
1806
-
// always fail.
1807
-
(TypedExpr::Var { name: one, .. }, TypedExpr::Var { name: other, .. }) => {
1808
-
if left.is_literal_bool() && right.is_literal_bool() {
1809
-
match binop {
1810
-
BinOp::Eq if one == other => Some(ComparisonOutcome::AlwaysSucceeds),
1811
-
BinOp::Eq => Some(ComparisonOutcome::AlwaysFails),
1812
-
BinOp::NotEq if one != other => Some(ComparisonOutcome::AlwaysSucceeds),
1813
-
BinOp::NotEq => Some(ComparisonOutcome::AlwaysFails),
1814
-
_ => None,
1815
-
}
1816
-
} else {
1817
-
match binop {
1818
-
BinOp::Eq if one == other => Some(ComparisonOutcome::AlwaysSucceeds),
1819
-
BinOp::NotEq if one == other => Some(ComparisonOutcome::AlwaysFails),
1820
-
_ => None,
1821
-
}
1822
-
}
1823
-
}
1764
+
let outcome = match (left, binop, right) {
1765
+
(left, BinOp::Eq, right) => match static_compare(left, right) {
1766
+
StaticComparison::CertainlyEqual => ComparisonOutcome::AlwaysSucceeds,
1767
+
StaticComparison::CertainlyDifferent => ComparisonOutcome::AlwaysFails,
1768
+
StaticComparison::CantTell => return,
1769
+
},
1824
1770
1825
-
(
1826
-
TypedExpr::ModuleSelect {
1827
-
constructor: constructor_one,
1828
-
module_name: module_name_one,
1829
-
..
1830
-
},
1831
-
TypedExpr::ModuleSelect {
1832
-
constructor: constructor_other,
1833
-
module_name: module_name_other,
1834
-
..
1835
-
},
1836
-
) => {
1837
-
let equals =
1838
-
module_name_one == module_name_other && constructor_one == constructor_other;
1839
-
match binop {
1840
-
BinOp::Eq if equals => Some(ComparisonOutcome::AlwaysSucceeds),
1841
-
BinOp::NotEq if equals => Some(ComparisonOutcome::AlwaysFails),
1842
-
_ => None,
1843
-
}
1844
-
}
1771
+
(left, BinOp::NotEq, right) => match static_compare(left, right) {
1772
+
StaticComparison::CertainlyEqual => ComparisonOutcome::AlwaysFails,
1773
+
StaticComparison::CertainlyDifferent => ComparisonOutcome::AlwaysSucceeds,
1774
+
StaticComparison::CantTell => return,
1775
+
},
1845
1776
1846
-
// We can only compare two record selects if the selected record is
1847
-
// exactly the same and is not obtained through a function call (that
1848
-
// might be producing different records each time it's invoked).
1849
-
//
1850
-
// For example:
1851
-
// ```gleam
1852
-
// Wibble(1).wibble == Wibble(1).wibble
1853
-
// // We can tell this always succeeds
1854
-
//
1855
-
// one.wibble != one.wibble
1856
-
// // We can tell this always fails
1857
-
//
1858
-
// new().wibble == new().wibble
1859
-
// // We're not sure if this will always succeed or fail
1860
-
// ```
1861
-
//
1862
-
(
1863
-
TypedExpr::RecordAccess {
1864
-
record: record_one,
1865
-
label: label_one,
1866
-
..
1867
-
},
1868
-
TypedExpr::RecordAccess {
1869
-
record: record_other,
1870
-
label: label_other,
1871
-
..
1872
-
},
1873
-
) if label_one == label_other => {
1874
-
match (binop, record_one.as_ref(), record_other.as_ref()) {
1875
-
(
1876
-
BinOp::Eq,
1877
-
TypedExpr::Var { name: one, .. },
1878
-
TypedExpr::Var { name: other, .. },
1879
-
) if one == other => Some(ComparisonOutcome::AlwaysSucceeds),
1880
-
(
1881
-
BinOp::NotEq,
1882
-
TypedExpr::Var { name: one, .. },
1883
-
TypedExpr::Var { name: other, .. },
1884
-
) if one == other => Some(ComparisonOutcome::AlwaysFails),
1885
-
_ => None,
1777
+
// We special handle int literals as there's other comparisons we
1778
+
// might want to perform
1779
+
(TypedExpr::Int { int_value: n, .. }, op, TypedExpr::Int { int_value: m, .. }) => {
1780
+
match op {
1781
+
BinOp::LtInt if n < m => ComparisonOutcome::AlwaysSucceeds,
1782
+
BinOp::LtInt => ComparisonOutcome::AlwaysFails,
1783
+
BinOp::LtEqInt if n <= m => ComparisonOutcome::AlwaysSucceeds,
1784
+
BinOp::LtEqInt => ComparisonOutcome::AlwaysFails,
1785
+
BinOp::GtInt if n > m => ComparisonOutcome::AlwaysSucceeds,
1786
+
BinOp::GtInt => ComparisonOutcome::AlwaysFails,
1787
+
BinOp::GtEqInt if n >= m => ComparisonOutcome::AlwaysSucceeds,
1788
+
BinOp::GtEqInt => ComparisonOutcome::AlwaysFails,
1789
+
_ => return,
1886
1790
}
1887
1791
}
1888
1792
1889
-
// All other values we can't really compare them at compile time to
1890
-
// make sure they're always the same or not.
1891
-
//
1892
-
// TODO: we could actualy do this for a wider range of expressions
1893
-
// if we did constant folding! For example we could tell that
1894
-
// `3 + 3 < 10` always succeeds.
1895
-
_ => None,
1896
-
};
1897
-
1898
-
let Some(outcome) = outcome else {
1899
-
return;
1793
+
_ => return,
1900
1794
};
1901
1795
1902
1796
self.problems
···
4925
4819
AlwaysFails,
4926
4820
AlwaysSucceeds,
4927
4821
}
4822
+
4823
+
enum StaticComparison {
4824
+
/// When we can statically tell that two values are going to be exactly the
4825
+
/// same.
4826
+
CertainlyEqual,
4827
+
/// When we can statically tell that two values are not going to be the
4828
+
/// same.
4829
+
CertainlyDifferent,
4830
+
/// When it's impossible to statically tell if two values are the same.
4831
+
CantTell,
4832
+
}
4833
+
4834
+
fn static_compare(one: &TypedExpr, other: &TypedExpr) -> StaticComparison {
4835
+
match (one, other) {
4836
+
(
4837
+
TypedExpr::Var {
4838
+
name: one,
4839
+
constructor: constructor_one,
4840
+
..
4841
+
},
4842
+
TypedExpr::Var {
4843
+
name: other,
4844
+
constructor: constructor_other,
4845
+
..
4846
+
},
4847
+
) => match (&constructor_one.variant, &constructor_other.variant) {
4848
+
(
4849
+
ValueConstructorVariant::LocalVariable { .. },
4850
+
ValueConstructorVariant::LocalVariable { .. },
4851
+
)
4852
+
| (
4853
+
ValueConstructorVariant::ModuleConstant { .. },
4854
+
ValueConstructorVariant::ModuleConstant { .. },
4855
+
)
4856
+
| (
4857
+
ValueConstructorVariant::LocalConstant { .. },
4858
+
ValueConstructorVariant::LocalConstant { .. },
4859
+
)
4860
+
| (ValueConstructorVariant::Record { .. }, ValueConstructorVariant::Record { .. })
4861
+
if one == other =>
4862
+
{
4863
+
StaticComparison::CertainlyEqual
4864
+
}
4865
+
4866
+
(
4867
+
ValueConstructorVariant::Record {
4868
+
variant_index: index_one,
4869
+
..
4870
+
},
4871
+
ValueConstructorVariant::Record {
4872
+
variant_index: index_other,
4873
+
..
4874
+
},
4875
+
) if index_one != index_other => StaticComparison::CertainlyDifferent,
4876
+
4877
+
(
4878
+
ValueConstructorVariant::LocalVariable { .. }
4879
+
| ValueConstructorVariant::ModuleConstant { .. }
4880
+
| ValueConstructorVariant::LocalConstant { .. }
4881
+
| ValueConstructorVariant::ModuleFn { .. }
4882
+
| ValueConstructorVariant::Record { .. },
4883
+
_,
4884
+
) => StaticComparison::CantTell,
4885
+
},
4886
+
4887
+
(TypedExpr::Int { int_value: n, .. }, TypedExpr::Int { int_value: m, .. }) => {
4888
+
if n == m {
4889
+
StaticComparison::CertainlyEqual
4890
+
} else {
4891
+
StaticComparison::CertainlyDifferent
4892
+
}
4893
+
}
4894
+
4895
+
(TypedExpr::Float { value: n, .. }, TypedExpr::Float { value: m, .. }) => {
4896
+
if n == m {
4897
+
StaticComparison::CertainlyEqual
4898
+
} else {
4899
+
StaticComparison::CertainlyDifferent
4900
+
}
4901
+
}
4902
+
4903
+
(TypedExpr::String { value: one, .. }, TypedExpr::String { value: other, .. }) => {
4904
+
if one == other {
4905
+
StaticComparison::CertainlyEqual
4906
+
} else {
4907
+
StaticComparison::CertainlyDifferent
4908
+
}
4909
+
}
4910
+
4911
+
(TypedExpr::NegateInt { value: one, .. }, TypedExpr::NegateInt { value: other, .. })
4912
+
| (TypedExpr::NegateBool { value: one, .. }, TypedExpr::NegateBool { value: other, .. }) => {
4913
+
static_compare(one, other)
4914
+
}
4915
+
4916
+
(
4917
+
TypedExpr::List {
4918
+
elements: elements_one,
4919
+
tail: tail_one,
4920
+
..
4921
+
},
4922
+
TypedExpr::List {
4923
+
elements: elements_other,
4924
+
tail: tail_other,
4925
+
..
4926
+
},
4927
+
) => {
4928
+
match (tail_one, tail_other) {
4929
+
(Some(one_tail), Some(other_tail)) => match static_compare(one_tail, other_tail) {
4930
+
StaticComparison::CertainlyDifferent => {
4931
+
return StaticComparison::CertainlyDifferent;
4932
+
}
4933
+
StaticComparison::CantTell => return StaticComparison::CantTell,
4934
+
StaticComparison::CertainlyEqual => (),
4935
+
},
4936
+
(None, Some(_)) | (Some(_), None) => return StaticComparison::CantTell,
4937
+
(None, None) => (),
4938
+
};
4939
+
4940
+
// If we can tell the two lists have a different number of items
4941
+
// then we know it's never going to match.
4942
+
if elements_one.len() != elements_other.len() {
4943
+
return StaticComparison::CertainlyDifferent;
4944
+
}
4945
+
4946
+
let mut comparison = StaticComparison::CertainlyEqual;
4947
+
for (one, other) in elements_one.iter().zip(elements_other.iter()) {
4948
+
match static_compare(one, other) {
4949
+
StaticComparison::CertainlyEqual => (),
4950
+
StaticComparison::CertainlyDifferent => {
4951
+
return StaticComparison::CertainlyDifferent;
4952
+
}
4953
+
StaticComparison::CantTell => comparison = StaticComparison::CantTell,
4954
+
}
4955
+
}
4956
+
comparison
4957
+
}
4958
+
4959
+
(
4960
+
TypedExpr::Tuple {
4961
+
elements: elements_one,
4962
+
..
4963
+
},
4964
+
TypedExpr::Tuple {
4965
+
elements: elements_other,
4966
+
..
4967
+
},
4968
+
) => {
4969
+
let mut comparison = StaticComparison::CertainlyEqual;
4970
+
for (one, other) in elements_one.iter().zip(elements_other.iter()) {
4971
+
match static_compare(one, other) {
4972
+
StaticComparison::CertainlyEqual => (),
4973
+
StaticComparison::CertainlyDifferent => {
4974
+
return StaticComparison::CertainlyDifferent;
4975
+
}
4976
+
StaticComparison::CantTell => comparison = StaticComparison::CantTell,
4977
+
}
4978
+
}
4979
+
comparison
4980
+
}
4981
+
4982
+
(
4983
+
TypedExpr::ModuleSelect {
4984
+
constructor: constructor_one,
4985
+
module_name: module_name_one,
4986
+
..
4987
+
},
4988
+
TypedExpr::ModuleSelect {
4989
+
constructor: constructor_other,
4990
+
module_name: module_name_other,
4991
+
..
4992
+
},
4993
+
) => {
4994
+
if module_name_one == module_name_other && constructor_one == constructor_other {
4995
+
StaticComparison::CertainlyEqual
4996
+
} else {
4997
+
StaticComparison::CantTell
4998
+
}
4999
+
}
5000
+
5001
+
(
5002
+
TypedExpr::Call {
5003
+
fun: fun_one,
5004
+
args: args_one,
5005
+
..
5006
+
},
5007
+
TypedExpr::Call {
5008
+
fun: fun_other,
5009
+
args: args_other,
5010
+
..
5011
+
},
5012
+
) => {
5013
+
if fun_one.is_record_builder() && fun_other.is_record_builder() {
5014
+
let mut comparison = StaticComparison::CertainlyEqual;
5015
+
for (one, other) in args_one.iter().zip(args_other.iter()) {
5016
+
match static_compare(&one.value, &other.value) {
5017
+
StaticComparison::CertainlyEqual => (),
5018
+
StaticComparison::CertainlyDifferent => {
5019
+
return StaticComparison::CertainlyDifferent;
5020
+
}
5021
+
StaticComparison::CantTell => comparison = StaticComparison::CantTell,
5022
+
}
5023
+
}
5024
+
comparison
5025
+
} else {
5026
+
StaticComparison::CantTell
5027
+
}
5028
+
}
5029
+
5030
+
(
5031
+
TypedExpr::RecordAccess {
5032
+
index: index_one,
5033
+
record: record_one,
5034
+
..
5035
+
},
5036
+
TypedExpr::RecordAccess {
5037
+
index: index_other,
5038
+
record: record_other,
5039
+
..
5040
+
},
5041
+
) => match static_compare(record_one, record_other) {
5042
+
StaticComparison::CertainlyEqual if index_one == index_other => {
5043
+
StaticComparison::CertainlyEqual
5044
+
}
5045
+
StaticComparison::CertainlyEqual
5046
+
| StaticComparison::CertainlyDifferent
5047
+
| StaticComparison::CantTell => StaticComparison::CantTell,
5048
+
},
5049
+
5050
+
// TODO: For complex expressions we just give up, maybe in future we
5051
+
// could be smarter and perform further comparisons but it sounds like
5052
+
// there's no huge value in this.
5053
+
(_, _) => StaticComparison::CantTell,
5054
+
}
5055
+
}
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison.snap
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison.snap
···
1
+
---
2
+
source: compiler-core/src/type_/tests/warnings.rs
3
+
expression: "pub fn main(a, b) { [1] == [a, b(1)] }"
4
+
---
5
+
----- SOURCE CODE
6
+
pub fn main(a, b) { [1] == [a, b(1)] }
7
+
8
+
----- WARNING
9
+
warning: Redundant comparison
10
+
┌─ /src/warning/wrn.gleam:1:21
11
+
│
12
+
1 │ pub fn main(a, b) { [1] == [a, b(1)] }
13
+
│ ^^^^^^^^^^^^^^^^ This is always `False`
14
+
15
+
This comparison is redundant since it always fails.
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_2.snap
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_2.snap
···
1
+
---
2
+
source: compiler-core/src/type_/tests/warnings.rs
3
+
expression: "pub fn main(a, b) { [1] != [a, b(1)] }"
4
+
---
5
+
----- SOURCE CODE
6
+
pub fn main(a, b) { [1] != [a, b(1)] }
7
+
8
+
----- WARNING
9
+
warning: Redundant comparison
10
+
┌─ /src/warning/wrn.gleam:1:21
11
+
│
12
+
1 │ pub fn main(a, b) { [1] != [a, b(1)] }
13
+
│ ^^^^^^^^^^^^^^^^ This is always `True`
14
+
15
+
This comparison is redundant since it always succeeds.
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_3.snap
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_3.snap
···
1
+
---
2
+
source: compiler-core/src/type_/tests/warnings.rs
3
+
expression: "pub fn main() { [1] != [1] }"
4
+
---
5
+
----- SOURCE CODE
6
+
pub fn main() { [1] != [1] }
7
+
8
+
----- WARNING
9
+
warning: Redundant comparison
10
+
┌─ /src/warning/wrn.gleam:1:17
11
+
│
12
+
1 │ pub fn main() { [1] != [1] }
13
+
│ ^^^^^^^^^^ This is always `False`
14
+
15
+
This comparison is redundant since it always fails.
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_4.snap
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_4.snap
···
1
+
---
2
+
source: compiler-core/src/type_/tests/warnings.rs
3
+
expression: "pub fn main(a) { [1, ..[1, a]] == [1, ..[1, a]] }"
4
+
---
5
+
----- SOURCE CODE
6
+
pub fn main(a) { [1, ..[1, a]] == [1, ..[1, a]] }
7
+
8
+
----- WARNING
9
+
warning: Redundant comparison
10
+
┌─ /src/warning/wrn.gleam:1:18
11
+
│
12
+
1 │ pub fn main(a) { [1, ..[1, a]] == [1, ..[1, a]] }
13
+
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This is always `True`
14
+
15
+
This comparison is redundant since it always succeeds.
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_5.snap
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_5.snap
···
1
+
---
2
+
source: compiler-core/src/type_/tests/warnings.rs
3
+
expression: "pub fn main(a) { [1, ..a] == [1, ..a] }"
4
+
---
5
+
----- SOURCE CODE
6
+
pub fn main(a) { [1, ..a] == [1, ..a] }
7
+
8
+
----- WARNING
9
+
warning: Redundant comparison
10
+
┌─ /src/warning/wrn.gleam:1:18
11
+
│
12
+
1 │ pub fn main(a) { [1, ..a] == [1, ..a] }
13
+
│ ^^^^^^^^^^^^^^^^^^^^ This is always `True`
14
+
15
+
This comparison is redundant since it always succeeds.
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_7.snap
+15
compiler-core/src/type_/tests/snapshots/gleam_core__type___tests__warnings__list_literals_redundant_comparison_7.snap
···
1
+
---
2
+
source: compiler-core/src/type_/tests/warnings.rs
3
+
expression: "pub fn main(a) { [a(1), 2] == [a(1), 3] }"
4
+
---
5
+
----- SOURCE CODE
6
+
pub fn main(a) { [a(1), 2] == [a(1), 3] }
7
+
8
+
----- WARNING
9
+
warning: Redundant comparison
10
+
┌─ /src/warning/wrn.gleam:1:18
11
+
│
12
+
1 │ pub fn main(a) { [a(1), 2] == [a(1), 3] }
13
+
│ ^^^^^^^^^^^^^^^^^^^^^^ This is always `False`
14
+
15
+
This comparison is redundant since it always fails.
+35
compiler-core/src/type_/tests/warnings.rs
+35
compiler-core/src/type_/tests/warnings.rs
···
4014
4014
}
4015
4015
4016
4016
#[test]
4017
+
fn list_literals_redundant_comparison() {
4018
+
assert_warning!("pub fn main(a, b) { [1] == [a, b(1)] }");
4019
+
}
4020
+
4021
+
#[test]
4022
+
fn list_literals_redundant_comparison_2() {
4023
+
assert_warning!("pub fn main(a, b) { [1] != [a, b(1)] }");
4024
+
}
4025
+
4026
+
#[test]
4027
+
fn list_literals_redundant_comparison_3() {
4028
+
assert_warning!("pub fn main() { [1] != [1] }");
4029
+
}
4030
+
4031
+
#[test]
4032
+
fn list_literals_redundant_comparison_4() {
4033
+
assert_warning!("pub fn main(a) { [1, ..[1, a]] == [1, ..[1, a]] }");
4034
+
}
4035
+
4036
+
#[test]
4037
+
fn list_literals_redundant_comparison_5() {
4038
+
assert_warning!("pub fn main(a) { [1, ..a] == [1, ..a] }");
4039
+
}
4040
+
4041
+
#[test]
4042
+
fn list_literals_redundant_comparison_6() {
4043
+
assert_no_warnings!("pub fn main(a) { [a(1)] == [a(1)] }");
4044
+
}
4045
+
4046
+
#[test]
4047
+
fn list_literals_redundant_comparison_7() {
4048
+
assert_warning!("pub fn main(a) { [a(1), 2] == [a(1), 3] }");
4049
+
}
4050
+
4051
+
#[test]
4017
4052
fn string_literals_redundant_comparison() {
4018
4053
assert_warning!("pub fn main() { \"wibble\" == \"wobble\" }");
4019
4054
}