mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 10:45:18 +00:00
Rollup merge of #69036 - eddyb:monoshim, r=nikomatsakis
rustc: don't resolve Instances which would produce malformed shims. There are some `InstanceDef` variants (shims and drop "glue") which contain a `Ty`, and that `Ty` is used in generating the shim MIR. But if that `Ty` mentions any generic parameters, the generated shim would refer to them (but they won't match the `Substs` of the `Instance`), or worse, generating the shim would fail because not enough of the type is known. Ideally we would always produce a "skeleton" of the type, e.g. `(_, _)` for dropping any tuples with two elements, or `Vec<_>` for dropping any `Vec` value, but that's a lot of work, and they would still not match the `Substs` of the `Instance` as it exists today, so `Instance` would probably need to change. By making `Instance::resolve` return `None` in the still-generic cases, we get behavior similar to specialization, where a default can only be used if there are no more generic parameters which would allow a more specialized `impl` to match. <hr/> This was found while testing the MIR inliner with #68965, because it was trying to inline shims. cc @rust-lang/wg-mir-opt
This commit is contained in:
commit
ffb3c2cb3d
@ -39,6 +39,10 @@ pub enum InstanceDef<'tcx> {
|
||||
|
||||
/// `<fn() as FnTrait>::call_*`
|
||||
/// `DefId` is `FnTrait::call_*`.
|
||||
///
|
||||
/// NB: the (`fn` pointer) type must currently be monomorphic to avoid double substitution
|
||||
/// problems with the MIR shim bodies. `Instance::resolve` enforces this.
|
||||
// FIXME(#69925) support polymorphic MIR shim bodies properly instead.
|
||||
FnPtrShim(DefId, Ty<'tcx>),
|
||||
|
||||
/// `<dyn Trait as Trait>::fn`, "direct calls" of which are implicitly
|
||||
@ -57,9 +61,17 @@ pub enum InstanceDef<'tcx> {
|
||||
/// The `DefId` is for `core::ptr::drop_in_place`.
|
||||
/// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop
|
||||
/// glue.
|
||||
///
|
||||
/// NB: the type must currently be monomorphic to avoid double substitution
|
||||
/// problems with the MIR shim bodies. `Instance::resolve` enforces this.
|
||||
// FIXME(#69925) support polymorphic MIR shim bodies properly instead.
|
||||
DropGlue(DefId, Option<Ty<'tcx>>),
|
||||
|
||||
///`<T as Clone>::clone` shim.
|
||||
///
|
||||
/// NB: the type must currently be monomorphic to avoid double substitution
|
||||
/// problems with the MIR shim bodies. `Instance::resolve` enforces this.
|
||||
// FIXME(#69925) support polymorphic MIR shim bodies properly instead.
|
||||
CloneShim(DefId, Ty<'tcx>),
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,13 @@ use rustc::mir::*;
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use std::fmt;
|
||||
@ -39,6 +39,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
|
||||
None,
|
||||
),
|
||||
ty::InstanceDef::FnPtrShim(def_id, ty) => {
|
||||
// FIXME(eddyb) support generating shims for a "shallow type",
|
||||
// e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
|
||||
// `Foo<Bar>` or `[String]` etc.
|
||||
assert!(!ty.needs_subst());
|
||||
|
||||
let trait_ = tcx.trait_of_item(def_id).unwrap();
|
||||
let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) {
|
||||
Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
|
||||
@ -81,17 +86,21 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
|
||||
None,
|
||||
)
|
||||
}
|
||||
ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty),
|
||||
ty::InstanceDef::DropGlue(def_id, ty) => {
|
||||
// FIXME(eddyb) support generating shims for a "shallow type",
|
||||
// e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
|
||||
// `Foo<Bar>` or `[String]` etc.
|
||||
assert!(!ty.needs_subst());
|
||||
|
||||
build_drop_shim(tcx, def_id, ty)
|
||||
}
|
||||
ty::InstanceDef::CloneShim(def_id, ty) => {
|
||||
let name = tcx.item_name(def_id);
|
||||
if name == sym::clone {
|
||||
build_clone_shim(tcx, def_id, ty)
|
||||
} else if name == sym::clone_from {
|
||||
debug!("make_shim({:?}: using default trait implementation", instance);
|
||||
return tcx.optimized_mir(def_id);
|
||||
} else {
|
||||
bug!("builtin clone shim {:?} not supported", instance)
|
||||
}
|
||||
// FIXME(eddyb) support generating shims for a "shallow type",
|
||||
// e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
|
||||
// `Foo<Bar>` or `[String]` etc.
|
||||
assert!(!ty.needs_subst());
|
||||
|
||||
build_clone_shim(tcx, def_id, ty)
|
||||
}
|
||||
ty::InstanceDef::Virtual(..) => {
|
||||
bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
|
||||
|
@ -1,6 +1,7 @@
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
use rustc::ty::{self, Instance, TyCtxt, TypeFoldable};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_span::sym;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
@ -31,21 +32,26 @@ pub fn resolve_instance<'tcx>(
|
||||
debug!(" => intrinsic");
|
||||
ty::InstanceDef::Intrinsic(def_id)
|
||||
}
|
||||
_ => {
|
||||
if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
|
||||
let ty = substs.type_at(0);
|
||||
if ty.needs_drop(tcx, param_env.with_reveal_all()) {
|
||||
debug!(" => nontrivial drop glue");
|
||||
ty::InstanceDef::DropGlue(def_id, Some(ty))
|
||||
} else {
|
||||
debug!(" => trivial drop glue");
|
||||
ty::InstanceDef::DropGlue(def_id, None)
|
||||
ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
|
||||
let ty = substs.type_at(0);
|
||||
|
||||
if ty.needs_drop(tcx, param_env) {
|
||||
// `DropGlue` requires a monomorphic aka concrete type.
|
||||
if ty.needs_subst() {
|
||||
return None;
|
||||
}
|
||||
|
||||
debug!(" => nontrivial drop glue");
|
||||
ty::InstanceDef::DropGlue(def_id, Some(ty))
|
||||
} else {
|
||||
debug!(" => free item");
|
||||
ty::InstanceDef::Item(def_id)
|
||||
debug!(" => trivial drop glue");
|
||||
ty::InstanceDef::DropGlue(def_id, None)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
debug!(" => free item");
|
||||
ty::InstanceDef::Item(def_id)
|
||||
}
|
||||
};
|
||||
Some(Instance { def, substs })
|
||||
};
|
||||
@ -113,20 +119,44 @@ fn resolve_associated_item<'tcx>(
|
||||
trait_closure_kind,
|
||||
))
|
||||
}
|
||||
traits::VtableFnPointer(ref data) => Some(Instance {
|
||||
def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
|
||||
substs: rcvr_substs,
|
||||
}),
|
||||
traits::VtableFnPointer(ref data) => {
|
||||
// `FnPtrShim` requires a monomorphic aka concrete type.
|
||||
if data.fn_ty.needs_subst() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
|
||||
substs: rcvr_substs,
|
||||
})
|
||||
}
|
||||
traits::VtableObject(ref data) => {
|
||||
let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
|
||||
Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
|
||||
}
|
||||
traits::VtableBuiltin(..) => {
|
||||
if tcx.lang_items().clone_trait().is_some() {
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
|
||||
substs: rcvr_substs,
|
||||
})
|
||||
if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() {
|
||||
// FIXME(eddyb) use lang items for methods instead of names.
|
||||
let name = tcx.item_name(def_id);
|
||||
if name == sym::clone {
|
||||
let self_ty = trait_ref.self_ty();
|
||||
|
||||
// `CloneShim` requires a monomorphic aka concrete type.
|
||||
if self_ty.needs_subst() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::CloneShim(def_id, self_ty),
|
||||
substs: rcvr_substs,
|
||||
})
|
||||
} else {
|
||||
assert_eq!(name, sym::clone_from);
|
||||
|
||||
// Use the default `fn clone_from` from `trait Clone`.
|
||||
let substs = tcx.erase_regions(&rcvr_substs);
|
||||
Some(ty::Instance::new(def_id, substs))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user