Rollup merge of #144291 - oli-obk:const_trait_alias, r=fee1-dead
Constify trait aliases Allow `const trait Foo = Bar + [const] Baz;` trait alias declarations. Their rules are the same as with super traits of const traits. So `[const] Baz` or `const Baz` is only required for `[const] Foo` or `const Foo` bounds respectively. tracking issue rust-lang/rust#41517 (part of the general trait alias feature gate, but I can split it out into a separate const trait alias feature gate. I just assumed that const traits would stabilize before trait aliases, and we'd want to stabilize trait aliases together with const trait aliases at the same time) r? ``@compiler-errors`` ``@fee1-dead``
This commit is contained in:
@@ -3540,8 +3540,9 @@ impl Item {
|
|||||||
ItemKind::Const(i) => Some(&i.generics),
|
ItemKind::Const(i) => Some(&i.generics),
|
||||||
ItemKind::Fn(i) => Some(&i.generics),
|
ItemKind::Fn(i) => Some(&i.generics),
|
||||||
ItemKind::TyAlias(i) => Some(&i.generics),
|
ItemKind::TyAlias(i) => Some(&i.generics),
|
||||||
ItemKind::TraitAlias(_, generics, _)
|
ItemKind::TraitAlias(i) => Some(&i.generics),
|
||||||
| ItemKind::Enum(_, generics, _)
|
|
||||||
|
ItemKind::Enum(_, generics, _)
|
||||||
| ItemKind::Struct(_, generics, _)
|
| ItemKind::Struct(_, generics, _)
|
||||||
| ItemKind::Union(_, generics, _) => Some(&generics),
|
| ItemKind::Union(_, generics, _) => Some(&generics),
|
||||||
ItemKind::Trait(i) => Some(&i.generics),
|
ItemKind::Trait(i) => Some(&i.generics),
|
||||||
@@ -3623,6 +3624,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)]
|
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||||
pub struct Trait {
|
pub struct Trait {
|
||||||
pub constness: Const,
|
pub constness: Const,
|
||||||
@@ -3798,7 +3808,7 @@ pub enum ItemKind {
|
|||||||
/// Trait alias.
|
/// Trait alias.
|
||||||
///
|
///
|
||||||
/// E.g., `trait Foo = Bar + Quux;`.
|
/// E.g., `trait Foo = Bar + Quux;`.
|
||||||
TraitAlias(Ident, Generics, GenericBounds),
|
TraitAlias(Box<TraitAlias>),
|
||||||
/// An implementation.
|
/// An implementation.
|
||||||
///
|
///
|
||||||
/// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
|
/// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
|
||||||
@@ -3831,7 +3841,7 @@ impl ItemKind {
|
|||||||
| ItemKind::Struct(ident, ..)
|
| ItemKind::Struct(ident, ..)
|
||||||
| ItemKind::Union(ident, ..)
|
| ItemKind::Union(ident, ..)
|
||||||
| ItemKind::Trait(box Trait { ident, .. })
|
| ItemKind::Trait(box Trait { ident, .. })
|
||||||
| ItemKind::TraitAlias(ident, ..)
|
| ItemKind::TraitAlias(box TraitAlias { ident, .. })
|
||||||
| ItemKind::MacroDef(ident, _)
|
| ItemKind::MacroDef(ident, _)
|
||||||
| ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
|
| ItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
|
||||||
|
|
||||||
@@ -3888,7 +3898,7 @@ impl ItemKind {
|
|||||||
| Self::Struct(_, generics, _)
|
| Self::Struct(_, generics, _)
|
||||||
| Self::Union(_, generics, _)
|
| Self::Union(_, generics, _)
|
||||||
| Self::Trait(box Trait { generics, .. })
|
| Self::Trait(box Trait { generics, .. })
|
||||||
| Self::TraitAlias(_, generics, _)
|
| Self::TraitAlias(box TraitAlias { generics, .. })
|
||||||
| Self::Impl(Impl { generics, .. }) => Some(generics),
|
| Self::Impl(Impl { generics, .. }) => Some(generics),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@@ -4050,8 +4060,8 @@ mod size_asserts {
|
|||||||
static_assert_size!(GenericBound, 88);
|
static_assert_size!(GenericBound, 88);
|
||||||
static_assert_size!(Generics, 40);
|
static_assert_size!(Generics, 40);
|
||||||
static_assert_size!(Impl, 64);
|
static_assert_size!(Impl, 64);
|
||||||
static_assert_size!(Item, 144);
|
static_assert_size!(Item, 136);
|
||||||
static_assert_size!(ItemKind, 80);
|
static_assert_size!(ItemKind, 72);
|
||||||
static_assert_size!(LitKind, 24);
|
static_assert_size!(LitKind, 24);
|
||||||
static_assert_size!(Local, 96);
|
static_assert_size!(Local, 96);
|
||||||
static_assert_size!(MetaItemLit, 40);
|
static_assert_size!(MetaItemLit, 40);
|
||||||
|
|||||||
@@ -833,8 +833,8 @@ macro_rules! common_visitor_and_walkers {
|
|||||||
visit_visitable!($($mut)? vis, impl_),
|
visit_visitable!($($mut)? vis, impl_),
|
||||||
ItemKind::Trait(trait_) =>
|
ItemKind::Trait(trait_) =>
|
||||||
visit_visitable!($($mut)? vis, trait_),
|
visit_visitable!($($mut)? vis, trait_),
|
||||||
ItemKind::TraitAlias(ident, generics, bounds) => {
|
ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds}) => {
|
||||||
visit_visitable!($($mut)? vis, ident, generics);
|
visit_visitable!($($mut)? vis, constness, ident, generics);
|
||||||
visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound)
|
visit_visitable_with!($($mut)? vis, bounds, BoundKind::Bound)
|
||||||
}
|
}
|
||||||
ItemKind::MacCall(m) =>
|
ItemKind::MacCall(m) =>
|
||||||
|
|||||||
@@ -415,7 +415,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
);
|
);
|
||||||
hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items)
|
hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items)
|
||||||
}
|
}
|
||||||
ItemKind::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 ident = self.lower_ident(*ident);
|
||||||
let (generics, bounds) = self.lower_generics(
|
let (generics, bounds) = self.lower_generics(
|
||||||
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 }) => {
|
ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => {
|
||||||
let ident = self.lower_ident(*ident);
|
let ident = self.lower_ident(*ident);
|
||||||
|
|||||||
@@ -1192,6 +1192,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
|
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) => {
|
ItemKind::Mod(safety, ident, mod_kind) => {
|
||||||
if let &Safety::Unsafe(span) = safety {
|
if let &Safety::Unsafe(span) = safety {
|
||||||
self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
|
self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" });
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use ast::StaticItem;
|
use ast::StaticItem;
|
||||||
use itertools::{Itertools, Position};
|
use itertools::{Itertools, Position};
|
||||||
use rustc_ast as ast;
|
use rustc_ast::{self as ast, ModKind, TraitAlias};
|
||||||
use rustc_ast::ModKind;
|
|
||||||
use rustc_span::Ident;
|
use rustc_span::Ident;
|
||||||
|
|
||||||
use crate::pp::BoxMarker;
|
use crate::pp::BoxMarker;
|
||||||
@@ -386,8 +385,11 @@ impl<'a> State<'a> {
|
|||||||
let empty = item.attrs.is_empty() && items.is_empty();
|
let empty = item.attrs.is_empty() && items.is_empty();
|
||||||
self.bclose(item.span, empty, cb);
|
self.bclose(item.span, empty, cb);
|
||||||
}
|
}
|
||||||
ast::ItemKind::TraitAlias(ident, generics, bounds) => {
|
ast::ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds }) => {
|
||||||
let (cb, ib) = self.head(visibility_qualified(&item.vis, "trait"));
|
let (cb, ib) = self.head("");
|
||||||
|
self.print_visibility(&item.vis);
|
||||||
|
self.print_constness(*constness);
|
||||||
|
self.word_nbsp("trait");
|
||||||
self.print_ident(*ident);
|
self.print_ident(*ident);
|
||||||
self.print_generic_params(&generics.params);
|
self.print_generic_params(&generics.params);
|
||||||
self.nbsp();
|
self.nbsp();
|
||||||
|
|||||||
@@ -4151,8 +4151,8 @@ impl<'hir> Item<'hir> {
|
|||||||
ItemKind::Trait(constness, is_auto, safety, ident, generics, bounds, items),
|
ItemKind::Trait(constness, is_auto, safety, ident, generics, bounds, items),
|
||||||
(*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>),
|
expect_trait_alias, (Constness, Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
|
||||||
ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds);
|
ItemKind::TraitAlias(constness, ident, generics, bounds), (*constness, *ident, generics, bounds);
|
||||||
|
|
||||||
expect_impl, &Impl<'hir>, ItemKind::Impl(imp), imp;
|
expect_impl, &Impl<'hir>, ItemKind::Impl(imp), imp;
|
||||||
}
|
}
|
||||||
@@ -4329,7 +4329,7 @@ pub enum ItemKind<'hir> {
|
|||||||
&'hir [TraitItemId],
|
&'hir [TraitItemId],
|
||||||
),
|
),
|
||||||
/// A trait alias.
|
/// 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 { .. }`.
|
/// An implementation, e.g., `impl<A> Trait for Foo { .. }`.
|
||||||
Impl(Impl<'hir>),
|
Impl(Impl<'hir>),
|
||||||
@@ -4374,7 +4374,7 @@ impl ItemKind<'_> {
|
|||||||
| ItemKind::Struct(ident, ..)
|
| ItemKind::Struct(ident, ..)
|
||||||
| ItemKind::Union(ident, ..)
|
| ItemKind::Union(ident, ..)
|
||||||
| ItemKind::Trait(_, _, _, ident, ..)
|
| ItemKind::Trait(_, _, _, ident, ..)
|
||||||
| ItemKind::TraitAlias(ident, ..) => Some(ident),
|
| ItemKind::TraitAlias(_, ident, ..) => Some(ident),
|
||||||
|
|
||||||
ItemKind::Use(_, UseKind::Glob | UseKind::ListStem)
|
ItemKind::Use(_, UseKind::Glob | UseKind::ListStem)
|
||||||
| ItemKind::ForeignMod { .. }
|
| ItemKind::ForeignMod { .. }
|
||||||
@@ -4392,7 +4392,7 @@ impl ItemKind<'_> {
|
|||||||
| ItemKind::Struct(_, generics, _)
|
| ItemKind::Struct(_, generics, _)
|
||||||
| ItemKind::Union(_, generics, _)
|
| ItemKind::Union(_, generics, _)
|
||||||
| ItemKind::Trait(_, _, _, _, generics, _, _)
|
| ItemKind::Trait(_, _, _, _, generics, _, _)
|
||||||
| ItemKind::TraitAlias(_, generics, _)
|
| ItemKind::TraitAlias(_, _, generics, _)
|
||||||
| ItemKind::Impl(Impl { generics, .. }) => generics,
|
| ItemKind::Impl(Impl { generics, .. }) => generics,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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_param_bound, bounds);
|
||||||
walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
|
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_ident(ident));
|
||||||
try_visit!(visitor.visit_generics(generics));
|
try_visit!(visitor.visit_generics(generics));
|
||||||
walk_list!(visitor, visit_param_bound, bounds);
|
walk_list!(visitor, visit_param_bound, bounds);
|
||||||
|
|||||||
@@ -847,7 +847,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
|||||||
hir::ItemKind::Trait(constness, is_auto, safety, ..) => {
|
hir::ItemKind::Trait(constness, is_auto, safety, ..) => {
|
||||||
(constness, false, is_auto == hir::IsAuto::Yes, 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"),
|
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Trait(_, _, _, _, _, self_bounds, ..)
|
ItemKind::Trait(_, _, _, _, _, self_bounds, ..)
|
||||||
| ItemKind::TraitAlias(_, _, self_bounds) => {
|
| ItemKind::TraitAlias(_, _, _, self_bounds) => {
|
||||||
is_trait = Some((self_bounds, item.span));
|
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 {
|
let (generics, superbounds) = match item.kind {
|
||||||
hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
|
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"),
|
_ => span_bug!(item.span, "super_predicates invoked on non-trait"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1032,7 +1032,10 @@ pub(super) fn const_conditions<'tcx>(
|
|||||||
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
|
hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
|
||||||
hir::ItemKind::Fn { generics, .. } => (generics, None, false),
|
hir::ItemKind::Fn { generics, .. } => (generics, None, false),
|
||||||
hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => {
|
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:?}"),
|
_ => bug!("const_conditions called on wrong item: {def_id:?}"),
|
||||||
},
|
},
|
||||||
@@ -1089,12 +1092,14 @@ pub(super) fn const_conditions<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
|
if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
|
||||||
// We've checked above that the trait is conditionally const.
|
if let Some(def_id) = def_id {
|
||||||
bounds.push((
|
// We've checked above that the trait is conditionally const.
|
||||||
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
|
bounds.push((
|
||||||
.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
|
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
|
||||||
DUMMY_SP,
|
.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
|
||||||
));
|
DUMMY_SP,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
icx.lowerer().lower_bounds(
|
icx.lowerer().lower_bounds(
|
||||||
tcx.types.self_param,
|
tcx.types.self_param,
|
||||||
@@ -1143,13 +1148,14 @@ pub(super) fn explicit_implied_const_bounds<'tcx>(
|
|||||||
span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds")
|
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) {
|
None => match tcx.hir_node_by_def_id(def_id) {
|
||||||
Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
|
Node::Item(hir::Item {
|
||||||
implied_predicates_with_filter(
|
kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..),
|
||||||
tcx,
|
..
|
||||||
def_id.to_def_id(),
|
}) => implied_predicates_with_filter(
|
||||||
PredicateFilter::SelfConstIfConst,
|
tcx,
|
||||||
)
|
def_id.to_def_id(),
|
||||||
}
|
PredicateFilter::SelfConstIfConst,
|
||||||
|
),
|
||||||
Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. })
|
Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. })
|
||||||
| Node::OpaqueTy(_) => {
|
| Node::OpaqueTy(_) => {
|
||||||
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
|
explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
|
||||||
|
|||||||
@@ -632,7 +632,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||||||
| hir::ItemKind::Struct(_, generics, _)
|
| hir::ItemKind::Struct(_, generics, _)
|
||||||
| hir::ItemKind::Union(_, generics, _)
|
| hir::ItemKind::Union(_, generics, _)
|
||||||
| hir::ItemKind::Trait(_, _, _, _, generics, ..)
|
| hir::ItemKind::Trait(_, _, _, _, generics, ..)
|
||||||
| hir::ItemKind::TraitAlias(_, generics, ..)
|
| hir::ItemKind::TraitAlias(_, _, generics, ..)
|
||||||
| hir::ItemKind::Impl(hir::Impl { generics, .. }) => {
|
| hir::ItemKind::Impl(hir::Impl { generics, .. }) => {
|
||||||
// These kinds of items have only early-bound lifetime parameters.
|
// These kinds of items have only early-bound lifetime parameters.
|
||||||
self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
|
self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
|
||||||
|
|||||||
@@ -765,8 +765,10 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
self.bclose(item.span, cb);
|
self.bclose(item.span, cb);
|
||||||
}
|
}
|
||||||
hir::ItemKind::TraitAlias(ident, generics, bounds) => {
|
hir::ItemKind::TraitAlias(constness, ident, generics, bounds) => {
|
||||||
let (cb, ib) = self.head("trait");
|
let (cb, ib) = self.head("");
|
||||||
|
self.print_constness(constness);
|
||||||
|
self.word_nbsp("trait");
|
||||||
self.print_ident(ident);
|
self.print_ident(ident);
|
||||||
self.print_generic_params(generics.params);
|
self.print_generic_params(generics.params);
|
||||||
self.nbsp();
|
self.nbsp();
|
||||||
|
|||||||
@@ -1596,7 +1596,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
Node::Item(hir::Item {
|
Node::Item(hir::Item {
|
||||||
kind:
|
kind:
|
||||||
hir::ItemKind::Trait(_, _, _, ident, ..)
|
hir::ItemKind::Trait(_, _, _, ident, ..)
|
||||||
| hir::ItemKind::TraitAlias(ident, ..),
|
| hir::ItemKind::TraitAlias(_, ident, ..),
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
// We may also encounter unsatisfied GAT or method bounds
|
// We may also encounter unsatisfied GAT or method bounds
|
||||||
|
|||||||
@@ -160,7 +160,9 @@ impl EarlyLintPass for NonCamelCaseTypes {
|
|||||||
ast::ItemKind::Trait(box ast::Trait { ident, .. }) => {
|
ast::ItemKind::Trait(box ast::Trait { ident, .. }) => {
|
||||||
self.check_case(cx, "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
|
// 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.
|
// trait impls where we should have warned for the trait definition already.
|
||||||
|
|||||||
@@ -2101,7 +2101,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
|
DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) => {
|
||||||
self.constness(def_id) == hir::Constness::Const
|
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 => {
|
DefKind::AssocTy => {
|
||||||
let parent_def_id = self.parent(def_id);
|
let parent_def_id = self.parent(def_id);
|
||||||
match self.def_kind(parent_def_id) {
|
match self.def_kind(parent_def_id) {
|
||||||
@@ -2144,7 +2144,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
| DefKind::Variant
|
| DefKind::Variant
|
||||||
| DefKind::TyAlias
|
| DefKind::TyAlias
|
||||||
| DefKind::ForeignTy
|
| DefKind::ForeignTy
|
||||||
| DefKind::TraitAlias
|
|
||||||
| DefKind::TyParam
|
| DefKind::TyParam
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
|
|||||||
@@ -196,10 +196,35 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn consider_trait_alias_candidate(
|
fn consider_trait_alias_candidate(
|
||||||
_ecx: &mut EvalCtxt<'_, D>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
_goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
) -> Result<Candidate<I>, NoSolution> {
|
) -> 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().into())
|
||||||
|
.iter_instantiated(cx, goal.predicate.trait_ref.args)
|
||||||
|
.map(|p| goal.with(cx, p));
|
||||||
|
|
||||||
|
let const_conditions = cx
|
||||||
|
.const_conditions(goal.predicate.def_id().into())
|
||||||
|
.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, where_clause_bounds);
|
||||||
|
ecx.add_goals(GoalSource::Misc, const_conditions);
|
||||||
|
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consider_builtin_sizedness_candidates(
|
fn consider_builtin_sizedness_candidates(
|
||||||
|
|||||||
@@ -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_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_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_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
|
||||||
|
|
||||||
parse_trait_impl_modifier_in_inherent_impl = inherent impls cannot be {$modifier_name}
|
parse_trait_impl_modifier_in_inherent_impl = inherent impls cannot be {$modifier_name}
|
||||||
|
|||||||
@@ -1999,14 +1999,6 @@ pub(crate) struct TraitAliasCannotBeAuto {
|
|||||||
pub span: Span,
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(parse_trait_alias_cannot_be_unsafe)]
|
#[diag(parse_trait_alias_cannot_be_unsafe)]
|
||||||
pub(crate) struct TraitAliasCannotBeUnsafe {
|
pub(crate) struct TraitAliasCannotBeUnsafe {
|
||||||
|
|||||||
@@ -943,9 +943,6 @@ impl<'a> Parser<'a> {
|
|||||||
self.expect_semi()?;
|
self.expect_semi()?;
|
||||||
|
|
||||||
let whole_span = lo.to(self.prev_token.span);
|
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 {
|
if is_auto == IsAuto::Yes {
|
||||||
self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span });
|
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);
|
self.psess.gated_spans.gate(sym::trait_alias, whole_span);
|
||||||
|
|
||||||
Ok(ItemKind::TraitAlias(ident, generics, bounds))
|
Ok(ItemKind::TraitAlias(Box::new(TraitAlias { constness, ident, generics, bounds })))
|
||||||
} else {
|
} else {
|
||||||
// It's a normal trait.
|
// It's a normal trait.
|
||||||
generics.where_clause = self.parse_where_clause()?;
|
generics.where_clause = self.parse_where_clause()?;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use std::sync::Arc;
|
|||||||
use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
|
use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem,
|
self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem,
|
||||||
ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TyAlias,
|
ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, TyAlias,
|
||||||
};
|
};
|
||||||
use rustc_attr_parsing as attr;
|
use rustc_attr_parsing as attr;
|
||||||
use rustc_attr_parsing::AttributeParser;
|
use rustc_attr_parsing::AttributeParser;
|
||||||
@@ -844,7 +844,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// These items live in the type namespace.
|
// These items live in the type namespace.
|
||||||
ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => {
|
ItemKind::TyAlias(box TyAlias { ident, .. })
|
||||||
|
| ItemKind::TraitAlias(box TraitAlias { ident, .. }) => {
|
||||||
self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion);
|
self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2645,7 +2645,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::TraitAlias(_, ref generics, ref bounds) => {
|
ItemKind::TraitAlias(box TraitAlias { ref generics, ref bounds, .. }) => {
|
||||||
// Create a new rib for the trait-wide type parameters.
|
// Create a new rib for the trait-wide type parameters.
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
@@ -5164,7 +5164,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
|
|||||||
| ItemKind::Union(_, generics, _)
|
| ItemKind::Union(_, generics, _)
|
||||||
| ItemKind::Impl(Impl { generics, .. })
|
| ItemKind::Impl(Impl { generics, .. })
|
||||||
| ItemKind::Trait(box Trait { generics, .. })
|
| ItemKind::Trait(box Trait { generics, .. })
|
||||||
| ItemKind::TraitAlias(_, generics, _) => {
|
| ItemKind::TraitAlias(box TraitAlias { generics, .. }) => {
|
||||||
if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind {
|
if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind {
|
||||||
self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs);
|
self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -476,9 +476,8 @@ pub fn report_dyn_incompatibility<'tcx>(
|
|||||||
let trait_str = tcx.def_path_str(trait_def_id);
|
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 {
|
let trait_span = tcx.hir_get_if_local(trait_def_id).and_then(|node| match node {
|
||||||
hir::Node::Item(item) => match item.kind {
|
hir::Node::Item(item) => match item.kind {
|
||||||
hir::ItemKind::Trait(_, _, _, ident, ..) | hir::ItemKind::TraitAlias(ident, _, _) => {
|
hir::ItemKind::Trait(_, _, _, ident, ..)
|
||||||
Some(ident.span)
|
| hir::ItemKind::TraitAlias(_, ident, _, _) => Some(ident.span),
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
| hir::ItemKind::Fn { generics, .. }
|
| hir::ItemKind::Fn { generics, .. }
|
||||||
| hir::ItemKind::TyAlias(_, generics, _)
|
| hir::ItemKind::TyAlias(_, generics, _)
|
||||||
| hir::ItemKind::Const(_, generics, _, _)
|
| hir::ItemKind::Const(_, generics, _, _)
|
||||||
| hir::ItemKind::TraitAlias(_, generics, _),
|
| hir::ItemKind::TraitAlias(_, _, generics, _),
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
| hir::Node::TraitItem(hir::TraitItem { generics, .. })
|
| hir::Node::TraitItem(hir::TraitItem { generics, .. })
|
||||||
@@ -444,7 +444,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
| hir::ItemKind::Fn { generics, .. }
|
| hir::ItemKind::Fn { generics, .. }
|
||||||
| hir::ItemKind::TyAlias(_, generics, _)
|
| hir::ItemKind::TyAlias(_, generics, _)
|
||||||
| hir::ItemKind::Const(_, generics, _, _)
|
| hir::ItemKind::Const(_, generics, _, _)
|
||||||
| hir::ItemKind::TraitAlias(_, generics, _),
|
| hir::ItemKind::TraitAlias(_, _, generics, _),
|
||||||
..
|
..
|
||||||
}) if finder.can_suggest_bound(generics) => {
|
}) if finder.can_suggest_bound(generics) => {
|
||||||
// Missing generic type parameter bound.
|
// Missing generic type parameter bound.
|
||||||
|
|||||||
@@ -69,6 +69,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
|
|||||||
Err(EvaluationFailure::NoSolution) => {}
|
Err(EvaluationFailure::NoSolution) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match evaluate_host_effect_from_trait_alias(selcx, obligation) {
|
||||||
|
Ok(result) => return Ok(result),
|
||||||
|
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
|
||||||
|
Err(EvaluationFailure::NoSolution) => {}
|
||||||
|
}
|
||||||
|
|
||||||
Err(EvaluationFailure::NoSolution)
|
Err(EvaluationFailure::NoSolution)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,3 +599,37 @@ fn evaluate_host_effect_from_selection_candidate<'tcx>(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn evaluate_host_effect_from_trait_alias<'tcx>(
|
||||||
|
selcx: &mut SelectionContext<'_, 'tcx>,
|
||||||
|
obligation: &HostEffectObligation<'tcx>,
|
||||||
|
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
|
||||||
|
let tcx = selcx.tcx();
|
||||||
|
let def_id = obligation.predicate.def_id();
|
||||||
|
if !tcx.trait_is_alias(def_id) {
|
||||||
|
return Err(EvaluationFailure::NoSolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(tcx
|
||||||
|
.const_conditions(def_id)
|
||||||
|
.instantiate(tcx, obligation.predicate.trait_ref.args)
|
||||||
|
.into_iter()
|
||||||
|
.map(|(trait_ref, span)| {
|
||||||
|
Obligation::new(
|
||||||
|
tcx,
|
||||||
|
obligation.cause.clone().derived_host_cause(
|
||||||
|
ty::Binder::dummy(obligation.predicate),
|
||||||
|
|derived| {
|
||||||
|
ObligationCauseCode::ImplDerivedHost(Box::new(ImplDerivedHostCause {
|
||||||
|
derived,
|
||||||
|
impl_def_id: def_id,
|
||||||
|
span,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
),
|
||||||
|
obligation.param_env,
|
||||||
|
trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|||||||
@@ -2827,7 +2827,7 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||||||
variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
|
variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
|
||||||
generics: clean_generics(generics, cx),
|
generics: clean_generics(generics, cx),
|
||||||
}),
|
}),
|
||||||
ItemKind::TraitAlias(_, generics, bounds) => TraitAliasItem(TraitAlias {
|
ItemKind::TraitAlias(_, _, generics, bounds) => TraitAliasItem(TraitAlias {
|
||||||
generics: clean_generics(generics, cx),
|
generics: clean_generics(generics, cx),
|
||||||
bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -528,7 +528,7 @@ impl LateLintPass<'_> for ItemNameRepetitions {
|
|||||||
| ItemKind::Macro(ident, ..)
|
| ItemKind::Macro(ident, ..)
|
||||||
| ItemKind::Static(_, ident, ..)
|
| ItemKind::Static(_, ident, ..)
|
||||||
| ItemKind::Trait(_, _, _, ident, ..)
|
| ItemKind::Trait(_, _, _, ident, ..)
|
||||||
| ItemKind::TraitAlias(ident, ..)
|
| ItemKind::TraitAlias(_, ident, ..)
|
||||||
| ItemKind::TyAlias(ident, ..)
|
| ItemKind::TyAlias(ident, ..)
|
||||||
| ItemKind::Union(ident, ..)
|
| ItemKind::Union(ident, ..)
|
||||||
| ItemKind::Use(_, UseKind::Single(ident)) => ident,
|
| ItemKind::Use(_, UseKind::Single(ident)) => ident,
|
||||||
|
|||||||
@@ -473,8 +473,24 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||||||
&& over(lb, rb, eq_generic_bound)
|
&& over(lb, rb, eq_generic_bound)
|
||||||
&& over(lis, ris, |l, r| eq_item(l, r, eq_assoc_item_kind))
|
&& over(lis, ris, |l, r| eq_item(l, r, eq_assoc_item_kind))
|
||||||
},
|
},
|
||||||
(TraitAlias(li, lg, lb), TraitAlias(ri, rg, rb)) => {
|
(
|
||||||
eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound)
|
TraitAlias(box ast::TraitAlias {
|
||||||
|
ident: li,
|
||||||
|
generics: lg,
|
||||||
|
bounds: lb,
|
||||||
|
constness: lc,
|
||||||
|
}),
|
||||||
|
TraitAlias(box ast::TraitAlias {
|
||||||
|
ident: ri,
|
||||||
|
generics: rg,
|
||||||
|
bounds: rb,
|
||||||
|
constness: rc,
|
||||||
|
}),
|
||||||
|
) => {
|
||||||
|
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 {
|
Impl(ast::Impl {
|
||||||
|
|||||||
@@ -1375,22 +1375,21 @@ impl<'a> Rewrite for TraitAliasBounds<'a> {
|
|||||||
|
|
||||||
pub(crate) fn format_trait_alias(
|
pub(crate) fn format_trait_alias(
|
||||||
context: &RewriteContext<'_>,
|
context: &RewriteContext<'_>,
|
||||||
ident: symbol::Ident,
|
ta: &ast::TraitAlias,
|
||||||
vis: &ast::Visibility,
|
vis: &ast::Visibility,
|
||||||
generics: &ast::Generics,
|
|
||||||
generic_bounds: &ast::GenericBounds,
|
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
let alias = rewrite_ident(context, ident);
|
let alias = rewrite_ident(context, ta.ident);
|
||||||
// 6 = "trait ", 2 = " ="
|
// 6 = "trait ", 2 = " ="
|
||||||
let g_shape = shape.offset_left(6)?.sub_width(2)?;
|
let g_shape = shape.offset_left(6)?.sub_width(2)?;
|
||||||
let generics_str = rewrite_generics(context, alias, generics, g_shape).ok()?;
|
let generics_str = rewrite_generics(context, alias, &ta.generics, g_shape).ok()?;
|
||||||
let vis_str = format_visibility(context, vis);
|
let vis_str = format_visibility(context, vis);
|
||||||
let lhs = format!("{vis_str}trait {generics_str} =");
|
let constness = format_constness(ta.constness);
|
||||||
|
let lhs = format!("{vis_str}{constness}trait {generics_str} =");
|
||||||
// 1 = ";"
|
// 1 = ";"
|
||||||
let trait_alias_bounds = TraitAliasBounds {
|
let trait_alias_bounds = TraitAliasBounds {
|
||||||
generic_bounds,
|
generic_bounds: &ta.bounds,
|
||||||
generics,
|
generics: &ta.generics,
|
||||||
};
|
};
|
||||||
rewrite_assign_rhs(
|
rewrite_assign_rhs(
|
||||||
context,
|
context,
|
||||||
|
|||||||
@@ -497,16 +497,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
|
|||||||
let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
|
let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
|
||||||
self.push_rewrite(item.span, rw);
|
self.push_rewrite(item.span, rw);
|
||||||
}
|
}
|
||||||
ast::ItemKind::TraitAlias(ident, ref generics, ref generic_bounds) => {
|
ast::ItemKind::TraitAlias(ref ta) => {
|
||||||
let shape = Shape::indented(self.block_indent, self.config);
|
let shape = Shape::indented(self.block_indent, self.config);
|
||||||
let rw = format_trait_alias(
|
let rw = format_trait_alias(&self.get_context(), ta, &item.vis, shape);
|
||||||
&self.get_context(),
|
|
||||||
ident,
|
|
||||||
&item.vis,
|
|
||||||
generics,
|
|
||||||
generic_bounds,
|
|
||||||
shape,
|
|
||||||
);
|
|
||||||
self.push_rewrite(item.span, rw);
|
self.push_rewrite(item.span, rw);
|
||||||
}
|
}
|
||||||
ast::ItemKind::ExternCrate(..) => {
|
ast::ItemKind::ExternCrate(..) => {
|
||||||
|
|||||||
@@ -181,3 +181,5 @@ trait Visible {
|
|||||||
pub fn f();
|
pub fn f();
|
||||||
pub fn g() {}
|
pub fn g() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const trait Foomp = Hash;
|
||||||
5
src/tools/rustfmt/tests/target/const_trait.rs
Normal file
5
src/tools/rustfmt/tests/target/const_trait.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#![feature(trait_alias, const_trait_impl)]
|
||||||
|
|
||||||
|
const trait Bar {}
|
||||||
|
|
||||||
|
const trait Foo = Bar;
|
||||||
@@ -218,3 +218,5 @@ trait Visible {
|
|||||||
pub fn f();
|
pub fn f();
|
||||||
pub fn g() {}
|
pub fn g() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const trait Foomp = Hash;
|
||||||
|
|||||||
9
tests/ui/consts/trait_alias.fail.stderr
Normal file
9
tests/ui/consts/trait_alias.fail.stderr
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
error[E0277]: the trait bound `T: [const] Baz` is not satisfied
|
||||||
|
--> $DIR/trait_alias.rs:24:11
|
||||||
|
|
|
||||||
|
LL | x.baz();
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
9
tests/ui/consts/trait_alias.next_fail.stderr
Normal file
9
tests/ui/consts/trait_alias.next_fail.stderr
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
error[E0277]: the trait bound `T: [const] Baz` is not satisfied
|
||||||
|
--> $DIR/trait_alias.rs:24:11
|
||||||
|
|
|
||||||
|
LL | x.baz();
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
31
tests/ui/consts/trait_alias.rs
Normal file
31
tests/ui/consts/trait_alias.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#![feature(trait_alias, const_trait_impl)]
|
||||||
|
//@ revisions: next_pass next_fail pass fail
|
||||||
|
//@[next_pass] compile-flags: -Znext-solver
|
||||||
|
//@[next_fail] compile-flags: -Znext-solver
|
||||||
|
//@[next_pass] check-pass
|
||||||
|
//@[pass] check-pass
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
const fn foo<T: [const] Foo>(x: &T) {
|
||||||
|
x.bar();
|
||||||
|
#[cfg(any(fail, next_fail))]
|
||||||
|
{
|
||||||
|
x.baz();
|
||||||
|
//[fail,next_fail]~^ ERROR: the trait bound `T: [const] Baz` is not satisfied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const _: () = foo(&());
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
31
tests/ui/consts/trait_alias_method_call.rs
Normal file
31
tests/ui/consts/trait_alias_method_call.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//! Test that we do not need to handle host effects in `expand_trait_aliases`
|
||||||
|
|
||||||
|
#![feature(trait_alias, const_trait_impl)]
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
pub const trait Bar {
|
||||||
|
fn bar(&self) {}
|
||||||
|
}
|
||||||
|
pub const trait Baz {
|
||||||
|
fn baz(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl const Bar for () {}
|
||||||
|
impl const Baz for () {}
|
||||||
|
|
||||||
|
pub const trait Foo = [const] Bar + Baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
use foo::Foo as _;
|
||||||
|
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
// Ok via `[const] Bar` on `Foo`
|
||||||
|
().bar();
|
||||||
|
// Also works, because everything is fully concrete, so we're ignoring that
|
||||||
|
// `Baz` is not a const trait bound of `Foo`.
|
||||||
|
().baz();
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
@@ -2,14 +2,14 @@ ast-stats ================================================================
|
|||||||
ast-stats POST EXPANSION AST STATS: input_stats
|
ast-stats POST EXPANSION AST STATS: input_stats
|
||||||
ast-stats Name Accumulated Size Count Item Size
|
ast-stats Name Accumulated Size Count Item Size
|
||||||
ast-stats ----------------------------------------------------------------
|
ast-stats ----------------------------------------------------------------
|
||||||
ast-stats Item 1_584 (NN.N%) 11 144
|
ast-stats Item 1_496 (NN.N%) 11 136
|
||||||
ast-stats - Enum 144 (NN.N%) 1
|
ast-stats - Enum 136 (NN.N%) 1
|
||||||
ast-stats - ExternCrate 144 (NN.N%) 1
|
ast-stats - ExternCrate 136 (NN.N%) 1
|
||||||
ast-stats - ForeignMod 144 (NN.N%) 1
|
ast-stats - ForeignMod 136 (NN.N%) 1
|
||||||
ast-stats - Impl 144 (NN.N%) 1
|
ast-stats - Impl 136 (NN.N%) 1
|
||||||
ast-stats - Trait 144 (NN.N%) 1
|
ast-stats - Trait 136 (NN.N%) 1
|
||||||
ast-stats - Fn 288 (NN.N%) 2
|
ast-stats - Fn 272 (NN.N%) 2
|
||||||
ast-stats - Use 576 (NN.N%) 4
|
ast-stats - Use 544 (NN.N%) 4
|
||||||
ast-stats Ty 896 (NN.N%) 14 64
|
ast-stats Ty 896 (NN.N%) 14 64
|
||||||
ast-stats - Ptr 64 (NN.N%) 1
|
ast-stats - Ptr 64 (NN.N%) 1
|
||||||
ast-stats - Ref 64 (NN.N%) 1
|
ast-stats - Ref 64 (NN.N%) 1
|
||||||
@@ -57,7 +57,7 @@ ast-stats GenericArgs 40 (NN.N%) 1 40
|
|||||||
ast-stats - AngleBracketed 40 (NN.N%) 1
|
ast-stats - AngleBracketed 40 (NN.N%) 1
|
||||||
ast-stats Crate 40 (NN.N%) 1 40
|
ast-stats Crate 40 (NN.N%) 1 40
|
||||||
ast-stats ----------------------------------------------------------------
|
ast-stats ----------------------------------------------------------------
|
||||||
ast-stats Total 7_528 129
|
ast-stats Total 7_440 129
|
||||||
ast-stats ================================================================
|
ast-stats ================================================================
|
||||||
hir-stats ================================================================
|
hir-stats ================================================================
|
||||||
hir-stats HIR STATS: input_stats
|
hir-stats HIR STATS: input_stats
|
||||||
|
|||||||
Reference in New Issue
Block a user