|
2 | 2 | //!
|
3 | 3 | //! [parser-tests]: https://github.com/rust-lang/rust/blob/894f7a4ba6554d3797404bbf550d9919df060b97/compiler/rustc_parse/src/parser/tests.rs
|
4 | 4 |
|
5 |
| -use annotate_snippets::{AnnotationKind, Group, Level, Origin, Renderer, Snippet}; |
| 5 | +use annotate_snippets::{AnnotationKind, Group, Level, Origin, Patch, Renderer, Snippet}; |
6 | 6 |
|
7 | 7 | use annotate_snippets::renderer::OutputTheme;
|
8 | 8 | use snapbox::{assert_data_eq, str};
|
@@ -2020,3 +2020,94 @@ LL | ... = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...0, 0, 0, 0, 0, 0, 0, 0, 0
|
2020 | 2020 | .term_width(120);
|
2021 | 2021 | assert_data_eq!(renderer.render(input), expected);
|
2022 | 2022 | }
|
| 2023 | + |
| 2024 | +#[test] |
| 2025 | +fn lint_map_unit_fn() { |
| 2026 | + // tests/ui/lint/lint_map_unit_fn.rs |
| 2027 | + let source = r#"#![deny(map_unit_fn)] |
| 2028 | +
|
| 2029 | +fn foo(items: &mut Vec<u8>) { |
| 2030 | + items.sort(); |
| 2031 | +} |
| 2032 | +
|
| 2033 | +fn main() { |
| 2034 | + let mut x: Vec<Vec<u8>> = vec![vec![0, 2, 1], vec![5, 4, 3]]; |
| 2035 | + x.iter_mut().map(foo); |
| 2036 | + //~^ ERROR `Iterator::map` call that discard the iterator's values |
| 2037 | + x.iter_mut().map(|items| { |
| 2038 | + //~^ ERROR `Iterator::map` call that discard the iterator's values |
| 2039 | + items.sort(); |
| 2040 | + }); |
| 2041 | + let f = |items: &mut Vec<u8>| { |
| 2042 | + items.sort(); |
| 2043 | + }; |
| 2044 | + x.iter_mut().map(f); |
| 2045 | + //~^ ERROR `Iterator::map` call that discard the iterator's values |
| 2046 | +} |
| 2047 | +"#; |
| 2048 | + |
| 2049 | + let input = Level::ERROR |
| 2050 | + .header("`Iterator::map` call that discard the iterator's values") |
| 2051 | + .group( |
| 2052 | + Group::new() |
| 2053 | + .element( |
| 2054 | + Snippet::source(source) |
| 2055 | + .origin("$DIR/lint_map_unit_fn.rs") |
| 2056 | + .fold(true) |
| 2057 | + .annotation(AnnotationKind::Context.span(271..278).label( |
| 2058 | + "this function returns `()`, which is likely not what you wanted", |
| 2059 | + )) |
| 2060 | + .annotation( |
| 2061 | + AnnotationKind::Context |
| 2062 | + .span(271..379) |
| 2063 | + .label("called `Iterator::map` with callable that returns `()`"), |
| 2064 | + ) |
| 2065 | + .annotation( |
| 2066 | + AnnotationKind::Context |
| 2067 | + .span(267..380) |
| 2068 | + .label("after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items") |
| 2069 | + ) |
| 2070 | + .annotation(AnnotationKind::Primary.span(267..380)), |
| 2071 | + ) |
| 2072 | + .element( |
| 2073 | + Level::NOTE.title("`Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated")), |
| 2074 | + ) |
| 2075 | + .group( |
| 2076 | + Group::new() |
| 2077 | + .element(Level::HELP.title("you might have meant to use `Iterator::for_each`")) |
| 2078 | + .element( |
| 2079 | + Snippet::source(source) |
| 2080 | + .origin("$DIR/lint_map_unit_fn.rs") |
| 2081 | + .fold(true) |
| 2082 | + .patch(Patch::new(267..270, r#"for_each"#)), |
| 2083 | + ), |
| 2084 | + ); |
| 2085 | + |
| 2086 | + let expected = str![[r#" |
| 2087 | +error: `Iterator::map` call that discard the iterator's values |
| 2088 | + --> $DIR/lint_map_unit_fn.rs:11:18 |
| 2089 | + | |
| 2090 | +LL | x.iter_mut().map(|items| { |
| 2091 | + | ^ ------- |
| 2092 | + | | | |
| 2093 | + | __________________|___this function returns `()`, which is likely not what you wanted |
| 2094 | + | |__________________| |
| 2095 | + | || |
| 2096 | +LL | || //~^ ERROR `Iterator::map` call that discard the iterator's values |
| 2097 | +LL | || items.sort(); |
| 2098 | +LL | || }); |
| 2099 | + | || -^ after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items |
| 2100 | + | ||_____|| |
| 2101 | + | |_____| |
| 2102 | + | called `Iterator::map` with callable that returns `()` |
| 2103 | + | |
| 2104 | + = note: `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated |
| 2105 | +help: you might have meant to use `Iterator::for_each` |
| 2106 | + | |
| 2107 | +LL - x.iter_mut().map(|items| { |
| 2108 | +LL + x.iter_mut().for_each(|items| { |
| 2109 | + | |
| 2110 | +"#]]; |
| 2111 | + let renderer = Renderer::plain().anonymized_line_numbers(true); |
| 2112 | + assert_data_eq!(renderer.render(input), expected); |
| 2113 | +} |
0 commit comments