1
Fork 0

refactor(rustc_middle): Substs -> GenericArg

This commit is contained in:
Mahdi Dibaiee 2023-07-11 22:35:29 +01:00
parent df5c2cf9bc
commit e55583c4b8
466 changed files with 4574 additions and 4604 deletions

View file

@ -1,7 +1,7 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
use crate::ty::{EarlyBinder, InternalSubsts, SubstsRef, TypeVisitableExt};
use crate::ty::{EarlyBinder, GenericArgs, GenericArgsRef, TypeVisitableExt};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
@ -16,13 +16,13 @@ use std::fmt;
/// A monomorphized `InstanceDef`.
///
/// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type
/// simply couples a potentially generic `InstanceDef` with some substs, and codegen and const eval
/// simply couples a potentially generic `InstanceDef` with some args, and codegen and const eval
/// will do all required substitution as they run.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, Lift, TypeFoldable, TypeVisitable)]
pub struct Instance<'tcx> {
pub def: InstanceDef<'tcx>,
pub substs: SubstsRef<'tcx>,
pub args: GenericArgsRef<'tcx>,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
@ -115,7 +115,7 @@ impl<'tcx> Instance<'tcx> {
/// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
let ty = tcx.type_of(self.def.def_id());
tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty)
tcx.subst_and_normalize_erasing_regions(self.args, param_env, ty)
}
/// Finds a crate that contains a monomorphization of this instance that
@ -139,13 +139,13 @@ impl<'tcx> Instance<'tcx> {
}
// If this a non-generic instance, it cannot be a shared monomorphization.
self.substs.non_erasable_generics().next()?;
self.args.non_erasable_generics().next()?;
match self.def {
InstanceDef::Item(def) => tcx
.upstream_monomorphizations_for(def)
.and_then(|monos| monos.get(&self.substs).cloned()),
InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.substs),
.and_then(|monos| monos.get(&self.args).cloned()),
InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args),
_ => None,
}
}
@ -265,8 +265,8 @@ impl<'tcx> InstanceDef<'tcx> {
}
/// Returns `true` when the MIR body associated with this instance should be monomorphized
/// by its users (e.g. codegen or miri) by substituting the `substs` from `Instance` (see
/// `Instance::substs_for_mir_body`).
/// by its users (e.g. codegen or miri) by substituting the `args` from `Instance` (see
/// `Instance::args_for_mir_body`).
///
/// Otherwise, returns `false` only for some kinds of shims where the construction of the MIR
/// body should perform necessary substitutions.
@ -294,10 +294,10 @@ fn fmt_instance(
type_length: rustc_session::Limit,
) -> fmt::Result {
ty::tls::with(|tcx| {
let substs = tcx.lift(instance.substs).expect("could not lift for printing");
let args = tcx.lift(instance.args).expect("could not lift for printing");
let s = FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length)
.print_def_path(instance.def_id(), substs)?
.print_def_path(instance.def_id(), args)?
.into_buffer();
f.write_str(&s)
})?;
@ -333,18 +333,18 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
}
impl<'tcx> Instance<'tcx> {
pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> Instance<'tcx> {
pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> {
assert!(
!substs.has_escaping_bound_vars(),
"substs of instance {:?} not normalized for codegen: {:?}",
!args.has_escaping_bound_vars(),
"args of instance {:?} not normalized for codegen: {:?}",
def_id,
substs
args
);
Instance { def: InstanceDef::Item(def_id), substs }
Instance { def: InstanceDef::Item(def_id), args }
}
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
let substs = InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
ty::GenericParamDefKind::Type { .. } => {
bug!("Instance::mono: {:?} has type parameters", def_id)
@ -354,7 +354,7 @@ impl<'tcx> Instance<'tcx> {
}
});
Instance::new(def_id, substs)
Instance::new(def_id, args)
}
#[inline]
@ -362,7 +362,7 @@ impl<'tcx> Instance<'tcx> {
self.def.def_id()
}
/// Resolves a `(def_id, substs)` pair to an (optional) instance -- most commonly,
/// Resolves a `(def_id, args)` pair to an (optional) instance -- most commonly,
/// this is used to find the precise code that will run for a trait method invocation,
/// if known.
///
@ -390,29 +390,29 @@ impl<'tcx> Instance<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
args: GenericArgsRef<'tcx>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
// All regions in the result of this query are erased, so it's
// fine to erase all of the input regions.
// HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)`
// HACK(eddyb) erase regions in `args` first, so that `param_env.and(...)`
// below is more likely to ignore the bounds in scope (e.g. if the only
// generic parameters mentioned by `substs` were lifetime ones).
let substs = tcx.erase_regions(substs);
tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, substs))))
// generic parameters mentioned by `args` were lifetime ones).
let args = tcx.erase_regions(args);
tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, args))))
}
pub fn expect_resolve(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
args: GenericArgsRef<'tcx>,
) -> Instance<'tcx> {
match ty::Instance::resolve(tcx, param_env, def_id, substs) {
match ty::Instance::resolve(tcx, param_env, def_id, args) {
Ok(Some(instance)) => instance,
instance => bug!(
"failed to resolve instance for {}: {instance:#?}",
tcx.def_path_str_with_substs(def_id, substs)
tcx.def_path_str_with_args(def_id, args)
),
}
}
@ -421,12 +421,12 @@ impl<'tcx> Instance<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
args: GenericArgsRef<'tcx>,
) -> Option<Instance<'tcx>> {
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
debug!("resolve(def_id={:?}, args={:?})", def_id, args);
// Use either `resolve_closure` or `resolve_for_vtable`
assert!(!tcx.is_closure(def_id), "Called `resolve_for_fn_ptr` on closure: {:?}", def_id);
Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
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) => {
debug!(" => fn pointer created for function with #[track_caller]");
@ -447,18 +447,18 @@ impl<'tcx> Instance<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
args: GenericArgsRef<'tcx>,
) -> Option<Instance<'tcx>> {
debug!("resolve_for_vtable(def_id={:?}, substs={:?})", def_id, substs);
let fn_sig = tcx.fn_sig(def_id).subst_identity();
debug!("resolve_for_vtable(def_id={:?}, args={:?})", def_id, args);
let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
&& fn_sig.input(0).skip_binder().is_param(0)
&& 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), substs })
Some(Instance { def: InstanceDef::VTableShim(def_id), args })
} else {
Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| {
match resolved.def {
InstanceDef::Item(def) => {
// We need to generate a shim when we cannot guarantee that
@ -489,12 +489,12 @@ impl<'tcx> Instance<'tcx> {
{
if tcx.is_closure(def) {
debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
def, def_id, substs);
def, def_id, args);
// 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), substs };
resolved = Instance { def: InstanceDef::ReifyShim(def_id), args };
} else {
debug!(
" => vtable fn pointer created for function with #[track_caller]: {:?}", def
@ -518,28 +518,28 @@ impl<'tcx> Instance<'tcx> {
pub fn resolve_closure(
tcx: TyCtxt<'tcx>,
def_id: DefId,
substs: ty::SubstsRef<'tcx>,
args: ty::GenericArgsRef<'tcx>,
requested_kind: ty::ClosureKind,
) -> Option<Instance<'tcx>> {
let actual_kind = substs.as_closure().kind();
let actual_kind = args.as_closure().kind();
match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs),
_ => Some(Instance::new(def_id, substs)),
Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args),
_ => Some(Instance::new(def_id, args)),
}
}
pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
let substs = tcx.mk_substs(&[ty.into()]);
Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
let args = tcx.mk_args(&[ty.into()]);
Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args)
}
#[instrument(level = "debug", skip(tcx), ret)]
pub fn fn_once_adapter_instance(
tcx: TyCtxt<'tcx>,
closure_did: DefId,
substs: ty::SubstsRef<'tcx>,
args: ty::GenericArgsRef<'tcx>,
) -> Option<Instance<'tcx>> {
let fn_once = tcx.require_lang_item(LangItem::FnOnce, None);
let call_once = tcx
@ -552,30 +552,30 @@ impl<'tcx> Instance<'tcx> {
tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER);
let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller };
let self_ty = Ty::new_closure(tcx, closure_did, substs);
let self_ty = Ty::new_closure(tcx, closure_did, args);
let sig = substs.as_closure().sig();
let sig = args.as_closure().sig();
let sig =
tcx.try_normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig).ok()?;
assert_eq!(sig.inputs().len(), 1);
let substs = tcx.mk_substs_trait(self_ty, [sig.inputs()[0].into()]);
let args = tcx.mk_args_trait(self_ty, [sig.inputs()[0].into()]);
debug!(?self_ty, ?sig);
Some(Instance { def, substs })
Some(Instance { def, args })
}
/// Depending on the kind of `InstanceDef`, 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 substitution array.
/// In the former case, we want to substitute those generic types and replace them with the
/// values from the substs when monomorphizing the function body. But in the latter case, we
/// values from the args when monomorphizing the function body. But in the latter case, we
/// don't want to do that substitution, since it has already been done effectively.
///
/// This function returns `Some(substs)` in the former case and `None` otherwise -- i.e., if
/// This function returns `Some(args)` in the former case and `None` otherwise -- i.e., if
/// this function returns `None`, then the MIR body does not require substitution during
/// codegen.
fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
self.def.has_polymorphic_mir_body().then_some(self.substs)
fn args_for_mir_body(&self) -> Option<GenericArgsRef<'tcx>> {
self.def.has_polymorphic_mir_body().then_some(self.args)
}
pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T
@ -583,10 +583,10 @@ impl<'tcx> Instance<'tcx> {
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
let v = v.map_bound(|v| *v);
if let Some(substs) = self.substs_for_mir_body() {
v.subst(tcx, substs)
if let Some(args) = self.args_for_mir_body() {
v.instantiate(tcx, args)
} else {
v.subst_identity()
v.instantiate_identity()
}
}
@ -600,8 +600,8 @@ impl<'tcx> Instance<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>> + Clone,
{
if let Some(substs) = self.substs_for_mir_body() {
tcx.subst_and_normalize_erasing_regions(substs, param_env, v)
if let Some(args) = self.args_for_mir_body() {
tcx.subst_and_normalize_erasing_regions(args, param_env, v)
} else {
tcx.normalize_erasing_regions(param_env, v.skip_binder())
}
@ -617,14 +617,14 @@ impl<'tcx> Instance<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>> + Clone,
{
if let Some(substs) = self.substs_for_mir_body() {
tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v)
if let Some(args) = self.args_for_mir_body() {
tcx.try_subst_and_normalize_erasing_regions(args, param_env, v)
} else {
tcx.try_normalize_erasing_regions(param_env, v.skip_binder())
}
}
/// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by
/// Returns a new `Instance` where generic parameters in `instance.args` are replaced by
/// identity parameters if they are determined to be unused in `instance.def`.
pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
debug!("polymorphize: running polymorphization analysis");
@ -632,18 +632,18 @@ impl<'tcx> Instance<'tcx> {
return self;
}
let polymorphized_substs = polymorphize(tcx, self.def, self.substs);
debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs);
Self { def: self.def, substs: polymorphized_substs }
let polymorphized_args = polymorphize(tcx, self.def, self.args);
debug!("polymorphize: self={:?} polymorphized_args={:?}", self, polymorphized_args);
Self { def: self.def, args: polymorphized_args }
}
}
fn polymorphize<'tcx>(
tcx: TyCtxt<'tcx>,
instance: ty::InstanceDef<'tcx>,
substs: SubstsRef<'tcx>,
) -> SubstsRef<'tcx> {
debug!("polymorphize({:?}, {:?})", instance, substs);
args: GenericArgsRef<'tcx>,
) -> GenericArgsRef<'tcx> {
debug!("polymorphize({:?}, {:?})", instance, args);
let unused = tcx.unused_generic_params(instance);
debug!("polymorphize: unused={:?}", unused);
@ -653,9 +653,9 @@ fn polymorphize<'tcx>(
// multiple mono items (and eventually symbol clashes).
let def_id = instance.def_id();
let upvars_ty = if tcx.is_closure(def_id) {
Some(substs.as_closure().tupled_upvars_ty())
Some(args.as_closure().tupled_upvars_ty())
} else if tcx.type_of(def_id).skip_binder().is_generator() {
Some(substs.as_generator().tupled_upvars_ty())
Some(args.as_generator().tupled_upvars_ty())
} else {
None
};
@ -674,22 +674,22 @@ fn polymorphize<'tcx>(
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
debug!("fold_ty: ty={:?}", ty);
match *ty.kind() {
ty::Closure(def_id, substs) => {
let polymorphized_substs =
polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
if substs == polymorphized_substs {
ty::Closure(def_id, args) => {
let polymorphized_args =
polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args);
if args == polymorphized_args {
ty
} else {
Ty::new_closure(self.tcx, def_id, polymorphized_substs)
Ty::new_closure(self.tcx, def_id, polymorphized_args)
}
}
ty::Generator(def_id, substs, movability) => {
let polymorphized_substs =
polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
if substs == polymorphized_substs {
ty::Generator(def_id, args, movability) => {
let polymorphized_args =
polymorphize(self.tcx, ty::InstanceDef::Item(def_id), args);
if args == polymorphized_args {
ty
} else {
Ty::new_generator(self.tcx, def_id, polymorphized_substs, movability)
Ty::new_generator(self.tcx, def_id, polymorphized_args, movability)
}
}
_ => ty.super_fold_with(self),
@ -697,7 +697,7 @@ fn polymorphize<'tcx>(
}
}
InternalSubsts::for_item(tcx, def_id, |param, _| {
GenericArgs::for_item(tcx, def_id, |param, _| {
let is_unused = unused.is_unused(param.index);
debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused);
match param.kind {
@ -706,7 +706,7 @@ fn polymorphize<'tcx>(
// ..and has upvars..
has_upvars &&
// ..and this param has the same type as the tupled upvars..
upvars_ty == Some(substs[param.index as usize].expect_ty()) => {
upvars_ty == Some(args[param.index as usize].expect_ty()) => {
// ..then double-check that polymorphization marked it used..
debug_assert!(!is_unused);
// ..and polymorphize any closures/generators captured as upvars.
@ -725,7 +725,7 @@ fn polymorphize<'tcx>(
tcx.mk_param_from_def(param),
// Otherwise, use the parameter as before.
_ => substs[param.index as usize],
_ => args[param.index as usize],
}
})
}