Rollup merge of #142695 - GrigorenkoPV:attributes/rustc_skip_during_method_dispatch, r=jdonszelmann
Port `#[rustc_skip_during_method_dispatch]` to the new attribute system Part of rust-lang/rust#131229 r? ``@jdonszelmann``
This commit is contained in:
commit
69cc875438
17 changed files with 246 additions and 41 deletions
|
|
@ -259,6 +259,9 @@ pub enum AttributeKind {
|
|||
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
|
||||
Repr(ThinVec<(ReprAttr, Span)>),
|
||||
|
||||
/// Represents `#[rustc_skip_during_method_dispatch]`.
|
||||
SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
|
||||
|
||||
/// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
|
||||
Stability {
|
||||
stability: Stability,
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ impl<S: Stage> SingleAttributeParser<S> for ColdParser {
|
|||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
if !args.no_args() {
|
||||
cx.expected_no_args(args.span().unwrap_or(cx.attr_span));
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -67,8 +67,8 @@ pub(crate) struct NakedParser {
|
|||
impl<S: Stage> AttributeParser<S> for NakedParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> =
|
||||
&[(&[sym::naked], template!(Word), |this, cx, args| {
|
||||
if !args.no_args() {
|
||||
cx.expected_no_args(args.span().unwrap_or(cx.attr_span));
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -175,10 +175,10 @@ impl<S: Stage> SingleAttributeParser<S> for NoMangleParser {
|
|||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
if !args.no_args() {
|
||||
cx.expected_no_args(args.span().unwrap_or(cx.attr_span));
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
return None;
|
||||
};
|
||||
}
|
||||
|
||||
Some(AttributeKind::NoMangle(cx.attr_span))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@ impl<S: Stage> SingleAttributeParser<S> for AsPtrParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
// FIXME: check that there's no args (this is currently checked elsewhere)
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
}
|
||||
Some(AttributeKind::AsPtr(cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
|
@ -27,8 +29,10 @@ impl<S: Stage> SingleAttributeParser<S> for PubTransparentParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
// FIXME: check that there's no args (this is currently checked elsewhere)
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
}
|
||||
Some(AttributeKind::PubTransparent(cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ pub(crate) mod must_use;
|
|||
pub(crate) mod repr;
|
||||
pub(crate) mod semantics;
|
||||
pub(crate) mod stability;
|
||||
pub(crate) mod traits;
|
||||
pub(crate) mod transparency;
|
||||
pub(crate) mod util;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@ impl<S: Stage> SingleAttributeParser<S> for MayDangleParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
}
|
||||
Some(AttributeKind::MayDangle(cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,10 @@ impl<S: Stage> SingleAttributeParser<S> for ConstStabilityIndirectParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
|
||||
fn convert(_cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.expected_no_args(span);
|
||||
}
|
||||
Some(AttributeKind::ConstStabilityIndirect)
|
||||
}
|
||||
}
|
||||
|
|
@ -361,8 +364,8 @@ pub(crate) fn parse_unstability<S: Stage>(
|
|||
};
|
||||
}
|
||||
Some(sym::soft) => {
|
||||
if !param.args().no_args() {
|
||||
cx.emit_err(session_diagnostics::SoftNoArgs { span: param.span() });
|
||||
if let Err(span) = args.no_args() {
|
||||
cx.emit_err(session_diagnostics::SoftNoArgs { span });
|
||||
}
|
||||
is_soft = true;
|
||||
}
|
||||
|
|
|
|||
54
compiler/rustc_attr_parsing/src/attributes/traits.rs
Normal file
54
compiler/rustc_attr_parsing/src/attributes/traits.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use core::mem;
|
||||
|
||||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::ArgParser;
|
||||
|
||||
pub(crate) struct SkipDuringMethodDispatchParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
|
||||
const TEMPLATE: AttributeTemplate = template!(List: "array, boxed_slice");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let mut array = false;
|
||||
let mut boxed_slice = false;
|
||||
let Some(args) = args.list() else {
|
||||
cx.expected_list(cx.attr_span);
|
||||
return None;
|
||||
};
|
||||
if args.is_empty() {
|
||||
cx.expected_at_least_one_argument(args.span);
|
||||
return None;
|
||||
}
|
||||
for arg in args.mixed() {
|
||||
let Some(arg) = arg.meta_item() else {
|
||||
cx.unexpected_literal(arg.span());
|
||||
continue;
|
||||
};
|
||||
if let Err(span) = arg.args().no_args() {
|
||||
cx.expected_no_args(span);
|
||||
}
|
||||
let path = arg.path();
|
||||
let (key, skip): (Symbol, &mut bool) = match path.word_sym() {
|
||||
Some(key @ sym::array) => (key, &mut array),
|
||||
Some(key @ sym::boxed_slice) => (key, &mut boxed_slice),
|
||||
_ => {
|
||||
cx.expected_specific_argument(path.span(), vec!["array", "boxed_slice"]);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if mem::replace(skip, true) {
|
||||
cx.duplicate_key(arg.span(), key);
|
||||
}
|
||||
}
|
||||
Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ use crate::attributes::semantics::MayDangleParser;
|
|||
use crate::attributes::stability::{
|
||||
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
|
||||
};
|
||||
use crate::attributes::traits::SkipDuringMethodDispatchParser;
|
||||
use crate::attributes::transparency::TransparencyParser;
|
||||
use crate::attributes::{AttributeParser as _, Combine, Single};
|
||||
use crate::parser::{ArgParser, MetaItemParser, PathParser};
|
||||
|
|
@ -119,6 +120,7 @@ attribute_parsers!(
|
|||
Single<OptimizeParser>,
|
||||
Single<PubTransparentParser>,
|
||||
Single<RustcForceInlineParser>,
|
||||
Single<SkipDuringMethodDispatchParser>,
|
||||
Single<TransparencyParser>,
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
|
|
@ -325,6 +327,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
|
||||
self.emit_err(AttributeParseError {
|
||||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn expected_specific_argument(
|
||||
&self,
|
||||
span: Span,
|
||||
|
|
|
|||
|
|
@ -169,9 +169,15 @@ impl<'a> ArgParser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Asserts that there are no arguments
|
||||
pub fn no_args(&self) -> bool {
|
||||
matches!(self, Self::NoArgs)
|
||||
/// Assert that there were no args.
|
||||
/// If there were, get a span to the arguments
|
||||
/// (to pass to [`AcceptContext::expected_no_args`](crate::context::AcceptContext::expected_no_args)).
|
||||
pub fn no_args(&self) -> Result<(), Span> {
|
||||
match self {
|
||||
Self::NoArgs => Ok(()),
|
||||
Self::List(args) => Err(args.span),
|
||||
Self::NameValue(args) => Err(args.eq_span.to(args.value_span)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -496,6 +496,7 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
|
|||
pub(crate) enum AttributeParseErrorReason {
|
||||
ExpectedNoArgs,
|
||||
ExpectedStringLiteral { byte_string: Option<Span> },
|
||||
ExpectedAtLeastOneArgument,
|
||||
ExpectedSingleArgument,
|
||||
ExpectedList,
|
||||
UnexpectedLiteral,
|
||||
|
|
@ -539,6 +540,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
diag.span_label(self.span, "expected a single argument here");
|
||||
diag.code(E0805);
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedAtLeastOneArgument => {
|
||||
diag.span_label(self.span, "expected at least 1 argument here");
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedList => {
|
||||
diag.span_label(self.span, "expected this to be a list");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1083,7 +1083,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
"the `#[rustc_main]` attribute is used internally to specify test entry point function",
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), WarnFollowing,
|
||||
rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), ErrorFollowing,
|
||||
EncodeCrossCrate::No,
|
||||
"the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \
|
||||
from method dispatch when the receiver is of the following type, for compatibility in \
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use std::ops::Bound;
|
|||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::Recovered;
|
||||
use rustc_attr_data_structures::{AttributeKind, find_attr};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_errors::{
|
||||
|
|
@ -1151,22 +1152,11 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
|||
let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
|
||||
let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
|
||||
|
||||
// FIXME: We could probably do way better attribute validation here.
|
||||
let mut skip_array_during_method_dispatch = false;
|
||||
let mut skip_boxed_slice_during_method_dispatch = false;
|
||||
for attr in tcx.get_attrs(def_id, sym::rustc_skip_during_method_dispatch) {
|
||||
if let Some(lst) = attr.meta_item_list() {
|
||||
for item in lst {
|
||||
if let Some(ident) = item.ident() {
|
||||
match ident.as_str() {
|
||||
"array" => skip_array_during_method_dispatch = true,
|
||||
"boxed_slice" => skip_boxed_slice_during_method_dispatch = true,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!(
|
||||
tcx.get_all_attrs(def_id),
|
||||
AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span:_ } => [*array, *boxed_slice]
|
||||
)
|
||||
.unwrap_or([false; 2]);
|
||||
|
||||
let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
|
||||
ty::trait_def::TraitSpecializationKind::Marker
|
||||
|
|
|
|||
|
|
@ -286,13 +286,20 @@ fn emit_malformed_attribute(
|
|||
if matches!(
|
||||
name,
|
||||
sym::inline
|
||||
| sym::may_dangle
|
||||
| sym::rustc_as_ptr
|
||||
| sym::rustc_pub_transparent
|
||||
| sym::rustc_const_stable_indirect
|
||||
| sym::rustc_force_inline
|
||||
| sym::rustc_confusables
|
||||
| sym::rustc_skip_during_method_dispatch
|
||||
| sym::repr
|
||||
| sym::align
|
||||
| sym::deprecated
|
||||
| sym::optimize
|
||||
| sym::cold
|
||||
| sym::naked
|
||||
| sym::no_mangle
|
||||
| sym::must_use
|
||||
) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -118,6 +118,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
for attr in attrs {
|
||||
let mut style = None;
|
||||
match attr {
|
||||
Attribute::Parsed(AttributeKind::SkipDuringMethodDispatch {
|
||||
span: attr_span,
|
||||
..
|
||||
}) => {
|
||||
self.check_must_be_applied_to_trait(*attr_span, span, target);
|
||||
}
|
||||
Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => {
|
||||
self.check_confusables(*first_span, target);
|
||||
}
|
||||
|
|
@ -250,7 +256,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| [sym::rustc_must_implement_one_of, ..]
|
||||
| [sym::rustc_deny_explicit_impl, ..]
|
||||
| [sym::rustc_do_not_implement_via_object, ..]
|
||||
| [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target),
|
||||
| [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),
|
||||
|
|
@ -1805,14 +1811,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
/// Checks if the attribute is applied to a trait.
|
||||
fn check_must_be_applied_to_trait(&self, attr: &Attribute, span: Span, target: Target) {
|
||||
fn check_must_be_applied_to_trait(&self, attr_span: Span, defn_span: Span, target: Target) {
|
||||
match target {
|
||||
Target::Trait => {}
|
||||
_ => {
|
||||
self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait {
|
||||
attr_span: attr.span(),
|
||||
defn_span: span,
|
||||
});
|
||||
self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait { attr_span, defn_span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -577,6 +577,7 @@ symbols! {
|
|||
box_new,
|
||||
box_patterns,
|
||||
box_syntax,
|
||||
boxed_slice,
|
||||
bpf_target_feature,
|
||||
braced_empty_structs,
|
||||
branch,
|
||||
|
|
|
|||
38
tests/ui/attributes/rustc_skip_during_method_dispatch.rs
Normal file
38
tests/ui/attributes/rustc_skip_during_method_dispatch.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_skip_during_method_dispatch]
|
||||
//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input [E0539]
|
||||
trait NotAList {}
|
||||
|
||||
#[rustc_skip_during_method_dispatch = "array"]
|
||||
//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input [E0539]
|
||||
trait AlsoNotAList {}
|
||||
|
||||
#[rustc_skip_during_method_dispatch()]
|
||||
//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
trait Argless {}
|
||||
|
||||
#[rustc_skip_during_method_dispatch(array, boxed_slice, array)]
|
||||
//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
trait Duplicate {}
|
||||
|
||||
#[rustc_skip_during_method_dispatch(slice)]
|
||||
//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
trait Unexpected {}
|
||||
|
||||
#[rustc_skip_during_method_dispatch(array = true)]
|
||||
//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
trait KeyValue {}
|
||||
|
||||
#[rustc_skip_during_method_dispatch("array")]
|
||||
//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
trait String {}
|
||||
|
||||
#[rustc_skip_during_method_dispatch(array, boxed_slice)]
|
||||
trait OK {}
|
||||
|
||||
#[rustc_skip_during_method_dispatch(array)]
|
||||
//~^ ERROR: attribute should be applied to a trait
|
||||
impl OK for () {}
|
||||
|
||||
fn main() {}
|
||||
76
tests/ui/attributes/rustc_skip_during_method_dispatch.stderr
Normal file
76
tests/ui/attributes/rustc_skip_during_method_dispatch.stderr
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
--> $DIR/rustc_skip_during_method_dispatch.rs:3:1
|
||||
|
|
||||
LL | #[rustc_skip_during_method_dispatch]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected this to be a list
|
||||
| help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
|
||||
|
||||
error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
--> $DIR/rustc_skip_during_method_dispatch.rs:7:1
|
||||
|
|
||||
LL | #[rustc_skip_during_method_dispatch = "array"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected this to be a list
|
||||
| help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
|
||||
|
||||
error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
--> $DIR/rustc_skip_during_method_dispatch.rs:11:1
|
||||
|
|
||||
LL | #[rustc_skip_during_method_dispatch()]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--^
|
||||
| | |
|
||||
| | expected at least 1 argument here
|
||||
| help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
|
||||
|
||||
error[E0538]: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
--> $DIR/rustc_skip_during_method_dispatch.rs:15:1
|
||||
|
|
||||
LL | #[rustc_skip_during_method_dispatch(array, boxed_slice, array)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----^^
|
||||
| | |
|
||||
| | found `array` used as a key more than once
|
||||
| help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
|
||||
|
||||
error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
--> $DIR/rustc_skip_during_method_dispatch.rs:19:1
|
||||
|
|
||||
LL | #[rustc_skip_during_method_dispatch(slice)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----^^
|
||||
| | |
|
||||
| | valid arguments are `array` or `boxed_slice`
|
||||
| help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
|
||||
|
||||
error[E0565]: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
--> $DIR/rustc_skip_during_method_dispatch.rs:23:1
|
||||
|
|
||||
LL | #[rustc_skip_during_method_dispatch(array = true)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^
|
||||
| | |
|
||||
| | didn't expect any arguments here
|
||||
| help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
|
||||
|
||||
error[E0565]: malformed `rustc_skip_during_method_dispatch` attribute input
|
||||
--> $DIR/rustc_skip_during_method_dispatch.rs:27:1
|
||||
|
|
||||
LL | #[rustc_skip_during_method_dispatch("array")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^
|
||||
| | |
|
||||
| | didn't expect a literal here
|
||||
| help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
|
||||
|
||||
error: attribute should be applied to a trait
|
||||
--> $DIR/rustc_skip_during_method_dispatch.rs:34:1
|
||||
|
|
||||
LL | #[rustc_skip_during_method_dispatch(array)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | impl OK for () {}
|
||||
| ----------------- not a trait
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0538, E0539, E0565.
|
||||
For more information about an error, try `rustc --explain E0538`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue