summaryrefslogtreecommitdiffstats
path: root/src/test/ui/rfc-2091-track-caller/tracked-trait-obj.rs
blob: 06883a857900ef5e027eb00c1db6015d33d16b5b (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
// run-pass

trait Tracked {
    #[track_caller]
    fn track_caller_trait_method(&self, line: u32, col: u32) {
        let location = std::panic::Location::caller();
        assert_eq!(location.file(), file!());
        // The trait method definition is annotated with `#[track_caller]`,
        // so caller location information will work through a method
        // call on a trait object
        assert_eq!(location.line(), line, "Bad line");
        assert_eq!(location.column(), col, "Bad col");
    }

    fn track_caller_not_on_trait_method(&self);

    #[track_caller]
    fn track_caller_through_self(self: Box<Self>, line: u32, col: u32);
}

impl Tracked for () {
    // We have `#[track_caller]` on the implementation of the method,
    // but not on the definition of the method in the trait. Therefore,
    // caller location information will *not* work through a method call
    // on a trait object. Instead, we will get the location of this method
    #[track_caller]
    fn track_caller_not_on_trait_method(&self) {
        let location = std::panic::Location::caller();
        assert_eq!(location.file(), file!());
        assert_eq!(location.line(), line!() - 3);
        assert_eq!(location.column(), 5);
    }

    // We don't have a `#[track_caller]` attribute, but
    // `#[track_caller]` is present on the trait definition,
    // so we'll still get location information
    fn track_caller_through_self(self: Box<Self>, line: u32, col: u32) {
        let location = std::panic::Location::caller();
        assert_eq!(location.file(), file!());
        // The trait method definition is annotated with `#[track_caller]`,
        // so caller location information will work through a method
        // call on a trait object
        assert_eq!(location.line(), line, "Bad line");
        assert_eq!(location.column(), col, "Bad col");
    }
}

fn main() {
    let tracked: &dyn Tracked = &();
    // The column is the start of 'track_caller_trait_method'
    tracked.track_caller_trait_method(line!(), 13);

    const TRACKED: &dyn Tracked = &();
    // The column is the start of 'track_caller_trait_method'
    TRACKED.track_caller_trait_method(line!(), 13);
    TRACKED.track_caller_not_on_trait_method();

    // The column is the start of `track_caller_through_self`
    let boxed: Box<dyn Tracked> = Box::new(());
    boxed.track_caller_through_self(line!(), 11);
}