Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 04accf1

Browse files
committed
add a builtin FnPtr trait
1 parent ed4dd0c commit 04accf1

File tree

17 files changed

+163
-13
lines changed

17 files changed

+163
-13
lines changed

‎compiler/rustc_const_eval/src/interpret/terminator.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
370370
| ty::InstanceDef::FnPtrShim(..)
371371
| ty::InstanceDef::DropGlue(..)
372372
| ty::InstanceDef::CloneShim(..)
373+
| ty::InstanceDef::FnPtrAddrShim(..)
373374
| ty::InstanceDef::Item(_) => {
374375
// We need MIR for this fn
375376
let Some((body, instance)) =

‎compiler/rustc_hir/src/lang_items.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ language_item_table! {
185185

186186
Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
187187

188+
FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, Target::Trait, GenericRequirement::Exact(0);
189+
FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
190+
188191
Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None;
189192
Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None;
190193

‎compiler/rustc_middle/src/mir/mono.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ impl<'tcx> CodegenUnit<'tcx> {
369369
| InstanceDef::Virtual(..)
370370
| InstanceDef::ClosureOnceShim { .. }
371371
| InstanceDef::DropGlue(..)
372-
| InstanceDef::CloneShim(..) => None,
372+
| InstanceDef::CloneShim(..)
373+
| InstanceDef::FnPtrAddrShim(..) => None,
373374
}
374375
}
375376
MonoItem::Static(def_id) => def_id.as_local().map(Idx::index),

‎compiler/rustc_middle/src/mir/visit.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,8 @@ macro_rules! make_mir_visitor {
402402

403403
ty::InstanceDef::FnPtrShim(_def_id, ty) |
404404
ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
405-
ty::InstanceDef::CloneShim(_def_id, ty) => {
405+
ty::InstanceDef::CloneShim(_def_id, ty) |
406+
ty::InstanceDef::FnPtrAddrShim(_def_id, ty) => {
406407
// FIXME(eddyb) use a better `TyContext` here.
407408
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
408409
}

‎compiler/rustc_middle/src/ty/instance.rs‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ pub enum InstanceDef<'tcx> {
9797
///
9898
/// The `DefId` is for `Clone::clone`, the `Ty` is the type `T` with the builtin `Clone` impl.
9999
CloneShim(DefId, Ty<'tcx>),
100+
101+
/// Compiler-generated `<T as FnPtr>::addr` implementation.
102+
///
103+
/// Automatically generated for all potentially higher-ranked `fn(I) -> R` types.
104+
///
105+
/// The `DefId` is for `FnPtr::Addr`, the `Ty` is the type `T`.
106+
FnPtrAddrShim(DefId, Ty<'tcx>),
100107
}
101108

102109
impl<'tcx> Instance<'tcx> {
@@ -152,7 +159,8 @@ impl<'tcx> InstanceDef<'tcx> {
152159
| InstanceDef::Intrinsic(def_id)
153160
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
154161
| InstanceDef::DropGlue(def_id, _)
155-
| InstanceDef::CloneShim(def_id, _) => def_id,
162+
| InstanceDef::CloneShim(def_id, _)
163+
| InstanceDef::FnPtrAddrShim(def_id, _) => def_id,
156164
}
157165
}
158166

@@ -168,7 +176,8 @@ impl<'tcx> InstanceDef<'tcx> {
168176
| InstanceDef::Intrinsic(..)
169177
| InstanceDef::ClosureOnceShim { .. }
170178
| InstanceDef::DropGlue(..)
171-
| InstanceDef::CloneShim(..) => None,
179+
| InstanceDef::CloneShim(..)
180+
| InstanceDef::FnPtrAddrShim(..) => None,
172181
}
173182
}
174183

@@ -183,7 +192,8 @@ impl<'tcx> InstanceDef<'tcx> {
183192
| InstanceDef::Intrinsic(def_id)
184193
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
185194
| InstanceDef::DropGlue(def_id, _)
186-
| InstanceDef::CloneShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
195+
| InstanceDef::CloneShim(def_id, _)
196+
| InstanceDef::FnPtrAddrShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
187197
}
188198
}
189199

@@ -265,6 +275,7 @@ impl<'tcx> InstanceDef<'tcx> {
265275
pub fn has_polymorphic_mir_body(&self) -> bool {
266276
match *self {
267277
InstanceDef::CloneShim(..)
278+
| InstanceDef::FnPtrAddrShim(..)
268279
| InstanceDef::FnPtrShim(..)
269280
| InstanceDef::DropGlue(_, Some(_)) => false,
270281
InstanceDef::ClosureOnceShim { .. }
@@ -299,6 +310,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
299310
InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"),
300311
InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({}))", ty),
301312
InstanceDef::CloneShim(_, ty) => write!(f, " - shim({})", ty),
313+
InstanceDef::FnPtrAddrShim(_, ty) => write!(f, " - shim({})", ty),
302314
}
303315
}
304316
}

‎compiler/rustc_middle/src/ty/mod.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2148,7 +2148,8 @@ impl<'tcx> TyCtxt<'tcx> {
21482148
| ty::InstanceDef::Virtual(..)
21492149
| ty::InstanceDef::ClosureOnceShim { .. }
21502150
| ty::InstanceDef::DropGlue(..)
2151-
| ty::InstanceDef::CloneShim(..) => self.mir_shims(instance),
2151+
| ty::InstanceDef::CloneShim(..)
2152+
| ty::InstanceDef::FnPtrAddrShim(..) => self.mir_shims(instance),
21522153
}
21532154
}
21542155

‎compiler/rustc_middle/src/ty/structural_impls.rs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
640640
ty::InstanceDef::CloneShim(def_id, ty) => {
641641
Some(ty::InstanceDef::CloneShim(def_id, tcx.lift(ty)?))
642642
}
643+
ty::InstanceDef::FnPtrAddrShim(def_id, ty) => {
644+
Some(ty::InstanceDef::FnPtrAddrShim(def_id, tcx.lift(ty)?))
645+
}
643646
}
644647
}
645648
}
@@ -943,6 +946,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
943946
CloneShim(did, ty) => {
944947
CloneShim(did.try_fold_with(folder)?, ty.try_fold_with(folder)?)
945948
}
949+
FnPtrAddrShim(did, ty) => {
950+
FnPtrAddrShim(did.try_fold_with(folder)?, ty.try_fold_with(folder)?)
951+
}
946952
},
947953
})
948954
}
@@ -957,7 +963,7 @@ impl<'tcx> TypeVisitable<'tcx> for ty::instance::Instance<'tcx> {
957963
VTableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
958964
did.visit_with(visitor)
959965
}
960-
FnPtrShim(did, ty) | CloneShim(did, ty) => {
966+
FnPtrShim(did, ty) | CloneShim(did, ty) | FnPtrAddrShim(did, ty)=> {
961967
did.visit_with(visitor)?;
962968
ty.visit_with(visitor)
963969
}

‎compiler/rustc_mir_transform/src/inline.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,8 @@ impl<'tcx> Inliner<'tcx> {
251251
| InstanceDef::FnPtrShim(..)
252252
| InstanceDef::ClosureOnceShim { .. }
253253
| InstanceDef::DropGlue(..)
254-
| InstanceDef::CloneShim(..) => return Ok(()),
254+
| InstanceDef::CloneShim(..)
255+
| InstanceDef::FnPtrAddrShim(..) => return Ok(()),
255256
}
256257

257258
if self.tcx.is_constructor(callee_def_id) {

‎compiler/rustc_mir_transform/src/inline/cycle.rs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,14 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
7979
// These have MIR and if that MIR is inlined, substituted and then inlining is run
8080
// again, a function item can end up getting inlined. Thus we'll be able to cause
8181
// a cycle that way
82+
//
83+
// FIXME: `FnPtrAddrShim` should not be able to cause recursion.
8284
InstanceDef::VTableShim(_)
8385
| InstanceDef::ReifyShim(_)
8486
| InstanceDef::FnPtrShim(..)
8587
| InstanceDef::ClosureOnceShim { .. }
86-
| InstanceDef::CloneShim(..) => {}
88+
| InstanceDef::CloneShim(..)
89+
| InstanceDef::FnPtrAddrShim(..) => {}
8790
InstanceDef::DropGlue(..) => {
8891
// FIXME: A not fully substituted drop shim can cause ICEs if one attempts to
8992
// have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this

‎compiler/rustc_mir_transform/src/shim.rs‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
7878
build_drop_shim(tcx, def_id, ty)
7979
}
8080
ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty),
81+
ty::InstanceDef::FnPtrAddrShim(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty),
8182
ty::InstanceDef::Virtual(..) => {
8283
bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
8384
}
@@ -788,3 +789,38 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
788789

789790
body
790791
}
792+
793+
/// ```ignore (pseudo-impl)
794+
/// impl FnPtr for fn(u32) {
795+
/// fn addr(self) -> usize {
796+
/// self as usize
797+
/// }
798+
/// }
799+
/// ```
800+
fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
801+
assert!(matches!(self_ty.kind(), ty::FnPtr(..)), "expected fn ptr, found {self_ty}");
802+
let span = tcx.def_span(def_id);
803+
let Some(sig) = tcx.bound_fn_sig(def_id).subst(tcx, &[self_ty.into()]).no_bound_vars() else {
804+
span_bug!(span, "FnPtr::addr with bound vars for `{self_ty}`");
805+
};
806+
let locals = local_decls_for_sig(&sig, span);
807+
808+
let source_info = SourceInfo::outermost(span);
809+
let rvalue = Rvalue::Cast(
810+
CastKind::PointerExposeAddress,
811+
Operand::Move(Place::from(Local::new(1))),
812+
tcx.types.usize,
813+
);
814+
let stmt = Statement {
815+
source_info,
816+
kind: StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
817+
};
818+
let statements = vec![stmt];
819+
let start_block = BasicBlockData {
820+
statements,
821+
terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }),
822+
is_cleanup: false,
823+
};
824+
let source = MirSource::from_instance(ty::InstanceDef::FnPtrAddrShim(def_id, self_ty));
825+
new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span)
826+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /