about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-06-29 08:52:19 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-06-29 08:58:36 +0000
commitc33b127d7c25977817faaae5eee84d57cde37c68 (patch)
tree11a14bb09ef713e1544a6209a50af016ef69b4d3
parent77e88a7c7afce2389b16b385f494be2f836c43ff (diff)
The only reason we had to replace opaque types in closures was due to async fn desugaring, make that explicit
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs26
-rw-r--r--compiler/rustc_typeck/src/check/check.rs3
-rw-r--r--compiler/rustc_typeck/src/check/closure.rs73
3 files changed, 35 insertions, 67 deletions
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 7d7fa9f2941..cc36d6a0a4f 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -5,7 +5,7 @@ use hir::{HirId, OpaqueTyOrigin};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::vec_map::VecMap;
 use rustc_hir as hir;
-use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::subst::{GenericArgKind, Subst};
 use rustc_middle::ty::{
@@ -38,38 +38,19 @@ pub struct OpaqueTypeDecl<'tcx> {
     pub origin: hir::OpaqueTyOrigin,
 }
 
-pub enum ReplaceOpaqueTypes {
-    /// 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.
-    OnlyForRPIT,
-    All,
-}
-
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn replace_opaque_types_with_inference_vars(
         &self,
         ty: Ty<'tcx>,
         body_id: HirId,
         span: Span,
-        code: ObligationCauseCode<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        replace: ReplaceOpaqueTypes,
     ) -> InferOk<'tcx, Ty<'tcx>> {
         if !ty.has_opaque_types() {
             return InferOk { value: ty, obligations: vec![] };
         }
         let mut obligations = vec![];
-        let replace_opaque_type = |def_id| match self.opaque_type_origin(def_id, span) {
-            None => false,
-            Some(OpaqueTyOrigin::FnReturn(..)) => true,
-            // Not using `==` or `matches!` here to make sure we exhaustively match variants.
-            Some(_) => match replace {
-                ReplaceOpaqueTypes::OnlyForRPIT => false,
-                ReplaceOpaqueTypes::All => true,
-            },
-        };
+        let replace_opaque_type = |def_id| self.opaque_type_origin(def_id, span).is_some();
         let value = ty.fold_with(&mut ty::fold::BottomUpFolder {
             tcx: self.tcx,
             lt_op: |lt| lt,
@@ -78,7 +59,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 ty::Opaque(def_id, _substs) if replace_opaque_type(def_id) => {
                     let def_span = self.tcx.def_span(def_id);
                     let span = if span.contains(def_span) { def_span } else { span };
-                    let cause = ObligationCause::new(span, body_id, code.clone());
+                    let code = traits::ObligationCauseCode::OpaqueReturnType(None);
+                    let cause = ObligationCause::new(span, body_id, code);
                     // FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
                     // for opaque types, and then use that kind to fix the spans for type errors
                     // that we see later on.
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 184bc4188c5..1cd66d1426d 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -13,7 +13,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ItemKind, Node, PathSegment};
-use rustc_infer::infer::opaque_types::ReplaceOpaqueTypes;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
@@ -97,9 +96,7 @@ pub(super) fn check_fn<'a, 'tcx>(
             declared_ret_ty,
             body.value.hir_id,
             decl.output.span(),
-            traits::ObligationCauseCode::OpaqueReturnType(None),
             param_env,
-            ReplaceOpaqueTypes::All,
         ));
     // If we replaced declared_ret_ty with infer vars, then we must be infering
     // an opaque type, so set a flag so we can improve diagnostics.
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs
index 918a42cf02b..131e594ed94 100644
--- a/compiler/rustc_typeck/src/check/closure.rs
+++ b/compiler/rustc_typeck/src/check/closure.rs
@@ -7,16 +7,13 @@ use crate::rustc_middle::ty::subst::Subst;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_infer::infer::opaque_types::ReplaceOpaqueTypes;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_infer::infer::{InferOk, InferResult};
-use rustc_infer::traits::ObligationCauseCode;
 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 _;
@@ -430,14 +427,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // 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,
@@ -609,23 +601,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // function.
                 Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => {
                     debug!("closure is async fn body");
-                    self.deduce_future_output_from_obligations(expr_def_id).unwrap_or_else(|| {
-                        // AFAIK, deducing the future output
-                        // always succeeds *except* in error cases
-                        // like #65159. I'd like to return Error
-                        // here, but I can't because I can't
-                        // easily (and locally) prove that we
-                        // *have* reported an
-                        // error. --nikomatsakis
-                        astconv.ty_infer(None, decl.output.span())
-                    })
+                    self.deduce_future_output_from_obligations(expr_def_id, body.id().hir_id)
+                        .unwrap_or_else(|| {
+                            // AFAIK, deducing the future output
+                            // always succeeds *except* in error cases
+                            // like #65159. I'd like to return Error
+                            // here, but I can't because I can't
+                            // easily (and locally) prove that we
+                            // *have* reported an
+                            // error. --nikomatsakis
+                            astconv.ty_infer(None, decl.output.span())
+                        })
                 }
 
                 _ => 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(
@@ -646,23 +637,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         result
     }
 
-    /// 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.
-    fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
-        let InferOk { value, obligations } = self.replace_opaque_types_with_inference_vars(
-            ty,
-            body_id,
-            span,
-            ObligationCauseCode::MiscObligation,
-            self.param_env,
-            ReplaceOpaqueTypes::OnlyForRPIT,
-        );
-        self.register_predicates(obligations);
-        value
-    }
-
     /// 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
@@ -670,7 +644,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// 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>> {
+    fn deduce_future_output_from_obligations(
+        &self,
+        expr_def_id: DefId,
+        body_id: hir::HirId,
+    ) -> Option<Ty<'tcx>> {
         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")
         });
@@ -700,14 +678,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Infer(ty::TyVar(ret_vid)) => {
                 self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
                     get_future_output(obligation.predicate, obligation.cause.span)
-                })
+                })?
             }
             ty::Opaque(def_id, substs) => self
                 .tcx
                 .bound_explicit_item_bounds(def_id)
                 .transpose_iter()
                 .map(|e| e.map_bound(|e| *e).transpose_tuple2())
-                .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0)),
+                .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?,
             ty::Error(_) => return None,
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
@@ -715,8 +693,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ),
         };
 
+        // async fn that have opaque types in their return type need to redo the conversion to inference variables
+        // as they fetch the still opaque version from the signature.
+        let InferOk { value: output_ty, obligations } = self
+            .replace_opaque_types_with_inference_vars(
+                output_ty,
+                body_id,
+                self.tcx.def_span(expr_def_id),
+                self.param_env,
+            );
+        self.register_predicates(obligations);
+
         debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty);
-        output_ty
+        Some(output_ty)
     }
 
     /// Given a projection like