Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

rustc: don't resolve Instances which would produce malformed shims. #69036

Merged
merged 2 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/librustc/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
eddyb marked this conversation as resolved.
Show resolved Hide resolved
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>),
}

Expand Down
33 changes: 21 additions & 12 deletions src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
70 changes: 50 additions & 20 deletions src/librustc_ty/instance.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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 })
};
Expand Down Expand Up @@ -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
}
Expand Down