diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 81efafc2d1dc..6b7c8e6c1940 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3626,6 +3626,7 @@ impl Default for FnHeader { #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct TraitAlias { + pub constness: Const, pub ident: Ident, pub generics: Generics, #[visitable(extra = BoundKind::Bound)] diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ed47c5f5274f..d850698f47b0 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -833,8 +833,8 @@ macro_rules! common_visitor_and_walkers { visit_visitable!($($mut)? vis, impl_), ItemKind::Trait(trait_) => visit_visitable!($($mut)? vis, trait_), - ItemKind::TraitAlias(box TraitAlias { ident, generics, bounds }) => { - visit_visitable!($($mut)? vis, ident, generics); + ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds}) => { + visit_visitable!($($mut)? vis, constness, ident, generics); visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound) } ItemKind::MacCall(m) => diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 56ceeb7ac581..177f33c0d8f1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -415,7 +415,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items) } - ItemKind::TraitAlias(box TraitAlias { ident, generics, bounds }) => { + ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds }) => { + let constness = self.lower_constness(*constness); let ident = self.lower_ident(*ident); let (generics, bounds) = self.lower_generics( generics, @@ -429,7 +430,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }, ); - hir::ItemKind::TraitAlias(ident, generics, bounds) + hir::ItemKind::TraitAlias(constness, ident, generics, bounds) } ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => { let ident = self.lower_ident(*ident); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 36f1387d4b08..294d03a83b16 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -385,8 +385,11 @@ impl<'a> State<'a> { let empty = item.attrs.is_empty() && items.is_empty(); self.bclose(item.span, empty, cb); } - ast::ItemKind::TraitAlias(box TraitAlias { ident, generics, bounds }) => { - let (cb, ib) = self.head(visibility_qualified(&item.vis, "trait")); + ast::ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds }) => { + let (cb, ib) = self.head(""); + self.print_visibility(&item.vis); + self.print_constness(*constness); + self.word_nbsp("trait"); self.print_ident(*ident); self.print_generic_params(&generics.params); self.nbsp(); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 38cb12cf24bc..31842e2023dc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4245,8 +4245,8 @@ impl<'hir> Item<'hir> { ItemKind::Trait(constness, is_auto, safety, ident, generics, bounds, items), (*constness, *is_auto, *safety, *ident, generics, bounds, items); - expect_trait_alias, (Ident, &'hir Generics<'hir>, GenericBounds<'hir>), - ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds); + expect_trait_alias, (Constness, Ident, &'hir Generics<'hir>, GenericBounds<'hir>), + ItemKind::TraitAlias(constness, ident, generics, bounds), (*constness, *ident, generics, bounds); expect_impl, &Impl<'hir>, ItemKind::Impl(imp), imp; } @@ -4423,7 +4423,7 @@ pub enum ItemKind<'hir> { &'hir [TraitItemId], ), /// A trait alias. - TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>), + TraitAlias(Constness, Ident, &'hir Generics<'hir>, GenericBounds<'hir>), /// An implementation, e.g., `impl Trait for Foo { .. }`. Impl(Impl<'hir>), @@ -4468,7 +4468,7 @@ impl ItemKind<'_> { | ItemKind::Struct(ident, ..) | ItemKind::Union(ident, ..) | ItemKind::Trait(_, _, _, ident, ..) - | ItemKind::TraitAlias(ident, ..) => Some(ident), + | ItemKind::TraitAlias(_, ident, ..) => Some(ident), ItemKind::Use(_, UseKind::Glob | UseKind::ListStem) | ItemKind::ForeignMod { .. } @@ -4486,7 +4486,7 @@ impl ItemKind<'_> { | ItemKind::Struct(_, generics, _) | ItemKind::Union(_, generics, _) | ItemKind::Trait(_, _, _, _, generics, _, _) - | ItemKind::TraitAlias(_, generics, _) + | ItemKind::TraitAlias(_, _, generics, _) | ItemKind::Impl(Impl { generics, .. }) => generics, _ => return None, }) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index dde71e499c47..4ab0500cafbc 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -626,7 +626,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_trait_item_ref, trait_item_refs); } - ItemKind::TraitAlias(ident, ref generics, bounds) => { + ItemKind::TraitAlias(_constness, ident, ref generics, bounds) => { try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 79aaa0cb7970..65aa19b91342 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -167,7 +167,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } } ItemKind::Trait(_, _, _, _, _, self_bounds, ..) - | ItemKind::TraitAlias(_, _, self_bounds) => { + | ItemKind::TraitAlias(_, _, _, self_bounds) => { is_trait = Some((self_bounds, item.span)); } _ => {} @@ -654,7 +654,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let (generics, superbounds) = match item.kind { hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), + hir::ItemKind::TraitAlias(_, _, generics, supertraits) => (generics, supertraits), _ => span_bug!(item.span, "super_predicates invoked on non-trait"), }; diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 8133f9f68234..14e48594c006 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -632,7 +632,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { | hir::ItemKind::Struct(_, generics, _) | hir::ItemKind::Union(_, generics, _) | hir::ItemKind::Trait(_, _, _, _, generics, ..) - | hir::ItemKind::TraitAlias(_, generics, ..) + | hir::ItemKind::TraitAlias(_, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) => { // These kinds of items have only early-bound lifetime parameters. self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item)); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ed5f61b3c69a..f838a592d94e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -765,8 +765,10 @@ impl<'a> State<'a> { } self.bclose(item.span, cb); } - hir::ItemKind::TraitAlias(ident, generics, bounds) => { - let (cb, ib) = self.head("trait"); + hir::ItemKind::TraitAlias(constness, ident, generics, bounds) => { + let (cb, ib) = self.head(""); + self.print_constness(constness); + self.word_nbsp("trait"); self.print_ident(ident); self.print_generic_params(generics.params); self.nbsp(); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8f2e06dd7127..0ddf5dd47784 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1594,7 +1594,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, _, _, ident, ..) - | hir::ItemKind::TraitAlias(ident, ..), + | hir::ItemKind::TraitAlias(_, ident, ..), .. }) // We may also encounter unsatisfied GAT or method bounds diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 52a35c98a98b..1862900077f0 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -863,7 +863,6 @@ parse_too_short_hex_escape = numeric character escape is too short parse_trailing_vert_not_allowed = a trailing `{$token}` is not allowed in an or-pattern parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto` -parse_trait_alias_cannot_be_const = trait aliases cannot be `const` parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe` parse_trait_impl_modifier_in_inherent_impl = inherent impls cannot be {$modifier_name} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 6d536aa850b3..a35c5c304d95 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1999,14 +1999,6 @@ pub(crate) struct TraitAliasCannotBeAuto { pub span: Span, } -#[derive(Diagnostic)] -#[diag(parse_trait_alias_cannot_be_const)] -pub(crate) struct TraitAliasCannotBeConst { - #[primary_span] - #[label(parse_trait_alias_cannot_be_const)] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(parse_trait_alias_cannot_be_unsafe)] pub(crate) struct TraitAliasCannotBeUnsafe { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index fde98d14ce11..4bb0d05c4f37 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -943,9 +943,6 @@ impl<'a> Parser<'a> { self.expect_semi()?; let whole_span = lo.to(self.prev_token.span); - if let Const::Yes(_) = constness { - self.dcx().emit_err(errors::TraitAliasCannotBeConst { span: whole_span }); - } if is_auto == IsAuto::Yes { self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span }); } @@ -955,7 +952,7 @@ impl<'a> Parser<'a> { self.psess.gated_spans.gate(sym::trait_alias, whole_span); - Ok(ItemKind::TraitAlias(Box::new(TraitAlias { ident, generics, bounds }))) + Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds }))) } else { // It's a normal trait. generics.where_clause = self.parse_where_clause()?; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index ded5969e83c5..8e4c7cec0dcf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -476,9 +476,8 @@ pub fn report_dyn_incompatibility<'tcx>( let trait_str = tcx.def_path_str(trait_def_id); let trait_span = tcx.hir_get_if_local(trait_def_id).and_then(|node| match node { hir::Node::Item(item) => match item.kind { - hir::ItemKind::Trait(_, _, _, ident, ..) | hir::ItemKind::TraitAlias(ident, _, _) => { - Some(ident.span) - } + hir::ItemKind::Trait(_, _, _, ident, ..) + | hir::ItemKind::TraitAlias(_, ident, _, _) => Some(ident.span), _ => unreachable!(), }, _ => None, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 4ecc48d6cc40..cd0dbb4d87f9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -364,7 +364,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | hir::ItemKind::Fn { generics, .. } | hir::ItemKind::TyAlias(_, generics, _) | hir::ItemKind::Const(_, generics, _, _) - | hir::ItemKind::TraitAlias(_, generics, _), + | hir::ItemKind::TraitAlias(_, _, generics, _), .. }) | hir::Node::TraitItem(hir::TraitItem { generics, .. }) @@ -444,7 +444,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | hir::ItemKind::Fn { generics, .. } | hir::ItemKind::TyAlias(_, generics, _) | hir::ItemKind::Const(_, generics, _, _) - | hir::ItemKind::TraitAlias(_, generics, _), + | hir::ItemKind::TraitAlias(_, _, generics, _), .. }) if finder.can_suggest_bound(generics) => { // Missing generic type parameter bound. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4a95f21a3a5b..7f23023622f6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2828,7 +2828,7 @@ fn clean_maybe_renamed_item<'tcx>( variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(), generics: clean_generics(generics, cx), }), - ItemKind::TraitAlias(_, generics, bounds) => TraitAliasItem(TraitAlias { + ItemKind::TraitAlias(_, _, generics, bounds) => TraitAliasItem(TraitAlias { generics: clean_generics(generics, cx), bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), }), diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs index 76f5fdfaa8dc..22767901614e 100644 --- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs +++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs @@ -528,7 +528,7 @@ impl LateLintPass<'_> for ItemNameRepetitions { | ItemKind::Macro(ident, ..) | ItemKind::Static(_, ident, ..) | ItemKind::Trait(_, _, _, ident, ..) - | ItemKind::TraitAlias(ident, ..) + | ItemKind::TraitAlias(_, ident, ..) | ItemKind::TyAlias(ident, ..) | ItemKind::Union(ident, ..) | ItemKind::Use(_, UseKind::Single(ident)) => ident, diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 4df1eb508713..839b46325b5e 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -478,13 +478,20 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ident: li, generics: lg, bounds: lb, + constness: lc, }), TraitAlias(box ast::TraitAlias { ident: ri, generics: rg, bounds: rb, + constness: rc, }), - ) => eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound), + ) => { + matches!(lc, ast::Const::No) == matches!(rc, ast::Const::No) + && eq_id(*li, *ri) + && eq_generics(lg, rg) + && over(lb, rb, eq_generic_bound) + }, ( Impl(ast::Impl { generics: lg, diff --git a/tests/ui/consts/trait_alias.fail.stderr b/tests/ui/consts/trait_alias.fail.stderr new file mode 100644 index 000000000000..97eb685b16a9 --- /dev/null +++ b/tests/ui/consts/trait_alias.fail.stderr @@ -0,0 +1,46 @@ +error: `[const]` is not allowed here + --> $DIR/trait_alias.rs:14:19 + | +LL | const trait Foo = [const] Bar + Baz; + | ^^^^^^^ + | + = note: this item cannot have `[const]` trait bounds + +error: `[const]` can only be applied to `const` traits + --> $DIR/trait_alias.rs:17:17 + | +LL | const fn foo(x: &T) { + | ^^^^^^^ can't be applied to `Foo` + | +help: mark `Foo` as `const` to allow it to have `const` implementations + | +LL | #[const_trait] const trait Foo = [const] Bar + Baz; + | ++++++++++++++ + +error: `[const]` can only be applied to `const` traits + --> $DIR/trait_alias.rs:17:17 + | +LL | const fn foo(x: &T) { + | ^^^^^^^ can't be applied to `Foo` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: mark `Foo` as `const` to allow it to have `const` implementations + | +LL | #[const_trait] const trait Foo = [const] Bar + Baz; + | ++++++++++++++ + +error[E0277]: the trait bound `T: [const] Bar` is not satisfied + --> $DIR/trait_alias.rs:20:7 + | +LL | x.bar(); + | ^^^ + +error[E0277]: the trait bound `T: [const] Baz` is not satisfied + --> $DIR/trait_alias.rs:24:11 + | +LL | x.baz(); + | ^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/trait_alias.pass.stderr b/tests/ui/consts/trait_alias.pass.stderr new file mode 100644 index 000000000000..00e7e2ca98c7 --- /dev/null +++ b/tests/ui/consts/trait_alias.pass.stderr @@ -0,0 +1,40 @@ +error: `[const]` is not allowed here + --> $DIR/trait_alias.rs:14:19 + | +LL | const trait Foo = [const] Bar + Baz; + | ^^^^^^^ + | + = note: this item cannot have `[const]` trait bounds + +error: `[const]` can only be applied to `const` traits + --> $DIR/trait_alias.rs:17:17 + | +LL | const fn foo(x: &T) { + | ^^^^^^^ can't be applied to `Foo` + | +help: mark `Foo` as `const` to allow it to have `const` implementations + | +LL | #[const_trait] const trait Foo = [const] Bar + Baz; + | ++++++++++++++ + +error: `[const]` can only be applied to `const` traits + --> $DIR/trait_alias.rs:17:17 + | +LL | const fn foo(x: &T) { + | ^^^^^^^ can't be applied to `Foo` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: mark `Foo` as `const` to allow it to have `const` implementations + | +LL | #[const_trait] const trait Foo = [const] Bar + Baz; + | ++++++++++++++ + +error[E0277]: the trait bound `T: [const] Bar` is not satisfied + --> $DIR/trait_alias.rs:20:7 + | +LL | x.bar(); + | ^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/trait_alias.rs b/tests/ui/consts/trait_alias.rs new file mode 100644 index 000000000000..945465de2ff8 --- /dev/null +++ b/tests/ui/consts/trait_alias.rs @@ -0,0 +1,31 @@ +#![feature(trait_alias, const_trait_impl)] +//@ revisions: pass fail + +const trait Bar { + fn bar(&self) {} +} +const trait Baz { + fn baz(&self) {} +} + +impl const Bar for () {} +impl const Baz for () {} + +const trait Foo = [const] Bar + Baz; +//~^ ERROR: `[const]` is not allowed here + +const fn foo(x: &T) { + //~^ ERROR: `[const]` can only be applied to `const` traits + //~| ERROR: `[const]` can only be applied to `const` traits + x.bar(); + //~^ ERROR: the trait bound `T: [const] Bar` is not satisfied + #[cfg(fail)] + { + x.baz(); + //[fail]~^ ERROR: the trait bound `T: [const] Baz` is not satisfied + } +} + +const _: () = foo(&()); + +fn main() {}