Merge ref 'a015919e54' from rust-lang/rust

Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: a015919e54
Filtered ref: 1867c5844dba22ac4d77d1ceb7d1624c14139c16
Upstream diff: 4ba1cf9ade...a015919e54

This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
The Miri Cronjob Bot 2025-09-14 05:00:30 +00:00
commit 603341a94f
216 changed files with 1721 additions and 1262 deletions

View file

@ -5,7 +5,9 @@ use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin, Target, find_attr};
use rustc_hir::{
self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr,
};
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
@ -1117,20 +1119,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
};
let span = self.lower_span(i.span);
let item = hir::ImplItem {
owner_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
generics,
impl_kind: if is_in_trait_impl {
ImplItemImplKind::Trait {
defaultness,
trait_item_def_id: self
.resolver
.get_partial_res(i.id)
.and_then(|r| r.expect_full_res().opt_def_id())
.ok_or_else(|| {
self.dcx().span_delayed_bug(
span,
"could not resolve trait item being implemented",
)
}),
}
} else {
ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) }
},
kind,
vis_span: self.lower_span(i.vis.span),
span: self.lower_span(i.span),
defaultness,
span,
has_delayed_lints: !self.delayed_lints.is_empty(),
trait_item_def_id: self
.resolver
.get_partial_res(i.id)
.map(|r| r.expect_full_res().opt_def_id())
.unwrap_or(None),
};
self.arena.alloc(item)
}

View file

@ -216,6 +216,10 @@ ast_passes_match_arm_with_no_body =
.suggestion = add a body after the pattern
ast_passes_missing_unsafe_on_extern = extern blocks must be unsafe
.suggestion = needs `unsafe` before the extern keyword
ast_passes_missing_unsafe_on_extern_lint = extern blocks should be unsafe
.suggestion = needs `unsafe` before the extern keyword
ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
.help = consider using the `#[path]` attribute to specify filesystem path

View file

@ -1131,7 +1131,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
MISSING_UNSAFE_ON_EXTERN,
item.id,
item.span,
BuiltinLintDiag::MissingUnsafeOnExtern {
errors::MissingUnsafeOnExternLint {
suggestion: item.span.shrink_to_lo(),
},
);

View file

@ -523,6 +523,13 @@ pub(crate) struct MissingUnsafeOnExtern {
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(ast_passes_missing_unsafe_on_extern_lint)]
pub(crate) struct MissingUnsafeOnExternLint {
#[suggestion(code = "unsafe ", applicability = "machine-applicable")]
pub suggestion: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_fieldless_union)]
pub(crate) struct FieldlessUnion {

View file

@ -43,11 +43,7 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
const TYPE: AttributeType = AttributeType::CrateLevel;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(n) = args else {
@ -76,11 +72,7 @@ impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
const TYPE: AttributeType = AttributeType::CrateLevel;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
@ -103,11 +95,7 @@ impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const TYPE: AttributeType = AttributeType::CrateLevel;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
@ -130,11 +118,7 @@ impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const TYPE: AttributeType = AttributeType::CrateLevel;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
@ -157,11 +141,7 @@ impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const TYPE: AttributeType = AttributeType::CrateLevel;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
@ -182,11 +162,8 @@ pub(crate) struct NoCoreParser;
impl<S: Stage> NoArgsAttributeParser<S> for NoCoreParser {
const PATH: &[Symbol] = &[sym::no_core];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore;
const TYPE: AttributeType = AttributeType::CrateLevel;
}
pub(crate) struct NoStdParser;
@ -194,9 +171,6 @@ pub(crate) struct NoStdParser;
impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
const PATH: &[Symbol] = &[sym::no_std];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
// because it's a crate-level attribute, we already warn about it.
// Putting target limitations here would give duplicate warnings
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
const TYPE: AttributeType = AttributeType::CrateLevel;
}

View file

@ -12,15 +12,11 @@
//! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
//! contents of attributes, if an attribute appear multiple times in a list
//!
//! By default, attributes are allowed anywhere. When adding an attribute that should only be used
//! at the crate root, consider setting the `TYPE` in the parser trait to
//! [`AttributeType::CrateLevel`](rustc_feature::AttributeType::CrateLevel).
//!
//! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
use std::marker::PhantomData;
use rustc_feature::{AttributeTemplate, AttributeType, template};
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;
@ -89,11 +85,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
///
/// If an attribute has this symbol, the `accept` function will be called on it.
const ATTRIBUTES: AcceptMapping<Self, S>;
const ALLOWED_TARGETS: AllowedTargets;
const TYPE: AttributeType = AttributeType::Normal;
/// The parser has gotten a chance to accept the attributes on an item,
/// here it can produce an attribute.
///
@ -135,8 +128,6 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
/// The template this attribute parser should implement. Used for diagnostics.
const TEMPLATE: AttributeTemplate;
const TYPE: AttributeType = AttributeType::Normal;
/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
}
@ -183,8 +174,6 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
)];
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
const TYPE: AttributeType = T::TYPE;
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
Some(self.1?.0)
}
@ -269,7 +258,6 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
const PATH: &[Symbol];
const ON_DUPLICATE: OnDuplicate<S>;
const ALLOWED_TARGETS: AllowedTargets;
const TYPE: AttributeType = AttributeType::Normal;
/// Create the [`AttributeKind`] given attribute's [`Span`].
const CREATE: fn(Span) -> AttributeKind;
@ -289,7 +277,6 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
const TEMPLATE: AttributeTemplate = template!(Word);
const TYPE: AttributeType = T::TYPE;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
if let Err(span) = args.no_args() {
@ -323,8 +310,6 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
/// The template this attribute parser should implement. Used for diagnostics.
const TEMPLATE: AttributeTemplate;
const TYPE: AttributeType = AttributeType::Normal;
/// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
fn extend<'c>(
cx: &'c mut AcceptContext<'_, '_, S>,
@ -360,7 +345,6 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
group.items.extend(T::extend(cx, args))
})];
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
const TYPE: AttributeType = T::TYPE;
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
if let Some(first_span) = self.first_span {

View file

@ -1,6 +1,6 @@
// data structures
#[doc(hidden)]
pub(super) use rustc_feature::{AttributeTemplate, AttributeType, template};
pub(super) use rustc_feature::{AttributeTemplate, template};
#[doc(hidden)]
pub(super) use rustc_hir::attrs::AttributeKind;
#[doc(hidden)]

View file

@ -1,7 +1,5 @@
use std::mem;
use rustc_feature::AttributeType;
use super::prelude::*;
use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
@ -155,8 +153,7 @@ pub(crate) struct CoherenceIsCoreParser;
impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const TYPE: AttributeType = AttributeType::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
}

View file

@ -6,7 +6,7 @@ use std::sync::LazyLock;
use private::Sealed;
use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
use rustc_errors::{Diag, Diagnostic, Level};
use rustc_feature::{AttributeTemplate, AttributeType};
use rustc_feature::AttributeTemplate;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
@ -83,7 +83,6 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
pub(super) template: AttributeTemplate,
pub(super) accept_fn: AcceptFn<S>,
pub(super) allowed_targets: AllowedTargets,
pub(super) attribute_type: AttributeType,
}
type AcceptFn<S> =
@ -133,7 +132,6 @@ macro_rules! attribute_parsers {
})
}),
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
});
}

View file

@ -272,7 +272,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
(accept.accept_fn)(&mut cx, args);
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
Self::check_type(accept.attribute_type, target, &mut cx);
Self::check_target(&accept.allowed_targets, target, &mut cx);
}
}

View file

@ -2,7 +2,7 @@ use std::borrow::Cow;
use rustc_ast::AttrStyle;
use rustc_errors::DiagArgValue;
use rustc_feature::{AttributeType, Features};
use rustc_feature::Features;
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{MethodKind, Target};
@ -14,6 +14,11 @@ use crate::session_diagnostics::InvalidTarget;
pub(crate) enum AllowedTargets {
AllowList(&'static [Policy]),
AllowListWarnRest(&'static [Policy]),
/// Special, and not the same as `AllowList(&[Allow(Target::Crate)])`.
/// For crate-level attributes we emit a specific set of lints to warn
/// people about accidentally not using them on the crate.
/// Only use this for attributes that are *exclusively* valid at the crate level.
CrateLevel,
}
pub(crate) enum AllowedResult {
@ -43,6 +48,7 @@ impl AllowedTargets {
AllowedResult::Warn
}
}
AllowedTargets::CrateLevel => AllowedResult::Allowed,
}
}
@ -50,6 +56,7 @@ impl AllowedTargets {
match self {
AllowedTargets::AllowList(list) => list,
AllowedTargets::AllowListWarnRest(list) => list,
AllowedTargets::CrateLevel => ALL_TARGETS,
}
.iter()
.filter_map(|target| match target {
@ -74,6 +81,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
target: Target,
cx: &mut AcceptContext<'_, 'sess, S>,
) {
Self::check_type(matches!(allowed_targets, AllowedTargets::CrateLevel), target, cx);
match allowed_targets.is_allowed(target) {
AllowedResult::Allowed => {}
AllowedResult::Warn => {
@ -109,7 +118,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
}
pub(crate) fn check_type(
attribute_type: AttributeType,
crate_level: bool,
target: Target,
cx: &mut AcceptContext<'_, 'sess, S>,
) {
@ -119,7 +128,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
return;
}
if attribute_type != AttributeType::CrateLevel {
if !crate_level {
return;
}

View file

@ -716,7 +716,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return (false, false, None);
};
let implemented_trait_item = self.infcx.tcx.associated_item(my_def).trait_item_def_id;
let implemented_trait_item = self.infcx.tcx.trait_item_of(my_def);
(
true,

View file

@ -64,6 +64,11 @@ builtin_macros_autodiff_ty_activity = {$act} can not be used for this type
builtin_macros_autodiff_unknown_activity = did not recognize Activity: `{$act}`
builtin_macros_autodiff_width = autodiff width must fit u32, but is {$width}
builtin_macros_avoid_att_syntax = avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
builtin_macros_avoid_intel_syntax = avoid using `.intel_syntax`, Intel syntax is the default
builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
.label = not applicable here
.label2 = not a `struct`, `enum` or `union`
@ -138,6 +143,8 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
.suggestion = remove the value
builtin_macros_duplicate_macro_attribute = duplicated attribute
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
.custom = use `std::env::var({$var_expr})` to read the variable at run time
@ -231,6 +238,8 @@ builtin_macros_derive_from_wrong_field_count = `#[derive(From)]` used on a struc
builtin_macros_derive_from_usage_note = `#[derive(From)]` can only be used on structs with exactly one field
builtin_macros_incomplete_include = include macro expected single expression in source
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
.note = only one `#[default]` attribute is needed
.label = `#[default]` used here
@ -294,3 +303,5 @@ builtin_macros_unexpected_lit = expected path to a trait, found literal
.label = not a trait
.str_lit = try using `#[derive({$sym})]`
.other = for example, write `#[derive(Debug)]` for `Debug`
builtin_macros_unnameable_test_items = cannot test inner items

View file

@ -1,4 +1,3 @@
use lint::BuiltinLintDiag;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AsmMacro, token};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
@ -352,7 +351,7 @@ fn expand_preparsed_asm(
lint::builtin::BAD_ASM_STYLE,
find_span(".intel_syntax"),
ecx.current_expansion.lint_node_id,
BuiltinLintDiag::AvoidUsingIntelSyntax,
errors::AvoidIntelSyntax,
);
}
if template_str.contains(".att_syntax") {
@ -360,7 +359,7 @@ fn expand_preparsed_asm(
lint::builtin::BAD_ASM_STYLE,
find_span(".att_syntax"),
ecx.current_expansion.lint_node_id,
BuiltinLintDiag::AvoidUsingAttSyntax,
errors::AvoidAttSyntax,
);
}
}

View file

@ -3,9 +3,29 @@ use rustc_errors::{
Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans,
Subdiagnostic,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Ident, Span, Symbol};
#[derive(LintDiagnostic)]
#[diag(builtin_macros_avoid_intel_syntax)]
pub(crate) struct AvoidIntelSyntax;
#[derive(LintDiagnostic)]
#[diag(builtin_macros_avoid_att_syntax)]
pub(crate) struct AvoidAttSyntax;
#[derive(LintDiagnostic)]
#[diag(builtin_macros_incomplete_include)]
pub(crate) struct IncompleteInclude;
#[derive(LintDiagnostic)]
#[diag(builtin_macros_unnameable_test_items)]
pub(crate) struct UnnameableTestItems;
#[derive(LintDiagnostic)]
#[diag(builtin_macros_duplicate_macro_attribute)]
pub(crate) struct DuplicateMacroAttribute;
#[derive(Diagnostic)]
#[diag(builtin_macros_requires_cfg_pattern)]
pub(crate) struct RequiresCfgPattern {

View file

@ -569,6 +569,7 @@ fn make_format_args(
detect_foreign_fmt,
str_style,
fmt_str,
uncooked_fmt_str.1.as_str(),
fmt_span,
);
}
@ -650,6 +651,7 @@ fn report_missing_placeholders(
detect_foreign_fmt: bool,
str_style: Option<usize>,
fmt_str: &str,
uncooked_fmt_str: &str,
fmt_span: Span,
) {
let mut diag = if let &[(span, named)] = &unused[..] {
@ -773,16 +775,20 @@ fn report_missing_placeholders(
diag.note(format!("consider adding {} format specifiers", unused.len()));
}
} else {
let original_fmt_str =
if fmt_str.len() >= 1 { &fmt_str[..fmt_str.len() - 1] } else { "" };
let msg = if unused.len() == 1 {
"a format specifier".to_string()
} else {
format!("{} format specifiers", unused.len())
};
let sugg = format!("\"{}{}\"", original_fmt_str, "{}".repeat(unused.len()));
let sugg = match str_style {
None => format!("\"{}{}\"", uncooked_fmt_str, "{}".repeat(unused.len())),
Some(n_hashes) => format!(
"r{hashes}\"{uncooked_fmt_str}{fmt_specifiers}\"{hashes}",
hashes = "#".repeat(n_hashes),
fmt_specifiers = "{}".repeat(unused.len())
),
};
let msg = format!("format specifiers use curly braces, consider adding {msg}");
diag.span_suggestion_verbose(fmt_span, msg, sugg, Applicability::MaybeIncorrect);

View file

@ -12,7 +12,6 @@ use rustc_expand::base::{
DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path,
};
use rustc_expand::module::DirOwnership;
use rustc_lint_defs::BuiltinLintDiag;
use rustc_parse::lexer::StripTokens;
use rustc_parse::parser::ForceCollect;
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
@ -159,7 +158,7 @@ pub(crate) fn expand_include<'cx>(
INCOMPLETE_INCLUDE,
p.token.span,
self.node_id,
BuiltinLintDiag::IncompleteInclude,
errors::IncompleteInclude,
);
}
Some(expr)

View file

@ -11,7 +11,6 @@ use rustc_errors::DiagCtxtHandle;
use rustc_expand::base::{ExtCtxt, ResolverExpand};
use rustc_expand::expand::{AstFragment, ExpansionConfig};
use rustc_feature::Features;
use rustc_lint_defs::BuiltinLintDiag;
use rustc_session::Session;
use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS;
use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency};
@ -165,7 +164,7 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> {
UNNAMEABLE_TEST_ITEMS,
attr.span,
i.id,
BuiltinLintDiag::UnnameableTestItems,
errors::UnnameableTestItems,
);
}
}

View file

@ -5,7 +5,6 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt};
use rustc_expand::expand::AstFragment;
use rustc_feature::AttributeTemplate;
use rustc_lint_defs::BuiltinLintDiag;
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
use rustc_parse::{exp, parser};
use rustc_session::errors::report_lit_error;
@ -49,7 +48,7 @@ pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable,
DUPLICATE_MACRO_ATTRIBUTES,
attr.span,
ecx.current_expansion.lint_node_id,
BuiltinLintDiag::DuplicateMacroAttribute,
errors::DuplicateMacroAttribute,
);
}
}

View file

@ -31,7 +31,7 @@ codegen_ssa_cpu_required = target requires explicitly specifying a cpu with `-C
codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
codegen_ssa_dlltool_fail_import_library =
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
{$stdout}
{$stderr}

View file

@ -562,15 +562,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
codegen_fn_attrs
}
/// If the provided DefId is a method in a trait impl, return the DefId of the method prototype.
fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
let impl_item = tcx.opt_associated_item(def_id)?;
match impl_item.container {
ty::AssocItemContainer::Impl => impl_item.trait_item_def_id,
_ => None,
}
}
fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
// Backtrack to the crate root.
let mut disabled = match tcx.opt_local_parent(did) {
@ -600,14 +591,15 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
/// applied to the method prototype.
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let Some(trait_item) = opt_trait_item(tcx, def_id) else { return false };
tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
tcx.trait_item_of(def_id).is_some_and(|id| {
tcx.codegen_fn_attrs(id).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
})
}
/// If the provided DefId is a method in a trait impl, return the value of the `#[align]`
/// attribute on the method prototype (if any).
fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Align> {
tcx.codegen_fn_attrs(opt_trait_item(tcx, def_id)?).alignment
tcx.codegen_fn_attrs(tcx.trait_item_of(def_id)?).alignment
}
/// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)]

View file

@ -3,6 +3,8 @@ expand_attributes_on_expressions_experimental =
.help_outer_doc = `///` is used for outer documentation comments; for a plain comment, use `//`
.help_inner_doc = `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !`
expand_cfg_attr_no_attributes = `#[cfg_attr]` does not expand to any attributes
expand_collapse_debuginfo_illegal =
illegal value for attribute #[collapse_debuginfo(no|external|yes)]
@ -78,6 +80,10 @@ expand_macro_body_stability =
.label = invalid body stability attribute
.label2 = body stability attribute affects this macro
expand_macro_call_unused_doc_comment = unused doc comment
.label = rustdoc does not generate documentation for macro invocations
.help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion
expand_macro_const_stability =
macros cannot have const stability attributes
.label = invalid const stability attribute
@ -89,6 +95,13 @@ expand_malformed_feature_attribute =
malformed `feature` attribute input
.expected = expected just one word
expand_metavar_still_repeating = variable `{$ident}` is still repeating at this depth
.label = expected repetition
expand_metavariable_wrong_operator = meta-variable repeats with different Kleene operator
.binder_label = expected repetition
.occurrence_label = conflicting repetition
expand_meta_var_dif_seq_matchers = {$msg}
expand_missing_fragment_specifier = missing fragment specifier
@ -147,6 +160,9 @@ expand_mve_unrecognized_var =
expand_non_inline_modules_in_proc_macro_input_are_unstable =
non-inline modules in proc macro input are unstable
expand_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
.suggestion = use pat_param to preserve semantics
expand_proc_macro_back_compat = using an old version of `{$crate_name}`
.note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
@ -176,11 +192,18 @@ expand_resolve_relative_path =
expand_trace_macro = trace_macro
expand_trailing_semi_macro = trailing semicolon in macro used in expression position
.note1 = macro invocations at the end of a block are treated as expressions
.note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`
expand_unknown_macro_variable = unknown macro variable `{$name}`
expand_unused_builtin_attribute = unused attribute `{$attr_name}`
.note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}`
.suggestion = remove the attribute
expand_unsupported_key_value =
key-value macro attributes are not supported
expand_var_still_repeating =
variable `{$ident}` is still repeating at this depth
expand_wrong_fragment_kind =
non-{$kind} macro in {$kind} position: {$name}

View file

@ -21,7 +21,6 @@ use rustc_feature::{
ACCEPTED_LANG_FEATURES, AttributeSafety, EnabledLangFeature, EnabledLibFeature, Features,
REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES,
};
use rustc_lint_defs::BuiltinLintDiag;
use rustc_session::Session;
use rustc_session::parse::feature_err;
use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym};
@ -315,7 +314,7 @@ impl<'a> StripUnconfigured<'a> {
rustc_lint_defs::builtin::UNUSED_ATTRIBUTES,
cfg_attr.span,
ast::CRATE_NODE_ID,
BuiltinLintDiag::CfgAttrNoAttributes,
crate::errors::CfgAttrNoAttributes,
);
}

View file

@ -3,9 +3,13 @@ use std::borrow::Cow;
use rustc_ast::ast;
use rustc_errors::codes::*;
use rustc_hir::limit::Limit;
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol};
#[derive(LintDiagnostic)]
#[diag(expand_cfg_attr_no_attributes)]
pub(crate) struct CfgAttrNoAttributes;
#[derive(Diagnostic)]
#[diag(expand_expr_repeat_no_syntax_vars)]
pub(crate) struct NoSyntaxVarsExprRepeat {
@ -28,13 +32,30 @@ pub(crate) struct CountRepetitionMisplaced {
}
#[derive(Diagnostic)]
#[diag(expand_var_still_repeating)]
pub(crate) struct VarStillRepeating {
#[diag(expand_metavar_still_repeating)]
pub(crate) struct MacroVarStillRepeating {
#[primary_span]
pub span: Span,
pub ident: MacroRulesNormalizedIdent,
}
#[derive(LintDiagnostic)]
#[diag(expand_metavar_still_repeating)]
pub(crate) struct MetaVarStillRepeatingLint {
#[label]
pub label: Span,
pub ident: MacroRulesNormalizedIdent,
}
#[derive(LintDiagnostic)]
#[diag(expand_metavariable_wrong_operator)]
pub(crate) struct MetaVariableWrongOperator {
#[label(expand_binder_label)]
pub binder: Span,
#[label(expand_occurrence_label)]
pub occurrence: Span,
}
#[derive(Diagnostic)]
#[diag(expand_meta_var_dif_seq_matchers)]
pub(crate) struct MetaVarsDifSeqMatchers {
@ -43,6 +64,12 @@ pub(crate) struct MetaVarsDifSeqMatchers {
pub msg: String,
}
#[derive(LintDiagnostic)]
#[diag(expand_unknown_macro_variable)]
pub(crate) struct UnknownMacroVariable {
pub name: MacroRulesNormalizedIdent,
}
#[derive(Diagnostic)]
#[diag(expand_resolve_relative_path)]
pub(crate) struct ResolveRelativePath {
@ -345,6 +372,15 @@ pub(crate) struct DuplicateMatcherBinding {
pub prev: Span,
}
#[derive(LintDiagnostic)]
#[diag(expand_duplicate_matcher_binding)]
pub(crate) struct DuplicateMatcherBindingLint {
#[label]
pub span: Span,
#[label(expand_label2)]
pub prev: Span,
}
#[derive(Diagnostic)]
#[diag(expand_missing_fragment_specifier)]
#[note]
@ -501,3 +537,39 @@ pub(crate) struct MacroArgsBadDelimSugg {
#[suggestion_part(code = ")")]
pub close: Span,
}
#[derive(LintDiagnostic)]
#[diag(expand_macro_call_unused_doc_comment)]
#[help]
pub(crate) struct MacroCallUnusedDocComment {
#[label]
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(expand_or_patterns_back_compat)]
pub(crate) struct OrPatternsBackCompat {
#[suggestion(code = "{suggestion}", applicability = "machine-applicable")]
pub span: Span,
pub suggestion: String,
}
#[derive(LintDiagnostic)]
#[diag(expand_trailing_semi_macro)]
pub(crate) struct TrailingMacro {
#[note(expand_note1)]
#[note(expand_note2)]
pub is_trailing: bool,
pub name: Ident,
}
#[derive(LintDiagnostic)]
#[diag(expand_unused_builtin_attribute)]
pub(crate) struct UnusedBuiltinAttribute {
#[note]
pub invoc_span: Span,
pub attr_name: Symbol,
pub macro_name: String,
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
pub attr_span: Span,
}

View file

@ -25,7 +25,6 @@ use rustc_parse::parser::{
token_descr,
};
use rustc_session::Session;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
use rustc_session::parse::feature_err;
use rustc_span::hygiene::SyntaxContext;
@ -2183,7 +2182,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
UNUSED_DOC_COMMENTS,
current_span,
self.cx.current_expansion.lint_node_id,
BuiltinLintDiag::UnusedDocComment(attr.span),
crate::errors::MacroCallUnusedDocComment { span: attr.span },
);
} else if rustc_attr_parsing::is_builtin_attr(attr)
&& !AttributeParser::<Early>::is_parsed_attribute(&attr.path())
@ -2196,7 +2195,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
UNUSED_ATTRIBUTES,
attr.span,
self.cx.current_expansion.lint_node_id,
BuiltinLintDiag::UnusedBuiltinAttribute {
crate::errors::UnusedBuiltinAttribute {
attr_name,
macro_name: pprust::path_to_string(&call.path),
invoc_span: call.path.span,

View file

@ -108,8 +108,7 @@
use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind};
use rustc_ast::{DUMMY_NODE_ID, NodeId};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::MultiSpan;
use rustc_lint_defs::BuiltinLintDiag;
use rustc_errors::DecorateDiagCompat;
use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
use rustc_session::parse::ParseSess;
use rustc_span::{ErrorGuaranteed, MacroRulesNormalizedIdent, Span, kw};
@ -245,9 +244,12 @@ fn check_binders(
// There are 3 possibilities:
if let Some(prev_info) = binders.get(&name) {
// 1. The meta-variable is already bound in the current LHS: This is an error.
let mut span = MultiSpan::from_span(span);
span.push_span_label(prev_info.span, "previous declaration");
buffer_lint(psess, span, node_id, BuiltinLintDiag::DuplicateMatcherBinding);
buffer_lint(
psess,
span,
node_id,
errors::DuplicateMatcherBindingLint { span, prev: prev_info.span },
);
} else if get_binder_info(macros, binders, name).is_none() {
// 2. The meta-variable is free: This is a binder.
binders.insert(name, BinderInfo { span, ops: ops.into() });
@ -579,7 +581,7 @@ fn check_ops_is_prefix(
return;
}
}
buffer_lint(psess, span.into(), node_id, BuiltinLintDiag::UnknownMacroVariable(name));
buffer_lint(psess, span, node_id, errors::UnknownMacroVariable { name });
}
/// Returns whether `binder_ops` is a prefix of `occurrence_ops`.
@ -604,29 +606,42 @@ fn ops_is_prefix(
psess: &ParseSess,
node_id: NodeId,
span: Span,
name: MacroRulesNormalizedIdent,
ident: MacroRulesNormalizedIdent,
binder_ops: &[KleeneToken],
occurrence_ops: &[KleeneToken],
) {
for (i, binder) in binder_ops.iter().enumerate() {
if i >= occurrence_ops.len() {
let mut span = MultiSpan::from_span(span);
span.push_span_label(binder.span, "expected repetition");
buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableStillRepeating(name));
buffer_lint(
psess,
span,
node_id,
errors::MetaVarStillRepeatingLint { label: binder.span, ident },
);
return;
}
let occurrence = &occurrence_ops[i];
if occurrence.op != binder.op {
let mut span = MultiSpan::from_span(span);
span.push_span_label(binder.span, "expected repetition");
span.push_span_label(occurrence.span, "conflicting repetition");
buffer_lint(psess, span, node_id, BuiltinLintDiag::MetaVariableWrongOperator);
buffer_lint(
psess,
span,
node_id,
errors::MetaVariableWrongOperator {
binder: binder.span,
occurrence: occurrence.span,
},
);
return;
}
}
}
fn buffer_lint(psess: &ParseSess, span: MultiSpan, node_id: NodeId, diag: BuiltinLintDiag) {
fn buffer_lint(
psess: &ParseSess,
span: Span,
node_id: NodeId,
diag: impl Into<DecorateDiagCompat>,
) {
// Macros loaded from other crates have dummy node ids.
if node_id != DUMMY_NODE_ID {
psess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, diag);

View file

@ -17,7 +17,6 @@ use rustc_hir as hir;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::MacroKinds;
use rustc_hir::find_attr;
use rustc_lint_defs::BuiltinLintDiag;
use rustc_lint_defs::builtin::{
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
};
@ -90,7 +89,7 @@ impl<'a> ParserAnyMacro<'a> {
SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
parser.token.span,
lint_node_id,
BuiltinLintDiag::TrailingMacro(is_trailing_mac, macro_ident),
errors::TrailingMacro { is_trailing: is_trailing_mac, name: macro_ident },
);
}
parser.bump();
@ -1425,7 +1424,7 @@ fn check_matcher_core<'tt>(
RUST_2021_INCOMPATIBLE_OR_PATTERNS,
span,
ast::CRATE_NODE_ID,
BuiltinLintDiag::OrPatternsBackCompat(span, suggestion),
errors::OrPatternsBackCompat { span, suggestion },
);
}
match is_in_follow(next_token, kind) {

View file

@ -17,8 +17,8 @@ use rustc_span::{
use smallvec::{SmallVec, smallvec};
use crate::errors::{
CountRepetitionMisplaced, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar,
NoSyntaxVarsExprRepeat, VarStillRepeating,
CountRepetitionMisplaced, MacroVarStillRepeating, MetaVarsDifSeqMatchers, MustRepeatOnce,
MveUnrecognizedVar, NoSyntaxVarsExprRepeat,
};
use crate::mbe::macro_parser::NamedMatch;
use crate::mbe::macro_parser::NamedMatch::*;
@ -483,7 +483,7 @@ fn transcribe_metavar<'tx>(
}
MatchedSeq(..) => {
// We were unable to descend far enough. This is an error.
return Err(dcx.create_err(VarStillRepeating { span: sp, ident }));
return Err(dcx.create_err(MacroVarStillRepeating { span: sp, ident }));
}
};

View file

@ -3220,12 +3220,21 @@ pub struct ImplItem<'hir> {
pub owner_id: OwnerId,
pub generics: &'hir Generics<'hir>,
pub kind: ImplItemKind<'hir>,
pub defaultness: Defaultness,
pub impl_kind: ImplItemImplKind,
pub span: Span,
pub vis_span: Span,
pub has_delayed_lints: bool,
/// When we are in a trait impl, link to the trait-item's id.
pub trait_item_def_id: Option<DefId>,
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum ImplItemImplKind {
Inherent {
vis_span: Span,
},
Trait {
defaultness: Defaultness,
/// Item in the trait that this item implements
trait_item_def_id: Result<DefId, ErrorGuaranteed>,
},
}
impl<'hir> ImplItem<'hir> {
@ -3239,6 +3248,13 @@ impl<'hir> ImplItem<'hir> {
ImplItemId { owner_id: self.owner_id }
}
pub fn vis_span(&self) -> Option<Span> {
match self.impl_kind {
ImplItemImplKind::Trait { .. } => None,
ImplItemImplKind::Inherent { vis_span, .. } => Some(vis_span),
}
}
expect_methods_self_kind! {
expect_const, (&'hir Ty<'hir>, BodyId), ImplItemKind::Const(ty, body), (ty, *body);
expect_fn, (&FnSig<'hir>, BodyId), ImplItemKind::Fn(ty, body), (ty, *body);
@ -4985,7 +5001,7 @@ mod size_asserts {
static_assert_size!(GenericBound<'_>, 64);
static_assert_size!(Generics<'_>, 56);
static_assert_size!(Impl<'_>, 40);
static_assert_size!(ImplItem<'_>, 96);
static_assert_size!(ImplItem<'_>, 88);
static_assert_size!(ImplItemKind<'_>, 40);
static_assert_size!(Item<'_>, 88);
static_assert_size!(ItemKind<'_>, 64);

View file

@ -1257,18 +1257,21 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
owner_id: _,
ident,
ref generics,
ref impl_kind,
ref kind,
ref defaultness,
span: _,
vis_span: _,
has_delayed_lints: _,
trait_item_def_id: _,
} = *impl_item;
try_visit!(visitor.visit_ident(ident));
try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_defaultness(defaultness));
try_visit!(visitor.visit_id(impl_item.hir_id()));
match impl_kind {
ImplItemImplKind::Inherent { vis_span: _ } => {}
ImplItemImplKind::Trait { defaultness, trait_item_def_id: _ } => {
try_visit!(visitor.visit_defaultness(defaultness));
}
}
match *kind {
ImplItemKind::Const(ref ty, body) => {
try_visit!(visitor.visit_ty_unambig(ty));

View file

@ -1009,8 +1009,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
res = res.and(check_associated_item(tcx, def_id));
let assoc_item = tcx.associated_item(def_id);
match assoc_item.container {
ty::AssocItemContainer::Impl => {}
ty::AssocItemContainer::Trait => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {}
ty::AssocContainer::Trait => {
res = res.and(check_trait_item(tcx, def_id));
}
}
@ -1026,8 +1026,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
res = res.and(check_associated_item(tcx, def_id));
let assoc_item = tcx.associated_item(def_id);
match assoc_item.container {
ty::AssocItemContainer::Impl => {}
ty::AssocItemContainer::Trait => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {}
ty::AssocContainer::Trait => {
res = res.and(check_trait_item(tcx, def_id));
}
}
@ -1043,8 +1043,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
let assoc_item = tcx.associated_item(def_id);
let has_type = match assoc_item.container {
ty::AssocItemContainer::Impl => true,
ty::AssocItemContainer::Trait => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
ty::AssocContainer::Trait => {
tcx.ensure_ok().explicit_item_bounds(def_id);
tcx.ensure_ok().explicit_item_self_bounds(def_id);
if tcx.is_conditionally_const(def_id) {
@ -1177,12 +1177,9 @@ fn check_impl_items_against_trait<'tcx>(
for &impl_item in impl_item_refs {
let ty_impl_item = tcx.associated_item(impl_item);
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
tcx.associated_item(trait_item_id)
} else {
// Checked in `associated_item`.
tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait");
continue;
let ty_trait_item = match ty_impl_item.expect_trait_impl() {
Ok(trait_item_id) => tcx.associated_item(trait_item_id),
Err(ErrorGuaranteed { .. }) => continue,
};
let res = tcx.ensure_ok().compare_impl_item(impl_item.expect_local());

View file

@ -37,7 +37,7 @@ pub(super) fn compare_impl_item(
impl_item_def_id: LocalDefId,
) -> Result<(), ErrorGuaranteed> {
let impl_item = tcx.associated_item(impl_item_def_id);
let trait_item = tcx.associated_item(impl_item.trait_item_def_id.unwrap());
let trait_item = tcx.associated_item(impl_item.expect_trait_impl()?);
let impl_trait_ref =
tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity();
debug!(?impl_trait_ref);
@ -298,14 +298,9 @@ fn compare_method_predicate_entailment<'tcx>(
// compatible with that of the trait method. We do this by
// checking that `impl_fty <: trait_fty`.
//
// FIXME. Unfortunately, this doesn't quite work right now because
// associated type normalization is not integrated into subtype
// checks. For the comparison to be valid, we need to
// normalize the associated types in the impl/trait methods
// first. However, because function types bind regions, just
// calling `FnCtxt::normalize` would have no effect on
// any associated types appearing in the fn arguments or return
// type.
// FIXME: We manually instantiate the trait method here as we need
// to manually compute its implied bounds. Otherwise this could just
// be `ocx.sub(impl_sig, trait_sig)`.
let mut wf_tys = FxIndexSet::default();
@ -446,7 +441,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
impl_m_def_id: LocalDefId,
) -> Result<&'tcx DefIdMap<ty::EarlyBinder<'tcx, Ty<'tcx>>>, ErrorGuaranteed> {
let impl_m = tcx.associated_item(impl_m_def_id.to_def_id());
let trait_m = tcx.associated_item(impl_m.trait_item_def_id.unwrap());
let trait_m = tcx.associated_item(impl_m.expect_trait_impl()?);
let impl_trait_ref =
tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).unwrap().instantiate_identity();
// First, check a few of the same things as `compare_impl_method`,
@ -1449,8 +1444,10 @@ fn compare_self_type<'tcx>(
let self_string = |method: ty::AssocItem| {
let untransformed_self_ty = match method.container {
ty::AssocItemContainer::Impl => impl_trait_ref.self_ty(),
ty::AssocItemContainer::Trait => tcx.types.self_param,
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
impl_trait_ref.self_ty()
}
ty::AssocContainer::Trait => tcx.types.self_param,
};
let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
let (infcx, param_env) = tcx
@ -2458,8 +2455,12 @@ fn param_env_with_gat_bounds<'tcx>(
for impl_ty in impl_tys_to_install {
let trait_ty = match impl_ty.container {
ty::AssocItemContainer::Trait => impl_ty,
ty::AssocItemContainer::Impl => tcx.associated_item(impl_ty.trait_item_def_id.unwrap()),
ty::AssocContainer::InherentImpl => bug!(),
ty::AssocContainer::Trait => impl_ty,
ty::AssocContainer::TraitImpl(Err(_)) => continue,
ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) => {
tcx.associated_item(trait_item_def_id)
}
};
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =

View file

@ -944,12 +944,11 @@ pub(crate) fn check_associated_item(
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
// other `Foo` impls are incoherent.
tcx.ensure_ok()
.coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?;
tcx.ensure_ok().coherent_trait(tcx.parent(item.trait_item_or_self()?))?;
let self_ty = match item.container {
ty::AssocItemContainer::Trait => tcx.types.self_param,
ty::AssocItemContainer::Impl => {
ty::AssocContainer::Trait => tcx.types.self_param,
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
tcx.type_of(item.container_id(tcx)).instantiate_identity()
}
};
@ -978,7 +977,7 @@ pub(crate) fn check_associated_item(
check_method_receiver(wfcx, hir_sig, item, self_ty)
}
ty::AssocKind::Type { .. } => {
if let ty::AssocItemContainer::Trait = item.container {
if let ty::AssocContainer::Trait = item.container {
check_associated_type_bounds(wfcx, item, span)
}
if item.defaultness(tcx).has_value() {

View file

@ -111,9 +111,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
let assoc_item = tcx.associated_item(def_id);
let trait_assoc_predicates =
tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
let trait_item_def_id = tcx.trait_item_of(def_id).unwrap();
let trait_assoc_predicates = tcx.explicit_predicates_of(trait_item_def_id);
let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
let impl_def_id = tcx.parent(fn_def_id);

View file

@ -125,8 +125,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
Some(ty::ImplTraitInTraitData::Impl { fn_def_id }) => {
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
Ok(map) => {
let assoc_item = tcx.associated_item(def_id);
return map[&assoc_item.trait_item_def_id.unwrap()];
let trait_item_def_id = tcx.trait_item_of(def_id).unwrap();
return map[&trait_item_def_id];
}
Err(_) => {
return ty::EarlyBinder::bind(Ty::new_error_with_message(
@ -198,7 +198,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
}
}
ImplItemKind::Type(ty) => {
if tcx.impl_trait_ref(tcx.hir_get_parent_item(hir_id)).is_none() {
if let ImplItemImplKind::Inherent { .. } = item.impl_kind {
check_feature_inherent_assoc_ty(tcx, item.span);
}

View file

@ -1021,7 +1021,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let container_id = assoc_item.container_id(tcx);
debug!(?def_id, ?container, ?container_id);
match container {
ty::AssocItemContainer::Trait => {
ty::AssocContainer::Trait => {
if let Err(e) = callee::check_legal_trait_for_method_call(
tcx,
path_span,
@ -1033,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.set_tainted_by_errors(e);
}
}
ty::AssocItemContainer::Impl => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
if segments.len() == 1 {
// `<T>::assoc` will end up here, and so
// can `T::assoc`. If this came from an

View file

@ -2354,7 +2354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We want it to always point to the trait item.
// If we're pointing at an inherent function, we don't need to do anything,
// so we fetch the parent and verify if it's a trait item.
&& let maybe_trait_item_def_id = assoc_item.trait_item_def_id.unwrap_or(def_id)
&& let Ok(maybe_trait_item_def_id) = assoc_item.trait_item_or_self()
&& let maybe_trait_def_id = self.tcx.parent(maybe_trait_item_def_id)
// Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce"
&& let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)

View file

@ -1882,7 +1882,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if segment.ident.name == sym::clone
&& results.type_dependent_def_id(expr.hir_id).is_some_and(|did| {
let assoc_item = self.tcx.associated_item(did);
assoc_item.container == ty::AssocItemContainer::Trait
assoc_item.container == ty::AssocContainer::Trait
&& assoc_item.container_id(self.tcx) == clone_trait_did
})
// If that clone call hasn't already dereferenced the self type (i.e. don't give this

View file

@ -278,8 +278,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
{
if let Some(item) = tcx.opt_associated_item(def_id.into())
&& let ty::AssocKind::Const { .. } = item.kind
&& let ty::AssocItemContainer::Impl = item.container
&& let Some(trait_item_def_id) = item.trait_item_def_id
&& let ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container
{
let impl_def_id = item.container_id(tcx);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();

View file

@ -18,8 +18,8 @@ use rustc_middle::middle::stability;
use rustc_middle::ty::elaborate::supertrait_def_ids;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
use rustc_middle::ty::{
self, AssocItem, AssocItemContainer, GenericArgs, GenericArgsRef, GenericParamDefKind,
ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, Upcast,
self, AssocContainer, AssocItem, GenericArgs, GenericArgsRef, GenericParamDefKind, ParamEnvAnd,
Ty, TyCtxt, TypeVisitableExt, Upcast,
};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
@ -528,7 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ProbeScope::Single(def_id) => {
let item = self.tcx.associated_item(def_id);
// FIXME(fn_delegation): Delegation to inherent methods is not yet supported.
assert_eq!(item.container, AssocItemContainer::Trait);
assert_eq!(item.container, AssocContainer::Trait);
let trait_def_id = self.tcx.parent(def_id);
let trait_span = self.tcx.def_span(trait_def_id);
@ -1659,7 +1659,7 @@ impl<'tcx> Pick<'tcx> {
/// Do not use for type checking.
pub(crate) fn differs_from(&self, other: &Self) -> bool {
let Self {
item: AssocItem { def_id, kind: _, container: _, trait_item_def_id: _ },
item: AssocItem { def_id, kind: _, container: _ },
kind: _,
import_ids: _,
autoderefs: _,
@ -1702,7 +1702,7 @@ impl<'tcx> Pick<'tcx> {
tcx.def_path_str(self.item.def_id),
));
}
(ty::AssocKind::Const { name }, ty::AssocItemContainer::Trait) => {
(ty::AssocKind::Const { name }, ty::AssocContainer::Trait) => {
let def_id = self.item.container_id(tcx);
lint.span_suggestion(
span,

View file

@ -30,6 +30,9 @@ interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
interface_input_file_would_be_overwritten =
the input file "{$path}" would be overwritten by the generated executable
interface_invalid_crate_type_value = invalid `crate_type` value
.suggestion = did you mean
interface_mixed_bin_crate =
cannot mix `bin` crate type with others

View file

@ -1,7 +1,7 @@
use std::io;
use std::path::Path;
use rustc_macros::Diagnostic;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
#[derive(Diagnostic)]
@ -108,3 +108,18 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
pub feature: &'a str,
pub enabled: &'a str,
}
#[derive(LintDiagnostic)]
#[diag(interface_invalid_crate_type_value)]
pub(crate) struct UnknownCrateTypes {
#[subdiagnostic]
pub sugg: Option<UnknownCrateTypesSub>,
}
#[derive(Subdiagnostic)]
#[suggestion(interface_suggestion, code = r#""{snippet}""#, applicability = "maybe-incorrect")]
pub(crate) struct UnknownCrateTypesSub {
#[primary_span]
pub span: Span,
pub snippet: Symbol,
}

View file

@ -13,9 +13,8 @@ use rustc_errors::LintBuffer;
use rustc_metadata::{DylibError, load_symbol_from_dylib};
use rustc_middle::ty::CurrentGcx;
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, Sysroot, host_tuple};
use rustc_session::lint::{self, BuiltinLintDiag};
use rustc_session::output::{CRATE_TYPES, categorize_crate_type};
use rustc_session::{EarlyDiagCtxt, Session, filesearch};
use rustc_session::{EarlyDiagCtxt, Session, filesearch, lint};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::source_map::SourceMapInputs;
@ -468,7 +467,10 @@ pub(crate) fn check_attr_crate_type(
lint::builtin::UNKNOWN_CRATE_TYPES,
ast::CRATE_NODE_ID,
span,
BuiltinLintDiag::UnknownCrateTypes { span, candidate },
errors::UnknownCrateTypes {
sugg: candidate
.map(|cand| errors::UnknownCrateTypesSub { span, snippet: cand }),
},
);
}
} else {

View file

@ -40,12 +40,6 @@ lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` order
lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering
.help = consider using ordering modes `Release`, `SeqCst` or `Relaxed`
lint_avoid_att_syntax =
avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
lint_avoid_intel_syntax =
avoid using `.intel_syntax`, Intel syntax is the default
lint_bad_attribute_argument = bad attribute argument
lint_bad_opt_access = {$msg}
@ -187,12 +181,6 @@ lint_builtin_unused_doc_comment = unused doc comment
lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
.suggestion = use `loop`
lint_byte_slice_in_packed_struct_with_derive = {$ty} slice in a packed struct that derives a built-in trait
.help = consider implementing the trait by hand, or remove the `packed` attribute
lint_cfg_attr_no_attributes =
`#[cfg_attr]` does not expand to any attributes
lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
lint_closure_returning_async_block = closure returning async block can be made into an async closure
@ -249,11 +237,6 @@ lint_dropping_copy_types = calls to `std::mem::drop` with a value that implement
lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
.label = argument has type `{$arg_ty}`
lint_duplicate_macro_attribute =
duplicated attribute
lint_duplicate_matcher_binding = duplicate matcher binding
lint_enum_intrinsics_mem_discriminant =
the return value of `mem::discriminant` is unspecified when called with a non-enum type
.note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum
@ -409,9 +392,6 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
lint_incomplete_include =
include macro expected single expression in source
lint_invalid_asm_label_binary = avoid using labels containing only the digits `0` and `1` in inline assembly
.label = use a different label that doesn't start with `0` or `1`
.help = start numbering with `2` instead
@ -427,9 +407,6 @@ lint_invalid_asm_label_named = avoid using named labels in inline assembly
.note = see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
lint_invalid_asm_label_no_span = the label may be declared in the expansion of a macro
lint_invalid_crate_type_value = invalid `crate_type` value
.suggestion = did you mean
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
lint_invalid_from_utf8_checked = calls to `{$method}` with an invalid literal always return an error
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
@ -470,15 +447,9 @@ lint_int_to_ptr_transmutes = transmuting an integer to a pointer creates a point
.suggestion_with_exposed_provenance = use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance
.suggestion_without_provenance_mut = if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
lint_legacy_derive_helpers = derive helper attribute is used before it is introduced
.label = the attribute is introduced here
lint_lintpass_by_hand = implementing `LintPass` by hand
.help = try using `declare_lint_pass!` or `impl_lint_pass!` instead
lint_macro_expanded_macro_exports_accessed_by_absolute_paths = macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
.note = the macro is defined here
lint_macro_expr_fragment_specifier_2024_migration =
the `expr` fragment specifier will accept more expressions in the 2024 edition
.suggestion = to keep the existing behavior, use the `expr_2021` fragment specifier
@ -486,10 +457,6 @@ lint_macro_is_private = macro `{$ident}` is private
lint_macro_rule_never_used = rule #{$n} of macro `{$name}` is never used
lint_macro_use_deprecated =
applying the `#[macro_use]` attribute to an `extern crate` item is deprecated
.help = remove it and import macros at use sites with a `use` item instead
lint_malformed_attribute = malformed lint attribute input
lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
@ -499,10 +466,6 @@ lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
.map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
.suggestion = you might have meant to use `Iterator::for_each`
lint_metavariable_still_repeating = variable `{$name}` is still repeating at this depth
lint_metavariable_wrong_operator = meta-variable repeats with different Kleene operator
lint_mismatched_lifetime_syntaxes_eliding_while_named =
eliding a lifetime that's named elsewhere is confusing
@ -548,9 +511,6 @@ lint_mismatched_lifetime_syntaxes_suggestion_mixed =
lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths =
use `'_` for type paths
lint_missing_unsafe_on_extern = extern blocks should be unsafe
.suggestion = needs `unsafe` before the extern keyword
lint_mixed_script_confusables =
the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
.includes_note = the usage includes {$includes}
@ -674,9 +634,6 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass
lint_opaque_hidden_inferred_bound_sugg = add this bound
lint_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
.suggestion = use pat_param to preserve semantics
lint_out_of_scope_macro_calls = cannot find macro `{$path}` in the current scope when looking from {$location}
.label = not found from {$location}
.help = import `macro_rules` with `use` to make it callable above its definition
@ -719,9 +676,6 @@ lint_pattern_in_foreign = patterns aren't allowed in foreign function declaratio
lint_private_extern_crate_reexport = extern crate `{$ident}` is private and cannot be re-exported
.suggestion = consider making the `extern crate` item publicly accessible
lint_proc_macro_derive_resolution_fallback = cannot find {$ns_descr} `{$ident}` in this scope
.label = names from parent modules are not accessible without an explicit import
lint_query_instability = using `{$query}` can result in unstable query results
.note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
@ -762,9 +716,6 @@ lint_redundant_semicolons_suggestion = remove {$multiple_semicolons ->
*[false] this semicolon
}
lint_reexport_private_dependency =
{$kind} `{$name}` from private dependency '{$krate}' is re-exported
lint_remove_mut_from_pattern = remove `mut` from the parameter
lint_removed_lint = lint `{$name}` has been removed: {$reason}
@ -826,10 +777,6 @@ lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal
lint_too_large_char_cast = value exceeds maximum `char` value
.note = maximum valid `char` value is `0x10FFFF`
lint_trailing_semi_macro = trailing semicolon in macro used in expression position
.note1 = macro invocations at the end of a block are treated as expressions
.note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`
lint_ty_qualified = usage of qualified `ty::{$ty}`
.suggestion = try importing it and using it unqualified
@ -935,13 +882,9 @@ lint_unknown_lint =
*[false] did you mean: `{$replace}`
}
lint_unknown_macro_variable = unknown macro variable `{$name}`
lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
.help = add `#![register_tool({$tool_name})]` to the crate root
lint_unnameable_test_items = cannot test inner items
lint_unnecessary_qualification = unnecessary qualification
.suggestion = remove the unnecessary path segments
@ -964,10 +907,6 @@ lint_untranslatable_diag = diagnostics should be created using translatable mess
lint_unused_allocation = unnecessary allocation, use `&` instead
lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead
lint_unused_builtin_attribute = unused attribute `{$attr_name}`
.note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}`
.suggestion = remove the attribute
lint_unused_closure =
unused {$pre}{$count ->
[one] closure
@ -993,14 +932,6 @@ lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
lint_unused_delim = unnecessary {$delim} around {$item}
.suggestion = remove these {$delim}
lint_unused_doc_comment = unused doc comment
.label = rustdoc does not generate documentation for macro invocations
.help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion
lint_unused_extern_crate = unused extern crate
.label = unused
.suggestion = remove the unused `extern crate`
lint_unused_import_braces = braces around {$node} is unnecessary
lint_unused_imports = {$num_snippets ->
@ -1014,15 +945,11 @@ lint_unused_imports = {$num_snippets ->
}
.help = if this is a test module, consider adding a `#[cfg(test)]` to the containing module
lint_unused_label = unused label
lint_unused_lifetime = lifetime parameter `{$ident}` never used
.suggestion = elide the unused lifetime
lint_unused_macro_definition = unused macro definition: `{$name}`
lint_unused_macro_use = unused `#[macro_use]` import
lint_unused_op = unused {$op} that must be used
.label = the {$op} produces a value
.suggestion = use `let _ = ...` to ignore the resulting value

View file

@ -29,12 +29,12 @@ use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_hir::intravisit::FnKind as HirFnKind;
use rustc_hir::{Body, FnDecl, PatKind, PredicateOrigin, find_attr};
use rustc_hir::{Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr};
use rustc_middle::bug;
use rustc_middle::lint::LevelAndSource;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef};
use rustc_middle::ty::{self, AssocContainer, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef};
use rustc_session::lint::FutureIncompatibilityReason;
// hardwired lints from rustc_lint_defs
pub use rustc_session::lint::builtin::*;
@ -61,7 +61,6 @@ use crate::lints::{
BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
};
use crate::nonstandard_style::{MethodLateContext, method_context};
use crate::{
EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
fluent_generated as fluent,
@ -469,14 +468,14 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
let context = method_context(cx, impl_item.owner_id.def_id);
let container = cx.tcx.associated_item(impl_item.owner_id.def_id).container;
match context {
match container {
// If the method is an impl for a trait, don't doc.
MethodLateContext::TraitImpl => return,
MethodLateContext::TraitAutoImpl => {}
AssocContainer::TraitImpl(_) => return,
AssocContainer::Trait => {}
// If the method is an impl for an item with docs_hidden, don't doc.
MethodLateContext::PlainImpl => {
AssocContainer::InherentImpl => {
let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id());
let impl_ty = cx.tcx.type_of(parent).instantiate_identity();
let outerdef = match impl_ty.kind() {
@ -1321,9 +1320,8 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
// Only lint inherent impl items.
if cx.tcx.associated_item(impl_item.owner_id).trait_item_def_id.is_none() {
self.perform_lint(cx, "item", impl_item.owner_id.def_id, impl_item.vis_span, false);
if let ImplItemImplKind::Inherent { vis_span } = impl_item.impl_kind {
self.perform_lint(cx, "item", impl_item.owner_id.def_id, vis_span, false);
}
}
}

View file

@ -64,17 +64,6 @@ pub fn decorate_builtin_lint(
}
.decorate_lint(diag);
}
BuiltinLintDiag::ProcMacroDeriveResolutionFallback {
span: macro_span,
ns_descr,
ident,
} => lints::ProcMacroDeriveResolutionFallback { span: macro_span, ns_descr, ident }
.decorate_lint(diag),
BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
lints::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def }
.decorate_lint(diag)
}
BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => {
lints::ElidedLifetimesInPaths {
subdiag: elided_lifetime_in_path_suggestion(
@ -87,10 +76,6 @@ pub fn decorate_builtin_lint(
}
.decorate_lint(diag);
}
BuiltinLintDiag::UnknownCrateTypes { span, candidate } => {
let sugg = candidate.map(|candidate| lints::UnknownCrateTypesSub { span, candidate });
lints::UnknownCrateTypes { sugg }.decorate_lint(diag);
}
BuiltinLintDiag::UnusedImports {
remove_whole_use,
num_to_remove,
@ -146,9 +131,6 @@ pub fn decorate_builtin_lint(
stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }
.decorate_lint(diag);
}
BuiltinLintDiag::UnusedDocComment(attr_span) => {
lints::UnusedDocComment { span: attr_span }.decorate_lint(diag);
}
BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => {
let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span };
if is_foreign {
@ -158,12 +140,6 @@ pub fn decorate_builtin_lint(
}
.decorate_lint(diag);
}
BuiltinLintDiag::LegacyDeriveHelpers(label_span) => {
lints::LegacyDeriveHelpers { span: label_span }.decorate_lint(diag);
}
BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => {
lints::OrPatternsBackCompat { span: suggestion_span, suggestion }.decorate_lint(diag);
}
BuiltinLintDiag::ReservedPrefix(label_span, prefix) => {
lints::ReservedPrefix {
label: label_span,
@ -183,18 +159,6 @@ pub fn decorate_builtin_lint(
lints::ReservedMultihash { suggestion }.decorate_lint(diag);
}
}
BuiltinLintDiag::UnusedBuiltinAttribute {
attr_name,
macro_name,
invoc_span,
attr_span,
} => {
lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name, attr_span }
.decorate_lint(diag);
}
BuiltinLintDiag::TrailingMacro(is_trailing, name) => {
lints::TrailingMacro { is_trailing, name }.decorate_lint(diag);
}
BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => {
lints::BreakWithLabelAndLoop {
sub: lints::BreakWithLabelAndLoopSub {
@ -221,9 +185,6 @@ pub fn decorate_builtin_lint(
};
lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag);
}
BuiltinLintDiag::MissingUnsafeOnExtern { suggestion } => {
lints::MissingUnsafeOnExtern { suggestion }.decorate_lint(diag);
}
BuiltinLintDiag::SingleUseLifetime {
param_span,
use_span: Some((use_span, elide)),
@ -253,7 +214,6 @@ pub fn decorate_builtin_lint(
.decorate_lint(diag);
}
BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => {
debug!(?deletion_span);
lints::UnusedLifetime { deletion_span, ident }.decorate_lint(diag);
}
BuiltinLintDiag::NamedArgumentUsedPositionally {
@ -291,12 +251,6 @@ pub fn decorate_builtin_lint(
}
.decorate_lint(diag);
}
BuiltinLintDiag::ByteSliceInPackedStructWithDerive { ty } => {
lints::ByteSliceInPackedStructWithDerive { ty }.decorate_lint(diag);
}
BuiltinLintDiag::UnusedExternCrate { span, removal_span } => {
lints::UnusedExternCrate { span, removal_span }.decorate_lint(diag);
}
BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => {
let suggestion_span = vis_span.between(ident_span);
let code = if vis_span.is_empty() { "use " } else { " use " };
@ -335,9 +289,6 @@ pub fn decorate_builtin_lint(
}
.decorate_lint(diag);
}
BuiltinLintDiag::ReexportPrivateDependency { name, kind, krate } => {
lints::ReexportPrivateDependency { name, kind, krate }.decorate_lint(diag);
}
BuiltinLintDiag::UnusedQualifications { removal_span } => {
lints::UnusedQualifications { removal_span }.decorate_lint(diag);
}
@ -377,15 +328,10 @@ pub fn decorate_builtin_lint(
});
lints::UnknownDiagnosticAttribute { typo }.decorate_lint(diag);
}
BuiltinLintDiag::MacroUseDeprecated => {
lints::MacroUseDeprecated.decorate_lint(diag);
}
BuiltinLintDiag::UnusedMacroUse => lints::UnusedMacroUse.decorate_lint(diag),
BuiltinLintDiag::PrivateExternCrateReexport { source: ident, extern_crate_span } => {
lints::PrivateExternCrateReexport { ident, sugg: extern_crate_span.shrink_to_lo() }
.decorate_lint(diag);
}
BuiltinLintDiag::UnusedLabel => lints::UnusedLabel.decorate_lint(diag),
BuiltinLintDiag::MacroIsPrivate(ident) => {
lints::MacroIsPrivate { ident }.decorate_lint(diag);
}
@ -398,36 +344,6 @@ pub fn decorate_builtin_lint(
BuiltinLintDiag::UnstableFeature(msg) => {
lints::UnstableFeature { msg }.decorate_lint(diag);
}
BuiltinLintDiag::AvoidUsingIntelSyntax => {
lints::AvoidIntelSyntax.decorate_lint(diag);
}
BuiltinLintDiag::AvoidUsingAttSyntax => {
lints::AvoidAttSyntax.decorate_lint(diag);
}
BuiltinLintDiag::IncompleteInclude => {
lints::IncompleteInclude.decorate_lint(diag);
}
BuiltinLintDiag::UnnameableTestItems => {
lints::UnnameableTestItems.decorate_lint(diag);
}
BuiltinLintDiag::DuplicateMacroAttribute => {
lints::DuplicateMacroAttribute.decorate_lint(diag);
}
BuiltinLintDiag::CfgAttrNoAttributes => {
lints::CfgAttrNoAttributes.decorate_lint(diag);
}
BuiltinLintDiag::MetaVariableStillRepeating(name) => {
lints::MetaVariableStillRepeating { name }.decorate_lint(diag);
}
BuiltinLintDiag::MetaVariableWrongOperator => {
lints::MetaVariableWrongOperator.decorate_lint(diag);
}
BuiltinLintDiag::DuplicateMatcherBinding => {
lints::DuplicateMatcherBinding.decorate_lint(diag);
}
BuiltinLintDiag::UnknownMacroVariable(name) => {
lints::UnknownMacroVariable { name }.decorate_lint(diag);
}
BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => {
lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag)
}

View file

@ -17,7 +17,7 @@ use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_session::Session;
use rustc_session::lint::AmbiguityErrorDiag;
use rustc_span::edition::Edition;
use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, sym};
use rustc_span::{Ident, Span, Symbol, sym};
use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds};
use crate::errors::{OverruledAttributeSub, RequestedLevel};
@ -2535,15 +2535,6 @@ pub(crate) mod unexpected_cfg_value {
}
}
#[derive(LintDiagnostic)]
#[diag(lint_macro_use_deprecated)]
#[help]
pub(crate) struct MacroUseDeprecated;
#[derive(LintDiagnostic)]
#[diag(lint_unused_macro_use)]
pub(crate) struct UnusedMacroUse;
#[derive(LintDiagnostic)]
#[diag(lint_private_extern_crate_reexport, code = E0365)]
pub(crate) struct PrivateExternCrateReexport {
@ -2552,10 +2543,6 @@ pub(crate) struct PrivateExternCrateReexport {
pub sugg: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_unused_label)]
pub(crate) struct UnusedLabel;
#[derive(LintDiagnostic)]
#[diag(lint_macro_is_private)]
pub(crate) struct MacroIsPrivate {
@ -2585,50 +2572,6 @@ impl<'a> LintDiagnostic<'a, ()> for UnstableFeature {
}
}
#[derive(LintDiagnostic)]
#[diag(lint_avoid_intel_syntax)]
pub(crate) struct AvoidIntelSyntax;
#[derive(LintDiagnostic)]
#[diag(lint_avoid_att_syntax)]
pub(crate) struct AvoidAttSyntax;
#[derive(LintDiagnostic)]
#[diag(lint_incomplete_include)]
pub(crate) struct IncompleteInclude;
#[derive(LintDiagnostic)]
#[diag(lint_unnameable_test_items)]
pub(crate) struct UnnameableTestItems;
#[derive(LintDiagnostic)]
#[diag(lint_duplicate_macro_attribute)]
pub(crate) struct DuplicateMacroAttribute;
#[derive(LintDiagnostic)]
#[diag(lint_cfg_attr_no_attributes)]
pub(crate) struct CfgAttrNoAttributes;
#[derive(LintDiagnostic)]
#[diag(lint_metavariable_still_repeating)]
pub(crate) struct MetaVariableStillRepeating {
pub name: MacroRulesNormalizedIdent,
}
#[derive(LintDiagnostic)]
#[diag(lint_metavariable_wrong_operator)]
pub(crate) struct MetaVariableWrongOperator;
#[derive(LintDiagnostic)]
#[diag(lint_duplicate_matcher_binding)]
pub(crate) struct DuplicateMatcherBinding;
#[derive(LintDiagnostic)]
#[diag(lint_unknown_macro_variable)]
pub(crate) struct UnknownMacroVariable {
pub name: MacroRulesNormalizedIdent,
}
#[derive(LintDiagnostic)]
#[diag(lint_unused_crate_dependency)]
#[help]
@ -2714,22 +2657,6 @@ pub(crate) struct AbsPathWithModuleSugg {
pub replacement: String,
}
#[derive(LintDiagnostic)]
#[diag(lint_proc_macro_derive_resolution_fallback)]
pub(crate) struct ProcMacroDeriveResolutionFallback {
#[label]
pub span: Span,
pub ns_descr: &'static str,
pub ident: Ident,
}
#[derive(LintDiagnostic)]
#[diag(lint_macro_expanded_macro_exports_accessed_by_absolute_paths)]
pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths {
#[note]
pub definition: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_hidden_lifetime_parameters)]
pub(crate) struct ElidedLifetimesInPaths {
@ -2737,21 +2664,6 @@ pub(crate) struct ElidedLifetimesInPaths {
pub subdiag: ElidedLifetimeInPathSubdiag,
}
#[derive(LintDiagnostic)]
#[diag(lint_invalid_crate_type_value)]
pub(crate) struct UnknownCrateTypes {
#[subdiagnostic]
pub sugg: Option<UnknownCrateTypesSub>,
}
#[derive(Subdiagnostic)]
#[suggestion(lint_suggestion, code = r#""{candidate}""#, applicability = "maybe-incorrect")]
pub(crate) struct UnknownCrateTypesSub {
#[primary_span]
pub span: Span,
pub candidate: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(lint_unused_imports)]
pub(crate) struct UnusedImports {
@ -2809,14 +2721,6 @@ pub(crate) enum RedundantImportSub {
DefinedPrelude(#[primary_span] Span),
}
#[derive(LintDiagnostic)]
#[diag(lint_unused_doc_comment)]
#[help]
pub(crate) struct UnusedDocComment {
#[label]
pub span: Span,
}
#[derive(LintDiagnostic)]
pub(crate) enum PatternsInFnsWithoutBody {
#[diag(lint_pattern_in_foreign)]
@ -2840,21 +2744,6 @@ pub(crate) struct PatternsInFnsWithoutBodySub {
pub ident: Ident,
}
#[derive(LintDiagnostic)]
#[diag(lint_legacy_derive_helpers)]
pub(crate) struct LegacyDeriveHelpers {
#[label]
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_or_patterns_back_compat)]
pub(crate) struct OrPatternsBackCompat {
#[suggestion(code = "{suggestion}", applicability = "machine-applicable")]
pub span: Span,
pub suggestion: String,
}
#[derive(LintDiagnostic)]
#[diag(lint_reserved_prefix)]
pub(crate) struct ReservedPrefix {
@ -2875,27 +2764,6 @@ pub(crate) struct RawPrefix {
pub suggestion: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_unused_builtin_attribute)]
pub(crate) struct UnusedBuiltinAttribute {
#[note]
pub invoc_span: Span,
pub attr_name: Symbol,
pub macro_name: String,
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
pub attr_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_trailing_semi_macro)]
pub(crate) struct TrailingMacro {
#[note(lint_note1)]
#[note(lint_note2)]
pub is_trailing: bool,
pub name: Ident,
}
#[derive(LintDiagnostic)]
#[diag(lint_break_with_label_and_loop)]
pub(crate) struct BreakWithLabelAndLoop {
@ -2938,13 +2806,6 @@ pub(crate) enum DeprecatedWhereClauseLocationSugg {
},
}
#[derive(LintDiagnostic)]
#[diag(lint_missing_unsafe_on_extern)]
pub(crate) struct MissingUnsafeOnExtern {
#[suggestion(code = "unsafe ", applicability = "machine-applicable")]
pub suggestion: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_single_use_lifetime)]
pub(crate) struct SingleUseLifetime {
@ -2992,23 +2853,6 @@ pub(crate) struct NamedArgumentUsedPositionally {
pub named_arg_name: String,
}
#[derive(LintDiagnostic)]
#[diag(lint_byte_slice_in_packed_struct_with_derive)]
#[help]
pub(crate) struct ByteSliceInPackedStructWithDerive {
// FIXME: make this translatable
pub ty: String,
}
#[derive(LintDiagnostic)]
#[diag(lint_unused_extern_crate)]
pub(crate) struct UnusedExternCrate {
#[label]
pub span: Span,
#[suggestion(code = "", applicability = "machine-applicable", style = "verbose")]
pub removal_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(lint_extern_crate_not_idiomatic)]
pub(crate) struct ExternCrateNotIdiomatic {
@ -3056,14 +2900,6 @@ pub(crate) struct HiddenGlobReexports {
pub namespace: String,
}
#[derive(LintDiagnostic)]
#[diag(lint_reexport_private_dependency)]
pub(crate) struct ReexportPrivateDependency {
pub name: String,
pub kind: String,
pub krate: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(lint_unnecessary_qualification)]
pub(crate) struct UnusedQualifications {

View file

@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{FnKind, Visitor};
use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr};
use rustc_middle::hir::nested_filter::All;
use rustc_middle::ty;
use rustc_middle::ty::AssocContainer;
use rustc_session::config::CrateType;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::def_id::LocalDefId;
@ -20,29 +20,6 @@ use crate::lints::{
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
#[derive(PartialEq)]
pub(crate) enum MethodLateContext {
TraitAutoImpl,
TraitImpl,
PlainImpl,
}
pub(crate) fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext {
let item = cx.tcx.associated_item(id);
match item.container {
ty::AssocItemContainer::Trait => MethodLateContext::TraitAutoImpl,
ty::AssocItemContainer::Impl => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) {
Some(_) => MethodLateContext::TraitImpl,
None => MethodLateContext::PlainImpl,
},
}
}
fn assoc_item_in_trait_impl(cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) -> bool {
let item = cx.tcx.associated_item(ii.owner_id);
item.trait_item_def_id.is_some()
}
declare_lint! {
/// The `non_camel_case_types` lint detects types, variants, traits and
/// type parameters that don't have camel case names.
@ -389,8 +366,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
id: LocalDefId,
) {
match &fk {
FnKind::Method(ident, sig, ..) => match method_context(cx, id) {
MethodLateContext::PlainImpl => {
FnKind::Method(ident, sig, ..) => match cx.tcx.associated_item(id).container {
AssocContainer::InherentImpl => {
if sig.header.abi != ExternAbi::Rust
&& find_attr!(cx.tcx.get_all_attrs(id), AttributeKind::NoMangle(..))
{
@ -398,10 +375,10 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
}
self.check_snake_case(cx, "method", ident);
}
MethodLateContext::TraitAutoImpl => {
AssocContainer::Trait => {
self.check_snake_case(cx, "trait method", ident);
}
_ => (),
AssocContainer::TraitImpl(_) => {}
},
FnKind::ItemFn(ident, _, header) => {
// Skip foreign-ABI #[no_mangle] functions (Issue #31924)
@ -602,7 +579,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) {
if let hir::ImplItemKind::Const(..) = ii.kind
&& !assoc_item_in_trait_impl(cx, ii)
&& let hir::ImplItemImplKind::Inherent { .. } = ii.impl_kind
{
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ii.ident);
}

View file

@ -11,7 +11,7 @@ use rustc_hir_id::{HashStableContext, HirId, ItemLocalId};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::def_id::DefPathHash;
pub use rustc_span::edition::Edition;
use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, sym};
use rustc_span::{Ident, Span, Symbol, sym};
use serde::{Deserialize, Serialize};
pub use self::Level::*;
@ -620,17 +620,7 @@ pub enum DeprecatedSinceKind {
#[derive(Debug)]
pub enum BuiltinLintDiag {
AbsPathWithModule(Span),
ProcMacroDeriveResolutionFallback {
span: Span,
ns_descr: &'static str,
ident: Ident,
},
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
ElidedLifetimesInPaths(usize, Span, bool, Span),
UnknownCrateTypes {
span: Span,
candidate: Option<Symbol>,
},
UnusedImports {
remove_whole_use: bool,
num_to_remove: usize,
@ -646,20 +636,11 @@ pub enum BuiltinLintDiag {
path: String,
since_kind: DeprecatedSinceKind,
},
UnusedDocComment(Span),
UnusedBuiltinAttribute {
attr_name: Symbol,
macro_name: String,
invoc_span: Span,
attr_span: Span,
},
PatternsInFnsWithoutBody {
span: Span,
ident: Ident,
is_foreign: bool,
},
LegacyDeriveHelpers(Span),
OrPatternsBackCompat(Span, String),
ReservedPrefix(Span, String),
/// `'r#` in edition < 2021.
RawPrefix(Span),
@ -668,15 +649,11 @@ pub enum BuiltinLintDiag {
is_string: bool,
suggestion: Span,
},
TrailingMacro(bool, Ident),
BreakWithLabelAndLoop(Span),
UnicodeTextFlow(Span, String),
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
DeprecatedWhereclauseLocation(Span, Option<(Span, String)>),
MissingUnsafeOnExtern {
suggestion: Span,
},
SingleUseLifetime {
/// Span of the parameter which declares this lifetime.
param_span: Span,
@ -701,14 +678,6 @@ pub enum BuiltinLintDiag {
/// Indicates if the named argument is used as a width/precision for formatting
is_formatting_arg: bool,
},
ByteSliceInPackedStructWithDerive {
// FIXME: enum of byte/string
ty: String,
},
UnusedExternCrate {
span: Span,
removal_span: Span,
},
ExternCrateNotIdiomatic {
vis_span: Span,
ident_span: Span,
@ -736,11 +705,6 @@ pub enum BuiltinLintDiag {
/// The local binding that shadows the glob reexport.
private_item_span: Span,
},
ReexportPrivateDependency {
name: String,
kind: String,
krate: Symbol,
},
UnusedQualifications {
/// The span of the unnecessarily-qualified path to remove.
removal_span: Span,
@ -763,27 +727,14 @@ pub enum BuiltinLintDiag {
span: Span,
typo_name: Option<Symbol>,
},
MacroUseDeprecated,
UnusedMacroUse,
PrivateExternCrateReexport {
source: Ident,
extern_crate_span: Span,
},
UnusedLabel,
MacroIsPrivate(Ident),
UnusedMacroDefinition(Symbol),
MacroRuleNeverUsed(usize, Symbol),
UnstableFeature(DiagMessage),
AvoidUsingIntelSyntax,
AvoidUsingAttSyntax,
IncompleteInclude,
UnnameableTestItems,
DuplicateMacroAttribute,
CfgAttrNoAttributes,
MetaVariableStillRepeating(MacroRulesNormalizedIdent),
MetaVariableWrongOperator,
DuplicateMatcherBinding,
UnknownMacroVariable(MacroRulesNormalizedIdent),
UnusedCrateDependency {
extern_crate: Symbol,
local_crate: Symbol,

View file

@ -1194,10 +1194,6 @@ impl<'a> CrateMetadataRef<'a> {
self.root.tables.default_fields.get(self, id).map(|d| d.decode(self))
}
fn get_trait_item_def_id(self, id: DefIndex) -> Option<DefId> {
self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode_from_cdata(self))
}
fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId {
self.root
.tables
@ -1359,14 +1355,9 @@ impl<'a> CrateMetadataRef<'a> {
}
_ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
};
let container = self.root.tables.assoc_container.get(self, id).unwrap();
let container = self.root.tables.assoc_container.get(self, id).unwrap().decode(self);
ty::AssocItem {
kind,
def_id: self.local_def_id(id),
trait_item_def_id: self.get_trait_item_def_id(id),
container,
}
ty::AssocItem { kind, def_id: self.local_def_id(id), container }
}
fn get_ctor(self, node_id: DefIndex) -> Option<(CtorKind, DefId)> {

View file

@ -22,7 +22,7 @@ use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::mir::interpret;
use rustc_middle::query::Providers;
use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::AssocItemContainer;
use rustc_middle::ty::AssocContainer;
use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::fast_reject::{self, TreatParams};
use rustc_middle::{bug, span_bug};
@ -1254,8 +1254,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
DefKind::AssocTy => {
let assoc_item = tcx.associated_item(def_id);
match assoc_item.container {
ty::AssocItemContainer::Impl => true,
ty::AssocItemContainer::Trait => assoc_item.defaultness(tcx).has_value(),
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(),
}
}
DefKind::TyParam => {
@ -1725,24 +1725,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let tcx = self.tcx;
let item = tcx.associated_item(def_id);
self.tables.defaultness.set_some(def_id.index, item.defaultness(tcx));
self.tables.assoc_container.set_some(def_id.index, item.container);
if matches!(item.container, AssocContainer::Trait | AssocContainer::TraitImpl(_)) {
self.tables.defaultness.set_some(def_id.index, item.defaultness(tcx));
}
match item.container {
AssocItemContainer::Trait => {
if item.is_type() {
self.encode_explicit_item_bounds(def_id);
self.encode_explicit_item_self_bounds(def_id);
if tcx.is_conditionally_const(def_id) {
record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id]
<- self.tcx.explicit_implied_const_bounds(def_id).skip_binder());
}
}
}
AssocItemContainer::Impl => {
if let Some(trait_item_def_id) = item.trait_item_def_id {
self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into());
}
record!(self.tables.assoc_container[def_id] <- item.container);
if let AssocContainer::Trait = item.container
&& item.is_type()
{
self.encode_explicit_item_bounds(def_id);
self.encode_explicit_item_self_bounds(def_id);
if tcx.is_conditionally_const(def_id) {
record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id]
<- self.tcx.explicit_implied_const_bounds(def_id).skip_binder());
}
}
if let ty::AssocKind::Type { data: ty::AssocTypeData::Rpitit(rpitit_info) } = item.kind {

View file

@ -447,7 +447,6 @@ define_tables! {
coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,
eval_static_initializer: Table<DefIndex, LazyValue<mir::interpret::ConstAllocation<'static>>>,
trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
trait_item_def_id: Table<DefIndex, RawDefId>,
expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
default_fields: Table<DefIndex, LazyValue<DefId>>,
params_in_repr: Table<DefIndex, LazyValue<DenseBitSet<u32>>>,
@ -459,7 +458,7 @@ define_tables! {
def_keys: Table<DefIndex, LazyValue<DefKey>>,
proc_macro_quoted_spans: Table<usize, LazyValue<Span>>,
variant_data: Table<DefIndex, LazyValue<VariantData>>,
assoc_container: Table<DefIndex, ty::AssocItemContainer>,
assoc_container: Table<DefIndex, LazyValue<ty::AssocContainer>>,
macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>,
proc_macro: Table<DefIndex, MacroKind>,
deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,

View file

@ -102,7 +102,7 @@ trivially_parameterized_over_tcx! {
rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault,
rustc_middle::mir::ConstQualifs,
rustc_middle::ty::AnonConstKind,
rustc_middle::ty::AssocItemContainer,
rustc_middle::ty::AssocContainer,
rustc_middle::ty::AsyncDestructor,
rustc_middle::ty::Asyncness,
rustc_middle::ty::DeducedParamAttrs,

View file

@ -221,13 +221,6 @@ fixed_size_enum! {
}
}
fixed_size_enum! {
ty::AssocItemContainer {
( Trait )
( Impl )
}
}
fixed_size_enum! {
MacroKind {
( Attr )

View file

@ -318,7 +318,7 @@ trivial! {
rustc_middle::traits::WellFormedLoc,
rustc_middle::ty::adjustment::CoerceUnsizedInfo,
rustc_middle::ty::AssocItem,
rustc_middle::ty::AssocItemContainer,
rustc_middle::ty::AssocContainer,
rustc_middle::ty::Asyncness,
rustc_middle::ty::AsyncDestructor,
rustc_middle::ty::BoundVariableKind,

View file

@ -1881,6 +1881,7 @@ rustc_queries! {
}
/// Returns whether the impl or associated function has the `default` keyword.
/// Note: This will ICE on inherent impl items. Consider using `AssocItem::defaultness`.
query defaultness(def_id: DefId) -> hir::Defaultness {
desc { |tcx| "looking up whether `{}` has `default`", tcx.def_path_str(def_id) }
separate_provide_extern

View file

@ -5,15 +5,17 @@ use rustc_hir::def::{DefKind, Namespace};
use rustc_hir::def_id::DefId;
use rustc_hir::find_attr;
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_span::{Ident, Symbol};
use rustc_span::{ErrorGuaranteed, Ident, Symbol};
use super::{TyCtxt, Visibility};
use crate::ty;
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)]
pub enum AssocItemContainer {
pub enum AssocContainer {
Trait,
Impl,
InherentImpl,
/// The `DefId` points to the trait item being implemented.
TraitImpl(Result<DefId, ErrorGuaranteed>),
}
/// Information about an associated item
@ -21,11 +23,7 @@ pub enum AssocItemContainer {
pub struct AssocItem {
pub def_id: DefId,
pub kind: AssocKind,
pub container: AssocItemContainer,
/// If this is an item in an impl of a trait then this is the `DefId` of
/// the associated item on the trait that this implements.
pub trait_item_def_id: Option<DefId>,
pub container: AssocContainer,
}
impl AssocItem {
@ -55,7 +53,34 @@ impl AssocItem {
///
/// [`type_of`]: crate::ty::TyCtxt::type_of
pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness {
tcx.defaultness(self.def_id)
match self.container {
AssocContainer::InherentImpl => hir::Defaultness::Final,
AssocContainer::Trait | AssocContainer::TraitImpl(_) => tcx.defaultness(self.def_id),
}
}
pub fn expect_trait_impl(&self) -> Result<DefId, ErrorGuaranteed> {
let AssocContainer::TraitImpl(trait_item_id) = self.container else {
bug!("expected item to be in a trait impl: {:?}", self.def_id);
};
trait_item_id
}
/// If this is a trait impl item, returns the `DefId` of the trait item this implements.
/// Otherwise, returns `DefId` for self. Returns an Err in case the trait item was not
/// resolved successfully.
pub fn trait_item_or_self(&self) -> Result<DefId, ErrorGuaranteed> {
match self.container {
AssocContainer::TraitImpl(id) => id,
AssocContainer::Trait | AssocContainer::InherentImpl => Ok(self.def_id),
}
}
pub fn trait_item_def_id(&self) -> Option<DefId> {
match self.container {
AssocContainer::TraitImpl(Ok(id)) => Some(id),
_ => None,
}
}
#[inline]
@ -71,16 +96,18 @@ impl AssocItem {
#[inline]
pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
match self.container {
AssocItemContainer::Impl => None,
AssocItemContainer::Trait => Some(tcx.parent(self.def_id)),
AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => None,
AssocContainer::Trait => Some(tcx.parent(self.def_id)),
}
}
#[inline]
pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
match self.container {
AssocItemContainer::Impl => Some(tcx.parent(self.def_id)),
AssocItemContainer::Trait => None,
AssocContainer::InherentImpl | AssocContainer::TraitImpl(_) => {
Some(tcx.parent(self.def_id))
}
AssocContainer::Trait => None,
}
}
@ -156,11 +183,11 @@ impl AssocItem {
return false;
}
let def_id = match (self.container, self.trait_item_def_id) {
(AssocItemContainer::Trait, _) => self.def_id,
(AssocItemContainer::Impl, Some(trait_item_did)) => trait_item_did,
// Inherent impl but this attr is only applied to trait assoc items.
(AssocItemContainer::Impl, None) => return true,
let def_id = match self.container {
AssocContainer::Trait => self.def_id,
AssocContainer::TraitImpl(Ok(trait_item_did)) => trait_item_did,
AssocContainer::TraitImpl(Err(_)) => return false,
AssocContainer::InherentImpl => return true,
};
find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_))
}

View file

@ -2276,7 +2276,16 @@ impl<'tcx> TyCtxt<'tcx> {
let is_impl_item = match self.hir_node_by_def_id(suitable_region_binding_scope) {
Node::Item(..) | Node::TraitItem(..) => false,
Node::ImplItem(..) => self.is_bound_region_in_impl_item(suitable_region_binding_scope),
Node::ImplItem(impl_item) => match impl_item.impl_kind {
// For now, we do not try to target impls of traits. This is
// because this message is going to suggest that the user
// change the fn signature, but they may not be free to do so,
// since the signature must match the trait.
//
// FIXME(#42706) -- in some cases, we could do better here.
hir::ImplItemImplKind::Trait { .. } => true,
_ => false,
},
_ => false,
};
@ -2330,21 +2339,6 @@ impl<'tcx> TyCtxt<'tcx> {
None
}
/// Checks if the bound region is in Impl Item.
pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
let container_id = self.parent(suitable_region_binding_scope.to_def_id());
if self.impl_trait_ref(container_id).is_some() {
// For now, we do not try to target impls of traits. This is
// because this message is going to suggest that the user
// change the fn signature, but they may not be free to do so,
// since the signature must match the trait.
//
// FIXME(#42706) -- in some cases, we could do better here.
return true;
}
false
}
/// Determines whether identifiers in the assembly have strict naming rules.
/// Currently, only NVPTX* targets need it.
pub fn has_strict_asm_symbol_naming(self) -> bool {

View file

@ -18,8 +18,8 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::normalize_erasing_regions::NormalizationError;
use crate::ty::print::{FmtPrinter, Print};
use crate::ty::{
self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, TypeVisitor,
self, AssocContainer, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
};
/// An `InstanceKind` along with the args that are needed to substitute the instance.
@ -611,26 +611,23 @@ impl<'tcx> Instance<'tcx> {
debug!(" => fn pointer created for virtual call");
resolved.def = InstanceKind::ReifyShim(def_id, reason);
}
// Reify `Trait::method` implementations if KCFI is enabled
// FIXME(maurer) only reify it if it is a vtable-safe function
_ if tcx.sess.is_sanitizer_kcfi_enabled()
&& tcx
.opt_associated_item(def_id)
.and_then(|assoc| assoc.trait_item_def_id)
.is_some() =>
{
// If this function could also go in a vtable, we need to `ReifyShim` it with
// KCFI because it can only attach one type per function.
resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason)
}
// Reify `::call`-like method implementations if KCFI is enabled
_ if tcx.sess.is_sanitizer_kcfi_enabled()
&& tcx.is_closure_like(resolved.def_id()) =>
{
// Reroute through a reify via the *unresolved* instance. The resolved one can't
// be directly reified because it's closure-like. The reify can handle the
// unresolved instance.
resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }
_ if tcx.sess.is_sanitizer_kcfi_enabled() => {
// Reify `::call`-like method implementations
if tcx.is_closure_like(resolved.def_id()) {
// Reroute through a reify via the *unresolved* instance. The resolved one can't
// be directly reified because it's closure-like. The reify can handle the
// unresolved instance.
resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }
// Reify `Trait::method` implementations
// FIXME(maurer) only reify it if it is a vtable-safe function
} else if let Some(assoc) = tcx.opt_associated_item(def_id)
&& let AssocContainer::Trait | AssocContainer::TraitImpl(Ok(_)) =
assoc.container
{
// If this function could also go in a vtable, we need to `ReifyShim` it with
// KCFI because it can only attach one type per function.
resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason)
}
}
_ => {}
}
@ -683,7 +680,7 @@ impl<'tcx> Instance<'tcx> {
&& !matches!(
tcx.opt_associated_item(def),
Some(ty::AssocItem {
container: ty::AssocItemContainer::Trait,
container: ty::AssocContainer::Trait,
..
})
);

View file

@ -1934,6 +1934,11 @@ impl<'tcx> TyCtxt<'tcx> {
Some((parent, def_kind))
}
/// Returns the trait item that is implemented by the given item `DefId`.
pub fn trait_item_of(self, def_id: impl IntoQueryParam<DefId>) -> Option<DefId> {
self.opt_associated_item(def_id.into_query_param())?.trait_item_def_id()
}
/// If the given `DefId` is an associated item of a trait,
/// returns the `DefId` of the trait; otherwise, returns `None`.
pub fn trait_of_assoc(self, def_id: DefId) -> Option<DefId> {
@ -2149,17 +2154,12 @@ impl<'tcx> TyCtxt<'tcx> {
let Some(item) = self.opt_associated_item(def_id) else {
return false;
};
if item.container != ty::AssocItemContainer::Impl {
return false;
}
let Some(trait_item_def_id) = item.trait_item_def_id else {
let AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container else {
return false;
};
return !self
.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id)
.is_empty();
!self.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id).is_empty()
}
}

View file

@ -75,7 +75,7 @@ passes_const_stable_not_stable =
.label = attribute specified here
passes_custom_mir_incompatible_dialect_and_phase =
The {$dialect} dialect is not compatible with the {$phase} phase
the {$dialect} dialect is not compatible with the {$phase} phase
.dialect_span = this dialect...
.phase_span = ... is not compatible with this phase

View file

@ -373,31 +373,27 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
/// Automatically generated items marked with `rustc_trivial_field_reads`
/// will be ignored for the purposes of dead code analysis (see PR #85200
/// for discussion).
fn should_ignore_item(&mut self, def_id: DefId) -> bool {
if let Some(impl_of) = self.tcx.trait_impl_of_assoc(def_id) {
if !self.tcx.is_automatically_derived(impl_of) {
return false;
}
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
fn should_ignore_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) -> bool {
if let hir::ImplItemImplKind::Trait { .. } = impl_item.impl_kind
&& let impl_of = self.tcx.parent(impl_item.owner_id.to_def_id())
&& self.tcx.is_automatically_derived(impl_of)
&& let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().instantiate_identity()
&& self.tcx.has_attr(trait_ref.def_id, sym::rustc_trivial_field_reads)
{
if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind()
&& let Some(adt_def_id) = adt_def.did().as_local()
{
let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().instantiate_identity();
if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind()
&& let Some(adt_def_id) = adt_def.did().as_local()
{
self.ignored_derived_traits.entry(adt_def_id).or_default().insert(trait_of);
}
return true;
self.ignored_derived_traits.entry(adt_def_id).or_default().insert(trait_ref.def_id);
}
return true;
}
false
}
fn visit_node(&mut self, node: Node<'tcx>) {
if let Node::ImplItem(hir::ImplItem { owner_id, .. }) = node
&& self.should_ignore_item(owner_id.to_def_id())
if let Node::ImplItem(impl_item) = node
&& self.should_ignore_impl_item(impl_item)
{
return;
}
@ -439,7 +435,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
}
Node::ImplItem(impl_item) => {
let item = self.tcx.local_parent(impl_item.owner_id.def_id);
if self.tcx.impl_trait_ref(item).is_none() {
if let hir::ImplItemImplKind::Inherent { .. } = impl_item.impl_kind {
//// If it's a type whose items are live, then it's live, too.
//// This is done to handle the case where, for example, the static
//// method of a private type is used, but the type itself is never
@ -484,13 +480,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
fn check_impl_or_impl_item_live(&mut self, local_def_id: LocalDefId) -> bool {
let (impl_block_id, trait_def_id) = match self.tcx.def_kind(local_def_id) {
// assoc impl items of traits are live if the corresponding trait items are live
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => (
self.tcx.local_parent(local_def_id),
self.tcx
.associated_item(local_def_id)
.trait_item_def_id
.and_then(|def_id| def_id.as_local()),
),
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => {
let trait_item_id =
self.tcx.trait_item_of(local_def_id).and_then(|def_id| def_id.as_local());
(self.tcx.local_parent(local_def_id), trait_item_id)
}
// impl items are live if the corresponding traits are live
DefKind::Impl { of_trait: true } => (
local_def_id,

View file

@ -21,8 +21,8 @@ use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::middle::stability::{AllowUnstable, Deprecated, DeprecationEntry, EvalResult};
use rustc_middle::query::{LocalCrate, Providers};
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{AssocContainer, TyCtxt};
use rustc_session::lint;
use rustc_session::lint::builtin::{DEPRECATED, INEFFECTIVE_UNSTABLE_TRAIT_IMPL};
use rustc_span::{Span, Symbol, sym};
@ -486,8 +486,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
self.check_compatible_stability(ii.owner_id.def_id);
let impl_def_id = self.tcx.hir_get_parent_item(ii.hir_id());
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
if let hir::ImplItemImplKind::Inherent { .. } = ii.impl_kind {
self.check_missing_stability(ii.owner_id.def_id);
self.check_missing_const_stability(ii.owner_id.def_id);
}
@ -711,7 +710,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
for impl_item_ref in items {
let impl_item = self.tcx.associated_item(impl_item_ref.owner_id);
if let Some(def_id) = impl_item.trait_item_def_id {
if let AssocContainer::TraitImpl(Ok(def_id)) = impl_item.container {
// Pass `None` to skip deprecation warnings.
self.tcx.check_stability(
def_id,

View file

@ -1612,11 +1612,7 @@ crate_def! {
pub struct AssocItem {
pub def_id: AssocDef,
pub kind: AssocKind,
pub container: AssocItemContainer,
/// If this is an item in an impl of a trait then this is the `DefId` of
/// the associated item on the trait that this implements.
pub trait_item_def_id: Option<AssocDef>,
pub container: AssocContainer,
}
#[derive(Clone, PartialEq, Debug, Eq, Serialize)]
@ -1636,9 +1632,11 @@ pub enum AssocKind {
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub enum AssocItemContainer {
pub enum AssocContainer {
InherentImpl,
/// The `AssocDef` points to the trait item being implemented.
TraitImpl(AssocDef),
Trait,
Impl,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]

View file

@ -1076,14 +1076,21 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind {
}
}
impl<'tcx> Stable<'tcx> for ty::AssocItemContainer {
type T = crate::ty::AssocItemContainer;
impl<'tcx> Stable<'tcx> for ty::AssocContainer {
type T = crate::ty::AssocContainer;
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
use crate::ty::AssocItemContainer;
fn stable(
&self,
tables: &mut Tables<'_, BridgeTys>,
_: &CompilerCtxt<'_, BridgeTys>,
) -> Self::T {
use crate::ty::AssocContainer;
match self {
ty::AssocItemContainer::Trait => AssocItemContainer::Trait,
ty::AssocItemContainer::Impl => AssocItemContainer::Impl,
ty::AssocContainer::Trait => AssocContainer::Trait,
ty::AssocContainer::InherentImpl => AssocContainer::InherentImpl,
ty::AssocContainer::TraitImpl(trait_item_id) => {
AssocContainer::TraitImpl(tables.assoc_def(trait_item_id.unwrap()))
}
}
}
}
@ -1100,7 +1107,6 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem {
def_id: tables.assoc_def(self.def_id),
kind: self.kind.stable(tables, cx),
container: self.container.stable(tables, cx),
trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)),
}
}
}

View file

@ -231,6 +231,9 @@ resolve_item_was_cfg_out = the item is gated here
resolve_label_with_similar_name_reachable =
a label with a similar name is reachable
resolve_legacy_derive_helpers = derive helper attribute is used before it is introduced
.label = the attribute is introduced here
resolve_lending_iterator_report_error =
associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
.note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type
@ -260,6 +263,9 @@ resolve_macro_defined_later =
resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments =
macro-expanded `extern crate` items cannot shadow names passed with `--extern`
resolve_macro_expanded_macro_exports_accessed_by_absolute_paths = macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
.note = the macro is defined here
resolve_macro_expected_found =
expected {$expected}, found {$found} `{$macro_path}`
.label = not {$article} {$expected}
@ -268,6 +274,10 @@ resolve_macro_extern_deprecated =
`#[macro_escape]` is a deprecated synonym for `#[macro_use]`
.help = try an outer attribute: `#[macro_use]`
resolve_macro_use_deprecated =
applying the `#[macro_use]` attribute to an `extern crate` item is deprecated
.help = remove it and import macros at use sites with a `use` item instead
resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
resolve_macro_use_name_already_in_use =
@ -339,6 +349,9 @@ resolve_param_in_ty_of_const_param =
resolve_pattern_doesnt_bind_name = pattern doesn't bind `{$name}`
resolve_proc_macro_derive_resolution_fallback = cannot find {$ns_descr} `{$ident}` in this scope
.label = names from parent modules are not accessible without an explicit import
resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
.help = you can define integration tests in a directory named `tests`
@ -348,6 +361,9 @@ resolve_reexport_of_crate_public =
resolve_reexport_of_private =
re-export of private `{$ident}`
resolve_reexport_private_dependency =
{$kind} `{$name}` from private dependency '{$krate}' is re-exported
resolve_relative_2018 =
relative paths are not supported in visibilities in 2018 edition or later
.suggestion = try
@ -465,6 +481,14 @@ resolve_unreachable_label_suggestion_use_similarly_named =
resolve_unreachable_label_with_similar_name_exists =
a label with a similar name exists but is unreachable
resolve_unused_extern_crate = unused extern crate
.label = unused
.suggestion = remove the unused `extern crate`
resolve_unused_label = unused label
resolve_unused_macro_use = unused `#[macro_use]` import
resolve_variable_bound_with_different_mode =
variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
.label = bound in different ways

View file

@ -169,7 +169,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> {
UNUSED_EXTERN_CRATES,
extern_crate.id,
span,
BuiltinLintDiag::UnusedExternCrate {
crate::errors::UnusedExternCrate {
span: extern_crate.span,
removal_span: extern_crate.span_with_attributes,
},
@ -406,7 +406,7 @@ impl Resolver<'_, '_> {
MACRO_USE_EXTERN_CRATE,
import.root_id,
import.span,
BuiltinLintDiag::MacroUseDeprecated,
crate::errors::MacroUseDeprecated,
);
}
}
@ -427,7 +427,7 @@ impl Resolver<'_, '_> {
UNUSED_IMPORTS,
import.root_id,
import.span,
BuiltinLintDiag::UnusedMacroUse,
crate::errors::UnusedMacroUse,
);
}
_ => {}

View file

@ -138,7 +138,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
CRATE_NODE_ID,
span_use,
BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
errors::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def },
);
}

View file

@ -3,7 +3,7 @@ use rustc_errors::{
Applicability, Diag, ElidedLifetimeInPathSubdiag, EmissionGuarantee, IntoDiagArg, MultiSpan,
Subdiagnostic,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Ident, Span, Symbol};
use crate::late::PatternSource;
@ -566,6 +566,22 @@ pub(crate) struct ProcMacroSameCrate {
pub(crate) is_test: bool,
}
#[derive(LintDiagnostic)]
#[diag(resolve_proc_macro_derive_resolution_fallback)]
pub(crate) struct ProcMacroDeriveResolutionFallback {
#[label]
pub span: Span,
pub ns_descr: &'static str,
pub ident: Ident,
}
#[derive(LintDiagnostic)]
#[diag(resolve_macro_expanded_macro_exports_accessed_by_absolute_paths)]
pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths {
#[note]
pub definition: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_imported_crate)]
pub(crate) struct CrateImported {
@ -1276,3 +1292,40 @@ pub(crate) struct TraitImplMismatch {
#[label(resolve_trait_impl_mismatch_label_item)]
pub(crate) trait_item_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(resolve_legacy_derive_helpers)]
pub(crate) struct LegacyDeriveHelpers {
#[label]
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(resolve_unused_extern_crate)]
pub(crate) struct UnusedExternCrate {
#[label]
pub span: Span,
#[suggestion(code = "", applicability = "machine-applicable", style = "verbose")]
pub removal_span: Span,
}
#[derive(LintDiagnostic)]
#[diag(resolve_reexport_private_dependency)]
pub(crate) struct ReexportPrivateDependency {
pub name: Symbol,
pub kind: &'static str,
pub krate: Symbol,
}
#[derive(LintDiagnostic)]
#[diag(resolve_unused_label)]
pub(crate) struct UnusedLabel;
#[derive(LintDiagnostic)]
#[diag(resolve_unused_macro_use)]
pub(crate) struct UnusedMacroUse;
#[derive(LintDiagnostic)]
#[diag(resolve_macro_use_deprecated)]
#[help]
pub(crate) struct MacroUseDeprecated;

View file

@ -4,7 +4,6 @@ use rustc_ast::{self as ast, NodeId};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS};
use rustc_middle::bug;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
use rustc_session::parse::feature_err;
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
@ -520,7 +519,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
lint_id,
orig_ident.span,
BuiltinLintDiag::ProcMacroDeriveResolutionFallback {
errors::ProcMacroDeriveResolutionFallback {
span: orig_ident.span,
ns_descr: ns.descr(),
ident,

View file

@ -720,9 +720,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
EXPORTED_PRIVATE_DEPENDENCIES,
binding_id,
binding.span,
BuiltinLintDiag::ReexportPrivateDependency {
kind: binding.res().descr().to_string(),
name: key.ident.name.to_string(),
crate::errors::ReexportPrivateDependency {
name: key.ident.name,
kind: binding.res().descr(),
krate: self.tcx.crate_name(reexported_def_id.krate),
},
);

View file

@ -29,7 +29,7 @@ use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::ty::{DelegationFnSig, Visibility};
use rustc_middle::{bug, span_bug};
use rustc_session::config::{CrateType, ResolveDocLinks};
use rustc_session::lint::{self, BuiltinLintDiag};
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::source_map::{Spanned, respan};
use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym};
@ -5225,7 +5225,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
lint::builtin::UNUSED_LABELS,
*id,
*span,
BuiltinLintDiag::UnusedLabel,
errors::UnusedLabel,
);
}
}

View file

@ -979,7 +979,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
LEGACY_DERIVE_HELPERS,
node_id,
ident.span,
BuiltinLintDiag::LegacyDeriveHelpers(binding.span),
errors::LegacyDeriveHelpers { span: binding.span },
);
}
}

View file

@ -469,8 +469,7 @@ fn implemented_method<'tcx>(
let ancestor = if let Some(impl_id) = tcx.impl_of_assoc(instance.def_id()) {
// Implementation in an `impl` block
trait_ref = tcx.impl_trait_ref(impl_id)?;
let impl_method = tcx.associated_item(instance.def_id());
method_id = impl_method.trait_item_def_id?;
method_id = tcx.trait_item_of(instance.def_id())?;
trait_method = tcx.associated_item(method_id);
trait_id = trait_ref.skip_binder().def_id;
impl_id

View file

@ -46,6 +46,8 @@ use crate::symbol::{Symbol, kw, sym};
use crate::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, with_session_globals};
/// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
///
/// See <https://rustc-dev-guide.rust-lang.org/macro-expansion.html> for more explanation.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct SyntaxContext(u32);
@ -61,7 +63,10 @@ pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency);
#[derive(Clone, Copy, Debug)]
struct SyntaxContextData {
/// The last macro expansion in the chain.
/// (Here we say the most deeply nested macro expansion is the "outermost" expansion.)
outer_expn: ExpnId,
/// Transparency of the last macro expansion
outer_transparency: Transparency,
parent: SyntaxContext,
/// This context, but with all transparent and semi-opaque expansions filtered away.
@ -450,11 +455,13 @@ impl HygieneData {
self.syntax_context_data[ctxt.0 as usize].opaque_and_semiopaque
}
/// See [`SyntaxContextData::outer_expn`]
#[inline]
fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
self.syntax_context_data[ctxt.0 as usize].outer_expn
}
/// The last macro expansion and its Transparency
#[inline]
fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) {
let data = &self.syntax_context_data[ctxt.0 as usize];
@ -900,6 +907,7 @@ impl SyntaxContext {
HygieneData::with(|data| data.normalize_to_macro_rules(self))
}
/// See [`SyntaxContextData::outer_expn`]
#[inline]
pub fn outer_expn(self) -> ExpnId {
HygieneData::with(|data| data.outer_expn(self))
@ -912,6 +920,7 @@ impl SyntaxContext {
HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone())
}
/// See [`HygieneData::outer_mark`]
#[inline]
fn outer_mark(self) -> (ExpnId, Transparency) {
HygieneData::with(|data| data.outer_mark(self))
@ -982,19 +991,20 @@ impl Span {
#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
pub struct ExpnData {
// --- The part unique to each expansion.
/// The kind of this expansion - macro or compiler desugaring.
pub kind: ExpnKind,
/// The expansion that produced this expansion.
/// The expansion that contains the definition of the macro for this expansion.
pub parent: ExpnId,
/// The location of the actual macro invocation or syntax sugar , e.g.
/// `let x = foo!();` or `if let Some(y) = x {}`
/// The span of the macro call which produced this expansion.
///
/// This may recursively refer to other macro invocations, e.g., if
/// `foo!()` invoked `bar!()` internally, and there was an
/// expression inside `bar!`; the call_site of the expression in
/// the expansion would point to the `bar!` invocation; that
/// call_site span would have its own ExpnData, with the call_site
/// pointing to the `foo!` invocation.
/// This span will typically have a different `ExpnData` and `call_site`.
/// This recursively traces back through any macro calls which expanded into further
/// macro calls, until the "source call-site" is reached at the root SyntaxContext.
/// For example, if `food!()` expands to `fruit!()` which then expands to `grape`,
/// then the call-site of `grape` is `fruit!()` and the call-site of `fruit!()`
/// is `food!()`.
///
/// For a desugaring expansion, this is the span of the expression or node that was
/// desugared.
pub call_site: Span,
/// Used to force two `ExpnData`s to have different `Fingerprint`s.
/// Due to macro expansion, it's possible to end up with two `ExpnId`s

View file

@ -710,8 +710,8 @@ impl Span {
if !ctxt.is_root() { ctxt.outer_expn_data().call_site.source_callsite() } else { self }
}
/// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
/// if any.
/// Returns the call-site span of the last macro expansion which produced this `Span`.
/// (see [`ExpnData::call_site`]). Returns `None` if this is not an expansion.
pub fn parent_callsite(self) -> Option<Span> {
let ctxt = self.ctxt();
(!ctxt.is_root()).then(|| ctxt.outer_expn_data().call_site)

View file

@ -857,11 +857,11 @@ fn foo(&self) -> Self::T { String::new() }
&& self.infcx.can_eq(param_env, assoc_ty, found)
{
let msg = match assoc_item.container {
ty::AssocItemContainer::Trait => {
ty::AssocContainer::Trait => {
"associated type defaults can't be assumed inside the \
trait defining them"
}
ty::AssocItemContainer::Impl => {
ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
"associated type is `default` and may be overridden"
}
};

View file

@ -571,13 +571,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// but right now it's not really very smart when it comes to implicit `Sized`
// predicates and bounds on the trait itself.
let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx)
else {
return;
};
let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else {
let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(impl_item_def_id.to_def_id()) else {
return;
};
let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
let trait_args = trait_ref
.instantiate_identity()
// Replace the explicit self type with `Self` for better suggestion rendering

View file

@ -5,7 +5,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::{LangItem, lang_items};
use rustc_middle::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv};
use rustc_middle::ty::{AssocContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv};
use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, sym};
use tracing::debug;
@ -76,8 +76,9 @@ pub fn call_kind<'tcx>(
let parent = tcx.opt_associated_item(method_did).and_then(|assoc| {
let container_id = assoc.container_id(tcx);
match assoc.container {
AssocItemContainer::Impl => tcx.trait_id_of_impl(container_id),
AssocItemContainer::Trait => Some(container_id),
AssocContainer::InherentImpl => None,
AssocContainer::TraitImpl(_) => tcx.trait_id_of_impl(container_id),
AssocContainer::Trait => Some(container_id),
}
});

View file

@ -421,7 +421,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
})
| hir::Node::ImplItem(hir::ImplItem {
generics,
trait_item_def_id: None,
impl_kind: hir::ImplItemImplKind::Inherent { .. },
kind: hir::ImplItemKind::Fn(..),
..
}) if finder.can_suggest_bound(generics) => {

View file

@ -387,7 +387,7 @@ pub(crate) fn assoc_def(
if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_def_id) {
// Ensure that the impl is constrained, otherwise projection may give us
// bad unconstrained infer vars.
if assoc_item.item.container == ty::AssocItemContainer::Impl
if let ty::AssocContainer::TraitImpl(_) = assoc_item.item.container
&& let Some(impl_def_id) = assoc_item.item.container_id(tcx).as_local()
{
tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?;

View file

@ -2,7 +2,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, ItemKind};
use rustc_hir::{self as hir, ImplItemImplKind, ItemKind};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
use rustc_middle::{bug, span_bug};
@ -63,7 +63,7 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems {
fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId> {
tcx.associated_items(impl_id)
.in_definition_order()
.filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id)))
.filter_map(|item| item.trait_item_def_id().map(|trait_item| (trait_item, item.def_id)))
.collect()
}
@ -97,12 +97,7 @@ fn associated_item_from_trait_item(
}
};
ty::AssocItem {
kind,
def_id: owner_id.to_def_id(),
trait_item_def_id: Some(owner_id.to_def_id()),
container: ty::AssocItemContainer::Trait,
}
ty::AssocItem { kind, def_id: owner_id.to_def_id(), container: ty::AssocContainer::Trait }
}
fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> ty::AssocItem {
@ -118,12 +113,13 @@ fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>
}
};
ty::AssocItem {
kind,
def_id: owner_id.to_def_id(),
trait_item_def_id: impl_item.trait_item_def_id,
container: ty::AssocItemContainer::Impl,
}
let container = match impl_item.impl_kind {
ImplItemImplKind::Inherent { .. } => ty::AssocContainer::InherentImpl,
ImplItemImplKind::Trait { trait_item_def_id, .. } => {
ty::AssocContainer::TraitImpl(trait_item_def_id)
}
};
ty::AssocItem { kind, def_id: owner_id.to_def_id(), container }
}
struct RPITVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
@ -190,7 +186,10 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
}
let did = item.owner_id.def_id.to_def_id();
let item = tcx.hir_impl_item(*item);
let Some(trait_item_def_id) = item.trait_item_def_id else {
let ImplItemImplKind::Trait {
trait_item_def_id: Ok(trait_item_def_id), ..
} = item.impl_kind
else {
return Some((did, vec![]));
};
let iter = in_trait_def[&trait_item_def_id].iter().map(|&id| {
@ -256,8 +255,7 @@ fn associated_type_for_impl_trait_in_trait(
}),
},
def_id,
trait_item_def_id: None,
container: ty::AssocItemContainer::Trait,
container: ty::AssocContainer::Trait,
});
// Copy visility of the containing function.
@ -322,8 +320,7 @@ fn associated_type_for_impl_trait_in_impl(
}),
},
def_id,
trait_item_def_id: Some(trait_assoc_def_id),
container: ty::AssocItemContainer::Impl,
container: ty::AssocContainer::TraitImpl(Ok(trait_assoc_def_id)),
});
// Copy visility of the containing function.

View file

@ -107,7 +107,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
// the assumed wf types of the trait's RPITIT GAT.
ty::ImplTraitInTraitData::Impl { .. } => {
let impl_def_id = tcx.local_parent(def_id);
let rpitit_def_id = tcx.associated_item(def_id).trait_item_def_id.unwrap();
let rpitit_def_id = tcx.trait_item_of(def_id).unwrap();
let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto(
tcx,
impl_def_id.to_def_id(),

View file

@ -245,7 +245,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
for &assoc in self.tcx.associated_items(parent).in_definition_order() {
trace!(?assoc);
if assoc.trait_item_def_id != Some(alias_ty.def_id) {
if assoc.expect_trait_impl() != Ok(alias_ty.def_id) {
continue;
}

View file

@ -88,7 +88,10 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
}),
..
})
| hir::Node::ImplItem(hir::ImplItem { defaultness, .. })
| hir::Node::ImplItem(hir::ImplItem {
impl_kind: hir::ImplItemImplKind::Trait { defaultness, .. },
..
})
| hir::Node::TraitItem(hir::TraitItem { defaultness, .. }) => *defaultness,
node => {
bug!("`defaultness` called on {:?}", node);
@ -165,7 +168,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
if tcx.def_kind(def_id) == DefKind::AssocFn
&& let assoc_item = tcx.associated_item(def_id)
&& assoc_item.container == ty::AssocItemContainer::Trait
&& assoc_item.container == ty::AssocContainer::Trait
&& assoc_item.defaultness(tcx).has_value()
{
let sig = tcx.fn_sig(def_id).instantiate_identity();

View file

@ -1433,7 +1433,6 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// # Examples
///
/// ```
/// #![feature(btree_extract_if)]
/// use std::collections::BTreeMap;
///
/// // Splitting a map into even and odd keys, reusing the original map:
@ -1450,7 +1449,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(low.keys().copied().collect::<Vec<_>>(), [0, 1, 2, 3]);
/// assert_eq!(high.keys().copied().collect::<Vec<_>>(), [4, 5, 6, 7]);
/// ```
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
pub fn extract_if<F, R>(&mut self, range: R, pred: F) -> ExtractIf<'_, K, V, R, F, A>
where
K: Ord,
@ -1937,7 +1936,7 @@ impl<K, V> Default for Values<'_, K, V> {
}
/// An iterator produced by calling `extract_if` on BTreeMap.
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ExtractIf<
'a,
@ -1970,7 +1969,7 @@ pub(super) struct ExtractIfInner<'a, K, V, R> {
range: R,
}
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<K, V, R, F, A> fmt::Debug for ExtractIf<'_, K, V, R, F, A>
where
K: fmt::Debug,
@ -1982,7 +1981,7 @@ where
}
}
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<K, V, R, F, A: Allocator + Clone> Iterator for ExtractIf<'_, K, V, R, F, A>
where
K: PartialOrd,
@ -2056,7 +2055,7 @@ impl<'a, K, V, R> ExtractIfInner<'a, K, V, R> {
}
}
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<K, V, R, F> FusedIterator for ExtractIf<'_, K, V, R, F>
where
K: PartialOrd,

View file

@ -1202,7 +1202,6 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// # Examples
///
/// ```
/// #![feature(btree_extract_if)]
/// use std::collections::BTreeSet;
///
/// // Splitting a set into even and odd values, reusing the original set:
@ -1219,7 +1218,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// assert_eq!(low.into_iter().collect::<Vec<_>>(), [0, 1, 2, 3]);
/// assert_eq!(high.into_iter().collect::<Vec<_>>(), [4, 5, 6, 7]);
/// ```
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
pub fn extract_if<F, R>(&mut self, range: R, pred: F) -> ExtractIf<'_, T, R, F, A>
where
T: Ord,
@ -1554,7 +1553,7 @@ impl<'a, T, A: Allocator + Clone> IntoIterator for &'a BTreeSet<T, A> {
}
/// An iterator produced by calling `extract_if` on BTreeSet.
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ExtractIf<
'a,
@ -1569,7 +1568,7 @@ pub struct ExtractIf<
alloc: A,
}
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<T, R, F, A> fmt::Debug for ExtractIf<'_, T, R, F, A>
where
T: fmt::Debug,
@ -1582,7 +1581,7 @@ where
}
}
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<T, R, F, A: Allocator + Clone> Iterator for ExtractIf<'_, T, R, F, A>
where
T: PartialOrd,
@ -1602,7 +1601,7 @@ where
}
}
#[unstable(feature = "btree_extract_if", issue = "70530")]
#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")]
impl<T, R, F, A: Allocator + Clone> FusedIterator for ExtractIf<'_, T, R, F, A>
where
T: PartialOrd,

View file

@ -1,6 +1,5 @@
// Disabling in Miri as these would take too long.
#![cfg(not(miri))]
#![feature(btree_extract_if)]
#![feature(iter_next_chunk)]
#![feature(repr_simd)]
#![feature(slice_partition_dedup)]

View file

@ -2,7 +2,6 @@
#![feature(alloc_layout_extra)]
#![feature(iter_array_chunks)]
#![feature(assert_matches)]
#![feature(btree_extract_if)]
#![feature(wtf8_internals)]
#![feature(char_max_len)]
#![feature(cow_is_borrowed)]

View file

@ -202,18 +202,23 @@ mod sealed {
impl<T> Sealed for *const T {}
}
/// Trait which permits the allowed types to be used with [`VaListImpl::arg`].
/// Types that are valid to read using [`VaListImpl::arg`].
///
/// # Safety
///
/// This trait must only be implemented for types that C passes as varargs without implicit promotion.
/// The standard library implements this trait for primitive types that are
/// expected to have a variable argument application-binary interface (ABI) on all
/// platforms.
///
/// In C varargs, integers smaller than [`c_int`] and floats smaller than [`c_double`]
/// are implicitly promoted to [`c_int`] and [`c_double`] respectively. Implementing this trait for
/// types that are subject to this promotion rule is invalid.
/// When C passes variable arguments, integers smaller than [`c_int`] and floats smaller
/// than [`c_double`] are implicitly promoted to [`c_int`] and [`c_double`] respectively.
/// Implementing this trait for types that are subject to this promotion rule is invalid.
///
/// [`c_int`]: core::ffi::c_int
/// [`c_double`]: core::ffi::c_double
// We may unseal this trait in the future, but currently our `va_arg` implementations don't support
// types with an alignment larger than 8, or with a non-scalar layout. Inline assembly can be used
// to accept unsupported types in the meantime.
pub unsafe trait VaArgSafe: sealed::Sealed {}
// i8 and i16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
@ -233,7 +238,19 @@ unsafe impl<T> VaArgSafe for *mut T {}
unsafe impl<T> VaArgSafe for *const T {}
impl<'f> VaListImpl<'f> {
/// Advance to the next arg.
/// Advance to and read the next variable argument.
///
/// # Safety
///
/// This function is only sound to call when the next variable argument:
///
/// - has a type that is ABI-compatible with the type `T`
/// - has a value that is a properly initialized value of type `T`
///
/// Calling this function with an incompatible type, an invalid value, or when there
/// are no more variable arguments, is unsound.
///
/// [valid]: https://doc.rust-lang.org/nightly/nomicon/what-unsafe-does.html
#[inline]
pub unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
// SAFETY: the caller must uphold the safety contract for `va_arg`.

View file

@ -1257,6 +1257,108 @@ mod ref_keyword {}
/// [`async`]: ../std/keyword.async.html
mod return_keyword {}
#[doc(keyword = "become")]
//
/// Perform a tail-call of a function.
///
/// <div class="warning">
///
/// `feature(explicit_tail_calls)` is currently incomplete and may not work properly.
/// </div>
///
/// When tail calling a function, instead of its stack frame being added to the
/// stack, the stack frame of the caller is directly replaced with the callee's.
/// This means that as long as a loop in a call graph only uses tail calls, the
/// stack growth will be bounded.
///
/// This is useful for writing functional-style code (since it prevents recursion
/// from exhausting resources) or for code optimization (since a tail call
/// *might* be cheaper than a normal call, tail calls can be used in a similar
/// manner to computed goto).
///
/// Example of using `become` to implement functional-style `fold`:
/// ```
/// #![feature(explicit_tail_calls)]
/// #![expect(incomplete_features)]
///
/// fn fold<T: Copy, S>(slice: &[T], init: S, f: impl Fn(S, T) -> S) -> S {
/// match slice {
/// // without `become`, on big inputs this could easily overflow the
/// // stack. using a tail call guarantees that the stack will not grow unboundedly
/// [first, rest @ ..] => become fold(rest, f(init, *first), f),
/// [] => init,
/// }
/// }
/// ```
///
/// Compilers can already perform "tail call optimization" -- they can replace normal
/// calls with tail calls, although there are no guarantees that this will be done.
/// However, to perform TCO, the call needs to be the last thing that happens
/// in the functions and be returned from it. This requirement is often broken
/// by drop code for locals, which is run after computing the return expression:
///
/// ```
/// fn example() {
/// let string = "meow".to_owned();
/// println!("{string}");
/// return help(); // this is *not* the last thing that happens in `example`...
/// }
///
/// // ... because it is desugared to this:
/// fn example_desugared() {
/// let string = "meow".to_owned();
/// println!("{string}");
/// let tmp = help();
/// drop(string);
/// return tmp;
/// }
///
/// fn help() {}
/// ```
///
/// For this reason, `become` also changes the drop order, such that locals are
/// dropped *before* evaluating the call.
///
/// In order to guarantee that the compiler can perform a tail call, `become`
/// currently has these requirements:
/// 1. callee and caller must have the same ABI, arguments, and return type
/// 2. callee and caller must not have varargs
/// 3. caller must not be marked with `#[track_caller]`
/// - callee is allowed to be marked with `#[track_caller]` as otherwise
/// adding `#[track_caller]` would be a breaking change. if callee is
/// marked with `#[track_caller]` a tail call is not guaranteed.
/// 4. callee and caller cannot be a closure
/// (unless it's coerced to a function pointer)
///
/// It is possible to tail-call a function pointer:
/// ```
/// #![feature(explicit_tail_calls)]
/// #![expect(incomplete_features)]
///
/// #[derive(Copy, Clone)]
/// enum Inst { Inc, Dec }
///
/// fn dispatch(stream: &[Inst], state: u32) -> u32 {
/// const TABLE: &[fn(&[Inst], u32) -> u32] = &[increment, decrement];
/// match stream {
/// [inst, rest @ ..] => become TABLE[*inst as usize](rest, state),
/// [] => state,
/// }
/// }
///
/// fn increment(stream: &[Inst], state: u32) -> u32 {
/// become dispatch(stream, state + 1)
/// }
///
/// fn decrement(stream: &[Inst], state: u32) -> u32 {
/// become dispatch(stream, state - 1)
/// }
///
/// let program = &[Inst::Inc, Inst::Inc, Inst::Dec, Inst::Inc];
/// assert_eq!(dispatch(program, 0), 2);
/// ```
mod become_keyword {}
#[doc(keyword = "self")]
//
/// The receiver of a method, or the current module.

View file

@ -284,7 +284,6 @@
#![feature(core_float_math)]
#![feature(decl_macro)]
#![feature(deprecated_suggestion)]
#![feature(derive_const)]
#![feature(doc_cfg)]
#![feature(doc_cfg_hide)]
#![feature(doc_masked)]
@ -332,11 +331,7 @@
#![feature(cfg_select)]
#![feature(char_internals)]
#![feature(clone_to_uninit)]
#![feature(const_cmp)]
#![feature(const_convert)]
#![feature(const_ops)]
#![feature(const_option_ops)]
#![feature(const_try)]
#![feature(core_intrinsics)]
#![feature(core_io_borrowed_buf)]
#![feature(drop_guard)]

View file

@ -198,11 +198,10 @@ impl Condvar {
/// the system time. This function is susceptible to spurious wakeups.
/// Condition variables normally have a boolean predicate associated with
/// them, and the predicate must always be checked each time this function
/// returns to protect against spurious wakeups. Additionally, it is
/// typically desirable for the timeout to not exceed some duration in
/// spite of spurious wakes, thus the sleep-duration is decremented by the
/// amount slept. Alternatively, use the `wait_timeout_while` method
/// to wait with a timeout while a predicate is true.
/// returns to protect against spurious wakeups. Furthermore, since the timeout
/// is given relative to the moment this function is called, it needs to be adjusted
/// when this function is called in a loop. The [`wait_timeout_while`] method
/// lets you wait with a timeout while a predicate is true, taking care of all these concerns.
///
/// The returned [`WaitTimeoutResult`] value indicates if the timeout is
/// known to have elapsed.

View file

@ -269,11 +269,10 @@ impl Condvar {
/// the system time. This function is susceptible to spurious wakeups.
/// Condition variables normally have a boolean predicate associated with
/// them, and the predicate must always be checked each time this function
/// returns to protect against spurious wakeups. Additionally, it is
/// typically desirable for the timeout to not exceed some duration in
/// spite of spurious wakes, thus the sleep-duration is decremented by the
/// amount slept. Alternatively, use the `wait_timeout_while` method
/// to wait with a timeout while a predicate is true.
/// returns to protect against spurious wakeups. Furthermore, since the timeout
/// is given relative to the moment this function is called, it needs to be adjusted
/// when this function is called in a loop. The [`wait_timeout_while`] method
/// lets you wait with a timeout while a predicate is true, taking care of all these concerns.
///
/// The returned [`WaitTimeoutResult`] value indicates if the timeout is
/// known to have elapsed.

View file

@ -25,15 +25,8 @@ impl Timespec {
Timespec { t: timespec { tv_sec, tv_nsec } }
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
// FIXME: const PartialOrd
let mut cmp = self.t.tv_sec - other.t.tv_sec;
if cmp == 0 {
cmp = self.t.tv_nsec as i64 - other.t.tv_nsec as i64;
}
if cmp >= 0 {
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
if self >= other {
Ok(if self.t.tv_nsec >= other.t.tv_nsec {
Duration::new(
(self.t.tv_sec - other.t.tv_sec) as u64,
@ -53,22 +46,20 @@ impl Timespec {
}
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = self.t.tv_sec.checked_add_unsigned(other.as_secs())?;
// Nano calculations can't overflow because nanos are <1B which fit
// in a u32.
let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
if nsec >= NSEC_PER_SEC as u32 {
nsec -= NSEC_PER_SEC as u32;
let mut nsec = other.subsec_nanos() + u32::try_from(self.t.tv_nsec).unwrap();
if nsec >= NSEC_PER_SEC.try_into().unwrap() {
nsec -= u32::try_from(NSEC_PER_SEC).unwrap();
secs = secs.checked_add(1)?;
}
Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } })
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = self.t.tv_sec.checked_sub_unsigned(other.as_secs())?;
// Similar to above, nanos can't overflow.
@ -222,18 +213,15 @@ impl SystemTime {
SystemTime(time)
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
self.0.sub_timespec(&other.0)
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_add_duration(other)?))
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_sub_duration(other)?))
}
}

View file

@ -32,22 +32,15 @@ impl SystemTime {
SystemTime(usercalls::insecure_time())
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
// FIXME: ok_or_else with const closures
match self.0.checked_sub(other.0) {
Some(duration) => Ok(duration),
None => Err(other.0 - self.0),
}
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_add(*other)?))
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_sub(*other)?))
}
}

View file

@ -39,8 +39,7 @@ impl SystemTime {
Self(t)
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
if self.0 >= other.0 {
Ok(Duration::from_secs((self.0 as u64).wrapping_sub(other.0 as u64)))
} else {
@ -48,13 +47,11 @@ impl SystemTime {
}
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_add_unsigned(other.as_secs())?))
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_sub_unsigned(other.as_secs())?))
}
}

View file

@ -80,32 +80,19 @@ impl SystemTime {
.unwrap_or_else(|| panic!("time not implemented on this platform"))
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
// FIXME: ok_or_else with const closures
match self.0.checked_sub(other.0) {
Some(duration) => Ok(duration),
None => Err(other.0 - self.0),
}
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
let temp = self.0.checked_add(*other)?;
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
let temp = Self(self.0.checked_add(*other)?);
// Check if can be represented in UEFI
// FIXME: const PartialOrd
let mut cmp = temp.as_secs() - MAX_UEFI_TIME.0.as_secs();
if cmp == 0 {
cmp = temp.subsec_nanos() as u64 - MAX_UEFI_TIME.0.subsec_nanos() as u64;
}
if cmp <= 0 { Some(SystemTime(temp)) } else { None }
if temp <= MAX_UEFI_TIME { Some(temp) } else { None }
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_sub(*other)?))
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
self.0.checked_sub(*other).map(Self)
}
}

View file

@ -38,18 +38,15 @@ impl SystemTime {
SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
self.t.sub_timespec(&other.t)
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime { t: self.t.checked_add_duration(other)? })
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
}
}
@ -136,15 +133,8 @@ impl Timespec {
Timespec::new(t.tv_sec as i64, t.tv_nsec as i64).unwrap()
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
// FIXME: const PartialOrd
let mut cmp = self.tv_sec - other.tv_sec;
if cmp == 0 {
cmp = self.tv_nsec.as_inner() as i64 - other.tv_nsec.as_inner() as i64;
}
if cmp >= 0 {
pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
if self >= other {
// NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
// to optimize it into a branchless form (see also #75545):
//
@ -179,8 +169,7 @@ impl Timespec {
}
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
pub fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = self.tv_sec.checked_add_unsigned(other.as_secs())?;
// Nano calculations can't overflow because nanos are <1B which fit
@ -190,11 +179,10 @@ impl Timespec {
nsec -= NSEC_PER_SEC as u32;
secs = secs.checked_add(1)?;
}
Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) })
Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) })
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?;
// Similar to above, nanos can't overflow.
@ -203,7 +191,7 @@ impl Timespec {
nsec += NSEC_PER_SEC as i32;
secs = secs.checked_sub(1)?;
}
Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) })
Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) })
}
#[allow(dead_code)]

View file

@ -31,22 +31,15 @@ impl SystemTime {
panic!("time not implemented on this platform")
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
// FIXME: ok_or_else with const closures
match self.0.checked_sub(other.0) {
Some(duration) => Ok(duration),
None => Err(other.0 - self.0),
}
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_add(*other)?))
}
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_sub(*other)?))
}
}

Some files were not shown because too many files have changed in this diff Show more