summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/tests/ui/manual_try_fold.rs
blob: 7299d7cf9862905fb015361189f3e8ee28655679 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//@aux-build:proc_macros.rs
#![allow(clippy::unnecessary_fold, unused)]
#![warn(clippy::manual_try_fold)]
#![feature(try_trait_v2)]
//@no-rustfix
use std::ops::{ControlFlow, FromResidual, Try};

#[macro_use]
extern crate proc_macros;

// Test custom `Try` with more than 1 argument
struct NotOption(i32, i32);

impl<R> FromResidual<R> for NotOption {
    fn from_residual(_: R) -> Self {
        todo!()
    }
}

impl Try for NotOption {
    type Output = ();
    type Residual = ();

    fn from_output(_: Self::Output) -> Self {
        todo!()
    }

    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        todo!()
    }
}

// Test custom `Try` with only 1 argument
#[derive(Default)]
struct NotOptionButWorse(i32);

impl<R> FromResidual<R> for NotOptionButWorse {
    fn from_residual(_: R) -> Self {
        todo!()
    }
}

impl Try for NotOptionButWorse {
    type Output = ();
    type Residual = ();

    fn from_output(_: Self::Output) -> Self {
        todo!()
    }

    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        todo!()
    }
}

fn main() {
    [1, 2, 3]
        .iter()
        .fold(Some(0i32), |sum, i| sum?.checked_add(*i))
        .unwrap();
    [1, 2, 3]
        .iter()
        .fold(NotOption(0i32, 0i32), |sum, i| NotOption(0i32, 0i32));
    [1, 2, 3]
        .iter()
        .fold(NotOptionButWorse(0i32), |sum, i| NotOptionButWorse(0i32));
    // Do not lint
    [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap();
    [1, 2, 3].iter().fold(0i32, |sum, i| sum + i);
    [1, 2, 3]
        .iter()
        .fold(NotOptionButWorse::default(), |sum, i| NotOptionButWorse::default());
    external! {
        [1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)).unwrap();
        [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap();
    }
    with_span! {
        span
        [1, 2, 3].iter().fold(Some(0i32), |sum, i| sum?.checked_add(*i)).unwrap();
        [1, 2, 3].iter().try_fold(0i32, |sum, i| sum.checked_add(*i)).unwrap();
    }
}

#[clippy::msrv = "1.26.0"]
fn msrv_too_low() {
    [1, 2, 3]
        .iter()
        .fold(Some(0i32), |sum, i| sum?.checked_add(*i))
        .unwrap();
}

#[clippy::msrv = "1.27.0"]
fn msrv_juust_right() {
    [1, 2, 3]
        .iter()
        .fold(Some(0i32), |sum, i| sum?.checked_add(*i))
        .unwrap();
}

mod issue11876 {
    struct Foo;

    impl Bar for Foo {
        type Output = u32;
    }

    trait Bar: Sized {
        type Output;
        fn fold<A, F>(self, init: A, func: F) -> Fold<Self, A, F>
        where
            A: Clone,
            F: Fn(A, Self::Output) -> A,
        {
            Fold { this: self, init, func }
        }
    }

    #[allow(dead_code)]
    struct Fold<S, A, F> {
        this: S,
        init: A,
        func: F,
    }

    fn main() {
        Foo.fold(Some(0), |acc, entry| Some(acc? + entry));
    }
}