Rollup merge of #103603 - camsteffen:refactor-lang, r=oli-obk
Lang item cleanups Various cleanups related to lang items.
This commit is contained in:
commit
c1c2922aa1
34 changed files with 223 additions and 281 deletions
|
@ -22,7 +22,6 @@ use rustc_data_structures::sync::ParallelIterator;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::weak_lang_items::WEAK_ITEMS_SYMBOLS;
|
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
use rustc_metadata::EncodedMetadata;
|
use rustc_metadata::EncodedMetadata;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||||
|
@ -887,14 +886,14 @@ impl CrateInfo {
|
||||||
// by the compiler, but that's ok because all this stuff is unstable anyway.
|
// by the compiler, but that's ok because all this stuff is unstable anyway.
|
||||||
let target = &tcx.sess.target;
|
let target = &tcx.sess.target;
|
||||||
if !are_upstream_rust_objects_already_included(tcx.sess) {
|
if !are_upstream_rust_objects_already_included(tcx.sess) {
|
||||||
let missing_weak_lang_items: FxHashSet<&Symbol> = info
|
let missing_weak_lang_items: FxHashSet<Symbol> = info
|
||||||
.used_crates
|
.used_crates
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|cnum| {
|
.flat_map(|&cnum| tcx.missing_lang_items(cnum))
|
||||||
tcx.missing_lang_items(*cnum)
|
.filter(|l| l.is_weak())
|
||||||
.iter()
|
.filter_map(|&l| {
|
||||||
.filter(|l| lang_items::required(tcx, **l))
|
let name = l.link_name()?;
|
||||||
.filter_map(|item| WEAK_ITEMS_SYMBOLS.get(item))
|
lang_items::required(tcx, l).then_some(name)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" };
|
let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" };
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//! context.
|
//! context.
|
||||||
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::lang_items::LangItemGroup;
|
use rustc_hir::lang_items;
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, AssocItemContainer, DefIdTree, Instance, ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{self, AssocItemContainer, DefIdTree, Instance, ParamEnv, Ty, TyCtxt};
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
|
@ -74,22 +74,24 @@ pub fn call_kind<'tcx>(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let fn_call = parent
|
let fn_call = parent.and_then(|p| {
|
||||||
.and_then(|p| tcx.lang_items().group(LangItemGroup::Fn).iter().find(|did| **did == p));
|
lang_items::FN_TRAITS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
|
||||||
|
});
|
||||||
|
|
||||||
let operator = (!from_hir_call)
|
let operator = if !from_hir_call && let Some(p) = parent {
|
||||||
.then(|| parent)
|
lang_items::OPERATORS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
|
||||||
.flatten()
|
} else {
|
||||||
.and_then(|p| tcx.lang_items().group(LangItemGroup::Op).iter().find(|did| **did == p));
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
|
let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
|
||||||
|
|
||||||
// Check for a 'special' use of 'self' -
|
// Check for a 'special' use of 'self' -
|
||||||
// an FnOnce call, an operator (e.g. `<<`), or a
|
// an FnOnce call, an operator (e.g. `<<`), or a
|
||||||
// deref coercion.
|
// deref coercion.
|
||||||
let kind = if let Some(&trait_id) = fn_call {
|
let kind = if let Some(trait_id) = fn_call {
|
||||||
Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_substs.type_at(0) })
|
Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_substs.type_at(0) })
|
||||||
} else if let Some(&trait_id) = operator {
|
} else if let Some(trait_id) = operator {
|
||||||
Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
|
Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
|
||||||
} else if is_deref {
|
} else if is_deref {
|
||||||
let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
|
let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
|
||||||
|
|
|
@ -21,6 +21,3 @@ monomorphize_large_assignments =
|
||||||
moving {$size} bytes
|
moving {$size} bytes
|
||||||
.label = value moved from here
|
.label = value moved from here
|
||||||
.note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
|
.note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
|
||||||
|
|
||||||
monomorphize_requires_lang_item =
|
|
||||||
requires `{$lang_item}` lang_item
|
|
||||||
|
|
|
@ -12,35 +12,56 @@ use crate::errors::LangItemError;
|
||||||
use crate::{MethodKind, Target};
|
use crate::{MethodKind, Target};
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use std::sync::LazyLock;
|
/// All of the language items, defined or not.
|
||||||
|
/// Defined lang items can come from the current crate or its dependencies.
|
||||||
pub enum LangItemGroup {
|
#[derive(HashStable_Generic, Debug)]
|
||||||
Op,
|
pub struct LanguageItems {
|
||||||
Fn,
|
/// Mappings from lang items to their possibly found [`DefId`]s.
|
||||||
|
/// The index corresponds to the order in [`LangItem`].
|
||||||
|
items: [Option<DefId>; std::mem::variant_count::<LangItem>()],
|
||||||
|
/// Lang items that were not found during collection.
|
||||||
|
pub missing: Vec<LangItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const NUM_GROUPS: usize = 2;
|
impl LanguageItems {
|
||||||
|
/// Construct an empty collection of lang items and no missing ones.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { items: [None; std::mem::variant_count::<LangItem>()], missing: Vec::new() }
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! expand_group {
|
pub fn get(&self, item: LangItem) -> Option<DefId> {
|
||||||
() => {
|
self.items[item as usize]
|
||||||
None
|
}
|
||||||
};
|
|
||||||
($group:expr) => {
|
pub fn set(&mut self, item: LangItem, def_id: DefId) {
|
||||||
Some($group)
|
self.items[item as usize] = Some(def_id);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
|
||||||
|
/// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
|
||||||
|
/// returns an error encapsulating the `LangItem`.
|
||||||
|
pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
|
||||||
|
self.get(it).ok_or_else(|| LangItemError(it))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter<'a>(&'a self) -> impl Iterator<Item = (LangItem, DefId)> + 'a {
|
||||||
|
self.items
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(i, id)| id.map(|id| (LangItem::from_u32(i as u32).unwrap(), id)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The actual lang items defined come at the end of this file in one handy table.
|
// The actual lang items defined come at the end of this file in one handy table.
|
||||||
// So you probably just want to nip down to the end.
|
// So you probably just want to nip down to the end.
|
||||||
macro_rules! language_item_table {
|
macro_rules! language_item_table {
|
||||||
(
|
(
|
||||||
$( $(#[$attr:meta])* $variant:ident $($group:expr)?, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
|
$( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
|
||||||
) => {
|
) => {
|
||||||
|
|
||||||
enum_from_u32! {
|
enum_from_u32! {
|
||||||
|
@ -66,12 +87,17 @@ macro_rules! language_item_table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The [group](LangItemGroup) that this lang item belongs to,
|
/// Opposite of [`LangItem::name`]
|
||||||
/// or `None` if it doesn't belong to a group.
|
pub fn from_name(name: Symbol) -> Option<Self> {
|
||||||
pub fn group(self) -> Option<LangItemGroup> {
|
match name {
|
||||||
use LangItemGroup::*;
|
$( $module::$name => Some(LangItem::$variant), )*
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn target(self) -> Target {
|
||||||
match self {
|
match self {
|
||||||
$( LangItem::$variant => expand_group!($($group)*), )*
|
$( LangItem::$variant => $target, )*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,50 +108,7 @@ macro_rules! language_item_table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All of the language items, defined or not.
|
|
||||||
/// Defined lang items can come from the current crate or its dependencies.
|
|
||||||
#[derive(HashStable_Generic, Debug)]
|
|
||||||
pub struct LanguageItems {
|
|
||||||
/// Mappings from lang items to their possibly found [`DefId`]s.
|
|
||||||
/// The index corresponds to the order in [`LangItem`].
|
|
||||||
pub items: Vec<Option<DefId>>,
|
|
||||||
/// Lang items that were not found during collection.
|
|
||||||
pub missing: Vec<LangItem>,
|
|
||||||
/// Mapping from [`LangItemGroup`] discriminants to all
|
|
||||||
/// [`DefId`]s of lang items in that group.
|
|
||||||
pub groups: [Vec<DefId>; NUM_GROUPS],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LanguageItems {
|
impl LanguageItems {
|
||||||
/// Construct an empty collection of lang items and no missing ones.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
fn init_none(_: LangItem) -> Option<DefId> { None }
|
|
||||||
const EMPTY: Vec<DefId> = Vec::new();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
items: vec![$(init_none(LangItem::$variant)),*],
|
|
||||||
missing: Vec::new(),
|
|
||||||
groups: [EMPTY; NUM_GROUPS],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the mappings to the possibly found `DefId`s for each lang item.
|
|
||||||
pub fn items(&self) -> &[Option<DefId>] {
|
|
||||||
&*self.items
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
|
|
||||||
/// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
|
|
||||||
/// returns an error encapsulating the `LangItem`.
|
|
||||||
pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
|
|
||||||
self.items[it as usize].ok_or_else(|| LangItemError(it))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the [`DefId`]s of all lang items in a group.
|
|
||||||
pub fn group(&self, group: LangItemGroup) -> &[DefId] {
|
|
||||||
self.groups[group as usize].as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
$(
|
$(
|
||||||
#[doc = concat!("Returns the [`DefId`] of the `", stringify!($name), "` lang item if it is defined.")]
|
#[doc = concat!("Returns the [`DefId`] of the `", stringify!($name), "` lang item if it is defined.")]
|
||||||
pub fn $method(&self) -> Option<DefId> {
|
pub fn $method(&self) -> Option<DefId> {
|
||||||
|
@ -133,15 +116,6 @@ macro_rules! language_item_table {
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mapping from the name of the lang item to its order and the form it must be of.
|
|
||||||
pub static ITEM_REFS: LazyLock<FxIndexMap<Symbol, (usize, Target)>> = LazyLock::new(|| {
|
|
||||||
let mut item_refs = FxIndexMap::default();
|
|
||||||
$( item_refs.insert($module::$name, (LangItem::$variant as usize, $target)); )*
|
|
||||||
item_refs
|
|
||||||
});
|
|
||||||
|
|
||||||
// End of the macro
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,30 +170,30 @@ language_item_table! {
|
||||||
TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0);
|
TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0);
|
||||||
TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3);
|
TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3);
|
||||||
|
|
||||||
Add(Op), sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1);
|
Add, sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Sub(Op), sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1);
|
Sub, sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Mul(Op), sym::mul, mul_trait, Target::Trait, GenericRequirement::Exact(1);
|
Mul, sym::mul, mul_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Div(Op), sym::div, div_trait, Target::Trait, GenericRequirement::Exact(1);
|
Div, sym::div, div_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Rem(Op), sym::rem, rem_trait, Target::Trait, GenericRequirement::Exact(1);
|
Rem, sym::rem, rem_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Neg(Op), sym::neg, neg_trait, Target::Trait, GenericRequirement::Exact(0);
|
Neg, sym::neg, neg_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
Not(Op), sym::not, not_trait, Target::Trait, GenericRequirement::Exact(0);
|
Not, sym::not, not_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
BitXor(Op), sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1);
|
BitXor, sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitAnd(Op), sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1);
|
BitAnd, sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitOr(Op), sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1);
|
BitOr, sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Shl(Op), sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1);
|
Shl, sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Shr(Op), sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1);
|
Shr, sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
AddAssign(Op), sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
AddAssign, sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
SubAssign(Op), sym::sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
SubAssign, sym::sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
MulAssign(Op), sym::mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
MulAssign, sym::mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
DivAssign(Op), sym::div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
DivAssign, sym::div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
RemAssign(Op), sym::rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
RemAssign, sym::rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitXorAssign(Op), sym::bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
BitXorAssign, sym::bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitAndAssign(Op), sym::bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
BitAndAssign, sym::bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
BitOrAssign(Op), sym::bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
BitOrAssign, sym::bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
ShlAssign(Op), sym::shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
ShlAssign, sym::shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
ShrAssign(Op), sym::shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
ShrAssign, sym::shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
Index(Op), sym::index, index_trait, Target::Trait, GenericRequirement::Exact(1);
|
Index, sym::index, index_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
IndexMut(Op), sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
IndexMut, sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
|
|
||||||
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
|
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
|
||||||
VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
|
VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
|
||||||
|
@ -229,9 +203,9 @@ language_item_table! {
|
||||||
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
|
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
|
||||||
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
|
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
|
||||||
|
|
||||||
Fn(Fn), kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
FnMut(Fn), sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
FnOnce(Fn), sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
|
FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
|
|
||||||
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
|
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
|
||||||
|
|
||||||
|
@ -241,8 +215,8 @@ language_item_table! {
|
||||||
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
|
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
|
||||||
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
|
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
|
||||||
|
|
||||||
PartialEq(Op), sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
|
PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
PartialOrd(Op), sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
|
PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||||
|
|
||||||
// A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
|
// A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
|
||||||
// various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
|
// various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
|
||||||
|
@ -338,3 +312,34 @@ pub enum GenericRequirement {
|
||||||
Minimum(usize),
|
Minimum(usize),
|
||||||
Exact(usize),
|
Exact(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static FN_TRAITS: &'static [LangItem] = &[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce];
|
||||||
|
|
||||||
|
pub static OPERATORS: &'static [LangItem] = &[
|
||||||
|
LangItem::Add,
|
||||||
|
LangItem::Sub,
|
||||||
|
LangItem::Mul,
|
||||||
|
LangItem::Div,
|
||||||
|
LangItem::Rem,
|
||||||
|
LangItem::Neg,
|
||||||
|
LangItem::Not,
|
||||||
|
LangItem::BitXor,
|
||||||
|
LangItem::BitAnd,
|
||||||
|
LangItem::BitOr,
|
||||||
|
LangItem::Shl,
|
||||||
|
LangItem::Shr,
|
||||||
|
LangItem::AddAssign,
|
||||||
|
LangItem::SubAssign,
|
||||||
|
LangItem::MulAssign,
|
||||||
|
LangItem::DivAssign,
|
||||||
|
LangItem::RemAssign,
|
||||||
|
LangItem::BitXorAssign,
|
||||||
|
LangItem::BitAndAssign,
|
||||||
|
LangItem::BitOrAssign,
|
||||||
|
LangItem::ShlAssign,
|
||||||
|
LangItem::ShrAssign,
|
||||||
|
LangItem::Index,
|
||||||
|
LangItem::IndexMut,
|
||||||
|
LangItem::PartialEq,
|
||||||
|
LangItem::PartialOrd,
|
||||||
|
];
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
#![feature(closure_track_caller)]
|
#![feature(closure_track_caller)]
|
||||||
#![feature(const_btree_len)]
|
#![feature(const_btree_len)]
|
||||||
#![feature(once_cell)]
|
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
#![feature(variant_count)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
|
|
|
@ -1,53 +1,31 @@
|
||||||
//! Validity checking for weak lang items
|
//! Validity checking for weak lang items
|
||||||
|
|
||||||
use crate::def_id::DefId;
|
use crate::LangItem;
|
||||||
use crate::{lang_items, LangItem, LanguageItems};
|
|
||||||
|
|
||||||
use rustc_ast as ast;
|
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
|
||||||
use std::sync::LazyLock;
|
|
||||||
|
|
||||||
macro_rules! weak_lang_items {
|
macro_rules! weak_lang_items {
|
||||||
($($name:ident, $item:ident, $sym:ident;)*) => (
|
($($item:ident, $sym:ident;)*) => {
|
||||||
|
pub static WEAK_LANG_ITEMS: &[LangItem] = &[$(LangItem::$item,)*];
|
||||||
|
|
||||||
pub static WEAK_ITEMS_REFS: LazyLock<FxIndexMap<Symbol, LangItem>> = LazyLock::new(|| {
|
impl LangItem {
|
||||||
let mut map = FxIndexMap::default();
|
pub fn is_weak(self) -> bool {
|
||||||
$(map.insert(sym::$name, LangItem::$item);)*
|
matches!(self, $(LangItem::$item)|*)
|
||||||
map
|
|
||||||
});
|
|
||||||
|
|
||||||
pub static WEAK_ITEMS_SYMBOLS: LazyLock<FxIndexMap<LangItem, Symbol>> = LazyLock::new(|| {
|
|
||||||
let mut map = FxIndexMap::default();
|
|
||||||
$(map.insert(LangItem::$item, sym::$sym);)*
|
|
||||||
map
|
|
||||||
});
|
|
||||||
|
|
||||||
pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol>
|
|
||||||
{
|
|
||||||
lang_items::extract(attrs).and_then(|(name, _)| {
|
|
||||||
$(if name == sym::$name {
|
|
||||||
Some(sym::$sym)
|
|
||||||
} else)* {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LanguageItems {
|
pub fn link_name(self) -> Option<Symbol> {
|
||||||
pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool {
|
match self {
|
||||||
let did = Some(item_def_id);
|
$( LangItem::$item => Some(sym::$sym),)*
|
||||||
|
_ => None,
|
||||||
$(self.$name() == did)||*
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
) }
|
|
||||||
|
|
||||||
weak_lang_items! {
|
weak_lang_items! {
|
||||||
panic_impl, PanicImpl, rust_begin_unwind;
|
PanicImpl, rust_begin_unwind;
|
||||||
eh_personality, EhPersonality, rust_eh_personality;
|
EhPersonality, rust_eh_personality;
|
||||||
eh_catch_typeinfo, EhCatchTypeinfo, rust_eh_catch_typeinfo;
|
EhCatchTypeinfo, rust_eh_catch_typeinfo;
|
||||||
oom, Oom, rust_oom;
|
Oom, rust_oom;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
|
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::intravisit::{walk_generics, Visitor as _};
|
use rustc_hir::intravisit::{walk_generics, Visitor as _};
|
||||||
use rustc_hir::lang_items::LangItem;
|
|
||||||
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
|
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
|
||||||
use rustc_middle::middle::stability::AllowUnstable;
|
use rustc_middle::middle::stability::AllowUnstable;
|
||||||
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
|
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
|
||||||
|
@ -884,9 +883,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sized_def_id = tcx.lang_items().require(LangItem::Sized);
|
let sized_def_id = tcx.lang_items().sized_trait();
|
||||||
match (&sized_def_id, unbound) {
|
match (&sized_def_id, unbound) {
|
||||||
(Ok(sized_def_id), Some(tpb))
|
(Some(sized_def_id), Some(tpb))
|
||||||
if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
|
if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
|
||||||
{
|
{
|
||||||
// There was in fact a `?Sized` bound, return without doing anything
|
// There was in fact a `?Sized` bound, return without doing anything
|
||||||
|
@ -906,7 +905,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
// There was no `?Sized` bound; add implicitly sized if `Sized` is available.
|
// There was no `?Sized` bound; add implicitly sized if `Sized` is available.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sized_def_id.is_err() {
|
if sized_def_id.is_none() {
|
||||||
// No lang item for `Sized`, so we can't add it as a bound.
|
// No lang item for `Sized`, so we can't add it as a bound.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::CtorKind;
|
use rustc_hir::def::CtorKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::weak_lang_items;
|
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
|
||||||
use rustc_hir::{GenericParamKind, Node};
|
use rustc_hir::{lang_items, GenericParamKind, LangItem, Node};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||||
use rustc_middle::mir::mono::Linkage;
|
use rustc_middle::mir::mono::Linkage;
|
||||||
|
@ -2104,12 +2104,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
||||||
// strippable by the linker.
|
// strippable by the linker.
|
||||||
//
|
//
|
||||||
// Additionally weak lang items have predetermined symbol names.
|
// Additionally weak lang items have predetermined symbol names.
|
||||||
if tcx.is_weak_lang_item(did.to_def_id()) {
|
if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||||
}
|
}
|
||||||
if let Some(name) = weak_lang_items::link_name(attrs) {
|
if let Some((name, _)) = lang_items::extract(attrs)
|
||||||
codegen_fn_attrs.export_name = Some(name);
|
&& let Some(lang_item) = LangItem::from_name(name)
|
||||||
codegen_fn_attrs.link_name = Some(name);
|
&& let Some(link_name) = lang_item.link_name()
|
||||||
|
{
|
||||||
|
codegen_fn_attrs.export_name = Some(link_name);
|
||||||
|
codegen_fn_attrs.link_name = Some(link_name);
|
||||||
}
|
}
|
||||||
check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
|
check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||||
use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
|
use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
|
||||||
use rustc_hir::diagnostic_items::DiagnosticItems;
|
use rustc_hir::diagnostic_items::DiagnosticItems;
|
||||||
use rustc_hir::lang_items;
|
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_middle::metadata::ModChild;
|
use rustc_middle::metadata::ModChild;
|
||||||
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
|
||||||
|
@ -967,7 +966,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over the language items in the given crate.
|
/// Iterates over the language items in the given crate.
|
||||||
fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
|
fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] {
|
||||||
tcx.arena.alloc_from_iter(
|
tcx.arena.alloc_from_iter(
|
||||||
self.root
|
self.root
|
||||||
.lang_items
|
.lang_items
|
||||||
|
@ -1319,7 +1318,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
|
fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] {
|
||||||
tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self))
|
tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ use rustc_hir::def_id::{
|
||||||
};
|
};
|
||||||
use rustc_hir::definitions::DefPathData;
|
use rustc_hir::definitions::DefPathData;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::lang_items;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
use rustc_middle::middle::exported_symbols::{
|
use rustc_middle::middle::exported_symbols::{
|
||||||
|
@ -1905,22 +1905,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
self.lazy_array(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
|
self.lazy_array(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, usize)> {
|
fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, LangItem)> {
|
||||||
empty_proc_macro!(self);
|
empty_proc_macro!(self);
|
||||||
let tcx = self.tcx;
|
let lang_items = self.tcx.lang_items().iter();
|
||||||
let lang_items = tcx.lang_items();
|
self.lazy_array(lang_items.filter_map(|(lang_item, def_id)| {
|
||||||
let lang_items = lang_items.items().iter();
|
def_id.as_local().map(|id| (id.local_def_index, lang_item))
|
||||||
self.lazy_array(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
|
|
||||||
if let Some(def_id) = opt_def_id {
|
|
||||||
if def_id.is_local() {
|
|
||||||
return Some((def_id.index, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_lang_items_missing(&mut self) -> LazyArray<lang_items::LangItem> {
|
fn encode_lang_items_missing(&mut self) -> LazyArray<LangItem> {
|
||||||
empty_proc_macro!(self);
|
empty_proc_macro!(self);
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
self.lazy_array(&tcx.lang_items().missing)
|
self.lazy_array(&tcx.lang_items().missing)
|
||||||
|
|
|
@ -12,7 +12,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, DefKind};
|
use rustc_hir::def::{CtorKind, DefKind};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
|
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
|
||||||
use rustc_hir::definitions::DefKey;
|
use rustc_hir::definitions::DefKey;
|
||||||
use rustc_hir::lang_items;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_index::bit_set::{BitSet, FiniteBitSet};
|
use rustc_index::bit_set::{BitSet, FiniteBitSet};
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::metadata::ModChild;
|
use rustc_middle::metadata::ModChild;
|
||||||
|
@ -230,8 +230,8 @@ pub(crate) struct CrateRoot {
|
||||||
dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
|
dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
|
||||||
lib_features: LazyArray<(Symbol, Option<Symbol>)>,
|
lib_features: LazyArray<(Symbol, Option<Symbol>)>,
|
||||||
stability_implications: LazyArray<(Symbol, Symbol)>,
|
stability_implications: LazyArray<(Symbol, Symbol)>,
|
||||||
lang_items: LazyArray<(DefIndex, usize)>,
|
lang_items: LazyArray<(DefIndex, LangItem)>,
|
||||||
lang_items_missing: LazyArray<lang_items::LangItem>,
|
lang_items_missing: LazyArray<LangItem>,
|
||||||
diagnostic_items: LazyArray<(Symbol, DefIndex)>,
|
diagnostic_items: LazyArray<(Symbol, DefIndex)>,
|
||||||
native_libraries: LazyArray<NativeLib>,
|
native_libraries: LazyArray<NativeLib>,
|
||||||
foreign_modules: LazyArray<ForeignModule>,
|
foreign_modules: LazyArray<ForeignModule>,
|
||||||
|
|
|
@ -36,10 +36,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_weak_lang_item(self, item_def_id: DefId) -> bool {
|
|
||||||
self.lang_items().is_weak_lang_item(item_def_id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the specified `lang_item` must be present for this
|
/// Returns `true` if the specified `lang_item` must be present for this
|
||||||
|
|
|
@ -1705,7 +1705,7 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the lang items defined in another crate by loading it from metadata.
|
/// Returns the lang items defined in another crate by loading it from metadata.
|
||||||
query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] {
|
query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, LangItem)] {
|
||||||
desc { "calculating the lang items defined in a crate" }
|
desc { "calculating the lang items defined in a crate" }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
|
@ -2456,7 +2456,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
|
pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
|
||||||
let def_id = self.lang_items().require(item).ok()?;
|
let def_id = self.lang_items().get(item)?;
|
||||||
Some(self.mk_generic_adt(def_id, ty))
|
Some(self.mk_generic_adt(def_id, ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ use std::iter;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::errors::{LargeAssignmentsLint, RecursionLimit, RequiresLangItem, TypeLengthLimit};
|
use crate::errors::{LargeAssignmentsLint, RecursionLimit, TypeLengthLimit};
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum MonoItemCollectionMode {
|
pub enum MonoItemCollectionMode {
|
||||||
|
@ -1298,14 +1298,7 @@ impl<'v> RootCollector<'_, 'v> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let start_def_id = match self.tcx.lang_items().require(LangItem::Start) {
|
let start_def_id = self.tcx.require_lang_item(LangItem::Start, None);
|
||||||
Ok(s) => s,
|
|
||||||
Err(lang_item_err) => {
|
|
||||||
self.tcx
|
|
||||||
.sess
|
|
||||||
.emit_fatal(RequiresLangItem { lang_item: lang_item_err.0.name().to_string() });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let main_ret_ty = self.tcx.fn_sig(main_def_id).output();
|
let main_ret_ty = self.tcx.fn_sig(main_def_id).output();
|
||||||
|
|
||||||
// Given that `main()` has no arguments,
|
// Given that `main()` has no arguments,
|
||||||
|
|
|
@ -32,12 +32,6 @@ pub struct TypeLengthLimit {
|
||||||
pub type_length: usize,
|
pub type_length: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(monomorphize_requires_lang_item)]
|
|
||||||
pub struct RequiresLangItem {
|
|
||||||
pub lang_item: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct UnusedGenericParams {
|
pub struct UnusedGenericParams {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub param_spans: Vec<Span>,
|
pub param_spans: Vec<Span>,
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::weak_lang_items;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
|
use rustc_hir::lang_items::{extract, GenericRequirement};
|
||||||
use rustc_hir::{HirId, LangItem, LanguageItems, Target};
|
use rustc_hir::{HirId, LangItem, LanguageItems, Target};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::cstore::ExternCrate;
|
use rustc_session::cstore::ExternCrate;
|
||||||
|
@ -43,17 +43,17 @@ impl<'tcx> LanguageItemCollector<'tcx> {
|
||||||
fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
|
fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
|
||||||
let attrs = self.tcx.hir().attrs(hir_id);
|
let attrs = self.tcx.hir().attrs(hir_id);
|
||||||
if let Some((name, span)) = extract(&attrs) {
|
if let Some((name, span)) = extract(&attrs) {
|
||||||
match ITEM_REFS.get(&name).cloned() {
|
match LangItem::from_name(name) {
|
||||||
// Known lang item with attribute on correct target.
|
// Known lang item with attribute on correct target.
|
||||||
Some((item_index, expected_target)) if actual_target == expected_target => {
|
Some(lang_item) if actual_target == lang_item.target() => {
|
||||||
self.collect_item_extended(item_index, hir_id, span);
|
self.collect_item_extended(lang_item, hir_id, span);
|
||||||
}
|
}
|
||||||
// Known lang item with attribute on incorrect target.
|
// Known lang item with attribute on incorrect target.
|
||||||
Some((_, expected_target)) => {
|
Some(lang_item) => {
|
||||||
self.tcx.sess.emit_err(LangItemOnIncorrectTarget {
|
self.tcx.sess.emit_err(LangItemOnIncorrectTarget {
|
||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
expected_target,
|
expected_target: lang_item.target(),
|
||||||
actual_target,
|
actual_target,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -65,12 +65,12 @@ impl<'tcx> LanguageItemCollector<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
|
fn collect_item(&mut self, lang_item: LangItem, item_def_id: DefId) {
|
||||||
// Check for duplicates.
|
// Check for duplicates.
|
||||||
if let Some(original_def_id) = self.items.items[item_index] {
|
if let Some(original_def_id) = self.items.get(lang_item) {
|
||||||
if original_def_id != item_def_id {
|
if original_def_id != item_def_id {
|
||||||
let local_span = self.tcx.hir().span_if_local(item_def_id);
|
let local_span = self.tcx.hir().span_if_local(item_def_id);
|
||||||
let lang_item_name = LangItem::from_u32(item_index as u32).unwrap().name();
|
let lang_item_name = lang_item.name();
|
||||||
let crate_name = self.tcx.crate_name(item_def_id.krate);
|
let crate_name = self.tcx.crate_name(item_def_id.krate);
|
||||||
let mut dependency_of = Empty;
|
let mut dependency_of = Empty;
|
||||||
let is_local = item_def_id.is_local();
|
let is_local = item_def_id.is_local();
|
||||||
|
@ -139,17 +139,13 @@ impl<'tcx> LanguageItemCollector<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matched.
|
// Matched.
|
||||||
self.items.items[item_index] = Some(item_def_id);
|
self.items.set(lang_item, item_def_id);
|
||||||
if let Some(group) = LangItem::from_u32(item_index as u32).unwrap().group() {
|
|
||||||
self.items.groups[group as usize].push(item_def_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Like collect_item() above, but also checks whether the lang item is declared
|
// Like collect_item() above, but also checks whether the lang item is declared
|
||||||
// with the right number of generic arguments.
|
// with the right number of generic arguments.
|
||||||
fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span) {
|
fn collect_item_extended(&mut self, lang_item: LangItem, hir_id: HirId, span: Span) {
|
||||||
let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
|
let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
|
||||||
let lang_item = LangItem::from_u32(item_index as u32).unwrap();
|
|
||||||
let name = lang_item.name();
|
let name = lang_item.name();
|
||||||
|
|
||||||
// Now check whether the lang_item has the expected number of generic
|
// Now check whether the lang_item has the expected number of generic
|
||||||
|
@ -197,7 +193,7 @@ impl<'tcx> LanguageItemCollector<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.collect_item(item_index, item_def_id);
|
self.collect_item(lang_item, item_def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,8 +204,8 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
|
||||||
|
|
||||||
// Collect lang items in other crates.
|
// Collect lang items in other crates.
|
||||||
for &cnum in tcx.crates(()).iter() {
|
for &cnum in tcx.crates(()).iter() {
|
||||||
for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() {
|
for &(def_id, lang_item) in tcx.defined_lang_items(cnum).iter() {
|
||||||
collector.collect_item(item_index, def_id);
|
collector.collect_item(lang_item, def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -380,13 +380,11 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for item in tcx.lang_items().items().iter() {
|
for (_, def_id) in tcx.lang_items().iter() {
|
||||||
if let Some(def_id) = *item {
|
|
||||||
if let Some(def_id) = def_id.as_local() {
|
if let Some(def_id) = def_id.as_local() {
|
||||||
reachable_context.worklist.push(def_id);
|
reachable_context.worklist.push(def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
{
|
{
|
||||||
// Some methods from non-exported (completely private) trait impls still have to be
|
// Some methods from non-exported (completely private) trait impls still have to be
|
||||||
// reachable if they are called from inlinable code. Generally, it's not known until
|
// reachable if they are called from inlinable code. Generally, it's not known until
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::lang_items::{self, LangItem};
|
use rustc_hir::lang_items::{self, LangItem};
|
||||||
use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
|
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
|
||||||
use rustc_middle::middle::lang_items::required;
|
use rustc_middle::middle::lang_items::required;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::CrateType;
|
use rustc_session::config::CrateType;
|
||||||
|
@ -29,8 +29,8 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
|
||||||
for id in crate_items.foreign_items() {
|
for id in crate_items.foreign_items() {
|
||||||
let attrs = tcx.hir().attrs(id.hir_id());
|
let attrs = tcx.hir().attrs(id.hir_id());
|
||||||
if let Some((lang_item, _)) = lang_items::extract(attrs) {
|
if let Some((lang_item, _)) = lang_items::extract(attrs) {
|
||||||
if let Some(&item) = WEAK_ITEMS_REFS.get(&lang_item) {
|
if let Some(item) = LangItem::from_name(lang_item) && item.is_weak() {
|
||||||
if items.require(item).is_err() {
|
if items.get(item).is_none() {
|
||||||
items.missing.push(item);
|
items.missing.push(item);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,8 +65,8 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, &item) in WEAK_ITEMS_REFS.iter() {
|
for &item in WEAK_LANG_ITEMS.iter() {
|
||||||
if missing.contains(&item) && required(tcx, item) && items.require(item).is_err() {
|
if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() {
|
||||||
if item == LangItem::PanicImpl {
|
if item == LangItem::PanicImpl {
|
||||||
tcx.sess.emit_err(MissingPanicHandler);
|
tcx.sess.emit_err(MissingPanicHandler);
|
||||||
} else if item == LangItem::Oom {
|
} else if item == LangItem::Oom {
|
||||||
|
@ -75,7 +75,7 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
|
||||||
tcx.sess.emit_note(MissingAllocErrorHandler);
|
tcx.sess.emit_note(MissingAllocErrorHandler);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tcx.sess.emit_err(MissingLangItem { name: *name });
|
tcx.sess.emit_err(MissingLangItem { name: item.name() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -974,7 +974,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
// useful for less general traits.
|
// useful for less general traits.
|
||||||
if peeled
|
if peeled
|
||||||
&& !self.tcx.trait_is_auto(def_id)
|
&& !self.tcx.trait_is_auto(def_id)
|
||||||
&& !self.tcx.lang_items().items().contains(&Some(def_id))
|
&& !self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
|
||||||
{
|
{
|
||||||
let trait_ref = trait_pred.to_poly_trait_ref();
|
let trait_ref = trait_pred.to_poly_trait_ref();
|
||||||
let impl_candidates =
|
let impl_candidates =
|
||||||
|
@ -1898,7 +1898,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
let def_id = trait_ref.def_id();
|
let def_id = trait_ref.def_id();
|
||||||
if impl_candidates.is_empty() {
|
if impl_candidates.is_empty() {
|
||||||
if self.tcx.trait_is_auto(def_id)
|
if self.tcx.trait_is_auto(def_id)
|
||||||
|| self.tcx.lang_items().items().contains(&Some(def_id))
|
|| self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
|
||||||
|| self.tcx.get_diagnostic_name(def_id).is_some()
|
|| self.tcx.get_diagnostic_name(def_id).is_some()
|
||||||
{
|
{
|
||||||
// Mentioning implementers of `Copy`, `Debug` and friends is not useful.
|
// Mentioning implementers of `Copy`, `Debug` and friends is not useful.
|
||||||
|
|
|
@ -1019,7 +1019,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
let mut never_suggest_borrow: Vec<_> =
|
let mut never_suggest_borrow: Vec<_> =
|
||||||
[LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized]
|
[LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized]
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|lang_item| self.tcx.lang_items().require(*lang_item).ok())
|
.filter_map(|lang_item| self.tcx.lang_items().get(*lang_item))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if let Some(def_id) = self.tcx.get_diagnostic_item(sym::Send) {
|
if let Some(def_id) = self.tcx.get_diagnostic_item(sym::Send) {
|
||||||
|
|
|
@ -6,11 +6,12 @@ use rustc_hir::intravisit::{
|
||||||
walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
|
walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
|
||||||
walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
|
walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
|
||||||
};
|
};
|
||||||
|
use rustc_hir::lang_items;
|
||||||
use rustc_hir::FnRetTy::Return;
|
use rustc_hir::FnRetTy::Return;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
|
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
|
||||||
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn,
|
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem,
|
||||||
TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
|
TraitItemKind, Ty, TyKind, WherePredicate,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::nested_filter as middle_nested_filter;
|
use rustc_middle::hir::nested_filter as middle_nested_filter;
|
||||||
|
@ -364,8 +365,6 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize {
|
||||||
lts.iter().collect::<FxHashSet<_>>().len()
|
lts.iter().collect::<FxHashSet<_>>().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
const CLOSURE_TRAIT_BOUNDS: [LangItem; 3] = [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce];
|
|
||||||
|
|
||||||
/// A visitor usable for `rustc_front::visit::walk_ty()`.
|
/// A visitor usable for `rustc_front::visit::walk_ty()`.
|
||||||
struct RefVisitor<'a, 'tcx> {
|
struct RefVisitor<'a, 'tcx> {
|
||||||
cx: &'a LateContext<'tcx>,
|
cx: &'a LateContext<'tcx>,
|
||||||
|
@ -424,12 +423,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>) {
|
fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>) {
|
||||||
let trait_ref = &poly_tref.trait_ref;
|
let trait_ref = &poly_tref.trait_ref;
|
||||||
if CLOSURE_TRAIT_BOUNDS.iter().any(|&item| {
|
if let Some(id) = trait_ref.trait_def_id() && lang_items::FN_TRAITS.iter().any(|&item| {
|
||||||
self.cx
|
self.cx.tcx.lang_items().get(item) == Some(id)
|
||||||
.tcx
|
|
||||||
.lang_items()
|
|
||||||
.require(item)
|
|
||||||
.map_or(false, |id| Some(id) == trait_ref.trait_def_id())
|
|
||||||
}) {
|
}) {
|
||||||
let mut sub_visitor = RefVisitor::new(self.cx);
|
let mut sub_visitor = RefVisitor::new(self.cx);
|
||||||
sub_visitor.visit_trait_ref(trait_ref);
|
sub_visitor.visit_trait_ref(trait_ref);
|
||||||
|
|
|
@ -92,7 +92,7 @@ fn check_into_iter(
|
||||||
&& match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
|
&& match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
|
||||||
&& let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
|
&& let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
|
||||||
&& let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
|
&& let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
|
||||||
&& cx.tcx.lang_items().require(hir::LangItem::IntoIterIntoIter).ok() == Some(into_iter_def_id)
|
&& Some(into_iter_def_id) == cx.tcx.lang_items().into_iter_fn()
|
||||||
&& match_acceptable_type(cx, left_expr, msrv)
|
&& match_acceptable_type(cx, left_expr, msrv)
|
||||||
&& SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) {
|
&& SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) {
|
||||||
suggest(cx, parent_expr, left_expr, target_expr);
|
suggest(cx, parent_expr, left_expr, target_expr);
|
||||||
|
|
|
@ -41,7 +41,7 @@ pub(crate) trait BindInsteadOfMap {
|
||||||
const GOOD_METHOD_NAME: &'static str;
|
const GOOD_METHOD_NAME: &'static str;
|
||||||
|
|
||||||
fn no_op_msg(cx: &LateContext<'_>) -> Option<String> {
|
fn no_op_msg(cx: &LateContext<'_>) -> Option<String> {
|
||||||
let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
|
let variant_id = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)?;
|
||||||
let item_id = cx.tcx.parent(variant_id);
|
let item_id = cx.tcx.parent(variant_id);
|
||||||
Some(format!(
|
Some(format!(
|
||||||
"using `{}.{}({})`, which is a no-op",
|
"using `{}.{}({})`, which is a no-op",
|
||||||
|
@ -52,7 +52,7 @@ pub(crate) trait BindInsteadOfMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lint_msg(cx: &LateContext<'_>) -> Option<String> {
|
fn lint_msg(cx: &LateContext<'_>) -> Option<String> {
|
||||||
let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
|
let variant_id = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)?;
|
||||||
let item_id = cx.tcx.parent(variant_id);
|
let item_id = cx.tcx.parent(variant_id);
|
||||||
Some(format!(
|
Some(format!(
|
||||||
"using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`",
|
"using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`",
|
||||||
|
@ -144,7 +144,7 @@ pub(crate) trait BindInsteadOfMap {
|
||||||
fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool {
|
fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def();
|
if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def();
|
||||||
if let Ok(vid) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM);
|
if let Some(vid) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM);
|
||||||
if adt.did() == cx.tcx.parent(vid);
|
if adt.did() == cx.tcx.parent(vid);
|
||||||
then {} else { return false; }
|
then {} else { return false; }
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ pub(crate) trait BindInsteadOfMap {
|
||||||
|
|
||||||
fn is_variant(cx: &LateContext<'_>, res: Res) -> bool {
|
fn is_variant(cx: &LateContext<'_>, res: Res) -> bool {
|
||||||
if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
|
if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
|
||||||
if let Ok(variant_id) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM) {
|
if let Some(variant_id) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM) {
|
||||||
return cx.tcx.parent(id) == variant_id;
|
return cx.tcx.parent(id) == variant_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use clippy_utils::source::snippet_opt;
|
||||||
use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait};
|
use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait};
|
||||||
use clippy_utils::{fn_def_id, get_parent_expr};
|
use clippy_utils::{fn_def_id, get_parent_expr};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{def_id::DefId, Expr, ExprKind, LangItem};
|
use rustc_hir::{def_id::DefId, Expr, ExprKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::{sym, Symbol};
|
use rustc_span::{sym, Symbol};
|
||||||
|
|
||||||
|
@ -100,5 +100,5 @@ pub fn check_for_loop_iter(
|
||||||
|
|
||||||
/// Returns true if the named method is `IntoIterator::into_iter`.
|
/// Returns true if the named method is `IntoIterator::into_iter`.
|
||||||
pub fn is_into_iter(cx: &LateContext<'_>, callee_def_id: DefId) -> bool {
|
pub fn is_into_iter(cx: &LateContext<'_>, callee_def_id: DefId) -> bool {
|
||||||
cx.tcx.lang_items().require(LangItem::IntoIterIntoIter) == Ok(callee_def_id)
|
Some(callee_def_id) == cx.tcx.lang_items().into_iter_fn()
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use clippy_utils::visitors::find_all_ret_expressions;
|
||||||
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
|
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
|
||||||
use clippy_utils::{meets_msrv, msrvs};
|
use clippy_utils::{meets_msrv, msrvs};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
|
use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node};
|
||||||
use rustc_hir_typeck::{FnCtxt, Inherited};
|
use rustc_hir_typeck::{FnCtxt, Inherited};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
@ -378,7 +378,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
|
||||||
Node::Expr(parent_expr) => {
|
Node::Expr(parent_expr) => {
|
||||||
if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
|
if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
|
||||||
{
|
{
|
||||||
if cx.tcx.lang_items().require(LangItem::IntoFutureIntoFuture) == Ok(callee_def_id) {
|
if Some(callee_def_id) == cx.tcx.lang_items().into_future_fn() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub(super) fn check<'tcx>(
|
||||||
let rty = cx.typeck_results().expr_ty(rhs);
|
let rty = cx.typeck_results().expr_ty(rhs);
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let Some((_, lang_item)) = binop_traits(op.node);
|
if let Some((_, lang_item)) = binop_traits(op.node);
|
||||||
if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item);
|
if let Some(trait_id) = cx.tcx.lang_items().get(lang_item);
|
||||||
let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
|
let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
|
||||||
if trait_ref_of_method(cx, parent_fn)
|
if trait_ref_of_method(cx, parent_fn)
|
||||||
.map_or(true, |t| t.path.res.def_id() != trait_id);
|
.map_or(true, |t| t.path.res.def_id() != trait_id);
|
||||||
|
|
|
@ -60,8 +60,8 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind;
|
if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind;
|
||||||
if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node);
|
if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node);
|
||||||
if let Ok(binop_trait_id) = cx.tcx.lang_items().require(binop_trait_lang);
|
if let Some(binop_trait_id) = cx.tcx.lang_items().get(binop_trait_lang);
|
||||||
if let Ok(op_assign_trait_id) = cx.tcx.lang_items().require(op_assign_trait_lang);
|
if let Some(op_assign_trait_id) = cx.tcx.lang_items().get(op_assign_trait_lang);
|
||||||
|
|
||||||
// Check for more than one binary operation in the implemented function
|
// Check for more than one binary operation in the implemented function
|
||||||
// Linting when multiple operations are involved can result in false positives
|
// Linting when multiple operations are involved can result in false positives
|
||||||
|
@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
|
||||||
(&OP_ASSIGN_TRAITS, SUSPICIOUS_OP_ASSIGN_IMPL),
|
(&OP_ASSIGN_TRAITS, SUSPICIOUS_OP_ASSIGN_IMPL),
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&(ts, _)| ts.iter().any(|&t| Ok(trait_id) == cx.tcx.lang_items().require(t)));
|
.find(|&(ts, _)| ts.iter().any(|&t| Some(trait_id) == cx.tcx.lang_items().get(t)));
|
||||||
if count_binops(body.value) == 1;
|
if count_binops(body.value) == 1;
|
||||||
then {
|
then {
|
||||||
span_lint(
|
span_lint(
|
||||||
|
|
|
@ -3,7 +3,7 @@ use clippy_utils::{match_def_path, paths};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
|
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(fun_def_id);
|
if Some(fun_def_id) == cx.tcx.lang_items().from_fn();
|
||||||
if let [.., last_arg] = args;
|
if let [.., last_arg] = args;
|
||||||
if let ExprKind::Lit(spanned) = &last_arg.kind;
|
if let ExprKind::Lit(spanned) = &last_arg.kind;
|
||||||
if let LitKind::Str(symbol, _) = spanned.node;
|
if let LitKind::Str(symbol, _) = spanned.node;
|
||||||
|
|
|
@ -3,7 +3,6 @@ use clippy_utils::ty::{match_type, peel_mid_ty_refs_is_mutable};
|
||||||
use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, paths, peel_ref_operators};
|
use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, paths, peel_ref_operators};
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||||
use rustc_hir::lang_items::LangItem;
|
|
||||||
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
|
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::nested_filter::OnlyBodies;
|
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||||
|
@ -132,11 +131,11 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
|
||||||
// If the Peekable is passed to a function, stop
|
// If the Peekable is passed to a function, stop
|
||||||
ExprKind::Call(_, args) => {
|
ExprKind::Call(_, args) => {
|
||||||
if let Some(func_did) = fn_def_id(self.cx, expr)
|
if let Some(func_did) = fn_def_id(self.cx, expr)
|
||||||
&& let Ok(into_iter_did) = self
|
&& let Some(into_iter_did) = self
|
||||||
.cx
|
.cx
|
||||||
.tcx
|
.tcx
|
||||||
.lang_items()
|
.lang_items()
|
||||||
.require(LangItem::IntoIterIntoIter)
|
.into_iter_fn()
|
||||||
&& func_did == into_iter_did
|
&& func_did == into_iter_did
|
||||||
{
|
{
|
||||||
// Probably a for loop desugar, stop searching
|
// Probably a for loop desugar, stop searching
|
||||||
|
|
|
@ -5,7 +5,7 @@ use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts};
|
||||||
use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, paths};
|
use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, paths};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Expr, ExprKind, HirId, LangItem, MatchSource};
|
use rustc_hir::{Expr, ExprKind, HirId, MatchSource};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
|
@ -153,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
|
||||||
}
|
}
|
||||||
|
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(def_id);
|
if Some(def_id) == cx.tcx.lang_items().from_fn();
|
||||||
if same_type_and_consts(a, b);
|
if same_type_and_consts(a, b);
|
||||||
|
|
||||||
then {
|
then {
|
||||||
|
|
|
@ -152,7 +152,7 @@ impl UnnecessaryDefPath {
|
||||||
has_ctor,
|
has_ctor,
|
||||||
),
|
),
|
||||||
(0, Item::LangItem(item)) => (
|
(0, Item::LangItem(item)) => (
|
||||||
format!("{cx_snip}.tcx.lang_items().require(LangItem::{item}).ok() == Some({def_snip})"),
|
format!("{cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some({def_snip})"),
|
||||||
has_ctor,
|
has_ctor,
|
||||||
),
|
),
|
||||||
// match_trait_method
|
// match_trait_method
|
||||||
|
@ -184,7 +184,7 @@ impl UnnecessaryDefPath {
|
||||||
(3, Item::LangItem(item)) => (
|
(3, Item::LangItem(item)) => (
|
||||||
format!(
|
format!(
|
||||||
"path_res({cx_snip}, {def_snip}).opt_def_id()\
|
"path_res({cx_snip}, {def_snip}).opt_def_id()\
|
||||||
.map_or(false, |id| {cx_snip}.tcx.lang_items().require(LangItem::{item}).ok() == Some(id))",
|
.map_or(false, |id| {cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some(id))",
|
||||||
),
|
),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
|
|
@ -247,7 +247,7 @@ pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
|
||||||
/// For example, use this to check whether a function call or a pattern is `Some(..)`.
|
/// For example, use this to check whether a function call or a pattern is `Some(..)`.
|
||||||
pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> bool {
|
pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> bool {
|
||||||
if let Res::Def(DefKind::Ctor(..), id) = res
|
if let Res::Def(DefKind::Ctor(..), id) = res
|
||||||
&& let Ok(lang_id) = cx.tcx.lang_items().require(lang_item)
|
&& let Some(lang_id) = cx.tcx.lang_items().get(lang_item)
|
||||||
&& let Some(id) = cx.tcx.opt_parent(id)
|
&& let Some(id) = cx.tcx.opt_parent(id)
|
||||||
{
|
{
|
||||||
id == lang_id
|
id == lang_id
|
||||||
|
@ -303,7 +303,7 @@ pub fn is_lang_item_or_ctor(cx: &LateContext<'_>, did: DefId, item: LangItem) ->
|
||||||
_ => did,
|
_ => did,
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.tcx.lang_items().require(item).map_or(false, |id| id == did)
|
cx.tcx.lang_items().get(item) == Some(did)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
|
pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
|
||||||
|
|
|
@ -318,11 +318,7 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb
|
||||||
/// Returns `false` if the `LangItem` is not defined.
|
/// Returns `false` if the `LangItem` is not defined.
|
||||||
pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
|
pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::Adt(adt, _) => cx
|
ty::Adt(adt, _) => cx.tcx.lang_items().get(lang_item) == Some(adt.did()),
|
||||||
.tcx
|
|
||||||
.lang_items()
|
|
||||||
.require(lang_item)
|
|
||||||
.map_or(false, |li| li == adt.did()),
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue