Auto merge of #3684 - rust-lang:rustup-2024-06-18, r=RalfJung
Automatic Rustup
This commit is contained in:
commit
62ef90cf46
167 changed files with 2090 additions and 1537 deletions
|
|
@ -97,7 +97,6 @@ Cargo
|
|||
- [Prevent dashes in `lib.name`, always normalizing to `_`.](https://github.com/rust-lang/cargo/pull/12783/)
|
||||
- [Stabilize MSRV-aware version requirement selection in `cargo add`.](https://github.com/rust-lang/cargo/pull/13608/)
|
||||
- [Switch to using `gitoxide` by default for listing files.](https://github.com/rust-lang/cargo/pull/13696/)
|
||||
- [Error on `[project]` in Edition 2024; `cargo fix --edition` will change it to `[package]`.](https://github.com/rust-lang/cargo/pull/13747/)
|
||||
|
||||
<a id="1.79.0-Rustdoc"></a>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_hir::intravisit::Visitor;
|
|||
use rustc_hir::{self as hir, BindingMode, ByRef, Node};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
|
||||
use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, Upcast};
|
||||
use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, Upcast};
|
||||
use rustc_middle::{
|
||||
hir::place::PlaceBase,
|
||||
mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
|
||||
|
|
@ -937,56 +937,81 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
let node = self.infcx.tcx.hir_node(fn_call_id);
|
||||
let def_id = hir.enclosing_body_owner(fn_call_id);
|
||||
let mut look_at_return = true;
|
||||
// If we can detect the expression to be an `fn` call where the closure was an argument,
|
||||
// we point at the `fn` definition argument...
|
||||
if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Call(func, args), .. }) = node {
|
||||
let arg_pos = args
|
||||
|
||||
// If the HIR node is a function or method call gets the def ID
|
||||
// of the called function or method and the span and args of the call expr
|
||||
let get_call_details = || {
|
||||
let hir::Node::Expr(hir::Expr { hir_id, kind, .. }) = node else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let typeck_results = self.infcx.tcx.typeck(def_id);
|
||||
|
||||
match kind {
|
||||
hir::ExprKind::Call(expr, args) => {
|
||||
if let Some(ty::FnDef(def_id, _)) =
|
||||
typeck_results.node_type_opt(expr.hir_id).as_ref().map(|ty| ty.kind())
|
||||
{
|
||||
Some((*def_id, expr.span, *args))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
hir::ExprKind::MethodCall(_, _, args, span) => {
|
||||
if let Some(def_id) = typeck_results.type_dependent_def_id(*hir_id) {
|
||||
Some((def_id, *span, *args))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
||||
// If we can detect the expression to be an function or method call where the closure was an argument,
|
||||
// we point at the function or method definition argument...
|
||||
if let Some((callee_def_id, call_span, call_args)) = get_call_details() {
|
||||
let arg_pos = call_args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, arg)| arg.hir_id == closure_id)
|
||||
.map(|(pos, _)| pos)
|
||||
.next();
|
||||
let tables = self.infcx.tcx.typeck(def_id);
|
||||
if let Some(ty::FnDef(def_id, _)) =
|
||||
tables.node_type_opt(func.hir_id).as_ref().map(|ty| ty.kind())
|
||||
{
|
||||
let arg = match hir.get_if_local(*def_id) {
|
||||
Some(
|
||||
hir::Node::Item(hir::Item {
|
||||
ident, kind: hir::ItemKind::Fn(sig, ..), ..
|
||||
|
||||
let arg = match hir.get_if_local(callee_def_id) {
|
||||
Some(
|
||||
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
|
||||
| hir::Node::TraitItem(hir::TraitItem {
|
||||
ident,
|
||||
kind: hir::TraitItemKind::Fn(sig, _),
|
||||
..
|
||||
})
|
||||
| hir::Node::ImplItem(hir::ImplItem {
|
||||
ident,
|
||||
kind: hir::ImplItemKind::Fn(sig, _),
|
||||
..
|
||||
}),
|
||||
) => Some(
|
||||
arg_pos
|
||||
.and_then(|pos| {
|
||||
sig.decl.inputs.get(
|
||||
pos + if sig.decl.implicit_self.has_implicit_self() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)
|
||||
})
|
||||
| hir::Node::TraitItem(hir::TraitItem {
|
||||
ident,
|
||||
kind: hir::TraitItemKind::Fn(sig, _),
|
||||
..
|
||||
})
|
||||
| hir::Node::ImplItem(hir::ImplItem {
|
||||
ident,
|
||||
kind: hir::ImplItemKind::Fn(sig, _),
|
||||
..
|
||||
}),
|
||||
) => Some(
|
||||
arg_pos
|
||||
.and_then(|pos| {
|
||||
sig.decl.inputs.get(
|
||||
pos + if sig.decl.implicit_self.has_implicit_self() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)
|
||||
})
|
||||
.map(|arg| arg.span)
|
||||
.unwrap_or(ident.span),
|
||||
),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(span) = arg {
|
||||
err.span_label(span, "change this to accept `FnMut` instead of `Fn`");
|
||||
err.span_label(func.span, "expects `Fn` instead of `FnMut`");
|
||||
err.span_label(closure_span, "in this closure");
|
||||
look_at_return = false;
|
||||
}
|
||||
.map(|arg| arg.span)
|
||||
.unwrap_or(ident.span),
|
||||
),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(span) = arg {
|
||||
err.span_label(span, "change this to accept `FnMut` instead of `Fn`");
|
||||
err.span_label(call_span, "expects `Fn` instead of `FnMut`");
|
||||
err.span_label(closure_span, "in this closure");
|
||||
look_at_return = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1020,7 +1045,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
fn suggest_using_iter_mut(&self, err: &mut Diag<'_>) {
|
||||
let source = self.body.source;
|
||||
let hir = self.infcx.tcx.hir();
|
||||
if let InstanceDef::Item(def_id) = source.instance
|
||||
if let InstanceKind::Item(def_id) = source.instance
|
||||
&& let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) = hir.get_if_local(def_id)
|
||||
&& let ExprKind::Closure(hir::Closure { kind: hir::ClosureKind::Closure, .. }) = kind
|
||||
&& let Node::Expr(expr) = self.infcx.tcx.parent_hir_node(*hir_id)
|
||||
|
|
|
|||
|
|
@ -628,9 +628,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
| GenericArgKind::Const(_),
|
||||
_,
|
||||
) => {
|
||||
// This was previously a `span_delayed_bug` and could be
|
||||
// reached by the test for #82126, but no longer.
|
||||
self.dcx().span_bug(
|
||||
self.dcx().span_delayed_bug(
|
||||
hir_arg.span(),
|
||||
format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -399,7 +399,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
}
|
||||
|
||||
match instance.def {
|
||||
InstanceDef::Intrinsic(_) => {
|
||||
InstanceKind::Intrinsic(_) => {
|
||||
match crate::intrinsics::codegen_intrinsic_call(
|
||||
fx,
|
||||
instance,
|
||||
|
|
@ -412,7 +412,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
Err(instance) => Some(instance),
|
||||
}
|
||||
}
|
||||
InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) => {
|
||||
InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) => {
|
||||
// empty drop glue - a nop.
|
||||
let dest = target.expect("Non terminating drop_in_place_real???");
|
||||
let ret_block = fx.get_block(dest);
|
||||
|
|
@ -494,7 +494,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
|
||||
let (func_ref, first_arg_override) = match instance {
|
||||
// Trait object call
|
||||
Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => {
|
||||
Some(Instance { def: InstanceKind::Virtual(_, idx), .. }) => {
|
||||
if fx.clif_comments.enabled() {
|
||||
let nop_inst = fx.bcx.ins().nop();
|
||||
fx.add_comment(
|
||||
|
|
@ -598,7 +598,7 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
let ty = drop_place.layout().ty;
|
||||
let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty).polymorphize(fx.tcx);
|
||||
|
||||
if let ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) =
|
||||
if let ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) =
|
||||
drop_instance.def
|
||||
{
|
||||
// we don't actually need to drop anything
|
||||
|
|
@ -630,7 +630,7 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
// FIXME(eddyb) perhaps move some of this logic into
|
||||
// `Instance::resolve_drop_in_place`?
|
||||
let virtual_drop = Instance {
|
||||
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
|
||||
def: ty::InstanceKind::Virtual(drop_instance.def_id(), 0),
|
||||
args: drop_instance.args,
|
||||
};
|
||||
let fn_abi =
|
||||
|
|
@ -673,7 +673,7 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
fx.bcx.switch_to_block(continued);
|
||||
|
||||
let virtual_drop = Instance {
|
||||
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
|
||||
def: ty::InstanceKind::Virtual(drop_instance.def_id(), 0),
|
||||
args: drop_instance.args,
|
||||
};
|
||||
let fn_abi =
|
||||
|
|
@ -684,7 +684,7 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
|
||||
}
|
||||
_ => {
|
||||
assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
|
||||
assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _)));
|
||||
|
||||
let fn_abi =
|
||||
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, ty::List::empty());
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ pub(crate) fn codegen_tls_ref<'tcx>(
|
|||
) -> CValue<'tcx> {
|
||||
let tls_ptr = if !def_id.is_local() && fx.tcx.needs_thread_local_shim(def_id) {
|
||||
let instance = ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
def: ty::InstanceKind::ThreadLocalShim(def_id),
|
||||
args: ty::GenericArgs::empty(),
|
||||
};
|
||||
let func_ref = fx.get_function_ref(instance);
|
||||
|
|
|
|||
|
|
@ -1261,7 +1261,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
}
|
||||
|
||||
// Unimplemented intrinsics must have a fallback body. The fallback body is obtained
|
||||
// by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`.
|
||||
// by converting the `InstanceKind::Intrinsic` to an `InstanceKind::Item`.
|
||||
_ => {
|
||||
let intrinsic = fx.tcx.intrinsic(instance.def_id()).unwrap();
|
||||
if intrinsic.must_be_overridden {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ mod prelude {
|
|||
pub(crate) use rustc_middle::mir::{self, *};
|
||||
pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
pub(crate) use rustc_middle::ty::{
|
||||
self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, UintTy,
|
||||
self, FloatTy, Instance, InstanceKind, IntTy, ParamEnv, Ty, TyCtxt, UintTy,
|
||||
};
|
||||
pub(crate) use rustc_span::Span;
|
||||
pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT};
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ fn exported_symbols_provider_local(
|
|||
|
||||
if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() {
|
||||
use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
|
||||
use rustc_middle::ty::InstanceDef;
|
||||
use rustc_middle::ty::InstanceKind;
|
||||
|
||||
// Normally, we require that shared monomorphizations are not hidden,
|
||||
// because if we want to re-use a monomorphization from a Rust dylib, it
|
||||
|
|
@ -337,7 +337,7 @@ fn exported_symbols_provider_local(
|
|||
}
|
||||
|
||||
match *mono_item {
|
||||
MonoItem::Fn(Instance { def: InstanceDef::Item(def), args }) => {
|
||||
MonoItem::Fn(Instance { def: InstanceKind::Item(def), args }) => {
|
||||
if args.non_erasable_generics(tcx, def).next().is_some() {
|
||||
let symbol = ExportedSymbol::Generic(def, args);
|
||||
symbols.push((
|
||||
|
|
@ -350,7 +350,7 @@ fn exported_symbols_provider_local(
|
|||
));
|
||||
}
|
||||
}
|
||||
MonoItem::Fn(Instance { def: InstanceDef::DropGlue(def_id, Some(ty)), args }) => {
|
||||
MonoItem::Fn(Instance { def: InstanceKind::DropGlue(def_id, Some(ty)), args }) => {
|
||||
// A little sanity-check
|
||||
debug_assert_eq!(
|
||||
args.non_erasable_generics(tcx, def_id).next(),
|
||||
|
|
@ -366,7 +366,7 @@ fn exported_symbols_provider_local(
|
|||
));
|
||||
}
|
||||
MonoItem::Fn(Instance {
|
||||
def: InstanceDef::AsyncDropGlueCtorShim(def_id, Some(ty)),
|
||||
def: InstanceKind::AsyncDropGlueCtorShim(def_id, Some(ty)),
|
||||
args,
|
||||
}) => {
|
||||
// A little sanity-check
|
||||
|
|
@ -556,7 +556,7 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
|
|||
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
|
||||
tcx,
|
||||
ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
def: ty::InstanceKind::ThreadLocalShim(def_id),
|
||||
args: ty::GenericArgs::empty(),
|
||||
},
|
||||
instantiating_crate,
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let ty = self.monomorphize(ty);
|
||||
let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
|
||||
|
||||
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
|
||||
if let ty::InstanceKind::DropGlue(_, None) = drop_fn.def {
|
||||
// we don't actually need to drop anything.
|
||||
return helper.funclet_br(self, bx, target, mergeable_succ);
|
||||
}
|
||||
|
|
@ -541,7 +541,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// \-------/
|
||||
//
|
||||
let virtual_drop = Instance {
|
||||
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
|
||||
def: ty::InstanceKind::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
|
||||
args: drop_fn.args,
|
||||
};
|
||||
debug!("ty = {:?}", ty);
|
||||
|
|
@ -583,7 +583,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
//
|
||||
// SO THEN WE CAN USE THE ABOVE CODE.
|
||||
let virtual_drop = Instance {
|
||||
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
|
||||
def: ty::InstanceKind::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
|
||||
args: drop_fn.args,
|
||||
};
|
||||
debug!("ty = {:?}", ty);
|
||||
|
|
@ -855,7 +855,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let def = instance.map(|i| i.def);
|
||||
|
||||
if let Some(
|
||||
ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None),
|
||||
ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None),
|
||||
) = def
|
||||
{
|
||||
// Empty drop glue; a no-op.
|
||||
|
|
@ -871,7 +871,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
// Handle intrinsics old codegen wants Expr's for, ourselves.
|
||||
let intrinsic = match def {
|
||||
Some(ty::InstanceDef::Intrinsic(def_id)) => Some(bx.tcx().intrinsic(def_id).unwrap()),
|
||||
Some(ty::InstanceKind::Intrinsic(def_id)) => Some(bx.tcx().intrinsic(def_id).unwrap()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
|
@ -1026,7 +1026,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
'make_args: for (i, arg) in first_args.iter().enumerate() {
|
||||
let mut op = self.codegen_operand(bx, &arg.node);
|
||||
|
||||
if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
|
||||
if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, def) {
|
||||
match op.val {
|
||||
Pair(data_ptr, meta) => {
|
||||
// In the case of Rc<Self>, we need to explicitly pass a
|
||||
|
|
|
|||
|
|
@ -704,7 +704,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let static_ = if !def_id.is_local() && bx.cx().tcx().needs_thread_local_shim(def_id)
|
||||
{
|
||||
let instance = ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
def: ty::InstanceKind::ThreadLocalShim(def_id),
|
||||
args: ty::GenericArgs::empty(),
|
||||
};
|
||||
let fn_ptr = bx.get_fn_addr(instance);
|
||||
|
|
|
|||
|
|
@ -399,7 +399,6 @@ const_eval_unwind_past_top =
|
|||
|
||||
## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`.
|
||||
## (We'd love to sort this differently to make that more clear but tidy won't let us...)
|
||||
const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
|
||||
const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty}
|
||||
|
||||
const_eval_validation_const_ref_to_extern = {$front_matter}: encountered reference to `extern` static in `const`
|
||||
|
|
@ -454,7 +453,6 @@ const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but
|
|||
const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers
|
||||
const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected}
|
||||
const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
|
||||
const_eval_validation_ref_to_static = {$front_matter}: encountered a reference pointing to a static variable in a constant
|
||||
const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
|
||||
const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
|
||||
const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC
|
|||
use rustc_middle::mir::*;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{Instance, InstanceDef, TypeVisitableExt};
|
||||
use rustc_middle::ty::{Instance, InstanceKind, TypeVisitableExt};
|
||||
use rustc_mir_dataflow::Analysis;
|
||||
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
|
|
@ -769,7 +769,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
|
||||
if let Ok(Some(instance)) =
|
||||
Instance::resolve(tcx, param_env, callee, fn_args)
|
||||
&& let InstanceDef::Item(def) = instance.def
|
||||
&& let InstanceKind::Item(def) = instance.def
|
||||
{
|
||||
// Resolve a trait method call to its concrete implementation, which may be in a
|
||||
// `const` trait impl. This is only used for the const stability check below, since
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
|
|||
|
||||
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
|
||||
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
|
||||
if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
|
||||
if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def {
|
||||
let ty = key.value.instance.ty(tcx, key.param_env);
|
||||
let ty::FnDef(_, args) = ty.kind() else {
|
||||
bug!("intrinsic with type {:?}", ty);
|
||||
|
|
|
|||
|
|
@ -398,10 +398,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
|
|||
|
||||
fn load_mir(
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
instance: ty::InstanceKind<'tcx>,
|
||||
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
|
||||
match instance {
|
||||
ty::InstanceDef::Item(def) => Ok(ecx.tcx.mir_for_ctfe(def)),
|
||||
ty::InstanceKind::Item(def) => Ok(ecx.tcx.mir_for_ctfe(def)),
|
||||
_ => Ok(ecx.tcx.instance_mir(instance)),
|
||||
}
|
||||
}
|
||||
|
|
@ -424,7 +424,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
|
|||
};
|
||||
|
||||
// Only check non-glue functions
|
||||
if let ty::InstanceDef::Item(def) = instance.def {
|
||||
if let ty::InstanceKind::Item(def) = instance.def {
|
||||
// Execution might have wandered off into other crates, so we cannot do a stability-
|
||||
// sensitive check here. But we can at least rule out functions that are not const at
|
||||
// all. That said, we have to allow calling functions inside a trait marked with
|
||||
|
|
@ -540,7 +540,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
|
|||
);
|
||||
}
|
||||
return Ok(Some(ty::Instance {
|
||||
def: ty::InstanceDef::Item(instance.def_id()),
|
||||
def: ty::InstanceKind::Item(instance.def_id()),
|
||||
args: instance.args,
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -640,9 +640,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
const_eval_validation_ref_to_uninhabited
|
||||
}
|
||||
|
||||
PtrToStatic { ptr_kind: PointerKind::Box } => const_eval_validation_box_to_static,
|
||||
PtrToStatic { ptr_kind: PointerKind::Ref(_) } => const_eval_validation_ref_to_static,
|
||||
|
||||
PointerAsInt { .. } => const_eval_validation_pointer_as_int,
|
||||
PartialPointer => const_eval_validation_partial_pointer,
|
||||
ConstRefToMutable => const_eval_validation_const_ref_to_mutable,
|
||||
|
|
@ -807,7 +804,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
);
|
||||
}
|
||||
NullPtr { .. }
|
||||
| PtrToStatic { .. }
|
||||
| ConstRefToMutable
|
||||
| ConstRefToExtern
|
||||
| MutableRefToImmutable
|
||||
|
|
|
|||
|
|
@ -562,7 +562,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
|
||||
pub fn load_mir(
|
||||
&self,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
instance: ty::InstanceKind<'tcx>,
|
||||
promoted: Option<mir::Promoted>,
|
||||
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
|
||||
trace!("load mir(instance={:?}, promoted={:?})", instance, promoted);
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ pub trait Machine<'tcx>: Sized {
|
|||
/// constants, ...
|
||||
fn load_mir(
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
instance: ty::InstanceKind<'tcx>,
|
||||
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
|
||||
Ok(ecx.tcx.instance_mir(instance))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
Drop { place, target, unwind, replace: _ } => {
|
||||
let place = self.eval_place(place)?;
|
||||
let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
|
||||
if let ty::InstanceDef::DropGlue(_, None) = instance.def {
|
||||
if let ty::InstanceKind::DropGlue(_, None) = instance.def {
|
||||
// This is the branch we enter if and only if the dropped type has no drop glue
|
||||
// whatsoever. This can happen as a result of monomorphizing a drop of a
|
||||
// generic. In order to make sure that generic and non-generic code behaves
|
||||
|
|
@ -550,7 +550,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
};
|
||||
|
||||
match instance.def {
|
||||
ty::InstanceDef::Intrinsic(def_id) => {
|
||||
ty::InstanceKind::Intrinsic(def_id) => {
|
||||
assert!(self.tcx.intrinsic(def_id).is_some());
|
||||
// FIXME: Should `InPlace` arguments be reset to uninit?
|
||||
if let Some(fallback) = M::call_intrinsic(
|
||||
|
|
@ -562,7 +562,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
unwind,
|
||||
)? {
|
||||
assert!(!self.tcx.intrinsic(fallback.def_id()).unwrap().must_be_overridden);
|
||||
assert!(matches!(fallback.def, ty::InstanceDef::Item(_)));
|
||||
assert!(matches!(fallback.def, ty::InstanceKind::Item(_)));
|
||||
return self.eval_fn_call(
|
||||
FnVal::Instance(fallback),
|
||||
(caller_abi, caller_fn_abi),
|
||||
|
|
@ -576,18 +576,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
ty::InstanceDef::VTableShim(..)
|
||||
| ty::InstanceDef::ReifyShim(..)
|
||||
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineKindShim { .. }
|
||||
| ty::InstanceDef::FnPtrShim(..)
|
||||
| ty::InstanceDef::DropGlue(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::FnPtrAddrShim(..)
|
||||
| ty::InstanceDef::ThreadLocalShim(..)
|
||||
| ty::InstanceDef::AsyncDropGlueCtorShim(..)
|
||||
| ty::InstanceDef::Item(_) => {
|
||||
ty::InstanceKind::VTableShim(..)
|
||||
| ty::InstanceKind::ReifyShim(..)
|
||||
| ty::InstanceKind::ClosureOnceShim { .. }
|
||||
| ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceKind::CoroutineKindShim { .. }
|
||||
| ty::InstanceKind::FnPtrShim(..)
|
||||
| ty::InstanceKind::DropGlue(..)
|
||||
| ty::InstanceKind::CloneShim(..)
|
||||
| ty::InstanceKind::FnPtrAddrShim(..)
|
||||
| ty::InstanceKind::ThreadLocalShim(..)
|
||||
| ty::InstanceKind::AsyncDropGlueCtorShim(..)
|
||||
| ty::InstanceKind::Item(_) => {
|
||||
// We need MIR for this fn
|
||||
let Some((body, instance)) = M::find_mir_or_eval_fn(
|
||||
self,
|
||||
|
|
@ -786,9 +786,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
Ok(()) => Ok(()),
|
||||
}
|
||||
}
|
||||
// `InstanceDef::Virtual` does not have callable MIR. Calls to `Virtual` instances must be
|
||||
// `InstanceKind::Virtual` does not have callable MIR. Calls to `Virtual` instances must be
|
||||
// codegen'd / interpreted as virtual calls through the vtable.
|
||||
ty::InstanceDef::Virtual(def_id, idx) => {
|
||||
ty::InstanceKind::Virtual(def_id, idx) => {
|
||||
let mut args = args.to_vec();
|
||||
// We have to implement all "object safe receivers". So we have to go search for a
|
||||
// pointer or `dyn Trait` type, but it could be wrapped in newtypes. So recursively
|
||||
|
|
@ -965,7 +965,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
let place = self.force_allocation(place)?;
|
||||
|
||||
// We behave a bit different from codegen here.
|
||||
// Codegen creates an `InstanceDef::Virtual` with index 0 (the slot of the drop method) and
|
||||
// Codegen creates an `InstanceKind::Virtual` with index 0 (the slot of the drop method) and
|
||||
// then dispatches that to the normal call machinery. However, our call machinery currently
|
||||
// only supports calling `VtblEntry::Method`; it would choke on a `MetadataDropInPlace`. So
|
||||
// instead we do the virtual call stuff ourselves. It's easier here than in `eval_fn_call`
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ where
|
|||
| ty::CoroutineClosure(def_id, args, ..)
|
||||
| ty::Coroutine(def_id, args, ..)
|
||||
| ty::FnDef(def_id, args) => {
|
||||
let instance = ty::InstanceDef::Item(def_id);
|
||||
let instance = ty::InstanceKind::Item(def_id);
|
||||
let unused_params = self.tcx.unused_generic_params(instance);
|
||||
for (index, arg) in args.into_iter().enumerate() {
|
||||
let index = index
|
||||
|
|
|
|||
|
|
@ -750,16 +750,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
/// Resolves an associated value path into a base type and associated constant, or method
|
||||
/// resolution. The newly resolved definition is written into `type_dependent_defs`.
|
||||
#[instrument(level = "trace", skip(self), ret)]
|
||||
pub fn resolve_ty_and_res_fully_qualified_call(
|
||||
&self,
|
||||
qpath: &'tcx QPath<'tcx>,
|
||||
hir_id: HirId,
|
||||
span: Span,
|
||||
) -> (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) {
|
||||
debug!(
|
||||
"resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}",
|
||||
qpath, hir_id, span
|
||||
);
|
||||
let (ty, qself, item_segment) = match *qpath {
|
||||
QPath::Resolved(ref opt_qself, path) => {
|
||||
return (
|
||||
|
|
@ -1417,10 +1414,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// This also occurs for an enum variant on a type alias.
|
||||
let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
|
||||
let self_ty = self.normalize(span, self_ty);
|
||||
match self.at(&self.misc(span), self.param_env).eq(
|
||||
match self.at(&self.misc(span), self.param_env).sub(
|
||||
DefineOpaqueTypes::Yes,
|
||||
impl_ty,
|
||||
self_ty,
|
||||
impl_ty,
|
||||
) {
|
||||
Ok(ok) => self.register_infer_ok_obligations(ok),
|
||||
Err(_) => {
|
||||
|
|
|
|||
|
|
@ -756,7 +756,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
|| tcx.hir().body_const_context(def_id).is_some()
|
||||
{
|
||||
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
|
||||
tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id()));
|
||||
tcx.ensure().unused_generic_params(ty::InstanceKind::Item(def_id.to_def_id()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ lint_associated_const_elided_lifetime = {$elided ->
|
|||
*[false] `'_` cannot be used here
|
||||
}
|
||||
.suggestion = use the `'static` lifetime
|
||||
.note = cannot automatically infer `'static` because of other lifetimes in scope
|
||||
|
||||
lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified
|
||||
.note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`
|
||||
|
|
|
|||
|
|
@ -319,11 +319,20 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
|
|||
BuiltinLintDiag::UnusedQualifications { removal_span } => {
|
||||
lints::UnusedQualifications { removal_span }.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span } => {
|
||||
BuiltinLintDiag::AssociatedConstElidedLifetime {
|
||||
elided,
|
||||
span: lt_span,
|
||||
lifetimes_in_scope,
|
||||
} => {
|
||||
let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span };
|
||||
let code = if elided { "'static " } else { "'static" };
|
||||
lints::AssociatedConstElidedLifetime { span: lt_span, code, elided }
|
||||
.decorate_lint(diag);
|
||||
lints::AssociatedConstElidedLifetime {
|
||||
span: lt_span,
|
||||
code,
|
||||
elided,
|
||||
lifetimes_in_scope,
|
||||
}
|
||||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::RedundantImportVisibility { max_vis, span: vis_span, import_vis } => {
|
||||
lints::RedundantImportVisibility { span: vis_span, help: (), max_vis, import_vis }
|
||||
|
|
|
|||
|
|
@ -2873,6 +2873,8 @@ pub struct AssociatedConstElidedLifetime {
|
|||
|
||||
pub code: &'static str,
|
||||
pub elided: bool,
|
||||
#[note]
|
||||
pub lifetimes_in_scope: MultiSpan,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
|
|||
|
|
@ -4593,16 +4593,18 @@ declare_lint! {
|
|||
|
||||
declare_lint! {
|
||||
/// The `elided_lifetimes_in_associated_constant` lint detects elided lifetimes
|
||||
/// that were erroneously allowed in associated constants.
|
||||
/// in associated constants when there are other lifetimes in scope. This was
|
||||
/// accidentally supported, and this lint was later relaxed to allow eliding
|
||||
/// lifetimes to `'static` when there are no lifetimes in scope.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(elided_lifetimes_in_associated_constant)]
|
||||
///
|
||||
/// struct Foo;
|
||||
/// struct Foo<'a>(&'a ());
|
||||
///
|
||||
/// impl Foo {
|
||||
/// impl<'a> Foo<'a> {
|
||||
/// const STR: &str = "hello, world";
|
||||
/// }
|
||||
/// ```
|
||||
|
|
|
|||
|
|
@ -696,6 +696,7 @@ pub enum BuiltinLintDiag {
|
|||
AssociatedConstElidedLifetime {
|
||||
elided: bool,
|
||||
span: Span,
|
||||
lifetimes_in_scope: MultiSpan,
|
||||
},
|
||||
RedundantImportVisibility {
|
||||
span: Span,
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ impl IntoArgs for (CrateNum, DefId) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> IntoArgs for ty::InstanceDef<'tcx> {
|
||||
impl<'tcx> IntoArgs for ty::InstanceKind<'tcx> {
|
||||
type Other = ();
|
||||
fn into_args(self) -> (DefId, ()) {
|
||||
(self.def_id(), ())
|
||||
|
|
|
|||
|
|
@ -1693,7 +1693,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses);
|
||||
}
|
||||
|
||||
let instance = ty::InstanceDef::Item(def_id.to_def_id());
|
||||
let instance = ty::InstanceKind::Item(def_id.to_def_id());
|
||||
let unused = tcx.unused_generic_params(instance);
|
||||
self.tables.unused_generic_params.set(def_id.local_def_index, unused);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ macro_rules! arena_types {
|
|||
rustc_hir::def_id::DefId,
|
||||
rustc_middle::ty::EarlyBinder<'tcx, rustc_middle::ty::Ty<'tcx>>
|
||||
>,
|
||||
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
|
||||
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<rustc_middle::ty::TyCtxt<'tcx>>,
|
||||
[] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>,
|
||||
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
|
||||
[] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem,
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ impl<'tcx> ExportedSymbol<'tcx> {
|
|||
tcx.symbol_name(ty::Instance::resolve_async_drop_in_place(tcx, ty))
|
||||
}
|
||||
ExportedSymbol::ThreadLocalShim(def_id) => tcx.symbol_name(ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
def: ty::InstanceKind::ThreadLocalShim(def_id),
|
||||
args: ty::GenericArgs::empty(),
|
||||
}),
|
||||
ExportedSymbol::NoDefId(symbol_name) => symbol_name,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ where
|
|||
if tcx.is_const_fn_raw(*def_id) {
|
||||
vec![tcx.optimized_mir(*def_id), tcx.mir_for_ctfe(*def_id)]
|
||||
} else {
|
||||
vec![tcx.instance_mir(ty::InstanceDef::Item(*def_id))]
|
||||
vec![tcx.instance_mir(ty::InstanceKind::Item(*def_id))]
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
|
|
|||
|
|
@ -438,9 +438,6 @@ pub enum ValidationErrorKind<'tcx> {
|
|||
ptr_kind: PointerKind,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
PtrToStatic {
|
||||
ptr_kind: PointerKind,
|
||||
},
|
||||
ConstRefToMutable,
|
||||
ConstRefToExtern,
|
||||
MutableRefToImmutable,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
|
|||
use crate::ty::print::{FmtPrinter, Printer};
|
||||
use crate::ty::visit::TypeVisitableExt;
|
||||
use crate::ty::{self, List, Ty, TyCtxt};
|
||||
use crate::ty::{AdtDef, Instance, InstanceDef, UserTypeAnnotationIndex};
|
||||
use crate::ty::{AdtDef, Instance, InstanceKind, UserTypeAnnotationIndex};
|
||||
use crate::ty::{GenericArg, GenericArgsRef};
|
||||
|
||||
use rustc_data_structures::captures::Captures;
|
||||
|
|
@ -233,7 +233,7 @@ impl RuntimePhase {
|
|||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
|
||||
pub struct MirSource<'tcx> {
|
||||
pub instance: InstanceDef<'tcx>,
|
||||
pub instance: InstanceKind<'tcx>,
|
||||
|
||||
/// If `Some`, this is a promoted rvalue within the parent function.
|
||||
pub promoted: Option<Promoted>,
|
||||
|
|
@ -241,10 +241,10 @@ pub struct MirSource<'tcx> {
|
|||
|
||||
impl<'tcx> MirSource<'tcx> {
|
||||
pub fn item(def_id: DefId) -> Self {
|
||||
MirSource { instance: InstanceDef::Item(def_id), promoted: None }
|
||||
MirSource { instance: InstanceKind::Item(def_id), promoted: None }
|
||||
}
|
||||
|
||||
pub fn from_instance(instance: InstanceDef<'tcx>) -> Self {
|
||||
pub fn from_instance(instance: InstanceKind<'tcx>) -> Self {
|
||||
MirSource { instance, promoted: None }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
|
||||
use crate::ty::{GenericArgs, Instance, InstanceDef, SymbolName, TyCtxt};
|
||||
use crate::ty::{GenericArgs, Instance, InstanceKind, SymbolName, TyCtxt};
|
||||
use rustc_attr::InlineAttr;
|
||||
use rustc_data_structures::base_n::BaseNString;
|
||||
use rustc_data_structures::base_n::ToBaseN;
|
||||
|
|
@ -56,7 +56,7 @@ impl<'tcx> MonoItem<'tcx> {
|
|||
/// Returns `true` if the mono item is user-defined (i.e. not compiler-generated, like shims).
|
||||
pub fn is_user_defined(&self) -> bool {
|
||||
match *self {
|
||||
MonoItem::Fn(instance) => matches!(instance.def, InstanceDef::Item(..)),
|
||||
MonoItem::Fn(instance) => matches!(instance.def, InstanceKind::Item(..)),
|
||||
MonoItem::Static(..) | MonoItem::GlobalAsm(..) => true,
|
||||
}
|
||||
}
|
||||
|
|
@ -69,9 +69,9 @@ impl<'tcx> MonoItem<'tcx> {
|
|||
match instance.def {
|
||||
// "Normal" functions size estimate: the number of
|
||||
// statements, plus one for the terminator.
|
||||
InstanceDef::Item(..)
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::AsyncDropGlueCtorShim(..) => {
|
||||
InstanceKind::Item(..)
|
||||
| InstanceKind::DropGlue(..)
|
||||
| InstanceKind::AsyncDropGlueCtorShim(..) => {
|
||||
let mir = tcx.instance_mir(instance.def);
|
||||
mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
|
||||
}
|
||||
|
|
@ -407,20 +407,20 @@ impl<'tcx> CodegenUnit<'tcx> {
|
|||
// instances into account. The others don't matter for
|
||||
// the codegen tests and can even make item order
|
||||
// unstable.
|
||||
InstanceDef::Item(def) => def.as_local().map(Idx::index),
|
||||
InstanceDef::VTableShim(..)
|
||||
| InstanceDef::ReifyShim(..)
|
||||
| InstanceDef::Intrinsic(..)
|
||||
| InstanceDef::FnPtrShim(..)
|
||||
| InstanceDef::Virtual(..)
|
||||
| InstanceDef::ClosureOnceShim { .. }
|
||||
| InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceDef::CoroutineKindShim { .. }
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::CloneShim(..)
|
||||
| InstanceDef::ThreadLocalShim(..)
|
||||
| InstanceDef::FnPtrAddrShim(..)
|
||||
| InstanceDef::AsyncDropGlueCtorShim(..) => None,
|
||||
InstanceKind::Item(def) => def.as_local().map(Idx::index),
|
||||
InstanceKind::VTableShim(..)
|
||||
| InstanceKind::ReifyShim(..)
|
||||
| InstanceKind::Intrinsic(..)
|
||||
| InstanceKind::FnPtrShim(..)
|
||||
| InstanceKind::Virtual(..)
|
||||
| InstanceKind::ClosureOnceShim { .. }
|
||||
| InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceKind::CoroutineKindShim { .. }
|
||||
| InstanceKind::DropGlue(..)
|
||||
| InstanceKind::CloneShim(..)
|
||||
| InstanceKind::ThreadLocalShim(..)
|
||||
| InstanceKind::FnPtrAddrShim(..)
|
||||
| InstanceKind::AsyncDropGlueCtorShim(..) => None,
|
||||
}
|
||||
}
|
||||
MonoItem::Static(def_id) => def_id.as_local().map(Idx::index),
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ fn dump_path<'tcx>(
|
|||
// All drop shims have the same DefId, so we have to add the type
|
||||
// to get unique file names.
|
||||
let shim_disambiguator = match source.instance {
|
||||
ty::InstanceDef::DropGlue(_, Some(ty)) => {
|
||||
ty::InstanceKind::DropGlue(_, Some(ty)) => {
|
||||
// Unfortunately, pretty-printed typed are not very filename-friendly.
|
||||
// We dome some filtering.
|
||||
let mut s = ".".to_owned();
|
||||
|
|
@ -188,7 +188,7 @@ fn dump_path<'tcx>(
|
|||
}));
|
||||
s
|
||||
}
|
||||
ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) => {
|
||||
ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)) => {
|
||||
// Unfortunately, pretty-printed typed are not very filename-friendly.
|
||||
// We dome some filtering.
|
||||
let mut s = ".".to_owned();
|
||||
|
|
@ -280,7 +280,7 @@ pub fn write_mir_pretty<'tcx>(
|
|||
// are shared between mir_for_ctfe and optimized_mir
|
||||
write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w)?;
|
||||
} else {
|
||||
let instance_mir = tcx.instance_mir(ty::InstanceDef::Item(def_id));
|
||||
let instance_mir = tcx.instance_mir(ty::InstanceKind::Item(def_id));
|
||||
render_body(w, instance_mir)?;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -337,27 +337,27 @@ macro_rules! make_mir_visitor {
|
|||
|
||||
let ty::Instance { def: callee_def, args: callee_args } = callee;
|
||||
match callee_def {
|
||||
ty::InstanceDef::Item(_def_id) => {}
|
||||
ty::InstanceKind::Item(_def_id) => {}
|
||||
|
||||
ty::InstanceDef::Intrinsic(_def_id) |
|
||||
ty::InstanceDef::VTableShim(_def_id) |
|
||||
ty::InstanceDef::ReifyShim(_def_id, _) |
|
||||
ty::InstanceDef::Virtual(_def_id, _) |
|
||||
ty::InstanceDef::ThreadLocalShim(_def_id) |
|
||||
ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
|
||||
ty::InstanceDef::ConstructCoroutineInClosureShim {
|
||||
ty::InstanceKind::Intrinsic(_def_id) |
|
||||
ty::InstanceKind::VTableShim(_def_id) |
|
||||
ty::InstanceKind::ReifyShim(_def_id, _) |
|
||||
ty::InstanceKind::Virtual(_def_id, _) |
|
||||
ty::InstanceKind::ThreadLocalShim(_def_id) |
|
||||
ty::InstanceKind::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
|
||||
ty::InstanceKind::ConstructCoroutineInClosureShim {
|
||||
coroutine_closure_def_id: _def_id,
|
||||
receiver_by_ref: _,
|
||||
} |
|
||||
ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id } |
|
||||
ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, None) |
|
||||
ty::InstanceDef::DropGlue(_def_id, None) => {}
|
||||
ty::InstanceKind::CoroutineKindShim { coroutine_def_id: _def_id } |
|
||||
ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, None) |
|
||||
ty::InstanceKind::DropGlue(_def_id, None) => {}
|
||||
|
||||
ty::InstanceDef::FnPtrShim(_def_id, ty) |
|
||||
ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
|
||||
ty::InstanceDef::CloneShim(_def_id, ty) |
|
||||
ty::InstanceDef::FnPtrAddrShim(_def_id, ty) |
|
||||
ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, Some(ty)) => {
|
||||
ty::InstanceKind::FnPtrShim(_def_id, ty) |
|
||||
ty::InstanceKind::DropGlue(_def_id, Some(ty)) |
|
||||
ty::InstanceKind::CloneShim(_def_id, ty) |
|
||||
ty::InstanceKind::FnPtrAddrShim(_def_id, ty) |
|
||||
ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, Some(ty)) => {
|
||||
// FIXME(eddyb) use a better `TyContext` here.
|
||||
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ tcx_lifetime! {
|
|||
rustc_middle::ty::GenericPredicates,
|
||||
rustc_middle::ty::inhabitedness::InhabitedPredicate,
|
||||
rustc_middle::ty::Instance,
|
||||
rustc_middle::ty::InstanceDef,
|
||||
rustc_middle::ty::InstanceKind,
|
||||
rustc_middle::ty::layout::FnAbiError,
|
||||
rustc_middle::ty::layout::LayoutError,
|
||||
rustc_middle::ty::ParamEnv,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ impl Key for () {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for ty::InstanceDef<'tcx> {
|
||||
impl<'tcx> Key for ty::InstanceKind<'tcx> {
|
||||
type Cache<V> = DefaultCache<Self, V>;
|
||||
|
||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||
|
|
@ -70,7 +70,7 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> AsLocalKey for ty::InstanceDef<'tcx> {
|
||||
impl<'tcx> AsLocalKey for ty::InstanceKind<'tcx> {
|
||||
type LocalKey = Self;
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
|||
|
|
@ -575,7 +575,7 @@ rustc_queries! {
|
|||
/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass
|
||||
/// (for compiler option `-Cinstrument-coverage`), after MIR optimizations
|
||||
/// have had a chance to potentially remove some of them.
|
||||
query coverage_ids_info(key: ty::InstanceDef<'tcx>) -> &'tcx mir::CoverageIdsInfo {
|
||||
query coverage_ids_info(key: ty::InstanceKind<'tcx>) -> &'tcx mir::CoverageIdsInfo {
|
||||
desc { |tcx| "retrieving coverage IDs info from MIR for `{}`", tcx.def_path_str(key.def_id()) }
|
||||
arena_cache
|
||||
}
|
||||
|
|
@ -1033,7 +1033,7 @@ rustc_queries! {
|
|||
}
|
||||
|
||||
/// Obtain all the calls into other local functions
|
||||
query mir_inliner_callees(key: ty::InstanceDef<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] {
|
||||
query mir_inliner_callees(key: ty::InstanceKind<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] {
|
||||
fatal_cycle
|
||||
desc { |tcx|
|
||||
"computing all local function calls in `{}`",
|
||||
|
|
@ -1140,7 +1140,7 @@ rustc_queries! {
|
|||
}
|
||||
|
||||
/// Generates a MIR body for the shim.
|
||||
query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> {
|
||||
query mir_shims(key: ty::InstanceKind<'tcx>) -> &'tcx mir::Body<'tcx> {
|
||||
arena_cache
|
||||
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
|
||||
}
|
||||
|
|
@ -1410,7 +1410,7 @@ rustc_queries! {
|
|||
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
|
||||
///
|
||||
/// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
|
||||
/// instead, where the instance is an `InstanceDef::Virtual`.
|
||||
/// instead, where the instance is an `InstanceKind::Virtual`.
|
||||
query fn_abi_of_fn_ptr(
|
||||
key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
|
||||
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
|
||||
|
|
@ -1421,7 +1421,7 @@ rustc_queries! {
|
|||
/// direct calls to an `fn`.
|
||||
///
|
||||
/// NB: that includes virtual calls, which are represented by "direct calls"
|
||||
/// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
|
||||
/// to an `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
|
||||
query fn_abi_of_instance(
|
||||
key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
|
||||
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
|
||||
|
|
@ -1918,7 +1918,7 @@ rustc_queries! {
|
|||
desc { "getting codegen unit `{sym}`" }
|
||||
}
|
||||
|
||||
query unused_generic_params(key: ty::InstanceDef<'tcx>) -> UnusedGenericParams {
|
||||
query unused_generic_params(key: ty::InstanceKind<'tcx>) -> UnusedGenericParams {
|
||||
cache_on_disk_if { key.def_id().is_local() }
|
||||
desc {
|
||||
|tcx| "determining which generic parameters are unused by `{}`",
|
||||
|
|
|
|||
|
|
@ -32,54 +32,7 @@ use std::hash::{Hash, Hasher};
|
|||
|
||||
pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
|
||||
// FIXME: Remove this import and import via `solve::`
|
||||
pub use rustc_type_ir::solve::BuiltinImplSource;
|
||||
|
||||
/// Depending on the stage of compilation, we want projection to be
|
||||
/// more or less conservative.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)]
|
||||
pub enum Reveal {
|
||||
/// At type-checking time, we refuse to project any associated
|
||||
/// type that is marked `default`. Non-`default` ("final") types
|
||||
/// are always projected. This is necessary in general for
|
||||
/// soundness of specialization. However, we *could* allow
|
||||
/// projections in fully-monomorphic cases. We choose not to,
|
||||
/// because we prefer for `default type` to force the type
|
||||
/// definition to be treated abstractly by any consumers of the
|
||||
/// impl. Concretely, that means that the following example will
|
||||
/// fail to compile:
|
||||
///
|
||||
/// ```compile_fail,E0308
|
||||
/// #![feature(specialization)]
|
||||
/// trait Assoc {
|
||||
/// type Output;
|
||||
/// }
|
||||
///
|
||||
/// impl<T> Assoc for T {
|
||||
/// default type Output = bool;
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let x: <() as Assoc>::Output = true;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// We also do not reveal the hidden type of opaque types during
|
||||
/// type-checking.
|
||||
UserFacing,
|
||||
|
||||
/// At codegen time, all monomorphic projections will succeed.
|
||||
/// Also, `impl Trait` is normalized to the concrete type,
|
||||
/// which has to be already collected by type-checking.
|
||||
///
|
||||
/// NOTE: as `impl Trait`'s concrete type should *never*
|
||||
/// be observable directly by the user, `Reveal::All`
|
||||
/// should not be used by checks which may expose
|
||||
/// type equality or type contents to the user.
|
||||
/// There are some exceptions, e.g., around auto traits and
|
||||
/// transmute-checking, which expose some details, but
|
||||
/// not the whole concrete type of the `impl Trait`.
|
||||
All,
|
||||
}
|
||||
pub use rustc_type_ir::solve::{BuiltinImplSource, Reveal};
|
||||
|
||||
/// The reason why we incurred this obligation; used for error reporting.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use rustc_ast_ir::try_visit;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_type_ir as ir;
|
||||
pub use rustc_type_ir::solve::*;
|
||||
|
||||
use crate::infer::canonical::QueryRegionConstraints;
|
||||
use crate::ty::{
|
||||
self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
|
||||
};
|
||||
|
|
@ -38,37 +37,18 @@ impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)]
|
||||
pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>);
|
||||
pub struct ExternalConstraints<'tcx>(
|
||||
pub(crate) Interned<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>>,
|
||||
);
|
||||
|
||||
impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
|
||||
type Target = ExternalConstraintsData<'tcx>;
|
||||
type Target = ExternalConstraintsData<TyCtxt<'tcx>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional constraints returned on success.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)]
|
||||
pub struct ExternalConstraintsData<'tcx> {
|
||||
// FIXME: implement this.
|
||||
pub region_constraints: QueryRegionConstraints<'tcx>,
|
||||
pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
|
||||
pub normalization_nested_goals: NestedNormalizationGoals<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)]
|
||||
pub struct NestedNormalizationGoals<'tcx>(pub Vec<(GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>);
|
||||
impl<'tcx> NestedNormalizationGoals<'tcx> {
|
||||
pub fn empty() -> Self {
|
||||
NestedNormalizationGoals(vec![])
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Having to clone `region_constraints` for folding feels bad and
|
||||
// probably isn't great wrt performance.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ use std::ops::{Bound, Deref};
|
|||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
type DefId = DefId;
|
||||
type LocalDefId = LocalDefId;
|
||||
type AdtDef = ty::AdtDef<'tcx>;
|
||||
|
||||
type GenericArgs = ty::GenericArgsRef<'tcx>;
|
||||
|
|
@ -382,7 +383,7 @@ pub struct CtxtInterners<'tcx> {
|
|||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
||||
layout: InternedSet<'tcx, LayoutS<FieldIdx, VariantIdx>>,
|
||||
adt_def: InternedSet<'tcx, AdtDefData>,
|
||||
external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
|
||||
external_constraints: InternedSet<'tcx, ExternalConstraintsData<TyCtxt<'tcx>>>,
|
||||
predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
|
||||
fields: InternedSet<'tcx, List<FieldIdx>>,
|
||||
local_def_ids: InternedSet<'tcx, List<LocalDefId>>,
|
||||
|
|
@ -2093,7 +2094,7 @@ direct_interners! {
|
|||
const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
|
||||
layout: pub mk_layout(LayoutS<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>,
|
||||
adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
|
||||
external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
|
||||
external_constraints: pub mk_external_constraints(ExternalConstraintsData<TyCtxt<'tcx>>):
|
||||
ExternalConstraints -> ExternalConstraints<'tcx>,
|
||||
predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData<'tcx>):
|
||||
PredefinedOpaques -> PredefinedOpaques<'tcx>,
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ use tracing::{debug, instrument};
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::fmt;
|
||||
|
||||
/// A monomorphized `InstanceDef`.
|
||||
/// An `InstanceKind` along with the args that are needed to substitute the instance.
|
||||
///
|
||||
/// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type
|
||||
/// simply couples a potentially generic `InstanceDef` with some args, and codegen and const eval
|
||||
/// simply couples a potentially generic `InstanceKind` with some args, and codegen and const eval
|
||||
/// will do all required instantiations as they run.
|
||||
///
|
||||
/// Note: the `Lift` impl is currently not used by rustc, but is used by
|
||||
|
|
@ -30,7 +30,7 @@ use std::fmt;
|
|||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, Lift, TypeFoldable, TypeVisitable)]
|
||||
pub struct Instance<'tcx> {
|
||||
pub def: InstanceDef<'tcx>,
|
||||
pub def: InstanceKind<'tcx>,
|
||||
pub args: GenericArgsRef<'tcx>,
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ pub enum ReifyReason {
|
|||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub enum InstanceDef<'tcx> {
|
||||
pub enum InstanceKind<'tcx> {
|
||||
/// A user-defined callable item.
|
||||
///
|
||||
/// This includes:
|
||||
|
|
@ -69,7 +69,7 @@ pub enum InstanceDef<'tcx> {
|
|||
|
||||
/// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI).
|
||||
///
|
||||
/// Alongside `Virtual`, this is the only `InstanceDef` that does not have its own callable MIR.
|
||||
/// Alongside `Virtual`, this is the only `InstanceKind` that does not have its own callable MIR.
|
||||
/// Instead, codegen and const eval "magically" evaluate calls to intrinsics purely in the
|
||||
/// caller.
|
||||
Intrinsic(DefId),
|
||||
|
|
@ -85,7 +85,7 @@ pub enum InstanceDef<'tcx> {
|
|||
///
|
||||
/// One example is `<dyn Trait as Trait>::fn`, where the shim contains
|
||||
/// a virtual call, which codegen supports only via a direct call to the
|
||||
/// `<dyn Trait as Trait>::fn` instance (an `InstanceDef::Virtual`).
|
||||
/// `<dyn Trait as Trait>::fn` instance (an `InstanceKind::Virtual`).
|
||||
///
|
||||
/// Another example is functions annotated with `#[track_caller]`, which
|
||||
/// must have their implicit caller location argument populated for a call.
|
||||
|
|
@ -107,7 +107,7 @@ pub enum InstanceDef<'tcx> {
|
|||
|
||||
/// Dynamic dispatch to `<dyn Trait as Trait>::fn`.
|
||||
///
|
||||
/// This `InstanceDef` does not have callable MIR. Calls to `Virtual` instances must be
|
||||
/// This `InstanceKind` does not have callable MIR. Calls to `Virtual` instances must be
|
||||
/// codegen'd as virtual calls through the vtable.
|
||||
///
|
||||
/// If this is reified to a `fn` pointer, a `ReifyShim` is used (see `ReifyShim` above for more
|
||||
|
|
@ -216,10 +216,10 @@ impl<'tcx> Instance<'tcx> {
|
|||
}
|
||||
|
||||
match self.def {
|
||||
InstanceDef::Item(def) => tcx
|
||||
InstanceKind::Item(def) => tcx
|
||||
.upstream_monomorphizations_for(def)
|
||||
.and_then(|monos| monos.get(&self.args).cloned()),
|
||||
InstanceDef::DropGlue(_, Some(_)) | InstanceDef::AsyncDropGlueCtorShim(_, _) => {
|
||||
InstanceKind::DropGlue(_, Some(_)) | InstanceKind::AsyncDropGlueCtorShim(_, _) => {
|
||||
tcx.upstream_drop_glue_for(self.args)
|
||||
}
|
||||
_ => None,
|
||||
|
|
@ -227,48 +227,48 @@ impl<'tcx> Instance<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> InstanceDef<'tcx> {
|
||||
impl<'tcx> InstanceKind<'tcx> {
|
||||
#[inline]
|
||||
pub fn def_id(self) -> DefId {
|
||||
match self {
|
||||
InstanceDef::Item(def_id)
|
||||
| InstanceDef::VTableShim(def_id)
|
||||
| InstanceDef::ReifyShim(def_id, _)
|
||||
| InstanceDef::FnPtrShim(def_id, _)
|
||||
| InstanceDef::Virtual(def_id, _)
|
||||
| InstanceDef::Intrinsic(def_id)
|
||||
| InstanceDef::ThreadLocalShim(def_id)
|
||||
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
|
||||
| ty::InstanceDef::ConstructCoroutineInClosureShim {
|
||||
InstanceKind::Item(def_id)
|
||||
| InstanceKind::VTableShim(def_id)
|
||||
| InstanceKind::ReifyShim(def_id, _)
|
||||
| InstanceKind::FnPtrShim(def_id, _)
|
||||
| InstanceKind::Virtual(def_id, _)
|
||||
| InstanceKind::Intrinsic(def_id)
|
||||
| InstanceKind::ThreadLocalShim(def_id)
|
||||
| InstanceKind::ClosureOnceShim { call_once: def_id, track_caller: _ }
|
||||
| ty::InstanceKind::ConstructCoroutineInClosureShim {
|
||||
coroutine_closure_def_id: def_id,
|
||||
receiver_by_ref: _,
|
||||
}
|
||||
| ty::InstanceDef::CoroutineKindShim { coroutine_def_id: def_id }
|
||||
| InstanceDef::DropGlue(def_id, _)
|
||||
| InstanceDef::CloneShim(def_id, _)
|
||||
| InstanceDef::FnPtrAddrShim(def_id, _)
|
||||
| InstanceDef::AsyncDropGlueCtorShim(def_id, _) => def_id,
|
||||
| ty::InstanceKind::CoroutineKindShim { coroutine_def_id: def_id }
|
||||
| InstanceKind::DropGlue(def_id, _)
|
||||
| InstanceKind::CloneShim(def_id, _)
|
||||
| InstanceKind::FnPtrAddrShim(def_id, _)
|
||||
| InstanceKind::AsyncDropGlueCtorShim(def_id, _) => def_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `DefId` of instances which might not require codegen locally.
|
||||
pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
|
||||
match self {
|
||||
ty::InstanceDef::Item(def) => Some(def),
|
||||
ty::InstanceDef::DropGlue(def_id, Some(_))
|
||||
| InstanceDef::AsyncDropGlueCtorShim(def_id, _)
|
||||
| InstanceDef::ThreadLocalShim(def_id) => Some(def_id),
|
||||
InstanceDef::VTableShim(..)
|
||||
| InstanceDef::ReifyShim(..)
|
||||
| InstanceDef::FnPtrShim(..)
|
||||
| InstanceDef::Virtual(..)
|
||||
| InstanceDef::Intrinsic(..)
|
||||
| InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineKindShim { .. }
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::CloneShim(..)
|
||||
| InstanceDef::FnPtrAddrShim(..) => None,
|
||||
ty::InstanceKind::Item(def) => Some(def),
|
||||
ty::InstanceKind::DropGlue(def_id, Some(_))
|
||||
| InstanceKind::AsyncDropGlueCtorShim(def_id, _)
|
||||
| InstanceKind::ThreadLocalShim(def_id) => Some(def_id),
|
||||
InstanceKind::VTableShim(..)
|
||||
| InstanceKind::ReifyShim(..)
|
||||
| InstanceKind::FnPtrShim(..)
|
||||
| InstanceKind::Virtual(..)
|
||||
| InstanceKind::Intrinsic(..)
|
||||
| InstanceKind::ClosureOnceShim { .. }
|
||||
| ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceKind::CoroutineKindShim { .. }
|
||||
| InstanceKind::DropGlue(..)
|
||||
| InstanceKind::CloneShim(..)
|
||||
| InstanceKind::FnPtrAddrShim(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -289,10 +289,10 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
let def_id = match *self {
|
||||
ty::InstanceDef::Item(def) => def,
|
||||
ty::InstanceDef::DropGlue(_, Some(_)) => return false,
|
||||
ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(_)) => return false,
|
||||
ty::InstanceDef::ThreadLocalShim(_) => return false,
|
||||
ty::InstanceKind::Item(def) => def,
|
||||
ty::InstanceKind::DropGlue(_, Some(_)) => return false,
|
||||
ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => return false,
|
||||
ty::InstanceKind::ThreadLocalShim(_) => return false,
|
||||
_ => return true,
|
||||
};
|
||||
matches!(
|
||||
|
|
@ -312,7 +312,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
if self.requires_inline(tcx) {
|
||||
return true;
|
||||
}
|
||||
if let ty::InstanceDef::DropGlue(.., Some(ty)) = *self {
|
||||
if let ty::InstanceKind::DropGlue(.., Some(ty)) = *self {
|
||||
// Drop glue generally wants to be instantiated at every codegen
|
||||
// unit, but without an #[inline] hint. We should make this
|
||||
// available to normal end-users.
|
||||
|
|
@ -332,7 +332,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
.map_or_else(|| adt_def.is_enum(), |dtor| tcx.cross_crate_inlinable(dtor.did))
|
||||
});
|
||||
}
|
||||
if let ty::InstanceDef::ThreadLocalShim(..) = *self {
|
||||
if let ty::InstanceKind::ThreadLocalShim(..) = *self {
|
||||
return false;
|
||||
}
|
||||
tcx.cross_crate_inlinable(self.def_id())
|
||||
|
|
@ -340,10 +340,10 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
|
||||
pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
match *self {
|
||||
InstanceDef::Item(def_id) | InstanceDef::Virtual(def_id, _) => {
|
||||
InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => {
|
||||
tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
|
||||
}
|
||||
InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller,
|
||||
InstanceKind::ClosureOnceShim { call_once: _, track_caller } => track_caller,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
@ -356,22 +356,22 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
/// body should perform necessary instantiations.
|
||||
pub fn has_polymorphic_mir_body(&self) -> bool {
|
||||
match *self {
|
||||
InstanceDef::CloneShim(..)
|
||||
| InstanceDef::ThreadLocalShim(..)
|
||||
| InstanceDef::FnPtrAddrShim(..)
|
||||
| InstanceDef::FnPtrShim(..)
|
||||
| InstanceDef::DropGlue(_, Some(_))
|
||||
| InstanceDef::AsyncDropGlueCtorShim(_, Some(_)) => false,
|
||||
InstanceDef::ClosureOnceShim { .. }
|
||||
| InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceDef::CoroutineKindShim { .. }
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::AsyncDropGlueCtorShim(..)
|
||||
| InstanceDef::Item(_)
|
||||
| InstanceDef::Intrinsic(..)
|
||||
| InstanceDef::ReifyShim(..)
|
||||
| InstanceDef::Virtual(..)
|
||||
| InstanceDef::VTableShim(..) => true,
|
||||
InstanceKind::CloneShim(..)
|
||||
| InstanceKind::ThreadLocalShim(..)
|
||||
| InstanceKind::FnPtrAddrShim(..)
|
||||
| InstanceKind::FnPtrShim(..)
|
||||
| InstanceKind::DropGlue(_, Some(_))
|
||||
| InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => false,
|
||||
InstanceKind::ClosureOnceShim { .. }
|
||||
| InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceKind::CoroutineKindShim { .. }
|
||||
| InstanceKind::DropGlue(..)
|
||||
| InstanceKind::AsyncDropGlueCtorShim(..)
|
||||
| InstanceKind::Item(_)
|
||||
| InstanceKind::Intrinsic(..)
|
||||
| InstanceKind::ReifyShim(..)
|
||||
| InstanceKind::Virtual(..)
|
||||
| InstanceKind::VTableShim(..) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -395,24 +395,24 @@ fn fmt_instance(
|
|||
})?;
|
||||
|
||||
match instance.def {
|
||||
InstanceDef::Item(_) => Ok(()),
|
||||
InstanceDef::VTableShim(_) => write!(f, " - shim(vtable)"),
|
||||
InstanceDef::ReifyShim(_, None) => write!(f, " - shim(reify)"),
|
||||
InstanceDef::ReifyShim(_, Some(ReifyReason::FnPtr)) => write!(f, " - shim(reify-fnptr)"),
|
||||
InstanceDef::ReifyShim(_, Some(ReifyReason::Vtable)) => write!(f, " - shim(reify-vtable)"),
|
||||
InstanceDef::ThreadLocalShim(_) => write!(f, " - shim(tls)"),
|
||||
InstanceDef::Intrinsic(_) => write!(f, " - intrinsic"),
|
||||
InstanceDef::Virtual(_, num) => write!(f, " - virtual#{num}"),
|
||||
InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({ty})"),
|
||||
InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"),
|
||||
InstanceDef::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"),
|
||||
InstanceDef::CoroutineKindShim { .. } => write!(f, " - shim"),
|
||||
InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"),
|
||||
InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
|
||||
InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"),
|
||||
InstanceDef::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"),
|
||||
InstanceDef::AsyncDropGlueCtorShim(_, None) => write!(f, " - shim(None)"),
|
||||
InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
|
||||
InstanceKind::Item(_) => Ok(()),
|
||||
InstanceKind::VTableShim(_) => write!(f, " - shim(vtable)"),
|
||||
InstanceKind::ReifyShim(_, None) => write!(f, " - shim(reify)"),
|
||||
InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr)) => write!(f, " - shim(reify-fnptr)"),
|
||||
InstanceKind::ReifyShim(_, Some(ReifyReason::Vtable)) => write!(f, " - shim(reify-vtable)"),
|
||||
InstanceKind::ThreadLocalShim(_) => write!(f, " - shim(tls)"),
|
||||
InstanceKind::Intrinsic(_) => write!(f, " - intrinsic"),
|
||||
InstanceKind::Virtual(_, num) => write!(f, " - virtual#{num}"),
|
||||
InstanceKind::FnPtrShim(_, ty) => write!(f, " - shim({ty})"),
|
||||
InstanceKind::ClosureOnceShim { .. } => write!(f, " - shim"),
|
||||
InstanceKind::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"),
|
||||
InstanceKind::CoroutineKindShim { .. } => write!(f, " - shim"),
|
||||
InstanceKind::DropGlue(_, None) => write!(f, " - shim(None)"),
|
||||
InstanceKind::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
|
||||
InstanceKind::CloneShim(_, ty) => write!(f, " - shim({ty})"),
|
||||
InstanceKind::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"),
|
||||
InstanceKind::AsyncDropGlueCtorShim(_, None) => write!(f, " - shim(None)"),
|
||||
InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -434,9 +434,9 @@ impl<'tcx> Instance<'tcx> {
|
|||
pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> {
|
||||
assert!(
|
||||
!args.has_escaping_bound_vars(),
|
||||
"args of instance {def_id:?} not normalized for codegen: {args:?}"
|
||||
"args of instance {def_id:?} has escaping bound vars: {args:?}"
|
||||
);
|
||||
Instance { def: InstanceDef::Item(def_id), args }
|
||||
Instance { def: InstanceKind::Item(def_id), args }
|
||||
}
|
||||
|
||||
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
|
||||
|
|
@ -526,13 +526,13 @@ impl<'tcx> Instance<'tcx> {
|
|||
let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr);
|
||||
Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| {
|
||||
match resolved.def {
|
||||
InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => {
|
||||
InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => {
|
||||
debug!(" => fn pointer created for function with #[track_caller]");
|
||||
resolved.def = InstanceDef::ReifyShim(def, reason);
|
||||
resolved.def = InstanceKind::ReifyShim(def, reason);
|
||||
}
|
||||
InstanceDef::Virtual(def_id, _) => {
|
||||
InstanceKind::Virtual(def_id, _) => {
|
||||
debug!(" => fn pointer created for virtual call");
|
||||
resolved.def = InstanceDef::ReifyShim(def_id, reason);
|
||||
resolved.def = InstanceKind::ReifyShim(def_id, reason);
|
||||
}
|
||||
// Reify `Trait::method` implementations if KCFI is enabled
|
||||
// FIXME(maurer) only reify it if it is a vtable-safe function
|
||||
|
|
@ -544,7 +544,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
{
|
||||
// If this function could also go in a vtable, we need to `ReifyShim` it with
|
||||
// KCFI because it can only attach one type per function.
|
||||
resolved.def = InstanceDef::ReifyShim(resolved.def_id(), reason)
|
||||
resolved.def = InstanceKind::ReifyShim(resolved.def_id(), reason)
|
||||
}
|
||||
// Reify `::call`-like method implementations if KCFI is enabled
|
||||
_ if tcx.sess.is_sanitizer_kcfi_enabled()
|
||||
|
|
@ -553,7 +553,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
// Reroute through a reify via the *unresolved* instance. The resolved one can't
|
||||
// be directly reified because it's closure-like. The reify can handle the
|
||||
// unresolved instance.
|
||||
resolved = Instance { def: InstanceDef::ReifyShim(def_id, reason), args }
|
||||
resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -575,12 +575,12 @@ impl<'tcx> Instance<'tcx> {
|
|||
&& tcx.generics_of(def_id).has_self;
|
||||
if is_vtable_shim {
|
||||
debug!(" => associated item with unsizeable self: Self");
|
||||
Some(Instance { def: InstanceDef::VTableShim(def_id), args })
|
||||
Some(Instance { def: InstanceKind::VTableShim(def_id), args })
|
||||
} else {
|
||||
let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable);
|
||||
Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| {
|
||||
match resolved.def {
|
||||
InstanceDef::Item(def) => {
|
||||
InstanceKind::Item(def) => {
|
||||
// We need to generate a shim when we cannot guarantee that
|
||||
// the caller of a trait object method will be aware of
|
||||
// `#[track_caller]` - this ensures that the caller
|
||||
|
|
@ -614,18 +614,18 @@ impl<'tcx> Instance<'tcx> {
|
|||
// Create a shim for the `FnOnce/FnMut/Fn` method we are calling
|
||||
// - unlike functions, invoking a closure always goes through a
|
||||
// trait.
|
||||
resolved = Instance { def: InstanceDef::ReifyShim(def_id, reason), args };
|
||||
resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args };
|
||||
} else {
|
||||
debug!(
|
||||
" => vtable fn pointer created for function with #[track_caller]: {:?}", def
|
||||
);
|
||||
resolved.def = InstanceDef::ReifyShim(def, reason);
|
||||
resolved.def = InstanceKind::ReifyShim(def, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
InstanceDef::Virtual(def_id, _) => {
|
||||
InstanceKind::Virtual(def_id, _) => {
|
||||
debug!(" => vtable fn pointer created for virtual call");
|
||||
resolved.def = InstanceDef::ReifyShim(def_id, reason)
|
||||
resolved.def = InstanceKind::ReifyShim(def_id, reason)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -676,7 +676,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
.def_id;
|
||||
let track_caller =
|
||||
tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER);
|
||||
let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller };
|
||||
let def = ty::InstanceKind::ClosureOnceShim { call_once, track_caller };
|
||||
|
||||
let self_ty = Ty::new_closure(tcx, closure_did, args);
|
||||
|
||||
|
|
@ -733,10 +733,10 @@ impl<'tcx> Instance<'tcx> {
|
|||
// If the closure's kind ty disagrees with the identity closure's kind ty,
|
||||
// then this must be a coroutine generated by one of the `ConstructCoroutineInClosureShim`s.
|
||||
if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() {
|
||||
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
|
||||
Some(Instance { def: ty::InstanceKind::Item(coroutine_def_id), args })
|
||||
} else {
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::CoroutineKindShim { coroutine_def_id },
|
||||
def: ty::InstanceKind::CoroutineKindShim { coroutine_def_id },
|
||||
args,
|
||||
})
|
||||
}
|
||||
|
|
@ -749,7 +749,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Depending on the kind of `InstanceDef`, the MIR body associated with an
|
||||
/// Depending on the kind of `InstanceKind`, the MIR body associated with an
|
||||
/// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
|
||||
/// cases the MIR body is expressed in terms of the types found in the generic parameter array.
|
||||
/// In the former case, we want to instantiate those generic types and replace them with the
|
||||
|
|
@ -832,7 +832,7 @@ impl<'tcx> Instance<'tcx> {
|
|||
|
||||
fn polymorphize<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
instance: ty::InstanceKind<'tcx>,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
) -> GenericArgsRef<'tcx> {
|
||||
debug!("polymorphize({:?}, {:?})", instance, args);
|
||||
|
|
@ -873,7 +873,7 @@ fn polymorphize<'tcx>(
|
|||
match *ty.kind() {
|
||||
ty::Closure(def_id, args) => {
|
||||
let polymorphized_args =
|
||||
polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args);
|
||||
polymorphize(self.tcx, ty::InstanceKind::Item(def_id), args);
|
||||
if args == polymorphized_args {
|
||||
ty
|
||||
} else {
|
||||
|
|
@ -882,7 +882,7 @@ fn polymorphize<'tcx>(
|
|||
}
|
||||
ty::Coroutine(def_id, args) => {
|
||||
let polymorphized_args =
|
||||
polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args);
|
||||
polymorphize(self.tcx, ty::InstanceKind::Item(def_id), args);
|
||||
if args == polymorphized_args {
|
||||
ty
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1302,7 +1302,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
|
|||
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
|
||||
///
|
||||
/// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
|
||||
/// instead, where the instance is an `InstanceDef::Virtual`.
|
||||
/// instead, where the instance is an `InstanceKind::Virtual`.
|
||||
#[inline]
|
||||
fn fn_abi_of_fn_ptr(
|
||||
&self,
|
||||
|
|
@ -1322,7 +1322,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
|
|||
/// direct calls to an `fn`.
|
||||
///
|
||||
/// NB: that includes virtual calls, which are represented by "direct calls"
|
||||
/// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
|
||||
/// to an `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`).
|
||||
#[inline]
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
fn fn_abi_of_instance(
|
||||
|
|
|
|||
|
|
@ -92,8 +92,9 @@ pub use self::context::{
|
|||
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
|
||||
TyCtxt, TyCtxtFeed,
|
||||
};
|
||||
pub use self::instance::{Instance, InstanceDef, ReifyReason, ShortInstance, UnusedGenericParams};
|
||||
pub use self::instance::{Instance, InstanceKind, ReifyReason, ShortInstance, UnusedGenericParams};
|
||||
pub use self::list::{List, ListWithCachedTypeInfo};
|
||||
pub use self::opaque_types::OpaqueTypeKey;
|
||||
pub use self::parameterized::ParameterizedOverTcx;
|
||||
pub use self::pattern::{Pattern, PatternKind};
|
||||
pub use self::predicate::{
|
||||
|
|
@ -758,45 +759,6 @@ impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct OpaqueTypeKey<'tcx> {
|
||||
pub def_id: LocalDefId,
|
||||
pub args: GenericArgsRef<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeKey<'tcx> {
|
||||
pub fn iter_captured_args(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> impl Iterator<Item = (usize, GenericArg<'tcx>)> {
|
||||
std::iter::zip(self.args, tcx.variances_of(self.def_id)).enumerate().filter_map(
|
||||
|(i, (arg, v))| match (arg.unpack(), v) {
|
||||
(_, ty::Invariant) => Some((i, arg)),
|
||||
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => None,
|
||||
_ => bug!("unexpected opaque type arg variance"),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn fold_captured_lifetime_args(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mut f: impl FnMut(Region<'tcx>) -> Region<'tcx>,
|
||||
) -> Self {
|
||||
let Self { def_id, args } = self;
|
||||
let args = std::iter::zip(args, tcx.variances_of(def_id)).map(|(arg, v)| {
|
||||
match (arg.unpack(), v) {
|
||||
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
|
||||
(ty::GenericArgKind::Lifetime(lt), _) => f(lt).into(),
|
||||
_ => arg,
|
||||
}
|
||||
});
|
||||
let args = tcx.mk_args_from_iter(args);
|
||||
Self { def_id, args }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
|
||||
pub struct OpaqueHiddenType<'tcx> {
|
||||
/// The span of this particular definition of the opaque type. So
|
||||
|
|
@ -1731,11 +1693,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the possibly-auto-generated MIR of a [`ty::InstanceDef`].
|
||||
/// Returns the possibly-auto-generated MIR of a [`ty::InstanceKind`].
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
|
||||
pub fn instance_mir(self, instance: ty::InstanceKind<'tcx>) -> &'tcx Body<'tcx> {
|
||||
match instance {
|
||||
ty::InstanceDef::Item(def) => {
|
||||
ty::InstanceKind::Item(def) => {
|
||||
debug!("calling def_kind on def: {:?}", def);
|
||||
let def_kind = self.def_kind(def);
|
||||
debug!("returned from def_kind: {:?}", def_kind);
|
||||
|
|
@ -1751,19 +1713,19 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
_ => self.optimized_mir(def),
|
||||
}
|
||||
}
|
||||
ty::InstanceDef::VTableShim(..)
|
||||
| ty::InstanceDef::ReifyShim(..)
|
||||
| ty::InstanceDef::Intrinsic(..)
|
||||
| ty::InstanceDef::FnPtrShim(..)
|
||||
| ty::InstanceDef::Virtual(..)
|
||||
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineKindShim { .. }
|
||||
| ty::InstanceDef::DropGlue(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::ThreadLocalShim(..)
|
||||
| ty::InstanceDef::FnPtrAddrShim(..)
|
||||
| ty::InstanceDef::AsyncDropGlueCtorShim(..) => self.mir_shims(instance),
|
||||
ty::InstanceKind::VTableShim(..)
|
||||
| ty::InstanceKind::ReifyShim(..)
|
||||
| ty::InstanceKind::Intrinsic(..)
|
||||
| ty::InstanceKind::FnPtrShim(..)
|
||||
| ty::InstanceKind::Virtual(..)
|
||||
| ty::InstanceKind::ClosureOnceShim { .. }
|
||||
| ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceKind::CoroutineKindShim { .. }
|
||||
| ty::InstanceKind::DropGlue(..)
|
||||
| ty::InstanceKind::CloneShim(..)
|
||||
| ty::InstanceKind::ThreadLocalShim(..)
|
||||
| ty::InstanceKind::FnPtrAddrShim(..)
|
||||
| ty::InstanceKind::AsyncDropGlueCtorShim(..) => self.mir_shims(instance),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ use rustc_span::def_id::DefId;
|
|||
use rustc_span::Span;
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey<TyCtxt<'tcx>>;
|
||||
|
||||
/// Converts generic params of a TypeFoldable from one
|
||||
/// item's generics to another. Usually from a function's generics
|
||||
/// list to the opaque type's own generics.
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ use rustc_index::{Idx, IndexVec};
|
|||
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::CoroutineArgs;
|
||||
use rustc_middle::ty::InstanceDef;
|
||||
use rustc_middle::ty::InstanceKind;
|
||||
use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_mir_dataflow::impls::{
|
||||
|
|
@ -1276,7 +1276,7 @@ fn create_coroutine_drop_shim<'tcx>(
|
|||
// Update the body's def to become the drop glue.
|
||||
let coroutine_instance = body.source.instance;
|
||||
let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None);
|
||||
let drop_instance = InstanceDef::DropGlue(drop_in_place, Some(coroutine_ty));
|
||||
let drop_instance = InstanceKind::DropGlue(drop_in_place, Some(coroutine_ty));
|
||||
|
||||
// Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible
|
||||
// filename.
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ use rustc_middle::bug;
|
|||
use rustc_middle::hir::place::{Projection, ProjectionKind};
|
||||
use rustc_middle::mir::visit::MutVisitor;
|
||||
use rustc_middle::mir::{self, dump_mir, MirPass};
|
||||
use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
|
||||
pub struct ByMoveBody;
|
||||
|
|
@ -102,7 +102,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
|||
|
||||
// We don't need to generate a by-move coroutine if the coroutine body was
|
||||
// produced by the `CoroutineKindShim`, since it's already by-move.
|
||||
if matches!(body.source.instance, ty::InstanceDef::CoroutineKindShim { .. }) {
|
||||
if matches!(body.source.instance, ty::InstanceKind::CoroutineKindShim { .. }) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
|
|||
MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body);
|
||||
dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(()));
|
||||
// FIXME: use query feeding to generate the body right here and then only store the `DefId` of the new body.
|
||||
by_move_body.source = mir::MirSource::from_instance(InstanceDef::CoroutineKindShim {
|
||||
by_move_body.source = mir::MirSource::from_instance(InstanceKind::CoroutineKindShim {
|
||||
coroutine_def_id: coroutine_def_id.to_def_id(),
|
||||
});
|
||||
body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body);
|
||||
|
|
|
|||
|
|
@ -168,11 +168,6 @@ impl CoverageCounters {
|
|||
self.counter_increment_sites.len()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(super) fn num_expressions(&self) -> usize {
|
||||
self.expressions.len()
|
||||
}
|
||||
|
||||
fn set_bcb_counter(&mut self, bcb: BasicCoverageBlock, counter_kind: BcbCounter) -> BcbCounter {
|
||||
if let Some(replaced) = self.bcb_counters[bcb].replace(counter_kind) {
|
||||
bug!(
|
||||
|
|
|
|||
|
|
@ -14,16 +14,16 @@ use std::ops::{Index, IndexMut};
|
|||
/// A coverage-specific simplification of the MIR control flow graph (CFG). The `CoverageGraph`s
|
||||
/// nodes are `BasicCoverageBlock`s, which encompass one or more MIR `BasicBlock`s.
|
||||
#[derive(Debug)]
|
||||
pub(super) struct CoverageGraph {
|
||||
pub(crate) struct CoverageGraph {
|
||||
bcbs: IndexVec<BasicCoverageBlock, BasicCoverageBlockData>,
|
||||
bb_to_bcb: IndexVec<BasicBlock, Option<BasicCoverageBlock>>,
|
||||
pub successors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
|
||||
pub predecessors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
|
||||
pub(crate) successors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
|
||||
pub(crate) predecessors: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
|
||||
dominators: Option<Dominators<BasicCoverageBlock>>,
|
||||
}
|
||||
|
||||
impl CoverageGraph {
|
||||
pub fn from_mir(mir_body: &mir::Body<'_>) -> Self {
|
||||
pub(crate) fn from_mir(mir_body: &mir::Body<'_>) -> Self {
|
||||
let (bcbs, bb_to_bcb) = Self::compute_basic_coverage_blocks(mir_body);
|
||||
|
||||
// Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock
|
||||
|
|
@ -135,24 +135,28 @@ impl CoverageGraph {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter_enumerated(
|
||||
pub(crate) fn iter_enumerated(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (BasicCoverageBlock, &BasicCoverageBlockData)> {
|
||||
self.bcbs.iter_enumerated()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn bcb_from_bb(&self, bb: BasicBlock) -> Option<BasicCoverageBlock> {
|
||||
pub(crate) fn bcb_from_bb(&self, bb: BasicBlock) -> Option<BasicCoverageBlock> {
|
||||
if bb.index() < self.bb_to_bcb.len() { self.bb_to_bcb[bb] } else { None }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn dominates(&self, dom: BasicCoverageBlock, node: BasicCoverageBlock) -> bool {
|
||||
pub(crate) fn dominates(&self, dom: BasicCoverageBlock, node: BasicCoverageBlock) -> bool {
|
||||
self.dominators.as_ref().unwrap().dominates(dom, node)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn cmp_in_dominator_order(&self, a: BasicCoverageBlock, b: BasicCoverageBlock) -> Ordering {
|
||||
pub(crate) fn cmp_in_dominator_order(
|
||||
&self,
|
||||
a: BasicCoverageBlock,
|
||||
b: BasicCoverageBlock,
|
||||
) -> Ordering {
|
||||
self.dominators.as_ref().unwrap().cmp_in_dominator_order(a, b)
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +170,7 @@ impl CoverageGraph {
|
|||
///
|
||||
/// FIXME: That assumption might not be true for [`TerminatorKind::Yield`]?
|
||||
#[inline(always)]
|
||||
pub(super) fn bcb_has_multiple_in_edges(&self, bcb: BasicCoverageBlock) -> bool {
|
||||
pub(crate) fn bcb_has_multiple_in_edges(&self, bcb: BasicCoverageBlock) -> bool {
|
||||
// Even though bcb0 conceptually has an extra virtual in-edge due to
|
||||
// being the entry point, we've already asserted that it has no _other_
|
||||
// in-edges, so there's no possibility of it having _multiple_ in-edges.
|
||||
|
|
@ -212,7 +216,7 @@ impl graph::StartNode for CoverageGraph {
|
|||
impl graph::Successors for CoverageGraph {
|
||||
#[inline]
|
||||
fn successors(&self, node: Self::Node) -> impl Iterator<Item = Self::Node> {
|
||||
self.successors[node].iter().cloned()
|
||||
self.successors[node].iter().copied()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +231,7 @@ rustc_index::newtype_index! {
|
|||
/// A node in the control-flow graph of CoverageGraph.
|
||||
#[orderable]
|
||||
#[debug_format = "bcb{}"]
|
||||
pub(super) struct BasicCoverageBlock {
|
||||
pub(crate) struct BasicCoverageBlock {
|
||||
const START_BCB = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -259,23 +263,23 @@ rustc_index::newtype_index! {
|
|||
/// queries (`dominates()`, `predecessors`, `successors`, etc.) have branch (control flow)
|
||||
/// significance.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(super) struct BasicCoverageBlockData {
|
||||
pub basic_blocks: Vec<BasicBlock>,
|
||||
pub(crate) struct BasicCoverageBlockData {
|
||||
pub(crate) basic_blocks: Vec<BasicBlock>,
|
||||
}
|
||||
|
||||
impl BasicCoverageBlockData {
|
||||
pub fn from(basic_blocks: Vec<BasicBlock>) -> Self {
|
||||
fn from(basic_blocks: Vec<BasicBlock>) -> Self {
|
||||
assert!(basic_blocks.len() > 0);
|
||||
Self { basic_blocks }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn leader_bb(&self) -> BasicBlock {
|
||||
pub(crate) fn leader_bb(&self) -> BasicBlock {
|
||||
self.basic_blocks[0]
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn last_bb(&self) -> BasicBlock {
|
||||
pub(crate) fn last_bb(&self) -> BasicBlock {
|
||||
*self.basic_blocks.last().unwrap()
|
||||
}
|
||||
}
|
||||
|
|
@ -364,7 +368,7 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
|
|||
/// CoverageGraph outside all loops. This supports traversing the BCB CFG in a way that
|
||||
/// ensures a loop is completely traversed before processing Blocks after the end of the loop.
|
||||
#[derive(Debug)]
|
||||
pub(super) struct TraversalContext {
|
||||
struct TraversalContext {
|
||||
/// BCB with one or more incoming loop backedges, indicating which loop
|
||||
/// this context is for.
|
||||
///
|
||||
|
|
@ -375,7 +379,7 @@ pub(super) struct TraversalContext {
|
|||
worklist: VecDeque<BasicCoverageBlock>,
|
||||
}
|
||||
|
||||
pub(super) struct TraverseCoverageGraphWithLoops<'a> {
|
||||
pub(crate) struct TraverseCoverageGraphWithLoops<'a> {
|
||||
basic_coverage_blocks: &'a CoverageGraph,
|
||||
|
||||
backedges: IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>>,
|
||||
|
|
@ -384,7 +388,7 @@ pub(super) struct TraverseCoverageGraphWithLoops<'a> {
|
|||
}
|
||||
|
||||
impl<'a> TraverseCoverageGraphWithLoops<'a> {
|
||||
pub(super) fn new(basic_coverage_blocks: &'a CoverageGraph) -> Self {
|
||||
pub(crate) fn new(basic_coverage_blocks: &'a CoverageGraph) -> Self {
|
||||
let backedges = find_loop_backedges(basic_coverage_blocks);
|
||||
|
||||
let worklist = VecDeque::from([basic_coverage_blocks.start_node()]);
|
||||
|
|
@ -400,7 +404,7 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
|
|||
|
||||
/// For each loop on the loop context stack (top-down), yields a list of BCBs
|
||||
/// within that loop that have an outgoing edge back to the loop header.
|
||||
pub(super) fn reloop_bcbs_per_loop(&self) -> impl Iterator<Item = &[BasicCoverageBlock]> {
|
||||
pub(crate) fn reloop_bcbs_per_loop(&self) -> impl Iterator<Item = &[BasicCoverageBlock]> {
|
||||
self.context_stack
|
||||
.iter()
|
||||
.rev()
|
||||
|
|
@ -408,39 +412,38 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
|
|||
.map(|header_bcb| self.backedges[header_bcb].as_slice())
|
||||
}
|
||||
|
||||
pub(super) fn next(&mut self) -> Option<BasicCoverageBlock> {
|
||||
pub(crate) fn next(&mut self) -> Option<BasicCoverageBlock> {
|
||||
debug!(
|
||||
"TraverseCoverageGraphWithLoops::next - context_stack: {:?}",
|
||||
self.context_stack.iter().rev().collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
while let Some(context) = self.context_stack.last_mut() {
|
||||
if let Some(bcb) = context.worklist.pop_front() {
|
||||
if !self.visited.insert(bcb) {
|
||||
debug!("Already visited: {bcb:?}");
|
||||
continue;
|
||||
}
|
||||
debug!("Visiting {bcb:?}");
|
||||
|
||||
if self.backedges[bcb].len() > 0 {
|
||||
debug!("{bcb:?} is a loop header! Start a new TraversalContext...");
|
||||
self.context_stack.push(TraversalContext {
|
||||
loop_header: Some(bcb),
|
||||
worklist: VecDeque::new(),
|
||||
});
|
||||
}
|
||||
self.add_successors_to_worklists(bcb);
|
||||
return Some(bcb);
|
||||
} else {
|
||||
// Strip contexts with empty worklists from the top of the stack
|
||||
let Some(bcb) = context.worklist.pop_front() else {
|
||||
// This stack level is exhausted; pop it and try the next one.
|
||||
self.context_stack.pop();
|
||||
continue;
|
||||
};
|
||||
|
||||
if !self.visited.insert(bcb) {
|
||||
debug!("Already visited: {bcb:?}");
|
||||
continue;
|
||||
}
|
||||
debug!("Visiting {bcb:?}");
|
||||
|
||||
if self.backedges[bcb].len() > 0 {
|
||||
debug!("{bcb:?} is a loop header! Start a new TraversalContext...");
|
||||
self.context_stack
|
||||
.push(TraversalContext { loop_header: Some(bcb), worklist: VecDeque::new() });
|
||||
}
|
||||
self.add_successors_to_worklists(bcb);
|
||||
return Some(bcb);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn add_successors_to_worklists(&mut self, bcb: BasicCoverageBlock) {
|
||||
fn add_successors_to_worklists(&mut self, bcb: BasicCoverageBlock) {
|
||||
let successors = &self.basic_coverage_blocks.successors[bcb];
|
||||
debug!("{:?} has {} successors:", bcb, successors.len());
|
||||
|
||||
|
|
@ -494,11 +497,11 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_complete(&self) -> bool {
|
||||
pub(crate) fn is_complete(&self) -> bool {
|
||||
self.visited.count() == self.visited.domain_size()
|
||||
}
|
||||
|
||||
pub fn unvisited(&self) -> Vec<BasicCoverageBlock> {
|
||||
pub(crate) fn unvisited(&self) -> Vec<BasicCoverageBlock> {
|
||||
let mut unvisited_set: BitSet<BasicCoverageBlock> =
|
||||
BitSet::new_filled(self.visited.domain_size());
|
||||
unvisited_set.subtract(&self.visited);
|
||||
|
|
@ -506,7 +509,7 @@ impl<'a> TraverseCoverageGraphWithLoops<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn find_loop_backedges(
|
||||
fn find_loop_backedges(
|
||||
basic_coverage_blocks: &CoverageGraph,
|
||||
) -> IndexVec<BasicCoverageBlock, Vec<BasicCoverageBlock>> {
|
||||
let num_bcbs = basic_coverage_blocks.num_nodes();
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
|||
/// Query implementation for `coverage_ids_info`.
|
||||
fn coverage_ids_info<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance_def: ty::InstanceDef<'tcx>,
|
||||
instance_def: ty::InstanceKind<'tcx>,
|
||||
) -> CoverageIdsInfo {
|
||||
let mir_body = tcx.instance_mir(instance_def);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
use std::collections::VecDeque;
|
||||
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::mir;
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
|
||||
use crate::coverage::mappings;
|
||||
use crate::coverage::spans::from_mir::SpanFromMir;
|
||||
use crate::coverage::spans::from_mir::{
|
||||
extract_covspans_and_holes_from_mir, ExtractedCovspans, Hole, SpanFromMir,
|
||||
};
|
||||
use crate::coverage::ExtractedHirInfo;
|
||||
|
||||
mod from_mir;
|
||||
|
|
@ -19,50 +25,181 @@ pub(super) fn extract_refined_covspans(
|
|||
basic_coverage_blocks: &CoverageGraph,
|
||||
code_mappings: &mut impl Extend<mappings::CodeMapping>,
|
||||
) {
|
||||
let sorted_span_buckets =
|
||||
from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks);
|
||||
for bucket in sorted_span_buckets {
|
||||
let refined_spans = refine_sorted_spans(bucket);
|
||||
code_mappings.extend(refined_spans.into_iter().map(|RefinedCovspan { span, bcb }| {
|
||||
let ExtractedCovspans { mut covspans, mut holes } =
|
||||
extract_covspans_and_holes_from_mir(mir_body, hir_info, basic_coverage_blocks);
|
||||
|
||||
// First, perform the passes that need macro information.
|
||||
covspans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb));
|
||||
remove_unwanted_macro_spans(&mut covspans);
|
||||
split_visible_macro_spans(&mut covspans);
|
||||
|
||||
// We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`.
|
||||
let mut covspans = covspans.into_iter().map(SpanFromMir::into_covspan).collect::<Vec<_>>();
|
||||
|
||||
let compare_covspans = |a: &Covspan, b: &Covspan| {
|
||||
compare_spans(a.span, b.span)
|
||||
// After deduplication, we want to keep only the most-dominated BCB.
|
||||
.then_with(|| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb).reverse())
|
||||
};
|
||||
covspans.sort_by(compare_covspans);
|
||||
|
||||
// Among covspans with the same span, keep only one,
|
||||
// preferring the one with the most-dominated BCB.
|
||||
// (Ideally we should try to preserve _all_ non-dominating BCBs, but that
|
||||
// requires a lot more complexity in the span refiner, for little benefit.)
|
||||
covspans.dedup_by(|b, a| a.span.source_equal(b.span));
|
||||
|
||||
// Sort the holes, and merge overlapping/adjacent holes.
|
||||
holes.sort_by(|a, b| compare_spans(a.span, b.span));
|
||||
holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b));
|
||||
|
||||
// Split the covspans into separate buckets that don't overlap any holes.
|
||||
let buckets = divide_spans_into_buckets(covspans, &holes);
|
||||
|
||||
for mut covspans in buckets {
|
||||
// Make sure each individual bucket is internally sorted.
|
||||
covspans.sort_by(compare_covspans);
|
||||
let _span = debug_span!("processing bucket", ?covspans).entered();
|
||||
|
||||
let mut covspans = remove_unwanted_overlapping_spans(covspans);
|
||||
debug!(?covspans, "after removing overlaps");
|
||||
|
||||
// Do one last merge pass, to simplify the output.
|
||||
covspans.dedup_by(|b, a| a.merge_if_eligible(b));
|
||||
debug!(?covspans, "after merge");
|
||||
|
||||
code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| {
|
||||
// Each span produced by the refiner represents an ordinary code region.
|
||||
mappings::CodeMapping { span, bcb }
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RefinedCovspan {
|
||||
span: Span,
|
||||
bcb: BasicCoverageBlock,
|
||||
/// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate
|
||||
/// multiple condition/consequent blocks that have the span of the whole macro
|
||||
/// invocation, which is unhelpful. Keeping only the first such span seems to
|
||||
/// give better mappings, so remove the others.
|
||||
///
|
||||
/// (The input spans should be sorted in BCB dominator order, so that the
|
||||
/// retained "first" span is likely to dominate the others.)
|
||||
fn remove_unwanted_macro_spans(covspans: &mut Vec<SpanFromMir>) {
|
||||
let mut seen_macro_spans = FxHashSet::default();
|
||||
covspans.retain(|covspan| {
|
||||
// Ignore (retain) non-macro-expansion spans.
|
||||
if covspan.visible_macro.is_none() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retain only the first macro-expanded covspan with this span.
|
||||
seen_macro_spans.insert(covspan.span)
|
||||
});
|
||||
}
|
||||
|
||||
impl RefinedCovspan {
|
||||
fn is_mergeable(&self, other: &Self) -> bool {
|
||||
self.bcb == other.bcb
|
||||
/// When a span corresponds to a macro invocation that is visible from the
|
||||
/// function body, split it into two parts. The first part covers just the
|
||||
/// macro name plus `!`, and the second part covers the rest of the macro
|
||||
/// invocation. This seems to give better results for code that uses macros.
|
||||
fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
|
||||
let mut extra_spans = vec![];
|
||||
|
||||
covspans.retain(|covspan| {
|
||||
let Some(visible_macro) = covspan.visible_macro else { return true };
|
||||
|
||||
let split_len = visible_macro.as_str().len() as u32 + 1;
|
||||
let (before, after) = covspan.span.split_at(split_len);
|
||||
if !covspan.span.contains(before) || !covspan.span.contains(after) {
|
||||
// Something is unexpectedly wrong with the split point.
|
||||
// The debug assertion in `split_at` will have already caught this,
|
||||
// but in release builds it's safer to do nothing and maybe get a
|
||||
// bug report for unexpected coverage, rather than risk an ICE.
|
||||
return true;
|
||||
}
|
||||
|
||||
extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb));
|
||||
extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb));
|
||||
false // Discard the original covspan that we just split.
|
||||
});
|
||||
|
||||
// The newly-split spans are added at the end, so any previous sorting
|
||||
// is not preserved.
|
||||
covspans.extend(extra_spans);
|
||||
}
|
||||
|
||||
/// Uses the holes to divide the given covspans into buckets, such that:
|
||||
/// - No span in any hole overlaps a bucket (truncating the spans if necessary).
|
||||
/// - The spans in each bucket are strictly after all spans in previous buckets,
|
||||
/// and strictly before all spans in subsequent buckets.
|
||||
///
|
||||
/// The resulting buckets are sorted relative to each other, but might not be
|
||||
/// internally sorted.
|
||||
#[instrument(level = "debug")]
|
||||
fn divide_spans_into_buckets(input_covspans: Vec<Covspan>, holes: &[Hole]) -> Vec<Vec<Covspan>> {
|
||||
debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
|
||||
debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
|
||||
|
||||
// Now we're ready to start carving holes out of the initial coverage spans,
|
||||
// and grouping them in buckets separated by the holes.
|
||||
|
||||
let mut input_covspans = VecDeque::from(input_covspans);
|
||||
let mut fragments = vec![];
|
||||
|
||||
// For each hole:
|
||||
// - Identify the spans that are entirely or partly before the hole.
|
||||
// - Put those spans in a corresponding bucket, truncated to the start of the hole.
|
||||
// - If one of those spans also extends after the hole, put the rest of it
|
||||
// in a "fragments" vector that is processed by the next hole.
|
||||
let mut buckets = (0..holes.len()).map(|_| vec![]).collect::<Vec<_>>();
|
||||
for (hole, bucket) in holes.iter().zip(&mut buckets) {
|
||||
let fragments_from_prev = std::mem::take(&mut fragments);
|
||||
|
||||
// Only inspect spans that precede or overlap this hole,
|
||||
// leaving the rest to be inspected by later holes.
|
||||
// (This relies on the spans and holes both being sorted.)
|
||||
let relevant_input_covspans =
|
||||
drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi());
|
||||
|
||||
for covspan in fragments_from_prev.into_iter().chain(relevant_input_covspans) {
|
||||
let (before, after) = covspan.split_around_hole_span(hole.span);
|
||||
bucket.extend(before);
|
||||
fragments.extend(after);
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, other: &Self) {
|
||||
debug_assert!(self.is_mergeable(other));
|
||||
self.span = self.span.to(other.span);
|
||||
}
|
||||
// After finding the spans before each hole, any remaining fragments/spans
|
||||
// form their own final bucket, after the final hole.
|
||||
// (If there were no holes, this will just be all of the initial spans.)
|
||||
fragments.extend(input_covspans);
|
||||
buckets.push(fragments);
|
||||
|
||||
buckets
|
||||
}
|
||||
|
||||
/// Similar to `.drain(..)`, but stops just before it would remove an item not
|
||||
/// satisfying the predicate.
|
||||
fn drain_front_while<'a, T>(
|
||||
queue: &'a mut VecDeque<T>,
|
||||
mut pred_fn: impl FnMut(&T) -> bool,
|
||||
) -> impl Iterator<Item = T> + Captures<'a> {
|
||||
std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None })
|
||||
}
|
||||
|
||||
/// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines"
|
||||
/// those spans by removing spans that overlap in unwanted ways, and by merging
|
||||
/// compatible adjacent spans.
|
||||
/// those spans by removing spans that overlap in unwanted ways.
|
||||
#[instrument(level = "debug")]
|
||||
fn refine_sorted_spans(sorted_spans: Vec<SpanFromMir>) -> Vec<RefinedCovspan> {
|
||||
fn remove_unwanted_overlapping_spans(sorted_spans: Vec<Covspan>) -> Vec<Covspan> {
|
||||
debug_assert!(sorted_spans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
|
||||
|
||||
// Holds spans that have been read from the input vector, but haven't yet
|
||||
// been committed to the output vector.
|
||||
let mut pending = vec![];
|
||||
let mut refined = vec![];
|
||||
|
||||
for curr in sorted_spans {
|
||||
pending.retain(|prev: &SpanFromMir| {
|
||||
pending.retain(|prev: &Covspan| {
|
||||
if prev.span.hi() <= curr.span.lo() {
|
||||
// There's no overlap between the previous/current covspans,
|
||||
// so move the previous one into the refined list.
|
||||
refined.push(RefinedCovspan { span: prev.span, bcb: prev.bcb });
|
||||
refined.push(prev.clone());
|
||||
false
|
||||
} else {
|
||||
// Otherwise, retain the previous covspan only if it has the
|
||||
|
|
@ -75,22 +212,57 @@ fn refine_sorted_spans(sorted_spans: Vec<SpanFromMir>) -> Vec<RefinedCovspan> {
|
|||
}
|
||||
|
||||
// Drain the rest of the pending list into the refined list.
|
||||
for prev in pending {
|
||||
refined.push(RefinedCovspan { span: prev.span, bcb: prev.bcb });
|
||||
}
|
||||
|
||||
// Do one last merge pass, to simplify the output.
|
||||
debug!(?refined, "before merge");
|
||||
refined.dedup_by(|b, a| {
|
||||
if a.is_mergeable(b) {
|
||||
debug!(?a, ?b, "merging list-adjacent refined spans");
|
||||
a.merge_from(b);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
debug!(?refined, "after merge");
|
||||
|
||||
refined.extend(pending);
|
||||
refined
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Covspan {
|
||||
span: Span,
|
||||
bcb: BasicCoverageBlock,
|
||||
}
|
||||
|
||||
impl Covspan {
|
||||
/// Splits this covspan into 0-2 parts:
|
||||
/// - The part that is strictly before the hole span, if any.
|
||||
/// - The part that is strictly after the hole span, if any.
|
||||
fn split_around_hole_span(&self, hole_span: Span) -> (Option<Self>, Option<Self>) {
|
||||
let before = try {
|
||||
let span = self.span.trim_end(hole_span)?;
|
||||
Self { span, ..*self }
|
||||
};
|
||||
let after = try {
|
||||
let span = self.span.trim_start(hole_span)?;
|
||||
Self { span, ..*self }
|
||||
};
|
||||
|
||||
(before, after)
|
||||
}
|
||||
|
||||
/// If `self` and `other` can be merged (i.e. they have the same BCB),
|
||||
/// mutates `self.span` to also include `other.span` and returns true.
|
||||
///
|
||||
/// Note that compatible covspans can be merged even if their underlying
|
||||
/// spans are not overlapping/adjacent; any space between them will also be
|
||||
/// part of the merged covspan.
|
||||
fn merge_if_eligible(&mut self, other: &Self) -> bool {
|
||||
if self.bcb != other.bcb {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.span = self.span.to(other.span);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Compares two spans in (lo ascending, hi descending) order.
|
||||
fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
|
||||
// First sort by span start.
|
||||
Ord::cmp(&a.lo(), &b.lo())
|
||||
// If span starts are the same, sort by span end in reverse order.
|
||||
// This ensures that if spans A and B are adjacent in the list,
|
||||
// and they overlap but are not equal, then either:
|
||||
// - Span A extends further left, or
|
||||
// - Both have the same start and span A extends further right
|
||||
.then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
use std::collections::VecDeque;
|
||||
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::coverage::CoverageKind;
|
||||
use rustc_middle::mir::{
|
||||
|
|
@ -13,25 +9,25 @@ use rustc_span::{ExpnKind, MacroKind, Span, Symbol};
|
|||
use crate::coverage::graph::{
|
||||
BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB,
|
||||
};
|
||||
use crate::coverage::spans::Covspan;
|
||||
use crate::coverage::ExtractedHirInfo;
|
||||
|
||||
pub(crate) struct ExtractedCovspans {
|
||||
pub(crate) covspans: Vec<SpanFromMir>,
|
||||
pub(crate) holes: Vec<Hole>,
|
||||
}
|
||||
|
||||
/// Traverses the MIR body to produce an initial collection of coverage-relevant
|
||||
/// spans, each associated with a node in the coverage graph (BCB) and possibly
|
||||
/// other metadata.
|
||||
///
|
||||
/// The returned spans are divided into one or more buckets, such that:
|
||||
/// - The spans in each bucket are strictly after all spans in previous buckets,
|
||||
/// and strictly before all spans in subsequent buckets.
|
||||
/// - The contents of each bucket are also sorted, in a specific order that is
|
||||
/// expected by the subsequent span-refinement step.
|
||||
pub(super) fn mir_to_initial_sorted_coverage_spans(
|
||||
pub(crate) fn extract_covspans_and_holes_from_mir(
|
||||
mir_body: &mir::Body<'_>,
|
||||
hir_info: &ExtractedHirInfo,
|
||||
basic_coverage_blocks: &CoverageGraph,
|
||||
) -> Vec<Vec<SpanFromMir>> {
|
||||
) -> ExtractedCovspans {
|
||||
let &ExtractedHirInfo { body_span, .. } = hir_info;
|
||||
|
||||
let mut initial_spans = vec![];
|
||||
let mut covspans = vec![];
|
||||
let mut holes = vec![];
|
||||
|
||||
for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() {
|
||||
|
|
@ -40,150 +36,21 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
|
|||
body_span,
|
||||
bcb,
|
||||
bcb_data,
|
||||
&mut initial_spans,
|
||||
&mut covspans,
|
||||
&mut holes,
|
||||
);
|
||||
}
|
||||
|
||||
// Only add the signature span if we found at least one span in the body.
|
||||
if !initial_spans.is_empty() || !holes.is_empty() {
|
||||
if !covspans.is_empty() || !holes.is_empty() {
|
||||
// If there is no usable signature span, add a fake one (before refinement)
|
||||
// to avoid an ugly gap between the body start and the first real span.
|
||||
// FIXME: Find a more principled way to solve this problem.
|
||||
let fn_sig_span = hir_info.fn_sig_span_extended.unwrap_or_else(|| body_span.shrink_to_lo());
|
||||
initial_spans.push(SpanFromMir::for_fn_sig(fn_sig_span));
|
||||
covspans.push(SpanFromMir::for_fn_sig(fn_sig_span));
|
||||
}
|
||||
|
||||
initial_spans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb));
|
||||
remove_unwanted_macro_spans(&mut initial_spans);
|
||||
split_visible_macro_spans(&mut initial_spans);
|
||||
|
||||
let compare_covspans = |a: &SpanFromMir, b: &SpanFromMir| {
|
||||
compare_spans(a.span, b.span)
|
||||
// After deduplication, we want to keep only the most-dominated BCB.
|
||||
.then_with(|| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb).reverse())
|
||||
};
|
||||
initial_spans.sort_by(compare_covspans);
|
||||
|
||||
// Among covspans with the same span, keep only one,
|
||||
// preferring the one with the most-dominated BCB.
|
||||
// (Ideally we should try to preserve _all_ non-dominating BCBs, but that
|
||||
// requires a lot more complexity in the span refiner, for little benefit.)
|
||||
initial_spans.dedup_by(|b, a| a.span.source_equal(b.span));
|
||||
|
||||
// Sort the holes, and merge overlapping/adjacent holes.
|
||||
holes.sort_by(|a, b| compare_spans(a.span, b.span));
|
||||
holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b));
|
||||
|
||||
// Now we're ready to start carving holes out of the initial coverage spans,
|
||||
// and grouping them in buckets separated by the holes.
|
||||
|
||||
let mut initial_spans = VecDeque::from(initial_spans);
|
||||
let mut fragments: Vec<SpanFromMir> = vec![];
|
||||
|
||||
// For each hole:
|
||||
// - Identify the spans that are entirely or partly before the hole.
|
||||
// - Put those spans in a corresponding bucket, truncated to the start of the hole.
|
||||
// - If one of those spans also extends after the hole, put the rest of it
|
||||
// in a "fragments" vector that is processed by the next hole.
|
||||
let mut buckets = (0..holes.len()).map(|_| vec![]).collect::<Vec<_>>();
|
||||
for (hole, bucket) in holes.iter().zip(&mut buckets) {
|
||||
let fragments_from_prev = std::mem::take(&mut fragments);
|
||||
|
||||
// Only inspect spans that precede or overlap this hole,
|
||||
// leaving the rest to be inspected by later holes.
|
||||
// (This relies on the spans and holes both being sorted.)
|
||||
let relevant_initial_spans =
|
||||
drain_front_while(&mut initial_spans, |c| c.span.lo() < hole.span.hi());
|
||||
|
||||
for covspan in fragments_from_prev.into_iter().chain(relevant_initial_spans) {
|
||||
let (before, after) = covspan.split_around_hole_span(hole.span);
|
||||
bucket.extend(before);
|
||||
fragments.extend(after);
|
||||
}
|
||||
}
|
||||
|
||||
// After finding the spans before each hole, any remaining fragments/spans
|
||||
// form their own final bucket, after the final hole.
|
||||
// (If there were no holes, this will just be all of the initial spans.)
|
||||
fragments.extend(initial_spans);
|
||||
buckets.push(fragments);
|
||||
|
||||
// Make sure each individual bucket is still internally sorted.
|
||||
for bucket in &mut buckets {
|
||||
bucket.sort_by(compare_covspans);
|
||||
}
|
||||
buckets
|
||||
}
|
||||
|
||||
fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
|
||||
// First sort by span start.
|
||||
Ord::cmp(&a.lo(), &b.lo())
|
||||
// If span starts are the same, sort by span end in reverse order.
|
||||
// This ensures that if spans A and B are adjacent in the list,
|
||||
// and they overlap but are not equal, then either:
|
||||
// - Span A extends further left, or
|
||||
// - Both have the same start and span A extends further right
|
||||
.then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
|
||||
}
|
||||
|
||||
/// Similar to `.drain(..)`, but stops just before it would remove an item not
|
||||
/// satisfying the predicate.
|
||||
fn drain_front_while<'a, T>(
|
||||
queue: &'a mut VecDeque<T>,
|
||||
mut pred_fn: impl FnMut(&T) -> bool,
|
||||
) -> impl Iterator<Item = T> + Captures<'a> {
|
||||
std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None })
|
||||
}
|
||||
|
||||
/// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate
|
||||
/// multiple condition/consequent blocks that have the span of the whole macro
|
||||
/// invocation, which is unhelpful. Keeping only the first such span seems to
|
||||
/// give better mappings, so remove the others.
|
||||
///
|
||||
/// (The input spans should be sorted in BCB dominator order, so that the
|
||||
/// retained "first" span is likely to dominate the others.)
|
||||
fn remove_unwanted_macro_spans(initial_spans: &mut Vec<SpanFromMir>) {
|
||||
let mut seen_macro_spans = FxHashSet::default();
|
||||
initial_spans.retain(|covspan| {
|
||||
// Ignore (retain) non-macro-expansion spans.
|
||||
if covspan.visible_macro.is_none() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retain only the first macro-expanded covspan with this span.
|
||||
seen_macro_spans.insert(covspan.span)
|
||||
});
|
||||
}
|
||||
|
||||
/// When a span corresponds to a macro invocation that is visible from the
|
||||
/// function body, split it into two parts. The first part covers just the
|
||||
/// macro name plus `!`, and the second part covers the rest of the macro
|
||||
/// invocation. This seems to give better results for code that uses macros.
|
||||
fn split_visible_macro_spans(initial_spans: &mut Vec<SpanFromMir>) {
|
||||
let mut extra_spans = vec![];
|
||||
|
||||
initial_spans.retain(|covspan| {
|
||||
let Some(visible_macro) = covspan.visible_macro else { return true };
|
||||
|
||||
let split_len = visible_macro.as_str().len() as u32 + 1;
|
||||
let (before, after) = covspan.span.split_at(split_len);
|
||||
if !covspan.span.contains(before) || !covspan.span.contains(after) {
|
||||
// Something is unexpectedly wrong with the split point.
|
||||
// The debug assertion in `split_at` will have already caught this,
|
||||
// but in release builds it's safer to do nothing and maybe get a
|
||||
// bug report for unexpected coverage, rather than risk an ICE.
|
||||
return true;
|
||||
}
|
||||
|
||||
extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb));
|
||||
extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb));
|
||||
false // Discard the original covspan that we just split.
|
||||
});
|
||||
|
||||
// The newly-split spans are added at the end, so any previous sorting
|
||||
// is not preserved.
|
||||
initial_spans.extend(extra_spans);
|
||||
ExtractedCovspans { covspans, holes }
|
||||
}
|
||||
|
||||
// Generate a set of coverage spans from the filtered set of `Statement`s and `Terminator`s of
|
||||
|
|
@ -402,12 +269,12 @@ fn unexpand_into_body_span_with_prev(
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Hole {
|
||||
span: Span,
|
||||
pub(crate) struct Hole {
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
impl Hole {
|
||||
fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool {
|
||||
pub(crate) fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool {
|
||||
if !self.span.overlaps_or_adjacent(other.span) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -418,7 +285,7 @@ impl Hole {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct SpanFromMir {
|
||||
pub(crate) struct SpanFromMir {
|
||||
/// A span that has been extracted from MIR and then "un-expanded" back to
|
||||
/// within the current function's `body_span`. After various intermediate
|
||||
/// processing steps, this span is emitted as part of the final coverage
|
||||
|
|
@ -426,9 +293,9 @@ pub(super) struct SpanFromMir {
|
|||
///
|
||||
/// With the exception of `fn_sig_span`, this should always be contained
|
||||
/// within `body_span`.
|
||||
pub(super) span: Span,
|
||||
visible_macro: Option<Symbol>,
|
||||
pub(super) bcb: BasicCoverageBlock,
|
||||
pub(crate) span: Span,
|
||||
pub(crate) visible_macro: Option<Symbol>,
|
||||
pub(crate) bcb: BasicCoverageBlock,
|
||||
}
|
||||
|
||||
impl SpanFromMir {
|
||||
|
|
@ -436,23 +303,12 @@ impl SpanFromMir {
|
|||
Self::new(fn_sig_span, None, START_BCB)
|
||||
}
|
||||
|
||||
fn new(span: Span, visible_macro: Option<Symbol>, bcb: BasicCoverageBlock) -> Self {
|
||||
pub(crate) fn new(span: Span, visible_macro: Option<Symbol>, bcb: BasicCoverageBlock) -> Self {
|
||||
Self { span, visible_macro, bcb }
|
||||
}
|
||||
|
||||
/// Splits this span into 0-2 parts:
|
||||
/// - The part that is strictly before the hole span, if any.
|
||||
/// - The part that is strictly after the hole span, if any.
|
||||
fn split_around_hole_span(&self, hole_span: Span) -> (Option<Self>, Option<Self>) {
|
||||
let before = try {
|
||||
let span = self.span.trim_end(hole_span)?;
|
||||
Self { span, ..*self }
|
||||
};
|
||||
let after = try {
|
||||
let span = self.span.trim_start(hole_span)?;
|
||||
Self { span, ..*self }
|
||||
};
|
||||
|
||||
(before, after)
|
||||
pub(crate) fn into_covspan(self) -> Covspan {
|
||||
let Self { span, visible_macro: _, bcb } = self;
|
||||
Covspan { span, bcb }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
//! globals is comparatively simpler. The easiest way is to wrap the test in a closure argument
|
||||
//! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`.
|
||||
|
||||
use super::counters;
|
||||
use super::graph::{self, BasicCoverageBlock};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
|
@ -551,108 +550,3 @@ fn test_covgraph_switchint_loop_then_inner_loop_else_break() {
|
|||
assert_successors(&basic_coverage_blocks, bcb(5), &[bcb(1)]);
|
||||
assert_successors(&basic_coverage_blocks, bcb(6), &[bcb(4)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_loop_backedges_none() {
|
||||
let mir_body = goto_switchint();
|
||||
let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
|
||||
if false {
|
||||
eprintln!(
|
||||
"basic_coverage_blocks = {:?}",
|
||||
basic_coverage_blocks.iter_enumerated().collect::<Vec<_>>()
|
||||
);
|
||||
eprintln!("successors = {:?}", basic_coverage_blocks.successors);
|
||||
}
|
||||
let backedges = graph::find_loop_backedges(&basic_coverage_blocks);
|
||||
assert_eq!(
|
||||
backedges.iter_enumerated().map(|(_bcb, backedges)| backedges.len()).sum::<usize>(),
|
||||
0,
|
||||
"backedges: {:?}",
|
||||
backedges
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_loop_backedges_one() {
|
||||
let mir_body = switchint_then_loop_else_return();
|
||||
let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
|
||||
let backedges = graph::find_loop_backedges(&basic_coverage_blocks);
|
||||
assert_eq!(
|
||||
backedges.iter_enumerated().map(|(_bcb, backedges)| backedges.len()).sum::<usize>(),
|
||||
1,
|
||||
"backedges: {:?}",
|
||||
backedges
|
||||
);
|
||||
|
||||
assert_eq!(backedges[bcb(1)], &[bcb(3)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_loop_backedges_two() {
|
||||
let mir_body = switchint_loop_then_inner_loop_else_break();
|
||||
let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
|
||||
let backedges = graph::find_loop_backedges(&basic_coverage_blocks);
|
||||
assert_eq!(
|
||||
backedges.iter_enumerated().map(|(_bcb, backedges)| backedges.len()).sum::<usize>(),
|
||||
2,
|
||||
"backedges: {:?}",
|
||||
backedges
|
||||
);
|
||||
|
||||
assert_eq!(backedges[bcb(1)], &[bcb(5)]);
|
||||
assert_eq!(backedges[bcb(4)], &[bcb(6)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_traverse_coverage_with_loops() {
|
||||
let mir_body = switchint_loop_then_inner_loop_else_break();
|
||||
let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
|
||||
let mut traversed_in_order = Vec::new();
|
||||
let mut traversal = graph::TraverseCoverageGraphWithLoops::new(&basic_coverage_blocks);
|
||||
while let Some(bcb) = traversal.next() {
|
||||
traversed_in_order.push(bcb);
|
||||
}
|
||||
|
||||
// bcb0 is visited first. Then bcb1 starts the first loop, and all remaining nodes, *except*
|
||||
// bcb6 are inside the first loop.
|
||||
assert_eq!(
|
||||
*traversed_in_order.last().expect("should have elements"),
|
||||
bcb(6),
|
||||
"bcb6 should not be visited until all nodes inside the first loop have been visited"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_make_bcb_counters() {
|
||||
rustc_span::create_default_session_globals_then(|| {
|
||||
let mir_body = goto_switchint();
|
||||
let basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body);
|
||||
// Historically this test would use `spans` internals to set up fake
|
||||
// coverage spans for BCBs 1 and 2. Now we skip that step and just tell
|
||||
// BCB counter construction that those BCBs have spans.
|
||||
let bcb_has_coverage_spans = |bcb: BasicCoverageBlock| (1..=2).contains(&bcb.as_usize());
|
||||
let coverage_counters = counters::CoverageCounters::make_bcb_counters(
|
||||
&basic_coverage_blocks,
|
||||
bcb_has_coverage_spans,
|
||||
);
|
||||
assert_eq!(coverage_counters.num_expressions(), 0);
|
||||
|
||||
assert_eq!(
|
||||
0, // bcb1 has a `Counter` with id = 0
|
||||
match coverage_counters.bcb_counter(bcb(1)).expect("should have a counter") {
|
||||
counters::BcbCounter::Counter { id, .. } => id,
|
||||
_ => panic!("expected a Counter"),
|
||||
}
|
||||
.as_u32()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
1, // bcb2 has a `Counter` with id = 1
|
||||
match coverage_counters.bcb_counter(bcb(2)).expect("should have a counter") {
|
||||
counters::BcbCounter::Counter { id, .. } => id,
|
||||
_ => panic!("expected a Counter"),
|
||||
}
|
||||
.as_u32()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}
|
|||
use rustc_middle::mir::visit::*;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_session::config::{DebugInfo, OptLevel};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::sym;
|
||||
|
|
@ -293,7 +293,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
}
|
||||
|
||||
match callee.def {
|
||||
InstanceDef::Item(_) => {
|
||||
InstanceKind::Item(_) => {
|
||||
// If there is no MIR available (either because it was not in metadata or
|
||||
// because it has no MIR because it's an extern function), then the inliner
|
||||
// won't cause cycles on this.
|
||||
|
|
@ -302,24 +302,24 @@ impl<'tcx> Inliner<'tcx> {
|
|||
}
|
||||
}
|
||||
// These have no own callable MIR.
|
||||
InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => {
|
||||
InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => {
|
||||
return Err("instance without MIR (intrinsic / virtual)");
|
||||
}
|
||||
// This cannot result in an immediate cycle since the callee MIR is a shim, which does
|
||||
// not get any optimizations run on it. Any subsequent inlining may cause cycles, but we
|
||||
// do not need to catch this here, we can wait until the inliner decides to continue
|
||||
// inlining a second time.
|
||||
InstanceDef::VTableShim(_)
|
||||
| InstanceDef::ReifyShim(..)
|
||||
| InstanceDef::FnPtrShim(..)
|
||||
| InstanceDef::ClosureOnceShim { .. }
|
||||
| InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceDef::CoroutineKindShim { .. }
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::CloneShim(..)
|
||||
| InstanceDef::ThreadLocalShim(..)
|
||||
| InstanceDef::FnPtrAddrShim(..)
|
||||
| InstanceDef::AsyncDropGlueCtorShim(..) => return Ok(()),
|
||||
InstanceKind::VTableShim(_)
|
||||
| InstanceKind::ReifyShim(..)
|
||||
| InstanceKind::FnPtrShim(..)
|
||||
| InstanceKind::ClosureOnceShim { .. }
|
||||
| InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceKind::CoroutineKindShim { .. }
|
||||
| InstanceKind::DropGlue(..)
|
||||
| InstanceKind::CloneShim(..)
|
||||
| InstanceKind::ThreadLocalShim(..)
|
||||
| InstanceKind::FnPtrAddrShim(..)
|
||||
| InstanceKind::AsyncDropGlueCtorShim(..) => return Ok(()),
|
||||
}
|
||||
|
||||
if self.tcx.is_constructor(callee_def_id) {
|
||||
|
|
@ -372,7 +372,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
let callee =
|
||||
Instance::resolve(self.tcx, self.param_env, def_id, args).ok().flatten()?;
|
||||
|
||||
if let InstanceDef::Virtual(..) | InstanceDef::Intrinsic(_) = callee.def {
|
||||
if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -384,7 +384,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
|
||||
// Additionally, check that the body that we're inlining actually agrees
|
||||
// with the ABI of the trait that the item comes from.
|
||||
if let InstanceDef::Item(instance_def_id) = callee.def
|
||||
if let InstanceKind::Item(instance_def_id) = callee.def
|
||||
&& self.tcx.def_kind(instance_def_id) == DefKind::AssocFn
|
||||
&& let instance_fn_sig = self.tcx.fn_sig(instance_def_id).skip_binder()
|
||||
&& instance_fn_sig.abi() != fn_sig.abi()
|
||||
|
|
@ -1063,10 +1063,10 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
|
|||
#[instrument(skip(tcx), level = "debug")]
|
||||
fn try_instance_mir<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: InstanceDef<'tcx>,
|
||||
instance: InstanceKind<'tcx>,
|
||||
) -> Result<&'tcx Body<'tcx>, &'static str> {
|
||||
if let ty::InstanceDef::DropGlue(_, Some(ty))
|
||||
| ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) = instance
|
||||
if let ty::InstanceKind::DropGlue(_, Some(ty))
|
||||
| ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)) = instance
|
||||
&& let ty::Adt(def, args) = ty.kind()
|
||||
{
|
||||
let fields = def.all_fields();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
|
|||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::mir::TerminatorKind;
|
||||
use rustc_middle::ty::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, InstanceDef, TyCtxt};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, InstanceKind, TyCtxt};
|
||||
use rustc_session::Limit;
|
||||
use rustc_span::sym;
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
|||
"you should not call `mir_callgraph_reachable` on immediate self recursion"
|
||||
);
|
||||
assert!(
|
||||
matches!(root.def, InstanceDef::Item(_)),
|
||||
matches!(root.def, InstanceKind::Item(_)),
|
||||
"you should not call `mir_callgraph_reachable` on shims"
|
||||
);
|
||||
assert!(
|
||||
|
|
@ -70,7 +70,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
|||
}
|
||||
|
||||
match callee.def {
|
||||
InstanceDef::Item(_) => {
|
||||
InstanceKind::Item(_) => {
|
||||
// If there is no MIR available (either because it was not in metadata or
|
||||
// because it has no MIR because it's an extern function), then the inliner
|
||||
// won't cause cycles on this.
|
||||
|
|
@ -80,24 +80,24 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
|||
}
|
||||
}
|
||||
// These have no own callable MIR.
|
||||
InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => continue,
|
||||
InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => continue,
|
||||
// These have MIR and if that MIR is inlined, instantiated and then inlining is run
|
||||
// again, a function item can end up getting inlined. Thus we'll be able to cause
|
||||
// a cycle that way
|
||||
InstanceDef::VTableShim(_)
|
||||
| InstanceDef::ReifyShim(..)
|
||||
| InstanceDef::FnPtrShim(..)
|
||||
| InstanceDef::ClosureOnceShim { .. }
|
||||
| InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceDef::CoroutineKindShim { .. }
|
||||
| InstanceDef::ThreadLocalShim { .. }
|
||||
| InstanceDef::CloneShim(..) => {}
|
||||
InstanceKind::VTableShim(_)
|
||||
| InstanceKind::ReifyShim(..)
|
||||
| InstanceKind::FnPtrShim(..)
|
||||
| InstanceKind::ClosureOnceShim { .. }
|
||||
| InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceKind::CoroutineKindShim { .. }
|
||||
| InstanceKind::ThreadLocalShim { .. }
|
||||
| InstanceKind::CloneShim(..) => {}
|
||||
|
||||
// This shim does not call any other functions, thus there can be no recursion.
|
||||
InstanceDef::FnPtrAddrShim(..) => {
|
||||
InstanceKind::FnPtrAddrShim(..) => {
|
||||
continue;
|
||||
}
|
||||
InstanceDef::DropGlue(..) | InstanceDef::AsyncDropGlueCtorShim(..) => {
|
||||
InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) => {
|
||||
// FIXME: A not fully instantiated drop shim can cause ICEs if one attempts to
|
||||
// have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this
|
||||
// needs some more analysis.
|
||||
|
|
@ -151,12 +151,12 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
|||
|
||||
pub(crate) fn mir_inliner_callees<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
instance: ty::InstanceKind<'tcx>,
|
||||
) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] {
|
||||
let steal;
|
||||
let guard;
|
||||
let body = match (instance, instance.def_id().as_local()) {
|
||||
(InstanceDef::Item(_), Some(def_id)) => {
|
||||
(InstanceKind::Item(_), Some(def_id)) => {
|
||||
steal = tcx.mir_promoted(def_id).0;
|
||||
guard = steal.borrow();
|
||||
&*guard
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
|
|||
if is_fn_like {
|
||||
// Do not compute the mir call graph without said call graph actually being used.
|
||||
if pm::should_run_pass(tcx, &inline::Inline) {
|
||||
tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def.to_def_id()));
|
||||
tcx.ensure_with_value().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,16 +29,16 @@ pub fn provide(providers: &mut Providers) {
|
|||
providers.mir_shims = make_shim;
|
||||
}
|
||||
|
||||
fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'tcx> {
|
||||
fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<'tcx> {
|
||||
debug!("make_shim({:?})", instance);
|
||||
|
||||
let mut result = match instance {
|
||||
ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance),
|
||||
ty::InstanceDef::VTableShim(def_id) => {
|
||||
ty::InstanceKind::Item(..) => bug!("item {:?} passed to make_shim", instance),
|
||||
ty::InstanceKind::VTableShim(def_id) => {
|
||||
let adjustment = Adjustment::Deref { source: DerefSource::MutPtr };
|
||||
build_call_shim(tcx, instance, Some(adjustment), CallKind::Direct(def_id))
|
||||
}
|
||||
ty::InstanceDef::FnPtrShim(def_id, ty) => {
|
||||
ty::InstanceKind::FnPtrShim(def_id, ty) => {
|
||||
let trait_ = tcx.trait_of_item(def_id).unwrap();
|
||||
// Supports `Fn` or `async Fn` traits.
|
||||
let adjustment = match tcx
|
||||
|
|
@ -58,10 +58,10 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
|
|||
// a virtual call, or a direct call to a function for which
|
||||
// indirect calls must be codegen'd differently than direct ones
|
||||
// (such as `#[track_caller]`).
|
||||
ty::InstanceDef::ReifyShim(def_id, _) => {
|
||||
ty::InstanceKind::ReifyShim(def_id, _) => {
|
||||
build_call_shim(tcx, instance, None, CallKind::Direct(def_id))
|
||||
}
|
||||
ty::InstanceDef::ClosureOnceShim { call_once: _, track_caller: _ } => {
|
||||
ty::InstanceKind::ClosureOnceShim { call_once: _, track_caller: _ } => {
|
||||
let fn_mut = tcx.require_lang_item(LangItem::FnMut, None);
|
||||
let call_mut = tcx
|
||||
.associated_items(fn_mut)
|
||||
|
|
@ -73,16 +73,16 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
|
|||
build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut))
|
||||
}
|
||||
|
||||
ty::InstanceDef::ConstructCoroutineInClosureShim {
|
||||
ty::InstanceKind::ConstructCoroutineInClosureShim {
|
||||
coroutine_closure_def_id,
|
||||
receiver_by_ref,
|
||||
} => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref),
|
||||
|
||||
ty::InstanceDef::CoroutineKindShim { coroutine_def_id } => {
|
||||
ty::InstanceKind::CoroutineKindShim { coroutine_def_id } => {
|
||||
return tcx.optimized_mir(coroutine_def_id).coroutine_by_move_body().unwrap().clone();
|
||||
}
|
||||
|
||||
ty::InstanceDef::DropGlue(def_id, ty) => {
|
||||
ty::InstanceKind::DropGlue(def_id, ty) => {
|
||||
// FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end
|
||||
// of this function. Is this intentional?
|
||||
if let Some(ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) {
|
||||
|
|
@ -127,16 +127,16 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
|
|||
|
||||
build_drop_shim(tcx, def_id, ty)
|
||||
}
|
||||
ty::InstanceDef::ThreadLocalShim(..) => build_thread_local_shim(tcx, instance),
|
||||
ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty),
|
||||
ty::InstanceDef::FnPtrAddrShim(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty),
|
||||
ty::InstanceDef::AsyncDropGlueCtorShim(def_id, ty) => {
|
||||
ty::InstanceKind::ThreadLocalShim(..) => build_thread_local_shim(tcx, instance),
|
||||
ty::InstanceKind::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty),
|
||||
ty::InstanceKind::FnPtrAddrShim(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty),
|
||||
ty::InstanceKind::AsyncDropGlueCtorShim(def_id, ty) => {
|
||||
async_destructor_ctor::build_async_destructor_ctor_shim(tcx, def_id, ty)
|
||||
}
|
||||
ty::InstanceDef::Virtual(..) => {
|
||||
bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
|
||||
ty::InstanceKind::Virtual(..) => {
|
||||
bug!("InstanceKind::Virtual ({:?}) is for direct calls only", instance)
|
||||
}
|
||||
ty::InstanceDef::Intrinsic(_) => {
|
||||
ty::InstanceKind::Intrinsic(_) => {
|
||||
bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
|
||||
}
|
||||
};
|
||||
|
|
@ -240,7 +240,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
|||
block(&mut blocks, TerminatorKind::Goto { target: return_block });
|
||||
block(&mut blocks, TerminatorKind::Return);
|
||||
|
||||
let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty));
|
||||
let source = MirSource::from_instance(ty::InstanceKind::DropGlue(def_id, ty));
|
||||
let mut body =
|
||||
new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
|
||||
|
||||
|
|
@ -392,7 +392,10 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'tcx> {
|
||||
fn build_thread_local_shim<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: ty::InstanceKind<'tcx>,
|
||||
) -> Body<'tcx> {
|
||||
let def_id = instance.def_id();
|
||||
|
||||
let span = tcx.def_span(def_id);
|
||||
|
|
@ -472,7 +475,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
|
|||
}
|
||||
|
||||
fn into_mir(self) -> Body<'tcx> {
|
||||
let source = MirSource::from_instance(ty::InstanceDef::CloneShim(
|
||||
let source = MirSource::from_instance(ty::InstanceKind::CloneShim(
|
||||
self.def_id,
|
||||
self.sig.inputs_and_output[0],
|
||||
));
|
||||
|
|
@ -682,14 +685,14 @@ impl<'tcx> CloneShimBuilder<'tcx> {
|
|||
#[instrument(level = "debug", skip(tcx), ret)]
|
||||
fn build_call_shim<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
instance: ty::InstanceKind<'tcx>,
|
||||
rcvr_adjustment: Option<Adjustment>,
|
||||
call_kind: CallKind<'tcx>,
|
||||
) -> Body<'tcx> {
|
||||
// `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used
|
||||
// to instantiate into the signature of the shim. It is not necessary for users of this
|
||||
// MIR body to perform further instantiations (see `InstanceDef::has_polymorphic_mir_body`).
|
||||
let (sig_args, untuple_args) = if let ty::InstanceDef::FnPtrShim(_, ty) = instance {
|
||||
// MIR body to perform further instantiations (see `InstanceKind::has_polymorphic_mir_body`).
|
||||
let (sig_args, untuple_args) = if let ty::InstanceKind::FnPtrShim(_, ty) = instance {
|
||||
let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx));
|
||||
|
||||
let untuple_args = sig.inputs();
|
||||
|
|
@ -741,8 +744,8 @@ fn build_call_shim<'tcx>(
|
|||
}
|
||||
|
||||
// FIXME(eddyb) avoid having this snippet both here and in
|
||||
// `Instance::fn_sig` (introduce `InstanceDef::fn_sig`?).
|
||||
if let ty::InstanceDef::VTableShim(..) = instance {
|
||||
// `Instance::fn_sig` (introduce `InstanceKind::fn_sig`?).
|
||||
if let ty::InstanceKind::VTableShim(..) = instance {
|
||||
// Modify fn(self, ...) to fn(self: *mut Self, ...)
|
||||
let mut inputs_and_output = sig.inputs_and_output.to_vec();
|
||||
let self_arg = &mut inputs_and_output[0];
|
||||
|
|
@ -1007,7 +1010,7 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t
|
|||
terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }),
|
||||
is_cleanup: false,
|
||||
};
|
||||
let source = MirSource::from_instance(ty::InstanceDef::FnPtrAddrShim(def_id, self_ty));
|
||||
let source = MirSource::from_instance(ty::InstanceKind::FnPtrAddrShim(def_id, self_ty));
|
||||
new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span)
|
||||
}
|
||||
|
||||
|
|
@ -1087,7 +1090,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
|
|||
is_cleanup: false,
|
||||
};
|
||||
|
||||
let source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim {
|
||||
let source = MirSource::from_instance(ty::InstanceKind::ConstructCoroutineInClosureShim {
|
||||
coroutine_closure_def_id,
|
||||
receiver_by_ref,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -529,7 +529,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
|
|||
|
||||
last_bb.terminator = Some(Terminator { source_info, kind: TerminatorKind::Return });
|
||||
|
||||
let source = MirSource::from_instance(ty::InstanceDef::AsyncDropGlueCtorShim(
|
||||
let source = MirSource::from_instance(ty::InstanceKind::AsyncDropGlueCtorShim(
|
||||
self.def_id,
|
||||
self.self_ty,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
|
|||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::{
|
||||
self, CoroutineArgsExt, InstanceDef, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
|
||||
self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
|
||||
Variance,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
|
|
@ -44,7 +44,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
|||
// terribly important that they pass the validator. However, I think other passes might
|
||||
// still see them, in which case they might be surprised. It would probably be better if we
|
||||
// didn't put this through the MIR pipeline at all.
|
||||
if matches!(body.source.instance, InstanceDef::Intrinsic(..) | InstanceDef::Virtual(..)) {
|
||||
if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) {
|
||||
return;
|
||||
}
|
||||
let def_id = body.source.def_id();
|
||||
|
|
@ -95,7 +95,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
|||
}
|
||||
|
||||
if let MirPhase::Runtime(_) = body.phase {
|
||||
if let ty::InstanceDef::Item(_) = body.source.instance {
|
||||
if let ty::InstanceKind::Item(_) = body.source.instance {
|
||||
if body.has_free_regions() {
|
||||
cfg_checker.fail(
|
||||
Location::START,
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
|
|||
use rustc_middle::ty::layout::ValidityRequirement;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{
|
||||
self, AssocKind, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable,
|
||||
self, AssocKind, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable,
|
||||
TypeVisitableExt, VtblEntry,
|
||||
};
|
||||
use rustc_middle::ty::{GenericArgKind, GenericArgs};
|
||||
|
|
@ -420,7 +420,7 @@ fn collect_items_rec<'tcx>(
|
|||
used_items.push(respan(
|
||||
starting_item.span,
|
||||
MonoItem::Fn(Instance {
|
||||
def: InstanceDef::ThreadLocalShim(def_id),
|
||||
def: InstanceKind::ThreadLocalShim(def_id),
|
||||
args: GenericArgs::empty(),
|
||||
}),
|
||||
));
|
||||
|
|
@ -938,7 +938,7 @@ fn visit_instance_use<'tcx>(
|
|||
if !should_codegen_locally(tcx, instance) {
|
||||
return;
|
||||
}
|
||||
if let ty::InstanceDef::Intrinsic(def_id) = instance.def {
|
||||
if let ty::InstanceKind::Intrinsic(def_id) = instance.def {
|
||||
let name = tcx.item_name(def_id);
|
||||
if let Some(_requirement) = ValidityRequirement::from_intrinsic(name) {
|
||||
// The intrinsics assert_inhabited, assert_zero_valid, and assert_mem_uninitialized_valid will
|
||||
|
|
@ -960,31 +960,31 @@ fn visit_instance_use<'tcx>(
|
|||
}
|
||||
|
||||
match instance.def {
|
||||
ty::InstanceDef::Virtual(..) | ty::InstanceDef::Intrinsic(_) => {
|
||||
ty::InstanceKind::Virtual(..) | ty::InstanceKind::Intrinsic(_) => {
|
||||
if !is_direct_call {
|
||||
bug!("{:?} being reified", instance);
|
||||
}
|
||||
}
|
||||
ty::InstanceDef::ThreadLocalShim(..) => {
|
||||
ty::InstanceKind::ThreadLocalShim(..) => {
|
||||
bug!("{:?} being reified", instance);
|
||||
}
|
||||
ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) => {
|
||||
ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) => {
|
||||
// Don't need to emit noop drop glue if we are calling directly.
|
||||
if !is_direct_call {
|
||||
output.push(create_fn_mono_item(tcx, instance, source));
|
||||
}
|
||||
}
|
||||
ty::InstanceDef::DropGlue(_, Some(_))
|
||||
| ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(_))
|
||||
| ty::InstanceDef::VTableShim(..)
|
||||
| ty::InstanceDef::ReifyShim(..)
|
||||
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineKindShim { .. }
|
||||
| ty::InstanceDef::Item(..)
|
||||
| ty::InstanceDef::FnPtrShim(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::FnPtrAddrShim(..) => {
|
||||
ty::InstanceKind::DropGlue(_, Some(_))
|
||||
| ty::InstanceKind::AsyncDropGlueCtorShim(_, Some(_))
|
||||
| ty::InstanceKind::VTableShim(..)
|
||||
| ty::InstanceKind::ReifyShim(..)
|
||||
| ty::InstanceKind::ClosureOnceShim { .. }
|
||||
| ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceKind::CoroutineKindShim { .. }
|
||||
| ty::InstanceKind::Item(..)
|
||||
| ty::InstanceKind::FnPtrShim(..)
|
||||
| ty::InstanceKind::CloneShim(..)
|
||||
| ty::InstanceKind::FnPtrAddrShim(..) => {
|
||||
output.push(create_fn_mono_item(tcx, instance, source));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ use rustc_middle::mir::mono::{
|
|||
};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceDef, TyCtxt};
|
||||
use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceKind, TyCtxt};
|
||||
use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
|
||||
use rustc_session::CodegenUnits;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
|
@ -620,20 +620,20 @@ fn characteristic_def_id_of_mono_item<'tcx>(
|
|||
match mono_item {
|
||||
MonoItem::Fn(instance) => {
|
||||
let def_id = match instance.def {
|
||||
ty::InstanceDef::Item(def) => def,
|
||||
ty::InstanceDef::VTableShim(..)
|
||||
| ty::InstanceDef::ReifyShim(..)
|
||||
| ty::InstanceDef::FnPtrShim(..)
|
||||
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineKindShim { .. }
|
||||
| ty::InstanceDef::Intrinsic(..)
|
||||
| ty::InstanceDef::DropGlue(..)
|
||||
| ty::InstanceDef::Virtual(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::ThreadLocalShim(..)
|
||||
| ty::InstanceDef::FnPtrAddrShim(..)
|
||||
| ty::InstanceDef::AsyncDropGlueCtorShim(..) => return None,
|
||||
ty::InstanceKind::Item(def) => def,
|
||||
ty::InstanceKind::VTableShim(..)
|
||||
| ty::InstanceKind::ReifyShim(..)
|
||||
| ty::InstanceKind::FnPtrShim(..)
|
||||
| ty::InstanceKind::ClosureOnceShim { .. }
|
||||
| ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceKind::CoroutineKindShim { .. }
|
||||
| ty::InstanceKind::Intrinsic(..)
|
||||
| ty::InstanceKind::DropGlue(..)
|
||||
| ty::InstanceKind::Virtual(..)
|
||||
| ty::InstanceKind::CloneShim(..)
|
||||
| ty::InstanceKind::ThreadLocalShim(..)
|
||||
| ty::InstanceKind::FnPtrAddrShim(..)
|
||||
| ty::InstanceKind::AsyncDropGlueCtorShim(..) => return None,
|
||||
};
|
||||
|
||||
// If this is a method, we want to put it into the same module as
|
||||
|
|
@ -777,28 +777,28 @@ fn mono_item_visibility<'tcx>(
|
|||
};
|
||||
|
||||
let def_id = match instance.def {
|
||||
InstanceDef::Item(def_id)
|
||||
| InstanceDef::DropGlue(def_id, Some(_))
|
||||
| InstanceDef::AsyncDropGlueCtorShim(def_id, Some(_)) => def_id,
|
||||
InstanceKind::Item(def_id)
|
||||
| InstanceKind::DropGlue(def_id, Some(_))
|
||||
| InstanceKind::AsyncDropGlueCtorShim(def_id, Some(_)) => def_id,
|
||||
|
||||
// We match the visibility of statics here
|
||||
InstanceDef::ThreadLocalShim(def_id) => {
|
||||
InstanceKind::ThreadLocalShim(def_id) => {
|
||||
return static_visibility(tcx, can_be_internalized, def_id);
|
||||
}
|
||||
|
||||
// These are all compiler glue and such, never exported, always hidden.
|
||||
InstanceDef::VTableShim(..)
|
||||
| InstanceDef::ReifyShim(..)
|
||||
| InstanceDef::FnPtrShim(..)
|
||||
| InstanceDef::Virtual(..)
|
||||
| InstanceDef::Intrinsic(..)
|
||||
| InstanceDef::ClosureOnceShim { .. }
|
||||
| InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceDef::CoroutineKindShim { .. }
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::AsyncDropGlueCtorShim(..)
|
||||
| InstanceDef::CloneShim(..)
|
||||
| InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden,
|
||||
InstanceKind::VTableShim(..)
|
||||
| InstanceKind::ReifyShim(..)
|
||||
| InstanceKind::FnPtrShim(..)
|
||||
| InstanceKind::Virtual(..)
|
||||
| InstanceKind::Intrinsic(..)
|
||||
| InstanceKind::ClosureOnceShim { .. }
|
||||
| InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceKind::CoroutineKindShim { .. }
|
||||
| InstanceKind::DropGlue(..)
|
||||
| InstanceKind::AsyncDropGlueCtorShim(..)
|
||||
| InstanceKind::CloneShim(..)
|
||||
| InstanceKind::FnPtrAddrShim(..) => return Visibility::Hidden,
|
||||
};
|
||||
|
||||
// The `start_fn` lang item is actually a monomorphized instance of a
|
||||
|
|
@ -813,7 +813,7 @@ fn mono_item_visibility<'tcx>(
|
|||
// internalization, but we have to understand that it's referenced
|
||||
// from the `main` symbol we'll generate later.
|
||||
//
|
||||
// This may be fixable with a new `InstanceDef` perhaps? Unsure!
|
||||
// This may be fixable with a new `InstanceKind` perhaps? Unsure!
|
||||
if tcx.is_lang_item(def_id, LangItem::Start) {
|
||||
*can_be_internalized = false;
|
||||
return Visibility::Hidden;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
/// parameters are used).
|
||||
fn unused_generic_params<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
instance: ty::InstanceKind<'tcx>,
|
||||
) -> UnusedGenericParams {
|
||||
assert!(instance.def_id().is_local());
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ fn unused_generic_params<'tcx>(
|
|||
fn should_polymorphize<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
instance: ty::InstanceKind<'tcx>,
|
||||
) -> bool {
|
||||
// If an instance's MIR body is not polymorphic then the modified generic parameters that are
|
||||
// derived from polymorphization's result won't make any difference.
|
||||
|
|
@ -97,7 +97,7 @@ fn should_polymorphize<'tcx>(
|
|||
}
|
||||
|
||||
// Don't polymorphize intrinsics or virtual calls - calling `instance_mir` will panic.
|
||||
if matches!(instance, ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::Virtual(..)) {
|
||||
if matches!(instance, ty::InstanceKind::Intrinsic(..) | ty::InstanceKind::Virtual(..)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
|
|||
/// a closure, coroutine or constant).
|
||||
#[instrument(level = "debug", skip(self, def_id, args))]
|
||||
fn visit_child_body(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) {
|
||||
let instance = ty::InstanceDef::Item(def_id);
|
||||
let instance = ty::InstanceKind::Item(def_id);
|
||||
let unused = self.tcx.unused_generic_params(instance);
|
||||
debug!(?self.unused_parameters, ?unused);
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
//! Crate containing the implementation of the next-generation trait solver.
|
||||
//!
|
||||
//! This crate may also contain things that are used by the old trait solver,
|
||||
//! but were uplifted in the process of making the new trait solver generic.
|
||||
//! So if you got to this crate from the old solver, it's totally normal.
|
||||
|
||||
pub mod canonicalizer;
|
||||
pub mod resolve;
|
||||
pub mod solve;
|
||||
|
|
|
|||
|
|
@ -973,8 +973,12 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
|
|||
|
||||
impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
|
||||
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
|
||||
let old_maybe_typeck_results =
|
||||
self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
|
||||
let new_typeck_results = self.tcx.typeck_body(body_id);
|
||||
// Do not try reporting privacy violations if we failed to infer types.
|
||||
if new_typeck_results.tainted_by_errors.is_some() {
|
||||
return;
|
||||
}
|
||||
let old_maybe_typeck_results = self.maybe_typeck_results.replace(new_typeck_results);
|
||||
self.visit_body(self.tcx.hir().body(body_id));
|
||||
self.maybe_typeck_results = old_maybe_typeck_results;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -966,7 +966,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
for single_import in &resolution.single_imports {
|
||||
let Some(import_vis) = single_import.vis.get() else {
|
||||
// This branch handles a cycle in single imports, which occurs
|
||||
// when we've previously captured the `vis` value during an import
|
||||
// when we've previously **steal** the `vis` value during an import
|
||||
// process.
|
||||
//
|
||||
// For example:
|
||||
|
|
@ -998,21 +998,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
let Some(module) = single_import.imported_module.get() else {
|
||||
return Err((Undetermined, Weak::No));
|
||||
};
|
||||
let ImportKind::Single { source: ident, target, target_bindings, .. } =
|
||||
&single_import.kind
|
||||
let ImportKind::Single { source, target, target_bindings, .. } = &single_import.kind
|
||||
else {
|
||||
unreachable!();
|
||||
};
|
||||
if (ident != target) && target_bindings.iter().all(|binding| binding.get().is_none()) {
|
||||
if source != target {
|
||||
// This branch allows the binding to be defined or updated later if the target name
|
||||
// can hide the source but these bindings are not obtained.
|
||||
// avoiding module inconsistency between the resolve process and the finalize process.
|
||||
// See more details in #124840
|
||||
return Err((Undetermined, Weak::No));
|
||||
// can hide the source.
|
||||
if target_bindings.iter().all(|binding| binding.get().is_none()) {
|
||||
// None of the target bindings are available, so we can't determine
|
||||
// if this binding is correct or not.
|
||||
// See more details in #124840
|
||||
return Err((Undetermined, Weak::No));
|
||||
} else if target_bindings[ns].get().is_none() && binding.is_some() {
|
||||
// `binding.is_some()` avoids the condition where the binding
|
||||
// truly doesn't exist in this namespace and should return `Err(Determined)`.
|
||||
return Err((Undetermined, Weak::No));
|
||||
}
|
||||
}
|
||||
|
||||
match self.resolve_ident_in_module(
|
||||
module,
|
||||
*ident,
|
||||
*source,
|
||||
ns,
|
||||
&single_import.parent_scope,
|
||||
None,
|
||||
|
|
|
|||
|
|
@ -310,9 +310,10 @@ enum LifetimeRibKind {
|
|||
/// error on default object bounds (e.g., `Box<dyn Foo>`).
|
||||
AnonymousReportError,
|
||||
|
||||
/// Resolves elided lifetimes to `'static`, but gives a warning that this behavior
|
||||
/// is a bug and will be reverted soon.
|
||||
AnonymousWarn(NodeId),
|
||||
/// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope,
|
||||
/// otherwise give a warning that the previous behavior of introducing a new early-bound
|
||||
/// lifetime is a bug and will be removed (if `emit_lint` is enabled).
|
||||
StaticIfNoLifetimeInScope { lint_id: NodeId, emit_lint: bool },
|
||||
|
||||
/// Signal we cannot find which should be the anonymous lifetime.
|
||||
ElisionFailure,
|
||||
|
|
@ -1212,7 +1213,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
|||
}
|
||||
LifetimeRibKind::AnonymousCreateParameter { .. }
|
||||
| LifetimeRibKind::AnonymousReportError
|
||||
| LifetimeRibKind::AnonymousWarn(_)
|
||||
| LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
|
||||
| LifetimeRibKind::Elided(_)
|
||||
| LifetimeRibKind::ElisionFailure
|
||||
| LifetimeRibKind::ConcreteAnonConst(_)
|
||||
|
|
@ -1580,7 +1581,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
// lifetime would be illegal.
|
||||
LifetimeRibKind::Item
|
||||
| LifetimeRibKind::AnonymousReportError
|
||||
| LifetimeRibKind::AnonymousWarn(_)
|
||||
| LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
|
||||
| LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
|
||||
// An anonymous lifetime is legal here, and bound to the right
|
||||
// place, go ahead.
|
||||
|
|
@ -1643,7 +1644,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
| LifetimeRibKind::Generics { .. }
|
||||
| LifetimeRibKind::ElisionFailure
|
||||
| LifetimeRibKind::AnonymousReportError
|
||||
| LifetimeRibKind::AnonymousWarn(_) => {}
|
||||
| LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1677,16 +1678,36 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
self.record_lifetime_res(lifetime.id, res, elision_candidate);
|
||||
return;
|
||||
}
|
||||
LifetimeRibKind::AnonymousWarn(node_id) => {
|
||||
self.r.lint_buffer.buffer_lint(
|
||||
lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
|
||||
node_id,
|
||||
lifetime.ident.span,
|
||||
lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
|
||||
elided,
|
||||
span: lifetime.ident.span,
|
||||
},
|
||||
);
|
||||
LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => {
|
||||
let mut lifetimes_in_scope = vec![];
|
||||
for rib in &self.lifetime_ribs[..i] {
|
||||
lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span));
|
||||
// Consider any anonymous lifetimes, too
|
||||
if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind
|
||||
&& let Some(extra) = self.r.extra_lifetime_params_map.get(&binder)
|
||||
{
|
||||
lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span));
|
||||
}
|
||||
}
|
||||
if lifetimes_in_scope.is_empty() {
|
||||
self.record_lifetime_res(
|
||||
lifetime.id,
|
||||
LifetimeRes::Static,
|
||||
elision_candidate,
|
||||
);
|
||||
return;
|
||||
} else if emit_lint {
|
||||
self.r.lint_buffer.buffer_lint(
|
||||
lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
|
||||
node_id,
|
||||
lifetime.ident.span,
|
||||
lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
|
||||
elided,
|
||||
span: lifetime.ident.span,
|
||||
lifetimes_in_scope: lifetimes_in_scope.into(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
LifetimeRibKind::AnonymousReportError => {
|
||||
if elided {
|
||||
|
|
@ -1904,7 +1925,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
// impl Foo for std::cell::Ref<u32> // note lack of '_
|
||||
// async fn foo(_: std::cell::Ref<u32>) { ... }
|
||||
LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
|
||||
| LifetimeRibKind::AnonymousWarn(_) => {
|
||||
| LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {
|
||||
let sess = self.r.tcx.sess;
|
||||
let subdiag = rustc_errors::elided_lifetime_in_path_suggestion(
|
||||
sess.source_map(),
|
||||
|
|
@ -2838,19 +2859,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
kind: LifetimeBinderKind::ConstItem,
|
||||
},
|
||||
|this| {
|
||||
this.visit_generics(generics);
|
||||
this.visit_ty(ty);
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::StaticIfNoLifetimeInScope {
|
||||
lint_id: item.id,
|
||||
emit_lint: false,
|
||||
},
|
||||
|this| {
|
||||
this.visit_generics(generics);
|
||||
this.visit_ty(ty);
|
||||
|
||||
// Only impose the restrictions of `ConstRibKind` for an
|
||||
// actual constant expression in a provided default.
|
||||
if let Some(expr) = expr {
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.resolve_const_body(expr, None);
|
||||
}
|
||||
// Only impose the restrictions of `ConstRibKind` for an
|
||||
// actual constant expression in a provided default.
|
||||
if let Some(expr) = expr {
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.resolve_const_body(expr, None);
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -3030,30 +3059,37 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
kind: LifetimeBinderKind::ConstItem,
|
||||
},
|
||||
|this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::AnonymousWarn(item.id), |this| {
|
||||
// If this is a trait impl, ensure the const
|
||||
// exists in trait
|
||||
this.check_trait_item(
|
||||
item.id,
|
||||
item.ident,
|
||||
&item.kind,
|
||||
ValueNS,
|
||||
item.span,
|
||||
seen_trait_items,
|
||||
|i, s, c| ConstNotMemberOfTrait(i, s, c),
|
||||
);
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::StaticIfNoLifetimeInScope {
|
||||
lint_id: item.id,
|
||||
// In impls, it's not a hard error yet due to backcompat.
|
||||
emit_lint: true,
|
||||
},
|
||||
|this| {
|
||||
// If this is a trait impl, ensure the const
|
||||
// exists in trait
|
||||
this.check_trait_item(
|
||||
item.id,
|
||||
item.ident,
|
||||
&item.kind,
|
||||
ValueNS,
|
||||
item.span,
|
||||
seen_trait_items,
|
||||
|i, s, c| ConstNotMemberOfTrait(i, s, c),
|
||||
);
|
||||
|
||||
this.visit_generics(generics);
|
||||
this.visit_ty(ty);
|
||||
if let Some(expr) = expr {
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.resolve_const_body(expr, None);
|
||||
}
|
||||
});
|
||||
this.visit_generics(generics);
|
||||
this.visit_ty(ty);
|
||||
if let Some(expr) = expr {
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.resolve_const_body(expr, None);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,9 +288,9 @@ pub fn transform_instance<'tcx>(
|
|||
mut instance: Instance<'tcx>,
|
||||
options: TransformTyOptions,
|
||||
) -> Instance<'tcx> {
|
||||
if (matches!(instance.def, ty::InstanceDef::Virtual(..))
|
||||
if (matches!(instance.def, ty::InstanceKind::Virtual(..))
|
||||
&& tcx.is_lang_item(instance.def_id(), LangItem::DropInPlace))
|
||||
|| matches!(instance.def, ty::InstanceDef::DropGlue(..))
|
||||
|| matches!(instance.def, ty::InstanceKind::DropGlue(..))
|
||||
{
|
||||
// Adjust the type ids of DropGlues
|
||||
//
|
||||
|
|
@ -316,7 +316,7 @@ pub fn transform_instance<'tcx>(
|
|||
let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]);
|
||||
let self_ty = Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn);
|
||||
instance.args = tcx.mk_args_trait(self_ty, List::empty());
|
||||
} else if let ty::InstanceDef::Virtual(def_id, _) = instance.def {
|
||||
} else if let ty::InstanceKind::Virtual(def_id, _) = instance.def {
|
||||
// Transform self into a trait object of the trait that defines the method for virtual
|
||||
// functions to match the type erasure done below.
|
||||
let upcast_ty = match tcx.trait_of_item(def_id) {
|
||||
|
|
@ -343,7 +343,7 @@ pub fn transform_instance<'tcx>(
|
|||
tcx.types.unit
|
||||
};
|
||||
instance.args = tcx.mk_args_trait(self_ty, instance.args.into_iter().skip(1));
|
||||
} else if let ty::InstanceDef::VTableShim(def_id) = instance.def
|
||||
} else if let ty::InstanceKind::VTableShim(def_id) = instance.def
|
||||
&& let Some(trait_id) = tcx.trait_of_item(def_id)
|
||||
{
|
||||
// Adjust the type ids of VTableShims to the type id expected in the call sites for the
|
||||
|
|
@ -387,7 +387,7 @@ pub fn transform_instance<'tcx>(
|
|||
// If we ever *do* start encoding the vtable index, we will need to generate an alias set
|
||||
// based on which vtables we are putting this method into, as there will be more than one
|
||||
// index value when supertraits are involved.
|
||||
instance.def = ty::InstanceDef::Virtual(method_id, 0);
|
||||
instance.def = ty::InstanceKind::Virtual(method_id, 0);
|
||||
let abstract_trait_args =
|
||||
tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
|
||||
instance.args = instance.args.rebase_onto(tcx, impl_id, abstract_trait_args);
|
||||
|
|
@ -442,7 +442,7 @@ pub fn transform_instance<'tcx>(
|
|||
.expect("No call-family function on closure-like Fn trait?")
|
||||
.def_id;
|
||||
|
||||
instance.def = ty::InstanceDef::Virtual(call, 0);
|
||||
instance.def = ty::InstanceKind::Virtual(call, 0);
|
||||
instance.args = abstract_args;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
//!
|
||||
//! For more information about LLVM KCFI and cross-language LLVM KCFI support for the Rust compiler,
|
||||
//! see the tracking issue #123479.
|
||||
use rustc_middle::ty::{Instance, InstanceDef, ReifyReason, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{Instance, InstanceKind, ReifyReason, Ty, TyCtxt};
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
use std::hash::Hasher;
|
||||
use twox_hash::XxHash64;
|
||||
|
|
@ -44,7 +44,7 @@ pub fn typeid_for_instance<'tcx>(
|
|||
//
|
||||
// This was implemented for KCFI support in #123106 and #123052 (which introduced the
|
||||
// ReifyReason). The tracking issue for KCFI support for Rust is #123479.
|
||||
if matches!(instance.def, InstanceDef::ReifyShim(_, Some(ReifyReason::FnPtr))) {
|
||||
if matches!(instance.def, InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr))) {
|
||||
options.insert(TypeIdOptions::USE_CONCRETE_SELF);
|
||||
}
|
||||
// A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl<'tcx> BodyBuilder<'tcx> {
|
|||
pub fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self {
|
||||
let instance = match instance.def {
|
||||
// To get the fallback body of an intrinsic, we need to convert it to an item.
|
||||
ty::InstanceDef::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args),
|
||||
ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args),
|
||||
_ => instance,
|
||||
};
|
||||
BodyBuilder { tcx, instance }
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
|||
fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[item];
|
||||
tables.tcx.instance_mir(rustc_middle::ty::InstanceDef::Item(def_id)).stable(&mut tables)
|
||||
tables.tcx.instance_mir(rustc_middle::ty::InstanceKind::Item(def_id)).stable(&mut tables)
|
||||
}
|
||||
|
||||
fn has_body(&self, def: DefId) -> bool {
|
||||
|
|
@ -548,13 +548,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
|||
fn is_empty_drop_shim(&self, def: InstanceDef) -> bool {
|
||||
let tables = self.0.borrow_mut();
|
||||
let instance = tables.instances[def];
|
||||
matches!(instance.def, ty::InstanceDef::DropGlue(_, None))
|
||||
matches!(instance.def, ty::InstanceKind::DropGlue(_, None))
|
||||
}
|
||||
|
||||
fn is_empty_async_drop_ctor_shim(&self, def: InstanceDef) -> bool {
|
||||
let tables = self.0.borrow_mut();
|
||||
let instance = tables.instances[def];
|
||||
matches!(instance.def, ty::InstanceDef::AsyncDropGlueCtorShim(_, None))
|
||||
matches!(instance.def, ty::InstanceKind::AsyncDropGlueCtorShim(_, None))
|
||||
}
|
||||
|
||||
fn mono_instance(&self, def_id: stable_mir::DefId) -> stable_mir::mir::mono::Instance {
|
||||
|
|
|
|||
|
|
@ -839,22 +839,22 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
|
|||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
let def = tables.instance_def(tables.tcx.lift(*self).unwrap());
|
||||
let kind = match self.def {
|
||||
ty::InstanceDef::Item(..) => stable_mir::mir::mono::InstanceKind::Item,
|
||||
ty::InstanceDef::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic,
|
||||
ty::InstanceDef::Virtual(_def_id, idx) => {
|
||||
ty::InstanceKind::Item(..) => stable_mir::mir::mono::InstanceKind::Item,
|
||||
ty::InstanceKind::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic,
|
||||
ty::InstanceKind::Virtual(_def_id, idx) => {
|
||||
stable_mir::mir::mono::InstanceKind::Virtual { idx }
|
||||
}
|
||||
ty::InstanceDef::VTableShim(..)
|
||||
| ty::InstanceDef::ReifyShim(..)
|
||||
| ty::InstanceDef::FnPtrAddrShim(..)
|
||||
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineKindShim { .. }
|
||||
| ty::InstanceDef::ThreadLocalShim(..)
|
||||
| ty::InstanceDef::DropGlue(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::FnPtrShim(..)
|
||||
| ty::InstanceDef::AsyncDropGlueCtorShim(..) => {
|
||||
ty::InstanceKind::VTableShim(..)
|
||||
| ty::InstanceKind::ReifyShim(..)
|
||||
| ty::InstanceKind::FnPtrAddrShim(..)
|
||||
| ty::InstanceKind::ClosureOnceShim { .. }
|
||||
| ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceKind::CoroutineKindShim { .. }
|
||||
| ty::InstanceKind::ThreadLocalShim(..)
|
||||
| ty::InstanceKind::DropGlue(..)
|
||||
| ty::InstanceKind::CloneShim(..)
|
||||
| ty::InstanceKind::FnPtrShim(..)
|
||||
| ty::InstanceKind::AsyncDropGlueCtorShim(..) => {
|
||||
stable_mir::mir::mono::InstanceKind::Shim
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -60,9 +60,9 @@ impl<'tcx> Tables<'tcx> {
|
|||
self.item_has_body(def_id)
|
||||
|| !matches!(
|
||||
instance.def,
|
||||
ty::InstanceDef::Virtual(..)
|
||||
| ty::InstanceDef::Intrinsic(..)
|
||||
| ty::InstanceDef::Item(..)
|
||||
ty::InstanceKind::Virtual(..)
|
||||
| ty::InstanceKind::Intrinsic(..)
|
||||
| ty::InstanceKind::Item(..)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ pub(super) fn mangle<'tcx>(
|
|||
printer
|
||||
.print_def_path(
|
||||
def_id,
|
||||
if let ty::InstanceDef::DropGlue(_, _) | ty::InstanceDef::AsyncDropGlueCtorShim(_, _) =
|
||||
instance.def
|
||||
if let ty::InstanceKind::DropGlue(_, _)
|
||||
| ty::InstanceKind::AsyncDropGlueCtorShim(_, _) = instance.def
|
||||
{
|
||||
// Add the name of the dropped type to the symbol name
|
||||
&*instance.args
|
||||
|
|
@ -68,13 +68,13 @@ pub(super) fn mangle<'tcx>(
|
|||
.unwrap();
|
||||
|
||||
match instance.def {
|
||||
ty::InstanceDef::ThreadLocalShim(..) => {
|
||||
ty::InstanceKind::ThreadLocalShim(..) => {
|
||||
printer.write_str("{{tls-shim}}").unwrap();
|
||||
}
|
||||
ty::InstanceDef::VTableShim(..) => {
|
||||
ty::InstanceKind::VTableShim(..) => {
|
||||
printer.write_str("{{vtable-shim}}").unwrap();
|
||||
}
|
||||
ty::InstanceDef::ReifyShim(_, reason) => {
|
||||
ty::InstanceKind::ReifyShim(_, reason) => {
|
||||
printer.write_str("{{reify-shim").unwrap();
|
||||
match reason {
|
||||
Some(ReifyReason::FnPtr) => printer.write_str("-fnptr").unwrap(),
|
||||
|
|
@ -85,8 +85,8 @@ pub(super) fn mangle<'tcx>(
|
|||
}
|
||||
// FIXME(async_closures): This shouldn't be needed when we fix
|
||||
// `Instance::ty`/`Instance::def_id`.
|
||||
ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineKindShim { .. } => {
|
||||
ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceKind::CoroutineKindShim { .. } => {
|
||||
printer.write_str("{{fn-once-shim}}").unwrap();
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -43,14 +43,14 @@ pub(super) fn mangle<'tcx>(
|
|||
|
||||
// Append `::{shim:...#0}` to shims that can coexist with a non-shim instance.
|
||||
let shim_kind = match instance.def {
|
||||
ty::InstanceDef::ThreadLocalShim(_) => Some("tls"),
|
||||
ty::InstanceDef::VTableShim(_) => Some("vtable"),
|
||||
ty::InstanceDef::ReifyShim(_, None) => Some("reify"),
|
||||
ty::InstanceDef::ReifyShim(_, Some(ReifyReason::FnPtr)) => Some("reify_fnptr"),
|
||||
ty::InstanceDef::ReifyShim(_, Some(ReifyReason::Vtable)) => Some("reify_vtable"),
|
||||
ty::InstanceKind::ThreadLocalShim(_) => Some("tls"),
|
||||
ty::InstanceKind::VTableShim(_) => Some("vtable"),
|
||||
ty::InstanceKind::ReifyShim(_, None) => Some("reify"),
|
||||
ty::InstanceKind::ReifyShim(_, Some(ReifyReason::FnPtr)) => Some("reify_fnptr"),
|
||||
ty::InstanceKind::ReifyShim(_, Some(ReifyReason::Vtable)) => Some("reify_vtable"),
|
||||
|
||||
ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineKindShim { .. } => Some("fn_once"),
|
||||
ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceKind::CoroutineKindShim { .. } => Some("fn_once"),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -135,8 +135,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
|||
// Remove any trivial region constraints once we've resolved regions
|
||||
external_constraints
|
||||
.region_constraints
|
||||
.outlives
|
||||
.retain(|(outlives, _)| outlives.0.as_region().map_or(true, |re| re != outlives.1));
|
||||
.retain(|outlives| outlives.0.as_region().map_or(true, |re| re != outlives.1));
|
||||
|
||||
let canonical = Canonicalizer::canonicalize(
|
||||
self.infcx,
|
||||
|
|
@ -179,8 +178,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
|||
fn compute_external_query_constraints(
|
||||
&self,
|
||||
certainty: Certainty,
|
||||
normalization_nested_goals: NestedNormalizationGoals<'tcx>,
|
||||
) -> ExternalConstraintsData<'tcx> {
|
||||
normalization_nested_goals: NestedNormalizationGoals<TyCtxt<'tcx>>,
|
||||
) -> ExternalConstraintsData<TyCtxt<'tcx>> {
|
||||
// We only return region constraints once the certainty is `Yes`. This
|
||||
// is necessary as we may drop nested goals on ambiguity, which may result
|
||||
// in unconstrained inference variables in the region constraints. It also
|
||||
|
|
@ -193,30 +192,40 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
|||
// Cannot use `take_registered_region_obligations` as we may compute the response
|
||||
// inside of a `probe` whenever we have multiple choices inside of the solver.
|
||||
let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
|
||||
let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| {
|
||||
make_query_region_constraints(
|
||||
self.interner(),
|
||||
region_obligations.iter().map(|r_o| {
|
||||
(r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())
|
||||
}),
|
||||
region_constraints,
|
||||
)
|
||||
});
|
||||
|
||||
let QueryRegionConstraints { outlives, member_constraints } =
|
||||
self.infcx.with_region_constraints(|region_constraints| {
|
||||
make_query_region_constraints(
|
||||
self.interner(),
|
||||
region_obligations.iter().map(|r_o| {
|
||||
(r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())
|
||||
}),
|
||||
region_constraints,
|
||||
)
|
||||
});
|
||||
assert_eq!(member_constraints, vec![]);
|
||||
let mut seen = FxHashSet::default();
|
||||
region_constraints.outlives.retain(|outlives| seen.insert(*outlives));
|
||||
region_constraints
|
||||
outlives
|
||||
.into_iter()
|
||||
.filter(|(outlives, _)| seen.insert(*outlives))
|
||||
.map(|(outlives, _origin)| outlives)
|
||||
.collect()
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
|
||||
// Only return opaque type keys for newly-defined opaques
|
||||
opaque_types.retain(|(a, _)| {
|
||||
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
|
||||
});
|
||||
|
||||
ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
|
||||
ExternalConstraintsData {
|
||||
region_constraints,
|
||||
opaque_types: self
|
||||
.infcx
|
||||
.clone_opaque_types_for_query_response()
|
||||
.into_iter()
|
||||
// Only return *newly defined* opaque types.
|
||||
.filter(|(a, _)| {
|
||||
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
|
||||
})
|
||||
.collect(),
|
||||
normalization_nested_goals,
|
||||
}
|
||||
}
|
||||
|
||||
/// After calling a canonical query, we apply the constraints returned
|
||||
|
|
@ -232,7 +241,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
original_values: Vec<ty::GenericArg<'tcx>>,
|
||||
response: CanonicalResponse<'tcx>,
|
||||
) -> (NestedNormalizationGoals<'tcx>, Certainty) {
|
||||
) -> (NestedNormalizationGoals<TyCtxt<'tcx>>, Certainty) {
|
||||
let instantiation = Self::compute_query_response_instantiation_values(
|
||||
self.infcx,
|
||||
&original_values,
|
||||
|
|
@ -369,16 +378,17 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
|||
}
|
||||
}
|
||||
|
||||
fn register_region_constraints(&mut self, region_constraints: &QueryRegionConstraints<'tcx>) {
|
||||
for &(ty::OutlivesPredicate(lhs, rhs), _) in ®ion_constraints.outlives {
|
||||
fn register_region_constraints(
|
||||
&mut self,
|
||||
outlives: &[ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>],
|
||||
) {
|
||||
for &ty::OutlivesPredicate(lhs, rhs) in outlives {
|
||||
match lhs.unpack() {
|
||||
GenericArgKind::Lifetime(lhs) => self.register_region_outlives(lhs, rhs),
|
||||
GenericArgKind::Type(lhs) => self.register_ty_outlives(lhs, rhs),
|
||||
GenericArgKind::Const(_) => bug!("const outlives: {lhs:?}: {rhs:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
assert!(region_constraints.member_constraints.is_empty());
|
||||
}
|
||||
|
||||
fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)]) {
|
||||
|
|
|
|||
|
|
@ -29,11 +29,9 @@ use super::inspect::ProofTreeBuilder;
|
|||
use super::{search_graph, GoalEvaluationKind, FIXPOINT_STEP_LIMIT};
|
||||
use super::{search_graph::SearchGraph, Goal};
|
||||
use super::{GoalSource, SolverMode};
|
||||
pub use select::InferCtxtSelectExt;
|
||||
|
||||
pub(super) mod canonical;
|
||||
mod probe;
|
||||
mod select;
|
||||
|
||||
pub struct EvalCtxt<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
|
||||
where
|
||||
|
|
@ -339,7 +337,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
|||
goal_evaluation_kind: GoalEvaluationKind,
|
||||
_source: GoalSource,
|
||||
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
||||
) -> Result<(NestedNormalizationGoals<'tcx>, bool, Certainty), NoSolution> {
|
||||
) -> Result<(NestedNormalizationGoals<TyCtxt<'tcx>>, bool, Certainty), NoSolution> {
|
||||
let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
|
||||
let mut goal_evaluation =
|
||||
self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
|
||||
|
|
@ -382,7 +380,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
original_values: Vec<ty::GenericArg<'tcx>>,
|
||||
response: CanonicalResponse<'tcx>,
|
||||
) -> (NestedNormalizationGoals<'tcx>, Certainty, bool) {
|
||||
) -> (NestedNormalizationGoals<TyCtxt<'tcx>>, Certainty, bool) {
|
||||
if let Certainty::Maybe(MaybeCause::Overflow { .. }) = response.value.certainty {
|
||||
return (NestedNormalizationGoals::empty(), response.value.certainty, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,12 +37,14 @@ mod normalize;
|
|||
mod normalizes_to;
|
||||
mod project_goals;
|
||||
mod search_graph;
|
||||
mod select;
|
||||
mod trait_goals;
|
||||
|
||||
pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
|
||||
pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt};
|
||||
pub use fulfill::{FulfillmentCtxt, NextSolverError};
|
||||
pub(crate) use normalize::deeply_normalize_for_diagnostics;
|
||||
pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
|
||||
pub use select::InferCtxtSelectExt;
|
||||
|
||||
/// How many fixpoint iterations we should attempt inside of the solver before bailing
|
||||
/// with overflow.
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ use rustc_infer::traits::query::NoSolution;
|
|||
use rustc_infer::traits::solve::inspect::ProbeKind;
|
||||
use rustc_infer::traits::solve::MaybeCause;
|
||||
use rustc_infer::traits::Reveal;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult};
|
||||
use rustc_middle::traits::BuiltinImplSource;
|
||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
||||
use rustc_middle::ty::NormalizesTo;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{TypeVisitableExt, Upcast};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
|
||||
|
||||
mod anon_const;
|
||||
|
|
@ -200,14 +200,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
|||
|
||||
let error_response = |ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, reason| {
|
||||
let guar = tcx.dcx().span_delayed_bug(tcx.def_span(assoc_def.item.def_id), reason);
|
||||
let error_term = match assoc_def.item.kind {
|
||||
ty::AssocKind::Const => ty::Const::new_error(tcx, guar).into(),
|
||||
ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
|
||||
// This makes no sense...
|
||||
ty::AssocKind::Fn => span_bug!(
|
||||
tcx.def_span(assoc_def.item.def_id),
|
||||
"cannot project to an associated function"
|
||||
),
|
||||
let error_term = match goal.predicate.alias.kind(tcx) {
|
||||
ty::AliasTermKind::ProjectionTy => Ty::new_error(tcx, guar).into(),
|
||||
ty::AliasTermKind::ProjectionConst => ty::Const::new_error(tcx, guar).into(),
|
||||
kind => bug!("expected projection, found {kind:?}"),
|
||||
};
|
||||
ecx.instantiate_normalizes_to_term(goal, error_term);
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
|
|
@ -238,9 +234,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
|||
}
|
||||
|
||||
// Finally we construct the actual value of the associated type.
|
||||
let term = match assoc_def.item.kind {
|
||||
ty::AssocKind::Type => tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()),
|
||||
ty::AssocKind::Const => {
|
||||
let term = match goal.predicate.alias.kind(tcx) {
|
||||
ty::AliasTermKind::ProjectionTy => {
|
||||
tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into())
|
||||
}
|
||||
ty::AliasTermKind::ProjectionConst => {
|
||||
if tcx.features().associated_const_equality {
|
||||
bug!("associated const projection is not supported yet")
|
||||
} else {
|
||||
|
|
@ -254,7 +252,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
|||
)
|
||||
}
|
||||
}
|
||||
ty::AssocKind::Fn => unreachable!("we should never project to a fn"),
|
||||
kind => bug!("expected projection, found {kind:?}"),
|
||||
};
|
||||
|
||||
ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, associated_item_args));
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_middle::query::Providers;
|
|||
use rustc_middle::ty::layout::{
|
||||
fn_can_unwind, FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout,
|
||||
};
|
||||
use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt};
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_target::abi::call::{
|
||||
|
|
@ -33,7 +33,7 @@ fn fn_sig_for_fn_abi<'tcx>(
|
|||
instance: ty::Instance<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> ty::PolyFnSig<'tcx> {
|
||||
if let InstanceDef::ThreadLocalShim(..) = instance.def {
|
||||
if let InstanceKind::ThreadLocalShim(..) = instance.def {
|
||||
return ty::Binder::dummy(tcx.mk_fn_sig(
|
||||
[],
|
||||
tcx.thread_local_ptr_ty(instance.def_id()),
|
||||
|
|
@ -63,7 +63,7 @@ fn fn_sig_for_fn_abi<'tcx>(
|
|||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if let ty::InstanceDef::VTableShim(..) = instance.def {
|
||||
if let ty::InstanceKind::VTableShim(..) = instance.def {
|
||||
// Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
|
||||
sig = sig.map_bound(|mut sig| {
|
||||
let mut inputs_and_output = sig.inputs_and_output.to_vec();
|
||||
|
|
@ -121,7 +121,7 @@ fn fn_sig_for_fn_abi<'tcx>(
|
|||
let mut coroutine_kind = args.as_coroutine_closure().kind();
|
||||
|
||||
let env_ty =
|
||||
if let InstanceDef::ConstructCoroutineInClosureShim { receiver_by_ref, .. } =
|
||||
if let InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref, .. } =
|
||||
instance.def
|
||||
{
|
||||
coroutine_kind = ty::ClosureKind::FnOnce;
|
||||
|
|
@ -174,7 +174,7 @@ fn fn_sig_for_fn_abi<'tcx>(
|
|||
// make sure we respect the `target_kind` in that shim.
|
||||
// FIXME(async_closures): This shouldn't be needed, and we should be populating
|
||||
// a separate def-id for these bodies.
|
||||
if let InstanceDef::CoroutineKindShim { .. } = instance.def {
|
||||
if let InstanceKind::CoroutineKindShim { .. } = instance.def {
|
||||
// Grab the parent coroutine-closure. It has the same args for the purposes
|
||||
// of instantiation, so this will be okay to do.
|
||||
let ty::CoroutineClosure(_, coroutine_closure_args) = *tcx
|
||||
|
|
@ -386,7 +386,7 @@ fn fn_abi_of_instance<'tcx>(
|
|||
extra_args,
|
||||
caller_location,
|
||||
Some(instance.def_id()),
|
||||
matches!(instance.def, ty::InstanceDef::Virtual(..)),
|
||||
matches!(instance.def, ty::InstanceKind::Virtual(..)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ fn resolve_instance<'tcx>(
|
|||
} else {
|
||||
let def = if tcx.intrinsic(def_id).is_some() {
|
||||
debug!(" => intrinsic");
|
||||
ty::InstanceDef::Intrinsic(def_id)
|
||||
ty::InstanceKind::Intrinsic(def_id)
|
||||
} else if tcx.is_lang_item(def_id, LangItem::DropInPlace) {
|
||||
let ty = args.type_at(0);
|
||||
|
||||
|
|
@ -53,10 +53,10 @@ fn resolve_instance<'tcx>(
|
|||
_ => return Ok(None),
|
||||
}
|
||||
|
||||
ty::InstanceDef::DropGlue(def_id, Some(ty))
|
||||
ty::InstanceKind::DropGlue(def_id, Some(ty))
|
||||
} else {
|
||||
debug!(" => trivial drop glue");
|
||||
ty::InstanceDef::DropGlue(def_id, None)
|
||||
ty::InstanceKind::DropGlue(def_id, None)
|
||||
}
|
||||
} else if tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace) {
|
||||
let ty = args.type_at(0);
|
||||
|
|
@ -75,15 +75,15 @@ fn resolve_instance<'tcx>(
|
|||
_ => return Ok(None),
|
||||
}
|
||||
debug!(" => nontrivial async drop glue ctor");
|
||||
ty::InstanceDef::AsyncDropGlueCtorShim(def_id, Some(ty))
|
||||
ty::InstanceKind::AsyncDropGlueCtorShim(def_id, Some(ty))
|
||||
} else {
|
||||
debug!(" => trivial async drop glue ctor");
|
||||
ty::InstanceDef::AsyncDropGlueCtorShim(def_id, None)
|
||||
ty::InstanceKind::AsyncDropGlueCtorShim(def_id, None)
|
||||
}
|
||||
} else {
|
||||
debug!(" => free item");
|
||||
// FIXME(effects): we may want to erase the effect param if that is present on this item.
|
||||
ty::InstanceDef::Item(def_id)
|
||||
ty::InstanceKind::Item(def_id)
|
||||
};
|
||||
|
||||
Ok(Some(Instance { def, args }))
|
||||
|
|
@ -226,7 +226,7 @@ fn resolve_associated_item<'tcx>(
|
|||
.copied()
|
||||
.position(|def_id| def_id == trait_item_id);
|
||||
offset.map(|offset| Instance {
|
||||
def: ty::InstanceDef::Virtual(trait_item_id, vtable_base + offset),
|
||||
def: ty::InstanceKind::Virtual(trait_item_id, vtable_base + offset),
|
||||
args: rcvr_args,
|
||||
})
|
||||
}
|
||||
|
|
@ -248,7 +248,7 @@ fn resolve_associated_item<'tcx>(
|
|||
};
|
||||
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::CloneShim(trait_item_id, self_ty),
|
||||
def: ty::InstanceKind::CloneShim(trait_item_id, self_ty),
|
||||
args: rcvr_args,
|
||||
})
|
||||
} else {
|
||||
|
|
@ -265,7 +265,7 @@ fn resolve_associated_item<'tcx>(
|
|||
return Ok(None);
|
||||
}
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::FnPtrAddrShim(trait_item_id, self_ty),
|
||||
def: ty::InstanceKind::FnPtrAddrShim(trait_item_id, self_ty),
|
||||
args: rcvr_args,
|
||||
})
|
||||
} else {
|
||||
|
|
@ -283,7 +283,7 @@ fn resolve_associated_item<'tcx>(
|
|||
{
|
||||
// For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`,
|
||||
// you either need to generate a shim body, or perhaps return
|
||||
// `InstanceDef::Item` pointing to a trait default method body if
|
||||
// `InstanceKind::Item` pointing to a trait default method body if
|
||||
// it is given a default implementation by the trait.
|
||||
bug!(
|
||||
"no definition for `{trait_ref}::{}` for built-in callable type",
|
||||
|
|
@ -295,7 +295,7 @@ fn resolve_associated_item<'tcx>(
|
|||
Some(Instance::resolve_closure(tcx, closure_def_id, args, target_kind))
|
||||
}
|
||||
ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
|
||||
def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_args.type_at(0)),
|
||||
def: ty::InstanceKind::FnPtrShim(trait_item_id, rcvr_args.type_at(0)),
|
||||
args: rcvr_args,
|
||||
}),
|
||||
ty::CoroutineClosure(coroutine_closure_def_id, args) => {
|
||||
|
|
@ -308,7 +308,7 @@ fn resolve_associated_item<'tcx>(
|
|||
Some(Instance::new(coroutine_closure_def_id, args))
|
||||
} else {
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::ConstructCoroutineInClosureShim {
|
||||
def: ty::InstanceKind::ConstructCoroutineInClosureShim {
|
||||
coroutine_closure_def_id,
|
||||
receiver_by_ref: target_kind != ty::ClosureKind::FnOnce,
|
||||
},
|
||||
|
|
@ -331,7 +331,7 @@ fn resolve_associated_item<'tcx>(
|
|||
// If we're computing `AsyncFnOnce` for a by-ref closure then
|
||||
// construct a new body that has the right return types.
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::ConstructCoroutineInClosureShim {
|
||||
def: ty::InstanceKind::ConstructCoroutineInClosureShim {
|
||||
coroutine_closure_def_id,
|
||||
receiver_by_ref: false,
|
||||
},
|
||||
|
|
@ -345,7 +345,7 @@ fn resolve_associated_item<'tcx>(
|
|||
Some(Instance::resolve_closure(tcx, closure_def_id, args, target_kind))
|
||||
}
|
||||
ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
|
||||
def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_args.type_at(0)),
|
||||
def: ty::InstanceKind::FnPtrShim(trait_item_id, rcvr_args.type_at(0)),
|
||||
args: rcvr_args,
|
||||
}),
|
||||
_ => bug!(
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ pub trait Interner:
|
|||
+ IrPrint<ty::FnSig<Self>>
|
||||
{
|
||||
type DefId: Copy + Debug + Hash + Eq + TypeFoldable<Self>;
|
||||
type LocalDefId: Copy + Debug + Hash + Eq + Into<Self::DefId> + TypeFoldable<Self>;
|
||||
type AdtDef: AdtDef<Self>;
|
||||
|
||||
type GenericArgs: GenericArgs<Self>;
|
||||
|
|
@ -103,7 +104,11 @@ pub trait Interner:
|
|||
type GenericsOf: GenericsOf<Self>;
|
||||
fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
|
||||
|
||||
type VariancesOf: Copy + Debug + Deref<Target = [ty::Variance]>;
|
||||
type VariancesOf: Copy
|
||||
+ Debug
|
||||
+ Deref<Target = [ty::Variance]>
|
||||
// FIXME: This is terrible!
|
||||
+ IntoIterator<Item: Deref<Target = ty::Variance>>;
|
||||
fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf;
|
||||
|
||||
// FIXME: Remove after uplifting `EarlyBinder`
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ mod flags;
|
|||
mod generic_arg;
|
||||
mod infcx;
|
||||
mod interner;
|
||||
mod opaque_ty;
|
||||
mod predicate;
|
||||
mod predicate_kind;
|
||||
mod region_kind;
|
||||
|
|
@ -63,6 +64,7 @@ pub use flags::*;
|
|||
pub use generic_arg::*;
|
||||
pub use infcx::InferCtxtLike;
|
||||
pub use interner::*;
|
||||
pub use opaque_ty::*;
|
||||
pub use predicate::*;
|
||||
pub use predicate_kind::*;
|
||||
pub use region_kind::*;
|
||||
|
|
|
|||
51
compiler/rustc_type_ir/src/opaque_ty.rs
Normal file
51
compiler/rustc_type_ir/src/opaque_ty.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
|
||||
use crate::inherent::*;
|
||||
use crate::{self as ty, Interner};
|
||||
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = ""),
|
||||
Debug(bound = ""),
|
||||
Copy(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub struct OpaqueTypeKey<I: Interner> {
|
||||
pub def_id: I::LocalDefId,
|
||||
pub args: I::GenericArgs,
|
||||
}
|
||||
|
||||
impl<I: Interner> OpaqueTypeKey<I> {
|
||||
pub fn iter_captured_args(self, tcx: I) -> impl Iterator<Item = (usize, I::GenericArg)> {
|
||||
let variances = tcx.variances_of(self.def_id.into());
|
||||
std::iter::zip(self.args, variances.into_iter()).enumerate().filter_map(|(i, (arg, v))| {
|
||||
match (arg.kind(), *v) {
|
||||
(_, ty::Invariant) => Some((i, arg)),
|
||||
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => None,
|
||||
_ => panic!("unexpected opaque type arg variance"),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fold_captured_lifetime_args(
|
||||
self,
|
||||
tcx: I,
|
||||
mut f: impl FnMut(I::Region) -> I::Region,
|
||||
) -> Self {
|
||||
let Self { def_id, args } = self;
|
||||
let variances = tcx.variances_of(def_id.into());
|
||||
let args =
|
||||
std::iter::zip(args, variances.into_iter()).map(|(arg, v)| match (arg.kind(), *v) {
|
||||
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
|
||||
(ty::GenericArgKind::Lifetime(lt), _) => f(lt).into(),
|
||||
_ => arg,
|
||||
});
|
||||
let args = tcx.mk_args_from_iter(args);
|
||||
Self { def_id, args }
|
||||
}
|
||||
}
|
||||
|
|
@ -154,7 +154,7 @@ pub enum RegionKind<I: Interner> {
|
|||
/// parameters via `tcx.liberate_late_bound_regions`. They are then treated
|
||||
/// the same way as `ReEarlyParam` while inside of the function.
|
||||
///
|
||||
/// See <https://rustc-dev-guide.rust-lang.org/early-late-bound-summary.html> for
|
||||
/// See <https://rustc-dev-guide.rust-lang.org/early-late-bound-params/early-late-bound-summary.html> for
|
||||
/// more info about early and late bound lifetime parameters.
|
||||
ReLateParam(I::LateParamRegion),
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,55 @@ use std::hash::Hash;
|
|||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
|
||||
use crate::{Canonical, CanonicalVarValues, Interner, Upcast};
|
||||
use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast};
|
||||
|
||||
/// Depending on the stage of compilation, we want projection to be
|
||||
/// more or less conservative.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub enum Reveal {
|
||||
/// At type-checking time, we refuse to project any associated
|
||||
/// type that is marked `default`. Non-`default` ("final") types
|
||||
/// are always projected. This is necessary in general for
|
||||
/// soundness of specialization. However, we *could* allow
|
||||
/// projections in fully-monomorphic cases. We choose not to,
|
||||
/// because we prefer for `default type` to force the type
|
||||
/// definition to be treated abstractly by any consumers of the
|
||||
/// impl. Concretely, that means that the following example will
|
||||
/// fail to compile:
|
||||
///
|
||||
/// ```compile_fail,E0308
|
||||
/// #![feature(specialization)]
|
||||
/// trait Assoc {
|
||||
/// type Output;
|
||||
/// }
|
||||
///
|
||||
/// impl<T> Assoc for T {
|
||||
/// default type Output = bool;
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let x: <() as Assoc>::Output = true;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// We also do not reveal the hidden type of opaque types during
|
||||
/// type-checking.
|
||||
UserFacing,
|
||||
|
||||
/// At codegen time, all monomorphic projections will succeed.
|
||||
/// Also, `impl Trait` is normalized to the concrete type,
|
||||
/// which has to be already collected by type-checking.
|
||||
///
|
||||
/// NOTE: as `impl Trait`'s concrete type should *never*
|
||||
/// be observable directly by the user, `Reveal::All`
|
||||
/// should not be used by checks which may expose
|
||||
/// type equality or type contents to the user.
|
||||
/// There are some exceptions, e.g., around auto traits and
|
||||
/// transmute-checking, which expose some details, but
|
||||
/// not the whole concrete type of the `impl Trait`.
|
||||
All,
|
||||
}
|
||||
|
||||
pub type CanonicalInput<I, T = <I as Interner>::Predicate> = Canonical<I, QueryInput<I, T>>;
|
||||
pub type CanonicalResponse<I> = Canonical<I, Response<I>>;
|
||||
|
|
@ -206,6 +254,47 @@ pub struct Response<I: Interner> {
|
|||
pub external_constraints: I::ExternalConstraints,
|
||||
}
|
||||
|
||||
/// Additional constraints returned on success.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = ""),
|
||||
Debug(bound = ""),
|
||||
Default(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub struct ExternalConstraintsData<I: Interner> {
|
||||
pub region_constraints: Vec<ty::OutlivesPredicate<I, I::GenericArg>>,
|
||||
pub opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>,
|
||||
pub normalization_nested_goals: NestedNormalizationGoals<I>,
|
||||
}
|
||||
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = ""),
|
||||
Debug(bound = ""),
|
||||
Default(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub struct NestedNormalizationGoals<I: Interner>(pub Vec<(GoalSource, Goal<I, I::Predicate>)>);
|
||||
|
||||
impl<I: Interner> NestedNormalizationGoals<I> {
|
||||
pub fn empty() -> Self {
|
||||
NestedNormalizationGoals(vec![])
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub enum Certainty {
|
||||
|
|
|
|||
|
|
@ -928,7 +928,7 @@ pub(crate) mod tags {
|
|||
/// An `Option` with a type tag `I`.
|
||||
///
|
||||
/// Since this struct implements `Erased`, the type can be erased to make a dynamically typed
|
||||
/// option. The type can be checked dynamically using `Erased::tag_id` and since this is statically
|
||||
/// option. The type can be checked dynamically using `Tagged::tag_id` and since this is statically
|
||||
/// checked for the concrete type, there is some degree of type safety.
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct TaggedOption<'a, I: tags::Type<'a>>(pub Option<I::Reified>);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#![unstable(feature = "async_drop", issue = "none")]
|
||||
#![unstable(feature = "async_drop", issue = "126482")]
|
||||
|
||||
use crate::fmt;
|
||||
use crate::future::{Future, IntoFuture};
|
||||
|
|
@ -10,27 +10,27 @@ use crate::task::{ready, Context, Poll};
|
|||
|
||||
/// Asynchronously drops a value by running `AsyncDrop::async_drop`
|
||||
/// on a value and its fields recursively.
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
pub fn async_drop<T>(value: T) -> AsyncDropOwning<T> {
|
||||
AsyncDropOwning { value: MaybeUninit::new(value), dtor: None, _pinned: PhantomPinned }
|
||||
}
|
||||
|
||||
/// A future returned by the [`async_drop`].
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
pub struct AsyncDropOwning<T> {
|
||||
value: MaybeUninit<T>,
|
||||
dtor: Option<AsyncDropInPlace<T>>,
|
||||
_pinned: PhantomPinned,
|
||||
}
|
||||
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
impl<T> fmt::Debug for AsyncDropOwning<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("AsyncDropOwning").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
impl<T> Future for AsyncDropOwning<T> {
|
||||
type Output = ();
|
||||
|
||||
|
|
@ -86,24 +86,24 @@ unsafe fn async_drop_in_place_raw<T: ?Sized>(
|
|||
/// returned future stores the `to_drop` pointer and user is required
|
||||
/// to guarantee that dropped value doesn't move.
|
||||
///
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
pub unsafe fn async_drop_in_place<T: ?Sized>(to_drop: *mut T) -> AsyncDropInPlace<T> {
|
||||
// SAFETY: `async_drop_in_place_raw` has the same safety requirements
|
||||
unsafe { AsyncDropInPlace(async_drop_in_place_raw(to_drop)) }
|
||||
}
|
||||
|
||||
/// A future returned by the [`async_drop_in_place`].
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
pub struct AsyncDropInPlace<T: ?Sized>(<T as AsyncDestruct>::AsyncDestructor);
|
||||
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
impl<T: ?Sized> fmt::Debug for AsyncDropInPlace<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("AsyncDropInPlace").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
impl<T: ?Sized> Future for AsyncDropInPlace<T> {
|
||||
type Output = ();
|
||||
|
||||
|
|
@ -117,18 +117,18 @@ impl<T: ?Sized> Future for AsyncDropInPlace<T> {
|
|||
// FIXME(zetanumbers): Add same restrictions on AsyncDrop impls as
|
||||
// with Drop impls
|
||||
/// Custom code within the asynchronous destructor.
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
#[lang = "async_drop"]
|
||||
pub trait AsyncDrop {
|
||||
/// A future returned by the [`AsyncDrop::async_drop`] to be part
|
||||
/// of the async destructor.
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
type Dropper<'a>: Future<Output = ()>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
/// Constructs the asynchronous destructor for this type.
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ pub use ready::{ready, Ready};
|
|||
#[stable(feature = "future_poll_fn", since = "1.64.0")]
|
||||
pub use poll_fn::{poll_fn, PollFn};
|
||||
|
||||
#[unstable(feature = "async_drop", issue = "none")]
|
||||
#[unstable(feature = "async_drop", issue = "126482")]
|
||||
pub use async_drop::{async_drop, async_drop_in_place, AsyncDrop, AsyncDropInPlace};
|
||||
|
||||
/// This type is needed because:
|
||||
|
|
|
|||
|
|
@ -2784,8 +2784,10 @@ macro_rules! int_impl {
|
|||
///
|
||||
/// In other words, the result is `self / rhs` rounded to the integer `q`
|
||||
/// such that `self >= q * rhs`.
|
||||
/// If `self > 0`, this is equal to round towards zero (the default in Rust);
|
||||
/// if `self < 0`, this is equal to round towards +/- infinity.
|
||||
/// If `self > 0`, this is equal to rounding towards zero (the default in Rust);
|
||||
/// if `self < 0`, this is equal to rounding away from zero (towards +/- infinity).
|
||||
/// If `rhs > 0`, this is equal to rounding towards -infinity;
|
||||
/// if `rhs < 0`, this is equal to rounding towards +infinity.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
|
|
@ -2823,8 +2825,8 @@ macro_rules! int_impl {
|
|||
/// Calculates the least nonnegative remainder of `self (mod rhs)`.
|
||||
///
|
||||
/// This is done as if by the Euclidean division algorithm -- given
|
||||
/// `r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and
|
||||
/// `0 <= r < abs(rhs)`.
|
||||
/// `r = self.rem_euclid(rhs)`, the result satisfies
|
||||
/// `self = rhs * self.div_euclid(rhs) + r` and `0 <= r < abs(rhs)`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@
|
|||
//! pointer. For code which *does* cast a usize to a pointer, the scope of the change depends
|
||||
//! on exactly what you're doing.
|
||||
//!
|
||||
//! In general you just need to make sure that if you want to convert a usize address to a
|
||||
//! In general, you just need to make sure that if you want to convert a usize address to a
|
||||
//! pointer and then use that pointer to read/write memory, you need to keep around a pointer
|
||||
//! that has sufficient provenance to perform that read/write itself. In this way all of your
|
||||
//! casts from an address to a pointer are essentially just applying offsets/indexing.
|
||||
|
|
@ -309,7 +309,7 @@
|
|||
//! i.e. the usual "ZSTs are fake, do what you want" rules apply *but* this only applies
|
||||
//! for actual forgery (integers cast to pointers). If you borrow some struct's field
|
||||
//! that *happens* to be zero-sized, the resulting pointer will have provenance tied to
|
||||
//! that allocation and it will still get invalidated if the allocation gets deallocated.
|
||||
//! that allocation, and it will still get invalidated if the allocation gets deallocated.
|
||||
//! In the future we may introduce an API to make such a forged allocation explicit.
|
||||
//!
|
||||
//! * [`wrapping_offset`][] a pointer outside its provenance. This includes pointers
|
||||
|
|
@ -698,7 +698,7 @@ pub const fn dangling_mut<T>() -> *mut T {
|
|||
///
|
||||
/// If there is no 'exposed' provenance that justifies the way this pointer will be used,
|
||||
/// the program has undefined behavior. In particular, the aliasing rules still apply: pointers
|
||||
/// and references that have been invalidated due to aliasing accesses cannot be used any more,
|
||||
/// and references that have been invalidated due to aliasing accesses cannot be used anymore,
|
||||
/// even if they have been exposed!
|
||||
///
|
||||
/// Note that there is no algorithm that decides which provenance will be used. You can think of this
|
||||
|
|
@ -1097,7 +1097,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, coun
|
|||
// If we end up here, it's because we're using a simple type -- like
|
||||
// a small power-of-two-sized thing -- or a special type with particularly
|
||||
// large alignment, particularly SIMD types.
|
||||
// Thus we're fine just reading-and-writing it, as either it's small
|
||||
// Thus, we're fine just reading-and-writing it, as either it's small
|
||||
// and that works well anyway or it's special and the type's author
|
||||
// presumably wanted things to be done in the larger chunk.
|
||||
|
||||
|
|
@ -1290,7 +1290,7 @@ pub const unsafe fn read<T>(src: *const T) -> T {
|
|||
// provides enough information to know that this is a typed operation.
|
||||
|
||||
// However, as of March 2023 the compiler was not capable of taking advantage
|
||||
// of that information. Thus the implementation here switched to an intrinsic,
|
||||
// of that information. Thus, the implementation here switched to an intrinsic,
|
||||
// which lowers to `_0 = *src` in MIR, to address a few issues:
|
||||
//
|
||||
// - Using `MaybeUninit::assume_init` after a `copy_nonoverlapping` was not
|
||||
|
|
@ -1570,7 +1570,7 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
|
|||
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
|
||||
/// *undefined behavior* in your program.
|
||||
///
|
||||
/// Instead you must use the [`ptr::addr_of_mut!`](addr_of_mut)
|
||||
/// Instead, you must use the [`ptr::addr_of_mut!`](addr_of_mut)
|
||||
/// macro to create the pointer. You may use that returned pointer together with
|
||||
/// this function.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,13 +1,4 @@
|
|||
#![stable(feature = "os_fd", since = "1.66.0")]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
mod net;
|
||||
#[path = "../../fd/owned.rs"]
|
||||
mod owned;
|
||||
#[path = "../../fd/raw.rs"]
|
||||
mod raw;
|
||||
|
||||
// Export the types and traits for the public API.
|
||||
#[stable(feature = "os_fd", since = "1.66.0")]
|
||||
pub use owned::*;
|
||||
#[stable(feature = "os_fd", since = "1.66.0")]
|
||||
pub use raw::*;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use crate::os::fd::*;
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ pub(crate) mod watchos;
|
|||
#[cfg(target_os = "xous")]
|
||||
pub mod xous;
|
||||
|
||||
#[cfg(any(unix, target_os = "wasi", doc))]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi", doc))]
|
||||
pub mod fd;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android", doc))]
|
||||
|
|
|
|||
|
|
@ -520,10 +520,12 @@ impl Build {
|
|||
return;
|
||||
}
|
||||
|
||||
// check_submodule
|
||||
let checked_out_hash =
|
||||
output(helpers::git(Some(&absolute_path)).args(["rev-parse", "HEAD"]));
|
||||
// update_submodules
|
||||
let submodule_git = || helpers::git(Some(&absolute_path));
|
||||
|
||||
// Determine commit checked out in submodule.
|
||||
let checked_out_hash = output(submodule_git().args(["rev-parse", "HEAD"]));
|
||||
let checked_out_hash = checked_out_hash.trim_end();
|
||||
// Determine commit that the submodule *should* have.
|
||||
let recorded =
|
||||
output(helpers::git(Some(&self.src)).args(["ls-tree", "HEAD"]).arg(relative_path));
|
||||
let actual_hash = recorded
|
||||
|
|
@ -531,8 +533,7 @@ impl Build {
|
|||
.nth(2)
|
||||
.unwrap_or_else(|| panic!("unexpected output `{}`", recorded));
|
||||
|
||||
// update_submodule
|
||||
if actual_hash == checked_out_hash.trim_end() {
|
||||
if actual_hash == checked_out_hash {
|
||||
// already checked out
|
||||
return;
|
||||
}
|
||||
|
|
@ -581,26 +582,22 @@ impl Build {
|
|||
// Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error).
|
||||
// diff-index reports the modifications through the exit status
|
||||
let has_local_modifications = !self.run_cmd(
|
||||
BootstrapCommand::from(helpers::git(Some(&absolute_path)).args([
|
||||
"diff-index",
|
||||
"--quiet",
|
||||
"HEAD",
|
||||
]))
|
||||
.allow_failure()
|
||||
.output_mode(match self.is_verbose() {
|
||||
true => OutputMode::PrintAll,
|
||||
false => OutputMode::PrintOutput,
|
||||
}),
|
||||
BootstrapCommand::from(submodule_git().args(["diff-index", "--quiet", "HEAD"]))
|
||||
.allow_failure()
|
||||
.output_mode(match self.is_verbose() {
|
||||
true => OutputMode::PrintAll,
|
||||
false => OutputMode::PrintOutput,
|
||||
}),
|
||||
);
|
||||
if has_local_modifications {
|
||||
self.run(helpers::git(Some(&absolute_path)).args(["stash", "push"]));
|
||||
self.run(submodule_git().args(["stash", "push"]));
|
||||
}
|
||||
|
||||
self.run(helpers::git(Some(&absolute_path)).args(["reset", "-q", "--hard"]));
|
||||
self.run(helpers::git(Some(&absolute_path)).args(["clean", "-qdfx"]));
|
||||
self.run(submodule_git().args(["reset", "-q", "--hard"]));
|
||||
self.run(submodule_git().args(["clean", "-qdfx"]));
|
||||
|
||||
if has_local_modifications {
|
||||
self.run(helpers::git(Some(&absolute_path)).args(["stash", "pop"]));
|
||||
self.run(submodule_git().args(["stash", "pop"]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -501,6 +501,16 @@ pub fn git(source_dir: Option<&Path>) -> Command {
|
|||
|
||||
if let Some(source_dir) = source_dir {
|
||||
git.current_dir(source_dir);
|
||||
// If we are running inside git (e.g. via a hook), `GIT_DIR` is set and takes precedence
|
||||
// over the current dir. Un-set it to make the current dir matter.
|
||||
git.env_remove("GIT_DIR");
|
||||
// Also un-set some other variables, to be on the safe side (based on cargo's
|
||||
// `fetch_with_cli`). In particular un-setting `GIT_INDEX_FILE` is required to fix some odd
|
||||
// misbehavior.
|
||||
git.env_remove("GIT_WORK_TREE")
|
||||
.env_remove("GIT_INDEX_FILE")
|
||||
.env_remove("GIT_OBJECT_DIRECTORY")
|
||||
.env_remove("GIT_ALTERNATE_OBJECT_DIRECTORIES");
|
||||
}
|
||||
|
||||
git
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5228bfac8267ad24659a81b92ec5417976b5edbc
|
||||
Subproject commit 45c1a6d69edfd1fc91fb7504cb73958dbd09441e
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit bbaabbe088e21a81a0d9ae6757705020d5d7b416
|
||||
Subproject commit cb58c430b4e8054c2cb81d2d4434092c482a93d8
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 6019b76f5b28938565b251bbba0bf5cc5c43d863
|
||||
Subproject commit 0b805c65804019b0ac8f2fe3117afad82a6069b8
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 4840dca06cadf48b305d3ce0aeafde7f80933f80
|
||||
Subproject commit b1d97bd6113aba732b2091ce093c76f2d05bb8a0
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue