Skip to content

Commit f8db8ff

Browse files
committed
Permit #[track_caller] on inherent methods
1 parent 6446f19 commit f8db8ff

File tree

3 files changed

+43
-14
lines changed

3 files changed

+43
-14
lines changed

src/librustc/hir/check_attr.rs

+32-12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ use std::fmt::{self, Display};
1616
use syntax::{attr, symbol::sym};
1717
use syntax_pos::Span;
1818

19+
#[derive(Copy, Clone, PartialEq)]
20+
pub(crate) enum MethodKind {
21+
Trait { body: bool },
22+
Inherent,
23+
}
24+
1925
#[derive(Copy, Clone, PartialEq)]
2026
pub(crate) enum Target {
2127
ExternCrate,
@@ -38,7 +44,7 @@ pub(crate) enum Target {
3844
Expression,
3945
Statement,
4046
AssocConst,
41-
Method { body: bool },
47+
Method(MethodKind),
4248
AssocTy,
4349
ForeignFn,
4450
ForeignStatic,
@@ -68,7 +74,7 @@ impl Display for Target {
6874
Target::Expression => "expression",
6975
Target::Statement => "statement",
7076
Target::AssocConst => "associated const",
71-
Target::Method { .. } => "method",
77+
Target::Method(_) => "method",
7278
Target::AssocTy => "associated type",
7379
Target::ForeignFn => "foreign function",
7480
Target::ForeignStatic => "foreign static item",
@@ -103,10 +109,10 @@ impl Target {
103109
match trait_item.kind {
104110
TraitItemKind::Const(..) => Target::AssocConst,
105111
TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
106-
Target::Method { body: false }
112+
Target::Method(MethodKind::Trait { body: false })
107113
}
108114
TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
109-
Target::Method { body: true }
115+
Target::Method(MethodKind::Trait { body: true })
110116
}
111117
TraitItemKind::Type(..) => Target::AssocTy,
112118
}
@@ -120,10 +126,22 @@ impl Target {
120126
}
121127
}
122128

123-
fn from_impl_item(impl_item: &hir::ImplItem) -> Target {
129+
fn from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem) -> Target {
124130
match impl_item.kind {
125131
hir::ImplItemKind::Const(..) => Target::Const,
126-
hir::ImplItemKind::Method(..) => Target::Method { body: true },
132+
hir::ImplItemKind::Method(..) => {
133+
let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id);
134+
let containing_item = tcx.hir().expect_item(parent_hir_id);
135+
let containing_impl_is_for_trait = match &containing_item.kind {
136+
hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr.is_some(),
137+
_ => bug!("parent of an ImplItem must be an Impl"),
138+
};
139+
if containing_impl_is_for_trait {
140+
Target::Method(MethodKind::Trait { body: true })
141+
} else {
142+
Target::Method(MethodKind::Inherent)
143+
}
144+
}
127145
hir::ImplItemKind::TyAlias(..) => Target::TyAlias,
128146
hir::ImplItemKind::OpaqueTy(..) => Target::OpaqueTy,
129147
}
@@ -176,8 +194,9 @@ impl CheckAttrVisitor<'tcx> {
176194
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
177195
fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool {
178196
match target {
179-
Target::Fn | Target::Closure | Target::Method { body: true } => true,
180-
Target::Method { body: false } | Target::ForeignFn => {
197+
Target::Fn | Target::Closure | Target::Method(MethodKind::Trait { body: true })
198+
| Target::Method(MethodKind::Inherent) => true,
199+
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
181200
self.tcx.struct_span_lint_hir(
182201
UNUSED_ATTRIBUTES,
183202
hir_id,
@@ -216,8 +235,8 @@ impl CheckAttrVisitor<'tcx> {
216235
).emit();
217236
false
218237
}
219-
Target::Fn => true,
220-
Target::Method { .. } => {
238+
Target::Fn | Target::Method(MethodKind::Inherent) => true,
239+
Target::Method(_) => {
221240
struct_span_err!(
222241
self.tcx.sess,
223242
*attr_span,
@@ -278,7 +297,8 @@ impl CheckAttrVisitor<'tcx> {
278297
/// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
279298
fn check_target_feature(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
280299
match target {
281-
Target::Fn | Target::Method { body: true } => true,
300+
Target::Fn | Target::Method(MethodKind::Trait { body: true })
301+
| Target::Method(MethodKind::Inherent) => true,
282302
_ => {
283303
self.tcx.sess
284304
.struct_span_err(attr.span, "attribute should be applied to a function")
@@ -471,7 +491,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
471491
}
472492

473493
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
474-
let target = Target::from_impl_item(impl_item);
494+
let target = Target::from_impl_item(self.tcx, impl_item);
475495
self.check_attributes(impl_item.hir_id, &impl_item.attrs, &impl_item.span, target, None);
476496
intravisit::walk_impl_item(self, impl_item)
477497
}

src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// check-fail
2+
13
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
24

35
trait Trait {
@@ -9,4 +11,11 @@ impl Trait for u64 {
911
fn unwrap(&self) {}
1012
}
1113

14+
struct S;
15+
16+
impl S {
17+
#[track_caller] // ok
18+
fn foo() {}
19+
}
20+
1221
fn main() {}

src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
2-
--> $DIR/error-with-trait-fn-impl.rs:1:12
2+
--> $DIR/error-with-trait-fn-impl.rs:3:12
33
|
44
LL | #![feature(track_caller)]
55
| ^^^^^^^^^^^^
66
|
77
= note: `#[warn(incomplete_features)]` on by default
88

99
error[E0738]: `#[track_caller]` may not be used on trait methods
10-
--> $DIR/error-with-trait-fn-impl.rs:8:5
10+
--> $DIR/error-with-trait-fn-impl.rs:10:5
1111
|
1212
LL | #[track_caller]
1313
| ^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)