diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index a5709089db689..8cc475b536d17 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -168,12 +168,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             match hir_bound {
                 hir::GenericBound::Trait(poly_trait_ref) => {
                     let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers;
-                    let polarity = match polarity {
-                        rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
-                        rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
-                        rustc_ast::BoundPolarity::Maybe(_) => continue,
-                    };
-
                     let _ = self.lower_poly_trait_ref(
                         &poly_trait_ref.trait_ref,
                         poly_trait_ref.span,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index f2ee4b0ccd417..7ece2632b6eb7 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -51,7 +51,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 &trait_bound.trait_ref,
                 trait_bound.span,
                 hir::BoundConstness::Never,
-                ty::PredicatePolarity::Positive,
+                hir::BoundPolarity::Positive,
                 dummy_self,
                 &mut bounds,
                 PredicateFilter::SelfOnly,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 2d0c3ec28c372..738b31331284f 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -659,7 +659,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         trait_ref: &hir::TraitRef<'tcx>,
         span: Span,
         constness: hir::BoundConstness,
-        polarity: ty::PredicatePolarity,
+        polarity: hir::BoundPolarity,
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
         predicate_filter: PredicateFilter,
@@ -681,15 +681,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             Some(self_ty),
         );
 
-        if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
-            && !self.tcx().is_const_trait(trait_def_id)
-        {
-            self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
-                span,
-                modifier: constness.as_str(),
-            });
-        }
-
         let tcx = self.tcx();
         let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
         debug!(?bound_vars);
@@ -699,6 +690,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             bound_vars,
         );
 
+        let polarity = match polarity {
+            rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
+            rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
+            rustc_ast::BoundPolarity::Maybe(_) => {
+                // Validate associated type at least. We may want to reject these
+                // outright in the future...
+                for constraint in trait_segment.args().constraints {
+                    let _ = self.lower_assoc_item_constraint(
+                        trait_ref.hir_ref_id,
+                        poly_trait_ref,
+                        constraint,
+                        &mut Default::default(),
+                        &mut Default::default(),
+                        constraint.span,
+                        predicate_filter,
+                    );
+                }
+                return arg_count;
+            }
+        };
+
+        if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
+            && !self.tcx().is_const_trait(trait_def_id)
+        {
+            self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
+                span,
+                modifier: constness.as_str(),
+            });
+        }
+
         match predicate_filter {
             PredicateFilter::All
             | PredicateFilter::SelfOnly
@@ -749,11 +770,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             // since we should have emitted an error for them earlier, and they
             // would not be well-formed!
             if polarity != ty::PredicatePolarity::Positive {
-                assert!(
-                    self.dcx().has_errors().is_some(),
+                self.dcx().span_delayed_bug(
+                    constraint.span,
                     "negative trait bounds should not have assoc item constraints",
                 );
-                continue;
+                break;
             }
 
             // Specify type to assert that error was already reported in `Err` case.
diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
index 4769581466898..46121308fa07c 100644
--- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
+++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs
@@ -3,8 +3,6 @@
 fn polarity() -> impl Sized + ?use<> {}
 //~^ ERROR expected identifier, found keyword `use`
 //~| ERROR cannot find trait `r#use` in this scope
-//~| WARN relaxing a default bound only does something for `?Sized`
-//~| WARN relaxing a default bound only does something for `?Sized`
 
 fn asyncness() -> impl Sized + async use<> {}
 //~^ ERROR expected identifier, found keyword `use`
diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
index aaebfe2a86e55..16e7470debf09 100644
--- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
+++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr
@@ -5,19 +5,19 @@ LL | fn polarity() -> impl Sized + ?use<> {}
    |                                ^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `use`
-  --> $DIR/bound-modifiers.rs:9:38
+  --> $DIR/bound-modifiers.rs:7:38
    |
 LL | fn asyncness() -> impl Sized + async use<> {}
    |                                      ^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `use`
-  --> $DIR/bound-modifiers.rs:14:38
+  --> $DIR/bound-modifiers.rs:12:38
    |
 LL | fn constness() -> impl Sized + const use<> {}
    |                                      ^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `use`
-  --> $DIR/bound-modifiers.rs:19:37
+  --> $DIR/bound-modifiers.rs:17:37
    |
 LL | fn binder() -> impl Sized + for<'a> use<> {}
    |                                     ^^^ expected identifier, found keyword
@@ -29,25 +29,25 @@ LL | fn polarity() -> impl Sized + ?use<> {}
    |                                ^^^ not found in this scope
 
 error[E0405]: cannot find trait `r#use` in this scope
-  --> $DIR/bound-modifiers.rs:9:38
+  --> $DIR/bound-modifiers.rs:7:38
    |
 LL | fn asyncness() -> impl Sized + async use<> {}
    |                                      ^^^ not found in this scope
 
 error[E0405]: cannot find trait `r#use` in this scope
-  --> $DIR/bound-modifiers.rs:14:38
+  --> $DIR/bound-modifiers.rs:12:38
    |
 LL | fn constness() -> impl Sized + const use<> {}
    |                                      ^^^ not found in this scope
 
 error[E0405]: cannot find trait `r#use` in this scope
-  --> $DIR/bound-modifiers.rs:19:37
+  --> $DIR/bound-modifiers.rs:17:37
    |
 LL | fn binder() -> impl Sized + for<'a> use<> {}
    |                                     ^^^ not found in this scope
 
 error[E0658]: async closures are unstable
-  --> $DIR/bound-modifiers.rs:9:32
+  --> $DIR/bound-modifiers.rs:7:32
    |
 LL | fn asyncness() -> impl Sized + async use<> {}
    |                                ^^^^^
@@ -58,7 +58,7 @@ LL | fn asyncness() -> impl Sized + async use<> {}
    = help: to use an async block, remove the `||`: `async {`
 
 error[E0658]: const trait impls are experimental
-  --> $DIR/bound-modifiers.rs:14:32
+  --> $DIR/bound-modifiers.rs:12:32
    |
 LL | fn constness() -> impl Sized + const use<> {}
    |                                ^^^^^
@@ -67,21 +67,7 @@ LL | fn constness() -> impl Sized + const use<> {}
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-  --> $DIR/bound-modifiers.rs:3:31
-   |
-LL | fn polarity() -> impl Sized + ?use<> {}
-   |                               ^^^^^^
-
-warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
-  --> $DIR/bound-modifiers.rs:3:31
-   |
-LL | fn polarity() -> impl Sized + ?use<> {}
-   |                               ^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 10 previous errors; 2 warnings emitted
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0405, E0658.
 For more information about an error, try `rustc --explain E0405`.
diff --git a/tests/ui/issues/issue-37534.rs b/tests/ui/issues/issue-37534.rs
index 40f7186db098e..dff89d3888d0c 100644
--- a/tests/ui/issues/issue-37534.rs
+++ b/tests/ui/issues/issue-37534.rs
@@ -1,6 +1,5 @@
 struct Foo<T: ?Hash> {}
 //~^ ERROR expected trait, found derive macro `Hash`
-//~^^ ERROR parameter `T` is never used
-//~^^^ WARN relaxing a default bound only does something for `?Sized`
+//~| WARN relaxing a default bound only does something for `?Sized`
 
 fn main() {}
diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr
index a687e733d3dae..8747bd5ac6fad 100644
--- a/tests/ui/issues/issue-37534.stderr
+++ b/tests/ui/issues/issue-37534.stderr
@@ -15,15 +15,6 @@ warning: relaxing a default bound only does something for `?Sized`; all other tr
 LL | struct Foo<T: ?Hash> {}
    |               ^^^^^
 
-error[E0392]: type parameter `T` is never used
-  --> $DIR/issue-37534.rs:1:12
-   |
-LL | struct Foo<T: ?Hash> {}
-   |            ^ unused type parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
-Some errors have detailed explanations: E0392, E0404.
-For more information about an error, try `rustc --explain E0392`.
+For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/trait-bounds/maybe-bound-generics-deny.rs b/tests/ui/trait-bounds/maybe-bound-generics-deny.rs
new file mode 100644
index 0000000000000..dfa8e9886b6b8
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-generics-deny.rs
@@ -0,0 +1,4 @@
+fn uwu<T: ?Sized<i32>>() {}
+//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/maybe-bound-generics-deny.stderr b/tests/ui/trait-bounds/maybe-bound-generics-deny.stderr
new file mode 100644
index 0000000000000..3297eb6279fab
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-generics-deny.stderr
@@ -0,0 +1,11 @@
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/maybe-bound-generics-deny.rs:1:12
+   |
+LL | fn uwu<T: ?Sized<i32>>() {}
+   |            ^^^^^----- help: remove the unnecessary generics
+   |            |
+   |            expected 0 generic arguments
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs
new file mode 100644
index 0000000000000..2cb63f25d063d
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs
@@ -0,0 +1,7 @@
+trait Trait {}
+
+fn test<T: ?self::<i32>::Trait>() {}
+//~^ ERROR type arguments are not allowed on this type
+//~| WARN relaxing a default bound only does something for `?Sized`
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr
new file mode 100644
index 0000000000000..701e493f5a527
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr
@@ -0,0 +1,17 @@
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-bound-has-path-args.rs:3:12
+   |
+LL | fn test<T: ?self::<i32>::Trait>() {}
+   |            ^^^^^^^^^^^^^^^^^^^
+
+error[E0109]: type arguments are not allowed on this type
+  --> $DIR/maybe-bound-has-path-args.rs:3:20
+   |
+LL | fn test<T: ?self::<i32>::Trait>() {}
+   |             ----   ^^^ type argument not allowed
+   |             |
+   |             not allowed on this type
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0109`.
diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.rs b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs
new file mode 100644
index 0000000000000..b6b2551e4638e
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs
@@ -0,0 +1,12 @@
+trait HasAssoc {
+    type Assoc;
+}
+fn hasassoc<T: ?HasAssoc<Assoc = ()>>() {}
+//~^ WARN relaxing a default bound
+
+trait NoAssoc {}
+fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
+//~^ WARN relaxing a default bound
+//~| ERROR associated type `Missing` not found for `NoAssoc`
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr
new file mode 100644
index 0000000000000..91d78e59cd5a7
--- /dev/null
+++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr
@@ -0,0 +1,21 @@
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-bound-with-assoc.rs:4:16
+   |
+LL | fn hasassoc<T: ?HasAssoc<Assoc = ()>>() {}
+   |                ^^^^^^^^^^^^^^^^^^^^^
+
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-bound-with-assoc.rs:8:15
+   |
+LL | fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0220]: associated type `Missing` not found for `NoAssoc`
+  --> $DIR/maybe-bound-with-assoc.rs:8:24
+   |
+LL | fn noassoc<T: ?NoAssoc<Missing = ()>>() {}
+   |                        ^^^^^^^ associated type `Missing` not found
+
+error: aborting due to 1 previous error; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0220`.