Port #[rustc_pass_by_value] to the new attribute system
This commit is contained in:
@@ -284,6 +284,9 @@ pub enum AttributeKind {
|
||||
/// Represents `#[optimize(size|speed)]`
|
||||
Optimize(OptimizeAttr, Span),
|
||||
|
||||
/// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
|
||||
PassByValue(Span),
|
||||
|
||||
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
|
||||
PubTransparent(Span),
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ impl AttributeKind {
|
||||
Naked(..) => No,
|
||||
NoMangle(..) => No,
|
||||
Optimize(..) => No,
|
||||
PassByValue(..) => Yes,
|
||||
PubTransparent(..) => Yes,
|
||||
Repr(..) => No,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
|
||||
@@ -17,3 +17,10 @@ impl<S: Stage> NoArgsAttributeParser<S> for PubTransparentParser {
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::PubTransparent;
|
||||
}
|
||||
|
||||
pub(crate) struct PassByValueParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for PassByValueParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_pass_by_value];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::PassByValue;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::deprecation::DeprecationParser;
|
||||
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
|
||||
use crate::attributes::link_attrs::{LinkNameParser, LinkSectionParser};
|
||||
use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
|
||||
use crate::attributes::lint_helpers::{AsPtrParser, PassByValueParser, PubTransparentParser};
|
||||
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
|
||||
use crate::attributes::must_use::MustUseParser;
|
||||
use crate::attributes::repr::{AlignParser, ReprParser};
|
||||
@@ -142,6 +142,7 @@ attribute_parsers!(
|
||||
Single<WithoutArgs<LoopMatchParser>>,
|
||||
Single<WithoutArgs<MayDangleParser>>,
|
||||
Single<WithoutArgs<NoMangleParser>>,
|
||||
Single<WithoutArgs<PassByValueParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
// tidy-alphabetical-end
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use rustc_attr_data_structures::{AttributeKind, find_attr};
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::sym;
|
||||
|
||||
use crate::lints::PassByValueDiag;
|
||||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
@@ -45,14 +45,16 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
|
||||
fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<String> {
|
||||
if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
|
||||
match path.res {
|
||||
Res::Def(_, def_id) if cx.tcx.has_attr(def_id, sym::rustc_pass_by_value) => {
|
||||
Res::Def(_, def_id)
|
||||
if find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::PassByValue(_)) =>
|
||||
{
|
||||
let name = cx.tcx.item_ident(def_id);
|
||||
let path_segment = path.segments.last().unwrap();
|
||||
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
|
||||
}
|
||||
Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
|
||||
if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() {
|
||||
if cx.tcx.has_attr(adt.did(), sym::rustc_pass_by_value) {
|
||||
if find_attr!(cx.tcx.get_all_attrs(adt.did()), AttributeKind::PassByValue(_)) {
|
||||
return Some(cx.tcx.def_path_str_with_args(adt.did(), args));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,6 +293,7 @@ fn emit_malformed_attribute(
|
||||
| sym::rustc_force_inline
|
||||
| sym::rustc_confusables
|
||||
| sym::rustc_skip_during_method_dispatch
|
||||
| sym::rustc_pass_by_value
|
||||
| sym::repr
|
||||
| sym::align
|
||||
| sym::deprecated
|
||||
|
||||
@@ -213,6 +213,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
Attribute::Parsed(AttributeKind::Used { span: attr_span, .. }) => {
|
||||
self.check_used(*attr_span, target, span);
|
||||
}
|
||||
&Attribute::Parsed(AttributeKind::PassByValue(attr_span)) => {
|
||||
self.check_pass_by_value(attr_span, span, target)
|
||||
}
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
match attr.path().as_slice() {
|
||||
@@ -275,7 +278,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
| [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr.span(), span, target),
|
||||
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
|
||||
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
|
||||
[sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
|
||||
[sym::rustc_allow_incoherent_impl, ..] => {
|
||||
self.check_allow_incoherent_impl(attr, span, target)
|
||||
}
|
||||
@@ -1438,11 +1440,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
}
|
||||
|
||||
/// Warns against some misuses of `#[pass_by_value]`
|
||||
fn check_pass_by_value(&self, attr: &Attribute, span: Span, target: Target) {
|
||||
fn check_pass_by_value(&self, attr_span: Span, span: Span, target: Target) {
|
||||
match target {
|
||||
Target::Struct | Target::Enum | Target::TyAlias => {}
|
||||
_ => {
|
||||
self.dcx().emit_err(errors::PassByValue { attr_span: attr.span(), span });
|
||||
self.dcx().emit_err(errors::PassByValue { attr_span, span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user