Rollup merge of #70089 - eddyb:closure-sig-infer, r=nikomatsakis
rustc_infer: remove InferCtxt::closure_sig as the FnSig is always shallowly known. That is, `ClosureSubsts` is always created (in `rustc_typeck::check::closure`) with a `FnSig`, as the number of inputs is known, even if they might all have inference types. The only useful thing `InferCtxt::closure_sig` was doing is resolving an inference variable used just to get the `ty::FnPtr` containing that `FnSig` into `ClosureSubsts`. The ideal way to solve this would be to add a constructor for `ClosureSubsts`, that combines the parent `Substs`, the closure kind, the signature, and capture types together, but for now I've went with resolving the inference types just after unifying them with the real types. r? @nikomatsakis
This commit is contained in:
commit
a6d0c35e86
15 changed files with 51 additions and 76 deletions
|
@ -681,9 +681,9 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
|
|
||||||
if self.tcx().sess.verbose() {
|
if self.tcx().sess.verbose() {
|
||||||
p!(write(
|
p!(write(
|
||||||
" closure_kind_ty={:?} closure_sig_ty={:?}",
|
" closure_kind_ty={:?} closure_sig_as_fn_ptr_ty={:?}",
|
||||||
substs.as_closure().kind_ty(did, self.tcx()),
|
substs.as_closure().kind_ty(did, self.tcx()),
|
||||||
substs.as_closure().sig_ty(did, self.tcx())
|
substs.as_closure().sig_as_fn_ptr_ty(did, self.tcx())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -371,7 +371,7 @@ pub struct ClosureSubsts<'tcx> {
|
||||||
/// parent slice and not canonical substs themselves.
|
/// parent slice and not canonical substs themselves.
|
||||||
struct SplitClosureSubsts<'tcx> {
|
struct SplitClosureSubsts<'tcx> {
|
||||||
closure_kind_ty: Ty<'tcx>,
|
closure_kind_ty: Ty<'tcx>,
|
||||||
closure_sig_ty: Ty<'tcx>,
|
closure_sig_as_fn_ptr_ty: Ty<'tcx>,
|
||||||
upvar_kinds: &'tcx [GenericArg<'tcx>],
|
upvar_kinds: &'tcx [GenericArg<'tcx>],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
|
||||||
let parent_len = generics.parent_count;
|
let parent_len = generics.parent_count;
|
||||||
SplitClosureSubsts {
|
SplitClosureSubsts {
|
||||||
closure_kind_ty: self.substs.type_at(parent_len),
|
closure_kind_ty: self.substs.type_at(parent_len),
|
||||||
closure_sig_ty: self.substs.type_at(parent_len + 1),
|
closure_sig_as_fn_ptr_ty: self.substs.type_at(parent_len + 1),
|
||||||
upvar_kinds: &self.substs[parent_len + 2..],
|
upvar_kinds: &self.substs[parent_len + 2..],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,12 +412,10 @@ impl<'tcx> ClosureSubsts<'tcx> {
|
||||||
self.split(def_id, tcx).closure_kind_ty
|
self.split(def_id, tcx).closure_kind_ty
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the type representing the closure signature for this
|
/// Returns the `fn` pointer type representing the closure signature for this
|
||||||
/// closure; may contain type variables during inference. To get
|
/// closure.
|
||||||
/// the closure signature during inference, use
|
pub fn sig_as_fn_ptr_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
|
||||||
/// `infcx.fn_sig(def_id)`.
|
self.split(def_id, tcx).closure_sig_as_fn_ptr_ty
|
||||||
pub fn sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
|
|
||||||
self.split(def_id, tcx).closure_sig_ty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the closure kind for this closure; only usable outside
|
/// Returns the closure kind for this closure; only usable outside
|
||||||
|
@ -429,16 +427,12 @@ impl<'tcx> ClosureSubsts<'tcx> {
|
||||||
self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
|
self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extracts the signature from the closure; only usable outside
|
/// Extracts the signature from the closure.
|
||||||
/// of an inference context, because in that context we know that
|
|
||||||
/// there are no type variables.
|
|
||||||
///
|
|
||||||
/// If you have an inference context, use `infcx.closure_sig()`.
|
|
||||||
pub fn sig(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
|
pub fn sig(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
|
||||||
let ty = self.sig_ty(def_id, tcx);
|
let ty = self.sig_as_fn_ptr_ty(def_id, tcx);
|
||||||
match ty.kind {
|
match ty.kind {
|
||||||
ty::FnPtr(sig) => sig,
|
ty::FnPtr(sig) => sig,
|
||||||
_ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind),
|
_ => bug!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {:?}", ty.kind),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2200,9 +2194,9 @@ impl<'tcx> TyS<'tcx> {
|
||||||
// ignore errors (#54954)
|
// ignore errors (#54954)
|
||||||
ty::Binder::dummy(FnSig::fake())
|
ty::Binder::dummy(FnSig::fake())
|
||||||
}
|
}
|
||||||
Closure(..) => {
|
Closure(..) => bug!(
|
||||||
bug!("to get the signature of a closure, use `closure_sig()` not `fn_sig()`",)
|
"to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`",
|
||||||
}
|
),
|
||||||
_ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self),
|
_ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1506,16 +1506,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
closure_kind_ty.to_opt_closure_kind()
|
closure_kind_ty.to_opt_closure_kind()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtains the signature of a closure. For closures, unlike
|
|
||||||
/// `tcx.fn_sig(def_id)`, this method will work during the
|
|
||||||
/// type-checking of the enclosing function and return the closure
|
|
||||||
/// signature in its partially inferred state.
|
|
||||||
pub fn closure_sig(&self, def_id: DefId, substs: SubstsRef<'tcx>) -> ty::PolyFnSig<'tcx> {
|
|
||||||
let closure_sig_ty = substs.as_closure().sig_ty(def_id, self.tcx);
|
|
||||||
let closure_sig_ty = self.shallow_resolve(closure_sig_ty);
|
|
||||||
closure_sig_ty.fn_sig(self.tcx)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clears the selection, evaluation, and projection caches. This is useful when
|
/// Clears the selection, evaluation, and projection caches. This is useful when
|
||||||
/// repeatedly attempting to select an `Obligation` while changing only
|
/// repeatedly attempting to select an `Obligation` while changing only
|
||||||
/// its `ParamEnv`, since `FulfillmentContext` doesn't use probing.
|
/// its `ParamEnv`, since `FulfillmentContext` doesn't use probing.
|
||||||
|
|
|
@ -1684,7 +1684,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
// case it ends up being assigned into the return place.
|
// case it ends up being assigned into the return place.
|
||||||
annotated_closure = self.annotate_fn_sig(
|
annotated_closure = self.annotate_fn_sig(
|
||||||
*def_id,
|
*def_id,
|
||||||
self.infcx.closure_sig(*def_id, *substs),
|
substs.as_closure().sig(*def_id, self.infcx.tcx),
|
||||||
);
|
);
|
||||||
debug!(
|
debug!(
|
||||||
"annotate_argument_and_return_for_borrow: \
|
"annotate_argument_and_return_for_borrow: \
|
||||||
|
|
|
@ -2085,9 +2085,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
|
|
||||||
CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
|
CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
|
||||||
let sig = match op.ty(*body, tcx).kind {
|
let sig = match op.ty(*body, tcx).kind {
|
||||||
ty::Closure(def_id, substs) => {
|
ty::Closure(def_id, substs) => substs.as_closure().sig(def_id, tcx),
|
||||||
substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx)
|
|
||||||
}
|
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig, *unsafety);
|
let ty_fn_ptr_from = tcx.coerce_closure_fn_ty(sig, *unsafety);
|
||||||
|
|
|
@ -580,7 +580,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||||
match defining_ty {
|
match defining_ty {
|
||||||
DefiningTy::Closure(def_id, substs) => {
|
DefiningTy::Closure(def_id, substs) => {
|
||||||
assert_eq!(self.mir_def_id, def_id);
|
assert_eq!(self.mir_def_id, def_id);
|
||||||
let closure_sig = substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx);
|
let closure_sig = substs.as_closure().sig(def_id, tcx);
|
||||||
let inputs_and_output = closure_sig.inputs_and_output();
|
let inputs_and_output = closure_sig.inputs_and_output();
|
||||||
let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap();
|
let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap();
|
||||||
ty::Binder::fuse(closure_ty, inputs_and_output, |closure_ty, inputs_and_output| {
|
ty::Binder::fuse(closure_ty, inputs_and_output, |closure_ty, inputs_and_output| {
|
||||||
|
|
|
@ -724,7 +724,7 @@ where
|
||||||
upvar_ty.visit_with(self);
|
upvar_ty.visit_with(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
substs.as_closure().sig_ty(def_id, self.tcx).visit_with(self);
|
substs.as_closure().sig_as_fn_ptr_ty(def_id, self.tcx).visit_with(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Generator(def_id, ref substs, _) => {
|
ty::Generator(def_id, ref substs, _) => {
|
||||||
|
|
|
@ -368,7 +368,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let self_ty = trait_ref.self_ty();
|
let self_ty = trait_ref.self_ty();
|
||||||
let (def_id, output_ty, callable) = match self_ty.kind {
|
let (def_id, output_ty, callable) = match self_ty.kind {
|
||||||
ty::Closure(def_id, substs) => {
|
ty::Closure(def_id, substs) => {
|
||||||
(def_id, self.closure_sig(def_id, substs).output(), "closure")
|
(def_id, substs.as_closure().sig(def_id, self.tcx).output(), "closure")
|
||||||
}
|
}
|
||||||
ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
|
ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
|
||||||
_ => return,
|
_ => return,
|
||||||
|
|
|
@ -1311,9 +1311,7 @@ fn confirm_closure_candidate<'cx, 'tcx>(
|
||||||
vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>,
|
vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>,
|
||||||
) -> Progress<'tcx> {
|
) -> Progress<'tcx> {
|
||||||
let tcx = selcx.tcx();
|
let tcx = selcx.tcx();
|
||||||
let infcx = selcx.infcx();
|
let closure_sig = vtable.substs.as_closure().sig(vtable.closure_def_id, tcx);
|
||||||
let closure_sig_ty = vtable.substs.as_closure().sig_ty(vtable.closure_def_id, tcx);
|
|
||||||
let closure_sig = infcx.shallow_resolve(closure_sig_ty).fn_sig(tcx);
|
|
||||||
let Normalized { value: closure_sig, obligations } = normalize_with_depth(
|
let Normalized { value: closure_sig, obligations } = normalize_with_depth(
|
||||||
selcx,
|
selcx,
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
|
|
|
@ -3349,9 +3349,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
"closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})",
|
"closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})",
|
||||||
obligation, closure_def_id, substs,
|
obligation, closure_def_id, substs,
|
||||||
);
|
);
|
||||||
let closure_type = self.infcx.closure_sig(closure_def_id, substs);
|
let closure_sig = substs.as_closure().sig(closure_def_id, self.tcx());
|
||||||
|
|
||||||
debug!("closure_trait_ref_unnormalized: closure_type = {:?}", closure_type);
|
debug!("closure_trait_ref_unnormalized: closure_sig = {:?}", closure_sig);
|
||||||
|
|
||||||
// (1) Feels icky to skip the binder here, but OTOH we know
|
// (1) Feels icky to skip the binder here, but OTOH we know
|
||||||
// that the self-type is an unboxed closure type and hence is
|
// that the self-type is an unboxed closure type and hence is
|
||||||
|
@ -3362,7 +3362,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
self.tcx(),
|
self.tcx(),
|
||||||
obligation.predicate.def_id(),
|
obligation.predicate.def_id(),
|
||||||
obligation.predicate.skip_binder().self_ty(), // (1)
|
obligation.predicate.skip_binder().self_ty(), // (1)
|
||||||
closure_type,
|
closure_sig,
|
||||||
util::TupleArgumentsFlag::No,
|
util::TupleArgumentsFlag::No,
|
||||||
)
|
)
|
||||||
.map_bound(|(trait_ref, _)| trait_ref)
|
.map_bound(|(trait_ref, _)| trait_ref)
|
||||||
|
|
|
@ -105,12 +105,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// haven't yet decided on whether the closure is fn vs
|
// haven't yet decided on whether the closure is fn vs
|
||||||
// fnmut vs fnonce. If so, we have to defer further processing.
|
// fnmut vs fnonce. If so, we have to defer further processing.
|
||||||
if self.closure_kind(def_id, substs).is_none() {
|
if self.closure_kind(def_id, substs).is_none() {
|
||||||
let closure_ty = self.closure_sig(def_id, substs);
|
let closure_sig = substs.as_closure().sig(def_id, self.tcx);
|
||||||
let fn_sig = self
|
let closure_sig = self
|
||||||
.replace_bound_vars_with_fresh_vars(
|
.replace_bound_vars_with_fresh_vars(
|
||||||
call_expr.span,
|
call_expr.span,
|
||||||
infer::FnCall,
|
infer::FnCall,
|
||||||
&closure_ty,
|
&closure_sig,
|
||||||
)
|
)
|
||||||
.0;
|
.0;
|
||||||
let adjustments = autoderef.adjust_steps(self, Needs::None);
|
let adjustments = autoderef.adjust_steps(self, Needs::None);
|
||||||
|
@ -121,12 +121,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
callee_expr,
|
callee_expr,
|
||||||
adjusted_ty,
|
adjusted_ty,
|
||||||
adjustments,
|
adjustments,
|
||||||
fn_sig,
|
fn_sig: closure_sig,
|
||||||
closure_def_id: def_id,
|
closure_def_id: def_id,
|
||||||
closure_substs: substs,
|
closure_substs: substs,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return Some(CallStep::DeferredClosure(fn_sig));
|
return Some(CallStep::DeferredClosure(closure_sig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,13 +116,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
interior,
|
interior,
|
||||||
generator_substs.witness(expr_def_id, self.tcx),
|
generator_substs.witness(expr_def_id, self.tcx),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// HACK(eddyb) this forces the types equated above into `substs` but
|
||||||
|
// it should rely on `GeneratorSubsts` providing a constructor, instead.
|
||||||
|
let substs = self.resolve_vars_if_possible(&substs);
|
||||||
|
|
||||||
return self.tcx.mk_generator(expr_def_id, substs, movability);
|
return self.tcx.mk_generator(expr_def_id, substs, movability);
|
||||||
}
|
}
|
||||||
|
|
||||||
let closure_type = self.tcx.mk_closure(expr_def_id, substs);
|
|
||||||
|
|
||||||
debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type);
|
|
||||||
|
|
||||||
// Tuple up the arguments and insert the resulting function type into
|
// Tuple up the arguments and insert the resulting function type into
|
||||||
// the `closures` table.
|
// the `closures` table.
|
||||||
let sig = bound_sig.map_bound(|sig| {
|
let sig = bound_sig.map_bound(|sig| {
|
||||||
|
@ -144,7 +145,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.demand_eqtype(
|
self.demand_eqtype(
|
||||||
expr.span,
|
expr.span,
|
||||||
sig_fn_ptr_ty,
|
sig_fn_ptr_ty,
|
||||||
substs.as_closure().sig_ty(expr_def_id, self.tcx),
|
substs.as_closure().sig_as_fn_ptr_ty(expr_def_id, self.tcx),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(kind) = opt_kind {
|
if let Some(kind) = opt_kind {
|
||||||
|
@ -155,6 +156,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HACK(eddyb) this forces the types equated above into `substs` but
|
||||||
|
// it should rely on `ClosureSubsts` providing a constructor, instead.
|
||||||
|
let substs = self.resolve_vars_if_possible(&substs);
|
||||||
|
|
||||||
|
let closure_type = self.tcx.mk_closure(expr_def_id, substs);
|
||||||
|
|
||||||
|
debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type);
|
||||||
|
|
||||||
closure_type
|
closure_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -750,9 +750,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
// `fn(arg0,arg1,...) -> _`
|
// `fn(arg0,arg1,...) -> _`
|
||||||
// or
|
// or
|
||||||
// `unsafe fn(arg0,arg1,...) -> _`
|
// `unsafe fn(arg0,arg1,...) -> _`
|
||||||
let sig = self.closure_sig(def_id_a, substs_a);
|
let closure_sig = substs_a.as_closure().sig(def_id_a, self.tcx);
|
||||||
let unsafety = fn_ty.unsafety();
|
let unsafety = fn_ty.unsafety();
|
||||||
let pointer_ty = self.tcx.coerce_closure_fn_ty(sig, unsafety);
|
let pointer_ty = self.tcx.coerce_closure_fn_ty(closure_sig, unsafety);
|
||||||
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);
|
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);
|
||||||
self.unify_and(
|
self.unify_and(
|
||||||
pointer_ty,
|
pointer_ty,
|
||||||
|
|
|
@ -4837,18 +4837,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let hir = self.tcx.hir();
|
let hir = self.tcx.hir();
|
||||||
let (def_id, sig) = match found.kind {
|
let (def_id, sig) = match found.kind {
|
||||||
ty::FnDef(def_id, _) => (def_id, found.fn_sig(self.tcx)),
|
ty::FnDef(def_id, _) => (def_id, found.fn_sig(self.tcx)),
|
||||||
ty::Closure(def_id, substs) => {
|
ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig(def_id, self.tcx)),
|
||||||
// We don't use `closure_sig` to account for malformed closures like
|
|
||||||
// `|_: [_; continue]| {}` and instead we don't suggest anything.
|
|
||||||
let closure_sig_ty = substs.as_closure().sig_ty(def_id, self.tcx);
|
|
||||||
(
|
|
||||||
def_id,
|
|
||||||
match closure_sig_ty.kind {
|
|
||||||
ty::FnPtr(sig) => sig,
|
|
||||||
_ => return false,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1527,16 +1527,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
|
||||||
// argument. In any case they are embedded within the
|
// argument. In any case they are embedded within the
|
||||||
// closure type as part of the `ClosureSubsts`.
|
// closure type as part of the `ClosureSubsts`.
|
||||||
//
|
//
|
||||||
// To get
|
// To get the signature of a closure, you should use the
|
||||||
// the signature of a closure, you should use the
|
// `sig` method on the `ClosureSubsts`:
|
||||||
// `closure_sig` method on the `ClosureSubsts`:
|
|
||||||
//
|
//
|
||||||
// closure_substs.sig(def_id, tcx)
|
// substs.as_closure().sig(def_id, tcx)
|
||||||
//
|
bug!(
|
||||||
// or, inside of an inference context, you can use
|
"to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`",
|
||||||
//
|
);
|
||||||
// infcx.closure_sig(def_id, closure_substs)
|
|
||||||
bug!("to get the signature of a closure, use `closure_sig()` not `fn_sig()`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x => {
|
x => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue