about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2021-12-13 21:22:02 -0800
committerMichael Goulet <michael@errs.io>2021-12-14 11:32:06 -0800
commitf29fb4792b1fa344817d95e997ef8de4befee302 (patch)
treee9b2bc5ec3174bb223db1fe4fe31b2b032355456 /compiler
parent8f117a77d0880ed59afcc1a19c72ec5c1e44b97c (diff)
downloadrust-f29fb4792b1fa344817d95e997ef8de4befee302.tar.gz
rust-f29fb4792b1fa344817d95e997ef8de4befee302.zip
Make TyS::is_suggestable more structual
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs64
1 files changed, 54 insertions, 10 deletions
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 1acb3ec57de..ee00f6c62f3 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,7 +1,12 @@
 //! Diagnostics related methods for `TyS`.
 
+use crate::ty::subst::{GenericArg, GenericArgKind};
 use crate::ty::TyKind::*;
-use crate::ty::{InferTy, TyCtxt, TyS};
+use crate::ty::{
+    ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy,
+    ProjectionTy, TyCtxt, TyS, TypeAndMut,
+};
+
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -63,16 +68,55 @@ impl<'tcx> TyS<'tcx> {
 
     /// Whether the type can be safely suggested during error recovery.
     pub fn is_suggestable(&self) -> bool {
-        !matches!(
-            self.kind(),
+        fn generic_arg_is_suggestible(arg: GenericArg<'_>) -> bool {
+            match arg.unpack() {
+                GenericArgKind::Type(ty) => ty.is_suggestable(),
+                GenericArgKind::Const(c) => const_is_suggestable(c.val),
+                _ => true,
+            }
+        }
+
+        fn const_is_suggestable(kind: ConstKind<'_>) -> bool {
+            match kind {
+                ConstKind::Infer(..)
+                | ConstKind::Bound(..)
+                | ConstKind::Placeholder(..)
+                | ConstKind::Error(..) => false,
+                _ => true,
+            }
+        }
+
+        // FIXME(compiler-errors): Some types are still not good to suggest,
+        // specifically references with lifetimes within the function. Not
+        //sure we have enough information to resolve whether a region is
+        // temporary, so I'll leave this as a fixme.
+
+        match self.kind() {
             Opaque(..)
-                | FnDef(..)
-                | FnPtr(..)
-                | Dynamic(..)
-                | Closure(..)
-                | Infer(..)
-                | Projection(..)
-        )
+            | FnDef(..)
+            | Closure(..)
+            | Infer(..)
+            | Generator(..)
+            | GeneratorWitness(..)
+            | Bound(_, _)
+            | Placeholder(_)
+            | Error(_) => false,
+            Dynamic(dty, _) => dty.iter().all(|pred| match pred.skip_binder() {
+                ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => {
+                    substs.iter().all(generic_arg_is_suggestible)
+                }
+                ExistentialPredicate::Projection(ExistentialProjection { substs, ty, .. }) => {
+                    ty.is_suggestable() && substs.iter().all(generic_arg_is_suggestible)
+                }
+                _ => true,
+            }),
+            Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) | Tuple(args) => {
+                args.iter().all(generic_arg_is_suggestible)
+            }
+            Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(),
+            Array(ty, c) => ty.is_suggestable() && const_is_suggestable(c.val),
+            _ => true,
+        }
     }
 }