]> git.proxmox.com Git - rustc.git/blame - library/core/src/panic/location.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / library / core / src / panic / location.rs
CommitLineData
94222f64
XL
1use crate::fmt;
2
3/// A struct containing information about the location of a panic.
4///
5/// This structure is created by [`PanicInfo::location()`].
6///
7/// [`PanicInfo::location()`]: crate::panic::PanicInfo::location
8///
9/// # Examples
10///
11/// ```should_panic
12/// use std::panic;
13///
14/// panic::set_hook(Box::new(|panic_info| {
15/// if let Some(location) = panic_info.location() {
16/// println!("panic occurred in file '{}' at line {}", location.file(), location.line());
17/// } else {
18/// println!("panic occurred but can't get location information...");
19/// }
20/// }));
21///
22/// panic!("Normal panic");
23/// ```
24///
25/// # Comparisons
26///
27/// Comparisons for equality and ordering are made in file, line, then column priority.
28/// Files are compared as strings, not `Path`, which could be unexpected.
29/// See [`Location::file`]'s documentation for more discussion.
30#[lang = "panic_location"]
31#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
32#[stable(feature = "panic_hooks", since = "1.10.0")]
33pub struct Location<'a> {
34 file: &'a str,
35 line: u32,
36 col: u32,
37}
38
39impl<'a> Location<'a> {
40 /// Returns the source location of the caller of this function. If that function's caller is
41 /// annotated then its call location will be returned, and so on up the stack to the first call
42 /// within a non-tracked function body.
43 ///
44 /// # Examples
45 ///
46 /// ```
47 /// use std::panic::Location;
48 ///
49 /// /// Returns the [`Location`] at which it is called.
50 /// #[track_caller]
51 /// fn get_caller_location() -> &'static Location<'static> {
52 /// Location::caller()
53 /// }
54 ///
55 /// /// Returns a [`Location`] from within this function's definition.
56 /// fn get_just_one_location() -> &'static Location<'static> {
57 /// get_caller_location()
58 /// }
59 ///
60 /// let fixed_location = get_just_one_location();
61 /// assert_eq!(fixed_location.file(), file!());
62 /// assert_eq!(fixed_location.line(), 14);
63 /// assert_eq!(fixed_location.column(), 5);
64 ///
65 /// // running the same untracked function in a different location gives us the same result
66 /// let second_fixed_location = get_just_one_location();
67 /// assert_eq!(fixed_location.file(), second_fixed_location.file());
68 /// assert_eq!(fixed_location.line(), second_fixed_location.line());
69 /// assert_eq!(fixed_location.column(), second_fixed_location.column());
70 ///
71 /// let this_location = get_caller_location();
72 /// assert_eq!(this_location.file(), file!());
73 /// assert_eq!(this_location.line(), 28);
74 /// assert_eq!(this_location.column(), 21);
75 ///
76 /// // running the tracked function in a different location produces a different value
77 /// let another_location = get_caller_location();
78 /// assert_eq!(this_location.file(), another_location.file());
79 /// assert_ne!(this_location.line(), another_location.line());
80 /// assert_ne!(this_location.column(), another_location.column());
81 /// ```
3c0e092e 82 #[must_use]
94222f64
XL
83 #[stable(feature = "track_caller", since = "1.46.0")]
84 #[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
85 #[track_caller]
86 pub const fn caller() -> &'static Location<'static> {
87 crate::intrinsics::caller_location()
88 }
89
90 /// Returns the name of the source file from which the panic originated.
91 ///
92 /// # `&str`, not `&Path`
93 ///
94 /// The returned name refers to a source path on the compiling system, but it isn't valid to
95 /// represent this directly as a `&Path`. The compiled code may run on a different system with
96 /// a different `Path` implementation than the system providing the contents and this library
97 /// does not currently have a different "host path" type.
98 ///
99 /// The most surprising behavior occurs when "the same" file is reachable via multiple paths in
100 /// the module system (usually using the `#[path = "..."]` attribute or similar), which can
101 /// cause what appears to be identical code to return differing values from this function.
102 ///
103 /// # Cross-compilation
104 ///
105 /// This value is not suitable for passing to `Path::new` or similar constructors when the host
106 /// platform and target platform differ.
107 ///
108 /// # Examples
109 ///
110 /// ```should_panic
111 /// use std::panic;
112 ///
113 /// panic::set_hook(Box::new(|panic_info| {
114 /// if let Some(location) = panic_info.location() {
115 /// println!("panic occurred in file '{}'", location.file());
116 /// } else {
117 /// println!("panic occurred but can't get location information...");
118 /// }
119 /// }));
120 ///
121 /// panic!("Normal panic");
122 /// ```
3c0e092e 123 #[must_use]
94222f64
XL
124 #[stable(feature = "panic_hooks", since = "1.10.0")]
125 pub fn file(&self) -> &str {
126 self.file
127 }
128
129 /// Returns the line number from which the panic originated.
130 ///
131 /// # Examples
132 ///
133 /// ```should_panic
134 /// use std::panic;
135 ///
136 /// panic::set_hook(Box::new(|panic_info| {
137 /// if let Some(location) = panic_info.location() {
138 /// println!("panic occurred at line {}", location.line());
139 /// } else {
140 /// println!("panic occurred but can't get location information...");
141 /// }
142 /// }));
143 ///
144 /// panic!("Normal panic");
145 /// ```
3c0e092e 146 #[must_use]
94222f64
XL
147 #[stable(feature = "panic_hooks", since = "1.10.0")]
148 pub fn line(&self) -> u32 {
149 self.line
150 }
151
152 /// Returns the column from which the panic originated.
153 ///
154 /// # Examples
155 ///
156 /// ```should_panic
157 /// use std::panic;
158 ///
159 /// panic::set_hook(Box::new(|panic_info| {
160 /// if let Some(location) = panic_info.location() {
161 /// println!("panic occurred at column {}", location.column());
162 /// } else {
163 /// println!("panic occurred but can't get location information...");
164 /// }
165 /// }));
166 ///
167 /// panic!("Normal panic");
168 /// ```
3c0e092e 169 #[must_use]
94222f64
XL
170 #[stable(feature = "panic_col", since = "1.25.0")]
171 pub fn column(&self) -> u32 {
172 self.col
173 }
174}
175
176#[unstable(
177 feature = "panic_internals",
178 reason = "internal details of the implementation of the `panic!` and related macros",
179 issue = "none"
180)]
181impl<'a> Location<'a> {
182 #[doc(hidden)]
183 pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
184 Location { file, line, col }
185 }
186}
187
188#[stable(feature = "panic_hook_display", since = "1.26.0")]
189impl fmt::Display for Location<'_> {
190 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
191 write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
192 }
193}