Skip to content

Constify trait aliases #144291

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

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3590,8 +3590,9 @@ impl Item {
ItemKind::Const(i) => Some(&i.generics),
ItemKind::Fn(i) => Some(&i.generics),
ItemKind::TyAlias(i) => Some(&i.generics),
ItemKind::TraitAlias(_, generics, _)
| ItemKind::Enum(_, generics, _)
ItemKind::TraitAlias(i) => Some(&i.generics),

ItemKind::Enum(_, generics, _)
| ItemKind::Struct(_, generics, _)
| ItemKind::Union(_, generics, _) => Some(&generics),
ItemKind::Trait(i) => Some(&i.generics),
Expand Down Expand Up @@ -3698,6 +3699,15 @@ 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)]
pub bounds: GenericBounds,
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct Trait {
pub constness: Const,
Expand Down Expand Up @@ -3889,7 +3899,7 @@ pub enum ItemKind {
/// Trait alias.
///
/// E.g., `trait Foo = Bar + Quux;`.
TraitAlias(Ident, Generics, GenericBounds),
TraitAlias(Box<TraitAlias>),
/// An implementation.
///
/// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
Expand Down Expand Up @@ -3922,7 +3932,7 @@ impl ItemKind {
| ItemKind::Struct(ident, ..)
| ItemKind::Union(ident, ..)
| ItemKind::Trait(box Trait { ident, .. })
| ItemKind::TraitAlias(ident, ..)
| ItemKind::TraitAlias(box TraitAlias { ident, .. })
| ItemKind::MacroDef(ident, _)
| ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),

Expand Down Expand Up @@ -3979,7 +3989,7 @@ impl ItemKind {
| Self::Struct(_, generics, _)
| Self::Union(_, generics, _)
| Self::Trait(box Trait { generics, .. })
| Self::TraitAlias(_, generics, _)
| Self::TraitAlias(box TraitAlias { generics, .. })
| Self::Impl(box Impl { generics, .. }) => Some(generics),
_ => None,
}
Expand Down Expand Up @@ -4141,8 +4151,8 @@ mod size_asserts {
static_assert_size!(GenericBound, 88);
static_assert_size!(Generics, 40);
static_assert_size!(Impl, 136);
static_assert_size!(Item, 144);
static_assert_size!(ItemKind, 80);
static_assert_size!(Item, 136);
static_assert_size!(ItemKind, 72);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

static_assert_size!(LitKind, 24);
static_assert_size!(Local, 96);
static_assert_size!(MetaItemLit, 40);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -836,8 +836,8 @@ macro_rules! common_visitor_and_walkers {
visit_visitable!($($mut)? vis, impl_),
ItemKind::Trait(trait_) =>
visit_visitable!($($mut)? vis, trait_),
ItemKind::TraitAlias(ident, generics, bounds) => {
visit_visitable!($($mut)? vis, ident, generics);
ItemKind::TraitAlias(box TraitAlias { ident, generics, bounds, constness}) => {
visit_visitable!($($mut)? vis, ident, generics, constness);
visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound)
}
ItemKind::MacCall(m) =>
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items)
}
ItemKind::TraitAlias(ident, generics, bounds) => {
ItemKind::TraitAlias(box TraitAlias { ident, generics, bounds, constness }) => {
let ident = self.lower_ident(*ident);
let (generics, bounds) = self.lower_generics(
generics,
Expand All @@ -458,7 +458,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
},
);
hir::ItemKind::TraitAlias(ident, generics, bounds)
let constness = self.lower_constness(*constness);
hir::ItemKind::TraitAlias(constness, ident, generics, bounds)
}
ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => {
let ident = self.lower_ident(*ident);
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
});
}
ItemKind::TraitAlias(box TraitAlias { constness, generics, bounds, .. }) => {
let disallowed = matches!(constness, ast::Const::No)
.then(|| TildeConstReason::Trait { span: item.span });
self.with_tilde_const(disallowed, |this| {
this.visit_generics(generics);
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
});
}
ItemKind::Mod(safety, ident, mod_kind) => {
if let &Safety::Unsafe(span) = safety {
self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use ast::StaticItem;
use itertools::{Itertools, Position};
use rustc_ast as ast;
use rustc_ast::ModKind;
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, ModKind, TraitAlias};
use rustc_span::Ident;

use crate::pp::BoxMarker;
Expand Down Expand Up @@ -387,8 +386,11 @@ impl<'a> State<'a> {
let empty = item.attrs.is_empty() && items.is_empty();
self.bclose(item.span, empty, cb);
}
ast::ItemKind::TraitAlias(ident, generics, bounds) => {
let (cb, ib) = self.head(visibility_qualified(&item.vis, "trait"));
ast::ItemKind::TraitAlias(box TraitAlias { ident, generics, bounds, constness }) => {
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();
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4175,8 +4175,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, &'hir Impl<'hir>, ItemKind::Impl(imp), imp;
}
Expand Down Expand Up @@ -4353,7 +4353,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<A> Trait for Foo { .. }`.
Impl(&'hir Impl<'hir>),
Expand Down Expand Up @@ -4396,7 +4396,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 { .. }
Expand All @@ -4414,7 +4414,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,
})
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,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);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
hir::ItemKind::Trait(constness, is_auto, safety, ..) => {
(constness, false, is_auto == hir::IsAuto::Yes, safety)
}
hir::ItemKind::TraitAlias(..) => (hir::Constness::NotConst, true, false, hir::Safety::Safe),
hir::ItemKind::TraitAlias(constness, ..) => (constness, true, false, hir::Safety::Safe),
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
};

Expand Down
38 changes: 22 additions & 16 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,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));
}
_ => {}
Expand Down Expand Up @@ -656,7 +656,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"),
};

Expand Down Expand Up @@ -1019,7 +1019,10 @@ pub(super) fn const_conditions<'tcx>(
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
hir::ItemKind::Fn { generics, .. } => (generics, None, false),
hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => {
(generics, Some((item.owner_id.def_id, supertraits)), false)
(generics, Some((Some(item.owner_id.def_id), supertraits)), false)
}
hir::ItemKind::TraitAlias(_, _, generics, supertraits) => {
(generics, Some((None, supertraits)), false)
}
_ => bug!("const_conditions called on wrong item: {def_id:?}"),
},
Expand Down Expand Up @@ -1075,12 +1078,14 @@ pub(super) fn const_conditions<'tcx>(
}

if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
// We've checked above that the trait is conditionally const.
bounds.push((
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
DUMMY_SP,
));
if let Some(def_id) = def_id {
// We've checked above that the trait is conditionally const.
bounds.push((
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
DUMMY_SP,
));
}

icx.lowerer().lower_bounds(
tcx.types.self_param,
Expand Down Expand Up @@ -1128,13 +1133,14 @@ pub(super) fn explicit_implied_const_bounds<'tcx>(
span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds")
}
None => match tcx.hir_node_by_def_id(def_id) {
Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
implied_predicates_with_filter(
tcx,
def_id.to_def_id(),
PredicateFilter::SelfConstIfConst,
)
}
Node::Item(hir::Item {
kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..),
..
}) => implied_predicates_with_filter(
tcx,
def_id.to_def_id(),
PredicateFilter::SelfConstIfConst,
),
Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. })
| Node::OpaqueTy(_) => {
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,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));
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {

let (trait_generics, trait_bounds) = match parent_trait.kind {
hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => (generics, supertraits),
hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
hir::ItemKind::TraitAlias(_, _, generics, supertraits) => (generics, supertraits),
_ => unreachable!(),
};

Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,8 +760,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();
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,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
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_lint/src/nonstandard_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ impl EarlyLintPass for NonCamelCaseTypes {
ast::ItemKind::Trait(box ast::Trait { ident, .. }) => {
self.check_case(cx, "trait", ident)
}
ast::ItemKind::TraitAlias(ident, _, _) => self.check_case(cx, "trait alias", ident),
ast::ItemKind::TraitAlias(box ast::TraitAlias { ident, .. }) => {
self.check_case(cx, "trait alias", ident)
}

// N.B. This check is only for inherent associated types, so that we don't lint against
// trait impls where we should have warned for the trait definition already.
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2109,7 +2109,7 @@ impl<'tcx> TyCtxt<'tcx> {
DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
self.constness(def_id) == hir::Constness::Const
}
DefKind::Trait => self.is_const_trait(def_id),
DefKind::TraitAlias | DefKind::Trait => self.is_const_trait(def_id),
DefKind::AssocTy => {
let parent_def_id = self.parent(def_id);
match self.def_kind(parent_def_id) {
Expand Down Expand Up @@ -2152,7 +2152,6 @@ impl<'tcx> TyCtxt<'tcx> {
| DefKind::Variant
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::TyParam
| DefKind::Const
| DefKind::ConstParam
Expand Down
31 changes: 28 additions & 3 deletions compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,35 @@ where
}

fn consider_trait_alias_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("trait aliases are never const")
let cx = ecx.cx();

ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
let where_clause_bounds = cx
.predicates_of(goal.predicate.def_id())
.iter_instantiated(cx, goal.predicate.trait_ref.args)
.map(|p| goal.with(cx, p));
ecx.add_goals(GoalSource::Misc, where_clause_bounds);

let const_conditions = cx
.const_conditions(goal.predicate.def_id())
.iter_instantiated(cx, goal.predicate.trait_ref.args)
.map(|bound_trait_ref| {
goal.with(
cx,
bound_trait_ref.to_host_effect_clause(cx, goal.predicate.constness),
)
});
// While you could think of trait aliases to have a single builtin impl
// which uses its implied trait bounds as where-clauses, using
// `GoalSource::ImplWhereClause` here would be incorrect, as we also
// impl them, which means we're "stepping out of the impl constructor"
// again. To handle this, we treat these cycles as ambiguous for now.
ecx.add_goals(GoalSource::Misc, const_conditions);
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
})
}

fn consider_builtin_sizedness_candidates(
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,6 @@ parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
.suggestion = remove the `{$token}`

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_transpose_dyn_or_impl = `for<...>` expected after `{$kw}`, not before
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1961,14 +1961,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 {
Expand Down
Loading
Loading