diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 9c33cc8ed0b9c..dbb88e42a3eb9 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -518,7 +518,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // RFC 2397
     gated!(
         do_not_recommend, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, experimental!(do_not_recommend)
+        EncodeCrossCrate::Yes, experimental!(do_not_recommend)
     ),
 
     // `#[cfi_encoding = ""]`
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 796222129f180..c72488331e828 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -11,6 +11,7 @@ use rustc_infer::traits::{
 };
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::symbol::sym;
 
 use super::eval_ctxt::GenerateProofTree;
 use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
@@ -320,6 +321,14 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             return ControlFlow::Break(self.obligation.clone());
         };
 
+        // Don't walk into impls that have `do_not_recommend`.
+        if let ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } =
+            candidate.kind()
+            && goal.infcx().tcx.has_attr(impl_def_id, sym::do_not_recommend)
+        {
+            return ControlFlow::Break(self.obligation.clone());
+        }
+
         // FIXME: Could we extract a trait ref from a projection here too?
         // FIXME: Also, what about considering >1 layer up the stack? May be necessary
         // for normalizes-to.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
new file mode 100644
index 0000000000000..a4d4b7b359ec8
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `*mut (): Foo` is not satisfied
+  --> $DIR/simple.rs:19:17
+   |
+LL |     needs_foo::<*mut ()>();
+   |                 ^^^^^^^ the trait `Send` is not implemented for `*mut ()`, which is required by `*mut (): Foo`
+   |
+note: required for `*mut ()` to implement `Foo`
+  --> $DIR/simple.rs:10:9
+   |
+LL | impl<T> Foo for T where T: Send {}
+   |         ^^^     ^          ---- unsatisfied trait bound introduced here
+note: required by a bound in `needs_foo`
+  --> $DIR/simple.rs:14:17
+   |
+LL | fn needs_foo<T: Foo>() {}
+   |                 ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
new file mode 100644
index 0000000000000..1341ca8175aff
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `*mut (): Foo` is not satisfied
+  --> $DIR/simple.rs:19:17
+   |
+LL |     needs_foo::<*mut ()>();
+   |                 ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
+   |
+note: required by a bound in `needs_foo`
+  --> $DIR/simple.rs:14:17
+   |
+LL | fn needs_foo<T: Foo>() {}
+   |                 ^^^ required by this bound in `needs_foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
new file mode 100644
index 0000000000000..15ff80ae4d953
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
@@ -0,0 +1,23 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#![feature(do_not_recommend)]
+
+trait Foo {}
+
+#[do_not_recommend]
+impl<T> Foo for T where T: Send {}
+//[current]~^ NOTE required for `*mut ()` to implement `Foo`
+//[current]~| NOTE unsatisfied trait bound introduced here
+
+fn needs_foo<T: Foo>() {}
+//~^ NOTE required by a bound in `needs_foo`
+//~| NOTE required by this bound in `needs_foo`
+
+fn main() {
+    needs_foo::<*mut ()>();
+    //~^ ERROR the trait bound `*mut (): Foo` is not satisfied
+    //[current]~| NOTE the trait `Send` is not implemented for `*mut ()`
+    //[next]~| NOTE the trait `Foo` is not implemented for `*mut ()`
+}