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

Fix generics handling for function calls #1215

Merged
merged 7 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
22 changes: 4 additions & 18 deletions frontend/exporter/src/types/mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,26 +955,12 @@ pub enum AggregateKind {
Option<UserTypeAnnotationIndex>,
Option<FieldIdx>,
),
#[custom_arm(rustc_middle::mir::AggregateKind::Closure(rust_id, generics) => {
let def_id : DefId = rust_id.sinto(s);
// The generics is meant to be converted to a function signature. Note
// that Rustc does its job: the PolyFnSig binds the captured local
// type, regions, etc. variables, which means we can treat the local
// closure like any top-level function.
#[custom_arm(rustc_middle::mir::AggregateKind::Closure(def_id, generics) => {
let closure = generics.as_closure();
let sig = closure.sig().sinto(s);

// Solve the predicates from the parent (i.e., the item which defines the closure).
let tcx = s.base().tcx;
let parent_generics = closure.parent_args();
let parent_generics_ref = tcx.mk_args(parent_generics);
// TODO: does this handle nested closures?
let parent = tcx.generics_of(rust_id).parent.unwrap();
let trait_refs = solve_item_required_traits(s, parent, parent_generics_ref);

AggregateKind::Closure(def_id, parent_generics.sinto(s), trait_refs, sig)
let args = ClosureArgs::sfrom(s, *def_id, closure);
AggregateKind::Closure(def_id.sinto(s), args)
})]
Closure(DefId, Vec<GenericArg>, Vec<ImplExpr>, PolyFnSig),
Closure(DefId, ClosureArgs),
Coroutine(DefId, Vec<GenericArg>),
CoroutineClosure(DefId, Vec<GenericArg>),
RawPtr(Ty, Mutability),
Expand Down
6 changes: 2 additions & 4 deletions frontend/exporter/src/types/new/full_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,8 @@ pub enum FullDefKind<Body> {
is_const: bool,
#[value({
let fun_type = s.base().tcx.type_of(s.owner_id()).instantiate_identity();
match fun_type.kind() {
ty::TyKind::Closure(_, args) => args.as_closure().sinto(s),
_ => unreachable!(),
}
let ty::TyKind::Closure(_, args) = fun_type.kind() else { unreachable!() };
ClosureArgs::sfrom(s, s.owner_id(), args.as_closure())
})]
args: ClosureArgs,
},
Expand Down
52 changes: 44 additions & 8 deletions frontend/exporter/src/types/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1272,21 +1272,57 @@ pub enum AliasRelationDirection {
}

/// Reflects [`ty::ClosureArgs`]
#[derive(AdtInto)]
#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: ty::ClosureArgs<ty::TyCtxt<'tcx>>, state: S as s)]
#[derive(Clone, Debug, JsonSchema)]
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
#[derive_group(Serializers)]
pub struct ClosureArgs {
#[value(self.kind().sinto(s))]
/// The base kind of this closure. The kinds are ordered by inclusion: any `Fn` works as an
/// `FnMut`, and any `FnMut` works as an `FnOnce`.
pub kind: ClosureKind,
#[value(self.parent_args().sinto(s))]
/// The arguments to the parent (i.e., the item which defines the closure).
pub parent_args: Vec<GenericArg>,
#[value(self.sig().sinto(s))]
pub sig: PolyFnSig,
#[value(self.upvar_tys().sinto(s))]
/// The solved predicates from the parent (i.e., the item which defines the closure).
pub parent_trait_refs: Vec<ImplExpr>,
/// The proper `fn(A, B, C) -> D` signature of the closure.
pub untupled_sig: PolyFnSig,
/// The signature of the closure as one input and one output, where the input arguments are
/// tupled. This is relevant to implementing the `Fn*` traits.
pub tupled_sig: PolyFnSig,
/// The set of captured variables. Together they form the state of the closure.
pub upvar_tys: Vec<Ty>,
}

#[cfg(feature = "rustc")]
impl ClosureArgs {
// Manual implementation because we need the `def_id` of the closure.
pub(crate) fn sfrom<'tcx, S>(
s: &S,
def_id: RDefId,
from: ty::ClosureArgs<ty::TyCtxt<'tcx>>,
) -> Self
where
S: UnderOwnerState<'tcx>,
{
let tcx = s.base().tcx;
let sig = from.sig();
ClosureArgs {
kind: from.kind().sinto(s),
parent_args: from.parent_args().sinto(s),
// The solved predicates from the parent (i.e., the item which defines the closure).
parent_trait_refs: {
// TODO: handle nested closures
W95Psp marked this conversation as resolved.
Show resolved Hide resolved
let parent = tcx.generics_of(def_id).parent.unwrap();
let parent_generics_ref = tcx.mk_args(from.parent_args());
solve_item_required_traits(s, parent, parent_generics_ref)
},
tupled_sig: sig.sinto(s),
untupled_sig: tcx
.signature_unclosure(sig, rustc_hir::Safety::Safe)
.sinto(s),
upvar_tys: from.upvar_tys().sinto(s),
}
}
}

/// Reflects [`ty::ClosureKind`]
#[derive(AdtInto)]
#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: ty::ClosureKind, state: S as _tcx)]
Expand Down