]> git.proxmox.com Git - rustc.git/blame - library/core/src/panic/location.rs
New upstream version 1.61.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]
ee023bcb 86 #[inline]
94222f64
XL
87 pub const fn caller() -> &'static Location<'static> {
88 crate::intrinsics::caller_location()
89 }
90
91 /// Returns the name of the source file from which the panic originated.
92 ///
93 /// # `&str`, not `&Path`
94 ///
95 /// The returned name refers to a source path on the compiling system, but it isn't valid to
96 /// represent this directly as a `&Path`. The compiled code may run on a different system with
97 /// a different `Path` implementation than the system providing the contents and this library
98 /// does not currently have a different "host path" type.
99 ///
100 /// The most surprising behavior occurs when "the same" file is reachable via multiple paths in
101 /// the module system (usually using the `#[path = "..."]` attribute or similar), which can
102 /// cause what appears to be identical code to return differing values from this function.
103 ///
104 /// # Cross-compilation
105 ///
106 /// This value is not suitable for passing to `Path::new` or similar constructors when the host
107 /// platform and target platform differ.
108 ///
109 /// # Examples
110 ///
111 /// ```should_panic
112 /// use std::panic;
113 ///
114 /// panic::set_hook(Box::new(|panic_info| {
115 /// if let Some(location) = panic_info.location() {
116 /// println!("panic occurred in file '{}'", location.file());
117 /// } else {
118 /// println!("panic occurred but can't get location information...");
119 /// }
120 /// }));
121 ///
122 /// panic!("Normal panic");
123 /// ```
3c0e092e 124 #[must_use]
94222f64
XL
125 #[stable(feature = "panic_hooks", since = "1.10.0")]
126 pub fn file(&self) -> &str {
127 self.file
128 }
129
130 /// Returns the line number from which the panic originated.
131 ///
132 /// # Examples
133 ///
134 /// ```should_panic
135 /// use std::panic;
136 ///
137 /// panic::set_hook(Box::new(|panic_info| {
138 /// if let Some(location) = panic_info.location() {
139 /// println!("panic occurred at line {}", location.line());
140 /// } else {
141 /// println!("panic occurred but can't get location information...");
142 /// }
143 /// }));
144 ///
145 /// panic!("Normal panic");
146 /// ```
3c0e092e 147 #[must_use]
94222f64
XL
148 #[stable(feature = "panic_hooks", since = "1.10.0")]
149 pub fn line(&self) -> u32 {
150 self.line
151 }
152
153 /// Returns the column from which the panic originated.
154 ///
155 /// # Examples
156 ///
157 /// ```should_panic
158 /// use std::panic;
159 ///
160 /// panic::set_hook(Box::new(|panic_info| {
161 /// if let Some(location) = panic_info.location() {
162 /// println!("panic occurred at column {}", location.column());
163 /// } else {
164 /// println!("panic occurred but can't get location information...");
165 /// }
166 /// }));
167 ///
168 /// panic!("Normal panic");
169 /// ```
3c0e092e 170 #[must_use]
94222f64
XL
171 #[stable(feature = "panic_col", since = "1.25.0")]
172 pub fn column(&self) -> u32 {
173 self.col
174 }
175}
176
177#[unstable(
178 feature = "panic_internals",
179 reason = "internal details of the implementation of the `panic!` and related macros",
180 issue = "none"
181)]
182impl<'a> Location<'a> {
183 #[doc(hidden)]
184 pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
185 Location { file, line, col }
186 }
187}
188
189#[stable(feature = "panic_hook_display", since = "1.26.0")]
190impl fmt::Display for Location<'_> {
191 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
192 write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
193 }
194}