Eagerly instantiate closure ty
This commit is contained in:
parent
098d4fd74c
commit
37a5464bc8
@ -68,12 +68,58 @@ pub fn check_expr_closure(
|
|||||||
|
|
||||||
debug!(?bound_sig, ?liberated_sig);
|
debug!(?bound_sig, ?liberated_sig);
|
||||||
|
|
||||||
|
let parent_args =
|
||||||
|
GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
|
||||||
|
|
||||||
|
let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin {
|
||||||
|
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||||
|
span: expr_span,
|
||||||
|
});
|
||||||
|
|
||||||
// FIXME: We could probably actually just unify this further --
|
// FIXME: We could probably actually just unify this further --
|
||||||
// instead of having a `FnSig` and a `Option<CoroutineTypes>`,
|
// instead of having a `FnSig` and a `Option<CoroutineTypes>`,
|
||||||
// we can have a `ClosureSignature { Coroutine { .. }, Closure { .. } }`,
|
// we can have a `ClosureSignature { Coroutine { .. }, Closure { .. } }`,
|
||||||
// similar to how `ty::GenSig` is a distinct data structure.
|
// similar to how `ty::GenSig` is a distinct data structure.
|
||||||
let coroutine_types = match closure.kind {
|
let (closure_ty, coroutine_types) = match closure.kind {
|
||||||
hir::ClosureKind::Closure => None,
|
hir::ClosureKind::Closure => {
|
||||||
|
// Tuple up the arguments and insert the resulting function type into
|
||||||
|
// the `closures` table.
|
||||||
|
let sig = bound_sig.map_bound(|sig| {
|
||||||
|
tcx.mk_fn_sig(
|
||||||
|
[Ty::new_tup(tcx, sig.inputs())],
|
||||||
|
sig.output(),
|
||||||
|
sig.c_variadic,
|
||||||
|
sig.unsafety,
|
||||||
|
sig.abi,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
debug!(?sig, ?expected_kind);
|
||||||
|
|
||||||
|
let closure_kind_ty = match expected_kind {
|
||||||
|
Some(kind) => Ty::from_closure_kind(tcx, kind),
|
||||||
|
|
||||||
|
// Create a type variable (for now) to represent the closure kind.
|
||||||
|
// It will be unified during the upvar inference phase (`upvar.rs`)
|
||||||
|
None => self.next_root_ty_var(TypeVariableOrigin {
|
||||||
|
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
|
||||||
|
kind: TypeVariableOriginKind::ClosureSynthetic,
|
||||||
|
span: expr_span,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
let closure_args = ty::ClosureArgs::new(
|
||||||
|
tcx,
|
||||||
|
ty::ClosureArgsParts {
|
||||||
|
parent_args,
|
||||||
|
closure_kind_ty,
|
||||||
|
closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig),
|
||||||
|
tupled_upvars_ty,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
(Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args), None)
|
||||||
|
}
|
||||||
hir::ClosureKind::Coroutine(kind) => {
|
hir::ClosureKind::Coroutine(kind) => {
|
||||||
let yield_ty = match kind {
|
let yield_ty = match kind {
|
||||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
||||||
@ -119,74 +165,6 @@ pub fn check_expr_closure(
|
|||||||
// Resume type defaults to `()` if the coroutine has no argument.
|
// Resume type defaults to `()` if the coroutine has no argument.
|
||||||
let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
|
let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit);
|
||||||
|
|
||||||
Some(CoroutineTypes { resume_ty, yield_ty })
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
check_fn(
|
|
||||||
&mut FnCtxt::new(self, self.param_env, closure.def_id),
|
|
||||||
liberated_sig,
|
|
||||||
coroutine_types,
|
|
||||||
closure.fn_decl,
|
|
||||||
expr_def_id,
|
|
||||||
body,
|
|
||||||
// Closure "rust-call" ABI doesn't support unsized params
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let parent_args =
|
|
||||||
GenericArgs::identity_for_item(tcx, tcx.typeck_root_def_id(expr_def_id.to_def_id()));
|
|
||||||
|
|
||||||
let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin {
|
|
||||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
|
||||||
span: expr_span,
|
|
||||||
});
|
|
||||||
|
|
||||||
match closure.kind {
|
|
||||||
hir::ClosureKind::Closure => {
|
|
||||||
assert_eq!(coroutine_types, None);
|
|
||||||
// Tuple up the arguments and insert the resulting function type into
|
|
||||||
// the `closures` table.
|
|
||||||
let sig = bound_sig.map_bound(|sig| {
|
|
||||||
tcx.mk_fn_sig(
|
|
||||||
[Ty::new_tup(tcx, sig.inputs())],
|
|
||||||
sig.output(),
|
|
||||||
sig.c_variadic,
|
|
||||||
sig.unsafety,
|
|
||||||
sig.abi,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
debug!(?sig, ?expected_kind);
|
|
||||||
|
|
||||||
let closure_kind_ty = match expected_kind {
|
|
||||||
Some(kind) => Ty::from_closure_kind(tcx, kind),
|
|
||||||
|
|
||||||
// Create a type variable (for now) to represent the closure kind.
|
|
||||||
// It will be unified during the upvar inference phase (`upvar.rs`)
|
|
||||||
None => self.next_root_ty_var(TypeVariableOrigin {
|
|
||||||
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
|
|
||||||
kind: TypeVariableOriginKind::ClosureSynthetic,
|
|
||||||
span: expr_span,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
let closure_args = ty::ClosureArgs::new(
|
|
||||||
tcx,
|
|
||||||
ty::ClosureArgsParts {
|
|
||||||
parent_args,
|
|
||||||
closure_kind_ty,
|
|
||||||
closure_sig_as_fn_ptr_ty: Ty::new_fn_ptr(tcx, sig),
|
|
||||||
tupled_upvars_ty,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
Ty::new_closure(tcx, expr_def_id.to_def_id(), closure_args.args)
|
|
||||||
}
|
|
||||||
hir::ClosureKind::Coroutine(_) => {
|
|
||||||
let Some(CoroutineTypes { resume_ty, yield_ty }) = coroutine_types else {
|
|
||||||
bug!("expected coroutine to have yield/resume types");
|
|
||||||
};
|
|
||||||
let interior = self.next_ty_var(TypeVariableOrigin {
|
let interior = self.next_ty_var(TypeVariableOrigin {
|
||||||
kind: TypeVariableOriginKind::MiscVariable,
|
kind: TypeVariableOriginKind::MiscVariable,
|
||||||
span: body.value.span,
|
span: body.value.span,
|
||||||
@ -209,9 +187,25 @@ pub fn check_expr_closure(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args)
|
(
|
||||||
|
Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args),
|
||||||
|
Some(CoroutineTypes { resume_ty, yield_ty }),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
check_fn(
|
||||||
|
&mut FnCtxt::new(self, self.param_env, closure.def_id),
|
||||||
|
liberated_sig,
|
||||||
|
coroutine_types,
|
||||||
|
closure.fn_decl,
|
||||||
|
expr_def_id,
|
||||||
|
body,
|
||||||
|
// Closure "rust-call" ABI doesn't support unsized params
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
closure_ty
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given the expected type, figures out what it can about this closure we
|
/// Given the expected type, figures out what it can about this closure we
|
||||||
@ -683,10 +677,10 @@ fn supplied_sig_of_closure(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
// All `gen {}` and `async gen {}` must return unit.
|
// All `gen {}` and `async gen {}` must return unit.
|
||||||
hir::ClosureKind::Coroutine(
|
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
|
||||||
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
|
hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen,
|
||||||
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
|
_,
|
||||||
) => self.tcx.types.unit,
|
)) => self.tcx.types.unit,
|
||||||
|
|
||||||
// For async blocks, we just fall back to `_` here.
|
// For async blocks, we just fall back to `_` here.
|
||||||
// For closures/coroutines, we know nothing about the return
|
// For closures/coroutines, we know nothing about the return
|
||||||
|
@ -9,7 +9,7 @@ LL | let c1 : () = c;
|
|||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found closure `{mod1::f<T>::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}`
|
found closure `{mod1::f<T>::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}`
|
||||||
help: use parentheses to call this closure
|
help: use parentheses to call this closure
|
||||||
|
|
|
|
||||||
LL | let c1 : () = c();
|
LL | let c1 : () = c();
|
||||||
|
@ -9,7 +9,7 @@ LL | let c1 : () = c;
|
|||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found closure `{f<T>::{closure#0} closure_args=(unavailable) args=[T, ?16t, extern "rust-call" fn(()), ?15t]}`
|
found closure `{f<T>::{closure#0} closure_args=(unavailable) args=[T, ?8t, extern "rust-call" fn(()), ?7t]}`
|
||||||
help: use parentheses to call this closure
|
help: use parentheses to call this closure
|
||||||
|
|
|
|
||||||
LL | let c1 : () = c();
|
LL | let c1 : () = c();
|
||||||
|
@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
|
|||||||
| expected due to this
|
| expected due to this
|
||||||
|
|
|
|
||||||
= note: expected fn pointer `fn(u8) -> u8`
|
= note: expected fn pointer `fn(u8) -> u8`
|
||||||
found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?6t]}`
|
found closure `{main::{closure#0} closure_args=(unavailable) args=[i8, extern "rust-call" fn((u8,)) -> u8, ?4t]}`
|
||||||
note: closures can only be coerced to `fn` types if they do not capture any variables
|
note: closures can only be coerced to `fn` types if they do not capture any variables
|
||||||
--> $DIR/closure-print-verbose.rs:10:39
|
--> $DIR/closure-print-verbose.rs:10:39
|
||||||
|
|
|
|
||||||
|
Loading…
Reference in New Issue
Block a user