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);
}
|