Skip to content

Commit

Permalink
Rollup merge of rust-lang#103351 - oli-obk:tilde_const_impls, r=fee1-…
Browse files Browse the repository at this point in the history
…dead

Require Drop impls to have the same constness on its bounds as the bounds on the struct have

r? ``@fee1-dead``
  • Loading branch information
matthiaskrgr authored Oct 21, 2022
2 parents db4696a + d6cf893 commit ed430ca
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 102 deletions.
52 changes: 3 additions & 49 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
&self.session.diagnostic()
}
Expand Down Expand Up @@ -1006,8 +992,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
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) {
Expand Down Expand Up @@ -1195,42 +1181,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
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);
Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_hir_analysis/src/check/dropck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $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>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail.rs:27:35
|
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
--> $DIR/const-drop-fail.rs:29:25
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`

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 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 | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
| ^^^^^^^^
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here
note: the implementor must specify the same requirement
--> $DIR/const-drop-fail.rs:53:1
|
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| +
LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ++++
LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors
error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0277, E0367.
For more information about an error, try `rustc --explain E0277`.
12 changes: 11 additions & 1 deletion src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -47,6 +47,16 @@ 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() {}
65 changes: 43 additions & 22 deletions src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
|
note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
--> $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>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `ConstDropImplWithBounds`
--> $DIR/const-drop-fail.rs:27:35
|
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
--> $DIR/const-drop-fail.rs:29:25
LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
| ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`

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 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 | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
| ^^^^^^^^
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here
note: the implementor must specify the same requirement
--> $DIR/const-drop-fail.rs:53:1
|
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| +
LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ++++
LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors
error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0277, E0367.
For more information about an error, try `rustc --explain E0277`.
2 changes: 1 addition & 1 deletion src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ mod t {
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) {
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit ed430ca

Please sign in to comment.