-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Deny more ~const
trait bounds
#117817
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deny more ~const
trait bounds
#117817
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,9 @@ enum SelfSemantic { | |
enum DisallowTildeConstContext<'a> { | ||
TraitObject, | ||
Fn(FnKind<'a>), | ||
Trait(Span), | ||
Impl(Span), | ||
Item, | ||
} | ||
|
||
struct AstValidator<'a> { | ||
|
@@ -110,18 +113,6 @@ impl<'a> AstValidator<'a> { | |
self.disallow_tilde_const = old; | ||
} | ||
|
||
fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) { | ||
self.with_tilde_const(None, f) | ||
} | ||
|
||
fn with_banned_tilde_const( | ||
&mut self, | ||
ctx: DisallowTildeConstContext<'a>, | ||
f: impl FnOnce(&mut Self), | ||
) { | ||
self.with_tilde_const(Some(ctx), f) | ||
} | ||
|
||
fn check_type_alias_where_clause_location( | ||
&mut self, | ||
ty_alias: &TyAlias, | ||
|
@@ -173,7 +164,7 @@ impl<'a> AstValidator<'a> { | |
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t)) | ||
} | ||
TyKind::TraitObject(..) => self | ||
.with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| { | ||
.with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| { | ||
visit::walk_ty(this, t) | ||
}), | ||
TyKind::Path(qself, path) => { | ||
|
@@ -822,11 +813,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { | |
|
||
this.visit_vis(&item.vis); | ||
this.visit_ident(item.ident); | ||
if let Const::Yes(_) = constness { | ||
this.with_tilde_const_allowed(|this| this.visit_generics(generics)); | ||
} else { | ||
this.visit_generics(generics); | ||
} | ||
let disallowed = matches!(constness, Const::No) | ||
.then(|| DisallowTildeConstContext::Impl(item.span)); | ||
this.with_tilde_const(disallowed, |this| this.visit_generics(generics)); | ||
this.visit_trait_ref(t); | ||
this.visit_ty(self_ty); | ||
|
||
|
@@ -840,10 +829,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { | |
polarity, | ||
defaultness, | ||
constness, | ||
generics: _, | ||
generics, | ||
of_trait: None, | ||
self_ty, | ||
items: _, | ||
items, | ||
}) => { | ||
let error = | ||
|annotation_span, annotation, only_trait: bool| errors::InherentImplCannot { | ||
|
@@ -875,6 +864,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { | |
if let &Const::Yes(span) = constness { | ||
self.err_handler().emit_err(error(span, "`const`", true)); | ||
} | ||
|
||
self.visit_vis(&item.vis); | ||
self.visit_ident(item.ident); | ||
self.with_tilde_const(None, |this| this.visit_generics(generics)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently permitting struct Struct;
#[const_trait] trait Trait {}
impl<T: ~const Trait> Struct {
const fn f(_: T) {}
} If I were to straight up deny There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably deny this first. We don't really need this to work and making it work certainly adds to the overhead. Perhaps a followup PR? Or I can do that. Thanks for working on this! :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should deny
at least in my opinion. |
||
self.visit_ty(self_ty); | ||
walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl); | ||
walk_list!(self, visit_attribute, &item.attrs); | ||
return; // Avoid visiting again. | ||
} | ||
ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => { | ||
self.check_defaultness(item.span, *defaultness); | ||
|
@@ -955,8 +952,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { | |
// context for the supertraits. | ||
this.visit_vis(&item.vis); | ||
this.visit_ident(item.ident); | ||
this.visit_generics(generics); | ||
this.with_tilde_const_allowed(|this| { | ||
let disallowed = | ||
(!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span)); | ||
this.with_tilde_const(disallowed, |this| { | ||
this.visit_generics(generics); | ||
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) | ||
}); | ||
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); | ||
|
@@ -976,16 +975,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { | |
} | ||
} | ||
ItemKind::Struct(vdata, 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(fields, ..) => { | ||
self.visit_vis(&item.vis); | ||
self.visit_ident(item.ident); | ||
self.visit_generics(generics); | ||
// Permit `Anon{Struct,Union}` as field type. | ||
walk_list!(self, visit_struct_field_def, fields); | ||
walk_list!(self, visit_attribute, &item.attrs); | ||
return; | ||
|
@@ -1001,6 +995,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { | |
self.visit_vis(&item.vis); | ||
self.visit_ident(item.ident); | ||
self.visit_generics(generics); | ||
// Permit `Anon{Struct,Union}` as field type. | ||
walk_list!(self, visit_struct_field_def, fields); | ||
walk_list!(self, visit_attribute, &item.attrs); | ||
return; | ||
|
@@ -1189,15 +1184,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> { | |
if let Some(reason) = &self.disallow_tilde_const => | ||
{ | ||
let reason = match reason { | ||
DisallowTildeConstContext::TraitObject => { | ||
errors::TildeConstReason::TraitObject | ||
} | ||
DisallowTildeConstContext::Fn(FnKind::Closure(..)) => { | ||
errors::TildeConstReason::Closure | ||
} | ||
DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => { | ||
errors::TildeConstReason::Function { ident: ident.span } | ||
} | ||
&DisallowTildeConstContext::Trait(span) => errors::TildeConstReason::Trait { span }, | ||
&DisallowTildeConstContext::Impl(span) => errors::TildeConstReason::Impl { span }, | ||
DisallowTildeConstContext::TraitObject => { | ||
errors::TildeConstReason::TraitObject | ||
} | ||
DisallowTildeConstContext::Item => errors::TildeConstReason::Item, | ||
}; | ||
self.err_handler() | ||
.emit_err(errors::TildeConstDisallowed { span: bound.span(), reason }); | ||
|
@@ -1305,7 +1303,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { | |
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl); | ||
|
||
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk)); | ||
|
||
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); | ||
} | ||
|
||
|
@@ -1374,18 +1371,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { | |
} | ||
|
||
match &item.kind { | ||
AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) | ||
if ctxt == AssocCtxt::Trait => | ||
{ | ||
self.visit_vis(&item.vis); | ||
self.visit_ident(item.ident); | ||
walk_list!(self, visit_attribute, &item.attrs); | ||
self.with_tilde_const_allowed(|this| { | ||
this.visit_generics(generics); | ||
walk_list!(this, visit_param_bound, bounds, BoundKind::Bound); | ||
}); | ||
walk_list!(self, visit_ty, ty); | ||
} | ||
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) | ||
if self.in_const_trait_or_impl | ||
|| ctxt == AssocCtxt::Trait | ||
|
@@ -1537,7 +1522,7 @@ pub fn check_crate( | |
in_const_trait_or_impl: false, | ||
has_proc_macro_decls: false, | ||
outer_impl_trait: None, | ||
disallow_tilde_const: None, | ||
disallow_tilde_const: Some(DisallowTildeConstContext::Item), | ||
is_impl_trait_banned: false, | ||
lint_buffer: lints, | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,16 @@ | ||
error: `~const` is not allowed here | ||
--> $DIR/assoc-type.rs:17:15 | ||
| | ||
LL | type Bar: ~const std::ops::Add; | ||
| ^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: this item cannot have `~const` trait bounds | ||
|
||
error: ~const can only be applied to `#[const_trait]` traits | ||
--> $DIR/assoc-type.rs:17:22 | ||
| | ||
LL | type Bar: ~const std::ops::Add; | ||
| ^^^^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
error: aborting due to 2 previous errors | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
#![feature(const_trait_impl, effects)] | ||
#![feature(const_trait_impl)] | ||
|
||
#[const_trait] | ||
trait MyTrait { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,10 @@ | ||
error[E0493]: destructor of `T` cannot be evaluated at compile-time | ||
--> $DIR/const-drop.rs:19:32 | ||
error: `~const` is not allowed here | ||
--> $DIR/const-drop.rs:67:38 | ||
| | ||
LL | const fn a<T: ~const Destruct>(_: T) {} | ||
| ^ - value is dropped here | ||
| | | ||
| the destructor for this type cannot be evaluated in constant functions | ||
|
||
error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time | ||
--> $DIR/const-drop.rs:24:13 | ||
LL | pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
LL | let _ = S(&mut c); | ||
| ^^^^^^^^^- value is dropped here | ||
| | | ||
| the destructor for this type cannot be evaluated in constant functions | ||
= note: this item cannot have `~const` trait bounds | ||
|
||
error: aborting due to 2 previous errors | ||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0493`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,10 @@ | ||
error[E0493]: destructor of `T` cannot be evaluated at compile-time | ||
--> $DIR/const-drop.rs:19:32 | ||
error: `~const` is not allowed here | ||
--> $DIR/const-drop.rs:67:38 | ||
| | ||
LL | const fn a<T: ~const Destruct>(_: T) {} | ||
| ^ - value is dropped here | ||
| | | ||
| the destructor for this type cannot be evaluated in constant functions | ||
|
||
error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time | ||
--> $DIR/const-drop.rs:24:13 | ||
LL | pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>); | ||
| ^^^^^^^^^^^^^^^^ | ||
| | ||
LL | let _ = S(&mut c); | ||
| ^^^^^^^^^- value is dropped here | ||
| | | ||
| the destructor for this type cannot be evaluated in constant functions | ||
= note: this item cannot have `~const` trait bounds | ||
|
||
error: aborting due to 2 previous errors | ||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0493`. |
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite ambiguous and we'd probably always want to have a reason.. OTOH, we don't want to allow tilde const for these "unknown" cases. Would be nice if this was turned into a
span_bug!
so that a more specific context is always defined.No need for this PR to have this though.