about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-11-23 19:38:22 +0000
committerMichael Goulet <michael@errs.io>2022-11-26 05:38:43 +0000
commit62108124946582e7536d84adedc1507e5c35e8fd (patch)
tree7173e75c1cbff2c47ad352cc2b0982c598f424d0
parentaff003becd8b6bf803202e958623031274ad69c9 (diff)
downloadrust-62108124946582e7536d84adedc1507e5c35e8fd.tar.gz
rust-62108124946582e7536d84adedc1507e5c35e8fd.zip
Do not record unresolved const vars in generator interior
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs14
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs13
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs86
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs9
-rw-r--r--src/test/ui/generator/unresolved-ct-var.rs14
-rw-r--r--src/test/ui/generator/unresolved-ct-var.stderr78
7 files changed, 173 insertions, 43 deletions
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 30d2c63fd84..50722c42a6c 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -98,8 +98,8 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
                 expr, scope, ty, self.expr_count, yield_data.span
             );
 
-            if let Some((unresolved_type, unresolved_type_span)) =
-                self.fcx.unresolved_type_vars(&ty)
+            if let Some((unresolved_term, unresolved_type_span)) =
+                self.fcx.first_unresolved_const_or_ty_var(&ty)
             {
                 // If unresolved type isn't a ty_var then unresolved_type_span is None
                 let span = self
@@ -108,13 +108,13 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
 
                 // If we encounter an int/float variable, then inference fallback didn't
                 // finish due to some other error. Don't emit spurious additional errors.
-                if let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) =
-                    unresolved_type.kind()
+                if let Some(unresolved_ty) = unresolved_term.ty()
+                    && let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) = unresolved_ty.kind()
                 {
                     self.fcx
                         .tcx
                         .sess
-                        .delay_span_bug(span, &format!("Encountered var {:?}", unresolved_type));
+                        .delay_span_bug(span, &format!("Encountered var {:?}", unresolved_term));
                 } else {
                     let note = format!(
                         "the type is part of the {} because of this {}",
@@ -122,7 +122,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
                     );
 
                     self.fcx
-                        .need_type_info_err_in_generator(self.kind, span, unresolved_type)
+                        .need_type_info_err_in_generator(self.kind, span, unresolved_term)
                         .span_note(yield_data.span, &*note)
                         .emit();
                 }
@@ -162,7 +162,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
                 expr.map(|e| e.span)
             );
             if let Some((unresolved_type, unresolved_type_span)) =
-                self.fcx.unresolved_type_vars(&ty)
+                self.fcx.first_unresolved_const_or_ty_var(&ty)
             {
                 debug!(
                     "remained unresolved_type = {:?}, unresolved_type_span: {:?}",
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 7b3178e610f..8c63f553141 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -571,7 +571,7 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         kind: hir::GeneratorKind,
         span: Span,
-        ty: Ty<'tcx>,
+        ty: ty::Term<'tcx>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let ty = self.resolve_vars_if_possible(ty);
         let data = self.extract_inference_diagnostics_data(ty.into(), None);
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 67feb83faac..cda9299dcb6 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1421,16 +1421,15 @@ impl<'tcx> InferCtxt<'tcx> {
         value.fold_with(&mut r)
     }
 
-    /// Returns the first unresolved variable contained in `T`. In the
-    /// process of visiting `T`, this will resolve (where possible)
-    /// type variables in `T`, but it never constructs the final,
-    /// resolved type, so it's more efficient than
-    /// `resolve_vars_if_possible()`.
-    pub fn unresolved_type_vars<T>(&self, value: &T) -> Option<(Ty<'tcx>, Option<Span>)>
+    /// Returns the first unresolved type or const variable contained in `T`.
+    pub fn first_unresolved_const_or_ty_var<T>(
+        &self,
+        value: &T,
+    ) -> Option<(ty::Term<'tcx>, Option<Span>)>
     where
         T: TypeVisitable<'tcx>,
     {
-        value.visit_with(&mut resolve::UnresolvedTypeFinder::new(self)).break_value()
+        value.visit_with(&mut resolve::UnresolvedTypeOrConstFinder::new(self)).break_value()
     }
 
     pub fn probe_const_var(
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 4db4ff2388d..8671f8d45a9 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -1,5 +1,6 @@
 use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use super::{FixupError, FixupResult, InferCtxt, Span};
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor};
 use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable, TypeVisitable};
@@ -110,48 +111,77 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
 /// type variables that don't yet have a value. The first unresolved type is stored.
 /// It does not construct the fully resolved type (which might
 /// involve some hashing and so forth).
-pub struct UnresolvedTypeFinder<'a, 'tcx> {
+pub struct UnresolvedTypeOrConstFinder<'a, 'tcx> {
     infcx: &'a InferCtxt<'tcx>,
 }
 
-impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
+impl<'a, 'tcx> UnresolvedTypeOrConstFinder<'a, 'tcx> {
     pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
-        UnresolvedTypeFinder { infcx }
+        UnresolvedTypeOrConstFinder { infcx }
     }
 }
 
-impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
-    type BreakTy = (Ty<'tcx>, Option<Span>);
+impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeOrConstFinder<'a, 'tcx> {
+    type BreakTy = (ty::Term<'tcx>, Option<Span>);
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         let t = self.infcx.shallow_resolve(t);
-        if t.has_infer_types() {
-            if let ty::Infer(infer_ty) = *t.kind() {
-                // Since we called `shallow_resolve` above, this must
-                // be an (as yet...) unresolved inference variable.
-                let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
-                    let mut inner = self.infcx.inner.borrow_mut();
-                    let ty_vars = &inner.type_variables();
-                    if let TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
-                        span,
-                    } = *ty_vars.var_origin(ty_vid)
-                    {
-                        Some(span)
-                    } else {
-                        None
-                    }
+        if let ty::Infer(infer_ty) = *t.kind() {
+            // Since we called `shallow_resolve` above, this must
+            // be an (as yet...) unresolved inference variable.
+            let ty_var_span = if let ty::TyVar(ty_vid) = infer_ty {
+                let mut inner = self.infcx.inner.borrow_mut();
+                let ty_vars = &inner.type_variables();
+                if let TypeVariableOrigin {
+                    kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
+                    span,
+                } = *ty_vars.var_origin(ty_vid)
+                {
+                    Some(span)
                 } else {
                     None
-                };
-                ControlFlow::Break((t, ty_var_span))
+                }
             } else {
-                // Otherwise, visit its contents.
-                t.super_visit_with(self)
-            }
+                None
+            };
+            ControlFlow::Break((t.into(), ty_var_span))
+        } else if !t.has_non_region_infer() {
+            // All const/type variables in inference types must already be resolved,
+            // no need to visit the contents.
+            ControlFlow::CONTINUE
         } else {
-            // All type variables in inference types must already be resolved,
-            // - no need to visit the contents, continue visiting.
+            // Otherwise, keep visiting.
+            t.super_visit_with(self)
+        }
+    }
+
+    fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+        let ct = self.infcx.shallow_resolve(ct);
+        if let ty::ConstKind::Infer(i) = ct.kind() {
+            // Since we called `shallow_resolve` above, this must
+            // be an (as yet...) unresolved inference variable.
+            let ct_var_span = if let ty::InferConst::Var(vid) = i {
+                let mut inner = self.infcx.inner.borrow_mut();
+                let ct_vars = &mut inner.const_unification_table();
+                if let ConstVariableOrigin {
+                    span,
+                    kind: ConstVariableOriginKind::ConstParameterDefinition(_, _),
+                } = ct_vars.probe_value(vid).origin
+                {
+                    Some(span)
+                } else {
+                    None
+                }
+            } else {
+                None
+            };
+            ControlFlow::Break((ct.into(), ct_var_span))
+        } else if !ct.has_non_region_infer() {
+            // All const/type variables in inference types must already be resolved,
+            // no need to visit the contents.
             ControlFlow::CONTINUE
+        } else {
+            // Otherwise, keep visiting.
+            ct.super_visit_with(self)
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index c1cf7896db5..239b67bd226 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -140,6 +140,15 @@ impl<'tcx> From<ty::Const<'tcx>> for GenericArg<'tcx> {
     }
 }
 
+impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> {
+    fn from(value: ty::Term<'tcx>) -> Self {
+        match value.unpack() {
+            ty::TermKind::Ty(t) => t.into(),
+            ty::TermKind::Const(c) => c.into(),
+        }
+    }
+}
+
 impl<'tcx> GenericArg<'tcx> {
     #[inline]
     pub fn unpack(self) -> GenericArgKind<'tcx> {
diff --git a/src/test/ui/generator/unresolved-ct-var.rs b/src/test/ui/generator/unresolved-ct-var.rs
new file mode 100644
index 00000000000..0a1570fc239
--- /dev/null
+++ b/src/test/ui/generator/unresolved-ct-var.rs
@@ -0,0 +1,14 @@
+// incremental
+// edition:2021
+
+fn main() {
+    let _ = async {
+        let s = std::array::from_fn(|_| ()).await;
+        //~^ ERROR `[(); _]` is not a future
+        //~| ERROR type inside `async` block must be known in this context
+        //~| ERROR type inside `async` block must be known in this context
+        //~| ERROR type inside `async` block must be known in this context
+        //~| ERROR type inside `async` block must be known in this context
+        //~| ERROR type inside `async` block must be known in this context
+    };
+}
diff --git a/src/test/ui/generator/unresolved-ct-var.stderr b/src/test/ui/generator/unresolved-ct-var.stderr
new file mode 100644
index 00000000000..fdf00dfad7a
--- /dev/null
+++ b/src/test/ui/generator/unresolved-ct-var.stderr
@@ -0,0 +1,78 @@
+error[E0277]: `[(); _]` is not a future
+  --> $DIR/unresolved-ct-var.rs:6:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ---------------------------^^^^^^
+   |                 |                          |
+   |                 |                          `[(); _]` is not a future
+   |                 |                          help: remove the `.await`
+   |                 this call returns `[(); _]`
+   |
+   = help: the trait `Future` is not implemented for `[(); _]`
+   = note: [(); _] must be a future or must implement `IntoFuture` to be awaited
+   = note: required for `[(); _]` to implement `IntoFuture`
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var.rs:6:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var.rs:6:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var.rs:6:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var.rs:6:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var.rs:6:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var.rs:6:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var.rs:6:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var.rs:6:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error[E0698]: type inside `async` block must be known in this context
+  --> $DIR/unresolved-ct-var.rs:6:17
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                 ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn`
+   |
+note: the type is part of the `async` block because of this `await`
+  --> $DIR/unresolved-ct-var.rs:6:44
+   |
+LL |         let s = std::array::from_fn(|_| ()).await;
+   |                                            ^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0277, E0698.
+For more information about an error, try `rustc --explain E0277`.