1
Fork 0

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:
Mazdak Farrokhzad 2020-03-21 08:51:18 +01:00 committed by GitHub
commit a6d0c35e86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 51 additions and 76 deletions

View file

@ -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())
)); ));
} }

View file

@ -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),
} }
} }

View file

@ -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.

View file

@ -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: \

View file

@ -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);

View file

@ -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| {

View file

@ -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, _) => {

View file

@ -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,

View file

@ -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,

View file

@ -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)

View file

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

View file

@ -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
} }

View file

@ -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,

View file

@ -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,
}; };

View file

@ -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 => {