Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make lang items private #73500

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/librustc_codegen_llvm/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use rustc_data_structures::base_n;
use rustc_data_structures::const_cstr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_hir::LangItemRecord;
use rustc_middle::bug;
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::ty::layout::{HasParamEnv, LayoutError, TyAndLayout};
Expand Down Expand Up @@ -340,7 +341,7 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}
let tcx = self.tcx;
let llfn = match tcx.lang_items().eh_personality() {
Some(def_id) if !wants_msvc_seh(self.sess()) => self.get_fn_addr(
LangItemRecord::Present(def_id) if !wants_msvc_seh(self.sess()) => self.get_fn_addr(
ty::Instance::resolve(
tcx,
ty::ParamEnv::reveal_all(),
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_codegen_llvm/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::MemFlags;
use rustc_hir as hir;
use rustc_hir::LangItemRecord;
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
use rustc_middle::ty::{self, Ty};
use rustc_middle::{bug, span_bug};
Expand Down Expand Up @@ -1009,11 +1010,11 @@ fn codegen_gnu_try(
let lpad_ty = bx.type_struct(&[bx.type_i8p(), bx.type_i32()], false);
let vals = catch.landing_pad(lpad_ty, bx.eh_personality(), 1);
let tydesc = match bx.tcx().lang_items().eh_catch_typeinfo() {
Some(tydesc) => {
LangItemRecord::Present(tydesc) => {
let tydesc = bx.get_static(tydesc);
bx.bitcast(tydesc, bx.type_i8p())
}
None => bx.const_null(bx.type_i8p()),
_ => bx.const_null(bx.type_i8p()),
};
catch.add_clause(vals, tydesc);
let ptr = catch.extract_value(vals, 0);
Expand Down
8 changes: 5 additions & 3 deletions src/librustc_codegen_ssa/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::Node;
use rustc_hir::{LangItemRecord, Node};
use rustc_index::vec::IndexVec;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::{
Expand Down Expand Up @@ -304,7 +304,9 @@ fn upstream_monomorphizations_provider(
let (def_id, substs) = match *exported_symbol {
ExportedSymbol::Generic(def_id, substs) => (def_id, substs),
ExportedSymbol::DropGlue(ty) => {
if let Some(drop_in_place_fn_def_id) = drop_in_place_fn_def_id {
if let LangItemRecord::Present(drop_in_place_fn_def_id) =
drop_in_place_fn_def_id
{
(drop_in_place_fn_def_id, tcx.intern_substs(&[ty.into()]))
} else {
// `drop_in_place` in place does not exist, don't try
Expand Down Expand Up @@ -351,7 +353,7 @@ fn upstream_drop_glue_for_provider<'tcx>(
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
) -> Option<CrateNum> {
if let Some(def_id) = tcx.lang_items().drop_in_place_fn() {
if let LangItemRecord::Present(def_id) = tcx.lang_items().drop_in_place_fn() {
tcx.upstream_monomorphizations_for(def_id).and_then(|monos| monos.get(&substs).cloned())
} else {
None
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_codegen_ssa/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use rustc_data_structures::profiling::print_time_passes_entry;
use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
use rustc_hir::lang_items::StartFnLangItem;
use rustc_hir::LangItemRecord;
use rustc_index::vec::Idx;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::cstore::EncodedMetadata;
Expand Down Expand Up @@ -458,7 +458,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);

let (start_fn, args) = if use_start_lang_item {
let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None);
let start_def_id = cx.tcx().lang_items().start_fn().require(&cx.tcx(), None);
let start_fn = cx.get_fn_addr(
ty::Instance::resolve(
cx.tcx(),
Expand Down Expand Up @@ -837,7 +837,7 @@ impl CrateInfo {
}
let missing = tcx.missing_lang_items(cnum);
for &item in missing.iter() {
if let Ok(id) = lang_items.require(item) {
if let LangItemRecord::Present(id) = lang_items.get(item) {
info.lang_item_to_crate.insert(item, id.krate);
}
}
Expand Down
8 changes: 1 addition & 7 deletions src/librustc_codegen_ssa/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,7 @@ mod temp_stable_hash_impls {
}

pub fn langcall(tcx: TyCtxt<'_>, span: Option<Span>, msg: &str, li: LangItem) -> DefId {
tcx.lang_items().require(li).unwrap_or_else(|s| {
let msg = format!("{} {}", msg, s);
match span {
Some(span) => tcx.sess.span_fatal(span, &msg[..]),
None => tcx.sess.fatal(&msg[..]),
}
})
tcx.lang_items().get(li).require_with(&tcx, span, |err| format!("{} {}", msg, err))
}

// To avoid UB from LLVM, these two functions mask RHS with an
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/mir/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
_ => None,
};
if let Some((def_id, args)) = check {
if Some(def_id) == self.fx.cx.tcx().lang_items().box_free_fn() {
if self.fx.cx.tcx().lang_items().box_free_fn().has_def_id(def_id) {
// box_free(x) shares with `drop x` the property that it
// is not guaranteed to be statically dominated by the
// definition of x, so x must always be in an alloca.
Expand Down
13 changes: 6 additions & 7 deletions src/librustc_codegen_ssa/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::traits::*;
use crate::MemFlags;

use rustc_apfloat::{ieee, Float, Round, Status};
use rustc_hir::lang_items::ExchangeMallocFnLangItem;
use rustc_middle::mir;
use rustc_middle::ty::cast::{CastTy, IntTy};
use rustc_middle::ty::layout::HasTyCtxt;
Expand Down Expand Up @@ -508,12 +507,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let llty_ptr = bx.cx().backend_type(box_layout);

// Allocate space:
let def_id = match bx.tcx().lang_items().require(ExchangeMallocFnLangItem) {
Ok(id) => id,
Err(s) => {
bx.cx().sess().fatal(&format!("allocation of `{}` {}", box_layout.ty, s));
}
};
let def_id = bx.tcx().lang_items().exchange_malloc_fn().require_with(
&bx.tcx(),
None,
|err| format!("allocation of `{}` {}", box_layout.ty, err),
);

let instance = ty::Instance::mono(bx.tcx(), def_id);
let r = bx.cx().get_fn_addr(instance);
let call = bx.call(r, &[llsize, llalign], None);
Expand Down
120 changes: 102 additions & 18 deletions src/librustc_hir/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,44 +47,122 @@ macro_rules! language_item_table {
}
}

pub trait MissingLangItemHandler {
fn span_fatal(&self, span: Span, msg: &str) -> !;

fn fatal(&self, msg: &str) -> !;
}

/// Represents the presence or possibly lack-of a particular lang item.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum LangItemRecord {
/// The lang item is present and has been assigned this `DefId`.
Present(DefId),
/// The lang item is missing (we keep the variant representing the item around
/// in case we need it for error reporting etc.).
Missing(LangItem),
}

impl LangItemRecord {
#[inline]
pub fn has_def_id(self, def_id: DefId) -> bool {
match self {
LangItemRecord::Present(assigned_id) if assigned_id == def_id => true,
_ => false,
}
}

#[inline]
pub fn require<H: MissingLangItemHandler>(self, handler: &H, span: Option<Span>) -> DefId {
self.require_with(handler, span, str::to_string)
}

pub fn require_with<H, F>(self, handler: &H, span: Option<Span>, err: F) -> DefId
where
H: MissingLangItemHandler,
F: Fn(&str) -> String,
{
match self {
LangItemRecord::Present(assigned_id) => assigned_id,
LangItemRecord::Missing(it) => {
let msg = err(&format!("requires `{}` lang_item", it.name()));
if let Some(span) = span {
handler.span_fatal(span, &msg)
} else {
handler.fatal(&msg)
}
}
}
}

#[inline]
pub fn is_present(self) -> bool {
match self {
LangItemRecord::Present(_) => true,
_ => false,
}
}

#[inline]
pub fn is_missing(self) -> bool {
!self.is_present()
}

#[inline]
pub fn is_local(self) -> bool {
match self {
LangItemRecord::Present(assigned_id) => assigned_id.is_local(),
_ => false,
}
}
}

#[derive(HashStable_Generic)]
pub struct LanguageItems {
/// Mappings from lang items to their possibly found `DefId`s.
/// Mappings from lang items to their corresponding record.
/// 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>,
// FIXME(doctorn) use Box<[LangItemRecord; std::mem::num_variants::<LangItem>()]>
pub items: Vec<LangItemRecord>,
}

impl LanguageItems {
/// Construct an empty collection of lang items and no missing ones.
/// Construct an empty collection of lang items. We initially assume that all items are
/// missing.
pub fn new() -> Self {
fn init_none(_: LangItem) -> Option<DefId> { None }
fn init_missing(it: LangItem) -> LangItemRecord {
LangItemRecord::Missing(it)
}

Self {
items: vec![$(init_none($variant)),*],
missing: Vec::new(),
items: vec![$(init_missing($variant)),*],
}
}

/// Returns the mappings to the possibly found `DefId`s for each lang item.
pub fn items(&self) -> &[Option<DefId>] {
/// Returns the `LangItemRecord` of each lang item.
pub fn items(&self) -> &[LangItemRecord] {
&*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 message as a string.
pub fn require(&self, it: LangItem) -> Result<DefId, String> {
self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name()))
/// Returns the missing lang items.
pub fn missing(&self) -> impl Iterator<Item = LangItem> + '_ {
self.items.iter().copied().filter_map(|record| {
match record {
LangItemRecord::Missing(it) => Some(it),
_ => None,
}
})
}

/// Returns the `LangItemRecord` of a specific lang item.
pub fn get(&self, it: LangItem) -> LangItemRecord {
self.items[it as usize]
}

$(
/// Returns the corresponding `DefId` for the lang item
/// Returns the `LangItemRecord` for the lang item.
#[doc = $name]
/// if it exists.
#[allow(dead_code)]
pub fn $method(&self) -> Option<DefId> {
pub fn $method(&self) -> LangItemRecord {
self.items[$variant as usize]
}
)*
Expand All @@ -109,6 +187,12 @@ impl<CTX> HashStable<CTX> for LangItem {
}
}

impl<CTX> HashStable<CTX> for LangItemRecord {
fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) {
::std::hash::Hash::hash(self, hasher);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this implementation correct? LangItemRecord can contain a DefId for which hash is not stable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch.

}

/// Extracts the first `lang = "$name"` out of a list of attributes.
/// The attributes `#[panic_handler]` and `#[alloc_error_handler]`
/// are also extracted out when found.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_hir/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ pub mod weak_lang_items;

pub use hir::*;
pub use hir_id::*;
pub use lang_items::{LangItem, LanguageItems};
pub use lang_items::{LangItem, LangItemRecord, LanguageItems, MissingLangItemHandler};
pub use stable_hash_impls::HashStableContext;
pub use target::{MethodKind, Target};
4 changes: 1 addition & 3 deletions src/librustc_hir/weak_lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> {

impl LanguageItems {
pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool {
let did = Some(item_def_id);

$(self.$name() == did)||*
$(self.$name().has_def_id(item_def_id))||*
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/librustc_metadata/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc_hir::definitions::DefPathTable;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
use rustc_hir::lang_items;
use rustc_hir::{AnonConst, GenericParamKind};
use rustc_hir::{AnonConst, GenericParamKind, LangItemRecord};
use rustc_index::vec::Idx;
use rustc_middle::hir::map::Map;
use rustc_middle::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLib};
Expand Down Expand Up @@ -1155,7 +1155,7 @@ impl EncodeContext<'tcx> {
// "unsized info", else just store None
let coerce_unsized_info =
trait_ref.and_then(|t| {
if Some(t.def_id) == self.tcx.lang_items().coerce_unsized_trait() {
if self.tcx.lang_items().coerce_unsized_trait().has_def_id(t.def_id) {
Some(self.tcx.at(item.span).coerce_unsized_info(def_id))
} else {
None
Expand Down Expand Up @@ -1441,7 +1441,7 @@ impl EncodeContext<'tcx> {
let lang_items = tcx.lang_items();
let lang_items = lang_items.items().iter();
self.lazy(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
if let Some(def_id) = opt_def_id {
if let LangItemRecord::Present(def_id) = opt_def_id {
if def_id.is_local() {
return Some((def_id.index, i));
}
Expand All @@ -1452,7 +1452,7 @@ impl EncodeContext<'tcx> {

fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> {
let tcx = self.tcx;
self.lazy(&tcx.lang_items().missing)
self.lazy(tcx.lang_items().missing())
}

/// Encodes an index, mapping each trait to its (local) implementations.
Expand Down
Loading