about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-01-14 02:00:45 +0000
committerMichael Goulet <michael@errs.io>2024-01-17 00:43:44 +0000
commit37a5464bc8e630beee4377ec7ccc0ee912291907 (patch)
treee66706a01a6701339e8efecd9a7d525bf051b282
parent098d4fd74c078b12bfc2e9438a2a04bc18b393bc (diff)
downloadrust-37a5464bc8e630beee4377ec7ccc0ee912291907.tar.gz
rust-37a5464bc8e630beee4377ec7ccc0ee912291907.zip
Eagerly instantiate closure ty
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs146
-rw-r--r--tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr2
-rw-r--r--tests/ui/closures/print/closure-print-generic-verbose-2.stderr2
-rw-r--r--tests/ui/closures/print/closure-print-verbose.stderr2
4 files changed, 73 insertions, 79 deletions
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 57fdfa4ecb6..d11198d7fd4 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -68,12 +68,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         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 --
         // instead of having a `FnSig` and a `Option<CoroutineTypes>`,
         // we can have a `ClosureSignature { Coroutine { .. }, Closure { .. } }`,
         // similar to how `ty::GenSig` is a distinct data structure.
-        let coroutine_types = match closure.kind {
-            hir::ClosureKind::Closure => None,
+        let (closure_ty, coroutine_types) = match closure.kind {
+            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) => {
                 let yield_ty = match kind {
                     hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
@@ -119,74 +165,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Resume type defaults to `()` if the coroutine has no argument.
                 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 {
                     kind: TypeVariableOriginKind::MiscVariable,
                     span: body.value.span,
@@ -209,9 +187,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     },
                 );
 
-                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
@@ -683,10 +677,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     })
                 }
                 // All `gen {}` and `async gen {}` must return unit.
-                hir::ClosureKind::Coroutine(
-                    hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
-                    | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
-                ) => self.tcx.types.unit,
+                hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
+                    hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen,
+                    _,
+                )) => self.tcx.types.unit,
 
                 // For async blocks, we just fall back to `_` here.
                 // For closures/coroutines, we know nothing about the return
diff --git a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
index 1a13255429f..02d75ff1228 100644
--- a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
+++ b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = 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
    |
 LL |         let c1 : () = c();
diff --git a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr
index 8553817247d..a5367688989 100644
--- a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr
+++ b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr
@@ -9,7 +9,7 @@ LL |         let c1 : () = c;
    |                  expected due to this
    |
    = 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
    |
 LL |         let c1 : () = c();
diff --git a/tests/ui/closures/print/closure-print-verbose.stderr b/tests/ui/closures/print/closure-print-verbose.stderr
index 3d0af5eb171..fca8f25792a 100644
--- a/tests/ui/closures/print/closure-print-verbose.stderr
+++ b/tests/ui/closures/print/closure-print-verbose.stderr
@@ -7,7 +7,7 @@ LL |     let foo: fn(u8) -> u8 = |v: u8| { a += v; a };
    |              expected due to this
    |
    = 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
   --> $DIR/closure-print-verbose.rs:10:39
    |