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

Add Instance::resolve_for_fn_ptr (RFC 2091 #2/N) #65182

Merged
merged 12 commits into from
Oct 13, 2019
1 change: 1 addition & 0 deletions src/librustc/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ impl<'tcx> CodegenUnit<'tcx> {
tcx.hir().as_local_hir_id(def_id)
}
InstanceDef::VtableShim(..) |
InstanceDef::ReifyShim(..) |
InstanceDef::Intrinsic(..) |
InstanceDef::FnPtrShim(..) |
InstanceDef::Virtual(..) |
Expand Down
28 changes: 28 additions & 0 deletions src/librustc/ty/instance.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::hir::CodegenFnAttrFlags;
use crate::hir::Unsafety;
use crate::hir::def::Namespace;
use crate::hir::def_id::DefId;
Expand Down Expand Up @@ -25,6 +26,11 @@ pub enum InstanceDef<'tcx> {
/// `<T as Trait>::method` where `method` receives unsizeable `self: Self`.
VtableShim(DefId),

/// `fn()` pointer where the function itself cannot be turned into a pointer.
///
/// One example in the compiler today is functions annotated with `#[track_caller]`.
anp marked this conversation as resolved.
Show resolved Hide resolved
ReifyShim(DefId),

/// `<fn() as FnTrait>::call_*`
/// `DefId` is `FnTrait::call_*`
FnPtrShim(DefId, Ty<'tcx>),
Expand Down Expand Up @@ -123,6 +129,7 @@ impl<'tcx> InstanceDef<'tcx> {
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, ) |
Expand Down Expand Up @@ -178,6 +185,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
InstanceDef::VtableShim(_) => {
write!(f, " - shim(vtable)")
}
InstanceDef::ReifyShim(_) => {
write!(f, " - shim(reify)")
}
InstanceDef::Intrinsic(_) => {
write!(f, " - intrinsic")
}
Expand Down Expand Up @@ -290,6 +300,24 @@ impl<'tcx> Instance<'tcx> {
result
}

pub fn resolve_for_fn_ptr(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> {
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) {
anp marked this conversation as resolved.
Show resolved Hide resolved
debug!(" => fn pointer created for function with #[track_caller]");
Some(Instance {
def: InstanceDef::ReifyShim(def_id),
substs,
})
} else {
Instance::resolve(tcx, param_env, def_id, substs)
}
}

pub fn resolve_for_vtable(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3026,6 +3026,7 @@ impl<'tcx> TyCtxt<'tcx> {
self.optimized_mir(did)
}
ty::InstanceDef::VtableShim(..) |
ty::InstanceDef::ReifyShim(..) |
ty::InstanceDef::Intrinsic(..) |
ty::InstanceDef::FnPtrShim(..) |
ty::InstanceDef::Virtual(..) |
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
Some(ty::InstanceDef::Item(def_id)),
ty::InstanceDef::VtableShim(def_id) =>
Some(ty::InstanceDef::VtableShim(def_id)),
ty::InstanceDef::ReifyShim(def_id) =>
Some(ty::InstanceDef::ReifyShim(def_id)),
ty::InstanceDef::Intrinsic(def_id) =>
Some(ty::InstanceDef::Intrinsic(def_id)),
ty::InstanceDef::FnPtrShim(def_id, ref ty) =>
Expand Down Expand Up @@ -966,6 +968,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
def: match self.def {
Item(did) => Item(did.fold_with(folder)),
VtableShim(did) => VtableShim(did.fold_with(folder)),
ReifyShim(did) => ReifyShim(did.fold_with(folder)),
Intrinsic(did) => Intrinsic(did.fold_with(folder)),
FnPtrShim(did, ty) => FnPtrShim(
did.fold_with(folder),
Expand Down Expand Up @@ -994,7 +997,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
use crate::ty::InstanceDef::*;
self.substs.visit_with(visitor) ||
match self.def {
Item(did) | VtableShim(did) | Intrinsic(did) | Virtual(did, _) => {
Item(did) | VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
did.visit_with(visitor)
},
FnPtrShim(did, ty) | CloneShim(did, ty) => {
Expand Down
17 changes: 17 additions & 0 deletions src/librustc_codegen_ssa/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>(
)
}

pub fn resolve_and_get_fn_for_ptr<'tcx,
anp marked this conversation as resolved.
Show resolved Hide resolved
Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
>(
cx: &Cx,
def_id: DefId,
substs: SubstsRef<'tcx>,
) -> Cx::Value {
cx.get_fn(
ty::Instance::resolve_for_fn_ptr(
cx.tcx(),
ty::ParamEnv::reveal_all(),
def_id,
substs
).unwrap()
)
}

pub fn resolve_and_get_fn_for_vtable<'tcx,
Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
>(
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bug!("reifying a fn ptr that requires const arguments");
}
OperandValue::Immediate(
callee::resolve_and_get_fn(bx.cx(), def_id, substs))
callee::resolve_and_get_fn_for_ptr(bx.cx(), def_id, substs))
anp marked this conversation as resolved.
Show resolved Hide resolved
}
_ => {
bug!("{} cannot be reified to a fn ptr", operand.layout.ty)
Expand Down
9 changes: 8 additions & 1 deletion src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
if self.tcx.has_attr(def_id, sym::rustc_args_required_const) {
bug!("reifying a fn ptr that requires const arguments");
}
let instance = self.resolve(def_id, substs)?;

let instance = ty::Instance::resolve_for_fn_ptr(
*self.tcx,
self.param_env,
def_id,
substs,
).ok_or_else(|| err_inval!(TooGeneric))?;

let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(())
}
ty::InstanceDef::VtableShim(..) |
ty::InstanceDef::ReifyShim(..) |
ty::InstanceDef::ClosureOnceShim { .. } |
ty::InstanceDef::FnPtrShim(..) |
ty::InstanceDef::DropGlue(..) |
Expand Down
12 changes: 8 additions & 4 deletions src/librustc_mir/monomorphize/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,10 +721,12 @@ fn visit_fn_use<'tcx>(
output: &mut Vec<MonoItem<'tcx>>,
) {
if let ty::FnDef(def_id, substs) = ty.kind {
let instance = ty::Instance::resolve(tcx,
ty::ParamEnv::reveal_all(),
def_id,
substs).unwrap();
let resolver = if is_direct_call {
ty::Instance::resolve
} else {
ty::Instance::resolve_for_fn_ptr
};
let instance = resolver(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap();
anp marked this conversation as resolved.
Show resolved Hide resolved
visit_instance_use(tcx, instance, is_direct_call, output);
}
}
Expand All @@ -747,6 +749,7 @@ fn visit_instance_use<'tcx>(
}
}
ty::InstanceDef::VtableShim(..) |
ty::InstanceDef::ReifyShim(..) |
ty::InstanceDef::Virtual(..) |
ty::InstanceDef::DropGlue(_, None) => {
// don't need to emit shim if we are calling directly.
Expand All @@ -773,6 +776,7 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx
let def_id = match instance.def {
ty::InstanceDef::Item(def_id) => def_id,
ty::InstanceDef::VtableShim(..) |
ty::InstanceDef::ReifyShim(..) |
ty::InstanceDef::ClosureOnceShim { .. } |
ty::InstanceDef::Virtual(..) |
ty::InstanceDef::FnPtrShim(..) |
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_mir/monomorphize/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ fn mono_item_visibility(

// These are all compiler glue and such, never exported, always hidden.
InstanceDef::VtableShim(..) |
InstanceDef::ReifyShim(..) |
InstanceDef::FnPtrShim(..) |
InstanceDef::Virtual(..) |
InstanceDef::Intrinsic(..) |
Expand Down Expand Up @@ -677,6 +678,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
let def_id = match instance.def {
ty::InstanceDef::Item(def_id) => def_id,
ty::InstanceDef::VtableShim(..) |
ty::InstanceDef::ReifyShim(..) |
ty::InstanceDef::FnPtrShim(..) |
ty::InstanceDef::ClosureOnceShim { .. } |
ty::InstanceDef::Intrinsic(..) |
Expand Down
8 changes: 5 additions & 3 deletions src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
Some(arg_tys)
)
}
ty::InstanceDef::Virtual(def_id, _) => {
// We are generating a call back to our def-id, which the
// codegen backend knows to turn to an actual virtual call.
// We are generating a call back to our def-id, which the
// codegen backend knows to turn to an actual virtual call.
ty::InstanceDef::Virtual(def_id, _) |
// ...or we are generating a call to the inner closure defined by #[track_caller]
anp marked this conversation as resolved.
Show resolved Hide resolved
ty::InstanceDef::ReifyShim(def_id) => {
build_call_shim(
tcx,
def_id,
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// failure-status: 101
// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET"
// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS"

#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete

#[track_caller]
fn f() {}

fn call_it(x: fn()) {
x();
}

fn main() {
call_it(f);
}
anp marked this conversation as resolved.
Show resolved Hide resolved
21 changes: 21 additions & 0 deletions src/test/ui/rfc-2091-track-caller/taking-fn-pointer.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
warning: the feature `track_caller` is incomplete and may cause the compiler to crash
--> $DIR/taking-fn-pointer.rs:5:12
|
LL | #![feature(track_caller)]
| ^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default

thread 'rustc' panicked at 'index out of bounds: the len is 1 but the index is 1', $SRC_DIR/libcore/slice/mod.rs:LL:COL
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports

note: rustc VERSION running on TARGET

note: compiler flags: FLAGS