Auto merge of #150407 - JonathanBrouwer:rollup-1v99kga, r=JonathanBrouwer

Rollup of 2 pull requests

Successful merges:

 - rust-lang/rust#147717 (compiler/middle/lint: Suggest `#[expect(dead_code)]` instead of `#[allow(dead_code)]`)
 - rust-lang/rust#150236 (Port `#[rustc_must_implement_one_of]` to attribute parser)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-12-26 20:51:49 +00:00
commit 1107bbac4b
21 changed files with 274 additions and 210 deletions

View file

@ -1,4 +1,5 @@
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
use rustc_session::errors;
use super::prelude::*;
use super::util::parse_single_integer;
@ -13,6 +14,52 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcMainParser {
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain;
}
pub(crate) struct RustcMustImplementOneOfParser;
impl<S: Stage> SingleAttributeParser<S> for RustcMustImplementOneOfParser {
const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const TEMPLATE: AttributeTemplate = template!(List: &["function1, function2, ..."]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span, args);
return None;
};
let mut fn_names = ThinVec::new();
let inputs: Vec<_> = list.mixed().collect();
if inputs.len() < 2 {
cx.expected_list_with_num_args_or_more(2, list.span);
return None;
}
let mut errored = false;
for argument in inputs {
let Some(meta) = argument.meta_item() else {
cx.expected_identifier(argument.span());
return None;
};
let Some(ident) = meta.ident() else {
cx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span: meta.span() });
errored = true;
continue;
};
fn_names.push(ident);
}
if errored {
return None;
}
Some(AttributeKind::RustcMustImplementOneOf { attr_span: cx.attr_span, fn_names })
}
}
pub(crate) struct RustcNeverReturnsNullPointerParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcNeverReturnsNullPointerParser {

View file

@ -64,8 +64,9 @@ use crate::attributes::rustc_internal::{
RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser,
RustcLegacyConstGenericsParser, RustcLintDiagnosticsParser, RustcLintOptDenyFieldAccessParser,
RustcLintOptTyParser, RustcLintQueryInstabilityParser,
RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcNeverReturnsNullPointerParser,
RustcNoImplicitAutorefsParser, RustcObjectLifetimeDefaultParser, RustcScalableVectorParser,
RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser,
RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser,
RustcObjectLifetimeDefaultParser, RustcScalableVectorParser,
RustcSimdMonomorphizeLaneLimitParser,
};
use crate::attributes::semantics::MayDangleParser;
@ -217,6 +218,7 @@ attribute_parsers!(
Single<RustcLayoutScalarValidRangeStartParser>,
Single<RustcLegacyConstGenericsParser>,
Single<RustcLintOptDenyFieldAccessParser>,
Single<RustcMustImplementOneOfParser>,
Single<RustcObjectLifetimeDefaultParser>,
Single<RustcScalableVectorParser>,
Single<RustcSimdMonomorphizeLaneLimitParser>,
@ -492,6 +494,17 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedList)
}
pub(crate) fn expected_list_with_num_args_or_more(
&self,
args: usize,
span: Span,
) -> ErrorGuaranteed {
self.emit_parse_error(
span,
AttributeParseErrorReason::ExpectedListWithNumArgsOrMore { args },
)
}
pub(crate) fn expected_list_or_no_args(&self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedListOrNoArgs)
}

View file

@ -8,7 +8,9 @@ use std::fmt::{Debug, Display};
use rustc_ast::token::{self, Delimiter, MetaVarKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, Path, StmtKind, UnOp};
use rustc_ast::{
AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, Path, PathSegment, StmtKind, UnOp,
};
use rustc_ast_pretty::pprust;
use rustc_errors::{Diag, PResult};
use rustc_hir::{self as hir, AttrPath};
@ -256,6 +258,11 @@ impl Debug for MetaItemParser {
}
impl MetaItemParser {
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
pub fn ident(&self) -> Option<Ident> {
if let [PathSegment { ident, .. }] = self.path.0.segments[..] { Some(ident) } else { None }
}
pub fn span(&self) -> Span {
if let Some(other) = self.args.span() {
self.path.borrow().span().with_hi(other.hi())

View file

@ -520,6 +520,9 @@ pub(crate) enum AttributeParseErrorReason<'a> {
ExpectedSingleArgument,
ExpectedList,
ExpectedListOrNoArgs,
ExpectedListWithNumArgsOrMore {
args: usize,
},
ExpectedNameValueOrNoArgs,
ExpectedNonEmptyStringLiteral,
UnexpectedLiteral,
@ -597,6 +600,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
AttributeParseErrorReason::ExpectedListOrNoArgs => {
diag.span_label(self.span, "expected a list or no arguments here");
}
AttributeParseErrorReason::ExpectedListWithNumArgsOrMore { args } => {
diag.span_label(self.span, format!("expected {args} or more items"));
}
AttributeParseErrorReason::ExpectedNameValueOrNoArgs => {
diag.span_label(self.span, "didn't expect a list here");
}

View file

@ -952,6 +952,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_main]`.
RustcMain,
/// Represents `#[rustc_must_implement_one_of]`
RustcMustImplementOneOf { attr_span: Span, fn_names: ThinVec<Ident> },
/// Represents `#[rustc_never_returns_null_ptr]`
RustcNeverReturnsNullPointer,

View file

@ -101,6 +101,7 @@ impl AttributeKind {
RustcLintQueryInstability => Yes,
RustcLintUntrackedQueryInformation => Yes,
RustcMain => No,
RustcMustImplementOneOf { .. } => No,
RustcNeverReturnsNullPointer => Yes,
RustcNoImplicitAutorefs => Yes,
RustcObjectLifetimeDefault => No,

View file

@ -208,14 +208,6 @@ hir_analysis_field_already_declared_previous_nested =
.previous_decl_label = `{$field_name}` first declared here in this unnamed field
.previous_nested_field_decl_note = field `{$field_name}` first declared here
hir_analysis_function_not_found_in_trait = function not found in this trait
hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
.note = required by this annotation
hir_analysis_functions_names_duplicated = functions names are duplicated
.note = all `#[rustc_must_implement_one_of]` arguments must be unique
hir_analysis_generic_args_on_overridden_impl = could not resolve generic parameters on overridden impl
hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`
@ -381,16 +373,6 @@ hir_analysis_missing_type_params =
*[other] parameters
} must be specified on the object type
hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
hir_analysis_must_implement_not_function = not a function
hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
hir_analysis_must_implement_not_function_span_note = required by this annotation
hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
hir_analysis_no_variant_named = no variant named `{$ident}` found for enum `{$ty}`
hir_analysis_not_supported_delegation = {$descr}

View file

@ -1340,9 +1340,7 @@ fn check_impl_items_against_trait<'tcx>(
}
if let Some(missing_items) = must_implement_one_of {
let attr_span = tcx
.get_attr(trait_ref.def_id, sym::rustc_must_implement_one_of)
.map(|attr| attr.span());
let attr_span = find_attr!(tcx.get_all_attrs(trait_ref.def_id), AttributeKind::RustcMustImplementOneOf {attr_span, ..} => *attr_span);
missing_items_must_implement_one_of_err(
tcx,

View file

@ -22,7 +22,6 @@ use std::ops::Bound;
use rustc_abi::{ExternAbi, Size};
use rustc_ast::Recovered;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err,
};
@ -916,84 +915,15 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
} else {
ty::trait_def::TraitSpecializationKind::None
};
let must_implement_one_of = attrs
.iter()
.find(|attr| attr.has_name(sym::rustc_must_implement_one_of))
// Check that there are at least 2 arguments of `#[rustc_must_implement_one_of]`
// and that they are all identifiers
.and_then(|attr| match attr.meta_item_list() {
Some(items) if items.len() < 2 => {
tcx.dcx().emit_err(errors::MustImplementOneOfAttribute { span: attr.span() });
None
}
Some(items) => items
.into_iter()
.map(|item| item.ident().ok_or(item.span()))
.collect::<Result<Box<[_]>, _>>()
.map_err(|span| {
tcx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span });
})
.ok()
.zip(Some(attr.span())),
// Error is reported by `rustc_attr!`
None => None,
})
// Check that all arguments of `#[rustc_must_implement_one_of]` reference
// functions in the trait with default implementations
.and_then(|(list, attr_span)| {
let errors = list.iter().filter_map(|ident| {
let item = tcx
.associated_items(def_id)
.filter_by_name_unhygienic(ident.name)
.find(|item| item.ident(tcx) == *ident);
match item {
Some(item) if matches!(item.kind, ty::AssocKind::Fn { .. }) => {
if !item.defaultness(tcx).has_value() {
tcx.dcx().emit_err(errors::FunctionNotHaveDefaultImplementation {
span: tcx.def_span(item.def_id),
note_span: attr_span,
});
return Some(());
}
return None;
}
Some(item) => {
tcx.dcx().emit_err(errors::MustImplementNotFunction {
span: tcx.def_span(item.def_id),
span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
note: errors::MustImplementNotFunctionNote {},
});
}
None => {
tcx.dcx().emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
}
}
Some(())
});
(errors.count() == 0).then_some(list)
})
// Check for duplicates
.and_then(|list| {
let mut set: UnordMap<Symbol, Span> = Default::default();
let mut no_dups = true;
for ident in &*list {
if let Some(dup) = set.insert(ident.name, ident.span) {
tcx.dcx()
.emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
no_dups = false;
}
}
no_dups.then_some(list)
});
let must_implement_one_of = find_attr!(
attrs,
AttributeKind::RustcMustImplementOneOf { fn_names, .. } =>
fn_names
.iter()
.cloned()
.collect::<Box<[_]>>()
);
let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_));
let implement_via_object = !find_attr!(attrs, AttributeKind::DoNotImplementViaObject(_));

View file

@ -741,66 +741,6 @@ pub(crate) struct ParenSugarAttribute {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_must_implement_one_of_attribute)]
pub(crate) struct MustImplementOneOfAttribute {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_must_be_name_of_associated_function)]
pub(crate) struct MustBeNameOfAssociatedFunction {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_function_not_have_default_implementation)]
pub(crate) struct FunctionNotHaveDefaultImplementation {
#[primary_span]
pub span: Span,
#[note]
pub note_span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_must_implement_not_function)]
pub(crate) struct MustImplementNotFunction {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub span_note: MustImplementNotFunctionSpanNote,
#[subdiagnostic]
pub note: MustImplementNotFunctionNote,
}
#[derive(Subdiagnostic)]
#[note(hir_analysis_must_implement_not_function_span_note)]
pub(crate) struct MustImplementNotFunctionSpanNote {
#[primary_span]
pub span: Span,
}
#[derive(Subdiagnostic)]
#[note(hir_analysis_must_implement_not_function_note)]
pub(crate) struct MustImplementNotFunctionNote {}
#[derive(Diagnostic)]
#[diag(hir_analysis_function_not_found_in_trait)]
pub(crate) struct FunctionNotFoundInTrait {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_functions_names_duplicated)]
#[note]
pub(crate) struct FunctionNamesDuplicated {
#[primary_span]
pub spans: Vec<Span>,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_simd_ffi_highly_experimental)]
#[help]

View file

@ -265,9 +265,16 @@ fn explain_lint_level_source(
"`{flag} {hyphen_case_lint_name}` implied by `{flag} {hyphen_case_flag_val}`"
));
if matches!(orig_level, Level::Warn | Level::Deny) {
err.help_once(format!(
"to override `{flag} {hyphen_case_flag_val}` add `#[allow({name})]`"
));
let help = if name == "dead_code" {
format!(
"to override `{flag} {hyphen_case_flag_val}` add `#[expect({name})]` or `#[allow({name})]`"
)
} else {
format!(
"to override `{flag} {hyphen_case_flag_val}` add `#[allow({name})]`"
)
};
err.help_once(help);
}
}
}

View file

@ -236,6 +236,14 @@ passes_feature_previously_declared =
passes_feature_stable_twice =
feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}
passes_function_not_found_in_trait = function not found in this trait
passes_function_not_have_default_implementation = function doesn't have a default implementation
.note = required by this annotation
passes_functions_names_duplicated = functions names are duplicated
.note = all `#[rustc_must_implement_one_of]` arguments must be unique
passes_has_incoherent_inherent_impl =
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits
.label = only adts, extern types and traits are supported
@ -370,6 +378,12 @@ passes_multiple_rustc_main =
.first = first `#[rustc_main]` function
.additional = additional `#[rustc_main]` function
passes_must_implement_not_function = not a function
passes_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
passes_must_implement_not_function_span_note = required by this annotation
passes_must_not_suspend =
`must_not_suspend` attribute should be applied to a struct, enum, union, or trait
.label = is not a struct, enum, union, or trait
@ -484,10 +498,6 @@ passes_sanitize_attribute_not_allowed =
.no_body = function has no body
.help = sanitize attribute can be applied to a function (with body), impl block, or module
passes_should_be_applied_to_trait =
attribute should be applied to a trait
.label = not a trait
passes_trait_impl_const_stability_mismatch = const stability on the impl does not match the const stability on the trait
passes_trait_impl_const_stability_mismatch_impl_stable = this impl is (implicitly) stable...
passes_trait_impl_const_stability_mismatch_impl_unstable = this impl is unstable...

View file

@ -14,6 +14,7 @@ use rustc_ast::{AttrStyle, MetaItemKind, ast};
use rustc_attr_parsing::{AttributeParser, Late};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
use rustc_feature::{
ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
@ -47,7 +48,7 @@ use rustc_session::lint::builtin::{
};
use rustc_session::parse::feature_err;
use rustc_span::edition::Edition;
use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, sym};
use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, sym};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
use rustc_trait_selection::traits::ObligationCtxt;
@ -219,6 +220,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
Attribute::Parsed(AttributeKind::EiiImpls(impls)) => {
self.check_eii_impl(impls, target)
},
Attribute::Parsed(AttributeKind::RustcMustImplementOneOf { attr_span, fn_names }) => {
self.check_rustc_must_implement_one_of(*attr_span, fn_names, hir_id,target)
},
Attribute::Parsed(
AttributeKind::EiiExternTarget { .. }
| AttributeKind::EiiExternItem
@ -316,7 +320,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| [sym::rustc_dirty, ..]
| [sym::rustc_if_this_changed, ..]
| [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr),
[sym::rustc_must_implement_one_of, ..] => 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_has_incoherent_inherent_impls, ..] => {
@ -445,6 +448,63 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.check_mix_no_mangle_export(hir_id, attrs);
}
fn check_rustc_must_implement_one_of(
&self,
attr_span: Span,
list: &ThinVec<Ident>,
hir_id: HirId,
target: Target,
) {
// Ignoring invalid targets because TyCtxt::associated_items emits bug if the target isn't valid
// the parser has already produced an error for the target being invalid
if !matches!(target, Target::Trait) {
return;
}
let def_id = hir_id.owner.def_id;
let items = self.tcx.associated_items(def_id);
// Check that all arguments of `#[rustc_must_implement_one_of]` reference
// functions in the trait with default implementations
for ident in list {
let item = items
.filter_by_name_unhygienic(ident.name)
.find(|item| item.ident(self.tcx) == *ident);
match item {
Some(item) if matches!(item.kind, ty::AssocKind::Fn { .. }) => {
if !item.defaultness(self.tcx).has_value() {
self.tcx.dcx().emit_err(errors::FunctionNotHaveDefaultImplementation {
span: self.tcx.def_span(item.def_id),
note_span: attr_span,
});
}
}
Some(item) => {
self.dcx().emit_err(errors::MustImplementNotFunction {
span: self.tcx.def_span(item.def_id),
span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
note: errors::MustImplementNotFunctionNote {},
});
}
None => {
self.dcx().emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
}
}
}
// Check for duplicates
let mut set: UnordMap<Symbol, Span> = Default::default();
for ident in &*list {
if let Some(dup) = set.insert(ident.name, ident.span) {
self.tcx
.dcx()
.emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
}
}
}
fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) {
for EiiImpl { span, inner_span, eii_macro, impl_marked_unsafe, is_default: _ } in impls {
match target {
@ -1221,16 +1281,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
/// Checks if the attribute is applied to a trait.
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, defn_span });
}
}
}
/// Checks if the `#[repr]` attributes on `item` are valid.
fn check_repr(
&self,

View file

@ -89,15 +89,6 @@ pub(crate) struct NonExhaustiveWithDefaultFieldValues {
pub defn_span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_should_be_applied_to_trait)]
pub(crate) struct AttrShouldBeAppliedToTrait {
#[primary_span]
pub attr_span: Span,
#[label]
pub defn_span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_doc_alias_bad_location)]
pub(crate) struct DocAliasBadLocation<'a> {
@ -1323,3 +1314,49 @@ pub(crate) struct DuplicateEiiImpls {
#[help]
pub help: (),
}
#[derive(Diagnostic)]
#[diag(passes_function_not_have_default_implementation)]
pub(crate) struct FunctionNotHaveDefaultImplementation {
#[primary_span]
pub span: Span,
#[note]
pub note_span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_must_implement_not_function)]
pub(crate) struct MustImplementNotFunction {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub span_note: MustImplementNotFunctionSpanNote,
#[subdiagnostic]
pub note: MustImplementNotFunctionNote,
}
#[derive(Subdiagnostic)]
#[note(passes_must_implement_not_function_span_note)]
pub(crate) struct MustImplementNotFunctionSpanNote {
#[primary_span]
pub span: Span,
}
#[derive(Subdiagnostic)]
#[note(passes_must_implement_not_function_note)]
pub(crate) struct MustImplementNotFunctionNote {}
#[derive(Diagnostic)]
#[diag(passes_function_not_found_in_trait)]
pub(crate) struct FunctionNotFoundInTrait {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_functions_names_duplicated)]
#[note]
pub(crate) struct FunctionNamesDuplicated {
#[primary_span]
pub spans: Vec<Span>,
}

View file

@ -81,6 +81,8 @@ session_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number liter
session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets
session_must_be_name_of_associated_function = must be a name of an associated function
session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine
session_not_supported = not supported

View file

@ -82,6 +82,13 @@ pub(crate) struct CliFeatureDiagnosticHelp {
pub(crate) feature: Symbol,
}
#[derive(Diagnostic)]
#[diag(session_must_be_name_of_associated_function)]
pub struct MustBeNameOfAssociatedFunction {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(session_not_circumvent_feature)]
pub(crate) struct NotCircumventFeature;

View file

@ -9,7 +9,7 @@ LL | Void(Void),
|
= note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
= note: `-W dead-code` implied by `-W unused`
= help: to override `-W unused` add `#[allow(dead_code)]`
= help: to override `-W unused` add `#[expect(dead_code)]` or `#[allow(dead_code)]`
warning: 1 warning emitted

View file

@ -0,0 +1,8 @@
//@ check-pass
//@ compile-flags: -Wunused
fn foo() -> &'static str { //~ WARN function `foo` is never used
"hello"
}
fn main() {}

View file

@ -0,0 +1,11 @@
warning: function `foo` is never used
--> $DIR/unused-fn-with-check-pass.rs:4:4
|
LL | fn foo() -> &'static str {
| ^^^
|
= note: `-W dead-code` implied by `-W unused`
= help: to override `-W unused` add `#[expect(dead_code)]` or `#[allow(dead_code)]`
warning: 1 warning emitted

View file

@ -12,7 +12,7 @@ trait Tr1 {
}
#[rustc_must_implement_one_of(a)]
//~^ ERROR the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
//~^ ERROR malformed
trait Tr2 {
fn a() {}
}
@ -36,11 +36,11 @@ trait Tr5 {
}
#[rustc_must_implement_one_of(abc, xyz)]
//~^ ERROR attribute should be applied to a trait
//~^ ERROR `#[rustc_must_implement_one_of]` attribute cannot be used on functions
fn function() {}
#[rustc_must_implement_one_of(abc, xyz)]
//~^ ERROR attribute should be applied to a trait
//~^ ERROR `#[rustc_must_implement_one_of]` attribute cannot be used on structs
struct Struct {}
fn main() {}

View file

@ -1,26 +1,36 @@
error: malformed `rustc_must_implement_one_of` attribute input
error[E0539]: malformed `rustc_must_implement_one_of` attribute input
--> $DIR/rustc_must_implement_one_of_misuse.rs:14:1
|
LL | #[rustc_must_implement_one_of(a)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^
| | |
| | expected 2 or more items
| help: must be of the form: `#[rustc_must_implement_one_of(function1, function2, ...)]`
error[E0539]: malformed `rustc_must_implement_one_of` attribute input
--> $DIR/rustc_must_implement_one_of_misuse.rs:20:1
|
LL | #[rustc_must_implement_one_of]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_must_implement_one_of(function1, function2, ...)]`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| expected this to be a list
| help: must be of the form: `#[rustc_must_implement_one_of(function1, function2, ...)]`
error: attribute should be applied to a trait
error: `#[rustc_must_implement_one_of]` attribute cannot be used on functions
--> $DIR/rustc_must_implement_one_of_misuse.rs:38:1
|
LL | #[rustc_must_implement_one_of(abc, xyz)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | fn function() {}
| ---------------- not a trait
|
= help: `#[rustc_must_implement_one_of]` can only be applied to traits
error: attribute should be applied to a trait
error: `#[rustc_must_implement_one_of]` attribute cannot be used on structs
--> $DIR/rustc_must_implement_one_of_misuse.rs:42:1
|
LL | #[rustc_must_implement_one_of(abc, xyz)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |
LL | struct Struct {}
| ---------------- not a trait
|
= help: `#[rustc_must_implement_one_of]` can only be applied to traits
error: function not found in this trait
--> $DIR/rustc_must_implement_one_of_misuse.rs:3:31
@ -40,12 +50,6 @@ error: function not found in this trait
LL | #[rustc_must_implement_one_of(a, b)]
| ^
error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
--> $DIR/rustc_must_implement_one_of_misuse.rs:14:1
|
LL | #[rustc_must_implement_one_of(a)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: not a function
--> $DIR/rustc_must_implement_one_of_misuse.rs:26:5
|
@ -98,3 +102,4 @@ LL | #[rustc_must_implement_one_of(a, b)]
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0539`.