about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs34
-rw-r--r--tests/ui/dropck/const_drop_is_valid.rs11
-rw-r--r--tests/ui/dropck/const_drop_is_valid.stderr45
-rw-r--r--tests/ui/dropck/constrained_by_assoc_type_equality.rs13
-rw-r--r--tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs12
-rw-r--r--tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr15
-rw-r--r--tests/ui/dropck/reject-specialized-drops-8142.rs202
-rw-r--r--tests/ui/dropck/reject-specialized-drops-8142.stderr133
-rw-r--r--tests/ui/dropck/transitive-outlives.bad.stderr9
-rw-r--r--tests/ui/dropck/transitive-outlives.rs2
-rw-r--r--tests/ui/dropck/unconstrained_const_param_on_drop.rs7
-rw-r--r--tests/ui/dropck/unconstrained_const_param_on_drop.stderr25
12 files changed, 358 insertions, 150 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 19371448025..06ec01484a4 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -6,10 +6,10 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
-use rustc_infer::traits::ObligationCauseCode;
+use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::util::CheckRegions;
-use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{GenericArgsRef, Ty};
 use rustc_trait_selection::regions::InferCtxtRegionExt;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 
@@ -115,8 +115,9 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
     Err(err.emit())
 }
 
-/// Confirms that every predicate imposed by dtor_predicates is
-/// implied by assuming the predicates attached to self_type_did.
+/// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
+/// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
+/// implied by the ADT being well formed.
 fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     tcx: TyCtxt<'tcx>,
     drop_impl_def_id: LocalDefId,
@@ -126,6 +127,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     let infcx = tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
 
+    let impl_span = tcx.def_span(drop_impl_def_id.to_def_id());
+
     // Take the param-env of the adt and instantiate the args that show up in
     // the implementation's self type. This gives us the assumptions that the
     // self ty of the implementation is allowed to know just from it being a
@@ -135,14 +138,27 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     // We don't need to normalize this param-env or anything, since we're only
     // instantiating it with free params, so no additional param-env normalization
     // can occur on top of what has been done in the param_env query itself.
-    let param_env =
+    //
+    // Note: Ideally instead of instantiating the `ParamEnv` with the arguments from the impl ty we
+    // could instead use identity args for the adt. Unfortunately this would cause any errors to
+    // reference the params from the ADT instead of from the impl which is bad UX. To resolve
+    // this we "rename" the ADT's params to be the impl's params which should not affect behaviour.
+    let impl_adt_ty = Ty::new_adt(tcx, tcx.adt_def(adt_def_id), adt_to_impl_args);
+    let adt_env =
         ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
 
-    for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
+    let fresh_impl_args = infcx.fresh_args_for_item(impl_span, drop_impl_def_id.to_def_id());
+    let fresh_adt_ty =
+        tcx.impl_trait_ref(drop_impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty();
+
+    ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty)
+        .unwrap();
+
+    for (clause, span) in tcx.predicates_of(drop_impl_def_id).instantiate(tcx, fresh_impl_args) {
         let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);
-        let pred = ocx.normalize(&normalize_cause, param_env, pred);
+        let pred = ocx.normalize(&normalize_cause, adt_env, clause);
         let cause = traits::ObligationCause::new(span, adt_def_id, ObligationCauseCode::DropImpl);
-        ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, pred));
+        ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred));
     }
 
     // All of the custom error reporting logic is to preserve parity with the old
@@ -176,7 +192,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
         return Err(guar.unwrap());
     }
 
-    let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(param_env));
+    let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(adt_env));
     if !errors.is_empty() {
         let mut guar = None;
         for error in errors {
diff --git a/tests/ui/dropck/const_drop_is_valid.rs b/tests/ui/dropck/const_drop_is_valid.rs
new file mode 100644
index 00000000000..0441b6ed067
--- /dev/null
+++ b/tests/ui/dropck/const_drop_is_valid.rs
@@ -0,0 +1,11 @@
+#![feature(effects)]
+//~^ WARN: the feature `effects` is incomplete
+
+struct A();
+
+impl const Drop for A {}
+//~^ ERROR: const trait impls are experimental
+//~| const `impl` for trait `Drop` which is not marked with `#[const_trait]`
+//~| not all trait items implemented, missing: `drop`
+
+fn main() {}
diff --git a/tests/ui/dropck/const_drop_is_valid.stderr b/tests/ui/dropck/const_drop_is_valid.stderr
new file mode 100644
index 00000000000..f15b7ba946d
--- /dev/null
+++ b/tests/ui/dropck/const_drop_is_valid.stderr
@@ -0,0 +1,45 @@
+error[E0658]: const trait impls are experimental
+  --> $DIR/const_drop_is_valid.rs:6:6
+   |
+LL | impl const Drop for A {}
+   |      ^^^^^
+   |
+   = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+   = 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: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/const_drop_is_valid.rs:1:12
+   |
+LL | #![feature(effects)]
+   |            ^^^^^^^
+   |
+   = note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: using `#![feature(effects)]` without enabling next trait solver globally
+   |
+   = note: the next trait solver must be enabled globally for the effects feature to work correctly
+   = help: use `-Znext-solver` to enable
+
+error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
+  --> $DIR/const_drop_is_valid.rs:6:12
+   |
+LL | impl const Drop for A {}
+   |            ^^^^
+   |
+   = 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[E0046]: not all trait items implemented, missing: `drop`
+  --> $DIR/const_drop_is_valid.rs:6:1
+   |
+LL | impl const Drop for A {}
+   | ^^^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation
+   |
+   = help: implement the missing item: `fn drop(&mut self) { todo!() }`
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0046, E0658.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality.rs b/tests/ui/dropck/constrained_by_assoc_type_equality.rs
new file mode 100644
index 00000000000..4101fe83c3b
--- /dev/null
+++ b/tests/ui/dropck/constrained_by_assoc_type_equality.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+
+struct Foo<T: Trait>(T);
+
+trait Trait {
+    type Assoc;
+}
+
+impl<T: Trait<Assoc = U>, U: ?Sized> Drop for Foo<T> {
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs
new file mode 100644
index 00000000000..3a85b86cb1f
--- /dev/null
+++ b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs
@@ -0,0 +1,12 @@
+trait Trait {
+    type Assoc;
+}
+
+struct Foo<T: Trait, U: ?Sized>(T, U);
+
+impl<T: Trait<Assoc = U>, U: ?Sized> Drop for Foo<T, U> {
+    //~^ ERROR: `Drop` impl requires `<T as Trait>::Assoc == U`
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr
new file mode 100644
index 00000000000..dab8c55d0e7
--- /dev/null
+++ b/tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.stderr
@@ -0,0 +1,15 @@
+error[E0367]: `Drop` impl requires `<T as Trait>::Assoc == U` but the struct it is implemented for does not
+  --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:7:15
+   |
+LL | impl<T: Trait<Assoc = U>, U: ?Sized> Drop for Foo<T, U> {
+   |               ^^^^^^^^^
+   |
+note: the implementor must specify the same requirement
+  --> $DIR/constrained_by_assoc_type_equality_and_self_ty.rs:5:1
+   |
+LL | struct Foo<T: Trait, U: ?Sized>(T, U);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0367`.
diff --git a/tests/ui/dropck/reject-specialized-drops-8142.rs b/tests/ui/dropck/reject-specialized-drops-8142.rs
index 7a3bbe7cb09..1b73fe9a065 100644
--- a/tests/ui/dropck/reject-specialized-drops-8142.rs
+++ b/tests/ui/dropck/reject-specialized-drops-8142.rs
@@ -1,75 +1,145 @@
 // Issue 8142: Test that Drop impls cannot be specialized beyond the
 // predicates attached to the type definition itself.
-trait Bound { fn foo(&self) { } }
-struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
-struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
-struct M<'m> { x: &'m i8 }
-struct N<'n> { x: &'n i8 }
-struct O<To> { x: *const To }
-struct P<Tp> { x: *const Tp }
-struct Q<Tq> { x: *const Tq }
-struct R<Tr> { x: *const Tr }
-struct S<Ts:Bound> { x: *const Ts }
-struct T<'t,Ts:'t> { x: &'t Ts }
+trait Bound {
+    fn foo(&self) {}
+}
+struct K<'l1, 'l2> {
+    x: &'l1 i8,
+    y: &'l2 u8,
+}
+struct L<'l1, 'l2> {
+    x: &'l1 i8,
+    y: &'l2 u8,
+}
+struct M<'m> {
+    x: &'m i8,
+}
+struct N<'n> {
+    x: &'n i8,
+}
+struct O<To> {
+    x: *const To,
+}
+struct P<Tp> {
+    x: *const Tp,
+}
+struct Q<Tq> {
+    x: *const Tq,
+}
+struct R<Tr> {
+    x: *const Tr,
+}
+struct S<Ts: Bound> {
+    x: *const Ts,
+}
+struct T<'t, Ts: 't> {
+    x: &'t Ts,
+}
 struct U;
-struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
-struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
+struct V<Tva, Tvb> {
+    x: *const Tva,
+    y: *const Tvb,
+}
+struct W<'l1, 'l2> {
+    x: &'l1 i8,
+    y: &'l2 u8,
+}
 struct X<const Ca: usize>;
 struct Y<const Ca: usize, const Cb: usize>;
 
-enum Enum<T> { Variant(T) }
+enum Enum<T> {
+    Variant(T),
+}
 struct TupleStruct<T>(T);
-union Union<T: Copy> { f: T }
+union Union<T: Copy> {
+    f: T,
+}
 
-impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> {                        // REJECT
+impl<'al, 'adds_bnd: 'al> Drop for K<'al, 'adds_bnd> {
     //~^ ERROR `Drop` impl requires `'adds_bnd: 'al`
-    fn drop(&mut self) { } }
-
-impl<'al,'adds_bnd>     Drop for L<'al,'adds_bnd> where 'adds_bnd:'al {    // REJECT
-    //~^ ERROR `Drop` impl requires `'adds_bnd: 'al`
-    fn drop(&mut self) { } }
-
-impl<'ml>               Drop for M<'ml>         { fn drop(&mut self) { } } // ACCEPT
-
-impl                    Drop for N<'static>     { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impls cannot be specialized
-
-impl<COkNoBound> Drop for O<COkNoBound> { fn drop(&mut self) { } } // ACCEPT
-
-impl              Drop for P<i8>          { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impls cannot be specialized
-
-impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
-
-impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impl requires `AddsRBnd: 'rbnd`
-
-impl<Bs:Bound>    Drop for S<Bs>          { fn drop(&mut self) { } } // ACCEPT
-
-impl<'t,Bt:'t>    Drop for T<'t,Bt>       { fn drop(&mut self) { } } // ACCEPT
-
-impl              Drop for U              { fn drop(&mut self) { } } // ACCEPT
-
-impl<One>         Drop for V<One,One>     { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impls cannot be specialized
-
-impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impls cannot be specialized
-
-impl              Drop for X<3>           { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impls cannot be specialized
-
-impl<const Ca: usize> Drop for Y<Ca, Ca>     { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impls cannot be specialized
-
-impl<AddsBnd:Bound> Drop for Enum<AddsBnd> { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
-
-impl<AddsBnd:Bound> Drop for TupleStruct<AddsBnd> { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
-
-impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT
-//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
-
-pub fn main() { }
+    fn drop(&mut self) {}
+}
+
+impl<'al, 'adds_bnd> Drop for L<'al, 'adds_bnd>
+//~^ ERROR `Drop` impl requires `'adds_bnd: 'al`
+where
+    'adds_bnd: 'al,
+{
+    fn drop(&mut self) {}
+}
+
+impl<'ml> Drop for M<'ml> {
+    fn drop(&mut self) {}
+}
+
+impl Drop for N<'static> {
+    //~^ ERROR `Drop` impls cannot be specialized
+    fn drop(&mut self) {}
+}
+
+impl<COkNoBound> Drop for O<COkNoBound> {
+    fn drop(&mut self) {}
+}
+
+impl Drop for P<i8> {
+    //~^ ERROR `Drop` impls cannot be specialized
+    fn drop(&mut self) {}
+}
+
+impl<AddsBnd: Bound> Drop for Q<AddsBnd> {
+    //~^ ERROR `Drop` impl requires `AddsBnd: Bound`
+    fn drop(&mut self) {}
+}
+
+impl<'rbnd, AddsRBnd: 'rbnd> Drop for R<AddsRBnd> {
+    fn drop(&mut self) {}
+}
+
+impl<Bs: Bound> Drop for S<Bs> {
+    fn drop(&mut self) {}
+}
+
+impl<'t, Bt: 't> Drop for T<'t, Bt> {
+    fn drop(&mut self) {}
+}
+
+impl Drop for U {
+    fn drop(&mut self) {}
+}
+
+impl<One> Drop for V<One, One> {
+    //~^ ERROR `Drop` impls cannot be specialized
+    fn drop(&mut self) {}
+}
+
+impl<'lw> Drop for W<'lw, 'lw> {
+    //~^ ERROR `Drop` impls cannot be specialized
+    fn drop(&mut self) {}
+}
+
+impl Drop for X<3> {
+    //~^ ERROR `Drop` impls cannot be specialized
+    fn drop(&mut self) {}
+}
+
+impl<const Ca: usize> Drop for Y<Ca, Ca> {
+    //~^ ERROR `Drop` impls cannot be specialized
+    fn drop(&mut self) {}
+}
+
+impl<AddsBnd: Bound> Drop for Enum<AddsBnd> {
+    //~^ ERROR `Drop` impl requires `AddsBnd: Bound`
+    fn drop(&mut self) {}
+}
+
+impl<AddsBnd: Bound> Drop for TupleStruct<AddsBnd> {
+    //~^ ERROR `Drop` impl requires `AddsBnd: Bound`
+    fn drop(&mut self) {}
+}
+
+impl<AddsBnd: Copy + Bound> Drop for Union<AddsBnd> {
+    //~^ ERROR `Drop` impl requires `AddsBnd: Bound`
+    fn drop(&mut self) {}
+}
+
+pub fn main() {}
diff --git a/tests/ui/dropck/reject-specialized-drops-8142.stderr b/tests/ui/dropck/reject-specialized-drops-8142.stderr
index cb48221c67a..9c8b6d54463 100644
--- a/tests/ui/dropck/reject-specialized-drops-8142.stderr
+++ b/tests/ui/dropck/reject-specialized-drops-8142.stderr
@@ -1,166 +1,157 @@
 error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:24:20
+  --> $DIR/reject-specialized-drops-8142.rs:58:1
    |
-LL | impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> {                        // REJECT
-   |                    ^^^
+LL | impl<'al, 'adds_bnd: 'al> Drop for K<'al, 'adds_bnd> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:4:1
+  --> $DIR/reject-specialized-drops-8142.rs:6:1
    |
-LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
-   | ^^^^^^^^^^^^^^^^^
+LL | struct K<'l1, 'l2> {
+   | ^^^^^^^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:28:67
+  --> $DIR/reject-specialized-drops-8142.rs:63:1
    |
-LL | impl<'al,'adds_bnd>     Drop for L<'al,'adds_bnd> where 'adds_bnd:'al {    // REJECT
-   |                                                                   ^^^
+LL | / impl<'al, 'adds_bnd> Drop for L<'al, 'adds_bnd>
+LL | |
+LL | | where
+LL | |     'adds_bnd: 'al,
+   | |___________________^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:5:1
+  --> $DIR/reject-specialized-drops-8142.rs:10:1
    |
-LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
-   | ^^^^^^^^^^^^^^^^^
+LL | struct L<'l1, 'l2> {
+   | ^^^^^^^^^^^^^^^^^^
 
 error[E0366]: `Drop` impls cannot be specialized
-  --> $DIR/reject-specialized-drops-8142.rs:34:1
+  --> $DIR/reject-specialized-drops-8142.rs:75:1
    |
-LL | impl                    Drop for N<'static>     { fn drop(&mut self) { } } // REJECT
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl Drop for N<'static> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `'static` is not a generic parameter
 note: use the same sequence of generic lifetime, type and const parameters as the struct definition
-  --> $DIR/reject-specialized-drops-8142.rs:7:1
+  --> $DIR/reject-specialized-drops-8142.rs:17:1
    |
-LL | struct N<'n> { x: &'n i8 }
+LL | struct N<'n> {
    | ^^^^^^^^^^^^
 
 error[E0366]: `Drop` impls cannot be specialized
-  --> $DIR/reject-specialized-drops-8142.rs:39:1
+  --> $DIR/reject-specialized-drops-8142.rs:84:1
    |
-LL | impl              Drop for P<i8>          { fn drop(&mut self) { } } // REJECT
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl Drop for P<i8> {
+   | ^^^^^^^^^^^^^^^^^^^
    |
    = note: `i8` is not a generic parameter
 note: use the same sequence of generic lifetime, type and const parameters as the struct definition
-  --> $DIR/reject-specialized-drops-8142.rs:9:1
+  --> $DIR/reject-specialized-drops-8142.rs:23:1
    |
-LL | struct P<Tp> { x: *const Tp }
+LL | struct P<Tp> {
    | ^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:42:14
+  --> $DIR/reject-specialized-drops-8142.rs:89:15
    |
-LL | impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
-   |              ^^^^^
+LL | impl<AddsBnd: Bound> Drop for Q<AddsBnd> {
+   |               ^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:10:1
+  --> $DIR/reject-specialized-drops-8142.rs:26:1
    |
-LL | struct Q<Tq> { x: *const Tq }
-   | ^^^^^^^^^^^^
-
-error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:45:21
-   |
-LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
-   |                     ^^^^^
-   |
-note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:11:1
-   |
-LL | struct R<Tr> { x: *const Tr }
+LL | struct Q<Tq> {
    | ^^^^^^^^^^^^
 
 error[E0366]: `Drop` impls cannot be specialized
-  --> $DIR/reject-specialized-drops-8142.rs:54:1
+  --> $DIR/reject-specialized-drops-8142.rs:110:1
    |
-LL | impl<One>         Drop for V<One,One>     { fn drop(&mut self) { } } // REJECT
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<One> Drop for V<One, One> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `One` is mentioned multiple times
 note: use the same sequence of generic lifetime, type and const parameters as the struct definition
-  --> $DIR/reject-specialized-drops-8142.rs:15:1
+  --> $DIR/reject-specialized-drops-8142.rs:39:1
    |
-LL | struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
+LL | struct V<Tva, Tvb> {
    | ^^^^^^^^^^^^^^^^^^
 
 error[E0366]: `Drop` impls cannot be specialized
-  --> $DIR/reject-specialized-drops-8142.rs:57:1
+  --> $DIR/reject-specialized-drops-8142.rs:115:1
    |
-LL | impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<'lw> Drop for W<'lw, 'lw> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `'lw` is mentioned multiple times
 note: use the same sequence of generic lifetime, type and const parameters as the struct definition
-  --> $DIR/reject-specialized-drops-8142.rs:16:1
+  --> $DIR/reject-specialized-drops-8142.rs:43:1
    |
-LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
+LL | struct W<'l1, 'l2> {
    | ^^^^^^^^^^^^^^^^^^
 
 error[E0366]: `Drop` impls cannot be specialized
-  --> $DIR/reject-specialized-drops-8142.rs:60:1
+  --> $DIR/reject-specialized-drops-8142.rs:120:1
    |
-LL | impl              Drop for X<3>           { fn drop(&mut self) { } } // REJECT
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl Drop for X<3> {
+   | ^^^^^^^^^^^^^^^^^^
    |
    = note: `3` is not a generic parameter
 note: use the same sequence of generic lifetime, type and const parameters as the struct definition
-  --> $DIR/reject-specialized-drops-8142.rs:17:1
+  --> $DIR/reject-specialized-drops-8142.rs:47:1
    |
 LL | struct X<const Ca: usize>;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0366]: `Drop` impls cannot be specialized
-  --> $DIR/reject-specialized-drops-8142.rs:63:1
+  --> $DIR/reject-specialized-drops-8142.rs:125:1
    |
-LL | impl<const Ca: usize> Drop for Y<Ca, Ca>     { fn drop(&mut self) { } } // REJECT
+LL | impl<const Ca: usize> Drop for Y<Ca, Ca> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `Ca` is mentioned multiple times
 note: use the same sequence of generic lifetime, type and const parameters as the struct definition
-  --> $DIR/reject-specialized-drops-8142.rs:18:1
+  --> $DIR/reject-specialized-drops-8142.rs:48:1
    |
 LL | struct Y<const Ca: usize, const Cb: usize>;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:66:14
+  --> $DIR/reject-specialized-drops-8142.rs:130:15
    |
-LL | impl<AddsBnd:Bound> Drop for Enum<AddsBnd> { fn drop(&mut self) { } } // REJECT
-   |              ^^^^^
+LL | impl<AddsBnd: Bound> Drop for Enum<AddsBnd> {
+   |               ^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:20:1
+  --> $DIR/reject-specialized-drops-8142.rs:50:1
    |
-LL | enum Enum<T> { Variant(T) }
+LL | enum Enum<T> {
    | ^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:69:14
+  --> $DIR/reject-specialized-drops-8142.rs:135:15
    |
-LL | impl<AddsBnd:Bound> Drop for TupleStruct<AddsBnd> { fn drop(&mut self) { } } // REJECT
-   |              ^^^^^
+LL | impl<AddsBnd: Bound> Drop for TupleStruct<AddsBnd> {
+   |               ^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:21:1
+  --> $DIR/reject-specialized-drops-8142.rs:53:1
    |
 LL | struct TupleStruct<T>(T);
    | ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not
-  --> $DIR/reject-specialized-drops-8142.rs:72:21
+  --> $DIR/reject-specialized-drops-8142.rs:140:22
    |
-LL | impl<AddsBnd:Copy + Bound> Drop for Union<AddsBnd> { fn drop(&mut self) { } } // REJECT
-   |                     ^^^^^
+LL | impl<AddsBnd: Copy + Bound> Drop for Union<AddsBnd> {
+   |                      ^^^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/reject-specialized-drops-8142.rs:22:1
+  --> $DIR/reject-specialized-drops-8142.rs:54:1
    |
-LL | union Union<T: Copy> { f: T }
+LL | union Union<T: Copy> {
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 13 previous errors
+error: aborting due to 12 previous errors
 
 Some errors have detailed explanations: E0366, E0367.
 For more information about an error, try `rustc --explain E0366`.
diff --git a/tests/ui/dropck/transitive-outlives.bad.stderr b/tests/ui/dropck/transitive-outlives.bad.stderr
index 9ecc4841dce..5b7968fce80 100644
--- a/tests/ui/dropck/transitive-outlives.bad.stderr
+++ b/tests/ui/dropck/transitive-outlives.bad.stderr
@@ -1,8 +1,11 @@
 error[E0367]: `Drop` impl requires `'a: 'c` but the struct it is implemented for does not
-  --> $DIR/transitive-outlives.rs:20:9
+  --> $DIR/transitive-outlives.rs:18:1
    |
-LL |     'a: 'c,
-   |         ^^
+LL | / impl<'a, 'b, 'c> Drop for DropMe<'a, 'b, 'c>
+LL | |
+LL | | where
+LL | |     'a: 'c,
+   | |___________^
    |
 note: the implementor must specify the same requirement
   --> $DIR/transitive-outlives.rs:7:1
diff --git a/tests/ui/dropck/transitive-outlives.rs b/tests/ui/dropck/transitive-outlives.rs
index e96ac6faae4..37c0a1ff5e2 100644
--- a/tests/ui/dropck/transitive-outlives.rs
+++ b/tests/ui/dropck/transitive-outlives.rs
@@ -16,9 +16,9 @@ where
 
 #[cfg(bad)]
 impl<'a, 'b, 'c> Drop for DropMe<'a, 'b, 'c>
+//[bad]~^ ERROR `Drop` impl requires `'a: 'c`
 where
     'a: 'c,
-    //[bad]~^ ERROR `Drop` impl requires `'a: 'c`
 {
     fn drop(&mut self) {}
 }
diff --git a/tests/ui/dropck/unconstrained_const_param_on_drop.rs b/tests/ui/dropck/unconstrained_const_param_on_drop.rs
new file mode 100644
index 00000000000..de77fa55fb2
--- /dev/null
+++ b/tests/ui/dropck/unconstrained_const_param_on_drop.rs
@@ -0,0 +1,7 @@
+struct Foo {}
+
+impl<const UNUSED: usize> Drop for Foo {}
+//~^ ERROR: `Drop` impl requires `the constant `_` has type `usize``
+//~| ERROR: the const parameter `UNUSED` is not constrained by the impl trait, self type, or predicates
+
+fn main() {}
diff --git a/tests/ui/dropck/unconstrained_const_param_on_drop.stderr b/tests/ui/dropck/unconstrained_const_param_on_drop.stderr
new file mode 100644
index 00000000000..851888534ee
--- /dev/null
+++ b/tests/ui/dropck/unconstrained_const_param_on_drop.stderr
@@ -0,0 +1,25 @@
+error[E0367]: `Drop` impl requires `the constant `_` has type `usize`` but the struct it is implemented for does not
+  --> $DIR/unconstrained_const_param_on_drop.rs:3:6
+   |
+LL | impl<const UNUSED: usize> Drop for Foo {}
+   |      ^^^^^^^^^^^^^^^^^^^
+   |
+note: the implementor must specify the same requirement
+  --> $DIR/unconstrained_const_param_on_drop.rs:1:1
+   |
+LL | struct Foo {}
+   | ^^^^^^^^^^
+
+error[E0207]: the const parameter `UNUSED` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/unconstrained_const_param_on_drop.rs:3:6
+   |
+LL | impl<const UNUSED: usize> Drop for Foo {}
+   |      ^^^^^^^^^^^^^^^^^^^ unconstrained const parameter
+   |
+   = note: expressions using a const parameter must map each value to a distinct output value
+   = note: proving the result of expressions other than the parameter are unique is not supported
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0367.
+For more information about an error, try `rustc --explain E0207`.