Rollup merge of #127220 - BoxyUwU:dropck_handle_extra_impl_params, r=compiler-errors
Graciously handle `Drop` impls introducing more generic parameters than the ADT Follow up to #110577 Fixes #126378 Fixes #126889 ## Motivation A current issue with the way we check drop impls do not specialize any of their generic parameters is that when the `Drop` impl introduces *more* generic parameters than are present on the ADT, we fail to prove any bounds involving those parameters. This can be demonstrated with the following [code on stable](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=139b65e4294634d7286a3282bc61e628) which fails due to the fact that `<T as Trait>::Assoc == U` is not present in `Foo`s `ParamEnv` even though arguably there is no reason it cannot compiler: ```rust struct Foo<T: Trait>(T); trait Trait { type Assoc; } impl<T: Trait<Assoc = U>, U: ?Sized> Drop for Foo<T> { //~^ ERROR: `Drop` impl requires `<T as Trait>::Assoc == U` but the struct ... fn drop(&mut self) {} } fn main() {} ``` I think the motivation for supporting this code is somewhat lacking, it might be useful in practice for deeply nested associated types where you might want to be able to write: `where T: Trait<Assoc: Other<AnotherAssoc: MoreTrait<YetAnotherAssoc: InnerTrait<Final = U>>>>` in order to be able to just use `U` in the function body instead of writing out the whole nested associated type. Regardless I don't think there is really any reason to *not* support this code and it is relatively easy to support it. What I find slightly more compelling is the fact that when defining a const parameter `const N: u8` we desugar that to having a where clause requiring the constant `N` is typed as `u8` (`ClauseKind::ConstArgHasType`). As we *always* desugar const parameters to have these bounds, if we attempt to prove that some const parameter `N` is of type `u8` and there is no bound on `N` in the enviroment that generally indicates usage of an incorrect `ParamEnv` (this has caught a bug already). Given that, if we write the following code: ```rust #![feature(associated_const_equality)] struct Foo<T: Trait>(T); trait Trait { const ASSOC: usize; } impl<T: Trait<ASSOC = N>, const N: usize> Drop for Foo<T> { fn drop(&mut self) {} } fn main() {} ``` The `Drop` impl would have this desugared where clause about `N` being of type `usize`, and if we were to try to prove that where clause in `Foo`'s `ParamEnv` we would ICE as there would not be any `ConstArgHasType` in the environment (which generally indicates improper `ParamEnv` usage. As this is otherwise well formed code (the `T: Trait<ASSOC = N>` causes `N` to be constrained) we have to handle this *somehow* and I believe the only principled way to support this is the changes I have made to `dropck.rs` that would cause these code examples to compiler (Perhaps we could just throw out all `ConstArgHasType` where clauses from the predicates we prove but that makes me nervous even if it might actually be okay). ## The changes Currently the way `dropck.rs` works is that take the `ParamEnv` of the ADT and instantiate it with the generic arguments used on the self ty of the `impl`. We then instantiate the predicates of the drop impl with the identity params to the impl, e.g. in the original example `<T as Trait>::Assoc == U` stays as `<T as Trait>::Assoc == U`. We then attempt to prove all the where clauses in the instantiated env of the self type ADT. This PR changes us to first instantiate the impl with infer vars, then we equate the self type (with infer vars as its generic arguments) with the self type as written by the user. This causes all generic parameters on the impl that are constrained via associated type/const equality bounds to be left as inference variables while all other parameters are still `Ty`/`Const`/`Region` Finally when instantiating the predicates on the impl, instead of using the identity arguments, we use the list of inference variables of which some have been inferred to the impl parameters. In practice this means that we wind up proving `<T as Trait>::Assoc == ?x` which can succeed just fine. In the const generics example we would wind up trying to prove `ConstArgHasType(?x: usize)` instead of `ConstArgHasType(N: usize)` which avoids the ICE as it is expected to encounter goals of the form `?x: usize`. At a higher level the way I justify/think about this is that as we are proving goals in the environment of the ADT (`Foo` in the above examples), we do not expect to encounter generic parameters from a different environment so we must "deal with them" somehow. In this PR we handle them by replacing them with inference variables as they should either *actually* be unconstrained (and we will error later) or they are constrained to be equal to some associated type/const. To go along with this it would be nice if we were not instantiating the adt's env with the generic arguments to the ADT in the `Drop` impl as it would make it clearer we are proving bounds in the adt's env instead of the `Drop` impl's. Instead we would map the predicates on the drop impl to be valid in the environment of the adt. In practice this causes diagnostic regressions as all of the generic parameters in errors refer to the ones defined on the adt; attempting to map these back to the ones on the impl, while possible, is involved as writing a `TypeFolder` over `FulfillmentError` is non trivial. ## Edge cases There are some subtle interactions here: One is that we should not allow `<T as Trait>::Assoc == U` to be present on the `Drop` if `U` is constrained by the self type of the impl and the bound is not present in the ADT's environment. demonstrated with the [following code](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=af839e2c3e43e03a624825c58af84dff): ```rust 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() {} ``` This is tested at `tests/ui/dropck/constrained_by_assoc_type_equality_and_self_ty.rs`. Another weirdness is that we permit the following code to compile now: ```rust struct Foo<T>(T); impl<'a, T: 'a> Drop for Foo<T> { fn drop(&mut self) {} } ``` This is caused by the fact that we permit unconstrained lifetime parameters in trait implementations as long as they are not used in associated types (so we do not wind up erroring on this code like we perhaps ought to), combined with the fact that as we are now proving `T: '?x` instead of `T: 'a` which allows proving the bound via `'?x= 'empty` wheras previously it would have failed. This is tested as part of `tests/ui/dropck/reject-specialized-drops-8142.rs`. --- r? `@compiler-errors`
This commit is contained in:
commit
29314e4fca
@ -6,10 +6,10 @@
|
||||
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 {
|
||||
|
11
tests/ui/dropck/const_drop_is_valid.rs
Normal file
11
tests/ui/dropck/const_drop_is_valid.rs
Normal file
@ -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() {}
|
45
tests/ui/dropck/const_drop_is_valid.stderr
Normal file
45
tests/ui/dropck/const_drop_is_valid.stderr
Normal file
@ -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`.
|
13
tests/ui/dropck/constrained_by_assoc_type_equality.rs
Normal file
13
tests/ui/dropck/constrained_by_assoc_type_equality.rs
Normal file
@ -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() {}
|
@ -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() {}
|
@ -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`.
|
@ -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) { } }
|
||||
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<'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) { } } // ACCEPT
|
||||
impl<'ml> Drop for M<'ml> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
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) { } } // ACCEPT
|
||||
impl<COkNoBound> Drop for O<COkNoBound> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl Drop for P<i8> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
impl Drop for P<i8> {
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
|
||||
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) { } } // REJECT
|
||||
//~^ ERROR `Drop` impl requires `AddsRBnd: 'rbnd`
|
||||
impl<'rbnd, AddsRBnd: 'rbnd> Drop for R<AddsRBnd> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<Bs:Bound> Drop for S<Bs> { fn drop(&mut self) { } } // ACCEPT
|
||||
impl<Bs: Bound> Drop for S<Bs> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<'t,Bt:'t> Drop for T<'t,Bt> { fn drop(&mut self) { } } // ACCEPT
|
||||
impl<'t, Bt: 't> Drop for T<'t, Bt> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl Drop for U { fn drop(&mut self) { } } // ACCEPT
|
||||
impl Drop for U {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
impl<One> Drop for V<One, One> {
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
impl<'lw> Drop for W<'lw, 'lw> {
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl Drop for X<3> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
impl Drop for X<3> {
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<const Ca: usize> Drop for Y<Ca, Ca> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impls cannot be specialized
|
||||
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> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
|
||||
impl<AddsBnd: Bound> Drop for Enum<AddsBnd> {
|
||||
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<AddsBnd:Bound> Drop for TupleStruct<AddsBnd> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
|
||||
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> { fn drop(&mut self) { } } // REJECT
|
||||
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
|
||||
impl<AddsBnd: Copy + Bound> Drop for Union<AddsBnd> {
|
||||
//~^ ERROR `Drop` impl requires `AddsBnd: Bound`
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
pub fn main() { }
|
||||
pub fn main() {}
|
||||
|
@ -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
|
||||
| ^^^
|
||||
|
|
||||
note: the implementor must specify the same requirement
|
||||
--> $DIR/reject-specialized-drops-8142.rs:5:1
|
||||
|
|
||||
LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0366]: `Drop` impls cannot be specialized
|
||||
--> $DIR/reject-specialized-drops-8142.rs:34:1
|
||||
|
|
||||
LL | impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | struct N<'n> { x: &'n i8 }
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error[E0366]: `Drop` impls cannot be specialized
|
||||
--> $DIR/reject-specialized-drops-8142.rs:39:1
|
||||
|
|
||||
LL | impl Drop for P<i8> { fn drop(&mut self) { } } // REJECT
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | struct P<Tp> { x: *const 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
|
||||
|
|
||||
LL | impl<AddsBnd:Bound> Drop for Q<AddsBnd> { fn drop(&mut self) { } } // 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:10:1
|
||||
|
|
||||
LL | struct Q<Tq> { x: *const Tq }
|
||||
| ^^^^^^^^^^^^
|
||||
LL | struct L<'l1, 'l2> {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not
|
||||
--> $DIR/reject-specialized-drops-8142.rs:45:21
|
||||
error[E0366]: `Drop` impls cannot be specialized
|
||||
--> $DIR/reject-specialized-drops-8142.rs:75:1
|
||||
|
|
||||
LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R<AddsRBnd> { fn drop(&mut self) { } } // REJECT
|
||||
| ^^^^^
|
||||
LL | impl Drop for N<'static> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the implementor must specify the same requirement
|
||||
--> $DIR/reject-specialized-drops-8142.rs:11:1
|
||||
= 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:17:1
|
||||
|
|
||||
LL | struct R<Tr> { x: *const Tr }
|
||||
LL | struct N<'n> {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error[E0366]: `Drop` impls cannot be specialized
|
||||
--> $DIR/reject-specialized-drops-8142.rs:54:1
|
||||
--> $DIR/reject-specialized-drops-8142.rs:84:1
|
||||
|
|
||||
LL | impl<One> Drop for V<One,One> { 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:23:1
|
||||
|
|
||||
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:89:15
|
||||
|
|
||||
LL | impl<AddsBnd: Bound> Drop for Q<AddsBnd> {
|
||||
| ^^^^^
|
||||
|
|
||||
note: the implementor must specify the same requirement
|
||||
--> $DIR/reject-specialized-drops-8142.rs:26:1
|
||||
|
|
||||
LL | struct Q<Tq> {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error[E0366]: `Drop` impls cannot be specialized
|
||||
--> $DIR/reject-specialized-drops-8142.rs:110:1
|
||||
|
|
||||
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`.
|
||||
|
@ -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
|
||||
|
@ -16,9 +16,9 @@ fn drop(&mut self) {}
|
||||
|
||||
#[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) {}
|
||||
}
|
||||
|
7
tests/ui/dropck/unconstrained_const_param_on_drop.rs
Normal file
7
tests/ui/dropck/unconstrained_const_param_on_drop.rs
Normal file
@ -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() {}
|
25
tests/ui/dropck/unconstrained_const_param_on_drop.stderr
Normal file
25
tests/ui/dropck/unconstrained_const_param_on_drop.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user