use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
use crate::astconv::AstConv;
-use crate::rustc_middle::ty::subst::Subst;
-use hir::OpaqueTyOrigin;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::infer::{InferOk, InferResult};
-use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Span;
-use rustc_span::DUMMY_SP;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::ArgKind;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
expected_ty: Ty<'tcx>,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
match *expected_ty.kind() {
- ty::Opaque(def_id, substs) => {
- let bounds = self.tcx.explicit_item_bounds(def_id);
- let sig = bounds.iter().find_map(|(pred, span)| match pred.kind().skip_binder() {
- ty::PredicateKind::Projection(proj_predicate) => self
- .deduce_sig_from_projection(
- Some(*span),
- pred.kind().rebind(proj_predicate.subst(self.tcx, substs)),
- ),
- _ => None,
- });
-
- let kind = bounds
- .iter()
- .filter_map(|(pred, _)| match pred.kind().skip_binder() {
- ty::PredicateKind::Trait(tp) => {
- self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
- }
- _ => None,
- })
- .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
- trace!(?sig, ?kind);
- (sig, kind)
- }
ty::Dynamic(ref object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| {
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
let expected_sig =
self.obligations_for_self_ty(expected_vid).find_map(|(_, obligation)| {
- debug!(?obligation.predicate);
+ debug!(
+ "deduce_expectations_from_obligations: obligation.predicate={:?}",
+ obligation.predicate
+ );
let bound_predicate = obligation.predicate.kind();
if let ty::PredicateKind::Projection(proj_predicate) =
// in this binder we are creating.
assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST));
let bound_sig = expected_sig.sig.map_bound(|sig| {
- let output = self.hide_parent_opaque_types(
- sig.output(),
- expected_sig.cause_span.unwrap_or(DUMMY_SP),
- body.id().hir_id,
- );
self.tcx.mk_fn_sig(
sig.inputs().iter().cloned(),
- output,
+ sig.output(),
sig.c_variadic,
hir::Unsafety::Normal,
Abi::RustCall,
.skip_binder()
.inputs()
.iter()
- .map(|ty| ArgKind::from_expected_ty(ty, None))
+ .map(|ty| ArgKind::from_expected_ty(*ty, None))
.collect();
let (closure_span, found_args) = match self.get_fn_like_arguments(expr_map_node) {
Some((sp, args)) => (Some(sp), args),
_ => astconv.ty_infer(None, decl.output.span()),
},
};
- let supplied_return =
- self.hide_parent_opaque_types(supplied_return, decl.output.span(), body.id().hir_id);
let result = ty::Binder::bind_with_vars(
self.tcx.mk_fn_sig(
result
}
- fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
- ty.fold_with(&mut ty::fold::BottomUpFolder {
- tcx: self.infcx.tcx,
- lt_op: |lt| lt,
- ct_op: |ct| ct,
- ty_op: |ty| match *ty.kind() {
- // Closures can't create hidden types for opaque types of their parent, as they
- // do not have all the outlives information available. Also `type_of` looks for
- // hidden types in the owner (so the closure's parent), so it would not find these
- // definitions.
- ty::Opaque(def_id, _substs)
- if matches!(
- self.infcx.opaque_type_origin(def_id, DUMMY_SP),
- Some(OpaqueTyOrigin::FnReturn(..))
- ) =>
- {
- let ty_var = self.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::TypeInference,
- span,
- });
- let cause = ObligationCause::misc(span, body_id);
- self.register_predicates(vec![self.infcx.opaque_ty_obligation(
- ty,
- ty_var,
- true,
- self.param_env,
- cause,
- )]);
- ty_var
- }
- _ => ty,
- },
- })
- }
-
/// Invoked when we are translating the generator that results
/// from desugaring an `async fn`. Returns the "sugared" return
/// type of the `async fn` -- that is, the return type that the
/// user specified. The "desugared" return type is an `impl
/// Future<Output = T>`, so we do this by searching through the
/// obligations to extract the `T`.
- #[instrument(skip(self), level = "debug")]
fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option<Ty<'tcx>> {
+ debug!("deduce_future_output_from_obligations(expr_def_id={:?})", expr_def_id);
+
let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn")
});
+ // In practice, the return type of the surrounding function is
+ // always a (not yet resolved) inference variable, because it
+ // is the hidden type for an `impl Trait` that we are going to
+ // be inferring.
let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
- let (def_id, substs) = match *ret_ty.kind() {
- ty::Opaque(def_id, substs) => (def_id, substs),
+ let ret_vid = match *ret_ty.kind() {
+ ty::Infer(ty::TyVar(ret_vid)) => ret_vid,
ty::Error(_) => return None,
_ => span_bug!(
self.tcx.def_span(expr_def_id),
),
};
- let item_bounds = self.tcx.explicit_item_bounds(def_id);
-
// Search for a pending obligation like
//
// `<R as Future>::Output = T`
//
// where R is the return type we are expecting. This type `T`
// will be our output.
- let output_ty = item_bounds.iter().find_map(|&(predicate, span)| {
- let bound_predicate = predicate.subst(self.tcx, substs).kind();
+ let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
+ let bound_predicate = obligation.predicate.kind();
if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() {
self.deduce_future_output_from_projection(
- span,
+ obligation.cause.span,
bound_predicate.rebind(proj_predicate),
)
} else {