Permit #[track_caller] on inherent methods
This commit is contained in:
parent
6446f192c7
commit
f8db8ffcf3
3 changed files with 43 additions and 14 deletions
|
@ -16,6 +16,12 @@ use std::fmt::{self, Display};
|
||||||
use syntax::{attr, symbol::sym};
|
use syntax::{attr, symbol::sym};
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
pub(crate) enum MethodKind {
|
||||||
|
Trait { body: bool },
|
||||||
|
Inherent,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub(crate) enum Target {
|
pub(crate) enum Target {
|
||||||
ExternCrate,
|
ExternCrate,
|
||||||
|
@ -38,7 +44,7 @@ pub(crate) enum Target {
|
||||||
Expression,
|
Expression,
|
||||||
Statement,
|
Statement,
|
||||||
AssocConst,
|
AssocConst,
|
||||||
Method { body: bool },
|
Method(MethodKind),
|
||||||
AssocTy,
|
AssocTy,
|
||||||
ForeignFn,
|
ForeignFn,
|
||||||
ForeignStatic,
|
ForeignStatic,
|
||||||
|
@ -68,7 +74,7 @@ impl Display for Target {
|
||||||
Target::Expression => "expression",
|
Target::Expression => "expression",
|
||||||
Target::Statement => "statement",
|
Target::Statement => "statement",
|
||||||
Target::AssocConst => "associated const",
|
Target::AssocConst => "associated const",
|
||||||
Target::Method { .. } => "method",
|
Target::Method(_) => "method",
|
||||||
Target::AssocTy => "associated type",
|
Target::AssocTy => "associated type",
|
||||||
Target::ForeignFn => "foreign function",
|
Target::ForeignFn => "foreign function",
|
||||||
Target::ForeignStatic => "foreign static item",
|
Target::ForeignStatic => "foreign static item",
|
||||||
|
@ -103,10 +109,10 @@ impl Target {
|
||||||
match trait_item.kind {
|
match trait_item.kind {
|
||||||
TraitItemKind::Const(..) => Target::AssocConst,
|
TraitItemKind::Const(..) => Target::AssocConst,
|
||||||
TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
|
TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
|
||||||
Target::Method { body: false }
|
Target::Method(MethodKind::Trait { body: false })
|
||||||
}
|
}
|
||||||
TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
|
TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
|
||||||
Target::Method { body: true }
|
Target::Method(MethodKind::Trait { body: true })
|
||||||
}
|
}
|
||||||
TraitItemKind::Type(..) => Target::AssocTy,
|
TraitItemKind::Type(..) => Target::AssocTy,
|
||||||
}
|
}
|
||||||
|
@ -120,10 +126,22 @@ impl Target {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_impl_item(impl_item: &hir::ImplItem) -> Target {
|
fn from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem) -> Target {
|
||||||
match impl_item.kind {
|
match impl_item.kind {
|
||||||
hir::ImplItemKind::Const(..) => Target::Const,
|
hir::ImplItemKind::Const(..) => Target::Const,
|
||||||
hir::ImplItemKind::Method(..) => Target::Method { body: true },
|
hir::ImplItemKind::Method(..) => {
|
||||||
|
let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id);
|
||||||
|
let containing_item = tcx.hir().expect_item(parent_hir_id);
|
||||||
|
let containing_impl_is_for_trait = match &containing_item.kind {
|
||||||
|
hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr.is_some(),
|
||||||
|
_ => bug!("parent of an ImplItem must be an Impl"),
|
||||||
|
};
|
||||||
|
if containing_impl_is_for_trait {
|
||||||
|
Target::Method(MethodKind::Trait { body: true })
|
||||||
|
} else {
|
||||||
|
Target::Method(MethodKind::Inherent)
|
||||||
|
}
|
||||||
|
}
|
||||||
hir::ImplItemKind::TyAlias(..) => Target::TyAlias,
|
hir::ImplItemKind::TyAlias(..) => Target::TyAlias,
|
||||||
hir::ImplItemKind::OpaqueTy(..) => Target::OpaqueTy,
|
hir::ImplItemKind::OpaqueTy(..) => Target::OpaqueTy,
|
||||||
}
|
}
|
||||||
|
@ -176,8 +194,9 @@ impl CheckAttrVisitor<'tcx> {
|
||||||
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
|
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
|
||||||
fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool {
|
fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool {
|
||||||
match target {
|
match target {
|
||||||
Target::Fn | Target::Closure | Target::Method { body: true } => true,
|
Target::Fn | Target::Closure | Target::Method(MethodKind::Trait { body: true })
|
||||||
Target::Method { body: false } | Target::ForeignFn => {
|
| Target::Method(MethodKind::Inherent) => true,
|
||||||
|
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
|
||||||
self.tcx.struct_span_lint_hir(
|
self.tcx.struct_span_lint_hir(
|
||||||
UNUSED_ATTRIBUTES,
|
UNUSED_ATTRIBUTES,
|
||||||
hir_id,
|
hir_id,
|
||||||
|
@ -216,8 +235,8 @@ impl CheckAttrVisitor<'tcx> {
|
||||||
).emit();
|
).emit();
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Target::Fn => true,
|
Target::Fn | Target::Method(MethodKind::Inherent) => true,
|
||||||
Target::Method { .. } => {
|
Target::Method(_) => {
|
||||||
struct_span_err!(
|
struct_span_err!(
|
||||||
self.tcx.sess,
|
self.tcx.sess,
|
||||||
*attr_span,
|
*attr_span,
|
||||||
|
@ -278,7 +297,8 @@ impl CheckAttrVisitor<'tcx> {
|
||||||
/// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
|
/// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
|
||||||
fn check_target_feature(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
|
fn check_target_feature(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
|
||||||
match target {
|
match target {
|
||||||
Target::Fn | Target::Method { body: true } => true,
|
Target::Fn | Target::Method(MethodKind::Trait { body: true })
|
||||||
|
| Target::Method(MethodKind::Inherent) => true,
|
||||||
_ => {
|
_ => {
|
||||||
self.tcx.sess
|
self.tcx.sess
|
||||||
.struct_span_err(attr.span, "attribute should be applied to a function")
|
.struct_span_err(attr.span, "attribute should be applied to a function")
|
||||||
|
@ -471,7 +491,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
|
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
|
||||||
let target = Target::from_impl_item(impl_item);
|
let target = Target::from_impl_item(self.tcx, impl_item);
|
||||||
self.check_attributes(impl_item.hir_id, &impl_item.attrs, &impl_item.span, target, None);
|
self.check_attributes(impl_item.hir_id, &impl_item.attrs, &impl_item.span, target, None);
|
||||||
intravisit::walk_impl_item(self, impl_item)
|
intravisit::walk_impl_item(self, impl_item)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// check-fail
|
||||||
|
|
||||||
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
|
||||||
|
|
||||||
trait Trait {
|
trait Trait {
|
||||||
|
@ -9,4 +11,11 @@ impl Trait for u64 {
|
||||||
fn unwrap(&self) {}
|
fn unwrap(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
#[track_caller] // ok
|
||||||
|
fn foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
|
||||||
--> $DIR/error-with-trait-fn-impl.rs:1:12
|
--> $DIR/error-with-trait-fn-impl.rs:3:12
|
||||||
|
|
|
|
||||||
LL | #![feature(track_caller)]
|
LL | #![feature(track_caller)]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
@ -7,7 +7,7 @@ LL | #![feature(track_caller)]
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
error[E0738]: `#[track_caller]` may not be used on trait methods
|
error[E0738]: `#[track_caller]` may not be used on trait methods
|
||||||
--> $DIR/error-with-trait-fn-impl.rs:8:5
|
--> $DIR/error-with-trait-fn-impl.rs:10:5
|
||||||
|
|
|
|
||||||
LL | #[track_caller]
|
LL | #[track_caller]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue