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
7 changed files with 121 additions and 104 deletions
|
@ -252,20 +252,6 @@ impl<'a> AstValidator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
fn err_handler(&self) -> &rustc_errors::Handler {
|
||||||
&self.session.diagnostic()
|
&self.session.diagnostic()
|
||||||
}
|
}
|
||||||
|
@ -1006,8 +992,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
visit::walk_lifetime(self, lifetime);
|
visit::walk_lifetime(self, lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_field_def(&mut self, s: &'a FieldDef) {
|
fn visit_field_def(&mut self, field: &'a FieldDef) {
|
||||||
visit::walk_field_def(self, s)
|
visit::walk_field_def(self, field)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, item: &'a Item) {
|
fn visit_item(&mut self, item: &'a Item) {
|
||||||
|
@ -1195,42 +1181,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
self.check_mod_file_item_asciionly(item.ident);
|
self.check_mod_file_item_asciionly(item.ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Struct(ref vdata, ref generics) => match vdata {
|
ItemKind::Union(ref 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) => {
|
|
||||||
if vdata.fields().is_empty() {
|
if vdata.fields().is_empty() {
|
||||||
self.err_handler().span_err(item.span, "unions cannot have zero fields");
|
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) => {
|
ItemKind::Const(def, .., None) => {
|
||||||
self.check_defaultness(item.span, def);
|
self.check_defaultness(item.span, def);
|
||||||
|
|
|
@ -184,13 +184,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
let p = p.kind();
|
let p = p.kind();
|
||||||
match (predicate.skip_binder(), p.skip_binder()) {
|
match (predicate.skip_binder(), p.skip_binder()) {
|
||||||
(ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => {
|
(ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => {
|
||||||
// Since struct predicates cannot have ~const, project the impl predicate
|
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
|
||||||
// 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()
|
|
||||||
}
|
}
|
||||||
(ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
|
(ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
|
||||||
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
|
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) {}
|
LL | const fn check<T: ~const Destruct>(_: T) {}
|
||||||
| ^^^^^^^^^^^^^^^ required by this bound in `check`
|
| ^^^^^^^^^^^^^^^ 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
|
--> $DIR/const-drop-fail.rs:48:5
|
||||||
|
|
|
|
||||||
LL | const _: () = check($exp);
|
|
||||||
| ----- required by a bound introduced by this call
|
|
||||||
...
|
|
||||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
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`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
|
||||||
--> $DIR/const-drop-fail.rs:29:25
|
--> $DIR/const-drop-fail.rs:48:5
|
||||||
|
|
|
|
||||||
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||||
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: 1 redundant requirement hidden
|
note: required by a bound in `ConstDropImplWithBounds`
|
||||||
= note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
|
--> $DIR/const-drop-fail.rs:27:35
|
||||||
note: required by a bound in `check`
|
|
||||||
--> $DIR/const-drop-fail.rs:35:19
|
|
||||||
|
|
|
|
||||||
LL | const fn check<T: ~const Destruct>(_: T) {}
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
|
||||||
| ^^^^^^^^^^^^^^^ required by this bound in `check`
|
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
|
||||||
help: consider borrowing here
|
|
||||||
|
|
|
||||||
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
|
||||||
| +
|
|
||||||
LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
|
||||||
| ++++
|
|
||||||
|
|
||||||
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 {}
|
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> {
|
impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
@ -47,6 +47,16 @@ check_all! {
|
||||||
//~^ ERROR can't drop
|
//~^ ERROR can't drop
|
||||||
ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||||
//~^ ERROR the trait bound
|
//~^ 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() {}
|
fn main() {}
|
||||||
|
|
|
@ -45,34 +45,55 @@ note: required by a bound in `check`
|
||||||
LL | const fn check<T: ~const Destruct>(_: T) {}
|
LL | const fn check<T: ~const Destruct>(_: T) {}
|
||||||
| ^^^^^^^^^^^^^^^ required by this bound in `check`
|
| ^^^^^^^^^^^^^^^ 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
|
--> $DIR/const-drop-fail.rs:48:5
|
||||||
|
|
|
|
||||||
LL | const _: () = check($exp);
|
|
||||||
| ----- required by a bound introduced by this call
|
|
||||||
...
|
|
||||||
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
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`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
|
||||||
--> $DIR/const-drop-fail.rs:29:25
|
--> $DIR/const-drop-fail.rs:48:5
|
||||||
|
|
|
|
||||||
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
|
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
||||||
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: 1 redundant requirement hidden
|
note: required by a bound in `ConstDropImplWithBounds`
|
||||||
= note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
|
--> $DIR/const-drop-fail.rs:27:35
|
||||||
note: required by a bound in `check`
|
|
||||||
--> $DIR/const-drop-fail.rs:35:19
|
|
||||||
|
|
|
|
||||||
LL | const fn check<T: ~const Destruct>(_: T) {}
|
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
|
||||||
| ^^^^^^^^^^^^^^^ required by this bound in `check`
|
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
|
||||||
help: consider borrowing here
|
|
||||||
|
|
|
||||||
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
|
||||||
| +
|
|
||||||
LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
|
|
||||||
| ++++
|
|
||||||
|
|
||||||
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 @@ mod t {
|
||||||
fn foo() {}
|
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> {
|
impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
|
||||||
fn drop(&mut self) {
|
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…
Add table
Add a link
Reference in a new issue