Simplify lang item groups
This commit is contained in:
parent
6621279a75
commit
a6180ede5c
@ -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| {
|
||||||
|
@ -17,22 +17,6 @@ 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;
|
||||||
|
|
||||||
pub enum LangItemGroup {
|
|
||||||
Op,
|
|
||||||
Fn,
|
|
||||||
}
|
|
||||||
|
|
||||||
const NUM_GROUPS: usize = 2;
|
|
||||||
|
|
||||||
macro_rules! expand_group {
|
|
||||||
() => {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
($group:expr) => {
|
|
||||||
Some($group)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// All of the language items, defined or not.
|
/// All of the language items, defined or not.
|
||||||
/// Defined lang items can come from the current crate or its dependencies.
|
/// Defined lang items can come from the current crate or its dependencies.
|
||||||
#[derive(HashStable_Generic, Debug)]
|
#[derive(HashStable_Generic, Debug)]
|
||||||
@ -42,21 +26,12 @@ pub struct LanguageItems {
|
|||||||
items: [Option<DefId>; std::mem::variant_count::<LangItem>()],
|
items: [Option<DefId>; std::mem::variant_count::<LangItem>()],
|
||||||
/// Lang items that were not found during collection.
|
/// Lang items that were not found during collection.
|
||||||
pub missing: Vec<LangItem>,
|
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.
|
/// Construct an empty collection of lang items and no missing ones.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
const EMPTY: Vec<DefId> = Vec::new();
|
Self { items: [None; std::mem::variant_count::<LangItem>()], missing: Vec::new() }
|
||||||
|
|
||||||
Self {
|
|
||||||
items: [None; std::mem::variant_count::<LangItem>()],
|
|
||||||
missing: Vec::new(),
|
|
||||||
groups: [EMPTY; NUM_GROUPS],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, item: LangItem) -> Option<DefId> {
|
pub fn get(&self, item: LangItem) -> Option<DefId> {
|
||||||
@ -86,7 +61,7 @@ impl LanguageItems {
|
|||||||
// 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! {
|
||||||
@ -120,15 +95,6 @@ macro_rules! language_item_table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The [group](LangItemGroup) that this lang item belongs to,
|
|
||||||
/// or `None` if it doesn't belong to a group.
|
|
||||||
pub fn group(self) -> Option<LangItemGroup> {
|
|
||||||
use LangItemGroup::*;
|
|
||||||
match self {
|
|
||||||
$( LangItem::$variant => expand_group!($($group)*), )*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn target(self) -> Target {
|
pub fn target(self) -> Target {
|
||||||
match self {
|
match self {
|
||||||
$( LangItem::$variant => $target, )*
|
$( LangItem::$variant => $target, )*
|
||||||
@ -143,11 +109,6 @@ macro_rules! language_item_table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LanguageItems {
|
impl LanguageItems {
|
||||||
/// 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> {
|
||||||
@ -209,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;
|
||||||
@ -242,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;
|
||||||
|
|
||||||
@ -254,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.
|
||||||
@ -351,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,
|
||||||
|
];
|
||||||
|
@ -140,9 +140,6 @@ impl<'tcx> LanguageItemCollector<'tcx> {
|
|||||||
|
|
||||||
// Matched.
|
// Matched.
|
||||||
self.items.set(lang_item, item_def_id);
|
self.items.set(lang_item, item_def_id);
|
||||||
if let Some(group) = lang_item.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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user