1
Fork 0

Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2025-02-01 05:13:09 +00:00
commit aa74d61665
374 changed files with 3634 additions and 2231 deletions

View file

@ -4234,6 +4234,7 @@ name = "rustc_monomorphize"
version = "0.0.0"
dependencies = [
"rustc_abi",
"rustc_ast",
"rustc_attr_parsing",
"rustc_data_structures",
"rustc_errors",
@ -4243,6 +4244,7 @@ dependencies = [
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_symbol_mangling",
"rustc_target",
"serde",
"serde_json",

View file

@ -79,6 +79,7 @@ pub struct AutoDiffItem {
pub target: String,
pub attrs: AutoDiffAttrs,
}
#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct AutoDiffAttrs {
/// Conceptually either forward or reverse mode AD, as described in various autodiff papers and
@ -231,7 +232,7 @@ impl AutoDiffAttrs {
self.ret_activity == DiffActivity::ActiveOnly
}
pub fn error() -> Self {
pub const fn error() -> Self {
AutoDiffAttrs {
mode: DiffMode::Error,
ret_activity: DiffActivity::None,

View file

@ -3777,7 +3777,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let tcx = self.infcx.tcx;
if let Some(Terminator { kind: TerminatorKind::Call { call_source, fn_span, .. }, .. }) =
&self.body[loan.reserve_location.block].terminator
&& let Some((method_did, method_args)) = rustc_middle::util::find_self_call(
&& let Some((method_did, method_args)) = mir::find_self_call(
tcx,
self.body,
loan.assigned_place.local,

View file

@ -17,7 +17,7 @@ use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement,
StatementKind, Terminator, TerminatorKind,
StatementKind, Terminator, TerminatorKind, find_self_call,
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, Ty, TyCtxt};
@ -1016,12 +1016,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
kind: TerminatorKind::Call { fn_span, call_source, .. }, ..
}) = &self.body[location.block].terminator
{
let Some((method_did, method_args)) = rustc_middle::util::find_self_call(
self.infcx.tcx,
self.body,
target_temp,
location.block,
) else {
let Some((method_did, method_args)) =
find_self_call(self.infcx.tcx, self.body, target_temp, location.block)
else {
return normal_ret;
};

View file

@ -417,6 +417,16 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
Some(source_info.span),
);
}
AssertKind::NullPointerDereference => {
let location = fx.get_caller_location(source_info).load_scalar(fx);
codegen_panic_inner(
fx,
rustc_hir::LangItem::PanicNullPointerDereference,
&[location],
Some(source_info.span),
)
}
_ => {
let location = fx.get_caller_location(source_info).load_scalar(fx);

View file

@ -6,7 +6,7 @@ use cranelift_module::*;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{AllocId, GlobalAlloc, Scalar, read_target_uint};
use rustc_middle::ty::{Binder, ExistentialTraitRef, ScalarInt};
use rustc_middle::ty::{ExistentialTraitRef, ScalarInt};
use crate::prelude::*;
@ -167,7 +167,9 @@ pub(crate) fn codegen_const_value<'tcx>(
&mut fx.constants_cx,
fx.module,
ty,
dyn_ty.principal(),
dyn_ty.principal().map(|principal| {
fx.tcx.instantiate_bound_regions_with_erased(principal)
}),
);
let local_data_id =
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
@ -243,7 +245,7 @@ pub(crate) fn data_id_for_vtable<'tcx>(
cx: &mut ConstantCx,
module: &mut dyn Module,
ty: Ty<'tcx>,
trait_ref: Option<Binder<'tcx, ExistentialTraitRef<'tcx>>>,
trait_ref: Option<ExistentialTraitRef<'tcx>>,
) -> DataId {
let alloc_id = tcx.vtable_allocation((ty, trait_ref));
data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not)
@ -460,9 +462,15 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
GlobalAlloc::Memory(target_alloc) => {
data_id_for_alloc_id(cx, module, alloc_id, target_alloc.inner().mutability)
}
GlobalAlloc::VTable(ty, dyn_ty) => {
data_id_for_vtable(tcx, cx, module, ty, dyn_ty.principal())
}
GlobalAlloc::VTable(ty, dyn_ty) => data_id_for_vtable(
tcx,
cx,
module,
ty,
dyn_ty
.principal()
.map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
),
GlobalAlloc::Static(def_id) => {
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
{

View file

@ -61,7 +61,12 @@ pub(crate) fn unsized_info<'tcx>(
old_info
}
}
(_, ty::Dynamic(data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()),
(_, ty::Dynamic(data, ..)) => crate::vtable::get_vtable(
fx,
source,
data.principal()
.map(|principal| fx.tcx.instantiate_bound_regions_with_erased(principal)),
),
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
}
}

View file

@ -90,7 +90,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
pub(crate) fn get_vtable<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
ty: Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
) -> Value {
let data_id = data_id_for_vtable(fx.tcx, &mut fx.constants_cx, fx.module, ty, trait_ref);
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);

View file

@ -234,7 +234,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
GlobalAlloc::VTable(ty, dyn_ty) => {
let alloc = self
.tcx
.global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
.global_alloc(self.tcx.vtable_allocation((
ty,
dyn_ty.principal().map(|principal| {
self.tcx.instantiate_bound_regions_with_erased(principal)
}),
)))
.unwrap_memory();
let init = const_alloc_to_gcc(self, alloc);
self.static_addr_of(init, alloc.inner().align, None)

View file

@ -14,7 +14,7 @@ use rustc_middle::ty::layout::{
FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError,
LayoutOfHelpers,
};
use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::source_map::respan;
use rustc_span::{DUMMY_SP, Span};
@ -90,7 +90,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
/// Cache generated vtables
pub vtables:
RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
// TODO(antoyo): improve the SSA API to not require those.
/// Mapping from function pointer type to indexes of on stack parameters.
@ -401,7 +401,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn vtables(
&self,
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
&self.vtables
}

View file

@ -7,7 +7,7 @@ use rustc_data_structures::sync::Lrc;
use rustc_index::bit_set::DenseBitSet;
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::{self, Body, SourceScope};
use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty};
use rustc_session::config::DebugInfo;
use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol};
use rustc_target::abi::Size;
@ -214,7 +214,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn create_vtable_debuginfo(
&self,
_ty: Ty<'tcx>,
_trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
_trait_ref: Option<ExistentialTraitRef<'tcx>>,
_vtable: Self::Value,
) {
// TODO(antoyo)

View file

@ -3,8 +3,6 @@
// Run-time:
// status: 0
#![feature(const_black_box)]
/*
* Code
*/

View file

@ -62,8 +62,8 @@ fn generate_enzyme_call<'ll>(
// add outer_fn name to ad_name to make it unique, in case users apply autodiff to multiple
// functions. Unwrap will only panic, if LLVM gave us an invalid string.
let name = llvm::get_value_name(outer_fn);
let outer_fn_name = std::ffi::CStr::from_bytes_with_nul(name).unwrap().to_str().unwrap();
ad_name.push_str(outer_fn_name.to_string().as_str());
let outer_fn_name = std::str::from_utf8(name).unwrap();
ad_name.push_str(outer_fn_name);
// Let us assume the user wrote the following function square:
//
@ -255,14 +255,14 @@ fn generate_enzyme_call<'ll>(
// have no debug info to copy, which would then be ok.
trace!("no dbg info");
}
// Now that we copied the metadata, get rid of dummy code.
llvm::LLVMRustEraseInstBefore(entry, last_inst);
llvm::LLVMRustEraseInstFromParent(last_inst);
if cx.val_ty(outer_fn) != cx.type_void() {
builder.ret(call);
} else {
// Now that we copied the metadata, get rid of dummy code.
llvm::LLVMRustEraseInstUntilInclusive(entry, last_inst);
if cx.val_ty(call) == cx.type_void() {
builder.ret_void();
} else {
builder.ret(call);
}
// Let's crash in case that we messed something up above and generated invalid IR.

View file

@ -314,7 +314,12 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
GlobalAlloc::VTable(ty, dyn_ty) => {
let alloc = self
.tcx
.global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
.global_alloc(self.tcx.vtable_allocation((
ty,
dyn_ty.principal().map(|principal| {
self.tcx.instantiate_bound_regions_with_erased(principal)
}),
)))
.unwrap_memory();
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
let value = self.static_addr_of_impl(init, alloc.inner().align, None);

View file

@ -77,8 +77,7 @@ pub(crate) struct CodegenCx<'ll, 'tcx> {
/// Cache instances of monomorphic and polymorphic items
pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
/// Cache generated vtables
pub vtables:
RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>,
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>>,
/// Cache of constant strings,
pub const_str_cache: RefCell<FxHashMap<String, &'ll Value>>,
@ -663,15 +662,14 @@ impl<'ll> SimpleCx<'ll> {
impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn vtables(
&self,
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>
{
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>> {
&self.vtables
}
fn apply_vcall_visibility_metadata(
&self,
ty: Ty<'tcx>,
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
vtable: &'ll Value,
) {
apply_vcall_visibility_metadata(self, ty, poly_trait_ref, vtable);

View file

@ -298,7 +298,7 @@ struct UsageSets<'tcx> {
/// Prepare sets of definitions that are relevant to deciding whether something
/// is an "unused function" for coverage purposes.
fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> {
let MonoItemPartitions { all_mono_items, codegen_units } =
let MonoItemPartitions { all_mono_items, codegen_units, .. } =
tcx.collect_and_partition_mono_items(());
// Obtain a MIR body for each function participating in codegen, via an

View file

@ -13,7 +13,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{
self, AdtKind, CoroutineArgsExt, Instance, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
};
use rustc_session::config::{self, DebugInfo, Lto};
use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Symbol, hygiene};
@ -1399,7 +1399,7 @@ pub(crate) fn build_global_var_di_node<'ll>(
fn build_vtable_type_di_node<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
ty: Ty<'tcx>,
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
) -> &'ll DIType {
let tcx = cx.tcx;
@ -1510,7 +1510,7 @@ fn find_vtable_behind_cast<'ll>(vtable: &'ll Value) -> &'ll Value {
pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
ty: Ty<'tcx>,
trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
trait_ref: Option<ExistentialTraitRef<'tcx>>,
vtable: &'ll Value,
) {
// FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
@ -1531,7 +1531,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
let vtable = find_vtable_behind_cast(vtable);
let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty);
let trait_ref_self = cx.tcx.erase_regions(trait_ref_self);
let trait_def_id = trait_ref_self.def_id();
let trait_def_id = trait_ref_self.def_id;
let trait_vis = cx.tcx.visibility(trait_def_id);
let cgus = cx.sess().codegen_units().as_usize();
@ -1590,7 +1590,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
pub(crate) fn create_vtable_di_node<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
ty: Ty<'tcx>,
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
vtable: &'ll Value,
) {
if cx.dbg_cx.is_none() {

View file

@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::HashStable;
use rustc_middle::bug;
use rustc_middle::ty::{self, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_middle::ty::{self, ExistentialTraitRef, Ty, TyCtxt};
use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
use crate::common::{AsCCharPtr, CodegenCx};
@ -44,7 +44,7 @@ pub(super) enum UniqueTypeId<'tcx> {
/// The ID for the additional wrapper struct type describing an enum variant in CPP-like mode.
VariantStructTypeCppLikeWrapper(Ty<'tcx>, VariantIdx, private::HiddenZst),
/// The ID of the artificial type we create for VTables.
VTableTy(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>, private::HiddenZst),
VTableTy(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>, private::HiddenZst),
}
impl<'tcx> UniqueTypeId<'tcx> {
@ -88,7 +88,7 @@ impl<'tcx> UniqueTypeId<'tcx> {
pub(crate) fn for_vtable_ty(
tcx: TyCtxt<'tcx>,
self_type: Ty<'tcx>,
implemented_trait: Option<PolyExistentialTraitRef<'tcx>>,
implemented_trait: Option<ExistentialTraitRef<'tcx>>,
) -> Self {
assert_eq!(
self_type,

View file

@ -588,7 +588,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn create_vtable_debuginfo(
&self,
ty: Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
vtable: Self::Value,
) {
metadata::create_vtable_di_node(self, ty, trait_ref, vtable)

View file

@ -7,11 +7,13 @@ use crate::llvm::Bool;
extern "C" {
// Enzyme
pub fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
pub fn LLVMRustEraseInstBefore(BB: &BasicBlock, I: &Value);
pub fn LLVMRustEraseInstUntilInclusive(BB: &BasicBlock, I: &Value);
pub fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
pub fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
pub fn LLVMRustEraseInstFromParent(V: &Value);
pub fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
pub fn LLVMDumpModule(M: &Module);
pub fn LLVMDumpValue(V: &Value);
pub fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
pub fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;

View file

@ -16,6 +16,8 @@ codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$erro
codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
codegen_ssa_autodiff_without_lto = using the autodiff feature requires using fat-lto
codegen_ssa_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty
codegen_ssa_cgu_not_recorded =

View file

@ -7,6 +7,7 @@ use std::sync::mpsc::{Receiver, Sender, channel};
use std::{fs, io, mem, str, thread};
use rustc_ast::attr;
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::jobserver::{self, Acquired};
use rustc_data_structures::memmap::Mmap;
@ -40,7 +41,7 @@ use tracing::debug;
use super::link::{self, ensure_removed};
use super::lto::{self, SerializedModule};
use super::symbol_export::symbol_name_for_instance_in_crate;
use crate::errors::ErrorCreatingRemarkDir;
use crate::errors::{AutodiffWithoutLto, ErrorCreatingRemarkDir};
use crate::traits::*;
use crate::{
CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
@ -118,6 +119,7 @@ pub struct ModuleConfig {
pub merge_functions: bool,
pub emit_lifetime_markers: bool,
pub llvm_plugins: Vec<String>,
pub autodiff: Vec<config::AutoDiff>,
}
impl ModuleConfig {
@ -266,6 +268,7 @@ impl ModuleConfig {
emit_lifetime_markers: sess.emit_lifetime_markers(),
llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]),
autodiff: if_regular!(sess.opts.unstable_opts.autodiff.clone(), vec![]),
}
}
@ -389,6 +392,7 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
fn generate_lto_work<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
autodiff: Vec<AutoDiffItem>,
needs_fat_lto: Vec<FatLtoInput<B>>,
needs_thin_lto: Vec<(String, B::ThinBuffer)>,
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
@ -397,11 +401,19 @@ fn generate_lto_work<B: ExtraBackendMethods>(
if !needs_fat_lto.is_empty() {
assert!(needs_thin_lto.is_empty());
let module =
let mut module =
B::run_fat_lto(cgcx, needs_fat_lto, import_only_modules).unwrap_or_else(|e| e.raise());
if cgcx.lto == Lto::Fat {
let config = cgcx.config(ModuleKind::Regular);
module = unsafe { module.autodiff(cgcx, autodiff, config).unwrap() };
}
// We are adding a single work item, so the cost doesn't matter.
vec![(WorkItem::LTO(module), 0)]
} else {
if !autodiff.is_empty() {
let dcx = cgcx.create_dcx();
dcx.handle().emit_fatal(AutodiffWithoutLto {});
}
assert!(needs_fat_lto.is_empty());
let (lto_modules, copy_jobs) = B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules)
.unwrap_or_else(|e| e.raise());
@ -1021,6 +1033,9 @@ pub(crate) enum Message<B: WriteBackendMethods> {
/// Sent from a backend worker thread.
WorkItem { result: Result<WorkItemResult<B>, Option<WorkerFatalError>>, worker_id: usize },
/// A vector containing all the AutoDiff tasks that we have to pass to Enzyme.
AddAutoDiffItems(Vec<AutoDiffItem>),
/// The frontend has finished generating something (backend IR or a
/// post-LTO artifact) for a codegen unit, and it should be passed to the
/// backend. Sent from the main thread.
@ -1348,6 +1363,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
// This is where we collect codegen units that have gone all the way
// through codegen and LLVM.
let mut autodiff_items = Vec::new();
let mut compiled_modules = vec![];
let mut compiled_allocator_module = None;
let mut needs_link = Vec::new();
@ -1459,9 +1475,13 @@ fn start_executing_work<B: ExtraBackendMethods>(
let needs_thin_lto = mem::take(&mut needs_thin_lto);
let import_only_modules = mem::take(&mut lto_import_only_modules);
for (work, cost) in
generate_lto_work(&cgcx, needs_fat_lto, needs_thin_lto, import_only_modules)
{
for (work, cost) in generate_lto_work(
&cgcx,
autodiff_items.clone(),
needs_fat_lto,
needs_thin_lto,
import_only_modules,
) {
let insertion_index = work_items
.binary_search_by_key(&cost, |&(_, cost)| cost)
.unwrap_or_else(|e| e);
@ -1596,6 +1616,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
main_thread_state = MainThreadState::Idle;
}
Message::AddAutoDiffItems(mut items) => {
autodiff_items.append(&mut items);
}
Message::CodegenComplete => {
if codegen_state != Aborted {
codegen_state = Completed;
@ -2070,6 +2094,10 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
drop(self.coordinator.sender.send(Box::new(Message::CodegenComplete::<B>)));
}
pub(crate) fn submit_autodiff_items(&self, items: Vec<AutoDiffItem>) {
drop(self.coordinator.sender.send(Box::new(Message::<B>::AddAutoDiffItems(items))));
}
pub(crate) fn check_for_errors(&self, sess: &Session) {
self.shared_emitter_main.check(sess, false);
}

View file

@ -18,14 +18,13 @@ use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, Debugger
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_middle::middle::{exported_symbols, lang_items};
use rustc_middle::mir::BinOp;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions};
use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_session::Session;
use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
use rustc_span::{DUMMY_SP, Symbol, sym};
use rustc_trait_selection::infer::at::ToTrace;
use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
use tracing::{debug, info};
@ -129,14 +128,9 @@ pub fn validate_trivial_unsize<'tcx>(
BoundRegionConversionTime::HigherRankedType,
hr_source_principal,
);
let Ok(()) = ocx.eq_trace(
let Ok(()) = ocx.eq(
&ObligationCause::dummy(),
param_env,
ToTrace::to_trace(
&ObligationCause::dummy(),
hr_target_principal,
hr_source_principal,
),
target_principal,
source_principal,
) else {
@ -211,7 +205,12 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
old_info
}
}
(_, ty::Dynamic(data, _, _)) => meth::get_vtable(cx, source, data.principal()),
(_, ty::Dynamic(data, _, _)) => meth::get_vtable(
cx,
source,
data.principal()
.map(|principal| bx.tcx().instantiate_bound_regions_with_erased(principal)),
),
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
}
}
@ -624,7 +623,9 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
// Run the monomorphization collector and partition the collected items into
// codegen units.
let codegen_units = tcx.collect_and_partition_mono_items(()).codegen_units;
let MonoItemPartitions { codegen_units, autodiff_items, .. } =
tcx.collect_and_partition_mono_items(());
let autodiff_fncs = autodiff_items.to_vec();
// Force all codegen_unit queries so they are already either red or green
// when compile_codegen_unit accesses them. We are not able to re-execute
@ -695,6 +696,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
);
}
if !autodiff_fncs.is_empty() {
ongoing_codegen.submit_autodiff_items(autodiff_fncs);
}
// For better throughput during parallel processing by LLVM, we used to sort
// CGUs largest to smallest. This would lead to better thread utilization
// by, for example, preventing a large CGU from being processed last and

View file

@ -1,5 +1,10 @@
use std::str::FromStr;
use rustc_ast::attr::list_contains_name;
use rustc_ast::{MetaItemInner, attr};
use rustc_ast::expand::autodiff_attrs::{
AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
};
use rustc_ast::{MetaItem, MetaItemInner, attr};
use rustc_attr_parsing::{InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::codes::*;
@ -13,6 +18,7 @@ use rustc_middle::middle::codegen_fn_attrs::{
};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::{self as ty, TyCtxt};
use rustc_session::parse::feature_err;
use rustc_session::{Session, lint};
@ -65,6 +71,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
}
// If our rustc version supports autodiff/enzyme, then we call our handler
// to check for any `#[rustc_autodiff(...)]` attributes.
if cfg!(llvm_enzyme) {
let ad = autodiff_attrs(tcx, did.into());
codegen_fn_attrs.autodiff_item = ad;
}
// When `no_builtins` is applied at the crate level, we should add the
// `no-builtins` attribute to each function to ensure it takes effect in LTO.
let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
@ -856,6 +869,109 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
}
}
/// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)]
/// macros. There are two forms. The pure one without args to mark primal functions (the functions
/// being differentiated). The other form is #[rustc_autodiff(Mode, ActivityList)] on top of the
/// placeholder functions. We wrote the rustc_autodiff attributes ourself, so this should never
/// panic, unless we introduced a bug when parsing the autodiff macro.
fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
let attrs = tcx.get_attrs(id, sym::rustc_autodiff);
let attrs =
attrs.filter(|attr| attr.name_or_empty() == sym::rustc_autodiff).collect::<Vec<_>>();
// check for exactly one autodiff attribute on placeholder functions.
// There should only be one, since we generate a new placeholder per ad macro.
// FIXME(ZuseZ4): re-enable this check. Currently we add multiple, which doesn't cause harm but
// looks strange e.g. under cargo-expand.
let attr = match &attrs[..] {
[] => return None,
[attr] => attr,
// These two attributes are the same and unfortunately duplicated due to a previous bug.
[attr, _attr2] => attr,
_ => {
//FIXME(ZuseZ4): Once we fixed our parser, we should also prohibit the two-attribute
//branch above.
span_bug!(attrs[1].span, "cg_ssa: rustc_autodiff should only exist once per source");
}
};
let list = attr.meta_item_list().unwrap_or_default();
// empty autodiff attribute macros (i.e. `#[autodiff]`) are used to mark source functions
if list.is_empty() {
return Some(AutoDiffAttrs::source());
}
let [mode, input_activities @ .., ret_activity] = &list[..] else {
span_bug!(attr.span, "rustc_autodiff attribute must contain mode and activities");
};
let mode = if let MetaItemInner::MetaItem(MetaItem { path: ref p1, .. }) = mode {
p1.segments.first().unwrap().ident
} else {
span_bug!(attr.span, "rustc_autodiff attribute must contain mode");
};
// parse mode
let mode = match mode.as_str() {
"Forward" => DiffMode::Forward,
"Reverse" => DiffMode::Reverse,
"ForwardFirst" => DiffMode::ForwardFirst,
"ReverseFirst" => DiffMode::ReverseFirst,
_ => {
span_bug!(mode.span, "rustc_autodiff attribute contains invalid mode");
}
};
// First read the ret symbol from the attribute
let ret_symbol = if let MetaItemInner::MetaItem(MetaItem { path: ref p1, .. }) = ret_activity {
p1.segments.first().unwrap().ident
} else {
span_bug!(attr.span, "rustc_autodiff attribute must contain the return activity");
};
// Then parse it into an actual DiffActivity
let Ok(ret_activity) = DiffActivity::from_str(ret_symbol.as_str()) else {
span_bug!(ret_symbol.span, "invalid return activity");
};
// Now parse all the intermediate (input) activities
let mut arg_activities: Vec<DiffActivity> = vec![];
for arg in input_activities {
let arg_symbol = if let MetaItemInner::MetaItem(MetaItem { path: ref p2, .. }) = arg {
match p2.segments.first() {
Some(x) => x.ident,
None => {
span_bug!(
arg.span(),
"rustc_autodiff attribute must contain the input activity"
);
}
}
} else {
span_bug!(arg.span(), "rustc_autodiff attribute must contain the input activity");
};
match DiffActivity::from_str(arg_symbol.as_str()) {
Ok(arg_activity) => arg_activities.push(arg_activity),
Err(_) => {
span_bug!(arg_symbol.span, "invalid input activity");
}
}
}
for &input in &arg_activities {
if !valid_input_activity(mode, input) {
span_bug!(attr.span, "Invalid input activity {} for {} mode", input, mode);
}
}
if !valid_ret_activity(mode, ret_activity) {
span_bug!(attr.span, "Invalid return activity {} for {} mode", ret_activity, mode);
}
Some(AutoDiffAttrs { mode, ret_activity, input_activity: arg_activities })
}
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
}

View file

@ -507,7 +507,7 @@ pub enum VTableNameKind {
pub fn compute_debuginfo_vtable_name<'tcx>(
tcx: TyCtxt<'tcx>,
t: Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
kind: VTableNameKind,
) -> String {
let cpp_like_debuginfo = cpp_like_debuginfo(tcx);
@ -530,8 +530,8 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
}
if let Some(trait_ref) = trait_ref {
let trait_ref = tcx
.normalize_erasing_late_bound_regions(ty::TypingEnv::fully_monomorphized(), trait_ref);
let trait_ref =
tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref);
push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name);
visited.clear();
push_generic_params_internal(tcx, trait_ref.args, &mut vtable_name, &mut visited);

View file

@ -39,6 +39,10 @@ pub(crate) struct CguNotRecorded<'a> {
pub cgu_name: &'a str,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_autodiff_without_lto)]
pub struct AutodiffWithoutLto;
#[derive(Diagnostic)]
#[diag(codegen_ssa_unknown_reuse_kind)]
pub(crate) struct UnknownReuseKind {

View file

@ -1,5 +1,5 @@
use rustc_middle::bug;
use rustc_middle::ty::{self, GenericArgKind, Ty};
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt};
use rustc_session::config::Lto;
use rustc_symbol_mangling::typeid_for_trait_ref;
use rustc_target::callconv::FnAbi;
@ -72,12 +72,19 @@ impl<'a, 'tcx> VirtualIndex {
/// This takes a valid `self` receiver type and extracts the principal trait
/// ref of the type. Return `None` if there is no principal trait.
fn dyn_trait_in_self(ty: Ty<'_>) -> Option<ty::PolyExistentialTraitRef<'_>> {
fn dyn_trait_in_self<'tcx>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
) -> Option<ty::ExistentialTraitRef<'tcx>> {
for arg in ty.peel_refs().walk() {
if let GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Dynamic(data, _, _) = ty.kind()
{
return data.principal();
// FIXME(arbitrary_self_types): This is likely broken for receivers which
// have a "non-self" trait objects as a generic argument.
return data
.principal()
.map(|principal| tcx.instantiate_bound_regions_with_erased(principal));
}
}
@ -96,7 +103,7 @@ fn dyn_trait_in_self(ty: Ty<'_>) -> Option<ty::PolyExistentialTraitRef<'_>> {
pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
cx: &Cx,
ty: Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
) -> Cx::Value {
let tcx = cx.tcx();
@ -131,7 +138,7 @@ pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
if bx.cx().sess().opts.unstable_opts.virtual_function_elimination
&& bx.cx().sess().lto() == Lto::Fat
{
if let Some(trait_ref) = dyn_trait_in_self(ty) {
if let Some(trait_ref) = dyn_trait_in_self(bx.tcx(), ty) {
let typeid = bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), trait_ref)).unwrap();
let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
return func;

View file

@ -713,6 +713,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// and `#[track_caller]` adds an implicit third argument.
(LangItem::PanicMisalignedPointerDereference, vec![required, found, location])
}
AssertKind::NullPointerDereference => {
// It's `fn panic_null_pointer_dereference()`,
// `#[track_caller]` adds an implicit argument.
(LangItem::PanicNullPointerDereference, vec![location])
}
_ => {
// It's `pub fn panic_...()` and `#[track_caller]` adds an implicit argument.
(msg.panic_function(), vec![location])

View file

@ -2,7 +2,7 @@ use std::ops::Range;
use rustc_abi::Size;
use rustc_middle::mir;
use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty};
use rustc_span::{SourceFile, Span, Symbol};
use rustc_target::callconv::FnAbi;
@ -13,7 +13,7 @@ pub trait DebugInfoCodegenMethods<'tcx>: BackendTypes {
fn create_vtable_debuginfo(
&self,
ty: Ty<'tcx>,
trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
trait_ref: Option<ExistentialTraitRef<'tcx>>,
vtable: Self::Value,
);

View file

@ -10,11 +10,11 @@ use super::BackendTypes;
pub trait MiscCodegenMethods<'tcx>: BackendTypes {
fn vtables(
&self,
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>;
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), Self::Value>>;
fn apply_vcall_visibility_metadata(
&self,
_ty: Ty<'tcx>,
_poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
_poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
_vtable: Self::Value,
) {
}

View file

@ -634,7 +634,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, place) => {
// These are only inserted for slice length, so the place must already be indirect.
// This implies we do not have to worry about whether the borrow escapes.
assert!(place.is_indirect(), "fake borrows are always indirect");
if !place.is_indirect() {
self.tcx.dcx().span_delayed_bug(
self.body.source_info(location).span,
"fake borrows are always indirect",
);
}
}
Rvalue::Cast(

View file

@ -508,6 +508,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
found: eval_to_int(found)?,
}
}
NullPointerDereference => NullPointerDereference,
};
Err(ConstEvalErrKind::AssertFailure(err)).into()
}

View file

@ -5,6 +5,7 @@ use std::borrow::Cow;
use either::{Left, Right};
use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx};
use rustc_hir::def_id::DefId;
use rustc_middle::ty::layout::{FnAbiOf, IntegerExt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef};
use rustc_middle::{bug, mir, span_bug};
@ -693,25 +694,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
trace!("Virtual call dispatches to {fn_inst:#?}");
// We can also do the lookup based on `def_id` and `dyn_ty`, and check that that
// produces the same result.
if cfg!(debug_assertions) {
let tcx = *self.tcx;
let trait_def_id = tcx.trait_of_item(def_id).unwrap();
let virtual_trait_ref =
ty::TraitRef::from_method(tcx, trait_def_id, instance.args);
let existential_trait_ref =
ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
let concrete_method = Instance::expect_resolve_for_vtable(
tcx,
self.typing_env,
def_id,
instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
self.cur_span(),
);
assert_eq!(fn_inst, concrete_method);
}
self.assert_virtual_instance_matches_concrete(dyn_ty, def_id, instance, fn_inst);
// Adjust receiver argument. Layout can be any (thin) ptr.
let receiver_ty = Ty::new_mut_ptr(self.tcx.tcx, dyn_ty);
@ -744,6 +727,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
}
fn assert_virtual_instance_matches_concrete(
&self,
dyn_ty: Ty<'tcx>,
def_id: DefId,
virtual_instance: ty::Instance<'tcx>,
concrete_instance: ty::Instance<'tcx>,
) {
let tcx = *self.tcx;
let trait_def_id = tcx.trait_of_item(def_id).unwrap();
let virtual_trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, virtual_instance.args);
let existential_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
let concrete_method = Instance::expect_resolve_for_vtable(
tcx,
self.typing_env,
def_id,
virtual_instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
self.cur_span(),
);
assert_eq!(concrete_instance, concrete_method);
}
/// Initiate a tail call to this function -- popping the current stack frame, pushing the new
/// stack frame and initializing the arguments.
pub(super) fn init_fn_tail_call(

View file

@ -414,36 +414,33 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Sanity-check that `supertrait_vtable_slot` in this type's vtable indeed produces
// our destination trait.
if cfg!(debug_assertions) {
let vptr_entry_idx =
self.tcx.supertrait_vtable_slot((src_pointee_ty, dest_pointee_ty));
let vtable_entries = self.vtable_entries(data_a.principal(), ty);
if let Some(entry_idx) = vptr_entry_idx {
let Some(&ty::VtblEntry::TraitVPtr(upcast_trait_ref)) =
vtable_entries.get(entry_idx)
else {
span_bug!(
self.cur_span(),
"invalid vtable entry index in {} -> {} upcast",
src_pointee_ty,
dest_pointee_ty
);
};
let erased_trait_ref = upcast_trait_ref
.map_bound(|r| ty::ExistentialTraitRef::erase_self_ty(*self.tcx, r));
assert!(
data_b
.principal()
.is_some_and(|b| self.eq_in_param_env(erased_trait_ref, b))
let vptr_entry_idx =
self.tcx.supertrait_vtable_slot((src_pointee_ty, dest_pointee_ty));
let vtable_entries = self.vtable_entries(data_a.principal(), ty);
if let Some(entry_idx) = vptr_entry_idx {
let Some(&ty::VtblEntry::TraitVPtr(upcast_trait_ref)) =
vtable_entries.get(entry_idx)
else {
span_bug!(
self.cur_span(),
"invalid vtable entry index in {} -> {} upcast",
src_pointee_ty,
dest_pointee_ty
);
} else {
// In this case codegen would keep using the old vtable. We don't want to do
// that as it has the wrong trait. The reason codegen can do this is that
// one vtable is a prefix of the other, so we double-check that.
let vtable_entries_b = self.vtable_entries(data_b.principal(), ty);
assert!(&vtable_entries[..vtable_entries_b.len()] == vtable_entries_b);
};
}
let erased_trait_ref =
ty::ExistentialTraitRef::erase_self_ty(*self.tcx, upcast_trait_ref);
assert!(data_b.principal().is_some_and(|b| self.eq_in_param_env(
erased_trait_ref,
self.tcx.instantiate_bound_regions_with_erased(b)
)));
} else {
// In this case codegen would keep using the old vtable. We don't want to do
// that as it has the wrong trait. The reason codegen can do this is that
// one vtable is a prefix of the other, so we double-check that.
let vtable_entries_b = self.vtable_entries(data_b.principal(), ty);
assert!(&vtable_entries[..vtable_entries_b.len()] == vtable_entries_b);
};
// Get the destination trait vtable and return that.
let new_vptr = self.get_vtable_ptr(ty, data_b)?;

View file

@ -54,7 +54,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
) -> &'tcx [VtblEntry<'tcx>] {
if let Some(trait_) = trait_ {
let trait_ref = trait_.with_self_ty(*self.tcx, dyn_ty);
let trait_ref = self.tcx.erase_regions(trait_ref);
let trait_ref =
self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref));
self.tcx.vtable_entries(trait_ref)
} else {
TyCtxt::COMMON_VTABLE_ENTRIES

View file

@ -76,6 +76,7 @@ pub mod sync;
pub mod tagged_ptr;
pub mod temp_dir;
pub mod thinvec;
pub mod thousands;
pub mod transitive_relation;
pub mod unhash;
pub mod unord;

View file

@ -0,0 +1,16 @@
//! This is an extremely bare-bones alternative to the `thousands` crate on
//! crates.io, for printing large numbers in a readable fashion.
#[cfg(test)]
mod tests;
// Converts the number to a string, with underscores as the thousands separator.
pub fn format_with_underscores(n: usize) -> String {
let mut s = n.to_string();
let mut i = s.len();
while i > 3 {
i -= 3;
s.insert(i, '_');
}
s
}

View file

@ -0,0 +1,14 @@
use super::*;
#[test]
fn test_format_with_underscores() {
assert_eq!("0", format_with_underscores(0));
assert_eq!("1", format_with_underscores(1));
assert_eq!("99", format_with_underscores(99));
assert_eq!("345", format_with_underscores(345));
assert_eq!("1_000", format_with_underscores(1_000));
assert_eq!("12_001", format_with_underscores(12_001));
assert_eq!("999_999", format_with_underscores(999_999));
assert_eq!("1_000_000", format_with_underscores(1_000_000));
assert_eq!("12_345_678", format_with_underscores(12_345_678));
}

View file

@ -7,6 +7,7 @@ use rustc_ast_pretty::pprust as pprust_ast;
use rustc_middle::bug;
use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
use rustc_middle::ty::{self, TyCtxt};
use rustc_mir_build::thir::print::{thir_flat, thir_tree};
use rustc_session::Session;
use rustc_session::config::{OutFileName, PpHirMode, PpMode, PpSourceMode};
use rustc_smir::rustc_internal::pretty::write_smir_pretty;
@ -313,7 +314,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
tcx.dcx().abort_if_errors();
debug!("pretty printing THIR tree");
for did in tcx.hir().body_owners() {
let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_tree(did));
let _ = writeln!(out, "{:?}:\n{}\n", did, thir_tree(tcx, did));
}
out
}
@ -324,7 +325,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
tcx.dcx().abort_if_errors();
debug!("pretty printing THIR flat");
for did in tcx.hir().body_owners() {
let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_flat(did));
let _ = writeln!(out, "{:?}:\n{}\n", did, thir_flat(tcx, did));
}
out
}

View file

@ -1136,7 +1136,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
rustc_attr!(
TEST, rustc_dump_vtable, Normal, template!(Word),
WarnFollowing, EncodeCrossCrate::Yes
WarnFollowing, EncodeCrossCrate::No
),
rustc_attr!(
TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/),

View file

@ -316,6 +316,7 @@ language_item_table! {
PanicAsyncFnResumedPanic, sym::panic_const_async_fn_resumed_panic, panic_const_async_fn_resumed_panic, Target::Fn, GenericRequirement::None;
PanicAsyncGenFnResumedPanic, sym::panic_const_async_gen_fn_resumed_panic, panic_const_async_gen_fn_resumed_panic, Target::Fn, GenericRequirement::None;
PanicGenFnNonePanic, sym::panic_const_gen_fn_none_panic, panic_const_gen_fn_none_panic, Target::Fn, GenericRequirement::None;
PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None;
/// libstd panic entry point. Necessary for const eval to be able to catch it
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;

View file

@ -424,12 +424,12 @@ fn compare_method_predicate_entailment<'tcx>(
Ok(())
}
struct RemapLateParam<'a, 'tcx> {
struct RemapLateParam<'tcx> {
tcx: TyCtxt<'tcx>,
mapping: &'a FxIndexMap<ty::LateParamRegionKind, ty::LateParamRegionKind>,
mapping: FxIndexMap<ty::LateParamRegionKind, ty::LateParamRegionKind>,
}
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'_, 'tcx> {
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.tcx
}
@ -653,6 +653,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
}))),
terr,
false,
None,
);
return Err(diag.emit());
}
@ -1070,6 +1071,7 @@ fn report_trait_method_mismatch<'tcx>(
}))),
terr,
false,
None,
);
diag.emit()
@ -1862,6 +1864,7 @@ fn compare_const_predicate_entailment<'tcx>(
}))),
terr,
false,
None,
);
return Err(diag.emit());
};

View file

@ -299,8 +299,7 @@ fn report_mismatched_rpitit_signature<'tcx>(
})
.collect();
let mut return_ty =
trait_m_sig.output().fold_with(&mut super::RemapLateParam { tcx, mapping: &mapping });
let mut return_ty = trait_m_sig.output().fold_with(&mut super::RemapLateParam { tcx, mapping });
if tcx.asyncness(impl_m_def_id).is_async() && tcx.asyncness(trait_m_def_id).is_async() {
let ty::Alias(ty::Projection, future_ty) = return_ty.kind() else {

View file

@ -1,7 +1,3 @@
// FIXME(@lcnr): Move this module out of `rustc_hir_analysis`.
//
// We don't do any drop checking during hir typeck.
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::codes::*;
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
@ -32,7 +28,10 @@ use crate::hir::def_id::{DefId, LocalDefId};
/// struct/enum definition for the nominal type itself (i.e.
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
///
pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorGuaranteed> {
pub(crate) fn check_drop_impl(
tcx: TyCtxt<'_>,
drop_impl_did: DefId,
) -> Result<(), ErrorGuaranteed> {
match tcx.impl_polarity(drop_impl_did) {
ty::ImplPolarity::Positive => {}
ty::ImplPolarity::Negative => {

View file

@ -199,7 +199,8 @@ pub fn check_intrinsic_type(
let split: Vec<&str> = name_str.split('_').collect();
assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
//We only care about the operation here
// Each atomic op has variants with different suffixes (`_seq_cst`, `_acquire`, etc.). Use
// string ops to strip the suffixes, because the variants all get the same treatment here.
let (n_tps, inputs, output) = match split[1] {
"cxchg" | "cxchgweak" => (
1,

View file

@ -455,18 +455,14 @@ fn fn_sig_suggestion<'tcx>(
let mut output = sig.output();
let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
output = if let ty::Alias(_, alias_ty) = *output.kind() {
tcx.explicit_item_self_bounds(alias_ty.def_id)
output = if let ty::Alias(_, alias_ty) = *output.kind()
&& let Some(output) = tcx
.explicit_item_self_bounds(alias_ty.def_id)
.iter_instantiated_copied(tcx, alias_ty.args)
.find_map(|(bound, _)| {
bound.as_projection_clause()?.no_bound_vars()?.term.as_type()
})
.unwrap_or_else(|| {
span_bug!(
ident.span,
"expected async fn to have `impl Future` output, but it returns {output}"
)
})
}) {
output
} else {
span_bug!(
ident.span,
@ -649,6 +645,7 @@ pub fn check_function_signature<'tcx>(
}))),
err,
false,
None,
);
return Err(diag.emit());
}

View file

@ -2267,14 +2267,12 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
let items = tcx.hir_module_items(module);
let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id));
res =
res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
res =
res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
res = res
.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
res = res.and(items.par_opaques(|item| tcx.ensure().check_well_formed(item)));
let res = items
.par_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id))
.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)))
.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)))
.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)))
.and(items.par_opaques(|item| tcx.ensure().check_well_formed(item)));
if module == LocalModDefId::CRATE_DEF_ID {
super::entry::check_for_entry_fn(tcx);
}

View file

@ -404,17 +404,12 @@ pub(crate) fn coerce_unsized_info<'tcx>(
check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
}
(&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => check_mutbl(
ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a },
ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b },
&|ty| Ty::new_imm_ptr(tcx, ty),
),
(&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => check_mutbl(
ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a },
ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b },
&|ty| Ty::new_imm_ptr(tcx, ty),
),
(&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b))
| (&ty::RawPtr(ty_a, mutbl_a), &ty::RawPtr(ty_b, mutbl_b)) => {
let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
}
(&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b))
if def_a.is_struct() && def_b.is_struct() =>

View file

@ -158,12 +158,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
let trait_ref = trait_header.trait_ref.instantiate_identity();
let trait_def = tcx.trait_def(trait_ref.def_id);
res = res.and(check_impl(tcx, impl_def_id, trait_ref, trait_def));
res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref));
res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def));
res = res.and(tcx.ensure().orphan_check_impl(impl_def_id));
res = res.and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header));
res = res
.and(check_impl(tcx, impl_def_id, trait_ref, trait_def))
.and(check_object_overlap(tcx, impl_def_id, trait_ref))
.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def))
.and(tcx.ensure().orphan_check_impl(impl_def_id))
.and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header));
}
res
@ -199,10 +199,9 @@ fn check_object_overlap<'tcx>(
for component_def_id in component_def_ids {
if !tcx.is_dyn_compatible(component_def_id) {
// FIXME(dyn_compat_renaming): Rename test and update comment.
// Without the 'dyn_compatible_for_dispatch' feature this is an error
// which will be reported by wfcheck. Ignore it here.
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
// This is tested by `coherence-impl-trait-for-trait-dyn-compatible.rs`.
// With the feature enabled, the trait is not implemented automatically,
// so this is valid.
} else {

View file

@ -57,7 +57,7 @@ mod type_of;
///////////////////////////////////////////////////////////////////////////
pub fn provide(providers: &mut Providers) {
pub(crate) fn provide(providers: &mut Providers) {
resolve_bound_vars::provide(providers);
*providers = Providers {
type_of: type_of::type_of,
@ -122,7 +122,7 @@ pub fn provide(providers: &mut Providers) {
/// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
/// `probe_ty_param_bounds` requests, drawing the information from
/// the HIR (`hir::Generics`), recursively.
pub struct ItemCtxt<'tcx> {
pub(crate) struct ItemCtxt<'tcx> {
tcx: TyCtxt<'tcx>,
item_def_id: LocalDefId,
tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
@ -148,7 +148,7 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector {
}
}
pub struct CollectItemTypesVisitor<'tcx> {
pub(crate) struct CollectItemTypesVisitor<'tcx> {
pub tcx: TyCtxt<'tcx>,
}
@ -364,19 +364,19 @@ fn bad_placeholder<'cx, 'tcx>(
}
impl<'tcx> ItemCtxt<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
}
pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
self.lowerer().lower_ty(hir_ty)
}
pub fn hir_id(&self) -> hir::HirId {
pub(crate) fn hir_id(&self) -> hir::HirId {
self.tcx.local_def_id_to_hir_id(self.item_def_id)
}
pub fn node(&self) -> hir::Node<'tcx> {
pub(crate) fn node(&self) -> hir::Node<'tcx> {
self.tcx.hir_node(self.hir_id())
}

View file

@ -1,7 +1,8 @@
use rustc_hir as hir;
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::intravisit;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::sym;
pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
@ -87,3 +88,82 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
}
}
}
pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
for id in tcx.hir().items() {
let def_id = id.owner_id.def_id;
let Some(attr) = tcx.get_attr(def_id, sym::rustc_dump_vtable) else {
continue;
};
let vtable_entries = match tcx.hir().item(id).kind {
hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
let trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate_identity();
if trait_ref.has_non_region_param() {
tcx.dcx().span_err(
attr.span,
"`rustc_dump_vtable` must be applied to non-generic impl",
);
continue;
}
if !tcx.is_dyn_compatible(trait_ref.def_id) {
tcx.dcx().span_err(
attr.span,
"`rustc_dump_vtable` must be applied to dyn-compatible trait",
);
continue;
}
let Ok(trait_ref) = tcx
.try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), trait_ref)
else {
tcx.dcx().span_err(
attr.span,
"`rustc_dump_vtable` applied to impl header that cannot be normalized",
);
continue;
};
tcx.vtable_entries(trait_ref)
}
hir::ItemKind::TyAlias(_, _) => {
let ty = tcx.type_of(def_id).instantiate_identity();
if ty.has_non_region_param() {
tcx.dcx().span_err(
attr.span,
"`rustc_dump_vtable` must be applied to non-generic type",
);
continue;
}
let Ok(ty) =
tcx.try_normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty)
else {
tcx.dcx().span_err(
attr.span,
"`rustc_dump_vtable` applied to type alias that cannot be normalized",
);
continue;
};
let ty::Dynamic(data, _, _) = *ty.kind() else {
tcx.dcx().span_err(attr.span, "`rustc_dump_vtable` to type alias of dyn type");
continue;
};
if let Some(principal) = data.principal() {
tcx.vtable_entries(
tcx.instantiate_bound_regions_with_erased(principal).with_self_ty(tcx, ty),
)
} else {
TyCtxt::COMMON_VTABLE_ENTRIES
}
}
_ => {
tcx.dcx().span_err(
attr.span,
"`rustc_dump_vtable` only applies to impl, or type alias of dyn type",
);
continue;
}
};
tcx.dcx().span_err(tcx.def_span(def_id), format!("vtable entries: {vtable_entries:#?}"));
}
}

View file

@ -12,13 +12,11 @@ use std::ops::ControlFlow;
use rustc_ast::visit::walk_list;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
use rustc_hir::{
self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap,
LifetimeName, Node,
self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeName, Node,
};
use rustc_macros::extension;
use rustc_middle::hir::nested_filter;
@ -26,7 +24,7 @@ use rustc_middle::middle::resolve_bound_vars::*;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::{DefId, LocalDefId, LocalDefIdMap};
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::{Ident, Span, sym};
use tracing::{debug, debug_span, instrument};
@ -62,33 +60,9 @@ impl ResolvedArg {
}
}
/// Maps the id of each bound variable reference to the variable decl
/// that it corresponds to.
///
/// FIXME. This struct gets converted to a `ResolveBoundVars` for
/// actual use. It has the same data, but indexed by `LocalDefId`. This
/// is silly.
#[derive(Debug, Default)]
struct NamedVarMap {
// maps from every use of a named (not anonymous) bound var to a
// `ResolvedArg` describing how that variable is bound
defs: ItemLocalMap<ResolvedArg>,
// Maps relevant hir items to the bound vars on them. These include:
// - function defs
// - function pointers
// - closures
// - trait refs
// - bound types (like `T` in `for<'a> T<'a>: Foo`)
late_bound_vars: ItemLocalMap<Vec<ty::BoundVariableKind>>,
// List captured variables for each opaque type.
opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
}
struct BoundVarContext<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
map: &'a mut NamedVarMap,
rbv: &'a mut ResolveBoundVars,
scope: ScopeRef<'a>,
}
@ -267,19 +241,12 @@ pub(crate) fn provide(providers: &mut Providers) {
/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
/// You should not read the result of this query directly, but rather use
/// `named_variable_map`, `is_late_bound_map`, etc.
/// `named_variable_map`, `late_bound_vars_map`, etc.
#[instrument(level = "debug", skip(tcx))]
fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
let mut named_variable_map = NamedVarMap {
defs: Default::default(),
late_bound_vars: Default::default(),
opaque_captured_lifetimes: Default::default(),
};
let mut visitor = BoundVarContext {
tcx,
map: &mut named_variable_map,
scope: &Scope::Root { opt_parent_item: None },
};
let mut rbv = ResolveBoundVars::default();
let mut visitor =
BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
match tcx.hir_owner_node(local_def_id) {
hir::OwnerNode::Item(item) => visitor.visit_item(item),
hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
@ -299,19 +266,10 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
hir::OwnerNode::Synthetic => unreachable!(),
}
let defs = named_variable_map.defs.into_sorted_stable_ord();
let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord();
let opaque_captured_lifetimes = named_variable_map.opaque_captured_lifetimes;
let rl = ResolveBoundVars {
defs: SortedMap::from_presorted_elements(defs),
late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars),
opaque_captured_lifetimes,
};
debug!(?rl.defs);
debug!(?rl.late_bound_vars);
debug!(?rl.opaque_captured_lifetimes);
rl
debug!(?rbv.defs);
debug!(?rbv.late_bound_vars);
debug!(?rbv.opaque_captured_lifetimes);
rbv
}
fn late_arg_as_bound_arg<'tcx>(
@ -404,7 +362,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Binder { hir_id, .. } => {
// Nested poly trait refs have the binders concatenated
let mut full_binders =
self.map.late_bound_vars.entry(hir_id.local_id).or_default().clone();
self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone();
full_binders.extend(supertrait_bound_vars);
break (full_binders, BinderScopeType::Concatenating);
}
@ -646,7 +604,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let captures = captures.into_inner().into_iter().collect();
debug!(?captures);
self.map.opaque_captured_lifetimes.insert(opaque.def_id, captures);
self.rbv.opaque_captured_lifetimes.insert(opaque.def_id, captures);
}
#[instrument(level = "debug", skip(self))]
@ -848,7 +806,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
hir::TyKind::Ref(lifetime_ref, ref mt) => {
self.visit_lifetime(lifetime_ref);
let scope = Scope::ObjectLifetimeDefault {
lifetime: self.map.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
lifetime: self.rbv.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
s: self.scope,
};
self.with(scope, |this| this.visit_ty_unambig(mt.ty));
@ -966,7 +924,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let bound_vars: Vec<_> =
self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
self.map.late_bound_vars.insert(hir_id.local_id, bound_vars);
self.rbv.late_bound_vars.insert(hir_id.local_id, bound_vars);
}
self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
intravisit::walk_fn_kind(self, fk);
@ -1140,8 +1098,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
where
F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
{
let BoundVarContext { tcx, map, .. } = self;
let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
let BoundVarContext { tcx, rbv, .. } = self;
let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope };
let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
{
let _enter = span.enter();
@ -1150,10 +1108,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
}
fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
if let Some(old) = self.map.late_bound_vars.insert(hir_id.local_id, binder) {
if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) {
bug!(
"overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
self.map.late_bound_vars[&hir_id.local_id]
self.rbv.late_bound_vars[&hir_id.local_id]
)
}
}
@ -1597,9 +1555,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
kind.descr(param_def_id.to_def_id())
),
};
self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
} else {
self.map.defs.insert(hir_id.local_id, def);
self.rbv.defs.insert(hir_id.local_id, def);
}
return;
}
@ -1632,7 +1590,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
}
});
self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
self.rbv.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
return;
}
Scope::Root { .. } => break,
@ -1725,7 +1683,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
}
};
let map = &self.map;
let rbv = &self.rbv;
let generics = self.tcx.generics_of(def_id);
// `type_def_id` points to an item, so there is nothing to inherit generics from.
@ -1744,7 +1702,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// This index can be used with `generic_args` since `parent_count == 0`.
let index = generics.param_def_id_to_index[&param_def_id] as usize;
generic_args.args.get(index).and_then(|arg| match arg {
GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id.local_id).copied(),
GenericArg::Lifetime(lt) => rbv.defs.get(&lt.hir_id.local_id).copied(),
_ => None,
})
}
@ -2042,7 +2000,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
debug!(span = ?lifetime_ref.ident.span);
self.map.defs.insert(lifetime_ref.hir_id.local_id, def);
self.rbv.defs.insert(lifetime_ref.hir_id.local_id, def);
}
// When we have a return type notation type in a where clause, like
@ -2197,7 +2155,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
// See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`.
// And this is exercised in:
// `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`.
let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
let existing_bound_vars = self.rbv.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
let existing_bound_vars_saved = existing_bound_vars.clone();
existing_bound_vars.extend(bound_vars);
self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);

View file

@ -100,213 +100,156 @@ enum InheritanceKind {
Own,
}
struct GenericsBuilder<'tcx> {
fn build_generics<'tcx>(
tcx: TyCtxt<'tcx>,
sig_id: DefId,
parent: Option<DefId>,
inh_kind: InheritanceKind,
}
) -> ty::Generics {
let mut own_params = vec![];
impl<'tcx> GenericsBuilder<'tcx> {
fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> {
GenericsBuilder { tcx, sig_id, parent: None, inh_kind: InheritanceKind::WithParent(false) }
let sig_generics = tcx.generics_of(sig_id);
if let InheritanceKind::WithParent(has_self) = inh_kind
&& let Some(parent_def_id) = sig_generics.parent
{
let sig_parent_generics = tcx.generics_of(parent_def_id);
own_params.append(&mut sig_parent_generics.own_params.clone());
if !has_self {
own_params.remove(0);
}
}
own_params.append(&mut sig_generics.own_params.clone());
fn with_parent(mut self, parent: DefId) -> Self {
self.parent = Some(parent);
self
}
// Lifetime parameters must be declared before type and const parameters.
// Therefore, When delegating from a free function to a associated function,
// generic parameters need to be reordered:
//
// trait Trait<'a, A> {
// fn foo<'b, B>(...) {...}
// }
//
// reuse Trait::foo;
// desugaring:
// fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
// Trait::foo(...)
// }
own_params.sort_by_key(|key| key.kind.is_ty_or_const());
fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
self.inh_kind = inh_kind;
self
}
let param_def_id_to_index =
own_params.iter().map(|param| (param.def_id, param.index)).collect();
fn build(self) -> ty::Generics {
let mut own_params = vec![];
let (parent_count, has_self) = if let Some(def_id) = parent {
let parent_generics = tcx.generics_of(def_id);
let parent_kind = tcx.def_kind(def_id);
(parent_generics.count(), parent_kind == DefKind::Trait)
} else {
(0, false)
};
let sig_generics = self.tcx.generics_of(self.sig_id);
if let InheritanceKind::WithParent(has_self) = self.inh_kind
&& let Some(parent_def_id) = sig_generics.parent
for (idx, param) in own_params.iter_mut().enumerate() {
param.index = (idx + parent_count) as u32;
// FIXME(fn_delegation): Default parameters are not inherited, because they are
// not permitted in functions. Therefore, there are 2 options here:
//
// - We can create non-default generic parameters.
// - We can substitute default parameters into the signature.
//
// At the moment, first option has been selected as the most general.
if let ty::GenericParamDefKind::Type { has_default, .. }
| ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
{
let sig_parent_generics = self.tcx.generics_of(parent_def_id);
own_params.append(&mut sig_parent_generics.own_params.clone());
if !has_self {
own_params.remove(0);
}
*has_default = false;
}
own_params.append(&mut sig_generics.own_params.clone());
}
// Lifetime parameters must be declared before type and const parameters.
// Therefore, When delegating from a free function to a associated function,
// generic parameters need to be reordered:
//
// trait Trait<'a, A> {
// fn foo<'b, B>(...) {...}
// }
//
// reuse Trait::foo;
// desugaring:
// fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
// Trait::foo(...)
// }
own_params.sort_by_key(|key| key.kind.is_ty_or_const());
let param_def_id_to_index =
own_params.iter().map(|param| (param.def_id, param.index)).collect();
let (parent_count, has_self) = if let Some(def_id) = self.parent {
let parent_generics = self.tcx.generics_of(def_id);
let parent_kind = self.tcx.def_kind(def_id);
(parent_generics.count(), parent_kind == DefKind::Trait)
} else {
(0, false)
};
for (idx, param) in own_params.iter_mut().enumerate() {
param.index = (idx + parent_count) as u32;
// FIXME(fn_delegation): Default parameters are not inherited, because they are
// not permitted in functions. Therefore, there are 2 options here:
//
// - We can create non-default generic parameters.
// - We can substitute default parameters into the signature.
//
// At the moment, first option has been selected as the most general.
if let ty::GenericParamDefKind::Type { has_default, .. }
| ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
{
*has_default = false;
}
}
ty::Generics {
parent: self.parent,
parent_count,
own_params,
param_def_id_to_index,
has_self,
has_late_bound_regions: sig_generics.has_late_bound_regions,
}
ty::Generics {
parent,
parent_count,
own_params,
param_def_id_to_index,
has_self,
has_late_bound_regions: sig_generics.has_late_bound_regions,
}
}
struct PredicatesBuilder<'tcx> {
fn build_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
sig_id: DefId,
parent: Option<DefId>,
inh_kind: InheritanceKind,
args: ty::GenericArgsRef<'tcx>,
}
impl<'tcx> PredicatesBuilder<'tcx> {
fn new(
) -> ty::GenericPredicates<'tcx> {
struct PredicatesCollector<'tcx> {
tcx: TyCtxt<'tcx>,
preds: Vec<(ty::Clause<'tcx>, Span)>,
args: ty::GenericArgsRef<'tcx>,
sig_id: DefId,
) -> PredicatesBuilder<'tcx> {
PredicatesBuilder {
tcx,
sig_id,
parent: None,
inh_kind: InheritanceKind::WithParent(false),
args,
}
}
fn with_parent(mut self, parent: DefId) -> Self {
self.parent = Some(parent);
self
}
fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
self.inh_kind = inh_kind;
self
}
fn build(self) -> ty::GenericPredicates<'tcx> {
struct PredicatesCollector<'tcx> {
tcx: TyCtxt<'tcx>,
preds: Vec<(ty::Clause<'tcx>, Span)>,
args: ty::GenericArgsRef<'tcx>,
impl<'tcx> PredicatesCollector<'tcx> {
fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> {
PredicatesCollector { tcx, preds: vec![], args }
}
impl<'tcx> PredicatesCollector<'tcx> {
fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> {
PredicatesCollector { tcx, preds: vec![], args }
}
fn with_own_preds(
mut self,
f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
def_id: DefId,
) -> Self {
let preds = f(def_id).instantiate_own(self.tcx, self.args);
self.preds.extend(preds);
self
}
fn with_preds(
mut self,
f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
def_id: DefId,
) -> Self {
let preds = f(def_id);
if let Some(parent_def_id) = preds.parent {
self = self.with_own_preds(f, parent_def_id);
}
self.with_own_preds(f, def_id)
}
fn with_own_preds(
mut self,
f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
def_id: DefId,
) -> Self {
let preds = f(def_id).instantiate_own(self.tcx, self.args);
self.preds.extend(preds);
self
}
let collector = PredicatesCollector::new(self.tcx, self.args);
// `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
// Note: `predicates_of` query can also add inferred outlives predicates, but that
// is not the case here as `sig_id` is either a trait or a function.
let preds = match self.inh_kind {
InheritanceKind::WithParent(false) => {
collector.with_preds(|def_id| self.tcx.explicit_predicates_of(def_id), self.sig_id)
fn with_preds(
mut self,
f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
def_id: DefId,
) -> Self {
let preds = f(def_id);
if let Some(parent_def_id) = preds.parent {
self = self.with_own_preds(f, parent_def_id);
}
InheritanceKind::WithParent(true) => {
collector.with_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
}
InheritanceKind::Own => {
collector.with_own_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
}
}
.preds;
ty::GenericPredicates {
parent: self.parent,
predicates: self.tcx.arena.alloc_from_iter(preds),
self.with_own_preds(f, def_id)
}
}
let collector = PredicatesCollector::new(tcx, args);
// `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
// Note: `predicates_of` query can also add inferred outlives predicates, but that
// is not the case here as `sig_id` is either a trait or a function.
let preds = match inh_kind {
InheritanceKind::WithParent(false) => {
collector.with_preds(|def_id| tcx.explicit_predicates_of(def_id), sig_id)
}
InheritanceKind::WithParent(true) => {
collector.with_preds(|def_id| tcx.predicates_of(def_id), sig_id)
}
InheritanceKind::Own => {
collector.with_own_preds(|def_id| tcx.predicates_of(def_id), sig_id)
}
}
.preds;
ty::GenericPredicates { parent, predicates: tcx.arena.alloc_from_iter(preds) }
}
struct GenericArgsBuilder<'tcx> {
fn build_generic_args<'tcx>(
tcx: TyCtxt<'tcx>,
remap_table: RemapTable,
sig_id: DefId,
def_id: LocalDefId,
}
args: ty::GenericArgsRef<'tcx>,
) -> ty::GenericArgsRef<'tcx> {
let caller_generics = tcx.generics_of(def_id);
let callee_generics = tcx.generics_of(sig_id);
impl<'tcx> GenericArgsBuilder<'tcx> {
fn new(tcx: TyCtxt<'tcx>, sig_id: DefId, def_id: LocalDefId) -> GenericArgsBuilder<'tcx> {
GenericArgsBuilder { tcx, remap_table: FxHashMap::default(), sig_id, def_id }
let mut remap_table = FxHashMap::default();
for caller_param in &caller_generics.own_params {
let callee_index = callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap();
remap_table.insert(callee_index, caller_param.index);
}
fn build_from_args(mut self, args: ty::GenericArgsRef<'tcx>) -> ty::GenericArgsRef<'tcx> {
let caller_generics = self.tcx.generics_of(self.def_id);
let callee_generics = self.tcx.generics_of(self.sig_id);
for caller_param in &caller_generics.own_params {
let callee_index =
callee_generics.param_def_id_to_index(self.tcx, caller_param.def_id).unwrap();
self.remap_table.insert(callee_index, caller_param.index);
}
let mut folder = ParamIndexRemapper { tcx: self.tcx, remap_table: self.remap_table };
args.fold_with(&mut folder)
}
let mut folder = ParamIndexRemapper { tcx, remap_table };
args.fold_with(&mut folder)
}
fn create_generic_args<'tcx>(
@ -314,8 +257,6 @@ fn create_generic_args<'tcx>(
def_id: LocalDefId,
sig_id: DefId,
) -> ty::GenericArgsRef<'tcx> {
let builder = GenericArgsBuilder::new(tcx, sig_id, def_id);
let caller_kind = fn_kind(tcx, def_id.into());
let callee_kind = fn_kind(tcx, sig_id);
match (caller_kind, callee_kind) {
@ -325,7 +266,7 @@ fn create_generic_args<'tcx>(
| (FnKind::AssocTrait, FnKind::Free)
| (FnKind::AssocTrait, FnKind::AssocTrait) => {
let args = ty::GenericArgs::identity_for_item(tcx, sig_id);
builder.build_from_args(args)
build_generic_args(tcx, sig_id, def_id, args)
}
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
@ -335,8 +276,9 @@ fn create_generic_args<'tcx>(
tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args;
let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
let method_args = tcx.mk_args_from_iter(trait_args.iter().skip(callee_generics.parent_count));
let method_args = builder.build_from_args(method_args);
let method_args =
tcx.mk_args_from_iter(trait_args.iter().skip(callee_generics.parent_count));
let method_args = build_generic_args(tcx, sig_id, def_id, method_args);
tcx.mk_args_from_iter(parent_args.iter().chain(method_args))
}
@ -347,16 +289,16 @@ fn create_generic_args<'tcx>(
let generic_self_ty = ty::GenericArg::from(self_ty);
let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
let trait_args = builder.build_from_args(trait_args);
let trait_args = build_generic_args(tcx, sig_id, def_id, trait_args);
let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1));
tcx.mk_args_from_iter(args)
}
// For trait impl's `sig_id` is always equal to the corresponding trait method.
// For inherent methods delegation is not yet supported.
(FnKind::AssocTraitImpl, _)
| (_, FnKind::AssocTraitImpl)
// Delegation to inherent methods is not yet supported.
| (_, FnKind::AssocInherentImpl) => unreachable!(),
}
}
@ -377,39 +319,31 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
def_id: LocalDefId,
sig_id: DefId,
) -> ty::Generics {
let builder = GenericsBuilder::new(tcx, sig_id);
let caller_kind = fn_kind(tcx, def_id.into());
let callee_kind = fn_kind(tcx, sig_id);
match (caller_kind, callee_kind) {
(FnKind::Free, FnKind::Free)
| (FnKind::Free, FnKind::AssocTrait) => builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build(),
(FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => {
build_generics(tcx, sig_id, None, InheritanceKind::WithParent(true))
}
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
builder
.with_parent(tcx.parent(def_id.into()))
.with_inheritance_kind(InheritanceKind::Own)
.build()
build_generics(tcx, sig_id, Some(tcx.parent(def_id.into())), InheritanceKind::Own)
}
(FnKind::AssocInherentImpl, FnKind::AssocTrait)
| (FnKind::AssocTrait, FnKind::AssocTrait) => {
builder
.with_parent(tcx.parent(def_id.into()))
.build()
}
(FnKind::AssocInherentImpl, FnKind::Free)
| (FnKind::AssocTrait, FnKind::Free) => {
builder
.with_parent(tcx.parent(def_id.into()))
.build()
}
| (FnKind::AssocTrait, FnKind::AssocTrait)
| (FnKind::AssocInherentImpl, FnKind::Free)
| (FnKind::AssocTrait, FnKind::Free) => build_generics(
tcx,
sig_id,
Some(tcx.parent(def_id.into())),
InheritanceKind::WithParent(false),
),
// For trait impl's `sig_id` is always equal to the corresponding trait method.
// For inherent methods delegation is not yet supported.
(FnKind::AssocTraitImpl, _)
| (_, FnKind::AssocTraitImpl)
// Delegation to inherent methods is not yet supported.
| (_, FnKind::AssocInherentImpl) => unreachable!(),
}
}
@ -420,36 +354,36 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
sig_id: DefId,
) -> ty::GenericPredicates<'tcx> {
let args = create_generic_args(tcx, def_id, sig_id);
let builder = PredicatesBuilder::new(tcx, args, sig_id);
let caller_kind = fn_kind(tcx, def_id.into());
let callee_kind = fn_kind(tcx, sig_id);
match (caller_kind, callee_kind) {
(FnKind::Free, FnKind::Free)
| (FnKind::Free, FnKind::AssocTrait) => {
builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build()
(FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => {
build_predicates(tcx, sig_id, None, InheritanceKind::WithParent(true), args)
}
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
builder
.with_parent(tcx.parent(def_id.into()))
.with_inheritance_kind(InheritanceKind::Own)
.build()
}
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => build_predicates(
tcx,
sig_id,
Some(tcx.parent(def_id.into())),
InheritanceKind::Own,
args,
),
(FnKind::AssocInherentImpl, FnKind::AssocTrait)
| (FnKind::AssocTrait, FnKind::AssocTrait)
| (FnKind::AssocInherentImpl, FnKind::Free)
| (FnKind::AssocTrait, FnKind::Free) => {
builder
.with_parent(tcx.parent(def_id.into()))
.build()
}
| (FnKind::AssocTrait, FnKind::Free) => build_predicates(
tcx,
sig_id,
Some(tcx.parent(def_id.into())),
InheritanceKind::WithParent(false),
args,
),
// For trait impl's `sig_id` is always equal to the corresponding trait method.
// For inherent methods delegation is not yet supported.
(FnKind::AssocTraitImpl, _)
| (_, FnKind::AssocTraitImpl)
// Delegation to inherent methods is not yet supported.
| (_, FnKind::AssocInherentImpl) => unreachable!(),
}
}

View file

@ -495,6 +495,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
.iter()
.any(|constraint| constraint.ident.name == item.name)
})
.filter(|item| !item.is_impl_trait_in_trait())
.map(|item| self.tcx.item_ident(item.def_id).to_string())
.collect()
} else {

View file

@ -273,7 +273,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
// We lower to an infer even when the feature gate is not enabled
// as it is useful for diagnostics to be able to see a `ConstKind::Infer`
args.push(ctx.provided_kind(&args, param, arg));
args.push(ctx.provided_kind(param, arg));
args_iter.next();
params.next();
}

View file

@ -296,7 +296,6 @@ pub trait GenericArgsLowerer<'a, 'tcx> {
fn provided_kind(
&mut self,
preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx>;
@ -480,7 +479,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
fn provided_kind(
&mut self,
_preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {

View file

@ -34,7 +34,7 @@
//! impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ }
//! ```
//!
//! We get that the generic pamameters for `impl2` are `[T, std::vec::IntoIter<T>]`.
//! We get that the generic parameters for `impl2` are `[T, std::vec::IntoIter<T>]`.
//! `T` is constrained to be `<I as Iterator>::Item`, so we check only
//! `std::vec::IntoIter<T>` for repeated parameters, which it doesn't have. The
//! predicates of `impl1` are only `T: Sized`, which is also a predicate of
@ -119,7 +119,6 @@ fn check_always_applicable(
impl2_node: Node,
) -> Result<(), ErrorGuaranteed> {
let span = tcx.def_span(impl1_def_id);
let mut res = check_has_items(tcx, impl1_def_id, impl2_node, span);
let (impl1_args, impl2_args) = get_impl_args(tcx, impl1_def_id, impl2_node)?;
let impl2_def_id = impl2_node.def_id();
@ -131,11 +130,10 @@ fn check_always_applicable(
unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args)
};
res = res.and(check_static_lifetimes(tcx, &parent_args, span));
res = res.and(check_duplicate_params(tcx, impl1_args, parent_args, span));
res = res.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span));
res
check_has_items(tcx, impl1_def_id, impl2_node, span)
.and(check_static_lifetimes(tcx, &parent_args, span))
.and(check_duplicate_params(tcx, impl1_args, parent_args, span))
.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span))
}
fn check_has_items(

View file

@ -83,12 +83,11 @@ pub mod autoderef;
mod bounds;
mod check_unused;
mod coherence;
mod delegation;
pub mod hir_ty_lowering;
// FIXME: This module shouldn't be public.
pub mod collect;
mod collect;
mod constrained_generic_params;
mod delegation;
mod errors;
pub mod hir_ty_lowering;
pub mod hir_wf_check;
mod impl_wf_check;
mod outlives;
@ -104,7 +103,8 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt};
use rustc_span::Span;
use rustc_trait_selection::traits;
use self::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
pub use crate::collect::suggest_impl_trait;
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
@ -152,11 +152,14 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
});
if tcx.features().rustc_attrs() {
tcx.sess.time("outlives_dumping", || outlives::dump::inferred_outlives(tcx));
tcx.sess.time("variance_dumping", || variance::dump::variances(tcx));
collect::dump::opaque_hidden_types(tcx);
collect::dump::predicates_and_item_bounds(tcx);
collect::dump::def_parents(tcx);
tcx.sess.time("dumping_rustc_attr_data", || {
outlives::dump::inferred_outlives(tcx);
variance::dump::variances(tcx);
collect::dump::opaque_hidden_types(tcx);
collect::dump::predicates_and_item_bounds(tcx);
collect::dump::def_parents(tcx);
collect::dump::vtables(tcx);
});
}
// Make sure we evaluate all static and (non-associated) const items, even if unused.

View file

@ -24,7 +24,7 @@ pub(super) fn infer_predicates(
// If new predicates were added then we need to re-calculate
// all crates since there could be new implied predicates.
'outer: loop {
loop {
let mut predicates_added = false;
// Visit all the crates and infer predicates
@ -90,7 +90,7 @@ pub(super) fn infer_predicates(
}
if !predicates_added {
break 'outer;
break;
}
}

View file

@ -27,9 +27,6 @@ mod solve;
pub(crate) mod dump;
/// Code for transforming variances.
mod xform;
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { variances_of, crate_variances, ..*providers };
}

View file

@ -12,8 +12,26 @@ use tracing::debug;
use super::constraints::*;
use super::terms::VarianceTerm::*;
use super::terms::*;
use super::xform::*;
fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance {
// Greatest lower bound of the variance lattice as defined in The Paper:
//
// *
// - +
// o
match (v1, v2) {
(ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
(ty::Covariant, ty::Contravariant) => ty::Invariant,
(ty::Contravariant, ty::Covariant) => ty::Invariant,
(ty::Covariant, ty::Covariant) => ty::Covariant,
(ty::Contravariant, ty::Contravariant) => ty::Contravariant,
(x, ty::Bivariant) | (ty::Bivariant, x) => x,
}
}
struct SolveContext<'a, 'tcx> {
terms_cx: TermsContext<'a, 'tcx>,
constraints: Vec<Constraint<'a>>,

View file

@ -1,22 +0,0 @@
use rustc_middle::ty;
pub(crate) fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance {
// Greatest lower bound of the variance lattice as
// defined in The Paper:
//
// *
// - +
// o
match (v1, v2) {
(ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
(ty::Covariant, ty::Contravariant) => ty::Invariant,
(ty::Contravariant, ty::Covariant) => ty::Invariant,
(ty::Covariant, ty::Covariant) => ty::Covariant,
(ty::Contravariant, ty::Contravariant) => ty::Contravariant,
(x, ty::Bivariant) | (ty::Bivariant, x) => x,
}
}

View file

@ -1261,7 +1261,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn provided_kind(
&mut self,
_preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {

View file

@ -1147,6 +1147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(self.param_env.and(trace.values)),
e,
true,
None,
);
}
}

View file

@ -31,12 +31,12 @@ use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt};
/// functions, closures, and `const`s, including performing type inference
/// with [`InferCtxt`].
///
/// This is in contrast to [`ItemCtxt`], which is used to type-check item *signatures*
/// and thus does not perform type inference.
/// This is in contrast to `rustc_hir_analysis::collect::ItemCtxt`, which is
/// used to type-check item *signatures* and thus does not perform type
/// inference.
///
/// See [`ItemCtxt`]'s docs for more.
/// See `ItemCtxt`'s docs for more.
///
/// [`ItemCtxt`]: rustc_hir_analysis::collect::ItemCtxt
/// [`InferCtxt`]: infer::InferCtxt
pub(crate) struct FnCtxt<'a, 'tcx> {
pub(super) body_id: LocalDefId,

View file

@ -12,8 +12,8 @@ use rustc_hir::{
GenericBound, HirId, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind, TyKind,
WherePredicateKind, expr_needs_parens,
};
use rustc_hir_analysis::collect::suggest_impl_trait;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_hir_analysis::suggest_impl_trait;
use rustc_middle::lint::in_external_macro;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::span_bug;

View file

@ -413,7 +413,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
fn provided_kind(
&mut self,
_preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {

View file

@ -402,6 +402,18 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
}
}
impl<'tcx> ToTrace<'tcx> for ty::ExistentialTraitRef<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(
ty::Binder::dummy(a),
ty::Binder::dummy(b),
)),
}
}
}
impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
@ -410,3 +422,15 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
}
}
}
impl<'tcx> ToTrace<'tcx> for ty::ExistentialProjection<'tcx> {
fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ValuePairs::ExistentialProjection(ExpectedFound::new(
ty::Binder::dummy(a),
ty::Binder::dummy(b),
)),
}
}
}

View file

@ -26,7 +26,6 @@ use rustc_parse::{
};
use rustc_passes::{abi_test, input_stats, layout_test};
use rustc_resolve::Resolver;
use rustc_session::code_stats::VTableSizeInfo;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_name};
@ -989,90 +988,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
// we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally.
let _ = tcx.all_diagnostic_items(());
});
if sess.opts.unstable_opts.print_vtable_sizes {
let traits = tcx.traits(LOCAL_CRATE);
for &tr in traits {
if !tcx.is_dyn_compatible(tr) {
continue;
}
let name = ty::print::with_no_trimmed_paths!(tcx.def_path_str(tr));
let mut first_dsa = true;
// Number of vtable entries, if we didn't have upcasting
let mut entries_ignoring_upcasting = 0;
// Number of vtable entries needed solely for upcasting
let mut entries_for_upcasting = 0;
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, tr));
// A slightly edited version of the code in
// `rustc_trait_selection::traits::vtable::vtable_entries`, that works without self
// type and just counts number of entries.
//
// Note that this is technically wrong, for traits which have associated types in
// supertraits:
//
// trait A: AsRef<Self::T> + AsRef<()> { type T; }
//
// Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>`
// and `AsRef<()>` are the same trait, thus we assume that those are different, and
// potentially over-estimate how many vtable entries there are.
//
// Similarly this is wrong for traits that have methods with possibly-impossible bounds.
// For example:
//
// trait B<T> { fn f(&self) where T: Copy; }
//
// Here `dyn B<u8>` will have 4 entries, while `dyn B<String>` will only have 3.
// However, since we don't know `T`, we can't know if `T: Copy` holds or not,
// thus we lean on the bigger side and say it has 4 entries.
traits::vtable::prepare_vtable_segments(tcx, trait_ref, |segment| {
match segment {
traits::vtable::VtblSegment::MetadataDSA => {
// If this is the first dsa, it would be included either way,
// otherwise it's needed for upcasting
if std::mem::take(&mut first_dsa) {
entries_ignoring_upcasting += 3;
} else {
entries_for_upcasting += 3;
}
}
traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
// Lookup the shape of vtable for the trait.
let own_existential_entries =
tcx.own_existential_vtable_entries(trait_ref.def_id());
// The original code here ignores the method if its predicates are
// impossible. We can't really do that as, for example, all not trivial
// bounds on generic parameters are impossible (since we don't know the
// parameters...), see the comment above.
entries_ignoring_upcasting += own_existential_entries.len();
if emit_vptr {
entries_for_upcasting += 1;
}
}
}
std::ops::ControlFlow::Continue::<std::convert::Infallible>(())
});
sess.code_stats.record_vtable_size(tr, &name, VTableSizeInfo {
trait_name: name.clone(),
entries: entries_ignoring_upcasting + entries_for_upcasting,
entries_ignoring_upcasting,
entries_for_upcasting,
upcasting_cost_percent: entries_for_upcasting as f64
/ entries_ignoring_upcasting as f64
* 100.,
})
}
}
}
/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
@ -1153,12 +1068,6 @@ pub(crate) fn start_codegen<'tcx>(
tcx.sess.code_stats.print_type_sizes();
}
if tcx.sess.opts.unstable_opts.print_vtable_sizes {
let crate_name = tcx.crate_name(LOCAL_CRATE);
tcx.sess.code_stats.print_vtable_sizes(crate_name);
}
codegen
}

View file

@ -8,12 +8,12 @@ use rustc_data_structures::profiling::TimePassesFormat;
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, registry};
use rustc_session::config::{
BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, CoverageOptions,
DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs,
FmtDebug, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay,
LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig,
OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes,
PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
AutoDiff, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel,
CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation,
Externs, FmtDebug, FunctionReturn, InliningThreshold, Input, InstrumentCoverage,
InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans,
NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
SymbolManglingVersion, WasiExecModel, build_configuration, build_session_options,
rustc_optgroups,
};
@ -760,6 +760,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(allow_features, Some(vec![String::from("lang_items")]));
tracked!(always_encode_mir, true);
tracked!(assume_incomplete_release, true);
tracked!(autodiff, vec![AutoDiff::Print]);
tracked!(binary_dep_depinfo, true);
tracked!(box_noalias, false);
tracked!(

View file

@ -37,7 +37,7 @@ declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTAB
impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
let def_id = item.owner_id.to_def_id();
// NOTE(nbdd0121): use `object_safety_violations` instead of `is_dyn_compatible` because
// NOTE(nbdd0121): use `dyn_compatibility_violations` instead of `is_dyn_compatible` because
// the latter will report `where_clause_object_safety` lint.
if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
&& cx.tcx.is_dyn_compatible(def_id)

View file

@ -319,7 +319,11 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
case LLVMRustAttributeKind::NoAlias:
return Attribute::NoAlias;
case LLVMRustAttributeKind::NoCapture:
#if LLVM_VERSION_GE(21, 0)
report_fatal_error("NoCapture doesn't exist in LLVM 21");
#else
return Attribute::NoCapture;
#endif
case LLVMRustAttributeKind::NoCfCheck:
return Attribute::NoCfCheck;
case LLVMRustAttributeKind::NoInline:
@ -431,6 +435,12 @@ extern "C" void LLVMRustEraseInstFromParent(LLVMValueRef Instr) {
extern "C" LLVMAttributeRef
LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) {
#if LLVM_VERSION_GE(21, 0)
// LLVM 21 replaced the NoCapture attribute with Captures(none).
if (RustAttr == LLVMRustAttributeKind::NoCapture) {
return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none()));
}
#endif
return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
}
@ -667,8 +677,6 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
}
typedef DIBuilder *LLVMRustDIBuilderRef;
template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
}
@ -677,12 +685,6 @@ template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
#define DIArray DINodeArray
#define unwrapDI unwrapDIPtr
// FIXME(Zalathar): This is a temporary typedef to avoid churning dozens of
// bindings that are going to be deleted and replaced with their LLVM-C
// equivalents, as part of #134009. After that happens, the remaining bindings
// can be adjusted to use `LLVMDIFlags` instead of relying on this typedef.
typedef LLVMDIFlags LLVMRustDIFlags;
// Statically assert that `LLVMDIFlags` (C) and `DIFlags` (C++) have the same
// layout, at least for the flags we know about. This isn't guaranteed, but is
// likely to remain true, and as long as it is true it makes conversions easy.
@ -955,7 +957,8 @@ extern "C" LLVMValueRef LLVMRustGetLastInstruction(LLVMBasicBlockRef BB) {
return nullptr;
}
extern "C" void LLVMRustEraseInstBefore(LLVMBasicBlockRef bb, LLVMValueRef I) {
extern "C" void LLVMRustEraseInstUntilInclusive(LLVMBasicBlockRef bb,
LLVMValueRef I) {
auto &BB = *unwrap(bb);
auto &Inst = *unwrap<Instruction>(I);
auto It = BB.begin();
@ -963,8 +966,6 @@ extern "C" void LLVMRustEraseInstBefore(LLVMBasicBlockRef bb, LLVMValueRef I) {
++It;
// Make sure we found the Instruction.
assert(It != BB.end());
// We don't want to erase the instruction itself.
It--;
// Delete in rev order to ensure no dangling references.
while (It != BB.begin()) {
auto Prev = std::prev(It);
@ -994,34 +995,34 @@ extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind,
unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
}
extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
return new DIBuilder(*unwrap(M));
extern "C" LLVMDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
return wrap(new DIBuilder(*unwrap(M)));
}
extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
delete Builder;
extern "C" void LLVMRustDIBuilderDispose(LLVMDIBuilderRef Builder) {
delete unwrap(Builder);
}
extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
Builder->finalize();
extern "C" void LLVMRustDIBuilderFinalize(LLVMDIBuilderRef Builder) {
unwrap(Builder)->finalize();
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
LLVMDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
const char *Producer, size_t ProducerLen, bool isOptimized,
const char *Flags, unsigned RuntimeVer, const char *SplitName,
size_t SplitNameLen, LLVMRustDebugEmissionKind Kind, uint64_t DWOId,
bool SplitDebugInlining, LLVMRustDebugNameTableKind TableKind) {
auto *File = unwrapDI<DIFile>(FileRef);
return wrap(Builder->createCompileUnit(
return wrap(unwrap(Builder)->createCompileUnit(
Lang, File, StringRef(Producer, ProducerLen), isOptimized, Flags,
RuntimeVer, StringRef(SplitName, SplitNameLen), fromRust(Kind), DWOId,
SplitDebugInlining, false, fromRust(TableKind)));
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename,
LLVMRustDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename,
size_t FilenameLen, const char *Directory,
size_t DirectoryLen, LLVMRustChecksumKind CSKind,
const char *Checksum, size_t ChecksumLen,
@ -1034,29 +1035,29 @@ LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename,
std::optional<StringRef> oSource{};
if (Source)
oSource = StringRef(Source, SourceLen);
return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
StringRef(Directory, DirectoryLen), CSInfo,
oSource));
return wrap(unwrap(Builder)->createFile(StringRef(Filename, FilenameLen),
StringRef(Directory, DirectoryLen),
CSInfo, oSource));
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
LLVMRustDIBuilderCreateSubroutineType(LLVMDIBuilderRef Builder,
LLVMMetadataRef ParameterTypes) {
return wrap(Builder->createSubroutineType(
return wrap(unwrap(Builder)->createSubroutineType(
DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
unsigned ScopeLine, LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags,
unsigned ScopeLine, LLVMDIFlags Flags, LLVMRustDISPFlags SPFlags,
LLVMValueRef MaybeFn, LLVMMetadataRef TParam, LLVMMetadataRef Decl) {
DITemplateParameterArray TParams =
DITemplateParameterArray(unwrap<MDTuple>(TParam));
DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
DINode::DIFlags llvmFlags = fromRust(Flags);
DISubprogram *Sub = Builder->createFunction(
DISubprogram *Sub = unwrap(Builder)->createFunction(
unwrapDI<DIScope>(Scope), StringRef(Name, NameLen),
StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo,
unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags, llvmSPFlags,
@ -1067,15 +1068,15 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) {
LLVMDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMMetadataRef TParam) {
DITemplateParameterArray TParams =
DITemplateParameterArray(unwrap<MDTuple>(TParam));
DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
DINode::DIFlags llvmFlags = fromRust(Flags);
DISubprogram *Sub = Builder->createMethod(
DISubprogram *Sub = unwrap(Builder)->createMethod(
unwrapDI<DIScope>(Scope), StringRef(Name, NameLen),
StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File), LineNo,
unwrapDI<DISubroutineType>(Ty), 0, 0,
@ -1085,39 +1086,39 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMethod(
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name,
LLVMRustDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name,
size_t NameLen, uint64_t SizeInBits,
unsigned Encoding) {
return wrap(
Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
return wrap(unwrap(Builder)->createBasicType(StringRef(Name, NameLen),
SizeInBits, Encoding));
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateTypedef(LLVMRustDIBuilderRef Builder,
LLVMMetadataRef Type, const char *Name,
size_t NameLen, LLVMMetadataRef File,
unsigned LineNo, LLVMMetadataRef Scope) {
return wrap(Builder->createTypedef(
LLVMRustDIBuilderCreateTypedef(LLVMDIBuilderRef Builder, LLVMMetadataRef Type,
const char *Name, size_t NameLen,
LLVMMetadataRef File, unsigned LineNo,
LLVMMetadataRef Scope) {
return wrap(unwrap(Builder)->createTypedef(
unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
LineNo, unwrapDIPtr<DIScope>(Scope)));
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
const char *Name, size_t NameLen) {
return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
SizeInBits, AlignInBits, AddressSpace,
StringRef(Name, NameLen)));
LLVMDIBuilderRef Builder, LLVMMetadataRef PointeeTy, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned AddressSpace, const char *Name,
size_t NameLen) {
return wrap(unwrap(Builder)->createPointerType(
unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, AddressSpace,
StringRef(Name, NameLen)));
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags,
uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, unsigned RunTimeLang,
LLVMMetadataRef VTableHolder, const char *UniqueId, size_t UniqueIdLen) {
return wrap(Builder->createStructType(
return wrap(unwrap(Builder)->createStructType(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
@ -1126,12 +1127,12 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags,
uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
LLVMMetadataRef Discriminator, LLVMMetadataRef Elements,
const char *UniqueId, size_t UniqueIdLen) {
return wrap(Builder->createVariantPart(
return wrap(unwrap(Builder)->createVariantPart(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
@ -1140,36 +1141,36 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMDIFlags Flags,
LLVMMetadataRef Ty) {
return wrap(Builder->createMemberType(
return wrap(unwrap(Builder)->createMemberType(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
unwrapDI<DIFile>(File), LineNo, SizeInBits, AlignInBits, OffsetInBits,
fromRust(Flags), unwrapDI<DIType>(Ty)));
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
LLVMDIFlags Flags, LLVMMetadataRef Ty) {
llvm::ConstantInt *D = nullptr;
if (Discriminant) {
D = unwrap<llvm::ConstantInt>(Discriminant);
}
return wrap(Builder->createVariantMemberType(
return wrap(unwrap(Builder)->createVariantMemberType(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
unwrapDI<DIFile>(File), LineNo, SizeInBits, AlignInBits, OffsetInBits, D,
fromRust(Flags), unwrapDI<DIType>(Ty)));
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticMemberType(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
LLVMRustDIFlags Flags, LLVMValueRef val, uint32_t AlignInBits) {
return wrap(Builder->createStaticMemberType(
LLVMDIFlags Flags, LLVMValueRef val, uint32_t AlignInBits) {
return wrap(unwrap(Builder)->createStaticMemberType(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), fromRust(Flags),
unwrap<llvm::ConstantInt>(val), llvm::dwarf::DW_TAG_member, AlignInBits));
@ -1183,21 +1184,21 @@ LLVMRustDIBuilderCreateQualifiedType(LLVMDIBuilderRef Builder, unsigned Tag,
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateLexicalBlock(LLVMRustDIBuilderRef Builder,
LLVMRustDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Builder,
LLVMMetadataRef Scope, LLVMMetadataRef File,
unsigned Line, unsigned Col) {
return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
unwrapDI<DIFile>(File), Line, Col));
return wrap(unwrap(Builder)->createLexicalBlock(
unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Line, Col));
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlockFile(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef File) {
return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
unwrapDI<DIFile>(File)));
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef File) {
return wrap(unwrap(Builder)->createLexicalBlockFile(
unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File)));
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name,
size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
bool IsLocalToUnit, LLVMValueRef V, LLVMMetadataRef Decl = nullptr,
@ -1206,16 +1207,16 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
llvm::DIExpression *InitExpr = nullptr;
if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
InitExpr = Builder->createConstantValueExpression(
InitExpr = unwrap(Builder)->createConstantValueExpression(
IntVal->getValue().getSExtValue());
} else if (llvm::ConstantFP *FPVal =
llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
InitExpr = Builder->createConstantValueExpression(
InitExpr = unwrap(Builder)->createConstantValueExpression(
FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
}
llvm::DIGlobalVariableExpression *VarExpr =
Builder->createGlobalVariableExpression(
unwrap(Builder)->createGlobalVariableExpression(
unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
StringRef(LinkageName, LinkageNameLen), unwrapDI<DIFile>(File),
LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
@ -1228,17 +1229,17 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
LLVMDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
unsigned ArgNo, uint32_t AlignInBits) {
LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMDIFlags Flags, unsigned ArgNo,
uint32_t AlignInBits) {
if (Tag == 0x100) { // DW_TAG_auto_variable
return wrap(Builder->createAutoVariable(
return wrap(unwrap(Builder)->createAutoVariable(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve,
fromRust(Flags), AlignInBits));
} else {
return wrap(Builder->createParameterVariable(
return wrap(unwrap(Builder)->createParameterVariable(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve,
fromRust(Flags)));
@ -1246,53 +1247,56 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
LLVMRustDIBuilderCreateArrayType(LLVMDIBuilderRef Builder, uint64_t Size,
uint32_t AlignInBits, LLVMMetadataRef Ty,
LLVMMetadataRef Subscripts) {
return wrap(
Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
DINodeArray(unwrapDI<MDTuple>(Subscripts))));
return wrap(unwrap(Builder)->createArrayType(
Size, AlignInBits, unwrapDI<DIType>(Ty),
DINodeArray(unwrapDI<MDTuple>(Subscripts))));
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
LLVMRustDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Builder, int64_t Lo,
int64_t Count) {
return wrap(Builder->getOrCreateSubrange(Lo, Count));
return wrap(unwrap(Builder)->getOrCreateSubrange(Lo, Count));
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
LLVMRustDIBuilderGetOrCreateArray(LLVMDIBuilderRef Builder,
LLVMMetadataRef *Ptr, unsigned Count) {
Metadata **DataValue = unwrap(Ptr);
return wrap(
Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
return wrap(unwrap(Builder)
->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count))
.get());
}
extern "C" void LLVMRustDIBuilderInsertDeclareAtEnd(
LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
LLVMBasicBlockRef InsertAtEnd) {
Builder->insertDeclare(unwrap(V), unwrap<DILocalVariable>(VarInfo),
Builder->createExpression(
llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
DebugLoc(cast<MDNode>(unwrap(DL))),
unwrap(InsertAtEnd));
extern "C" void
LLVMRustDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef V,
LLVMMetadataRef VarInfo, uint64_t *AddrOps,
unsigned AddrOpsCount, LLVMMetadataRef DL,
LLVMBasicBlockRef InsertAtEnd) {
unwrap(Builder)->insertDeclare(
unwrap(V), unwrap<DILocalVariable>(VarInfo),
unwrap(Builder)->createExpression(
llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
DebugLoc(cast<MDNode>(unwrap(DL))), unwrap(InsertAtEnd));
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
const uint64_t Value[2], unsigned SizeInBits, bool IsUnsigned) {
return wrap(Builder->createEnumerator(
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder, const char *Name,
size_t NameLen, const uint64_t Value[2],
unsigned SizeInBits, bool IsUnsigned) {
return wrap(unwrap(Builder)->createEnumerator(
StringRef(Name, NameLen),
APSInt(APInt(SizeInBits, ArrayRef<uint64_t>(Value, 2)), IsUnsigned)));
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef Elements,
LLVMMetadataRef ClassTy, bool IsScoped) {
return wrap(Builder->createEnumerationType(
return wrap(unwrap(Builder)->createEnumerationType(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
DINodeArray(unwrapDI<MDTuple>(Elements)), unwrapDI<DIType>(ClassTy),
@ -1300,12 +1304,12 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags,
uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
LLVMMetadataRef Elements, unsigned RunTimeLang, const char *UniqueId,
size_t UniqueIdLen) {
return wrap(Builder->createUnionType(
return wrap(unwrap(Builder)->createUnionType(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
fromRust(Flags), DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
@ -1313,28 +1317,28 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
}
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, LLVMMetadataRef Ty) {
bool IsDefault = false; // FIXME: should we ever set this true?
return wrap(Builder->createTemplateTypeParameter(
return wrap(unwrap(Builder)->createTemplateTypeParameter(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
unwrapDI<DIType>(Ty), IsDefault));
}
extern "C" LLVMMetadataRef
LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder,
LLVMRustDIBuilderCreateNameSpace(LLVMDIBuilderRef Builder,
LLVMMetadataRef Scope, const char *Name,
size_t NameLen, bool ExportSymbols) {
return wrap(Builder->createNameSpace(
return wrap(unwrap(Builder)->createNameSpace(
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols));
}
extern "C" void LLVMRustDICompositeTypeReplaceArrays(
LLVMRustDIBuilderRef Builder, LLVMMetadataRef CompositeTy,
LLVMDIBuilderRef Builder, LLVMMetadataRef CompositeTy,
LLVMMetadataRef Elements, LLVMMetadataRef Params) {
DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
DINodeArray(unwrap<MDTuple>(Params)));
unwrap(Builder)->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
DINodeArray(unwrap<MDTuple>(Params)));
}
extern "C" LLVMMetadataRef

View file

@ -9,6 +9,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::memmap::{Mmap, MmapMut};
use rustc_data_structures::sync::{Lrc, join, par_for_each_in};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_data_structures::thousands::format_with_underscores;
use rustc_feature::Features;
use rustc_hir as hir;
use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId, LocalDefIdSet};
@ -22,7 +23,6 @@ use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::fast_reject::{self, TreatParams};
use rustc_middle::ty::{AssocItemContainer, SymbolName};
use rustc_middle::util::common::to_readable_str;
use rustc_middle::{bug, span_bug};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque};
use rustc_session::config::{CrateType, OptLevel};
@ -782,7 +782,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
"{} {:<23}{:>10} ({:4.1}%)",
prefix,
label,
to_readable_str(size),
format_with_underscores(size),
perc(size)
);
}
@ -791,7 +791,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
"{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
prefix,
"Total",
to_readable_str(total_bytes),
format_with_underscores(total_bytes),
perc(zero_bytes)
);
eprintln!("{prefix}");

View file

@ -17,6 +17,9 @@ middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further itera
middle_assert_misaligned_ptr_deref =
misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
middle_assert_null_ptr_deref =
null pointer dereference occurred
middle_assert_op_overflow =
attempt to compute `{$left} {$op} {$right}`, which would overflow
@ -32,6 +35,8 @@ middle_assert_shl_overflow =
middle_assert_shr_overflow =
attempt to shift right by `{$val}`, which would overflow
middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty} is unsafe
middle_bounds_check =
index out of bounds: the length is {$len} but the index is {$index}
@ -107,6 +112,8 @@ middle_type_length_limit = reached the type-length limit while instantiating `{$
middle_unknown_layout =
the type `{$ty}` has an unknown layout
middle_unsupported_union = we don't support unions yet: '{$ty_name}'
middle_values_too_big =
values of the type `{$ty}` are too big for the target architecture

View file

@ -87,6 +87,7 @@ macro_rules! arena_types {
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>,
[decode] attribute: rustc_hir::Attribute,
[] name_set: rustc_data_structures::unord::UnordSet<rustc_span::Symbol>,
[] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem,
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::Symbol>,
[] pats: rustc_middle::ty::PatternKind<'tcx>,

View file

@ -37,6 +37,20 @@ pub struct OpaqueHiddenTypeMismatch<'tcx> {
pub sub: TypeMismatchReason,
}
#[derive(Diagnostic)]
#[diag(middle_unsupported_union)]
pub struct UnsupportedUnion {
pub ty_name: String,
}
#[derive(Diagnostic)]
#[diag(middle_autodiff_unsafe_inner_const_ref)]
pub struct AutodiffUnsafeInnerConstRef {
#[primary_span]
pub span: Span,
pub ty: String,
}
#[derive(Subdiagnostic)]
pub enum TypeMismatchReason {
#[label(middle_conflict_types)]

View file

@ -1,7 +1,7 @@
//! "Hooks" provide a way for `tcx` functionality to be provided by some downstream crate without
//! everything in rustc having to depend on that crate. This is somewhat similar to queries, but
//! queries come with a lot of machinery for caching and incremental compilation, whereas hooks are
//! just plain function pointers without any of the query magic.
//! "Hooks" let you write `tcx` methods in downstream crates and call them in this crate, reducing
//! the amount of code that needs to be in this crate (which is already very big). This is somewhat
//! similar to queries, but queries come with a lot of machinery for caching and incremental
//! compilation, whereas hooks are just plain function pointers without any of the query magic.
use rustc_hir::def_id::{DefId, DefPathHash};
use rustc_session::StableCrateId;
@ -75,12 +75,6 @@ declare_hooks! {
/// (Eligible functions might nevertheless be skipped for other reasons.)
hook is_eligible_for_coverage(key: LocalDefId) -> bool;
/// Create the MIR for a given `DefId` - this includes
/// unreachable code.
/// You do not want to call this yourself, instead use the cached version
/// via `mir_built`
hook build_mir(key: LocalDefId) -> mir::Body<'tcx>;
/// Imports all `SourceFile`s from the given crate into the current session.
/// This normally happens automatically when we decode a `Span` from
/// that crate's metadata - however, the incr comp cache needs
@ -99,14 +93,11 @@ declare_hooks! {
/// Will fetch a DefId from a DefPathHash for a foreign crate.
hook def_path_hash_to_def_id_extern(hash: DefPathHash, stable_crate_id: StableCrateId) -> DefId;
/// Create a THIR tree for debugging.
hook thir_tree(key: LocalDefId) -> String;
/// Create a list-like THIR representation for debugging.
hook thir_flat(key: LocalDefId) -> String;
/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
/// can just link to the upstream crate and therefore don't need a mono item.
///
/// Note: this hook isn't called within `rustc_middle` but #127779 suggests it's a hook instead
/// of a normal function because external tools might want to override it.
hook should_codegen_locally(instance: crate::ty::Instance<'tcx>) -> bool;
hook alloc_self_profile_query_strings() -> ();

View file

@ -4,8 +4,8 @@
///
/// If you have a span available, you should use [`span_bug`] instead.
///
/// If the bug should only be emitted when compilation didn't fail, [`DiagCtxtHandle::span_delayed_bug`]
/// may be useful.
/// If the bug should only be emitted when compilation didn't fail,
/// [`DiagCtxtHandle::span_delayed_bug`] may be useful.
///
/// [`DiagCtxtHandle::span_delayed_bug`]: rustc_errors::DiagCtxtHandle::span_delayed_bug
/// [`span_bug`]: crate::span_bug
@ -14,14 +14,8 @@ macro_rules! bug {
() => (
$crate::bug!("impossible case reached")
);
($msg:expr) => (
$crate::util::bug::bug_fmt(::std::format_args!($msg))
);
($msg:expr,) => (
$crate::bug!($msg)
);
($fmt:expr, $($arg:tt)+) => (
$crate::util::bug::bug_fmt(::std::format_args!($fmt, $($arg)+))
($($arg:tt)+) => (
$crate::util::bug::bug_fmt(::std::format_args!($($arg)+))
);
}
@ -30,20 +24,14 @@ macro_rules! bug {
/// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger
/// ICEs.
///
/// If the bug should only be emitted when compilation didn't fail, [`DiagCtxtHandle::span_delayed_bug`]
/// may be useful.
/// If the bug should only be emitted when compilation didn't fail,
/// [`DiagCtxtHandle::span_delayed_bug`] may be useful.
///
/// [`DiagCtxtHandle::span_delayed_bug`]: rustc_errors::DiagCtxtHandle::span_delayed_bug
#[macro_export]
macro_rules! span_bug {
($span:expr, $msg:expr) => (
$crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg))
);
($span:expr, $msg:expr,) => (
$crate::span_bug!($span, $msg)
);
($span:expr, $fmt:expr, $($arg:tt)+) => (
$crate::util::bug::span_bug_fmt($span, ::std::format_args!($fmt, $($arg)+))
($span:expr, $($arg:tt)+) => (
$crate::util::bug::span_bug_fmt($span, ::std::format_args!($($arg)+))
);
}
@ -53,7 +41,6 @@ macro_rules! span_bug {
// When possible, use one of these (relatively) convenient macros to write
// the impls for you.
#[macro_export]
macro_rules! TrivialLiftImpls {
($($ty:ty),+ $(,)?) => {
$(
@ -69,7 +56,6 @@ macro_rules! TrivialLiftImpls {
/// Used for types that are `Copy` and which **do not care about arena
/// allocated data** (i.e., don't need to be folded).
#[macro_export]
macro_rules! TrivialTypeTraversalImpls {
($($ty:ty),+ $(,)?) => {
$(
@ -104,7 +90,6 @@ macro_rules! TrivialTypeTraversalImpls {
};
}
#[macro_export]
macro_rules! TrivialTypeTraversalAndLiftImpls {
($($t:tt)*) => {
TrivialTypeTraversalImpls! { $($t)* }

View file

@ -1,4 +1,5 @@
use rustc_abi::Align;
use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs;
use rustc_attr_parsing::{InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_span::Symbol;
@ -52,6 +53,8 @@ pub struct CodegenFnAttrs {
/// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
/// the function entry.
pub patchable_function_entry: Option<PatchableFunctionEntry>,
/// For the `#[autodiff]` macros.
pub autodiff_item: Option<AutoDiffAttrs>,
}
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
@ -160,6 +163,7 @@ impl CodegenFnAttrs {
instruction_set: None,
alignment: None,
patchable_function_entry: None,
autodiff_item: None,
}
}

View file

@ -45,15 +45,22 @@ pub enum ObjectLifetimeDefault {
Param(DefId),
}
/// Maps the id of each lifetime reference to the lifetime decl
/// Maps the id of each bound variable reference to the variable decl
/// that it corresponds to.
#[derive(HashStable, Debug)]
#[derive(Debug, Default, HashStable)]
pub struct ResolveBoundVars {
/// Maps from every use of a named (not anonymous) lifetime to a
/// `Region` describing how that region is bound
// Maps from every use of a named (not anonymous) bound var to a
// `ResolvedArg` describing how that variable is bound.
pub defs: SortedMap<ItemLocalId, ResolvedArg>,
// Maps relevant hir items to the bound vars on them. These include:
// - function defs
// - function pointers
// - closures
// - trait refs
// - bound types (like `T` in `for<'a> T<'a>: Foo`)
pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>,
// List captured variables for each opaque type.
pub opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>,
}

View file

@ -27,7 +27,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisit
use rustc_serialize::{Decodable, Encodable};
use rustc_span::source_map::Spanned;
use rustc_span::{DUMMY_SP, Span, Symbol};
use tracing::trace;
use tracing::{debug, trace};
pub use self::query::*;
use self::visit::TyContext;
@ -1796,6 +1796,47 @@ impl DefLocation {
}
}
/// Checks if the specified `local` is used as the `self` parameter of a method call
/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
/// returned.
pub fn find_self_call<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
local: Local,
block: BasicBlock,
) -> Option<(DefId, GenericArgsRef<'tcx>)> {
debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator);
if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
&body[block].terminator
&& let Operand::Constant(box ConstOperand { const_, .. }) = func
&& let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
&& let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
tcx.opt_associated_item(def_id)
&& let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
**args
{
if self_place.as_local() == Some(local) {
return Some((def_id, fn_args));
}
// Handle the case where `self_place` gets reborrowed.
// This happens when the receiver is `&T`.
for stmt in &body[block].statements {
if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind
&& let Some(reborrow_local) = place.as_local()
&& self_place.as_local() == Some(reborrow_local)
&& let Rvalue::Ref(_, _, deref_place) = rvalue
&& let PlaceRef { local: deref_local, projection: [ProjectionElem::Deref] } =
deref_place.as_ref()
&& deref_local == local
{
return Some((def_id, fn_args));
}
}
}
None
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {

View file

@ -1,6 +1,7 @@
use std::fmt;
use std::hash::Hash;
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
use rustc_attr_parsing::InlineAttr;
use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::fingerprint::Fingerprint;
@ -246,6 +247,7 @@ impl ToStableHashKey<StableHashingContext<'_>> for MonoItem<'_> {
pub struct MonoItemPartitions<'tcx> {
pub codegen_units: &'tcx [CodegenUnit<'tcx>],
pub all_mono_items: &'tcx DefIdSet,
pub autodiff_items: &'tcx [AutoDiffItem],
}
#[derive(Debug, HashStable)]

View file

@ -1076,6 +1076,7 @@ pub enum AssertKind<O> {
ResumedAfterReturn(CoroutineKind),
ResumedAfterPanic(CoroutineKind),
MisalignedPointerDereference { required: O, found: O },
NullPointerDereference,
}
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]

View file

@ -206,6 +206,7 @@ impl<O> AssertKind<O> {
ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => {
LangItem::PanicGenFnNonePanic
}
NullPointerDereference => LangItem::PanicNullPointerDereference,
BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
bug!("Unexpected AssertKind")
@ -271,6 +272,7 @@ impl<O> AssertKind<O> {
"\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {required:?}, {found:?}"
)
}
NullPointerDereference => write!(f, "\"null pointer dereference occured\""),
ResumedAfterReturn(CoroutineKind::Coroutine(_)) => {
write!(f, "\"coroutine resumed after completion\"")
}
@ -341,7 +343,7 @@ impl<O> AssertKind<O> {
ResumedAfterPanic(CoroutineKind::Coroutine(_)) => {
middle_assert_coroutine_resume_after_panic
}
NullPointerDereference => middle_assert_null_ptr_deref,
MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref,
}
}
@ -374,7 +376,7 @@ impl<O> AssertKind<O> {
add!("left", format!("{left:#?}"));
add!("right", format!("{right:#?}"));
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) => {}
ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference => {}
MisalignedPointerDereference { required, found } => {
add!("required", format!("{required:#?}"));
add!("found", format!("{found:#?}"));

View file

@ -636,7 +636,7 @@ macro_rules! make_mir_visitor {
OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
self.visit_operand(op, location);
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference => {
// Nothing to visit
}
MisalignedPointerDereference { required, found } => {

View file

@ -95,7 +95,7 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
}
}
impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
impl<'tcx> Key for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) {
type Cache<V> = DefaultCache<Self, V>;
fn default_span(&self, _: TyCtxt<'_>) -> Span {

View file

@ -1437,9 +1437,9 @@ rustc_queries! {
desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) }
}
query vtable_entries(key: ty::PolyTraitRef<'tcx>)
query vtable_entries(key: ty::TraitRef<'tcx>)
-> &'tcx [ty::VtblEntry<'tcx>] {
desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) }
desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id) }
}
query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize {
@ -1451,7 +1451,7 @@ rustc_queries! {
key.1, key.0 }
}
query vtable_allocation(key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId {
query vtable_allocation(key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId {
desc { |tcx| "vtable const allocation for <{} as {}>",
key.0,
key.1.map(|trait_ref| format!("{trait_ref}")).unwrap_or("_".to_owned())

View file

@ -428,7 +428,7 @@ pub enum IsConstable {
Ctor,
}
crate::TrivialTypeTraversalAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
IsConstable,
}

View file

@ -858,7 +858,12 @@ where
}
let mk_dyn_vtable = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
let min_count = ty::vtable_min_entries(tcx, principal);
let min_count = ty::vtable_min_entries(
tcx,
principal.map(|principal| {
tcx.instantiate_bound_regions_with_erased(principal)
}),
);
Ty::new_imm_ref(
tcx,
tcx.lifetimes.re_static,

View file

@ -4,7 +4,7 @@ use crate::ty::{self, ExistentialPredicateStableCmpExt, TyCtxt};
impl<'tcx> TyCtxt<'tcx> {
/// Given a `def_id` of a trait or impl method, compute whether that method needs to
/// have an RPITIT shim applied to it for it to be object safe. If so, return the
/// have an RPITIT shim applied to it for it to be dyn compatible. If so, return the
/// `def_id` of the RPITIT, and also the args of trait method that returns the RPITIT.
///
/// NOTE that these args are not, in general, the same as than the RPITIT's args. They

View file

@ -7,7 +7,7 @@ use rustc_type_ir::elaborate;
use crate::mir::interpret::{
AllocId, AllocInit, Allocation, CTFE_ALLOC_SALT, Pointer, Scalar, alloc_range,
};
use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
use crate::ty::{self, Instance, TraitRef, Ty, TyCtxt};
#[derive(Clone, Copy, PartialEq, HashStable)]
pub enum VtblEntry<'tcx> {
@ -22,7 +22,7 @@ pub enum VtblEntry<'tcx> {
/// dispatchable associated function
Method(Instance<'tcx>),
/// pointer to a separate supertrait vtable, can be used by trait upcasting coercion
TraitVPtr(PolyTraitRef<'tcx>),
TraitVPtr(TraitRef<'tcx>),
}
impl<'tcx> fmt::Debug for VtblEntry<'tcx> {
@ -59,7 +59,7 @@ pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2;
// function is an accurate approximation. We verify this when actually computing the vtable below.
pub(crate) fn vtable_min_entries<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
) -> usize {
let mut count = TyCtxt::COMMON_VTABLE_ENTRIES.len();
let Some(trait_ref) = trait_ref else {
@ -67,7 +67,7 @@ pub(crate) fn vtable_min_entries<'tcx>(
};
// This includes self in supertraits.
for def_id in elaborate::supertrait_def_ids(tcx, trait_ref.def_id()) {
for def_id in elaborate::supertrait_def_ids(tcx, trait_ref.def_id) {
count += tcx.own_existential_vtable_entries(def_id).len();
}
@ -83,7 +83,7 @@ pub(crate) fn vtable_min_entries<'tcx>(
/// initial contents.)
pub(super) fn vtable_allocation_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>),
) -> AllocId {
let (ty, poly_trait_ref) = key;
@ -118,7 +118,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
for (idx, entry) in vtable_entries.iter().enumerate() {
let idx: u64 = u64::try_from(idx).unwrap();
let scalar = match entry {
let scalar = match *entry {
VtblEntry::MetadataDropInPlace => {
if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) {
let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
@ -134,13 +134,12 @@ pub(super) fn vtable_allocation_provider<'tcx>(
VtblEntry::Vacant => continue,
VtblEntry::Method(instance) => {
// Prepare the fn ptr we write into the vtable.
let fn_alloc_id = tcx.reserve_and_set_fn_alloc(*instance, CTFE_ALLOC_SALT);
let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT);
let fn_ptr = Pointer::from(fn_alloc_id);
Scalar::from_pointer(fn_ptr, &tcx)
}
VtblEntry::TraitVPtr(trait_ref) => {
let super_trait_ref = trait_ref
.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
let super_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref);
let supertrait_alloc_id = tcx.vtable_allocation((ty, Some(super_trait_ref)));
let vptr = Pointer::from(supertrait_alloc_id);
Scalar::from_pointer(vptr, &tcx)

View file

@ -1,4 +1,4 @@
// These functions are used by macro expansion for bug! and span_bug!
// These functions are used by macro expansion for `bug!` and `span_bug!`.
use std::fmt;
use std::panic::{Location, panic_any};
@ -8,15 +8,15 @@ use rustc_span::Span;
use crate::ty::{TyCtxt, tls};
// This wrapper makes for more compact code at callsites than calling `opt_span_buf_fmt` directly.
#[cold]
#[inline(never)]
#[track_caller]
pub fn bug_fmt(args: fmt::Arguments<'_>) -> ! {
// this wrapper mostly exists so I don't have to write a fully
// qualified path of None::<Span> inside the bug!() macro definition
opt_span_bug_fmt(None::<Span>, args, Location::caller());
}
// This wrapper makes for more compact code at callsites than calling `opt_span_buf_fmt` directly.
#[cold]
#[inline(never)]
#[track_caller]

View file

@ -1,22 +0,0 @@
#[cfg(test)]
mod tests;
pub fn to_readable_str(mut val: usize) -> String {
let mut groups = vec![];
loop {
let group = val % 1000;
val /= 1000;
if val == 0 {
groups.push(group.to_string());
break;
} else {
groups.push(format!("{group:03}"));
}
}
groups.reverse();
groups.join("_")
}

View file

@ -1,14 +0,0 @@
use super::*;
#[test]
fn test_to_readable_str() {
assert_eq!("0", to_readable_str(0));
assert_eq!("1", to_readable_str(1));
assert_eq!("99", to_readable_str(99));
assert_eq!("999", to_readable_str(999));
assert_eq!("1_000", to_readable_str(1_000));
assert_eq!("1_001", to_readable_str(1_001));
assert_eq!("999_999", to_readable_str(999_999));
assert_eq!("1_000_000", to_readable_str(1_000_000));
assert_eq!("1_234_567", to_readable_str(1_234_567));
}

View file

@ -1,47 +0,0 @@
use rustc_span::def_id::DefId;
use rustc_span::source_map::Spanned;
use tracing::debug;
use crate::mir::*;
use crate::ty::{self, GenericArgsRef, TyCtxt};
/// Checks if the specified `local` is used as the `self` parameter of a method call
/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
/// returned.
pub fn find_self_call<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
local: Local,
block: BasicBlock,
) -> Option<(DefId, GenericArgsRef<'tcx>)> {
debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator);
if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
&body[block].terminator
&& let Operand::Constant(box ConstOperand { const_, .. }) = func
&& let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
&& let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
tcx.opt_associated_item(def_id)
&& let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
**args
{
if self_place.as_local() == Some(local) {
return Some((def_id, fn_args));
}
// Handle the case where `self_place` gets reborrowed.
// This happens when the receiver is `&T`.
for stmt in &body[block].statements {
if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind
&& let Some(reborrow_local) = place.as_local()
&& self_place.as_local() == Some(reborrow_local)
&& let Rvalue::Ref(_, _, deref_place) = rvalue
&& let PlaceRef { local: deref_local, projection: [ProjectionElem::Deref] } =
deref_place.as_ref()
&& deref_local == local
{
return Some((def_id, fn_args));
}
}
}
None
}

View file

@ -1,8 +1,4 @@
pub mod bug;
pub mod common;
pub mod find_self_call;
pub use find_self_call::find_self_call;
#[derive(Default, Copy, Clone)]
pub struct Providers {

View file

@ -6,7 +6,7 @@
//! present, and if so we branch off into this module, which implements the attribute by
//! implementing a custom lowering from THIR to MIR.
//!
//! The result of this lowering is returned "normally" from the `build_mir` hook, with the only
//! The result of this lowering is returned "normally" from `build_mir`, with the only
//! notable difference being that the `injected` field in the body is set. Various components of the
//! MIR pipeline, like borrowck and the pass manager will then consult this field (via
//! `body.should_skip()`) to skip the parts of the MIR pipeline that precede the MIR phase the user

View file

@ -20,7 +20,6 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
use rustc_middle::middle::region;
use rustc_middle::mir::*;
use rustc_middle::query::TyCtxtAt;
use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir};
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_middle::{bug, span_bug};
@ -45,9 +44,9 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
.collect()
}
/// Construct the MIR for a given `DefId`.
pub(crate) fn build_mir<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx> {
let tcx = tcx.tcx;
/// Create the MIR for a given `DefId`, including unreachable code. Do not call
/// this directly; instead use the cached version via `mir_built`.
pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> {
tcx.ensure_with_value().thir_abstract_const(def);
if let Err(e) = tcx.check_match(def) {
return construct_error(tcx, def, e);

View file

@ -14,11 +14,11 @@
// The `builder` module used to be named `build`, but that was causing GitHub's
// "Go to file" feature to silently ignore all files in the module, probably
// because it assumes that "build" is a build-output directory. See #134365.
mod builder;
pub mod builder;
mod check_tail_calls;
mod check_unsafety;
mod errors;
mod thir;
pub mod thir;
use rustc_middle::util::Providers;
@ -27,12 +27,9 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
pub fn provide(providers: &mut Providers) {
providers.check_match = thir::pattern::check_match;
providers.lit_to_const = thir::constant::lit_to_const;
providers.hooks.build_mir = builder::build_mir;
providers.closure_saved_names_of_captured_variables =
builder::closure_saved_names_of_captured_variables;
providers.check_unsafety = check_unsafety::check_unsafety;
providers.check_tail_calls = check_tail_calls::check_tail_calls;
providers.thir_body = thir::cx::thir_body;
providers.hooks.thir_tree = thir::print::thir_tree;
providers.hooks.thir_flat = thir::print::thir_flat;
}

View file

@ -7,5 +7,5 @@
pub(crate) mod constant;
pub(crate) mod cx;
pub(crate) mod pattern;
pub(crate) mod print;
pub mod print;
mod util;

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