Rollup merge of #103351 - oli-obk:tilde_const_impls, r=fee1-dead
Require Drop impls to have the same constness on its bounds as the bounds on the struct have r? ``@fee1-dead``
This commit is contained in:
commit
ed430ca5fe
@ -252,20 +252,6 @@ fn walk_ty(&mut self, t: &'a Ty) {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
|
||||
if let Some(ident) = field.ident {
|
||||
if ident.name == kw::Underscore {
|
||||
self.visit_vis(&field.vis);
|
||||
self.visit_ident(ident);
|
||||
self.visit_ty_common(&field.ty);
|
||||
self.walk_ty(&field.ty);
|
||||
walk_list!(self, visit_attribute, &field.attrs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.visit_field_def(field);
|
||||
}
|
||||
|
||||
fn err_handler(&self) -> &rustc_errors::Handler {
|
||||
&self.session.diagnostic()
|
||||
}
|
||||
@ -1006,8 +992,8 @@ fn visit_lifetime(&mut self, lifetime: &'a Lifetime, _: visit::LifetimeCtxt) {
|
||||
visit::walk_lifetime(self, lifetime);
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, s: &'a FieldDef) {
|
||||
visit::walk_field_def(self, s)
|
||||
fn visit_field_def(&mut self, field: &'a FieldDef) {
|
||||
visit::walk_field_def(self, field)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &'a Item) {
|
||||
@ -1195,42 +1181,10 @@ fn visit_item(&mut self, item: &'a Item) {
|
||||
self.check_mod_file_item_asciionly(item.ident);
|
||||
}
|
||||
}
|
||||
ItemKind::Struct(ref vdata, ref generics) => match vdata {
|
||||
// Duplicating the `Visitor` logic allows catching all cases
|
||||
// of `Anonymous(Struct, Union)` outside of a field struct or union.
|
||||
//
|
||||
// Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
|
||||
// encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
|
||||
// it uses `visit_ty_common`, which doesn't contain that specific check.
|
||||
VariantData::Struct(ref fields, ..) => {
|
||||
self.visit_vis(&item.vis);
|
||||
self.visit_ident(item.ident);
|
||||
self.visit_generics(generics);
|
||||
self.with_banned_assoc_ty_bound(|this| {
|
||||
walk_list!(this, visit_struct_field_def, fields);
|
||||
});
|
||||
walk_list!(self, visit_attribute, &item.attrs);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
ItemKind::Union(ref vdata, ref generics) => {
|
||||
ItemKind::Union(ref vdata, ..) => {
|
||||
if vdata.fields().is_empty() {
|
||||
self.err_handler().span_err(item.span, "unions cannot have zero fields");
|
||||
}
|
||||
match vdata {
|
||||
VariantData::Struct(ref fields, ..) => {
|
||||
self.visit_vis(&item.vis);
|
||||
self.visit_ident(item.ident);
|
||||
self.visit_generics(generics);
|
||||
self.with_banned_assoc_ty_bound(|this| {
|
||||
walk_list!(this, visit_struct_field_def, fields);
|
||||
});
|
||||
walk_list!(self, visit_attribute, &item.attrs);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ItemKind::Const(def, .., None) => {
|
||||
self.check_defaultness(item.span, def);
|
||||
|
@ -184,13 +184,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||
let p = p.kind();
|
||||
match (predicate.skip_binder(), p.skip_binder()) {
|
||||
(ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => {
|
||||
// Since struct predicates cannot have ~const, project the impl predicate
|
||||
// onto one that ignores the constness. This is equivalent to saying that
|
||||
// we match a `Trait` bound on the struct with a `Trait` or `~const Trait`
|
||||
// in the impl.
|
||||
let non_const_a =
|
||||
ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..a };
|
||||
relator.relate(predicate.rebind(non_const_a), p.rebind(b)).is_ok()
|
||||
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
|
||||
}
|
||||
(ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
|
||||
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
|
||||
|
@ -45,34 +45,55 @@ note: required by a bound in `check`
|
||||
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
|
||||
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:48:47
|
||||
|
|
||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
|
||||
--> $DIR/const-drop-fail.rs:48:47
|
||||
|
|
||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ^^^^^^^^^^^
|
||||
note: required by a bound in `ConstDropImplWithBounds`
|
||||
--> $DIR/const-drop-fail.rs:27:35
|
||||
|
|
||||
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
|
||||
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:48:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
...
|
||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
||||
|
|
||||
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
|
||||
--> $DIR/const-drop-fail.rs:29:25
|
||||
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
|
||||
--> $DIR/const-drop-fail.rs:48:5
|
||||
|
|
||||
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:35:19
|
||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `ConstDropImplWithBounds`
|
||||
--> $DIR/const-drop-fail.rs:27:35
|
||||
|
|
||||
LL | const fn check<T: ~const Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| +
|
||||
LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ++++
|
||||
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
|
||||
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
|
||||
--> $DIR/const-drop-fail.rs:55:9
|
||||
|
|
||||
LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: the implementor must specify the same requirement
|
||||
--> $DIR/const-drop-fail.rs:53:1
|
||||
|
|
||||
LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0367.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
@ -24,7 +24,7 @@ trait A { fn a() { } }
|
||||
|
||||
impl A for NonTrivialDrop {}
|
||||
|
||||
struct ConstDropImplWithBounds<T: A>(PhantomData<T>);
|
||||
struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
|
||||
|
||||
impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
|
||||
fn drop(&mut self) {
|
||||
@ -47,6 +47,16 @@ macro_rules! check_all {
|
||||
//~^ ERROR can't drop
|
||||
ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
//~^ ERROR the trait bound
|
||||
//~| ERROR the trait bound
|
||||
}
|
||||
|
||||
struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
|
||||
|
||||
impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
|
||||
//~^ ERROR `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
|
||||
fn drop(&mut self) {
|
||||
T::a();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -45,34 +45,55 @@ note: required by a bound in `check`
|
||||
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
|
||||
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:48:47
|
||||
|
|
||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
|
||||
--> $DIR/const-drop-fail.rs:48:47
|
||||
|
|
||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ^^^^^^^^^^^
|
||||
note: required by a bound in `ConstDropImplWithBounds`
|
||||
--> $DIR/const-drop-fail.rs:27:35
|
||||
|
|
||||
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
|
||||
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
|
||||
|
||||
error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
|
||||
--> $DIR/const-drop-fail.rs:48:5
|
||||
|
|
||||
LL | const _: () = check($exp);
|
||||
| ----- required by a bound introduced by this call
|
||||
...
|
||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
||||
|
|
||||
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
|
||||
--> $DIR/const-drop-fail.rs:29:25
|
||||
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
|
||||
--> $DIR/const-drop-fail.rs:48:5
|
||||
|
|
||||
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:35:19
|
||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `ConstDropImplWithBounds`
|
||||
--> $DIR/const-drop-fail.rs:27:35
|
||||
|
|
||||
LL | const fn check<T: ~const Destruct>(_: T) {}
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `check`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| +
|
||||
LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||
| ++++
|
||||
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
|
||||
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
|
||||
--> $DIR/const-drop-fail.rs:55:9
|
||||
|
|
||||
LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: the implementor must specify the same requirement
|
||||
--> $DIR/const-drop-fail.rs:53:1
|
||||
|
|
||||
LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0367.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
@ -60,7 +60,7 @@ impl SomeTrait for i32 {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
pub struct ConstDropWithBound<T: SomeTrait>(pub core::marker::PhantomData<T>);
|
||||
pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
|
||||
|
||||
impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
|
||||
fn drop(&mut self) {
|
||||
|
@ -0,0 +1,17 @@
|
||||
// check-pass
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
#[const_trait]
|
||||
trait Foo {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
struct Bar<T>(T);
|
||||
|
||||
impl<T: ~const Foo> Bar<T> {
|
||||
const fn foo(&self) {
|
||||
self.0.foo()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user