Merge ref 'a015919e54' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref:a015919e54Filtered ref: 1867c5844dba22ac4d77d1ceb7d1624c14139c16 Upstream diff:4ba1cf9ade...a015919e54This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
commit
603341a94f
216 changed files with 1721 additions and 1262 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(...)]
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 }));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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]> =
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)> {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>>,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -221,13 +221,6 @@ fixed_size_enum! {
|
|||
}
|
||||
}
|
||||
|
||||
fixed_size_enum! {
|
||||
ty::AssocItemContainer {
|
||||
( Trait )
|
||||
( Impl )
|
||||
}
|
||||
}
|
||||
|
||||
fixed_size_enum! {
|
||||
MacroKind {
|
||||
( Attr )
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(_))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
..
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue