提交 f8db8ffc 编写于 作者: V varkor

Permit #[track_caller] on inherent methods

上级 6446f192
......@@ -16,6 +16,12 @@
use syntax::{attr, symbol::sym};
use syntax_pos::Span;
#[derive(Copy, Clone, PartialEq)]
pub(crate) enum MethodKind {
Trait { body: bool },
Inherent,
}
#[derive(Copy, Clone, PartialEq)]
pub(crate) enum Target {
ExternCrate,
......@@ -38,7 +44,7 @@ pub(crate) enum Target {
Expression,
Statement,
AssocConst,
Method { body: bool },
Method(MethodKind),
AssocTy,
ForeignFn,
ForeignStatic,
......@@ -68,7 +74,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Target::Expression => "expression",
Target::Statement => "statement",
Target::AssocConst => "associated const",
Target::Method { .. } => "method",
Target::Method(_) => "method",
Target::AssocTy => "associated type",
Target::ForeignFn => "foreign function",
Target::ForeignStatic => "foreign static item",
......@@ -103,10 +109,10 @@ fn from_trait_item(trait_item: &TraitItem) -> Target {
match trait_item.kind {
TraitItemKind::Const(..) => Target::AssocConst,
TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => {
Target::Method { body: false }
Target::Method(MethodKind::Trait { body: false })
}
TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => {
Target::Method { body: true }
Target::Method(MethodKind::Trait { body: true })
}
TraitItemKind::Type(..) => Target::AssocTy,
}
......@@ -120,10 +126,22 @@ fn from_foreign_item(foreign_item: &hir::ForeignItem) -> 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 {
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::OpaqueTy(..) => Target::OpaqueTy,
}
......@@ -176,8 +194,9 @@ fn check_attributes(
/// 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 {
match target {
Target::Fn | Target::Closure | Target::Method { body: true } => true,
Target::Method { body: false } | Target::ForeignFn => {
Target::Fn | Target::Closure | Target::Method(MethodKind::Trait { body: true })
| Target::Method(MethodKind::Inherent) => true,
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
self.tcx.struct_span_lint_hir(
UNUSED_ATTRIBUTES,
hir_id,
......@@ -216,8 +235,8 @@ fn check_track_caller(
).emit();
false
}
Target::Fn => true,
Target::Method { .. } => {
Target::Fn | Target::Method(MethodKind::Inherent) => true,
Target::Method(_) => {
struct_span_err!(
self.tcx.sess,
*attr_span,
......@@ -278,7 +297,8 @@ fn check_marker(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
/// 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 {
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
.struct_span_err(attr.span, "attribute should be applied to a function")
......@@ -471,7 +491,7 @@ fn visit_foreign_item(&mut self, f_item: &'tcx hir::ForeignItem) {
}
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);
intravisit::walk_impl_item(self, impl_item)
}
......
// check-fail
#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete
trait Trait {
......@@ -9,4 +11,11 @@ impl Trait for u64 {
fn unwrap(&self) {}
}
struct S;
impl S {
#[track_caller] // ok
fn foo() {}
}
fn main() {}
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)]
| ^^^^^^^^^^^^
......@@ -7,7 +7,7 @@ LL | #![feature(track_caller)]
= note: `#[warn(incomplete_features)]` on by default
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]
| ^^^^^^^^^^^^^^^
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册