From ee713f3d4350c75bae85749619b0e1508f433e02 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 29 Sep 2022 21:22:34 +0000
Subject: [PATCH 1/8] Check generic argument compatibility when projecting
 assoc ty

---
 .../src/traits/project.rs                     | 42 ++++++++++++++++++-
 .../generic-associated-types/issue-102114.rs  | 16 +++++++
 .../issue-102114.stderr                       | 12 ++++++
 3 files changed, 68 insertions(+), 2 deletions(-)
 create mode 100644 src/test/ui/generic-associated-types/issue-102114.rs
 create mode 100644 src/test/ui/generic-associated-types/issue-102114.stderr

diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 07b65a9748d7c..29172d6caaff6 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -2146,10 +2146,10 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     } else {
         ty.map_bound(|ty| ty.into())
     };
-    if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
+    if !check_substs_compatible(tcx, &assoc_ty.item, substs) {
         let err = tcx.ty_error_with_message(
             obligation.cause.span,
-            "impl item and trait item have different parameter counts",
+            "impl item and trait item have different parameters",
         );
         Progress { term: err.into(), obligations: nested }
     } else {
@@ -2158,6 +2158,44 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     }
 }
 
+// Verify that the trait item and its implementation have compatible substs lists
+fn check_substs_compatible<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    assoc_ty: &ty::AssocItem,
+    substs: ty::SubstsRef<'tcx>,
+) -> bool {
+    fn check_substs_compatible_inner<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        generics: &'tcx ty::Generics,
+        args: &'tcx [ty::GenericArg<'tcx>],
+    ) -> bool {
+        if generics.count() != args.len() {
+            return false;
+        }
+
+        let (parent_args, own_args) = args.split_at(generics.parent_count);
+
+        if let Some(parent) = generics.parent
+            && let parent_generics = tcx.generics_of(parent)
+            && !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
+            return false;
+        }
+
+        for (param, arg) in std::iter::zip(&generics.params, own_args) {
+            match (&param.kind, arg.unpack()) {
+                (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
+                | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
+                | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
+                _ => return false,
+            }
+        }
+
+        true
+    }
+
+    check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice())
+}
+
 fn confirm_impl_trait_in_trait_candidate<'tcx>(
     selcx: &mut SelectionContext<'_, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
diff --git a/src/test/ui/generic-associated-types/issue-102114.rs b/src/test/ui/generic-associated-types/issue-102114.rs
new file mode 100644
index 0000000000000..de31737efef52
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-102114.rs
@@ -0,0 +1,16 @@
+trait A {
+    type B<'b>;
+    fn a() -> Self::B<'static>;
+}
+
+struct C;
+
+struct Wrapper<T>(T);
+
+impl A for C {
+    type B<T> = Wrapper<T>;
+    //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters
+    fn a() -> Self::B<'static> {}
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-102114.stderr b/src/test/ui/generic-associated-types/issue-102114.stderr
new file mode 100644
index 0000000000000..8e41dee54d7e4
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-102114.stderr
@@ -0,0 +1,12 @@
+error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/issue-102114.rs:11:12
+   |
+LL |     type B<'b>;
+   |            -- expected 0 type parameters
+...
+LL |     type B<T> = Wrapper<T>;
+   |            ^ found 1 type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.

From 513fc80bbd3b13eddc20b4822ed25b05d7f55194 Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jnelson@cloudflare.com>
Date: Sat, 24 Sep 2022 12:51:18 -0500
Subject: [PATCH 2/8] Package `rust-docs-json` into nightly components (take 3)

`dist` creates a `rust-docs-json.tar.xz` tarfile. But build-manifest expected it to be named
`rust-docs-json-preview.tar.xz`. Change build-manifest to allow the name without the `-preview` suffix.

This also adds `rust-docs-json` to the `rust` component. I'm not quite sure why it exists,
but rustup uses it to determine which components are available.
---
 src/bootstrap/dist.rs                    | 1 +
 src/tools/build-manifest/src/main.rs     | 2 +-
 src/tools/build-manifest/src/versions.rs | 4 ++++
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 563e67a326f19..a9a9be9950f11 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1365,6 +1365,7 @@ impl Step for Extended {
         }
 
         add_component!("rust-docs" => Docs { host: target });
+        add_component!("rust-json-docs" => JsonDocs { host: target });
         add_component!("rust-demangler"=> RustDemangler { compiler, target });
         add_component!("cargo" => Cargo { compiler, target });
         add_component!("rustfmt" => Rustfmt { compiler, target });
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 14311cff5c8c5..1ea07e9fefb74 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -437,7 +437,7 @@ impl Builder {
             host_component("rustfmt-preview"),
             host_component("llvm-tools-preview"),
             host_component("rust-analysis"),
-            host_component("rust-docs-json"),
+            host_component("rust-docs-json-preview"),
         ]);
 
         extensions.extend(
diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs
index 92ef9968fe525..4da62fa67b408 100644
--- a/src/tools/build-manifest/src/versions.rs
+++ b/src/tools/build-manifest/src/versions.rs
@@ -20,6 +20,7 @@ pub(crate) enum PkgType {
     Rustfmt,
     LlvmTools,
     Miri,
+    JsonDocs,
     Other(String),
 }
 
@@ -36,6 +37,7 @@ impl PkgType {
             "rustfmt" | "rustfmt-preview" => PkgType::Rustfmt,
             "llvm-tools" | "llvm-tools-preview" => PkgType::LlvmTools,
             "miri" | "miri-preview" => PkgType::Miri,
+            "rust-docs-json" | "rust-docs-json-preview" => PkgType::JsonDocs,
             other => PkgType::Other(other.into()),
         }
     }
@@ -53,6 +55,7 @@ impl PkgType {
             PkgType::Rustfmt => "rustfmt",
             PkgType::LlvmTools => "llvm-tools",
             PkgType::Miri => "miri",
+            PkgType::JsonDocs => "rust-docs-json",
             PkgType::Other(component) => component,
         }
     }
@@ -72,6 +75,7 @@ impl PkgType {
             PkgType::Rust => true,
             PkgType::RustSrc => true,
             PkgType::Rustc => true,
+            PkgType::JsonDocs => true,
             PkgType::Other(_) => true,
         }
     }

From d44e14225ab00e164aa9ea9e8d9e1bee40f96b3e Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jnelson@cloudflare.com>
Date: Sat, 1 Oct 2022 15:38:27 -0500
Subject: [PATCH 3/8] Give better errors when build-manifest fails

---
 src/tools/build-manifest/src/main.rs     | 8 +++++++-
 src/tools/build-manifest/src/versions.rs | 4 ++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 1ea07e9fefb74..b0006cb90bdd6 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -193,6 +193,12 @@ macro_rules! t {
             Err(e) => panic!("{} failed with {}", stringify!($e), e),
         }
     };
+    ($e:expr, $extra:expr) => {
+        match $e {
+            Ok(e) => e,
+            Err(e) => panic!("{} failed with {}: {}", stringify!($e), e, $extra),
+        }
+    };
 }
 
 struct Builder {
@@ -584,7 +590,7 @@ impl Builder {
         self.shipped_files.insert(name.clone());
 
         let dst = self.output.join(name);
-        t!(fs::write(&dst, contents));
+        t!(fs::write(&dst, contents), format!("failed to create manifest {}", dst.display()));
     }
 
     fn write_shipped_files(&self, path: &Path) {
diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs
index 4da62fa67b408..0186194a41f55 100644
--- a/src/tools/build-manifest/src/versions.rs
+++ b/src/tools/build-manifest/src/versions.rs
@@ -117,6 +117,9 @@ impl Versions {
             Some(version) => Ok(version.clone()),
             None => {
                 let version_info = self.load_version_from_tarball(package)?;
+                if *package == PkgType::Rust && version_info.version.is_none() {
+                    panic!("missing version info for toolchain");
+                }
                 self.versions.insert(package.clone(), version_info.clone());
                 Ok(version_info)
             }
@@ -131,6 +134,7 @@ impl Versions {
             Ok(file) => file,
             Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
                 // Missing tarballs do not return an error, but return empty data.
+                println!("warning: missing tarball {}", tarball.display());
                 return Ok(VersionInfo::default());
             }
             Err(err) => return Err(err.into()),

From 33bcea8f614f5019012f16b49dc3cd934326ca87 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 3 Oct 2022 17:08:42 +0000
Subject: [PATCH 4/8] Only allow ~const bounds for traits with #[const_trait]

---
 .../rustc_trait_selection/src/traits/wf.rs    |  4 ++++
 library/core/src/iter/traits/collect.rs       |  2 +-
 library/core/src/marker.rs                    |  1 +
 src/test/ui/consts/const-fn-error.stderr      |  4 ++--
 src/test/ui/consts/const-for.stderr           |  4 ++--
 .../constifconst-call-in-const-position.rs    |  1 +
 ...constifconst-call-in-const-position.stderr |  2 +-
 src/test/ui/never_type/issue-52443.stderr     |  4 ++--
 .../call-generic-method-nonconst.rs           |  9 +++++--
 .../call-generic-method-nonconst.stderr       | 21 +++++++---------
 .../const-drop-fail.precise.stderr            | 16 ++++++-------
 .../const-drop-fail.rs                        |  3 ++-
 .../const-drop-fail.stock.stderr              | 16 ++++++-------
 .../const-impl-requires-const-trait.rs        |  1 +
 .../const-impl-requires-const-trait.stderr    |  8 ++++++-
 ...ault-method-body-is-const-body-checking.rs |  1 +
 ...-method-body-is-const-body-checking.stderr |  6 ++---
 .../super-traits-fail-2.nn.stderr             |  8 +++++++
 .../super-traits-fail-2.ny.stderr             |  8 +++++++
 .../super-traits-fail-2.rs                    |  9 +++++--
 .../super-traits-fail-2.stderr                | 24 -------------------
 .../super-traits-fail-2.yn.stderr             | 21 ++++++++++++++++
 .../super-traits-fail-2.yy.stderr             | 21 ++++++++++++++++
 .../super-traits-fail-3.nn.stderr             | 14 +++++++++++
 .../super-traits-fail-3.ny.stderr             |  8 +++++++
 .../super-traits-fail-3.rs                    | 20 ++++++++++++++++
 .../super-traits-fail-3.yn.stderr             |  8 +++++++
 .../tilde-const-invalid-places.rs             |  1 +
 .../tilde-const-invalid-places.stderr         | 10 ++++----
 .../trait-where-clause-const.rs               |  2 ++
 .../trait-where-clause-const.stderr           |  8 +++----
 .../trait-where-clause-self-referential.rs    |  1 +
 .../trait-where-clause.rs                     |  1 +
 .../trait-where-clause.stderr                 |  8 +++----
 34 files changed, 192 insertions(+), 83 deletions(-)
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
 delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs
 create mode 100644 src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr

diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 9722b48a68ab6..ef7b27e408cde 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -308,6 +308,10 @@ impl<'tcx> WfPredicates<'tcx> {
         let obligations = if trait_pred.constness == ty::BoundConstness::NotConst {
             self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
         } else {
+            if !tcx.has_attr(trait_ref.def_id, rustc_span::sym::const_trait) {
+                tcx.sess
+                    .span_err(self.span, "~const can only be applied to `#[const_trait]` traits");
+            }
             self.nominal_obligations(trait_ref.def_id, trait_ref.substs)
         };
 
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index e598a54b4f151..e099700e3e7c8 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -264,7 +264,7 @@ pub trait IntoIterator {
 
 #[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<I: ~const Iterator> const IntoIterator for I {
+impl<I: Iterator> const IntoIterator for I {
     type Item = I::Item;
     type IntoIter = I;
 
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 5cb5e4458cc68..d5ed52124e2ca 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -799,6 +799,7 @@ impl<T: ?Sized> Unpin for *mut T {}
 #[unstable(feature = "const_trait_impl", issue = "67792")]
 #[lang = "destruct"]
 #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
+#[const_trait]
 pub trait Destruct {}
 
 /// A marker for tuple types.
diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr
index e36324f0b3eea..02960b363e78f 100644
--- a/src/test/ui/consts/const-fn-error.stderr
+++ b/src/test/ui/consts/const-fn-error.stderr
@@ -22,8 +22,8 @@ LL |     for i in 0..x {
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
-LL | impl<I: ~const Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: Iterator> const IntoIterator for I {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constant functions
diff --git a/src/test/ui/consts/const-for.stderr b/src/test/ui/consts/const-for.stderr
index f2e1c8a4991a3..11e4ae309c01f 100644
--- a/src/test/ui/consts/const-for.stderr
+++ b/src/test/ui/consts/const-for.stderr
@@ -7,8 +7,8 @@ LL |     for _ in 0..5 {}
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
-LL | impl<I: ~const Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: Iterator> const IntoIterator for I {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
diff --git a/src/test/ui/consts/constifconst-call-in-const-position.rs b/src/test/ui/consts/constifconst-call-in-const-position.rs
index bf67e5a3f76ac..fcf01d5bc71a3 100644
--- a/src/test/ui/consts/constifconst-call-in-const-position.rs
+++ b/src/test/ui/consts/constifconst-call-in-const-position.rs
@@ -2,6 +2,7 @@
 
 #![feature(const_trait_impl, generic_const_exprs)]
 
+#[const_trait]
 pub trait Tr {
     fn a() -> usize;
 }
diff --git a/src/test/ui/consts/constifconst-call-in-const-position.stderr b/src/test/ui/consts/constifconst-call-in-const-position.stderr
index e3f67b4467867..d4a445120a25d 100644
--- a/src/test/ui/consts/constifconst-call-in-const-position.stderr
+++ b/src/test/ui/consts/constifconst-call-in-const-position.stderr
@@ -8,7 +8,7 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0080]: evaluation of `foo::<()>::{constant#0}` failed
-  --> $DIR/constifconst-call-in-const-position.rs:15:38
+  --> $DIR/constifconst-call-in-const-position.rs:16:38
    |
 LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
    |                                      ^^^^^^ calling non-const function `<() as Tr>::a`
diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr
index 3c0daa4c55f01..0910e9ad77a84 100644
--- a/src/test/ui/never_type/issue-52443.stderr
+++ b/src/test/ui/never_type/issue-52443.stderr
@@ -47,8 +47,8 @@ LL |     [(); { for _ in 0usize.. {}; 0}];
 note: impl defined here, but it is not `const`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
-LL | impl<I: ~const Iterator> const IntoIterator for I {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: Iterator> const IntoIterator for I {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
 error[E0658]: mutable references are not allowed in constants
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
index d3e14a53a2fc3..414a8c87d2c41 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
@@ -2,13 +2,18 @@
 
 struct S;
 
-impl PartialEq for S {
+#[const_trait]
+trait Foo {
+    fn eq(&self, _: &Self) -> bool;
+}
+
+impl Foo for S {
     fn eq(&self, _: &S) -> bool {
         true
     }
 }
 
-const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+const fn equals_self<T: ~const Foo>(t: &T) -> bool {
     true
 }
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
index 0a2a5f0f24578..706f52343659e 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -1,26 +1,21 @@
-error[E0277]: can't compare `S` with `S` in const contexts
-  --> $DIR/call-generic-method-nonconst.rs:18:34
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+  --> $DIR/call-generic-method-nonconst.rs:23:34
    |
 LL | pub const EQ: bool = equals_self(&S);
-   |                      ----------- ^^ no implementation for `S == S`
+   |                      ----------- ^^ the trait `~const Foo` is not implemented for `S`
    |                      |
    |                      required by a bound introduced by this call
    |
-   = help: the trait `~const PartialEq` is not implemented for `S`
-note: the trait `PartialEq` is implemented for `S`, but that implementation is not `const`
-  --> $DIR/call-generic-method-nonconst.rs:18:34
+note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
+  --> $DIR/call-generic-method-nonconst.rs:23:34
    |
 LL | pub const EQ: bool = equals_self(&S);
    |                                  ^^
 note: required by a bound in `equals_self`
-  --> $DIR/call-generic-method-nonconst.rs:11:25
-   |
-LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
-   |                         ^^^^^^^^^^^^^^^^ required by this bound in `equals_self`
-help: consider annotating `S` with `#[derive(PartialEq)]`
-   |
-LL | #[derive(PartialEq)]
+  --> $DIR/call-generic-method-nonconst.rs:16:25
    |
+LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool {
+   |                         ^^^^^^^^^^ required by this bound in `equals_self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
index 2295a822fa48b..ddf0e2d91c097 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't drop `NonTrivialDrop` in const contexts
-  --> $DIR/const-drop-fail.rs:43:5
+  --> $DIR/const-drop-fail.rs:44:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -9,7 +9,7 @@ LL |     NonTrivialDrop,
    |
    = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:34:19
+  --> $DIR/const-drop-fail.rs:35:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
@@ -21,7 +21,7 @@ LL |     &mut NonTrivialDrop,
    |     ++++
 
 error[E0277]: can't drop `NonTrivialDrop` in const contexts
-  --> $DIR/const-drop-fail.rs:45:5
+  --> $DIR/const-drop-fail.rs:46:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -30,7 +30,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
    |
 note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
-  --> $DIR/const-drop-fail.rs:45:5
+  --> $DIR/const-drop-fail.rs:46:5
    |
 LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,13 +40,13 @@ note: required because it appears within the type `ConstImplWithDropGlue`
 LL | struct ConstImplWithDropGlue(NonTrivialDrop);
    |        ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:34:19
+  --> $DIR/const-drop-fail.rs:35:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:47:5
+  --> $DIR/const-drop-fail.rs:48:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -55,14 +55,14 @@ LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
    |
 note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
-  --> $DIR/const-drop-fail.rs:28:25
+  --> $DIR/const-drop-fail.rs:29:25
    |
 LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
    |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: 1 redundant requirement hidden
    = note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:34:19
+  --> $DIR/const-drop-fail.rs:35:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
index 001dd430a8621..565e2c77ac5ca 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
@@ -19,7 +19,8 @@ impl const Drop for ConstImplWithDropGlue {
     fn drop(&mut self) {}
 }
 
-trait A { fn a() { println!("A"); } }
+#[const_trait]
+trait A { fn a() { } }
 
 impl A for NonTrivialDrop {}
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
index 2295a822fa48b..ddf0e2d91c097 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't drop `NonTrivialDrop` in const contexts
-  --> $DIR/const-drop-fail.rs:43:5
+  --> $DIR/const-drop-fail.rs:44:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -9,7 +9,7 @@ LL |     NonTrivialDrop,
    |
    = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:34:19
+  --> $DIR/const-drop-fail.rs:35:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
@@ -21,7 +21,7 @@ LL |     &mut NonTrivialDrop,
    |     ++++
 
 error[E0277]: can't drop `NonTrivialDrop` in const contexts
-  --> $DIR/const-drop-fail.rs:45:5
+  --> $DIR/const-drop-fail.rs:46:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -30,7 +30,7 @@ LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
    |
 note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
-  --> $DIR/const-drop-fail.rs:45:5
+  --> $DIR/const-drop-fail.rs:46:5
    |
 LL |     ConstImplWithDropGlue(NonTrivialDrop),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,13 +40,13 @@ note: required because it appears within the type `ConstImplWithDropGlue`
 LL | struct ConstImplWithDropGlue(NonTrivialDrop);
    |        ^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:34:19
+  --> $DIR/const-drop-fail.rs:35:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
 
 error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
-  --> $DIR/const-drop-fail.rs:47:5
+  --> $DIR/const-drop-fail.rs:48:5
    |
 LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
@@ -55,14 +55,14 @@ LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
    |
 note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
-  --> $DIR/const-drop-fail.rs:28:25
+  --> $DIR/const-drop-fail.rs:29:25
    |
 LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
    |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: 1 redundant requirement hidden
    = note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
 note: required by a bound in `check`
-  --> $DIR/const-drop-fail.rs:34:19
+  --> $DIR/const-drop-fail.rs:35:19
    |
 LL | const fn check<T: ~const Destruct>(_: T) {}
    |                   ^^^^^^^^^^^^^^^ required by this bound in `check`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
index 1aff05627850b..8757d74082e1a 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
@@ -5,5 +5,6 @@ pub trait A {}
 
 impl const A for () {}
 //~^ ERROR: const `impl`s must be for traits marked with `#[const_trait]`
+//~| ERROR: ~const can only be applied to `#[const_trait]` traits
 
 fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
index 6b465a9c62e2e..f9c69d6c6bf84 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
@@ -10,5 +10,11 @@ note: this trait must be annotated with `#[const_trait]`
 LL | pub trait A {}
    | ^^^^^^^^^^^
 
-error: aborting due to previous error
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/const-impl-requires-const-trait.rs:6:12
+   |
+LL | impl const A for () {}
+   |            ^
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
index d27291231fbd7..96acdc300e0dd 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
@@ -1,5 +1,6 @@
 #![feature(const_trait_impl)]
 
+#[const_trait]
 trait Tr {}
 impl Tr for () {}
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
index 7542b81fe2adb..d102956cd2ec2 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
@@ -1,16 +1,16 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-body-checking.rs:11:15
+  --> $DIR/default-method-body-is-const-body-checking.rs:12:15
    |
 LL |         foo::<()>();
    |               ^^ the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
-  --> $DIR/default-method-body-is-const-body-checking.rs:11:15
+  --> $DIR/default-method-body-is-const-body-checking.rs:12:15
    |
 LL |         foo::<()>();
    |               ^^
 note: required by a bound in `foo`
-  --> $DIR/default-method-body-is-const-body-checking.rs:6:28
+  --> $DIR/default-method-body-is-const-body-checking.rs:7:28
    |
 LL | const fn foo<T>() where T: ~const Tr {}
    |                            ^^^^^^^^^ required by this bound in `foo`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
new file mode 100644
index 0000000000000..b86acb2cc9ab2
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-2.rs:11:12
+   |
+LL | trait Bar: ~const Foo {}
+   |            ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
new file mode 100644
index 0000000000000..b86acb2cc9ab2
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-2.rs:11:12
+   |
+LL | trait Bar: ~const Foo {}
+   |            ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
index 7b38c15afc20b..d183efde2df1f 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
@@ -1,14 +1,19 @@
 #![feature(const_trait_impl)]
 
+// revisions: yy yn ny nn
+
+#[cfg_attr(any(yy, yn), const_trait)]
 trait Foo {
     fn a(&self);
 }
+
+#[cfg_attr(any(yy, ny), const_trait)]
 trait Bar: ~const Foo {}
+//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
 
 const fn foo<T: Bar>(x: &T) {
     x.a();
-    //~^ ERROR the trait bound
-    //~| ERROR cannot call
+    //[yn,yy]~^ ERROR the trait bound
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr
deleted file mode 100644
index 1766cdbee8af2..0000000000000
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0277]: the trait bound `T: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail-2.rs:9:7
-   |
-LL |     x.a();
-   |       ^^^ the trait `~const Foo` is not implemented for `T`
-   |
-note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/super-traits-fail-2.rs:9:7
-   |
-LL |     x.a();
-   |       ^^^
-
-error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
-  --> $DIR/super-traits-fail-2.rs:9:7
-   |
-LL |     x.a();
-   |       ^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
new file mode 100644
index 0000000000000..b52eb2c0332fd
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+  --> $DIR/super-traits-fail-2.rs:15:5
+   |
+LL |     x.a();
+   |     ^ - required by a bound introduced by this call
+   |     |
+   |     the trait `~const Foo` is not implemented for `T`
+   |
+note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
+  --> $DIR/super-traits-fail-2.rs:15:5
+   |
+LL |     x.a();
+   |     ^
+help: consider further restricting this bound
+   |
+LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
+   |                     ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
new file mode 100644
index 0000000000000..b52eb2c0332fd
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+  --> $DIR/super-traits-fail-2.rs:15:5
+   |
+LL |     x.a();
+   |     ^ - required by a bound introduced by this call
+   |     |
+   |     the trait `~const Foo` is not implemented for `T`
+   |
+note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
+  --> $DIR/super-traits-fail-2.rs:15:5
+   |
+LL |     x.a();
+   |     ^
+help: consider further restricting this bound
+   |
+LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
+   |                     ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
new file mode 100644
index 0000000000000..191edca1761c8
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
@@ -0,0 +1,14 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:12:12
+   |
+LL | trait Bar: ~const Foo {}
+   |            ^^^^^^^^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:15:17
+   |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+   |                 ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
new file mode 100644
index 0000000000000..a3b4c302a57f8
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:12:12
+   |
+LL | trait Bar: ~const Foo {}
+   |            ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs
new file mode 100644
index 0000000000000..70d2936d3b259
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs
@@ -0,0 +1,20 @@
+#![feature(const_trait_impl)]
+
+// revisions: yy yn ny nn
+//[yy] check-pass
+
+#[cfg_attr(any(yy, yn), const_trait)]
+trait Foo {
+    fn a(&self);
+}
+
+#[cfg_attr(any(yy, ny), const_trait)]
+trait Bar: ~const Foo {}
+//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+
+const fn foo<T: ~const Bar>(x: &T) {
+    //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+    x.a();
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr
new file mode 100644
index 0000000000000..9d61166546593
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:15:17
+   |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+   |                 ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
index 350be4d8250d6..5bd52151f42ac 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
@@ -1,6 +1,7 @@
 #![feature(const_trait_impl)]
 #![feature(associated_type_bounds)]
 
+#[const_trait]
 trait T {}
 struct S;
 impl T for S {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
index 8d781d063d1c0..5d2133156343d 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
@@ -1,5 +1,5 @@
 error: `~const` is not allowed here
-  --> $DIR/tilde-const-invalid-places.rs:8:19
+  --> $DIR/tilde-const-invalid-places.rs:9:19
    |
 LL | fn rpit() -> impl ~const T { S }
    |                   ^^^^^^^^
@@ -7,7 +7,7 @@ LL | fn rpit() -> impl ~const T { S }
    = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
 
 error: `~const` is not allowed here
-  --> $DIR/tilde-const-invalid-places.rs:11:17
+  --> $DIR/tilde-const-invalid-places.rs:12:17
    |
 LL | fn apit(_: impl ~const T) {}
    |                 ^^^^^^^^
@@ -15,7 +15,7 @@ LL | fn apit(_: impl ~const T) {}
    = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
 
 error: `~const` is not allowed here
-  --> $DIR/tilde-const-invalid-places.rs:14:50
+  --> $DIR/tilde-const-invalid-places.rs:15:50
    |
 LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
    |                                                  ^^^^^^^^
@@ -23,7 +23,7 @@ LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
    = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
 
 error: `~const` is not allowed here
-  --> $DIR/tilde-const-invalid-places.rs:17:48
+  --> $DIR/tilde-const-invalid-places.rs:18:48
    |
 LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
    |                                                ^^^^^^^^
@@ -31,7 +31,7 @@ LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
    = note: only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions
 
 error: `~const` and `?` are mutually exclusive
-  --> $DIR/tilde-const-invalid-places.rs:20:25
+  --> $DIR/tilde-const-invalid-places.rs:21:25
    |
 LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
    |                         ^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
index 47c38c979c328..bfe98b98c7420 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
@@ -4,8 +4,10 @@
 // test is not enough.
 #![feature(const_trait_impl)]
 
+#[const_trait]
 trait Bar {}
 
+#[const_trait]
 trait Foo {
     fn a();
     fn b() where Self: ~const Bar;
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
index 13d8639de30c3..f2846b6a66262 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: ~const Bar` is not satisfied
-  --> $DIR/trait-where-clause-const.rs:17:5
+  --> $DIR/trait-where-clause-const.rs:19:5
    |
 LL |     T::b();
    |     ^^^^^^ the trait `~const Bar` is not implemented for `T`
    |
 note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/trait-where-clause-const.rs:17:5
+  --> $DIR/trait-where-clause-const.rs:19:5
    |
 LL |     T::b();
    |     ^^^^^^
@@ -15,13 +15,13 @@ LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
    |                                    ++++++++++++
 
 error[E0277]: the trait bound `T: ~const Bar` is not satisfied
-  --> $DIR/trait-where-clause-const.rs:19:5
+  --> $DIR/trait-where-clause-const.rs:21:5
    |
 LL |     T::c::<T>();
    |     ^^^^^^^^^^^ the trait `~const Bar` is not implemented for `T`
    |
 note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/trait-where-clause-const.rs:19:5
+  --> $DIR/trait-where-clause-const.rs:21:5
    |
 LL |     T::c::<T>();
    |     ^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
index acea58eaecb9a..3b028ac48db4b 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
@@ -2,6 +2,7 @@
 
 #![feature(const_trait_impl)]
 
+#[const_trait]
 trait Foo {
     fn bar() where Self: ~const Foo;
 }
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
index 5bd23a8cb2079..85ca5fc904877 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
@@ -1,5 +1,6 @@
 #![feature(const_trait_impl)]
 
+#[const_trait]
 trait Bar {}
 
 trait Foo {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
index 96365d3343362..11f0c40160d89 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:13:5
+  --> $DIR/trait-where-clause.rs:14:5
    |
 LL |     T::b();
    |     ^^^^ the trait `Bar` is not implemented for `T`
    |
 note: required by a bound in `Foo::b`
-  --> $DIR/trait-where-clause.rs:7:24
+  --> $DIR/trait-where-clause.rs:8:24
    |
 LL |     fn b() where Self: ~const Bar;
    |                        ^^^^^^^^^^ required by this bound in `Foo::b`
@@ -15,13 +15,13 @@ LL | fn test1<T: Foo + Bar>() {
    |                 +++++
 
 error[E0277]: the trait bound `T: Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:15:12
+  --> $DIR/trait-where-clause.rs:16:12
    |
 LL |     T::c::<T>();
    |            ^ the trait `Bar` is not implemented for `T`
    |
 note: required by a bound in `Foo::c`
-  --> $DIR/trait-where-clause.rs:8:13
+  --> $DIR/trait-where-clause.rs:9:13
    |
 LL |     fn c<T: ~const Bar>();
    |             ^^^^^^^^^^ required by this bound in `Foo::c`

From ee691e02c3031ec27e4136f9f1a9bddecd15cb20 Mon Sep 17 00:00:00 2001
From: Rageking8 <tomleetyt@gmail.com>
Date: Tue, 4 Oct 2022 16:13:50 +0800
Subject: [PATCH 5/8] add test for #102605

---
 src/test/ui/impl-trait/issue-102605.rs     | 15 ++++++++
 src/test/ui/impl-trait/issue-102605.stderr | 41 ++++++++++++++++++++++
 2 files changed, 56 insertions(+)
 create mode 100644 src/test/ui/impl-trait/issue-102605.rs
 create mode 100644 src/test/ui/impl-trait/issue-102605.stderr

diff --git a/src/test/ui/impl-trait/issue-102605.rs b/src/test/ui/impl-trait/issue-102605.rs
new file mode 100644
index 0000000000000..3bbdf35af8f90
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-102605.rs
@@ -0,0 +1,15 @@
+// edition:2021
+
+async fn foo() -> Result<(), String> {
+    Ok(())
+}
+
+fn convert_result<T, E>(r: Result<T, E>) -> Option<T> {
+    None
+}
+
+fn main() -> Option<()> {
+    //~^ ERROR `main` has invalid return type `Option<()>`
+    convert_result(foo())
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/impl-trait/issue-102605.stderr b/src/test/ui/impl-trait/issue-102605.stderr
new file mode 100644
index 0000000000000..d4aba914908fd
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-102605.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-102605.rs:13:20
+   |
+LL |     convert_result(foo())
+   |     -------------- ^^^^^ expected enum `Result`, found opaque type
+   |     |
+   |     arguments to this function are incorrect
+   |
+note: while checking the return type of the `async fn`
+  --> $DIR/issue-102605.rs:3:19
+   |
+LL | async fn foo() -> Result<(), String> {
+   |                   ^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
+   = note:     expected enum `Result<(), _>`
+           found opaque type `impl Future<Output = Result<(), String>>`
+note: function defined here
+  --> $DIR/issue-102605.rs:7:4
+   |
+LL | fn convert_result<T, E>(r: Result<T, E>) -> Option<T> {
+   |    ^^^^^^^^^^^^^^       ---------------
+help: consider `await`ing on the `Future`
+   |
+LL |     convert_result(foo().await)
+   |                         ++++++
+help: try wrapping the expression in `Err`
+   |
+LL |     convert_result(Err(foo()))
+   |                    ++++     +
+
+error[E0277]: `main` has invalid return type `Option<()>`
+  --> $DIR/issue-102605.rs:11:14
+   |
+LL | fn main() -> Option<()> {
+   |              ^^^^^^^^^^ `main` can only return types that implement `Termination`
+   |
+   = help: consider using `()`, or a `Result`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.

From c72c6e01c8020c7a285b76a9b61934e3501b80f3 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 4 Oct 2022 08:59:20 +0000
Subject: [PATCH 6/8] Merge the `~const` and `impl const` checks and add some
 explanatory notes

---
 compiler/rustc_passes/src/check_const.rs      | 26 -------------------
 .../rustc_trait_selection/src/traits/wf.rs    | 26 +++++++++++++++++--
 .../const-impl-requires-const-trait.rs        |  5 ++--
 .../const-impl-requires-const-trait.stderr    | 22 ++++++----------
 4 files changed, 34 insertions(+), 45 deletions(-)

diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 116aaf4834981..e502b9b54e302 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -191,32 +191,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
         self.tcx.hir()
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let tcx = self.tcx;
-        if let hir::ItemKind::Impl(hir::Impl {
-            constness: hir::Constness::Const,
-            of_trait: Some(trait_ref),
-            ..
-        }) = item.kind
-            && let Some(def_id) = trait_ref.trait_def_id()
-        {
-            let source_map = tcx.sess.source_map();
-            if !tcx.has_attr(def_id, sym::const_trait) {
-                tcx.sess
-                    .struct_span_err(
-                        source_map.guess_head_span(item.span),
-                        "const `impl`s must be for traits marked with `#[const_trait]`",
-                    )
-                    .span_note(
-                        source_map.guess_head_span(tcx.def_span(def_id)),
-                        "this trait must be annotated with `#[const_trait]`",
-                    )
-                    .emit();
-            }
-        }
-        intravisit::walk_item(self, item);
-    }
-
     fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
         let kind = Some(hir::ConstContext::Const);
         self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index ef7b27e408cde..5f901d6995e4b 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -309,8 +309,30 @@ impl<'tcx> WfPredicates<'tcx> {
             self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
         } else {
             if !tcx.has_attr(trait_ref.def_id, rustc_span::sym::const_trait) {
-                tcx.sess
-                    .span_err(self.span, "~const can only be applied to `#[const_trait]` traits");
+                if let Some(item) = self.item &&
+                   let hir::ItemKind::Impl(impl_) = item.kind &&
+                   let Some(trait_) = &impl_.of_trait &&
+                   let Some(def_id) = trait_.trait_def_id() &&
+                   def_id == trait_ref.def_id
+                {
+                    let trait_name = tcx.item_name(def_id);
+                    let mut err = tcx.sess.struct_span_err(
+                        self.span,
+                        &format!("const `impl` for trait `{trait_name}` which is not marked with `#[const_trait]`"),
+                    );
+                    if def_id.is_local() {
+                        let sp = tcx.def_span(def_id).shrink_to_lo();
+                        err.span_suggestion(sp, &format!("mark `{trait_name}` as const"), "#[const_trait]", rustc_errors::Applicability::MachineApplicable);
+                    }
+                    err.note("marking a trait with `#[const_trait]` ensures all default method bodies are `const`");
+                    err.note("adding a non-const method body in the future would be a breaking change");
+                    err.emit();
+                } else {
+                    tcx.sess.span_err(
+                        self.span,
+                        "~const can only be applied to `#[const_trait]` traits",
+                    );
+                }
             }
             self.nominal_obligations(trait_ref.def_id, trait_ref.substs)
         };
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
index 8757d74082e1a..2b4963991dbef 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
@@ -1,10 +1,9 @@
 #![feature(const_trait_impl)]
 
 pub trait A {}
-//~^ NOTE: this trait must be annotated with `#[const_trait]`
+//~^ HELP: mark `A` as const
 
 impl const A for () {}
-//~^ ERROR: const `impl`s must be for traits marked with `#[const_trait]`
-//~| ERROR: ~const can only be applied to `#[const_trait]` traits
+//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
 
 fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
index f9c69d6c6bf84..478adcf3e9e89 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
@@ -1,20 +1,14 @@
-error: const `impl`s must be for traits marked with `#[const_trait]`
-  --> $DIR/const-impl-requires-const-trait.rs:6:1
-   |
-LL | impl const A for () {}
-   | ^^^^^^^^^^^^^^^^^^^
-   |
-note: this trait must be annotated with `#[const_trait]`
-  --> $DIR/const-impl-requires-const-trait.rs:3:1
-   |
-LL | pub trait A {}
-   | ^^^^^^^^^^^
-
-error: ~const can only be applied to `#[const_trait]` traits
+error: const `impl` for trait `A` which is not marked with `#[const_trait]`
   --> $DIR/const-impl-requires-const-trait.rs:6:12
    |
+LL | pub trait A {}
+   | - help: mark `A` as const: `#[const_trait]`
+...
 LL | impl const A for () {}
    |            ^
+   |
+   = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+   = note: adding a non-const method body in the future would be a breaking change
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 

From c7b6ebdf7c0acf2382696988c09902beb91f4082 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 4 Oct 2022 09:43:34 +0000
Subject: [PATCH 7/8] It's not about types or consts, but the lack of regions

---
 compiler/rustc_borrowck/src/type_check/mod.rs  |  2 +-
 .../src/check/fn_ctxt/_impl.rs                 |  4 ++--
 .../src/check/fn_ctxt/checks.rs                |  2 +-
 .../src/check/intrinsicck.rs                   |  2 +-
 compiler/rustc_hir_analysis/src/check/op.rs    |  4 ++--
 .../rustc_hir_analysis/src/check/wfcheck.rs    |  4 +---
 compiler/rustc_infer/src/infer/mod.rs          | 18 +++++++-----------
 .../rustc_infer/src/infer/nll_relate/mod.rs    |  2 +-
 compiler/rustc_infer/src/infer/resolve.rs      |  4 ++--
 .../rustc_middle/src/mir/interpret/queries.rs  |  4 ++--
 compiler/rustc_middle/src/mir/mod.rs           |  8 ++++----
 compiler/rustc_middle/src/ty/abstract_const.rs |  8 ++++----
 compiler/rustc_middle/src/ty/fast_reject.rs    |  2 +-
 compiler/rustc_middle/src/ty/layout.rs         |  4 ++--
 compiler/rustc_middle/src/ty/visit.rs          |  8 ++++----
 .../rustc_monomorphize/src/polymorphize.rs     | 10 +++++-----
 compiler/rustc_symbol_mangling/src/v0.rs       |  2 +-
 .../src/traits/const_evaluatable.rs            |  6 +++---
 .../src/traits/error_reporting/mod.rs          |  8 ++++----
 .../src/traits/error_reporting/suggestions.rs  |  2 +-
 .../src/traits/fulfill.rs                      |  8 ++++----
 .../rustc_trait_selection/src/traits/misc.rs   |  2 +-
 .../rustc_trait_selection/src/traits/mod.rs    |  2 +-
 .../src/traits/project.rs                      |  2 +-
 .../src/traits/select/candidate_assembly.rs    |  6 +++---
 .../src/traits/select/mod.rs                   |  4 ++--
 .../src/implied_outlives_bounds.rs             |  2 +-
 compiler/rustc_ty_utils/src/consts.rs          | 12 ++++++------
 compiler/rustc_ty_utils/src/layout.rs          |  4 ++--
 .../clippy/clippy_lints/src/dereference.rs     |  2 +-
 30 files changed, 71 insertions(+), 77 deletions(-)

diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index d03f036964857..28ed88e8345c4 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -236,7 +236,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
                 .unwrap();
             let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
             trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
-            if hidden_type.has_infer_types_or_consts() {
+            if hidden_type.has_non_region_infer() {
                 infcx.tcx.sess.delay_span_bug(
                     decl.hidden_type.span,
                     &format!("could not resolve {:#?}", hidden_type.ty.kind()),
diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/_impl.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/_impl.rs
index 4bd5e9f6ab579..e51e528062094 100644
--- a/compiler/rustc_hir_analysis/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_analysis/src/check/fn_ctxt/_impl.rs
@@ -91,14 +91,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
     ) -> Ty<'tcx> {
         // No Infer()? Nothing needs doing.
-        if !ty.has_infer_types_or_consts() {
+        if !ty.has_non_region_infer() {
             debug!("no inference var, nothing needs doing");
             return ty;
         }
 
         // If `ty` is a type variable, see whether we already know what it is.
         ty = self.resolve_vars_if_possible(ty);
-        if !ty.has_infer_types_or_consts() {
+        if !ty.has_non_region_infer() {
             debug!(?ty);
             return ty;
         }
diff --git a/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs b/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs
index 44d7973d63204..13e74021b9e0a 100644
--- a/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_analysis/src/check/fn_ctxt/checks.rs
@@ -63,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let get_operand_ty = |expr| {
                 let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
                 let ty = self.resolve_vars_if_possible(ty);
-                if ty.has_infer_types_or_consts() {
+                if ty.has_non_region_infer() {
                     assert!(self.is_tainted_by_errors());
                     self.tcx.ty_error()
                 } else {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 13a800304158b..4abc00cefb68f 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -149,7 +149,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
         target_features: &FxHashSet<Symbol>,
     ) -> Option<InlineAsmType> {
         let ty = (self.get_operand_ty)(expr);
-        if ty.has_infer_types_or_consts() {
+        if ty.has_non_region_infer() {
             bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty);
         }
         let asm_ty_isize = match self.tcx.sess.target.pointer_width {
diff --git a/compiler/rustc_hir_analysis/src/check/op.rs b/compiler/rustc_hir_analysis/src/check/op.rs
index 2d7d9020e3ecc..d876b1d20fe22 100644
--- a/compiler/rustc_hir_analysis/src/check/op.rs
+++ b/compiler/rustc_hir_analysis/src/check/op.rs
@@ -471,7 +471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // This has nothing here because it means we did string
                         // concatenation (e.g., "Hello " + "World!"). This means
                         // we don't want the note in the else clause to be emitted
-                    } else if lhs_ty.has_param_types_or_consts() {
+                    } else if lhs_ty.has_non_region_param() {
                         // Look for a TraitPredicate in the Fulfillment errors,
                         // and use it to generate a suggestion.
                         //
@@ -657,7 +657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         format!("cannot apply unary operator `{}`", op.as_str()),
                     );
 
-                    if operand_ty.has_param_types_or_consts() {
+                    if operand_ty.has_non_region_param() {
                         let predicates = errors.iter().filter_map(|error| {
                             error.obligation.predicate.to_opt_poly_trait_pred()
                         });
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 7965ec1b43f41..d607f9014200e 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1428,9 +1428,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
             let substituted_pred = predicates.rebind(pred).subst(tcx, substs);
             // Don't check non-defaulted params, dependent defaults (including lifetimes)
             // or preds with multiple params.
-            if substituted_pred.has_param_types_or_consts()
-                || param_count.params.len() > 1
-                || has_region
+            if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
             {
                 None
             } else if predicates.0.predicates.iter().any(|&(p, _)| p == substituted_pred) {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index b9fd79e0d2f3a..70edcd10f5f32 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -712,9 +712,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     ) -> bool {
         // Reject any attempt to unify two unevaluated constants that contain inference
         // variables, since inference variables in queries lead to ICEs.
-        if a.substs.has_infer_types_or_consts()
-            || b.substs.has_infer_types_or_consts()
-            || param_env.has_infer_types_or_consts()
+        if a.substs.has_non_region_infer()
+            || b.substs.has_non_region_infer()
+            || param_env.has_non_region_infer()
         {
             debug!("a or b or param_env contain infer vars in its substs -> cannot unify");
             return false;
@@ -1734,7 +1734,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         // Postpone the evaluation of constants whose substs depend on inference
         // variables
-        if substs.has_infer_types_or_consts() {
+        if substs.has_non_region_infer() {
             let ac = AbstractConst::new(self.tcx, unevaluated);
             match ac {
                 Ok(None) => {
@@ -2072,21 +2072,17 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
 ) -> SubstsRef<'tcx> {
     tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
         match arg.unpack() {
-            GenericArgKind::Type(_)
-                if arg.has_param_types_or_consts() || arg.has_infer_types_or_consts() =>
-            {
+            GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
                 tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::ROOT,
                     name: ty::BoundVar::from_usize(idx),
                 }))
                 .into()
             }
-            GenericArgKind::Const(ct)
-                if ct.has_infer_types_or_consts() || ct.has_param_types_or_consts() =>
-            {
+            GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => {
                 let ty = ct.ty();
                 // If the type references param or infer, replace that too...
-                if ty.has_param_types_or_consts() || ty.has_infer_types_or_consts() {
+                if ty.has_non_region_param() || ty.has_non_region_infer() {
                     bug!("const `{ct}`'s type should not reference params or types");
                 }
                 tcx.mk_const(ty::ConstS {
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index bb6f6ae60e26a..91e73451a0fd3 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -357,7 +357,7 @@ where
             // In NLL, we don't have type inference variables
             // floating around, so we can do this rather imprecise
             // variant of the occurs-check.
-            assert!(!generalized_ty.has_infer_types_or_consts());
+            assert!(!generalized_ty.has_non_region_infer());
         }
 
         self.infcx.inner.borrow_mut().type_variables().instantiate(vid, generalized_ty);
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 3d99f0958f7f9..bb188496caa0d 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -32,7 +32,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.has_infer_types_or_consts() {
+        if !t.has_non_region_infer() {
             t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             let t = self.infcx.shallow_resolve(t);
@@ -41,7 +41,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
     }
 
     fn fold_const(&mut self, ct: Const<'tcx>) -> Const<'tcx> {
-        if !ct.has_infer_types_or_consts() {
+        if !ct.has_non_region_infer() {
             ct // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
             let ct = self.infcx.shallow_resolve(ct);
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 734c31192c7c3..8f67161420dad 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -45,7 +45,7 @@ impl<'tcx> TyCtxt<'tcx> {
         //
         // When trying to evaluate constants containing inference variables,
         // use `Infcx::const_eval_resolve` instead.
-        if ct.substs.has_infer_types_or_consts() {
+        if ct.substs.has_non_region_infer() {
             bug!("did not expect inference variables here");
         }
 
@@ -76,7 +76,7 @@ impl<'tcx> TyCtxt<'tcx> {
         //
         // When trying to evaluate constants containing inference variables,
         // use `Infcx::const_eval_resolve` instead.
-        if ct.substs.has_infer_types_or_consts() {
+        if ct.substs.has_non_region_infer() {
             bug!("did not expect inference variables here");
         }
 
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 78a1678881583..a9ebd78340331 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -313,7 +313,7 @@ impl<'tcx> Body<'tcx> {
             is_polymorphic: false,
             tainted_by_errors,
         };
-        body.is_polymorphic = body.has_param_types_or_consts();
+        body.is_polymorphic = body.has_non_region_param();
         body
     }
 
@@ -339,7 +339,7 @@ impl<'tcx> Body<'tcx> {
             is_polymorphic: false,
             tainted_by_errors: None,
         };
-        body.is_polymorphic = body.has_param_types_or_consts();
+        body.is_polymorphic = body.has_non_region_param();
         body
     }
 
@@ -2760,7 +2760,7 @@ fn pretty_print_const_value<'tcx>(
             }
             // Aggregates, printed as array/tuple/struct/variant construction syntax.
             //
-            // NB: the `has_param_types_or_consts` check ensures that we can use
+            // NB: the `has_non_region_param` check ensures that we can use
             // the `destructure_const` query with an empty `ty::ParamEnv` without
             // introducing ICEs (e.g. via `layout_of`) from missing bounds.
             // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
@@ -2768,7 +2768,7 @@ fn pretty_print_const_value<'tcx>(
             //
             // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
             // correct `ty::ParamEnv` to allow printing *all* constant values.
-            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
+            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
                 let ct = tcx.lift(ct).unwrap();
                 let ty = tcx.lift(ty).unwrap();
                 if let Some(contents) = tcx.try_destructure_mir_constant(
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 641e53f2a154c..1aa4df7780084 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -71,16 +71,16 @@ impl<'tcx> AbstractConst<'tcx> {
         walk_abstract_const::<!, _>(tcx, self, |node| {
             match node.root(tcx) {
                 Node::Leaf(leaf) => {
-                    if leaf.has_infer_types_or_consts() {
+                    if leaf.has_non_region_infer() {
                         failure_kind = FailureKind::MentionsInfer;
-                    } else if leaf.has_param_types_or_consts() {
+                    } else if leaf.has_non_region_param() {
                         failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
                     }
                 }
                 Node::Cast(_, _, ty) => {
-                    if ty.has_infer_types_or_consts() {
+                    if ty.has_non_region_infer() {
                         failure_kind = FailureKind::MentionsInfer;
-                    } else if ty.has_param_types_or_consts() {
+                    } else if ty.has_non_region_param() {
                         failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
                     }
                 }
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 41bb3c7140172..3be0bc4defc5c 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -132,7 +132,7 @@ pub fn simplify_type<'tcx>(
             // don't unify with anything else as long as they are fully normalized.
             //
             // We will have to be careful with lazy normalization here.
-            TreatParams::AsPlaceholder if !ty.has_infer_types_or_consts() => {
+            TreatParams::AsPlaceholder if !ty.has_non_region_infer() => {
                 debug!("treating `{}` as a placeholder", ty);
                 Some(PlaceholderSimplifiedType)
             }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 4fb4c9b11e7ea..5f8729a8ddf3c 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -244,7 +244,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
-        debug_assert!(!ty.has_infer_types_or_consts());
+        debug_assert!(!ty.has_non_region_infer());
 
         // First try computing a static layout.
         let err = match tcx.layout_of(param_env.and(ty)) {
@@ -260,7 +260,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
                 let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 match tail.kind() {
                     ty::Param(_) | ty::Projection(_) => {
-                        debug_assert!(tail.has_param_types_or_consts());
+                        debug_assert!(tail.has_non_region_param());
                         Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
                     }
                     _ => bug!(
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 9c3b6a794e19a..44efb93a53bfc 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -104,8 +104,8 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
             None
         }
     }
-    fn has_param_types_or_consts(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
+    fn has_non_region_param(&self) -> bool {
+        self.has_type_flags(TypeFlags::NEEDS_SUBST - TypeFlags::HAS_RE_PARAM)
     }
     fn has_infer_regions(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_RE_INFER)
@@ -113,8 +113,8 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
     fn has_infer_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_INFER)
     }
-    fn has_infer_types_or_consts(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER)
+    fn has_non_region_infer(&self) -> bool {
+        self.has_type_flags(TypeFlags::NEEDS_INFER - TypeFlags::HAS_RE_INFER)
     }
     fn needs_infer(&self) -> bool {
         self.has_type_flags(TypeFlags::NEEDS_INFER)
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index b7e3ca571e10b..a93f6a60114a6 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -290,7 +290,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
 impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !c.has_param_types_or_consts() {
+        if !c.has_non_region_param() {
             return ControlFlow::CONTINUE;
         }
 
@@ -311,7 +311,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
     }
 
     fn visit_mir_const(&mut self, constant: ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !constant.has_param_types_or_consts() {
+        if !constant.has_non_region_param() {
             return ControlFlow::CONTINUE;
         }
 
@@ -336,7 +336,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
 
     #[instrument(level = "debug", skip(self))]
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !ty.has_param_types_or_consts() {
+        if !ty.has_non_region_param() {
             return ControlFlow::CONTINUE;
         }
 
@@ -373,7 +373,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
 
     #[instrument(level = "debug", skip(self))]
     fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !c.has_param_types_or_consts() {
+        if !c.has_non_region_param() {
             return ControlFlow::CONTINUE;
         }
 
@@ -391,7 +391,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
 
     #[instrument(level = "debug", skip(self))]
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !ty.has_param_types_or_consts() {
+        if !ty.has_non_region_param() {
             return ControlFlow::CONTINUE;
         }
 
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 18e7e74741af8..ecfe6861e84cb 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -301,7 +301,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
         // Encode impl generic params if the substitutions contain parameters (implying
         // polymorphization is enabled) and this isn't an inherent impl.
-        if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
+        if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_non_region_param()) {
             self = self.path_generic_args(
                 |this| {
                     this.path_append_ns(
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 3f98db6b2a924..911d1cf8bdf6b 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -236,9 +236,9 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
             }
 
             Err(ErrorHandled::TooGeneric) => {
-                let err = if uv.has_infer_types_or_consts() {
+                let err = if uv.has_non_region_infer() {
                     NotConstEvaluatable::MentionsInfer
-                } else if uv.has_param_types_or_consts() {
+                } else if uv.has_non_region_param() {
                     NotConstEvaluatable::MentionsParam
                 } else {
                     let guar = infcx.tcx.sess.delay_span_bug(span, format!("Missing value for constant, but no error reported?"));
@@ -254,7 +254,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
             }
             Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
             Ok(_) => {
-                if uv.substs.has_param_types_or_consts() {
+                if uv.substs.has_non_region_param() {
                     assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
                     let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 5fdadd0b4b41b..4398d71a89d42 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -661,7 +661,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                                     );
                                 }
                             }
-                        } else if !trait_ref.has_infer_types_or_consts()
+                        } else if !trait_ref.has_non_region_infer()
                             && self.predicate_can_apply(obligation.param_env, trait_ref)
                         {
                             // If a where-clause may be useful, remind the
@@ -2093,7 +2093,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                 // Pick the first substitution that still contains inference variables as the one
                 // we're going to emit an error for. If there are none (see above), fall back to
                 // a more general error.
-                let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts());
+                let subst = data.trait_ref.substs.iter().find(|s| s.has_non_region_infer());
 
                 let mut err = if let Some(subst) = subst {
                     self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283, true)
@@ -2323,7 +2323,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                     .substs
                     .iter()
                     .chain(Some(data.term.into_arg()))
-                    .find(|g| g.has_infer_types_or_consts());
+                    .find(|g| g.has_non_region_infer());
                 if let Some(subst) = subst {
                     let mut err = self.emit_inference_failure_err(
                         body_id,
@@ -2352,7 +2352,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                 if predicate.references_error() || self.is_tainted_by_errors() {
                     return;
                 }
-                let subst = data.substs.iter().find(|g| g.has_infer_types_or_consts());
+                let subst = data.substs.iter().find(|g| g.has_non_region_infer());
                 if let Some(subst) = subst {
                     let err = self.emit_inference_failure_err(
                         body_id,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 698fc81c58775..7aae014af6044 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1231,7 +1231,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 return;
             }
             let trait_pred = self.resolve_vars_if_possible(trait_pred);
-            if trait_pred.has_infer_types_or_consts() {
+            if trait_pred.has_non_region_infer() {
                 // Do not ICE while trying to find if a reborrow would succeed on a trait with
                 // unresolved bindings.
                 return;
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index f13736a76b214..5802f038e893c 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -279,7 +279,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
 
         debug!(?obligation, "pre-resolve");
 
-        if obligation.predicate.has_infer_types_or_consts() {
+        if obligation.predicate.has_non_region_infer() {
             obligation.predicate =
                 self.selcx.infcx().resolve_vars_if_possible(obligation.predicate);
         }
@@ -569,7 +569,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                             )
                         }
                         (Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
-                            if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
+                            if c1.has_non_region_infer() || c2.has_non_region_infer() {
                                 ProcessResult::Unchanged
                             } else {
                                 // Two different constants using generic parameters ~> error.
@@ -726,11 +726,11 @@ fn substs_infer_vars<'a, 'tcx>(
         .resolve_vars_if_possible(substs)
         .skip_binder() // ok because this check doesn't care about regions
         .iter()
-        .filter(|arg| arg.has_infer_types_or_consts())
+        .filter(|arg| arg.has_non_region_infer())
         .flat_map(|arg| {
             let mut walker = arg.walk();
             while let Some(c) = walker.next() {
-                if !c.has_infer_types_or_consts() {
+                if !c.has_non_region_infer() {
                     walker.visited.remove(&c);
                     walker.skip_current_subtree();
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index e1bd48ba8aca8..41b742734cd8d 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -57,7 +57,7 @@ pub fn can_type_implement_copy<'tcx>(
                 // to begin with, and point to the bad field's span instead.
                 let cause = if field
                     .ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
-                    .has_param_types_or_consts()
+                    .has_non_region_param()
                 {
                     parent_cause.clone()
                 } else {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 8da68c225d8e7..659ffc178aa54 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -170,7 +170,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
         result
     );
 
-    if result && ty.has_infer_types_or_consts() {
+    if result && ty.has_non_region_infer() {
         // Because of inference "guessing", selection can sometimes claim
         // to succeed while the success requires a guess. To ensure
         // this function's result remains infallible, we must confirm
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 07b65a9748d7c..7db96c0cef01c 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1488,7 +1488,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
                     candidate_set.push_candidate(ctor(data));
 
                     if potentially_unnormalized_candidates
-                        && !obligation.predicate.has_infer_types_or_consts()
+                        && !obligation.predicate.has_non_region_infer()
                     {
                         // HACK: Pick the first trait def candidate for a fully
                         // inferred predicate. This is to allow duplicates that
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 6d856435355ed..9a8331614b0e8 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -174,7 +174,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         debug!(?stack, ?candidates, "winnowed to {} candidates", candidates.len());
 
-        let needs_infer = stack.obligation.predicate.has_infer_types_or_consts();
+        let needs_infer = stack.obligation.predicate.has_non_region_infer();
 
         // If there are STILL multiple candidates, we can further
         // reduce the list by dropping duplicates -- including
@@ -889,11 +889,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &TraitObligation<'tcx>,
         candidates: &mut SelectionCandidateSet<'tcx>,
     ) {
-        if obligation.has_param_types_or_consts() {
+        if obligation.has_non_region_param() {
             return;
         }
 
-        if obligation.has_infer_types_or_consts() {
+        if obligation.has_non_region_infer() {
             candidates.ambiguous = true;
             return;
         }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index bac3498523704..8f2a6f337baad 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -728,7 +728,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             )
                         }
                         (Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
-                            if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
+                            if c1.has_non_region_infer() || c2.has_non_region_infer() {
                                 Ok(EvaluatedToAmbig)
                             } else {
                                 // Two different constants using generic parameters ~> error.
@@ -1520,7 +1520,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             if !generics.params.is_empty()
                 && obligation.predicate.substs[generics.parent_count..]
                     .iter()
-                    .any(|&p| p.has_infer_types_or_consts() && self.infcx.shallow_resolve(p) != p)
+                    .any(|&p| p.has_non_region_infer() && self.infcx.shallow_resolve(p) != p)
             {
                 ProjectionMatchesProjection::Ambiguous
             } else {
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 32aca4a8a3f91..e540ee1664d1d 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -79,7 +79,7 @@ fn compute_implied_outlives_bounds<'tcx>(
         // implied bounds in some cases, mostly when dealing with projections.
         fulfill_cx.register_predicate_obligations(
             infcx,
-            obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(),
+            obligations.iter().filter(|o| o.predicate.has_non_region_infer()).cloned(),
         );
 
         // From the full set of obligations, just filter down to the
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 493ef33511355..e057bb6682501 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -135,30 +135,30 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
 
         impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
             fn expr_is_poly(&mut self, expr: &thir::Expr<'tcx>) -> bool {
-                if expr.ty.has_param_types_or_consts() {
+                if expr.ty.has_non_region_param() {
                     return true;
                 }
 
                 match expr.kind {
-                    thir::ExprKind::NamedConst { substs, .. } => substs.has_param_types_or_consts(),
+                    thir::ExprKind::NamedConst { substs, .. } => substs.has_non_region_param(),
                     thir::ExprKind::ConstParam { .. } => true,
                     thir::ExprKind::Repeat { value, count } => {
                         self.visit_expr(&self.thir()[value]);
-                        count.has_param_types_or_consts()
+                        count.has_non_region_param()
                     }
                     _ => false,
                 }
             }
 
             fn pat_is_poly(&mut self, pat: &thir::Pat<'tcx>) -> bool {
-                if pat.ty.has_param_types_or_consts() {
+                if pat.ty.has_non_region_param() {
                     return true;
                 }
 
                 match pat.kind {
-                    thir::PatKind::Constant { value } => value.has_param_types_or_consts(),
+                    thir::PatKind::Constant { value } => value.has_non_region_param(),
                     thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
-                        lo.has_param_types_or_consts() || hi.has_param_types_or_consts()
+                        lo.has_non_region_param() || hi.has_non_region_param()
                     }
                     _ => false,
                 }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 9e4dc26bfd4d2..345911f4309ae 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -351,7 +351,7 @@ fn layout_of_uncached<'tcx>(
     let univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| {
         Ok(tcx.intern_layout(univariant_uninterned(cx, ty, fields, repr, kind)?))
     };
-    debug_assert!(!ty.has_infer_types_or_consts());
+    debug_assert!(!ty.has_non_region_infer());
 
     Ok(match *ty.kind() {
         // Basic scalars.
@@ -1688,7 +1688,7 @@ fn record_layout_for_printing_outlined<'tcx>(
     // Ignore layouts that are done with non-empty environments or
     // non-monomorphic layouts, as the user only wants to see the stuff
     // resulting from the final codegen session.
-    if layout.ty.has_param_types_or_consts() || !cx.param_env.caller_bounds().is_empty() {
+    if layout.ty.has_non_region_param() || !cx.param_env.caller_bounds().is_empty() {
         return;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index e54d71fc8e417..f0d5ed6f594bd 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1238,7 +1238,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
             ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => {
                 Position::ReborrowStable(precedence).into()
             },
-            ty::Adt(_, substs) if substs.has_param_types_or_consts() => {
+            ty::Adt(_, substs) if substs.has_non_region_param() => {
                 TyPosition::new_deref_stable_for_result(precedence, ty)
             },
             ty::Bool

From 93a17c8aeade5ea650e6dc5c047d895e3afaa091 Mon Sep 17 00:00:00 2001
From: lcnr <rust@lcnr.de>
Date: Tue, 4 Oct 2022 14:18:11 +0200
Subject: [PATCH 8/8] missing value to delay_span_bug

---
 compiler/rustc_ty_utils/src/instance.rs | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index fa1dc90e4a24b..81ca8b646fff1 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -171,9 +171,13 @@ fn resolve_associated_item<'tcx>(
                 return Ok(None);
             }
 
-            // If the item does not have a value, then we cannot return an instance.
+            // Any final impl is required to define all associated items.
             if !leaf_def.item.defaultness(tcx).has_value() {
-                return Ok(None);
+                let guard = tcx.sess.delay_span_bug(
+                    tcx.def_span(leaf_def.item.def_id),
+                    "missing value for assoc item in impl",
+                );
+                return Err(guard);
             }
 
             let substs = tcx.erase_regions(substs);