Skip to content

Commit c33b127

Browse files
committed
The only reason we had to replace opaque types in closures was due to async fn desugaring, make that explicit
1 parent 77e88a7 commit c33b127

File tree

3 files changed

+35
-67
lines changed

3 files changed

+35
-67
lines changed

compiler/rustc_infer/src/infer/opaque_types.rs

+4-22
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use hir::{HirId, OpaqueTyOrigin};
55
use rustc_data_structures::sync::Lrc;
66
use rustc_data_structures::vec_map::VecMap;
77
use rustc_hir as hir;
8-
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
8+
use rustc_middle::traits::ObligationCause;
99
use rustc_middle::ty::fold::BottomUpFolder;
1010
use rustc_middle::ty::subst::{GenericArgKind, Subst};
1111
use rustc_middle::ty::{
@@ -38,38 +38,19 @@ pub struct OpaqueTypeDecl<'tcx> {
3838
pub origin: hir::OpaqueTyOrigin,
3939
}
4040

41-
pub enum ReplaceOpaqueTypes {
42-
/// Closures can't create hidden types for opaque types of their parent, as they
43-
/// do not have all the outlives information available. Also `type_of` looks for
44-
/// hidden types in the owner (so the closure's parent), so it would not find these
45-
/// definitions.
46-
OnlyForRPIT,
47-
All,
48-
}
49-
5041
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
5142
pub fn replace_opaque_types_with_inference_vars(
5243
&self,
5344
ty: Ty<'tcx>,
5445
body_id: HirId,
5546
span: Span,
56-
code: ObligationCauseCode<'tcx>,
5747
param_env: ty::ParamEnv<'tcx>,
58-
replace: ReplaceOpaqueTypes,
5948
) -> InferOk<'tcx, Ty<'tcx>> {
6049
if !ty.has_opaque_types() {
6150
return InferOk { value: ty, obligations: vec![] };
6251
}
6352
let mut obligations = vec![];
64-
let replace_opaque_type = |def_id| match self.opaque_type_origin(def_id, span) {
65-
None => false,
66-
Some(OpaqueTyOrigin::FnReturn(..)) => true,
67-
// Not using `==` or `matches!` here to make sure we exhaustively match variants.
68-
Some(_) => match replace {
69-
ReplaceOpaqueTypes::OnlyForRPIT => false,
70-
ReplaceOpaqueTypes::All => true,
71-
},
72-
};
53+
let replace_opaque_type = |def_id| self.opaque_type_origin(def_id, span).is_some();
7354
let value = ty.fold_with(&mut ty::fold::BottomUpFolder {
7455
tcx: self.tcx,
7556
lt_op: |lt| lt,
@@ -78,7 +59,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
7859
ty::Opaque(def_id, _substs) if replace_opaque_type(def_id) => {
7960
let def_span = self.tcx.def_span(def_id);
8061
let span = if span.contains(def_span) { def_span } else { span };
81-
let cause = ObligationCause::new(span, body_id, code.clone());
62+
let code = traits::ObligationCauseCode::OpaqueReturnType(None);
63+
let cause = ObligationCause::new(span, body_id, code);
8264
// FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
8365
// for opaque types, and then use that kind to fix the spans for type errors
8466
// that we see later on.

compiler/rustc_typeck/src/check/check.rs

-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
1313
use rustc_hir::intravisit::Visitor;
1414
use rustc_hir::lang_items::LangItem;
1515
use rustc_hir::{ItemKind, Node, PathSegment};
16-
use rustc_infer::infer::opaque_types::ReplaceOpaqueTypes;
1716
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1817
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1918
use rustc_infer::traits::Obligation;
@@ -97,9 +96,7 @@ pub(super) fn check_fn<'a, 'tcx>(
9796
declared_ret_ty,
9897
body.value.hir_id,
9998
decl.output.span(),
100-
traits::ObligationCauseCode::OpaqueReturnType(None),
10199
param_env,
102-
ReplaceOpaqueTypes::All,
103100
));
104101
// If we replaced declared_ret_ty with infer vars, then we must be infering
105102
// an opaque type, so set a flag so we can improve diagnostics.

compiler/rustc_typeck/src/check/closure.rs

+31-42
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@ use crate::rustc_middle::ty::subst::Subst;
77
use rustc_hir as hir;
88
use rustc_hir::def_id::DefId;
99
use rustc_hir::lang_items::LangItem;
10-
use rustc_infer::infer::opaque_types::ReplaceOpaqueTypes;
1110
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1211
use rustc_infer::infer::LateBoundRegionConversionTime;
1312
use rustc_infer::infer::{InferOk, InferResult};
14-
use rustc_infer::traits::ObligationCauseCode;
1513
use rustc_middle::ty::fold::TypeFoldable;
1614
use rustc_middle::ty::subst::InternalSubsts;
1715
use rustc_middle::ty::{self, Ty};
1816
use rustc_span::source_map::Span;
19-
use rustc_span::DUMMY_SP;
2017
use rustc_target::spec::abi::Abi;
2118
use rustc_trait_selection::traits::error_reporting::ArgKind;
2219
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
@@ -430,14 +427,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
430427
// in this binder we are creating.
431428
assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST));
432429
let bound_sig = expected_sig.sig.map_bound(|sig| {
433-
let output = self.hide_parent_opaque_types(
434-
sig.output(),
435-
expected_sig.cause_span.unwrap_or(DUMMY_SP),
436-
body.id().hir_id,
437-
);
438430
self.tcx.mk_fn_sig(
439431
sig.inputs().iter().cloned(),
440-
output,
432+
sig.output(),
441433
sig.c_variadic,
442434
hir::Unsafety::Normal,
443435
Abi::RustCall,
@@ -609,23 +601,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
609601
// function.
610602
Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => {
611603
debug!("closure is async fn body");
612-
self.deduce_future_output_from_obligations(expr_def_id).unwrap_or_else(|| {
613-
// AFAIK, deducing the future output
614-
// always succeeds *except* in error cases
615-
// like #65159. I'd like to return Error
616-
// here, but I can't because I can't
617-
// easily (and locally) prove that we
618-
// *have* reported an
619-
// error. --nikomatsakis
620-
astconv.ty_infer(None, decl.output.span())
621-
})
604+
self.deduce_future_output_from_obligations(expr_def_id, body.id().hir_id)
605+
.unwrap_or_else(|| {
606+
// AFAIK, deducing the future output
607+
// always succeeds *except* in error cases
608+
// like #65159. I'd like to return Error
609+
// here, but I can't because I can't
610+
// easily (and locally) prove that we
611+
// *have* reported an
612+
// error. --nikomatsakis
613+
astconv.ty_infer(None, decl.output.span())
614+
})
622615
}
623616

624617
_ => astconv.ty_infer(None, decl.output.span()),
625618
},
626619
};
627-
let supplied_return =
628-
self.hide_parent_opaque_types(supplied_return, decl.output.span(), body.id().hir_id);
629620

630621
let result = ty::Binder::bind_with_vars(
631622
self.tcx.mk_fn_sig(
@@ -646,31 +637,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
646637
result
647638
}
648639

649-
/// Closures can't create hidden types for opaque types of their parent, as they
650-
/// do not have all the outlives information available. Also `type_of` looks for
651-
/// hidden types in the owner (so the closure's parent), so it would not find these
652-
/// definitions.
653-
fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
654-
let InferOk { value, obligations } = self.replace_opaque_types_with_inference_vars(
655-
ty,
656-
body_id,
657-
span,
658-
ObligationCauseCode::MiscObligation,
659-
self.param_env,
660-
ReplaceOpaqueTypes::OnlyForRPIT,
661-
);
662-
self.register_predicates(obligations);
663-
value
664-
}
665-
666640
/// Invoked when we are translating the generator that results
667641
/// from desugaring an `async fn`. Returns the "sugared" return
668642
/// type of the `async fn` -- that is, the return type that the
669643
/// user specified. The "desugared" return type is an `impl
670644
/// Future<Output = T>`, so we do this by searching through the
671645
/// obligations to extract the `T`.
672646
#[instrument(skip(self), level = "debug")]
673-
fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option<Ty<'tcx>> {
647+
fn deduce_future_output_from_obligations(
648+
&self,
649+
expr_def_id: DefId,
650+
body_id: hir::HirId,
651+
) -> Option<Ty<'tcx>> {
674652
let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
675653
span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn")
676654
});
@@ -700,23 +678,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
700678
ty::Infer(ty::TyVar(ret_vid)) => {
701679
self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
702680
get_future_output(obligation.predicate, obligation.cause.span)
703-
})
681+
})?
704682
}
705683
ty::Opaque(def_id, substs) => self
706684
.tcx
707685
.bound_explicit_item_bounds(def_id)
708686
.transpose_iter()
709687
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
710-
.find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0)),
688+
.find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?,
711689
ty::Error(_) => return None,
712690
_ => span_bug!(
713691
self.tcx.def_span(expr_def_id),
714692
"async fn generator return type not an inference variable"
715693
),
716694
};
717695

696+
// async fn that have opaque types in their return type need to redo the conversion to inference variables
697+
// as they fetch the still opaque version from the signature.
698+
let InferOk { value: output_ty, obligations } = self
699+
.replace_opaque_types_with_inference_vars(
700+
output_ty,
701+
body_id,
702+
self.tcx.def_span(expr_def_id),
703+
self.param_env,
704+
);
705+
self.register_predicates(obligations);
706+
718707
debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty);
719-
output_ty
708+
Some(output_ty)
720709
}
721710

722711
/// Given a projection like

0 commit comments

Comments
 (0)