Skip to content

Commit cb034f2

Browse files
Auto merge of #148434 - oli-obk:inherent-const-impl, r=<try>
Inherent const impl
2 parents e5efc33 + d780ac6 commit cb034f2

File tree

39 files changed

+351
-283
lines changed

39 files changed

+351
-283
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3687,6 +3687,7 @@ pub struct TyAlias {
36873687
#[derive(Clone, Encodable, Decodable, Debug)]
36883688
pub struct Impl {
36893689
pub generics: Generics,
3690+
pub constness: Const,
36903691
pub of_trait: Option<Box<TraitImplHeader>>,
36913692
pub self_ty: Box<Ty>,
36923693
pub items: ThinVec<Box<AssocItem>>,
@@ -3696,7 +3697,6 @@ pub struct Impl {
36963697
pub struct TraitImplHeader {
36973698
pub defaultness: Defaultness,
36983699
pub safety: Safety,
3699-
pub constness: Const,
37003700
pub polarity: ImplPolarity,
37013701
pub trait_ref: TraitRef,
37023702
}
@@ -4072,9 +4072,9 @@ mod size_asserts {
40724072
static_assert_size!(GenericArg, 24);
40734073
static_assert_size!(GenericBound, 88);
40744074
static_assert_size!(Generics, 40);
4075-
static_assert_size!(Impl, 64);
4076-
static_assert_size!(Item, 136);
4077-
static_assert_size!(ItemKind, 72);
4075+
static_assert_size!(Impl, 80);
4076+
static_assert_size!(Item, 152);
4077+
static_assert_size!(ItemKind, 88);
40784078
static_assert_size!(LitKind, 24);
40794079
static_assert_size!(Local, 96);
40804080
static_assert_size!(MetaItemLit, 40);
@@ -4085,7 +4085,7 @@ mod size_asserts {
40854085
static_assert_size!(PathSegment, 24);
40864086
static_assert_size!(Stmt, 32);
40874087
static_assert_size!(StmtKind, 16);
4088-
static_assert_size!(TraitImplHeader, 80);
4088+
static_assert_size!(TraitImplHeader, 72);
40894089
static_assert_size!(Ty, 64);
40904090
static_assert_size!(TyKind, 40);
40914091
// tidy-alphabetical-end

compiler/rustc_ast/src/visit.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -928,11 +928,11 @@ macro_rules! common_visitor_and_walkers {
928928
}
929929

930930
impl_walkable!(|&$($mut)? $($lt)? self: Impl, vis: &mut V| {
931-
let Impl { generics, of_trait, self_ty, items } = self;
931+
let Impl { generics, of_trait, self_ty, items, constness: _ } = self;
932932
try_visit!(vis.visit_generics(generics));
933933
if let Some(box of_trait) = of_trait {
934-
let TraitImplHeader { defaultness, safety, constness, polarity, trait_ref } = of_trait;
935-
visit_visitable!($($mut)? vis, defaultness, safety, constness, polarity, trait_ref);
934+
let TraitImplHeader { defaultness, safety, polarity, trait_ref } = of_trait;
935+
visit_visitable!($($mut)? vis, defaultness, safety, polarity, trait_ref);
936936
}
937937
try_visit!(vis.visit_ty(self_ty));
938938
visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() });

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
345345
of_trait,
346346
self_ty: ty,
347347
items: impl_items,
348+
constness,
348349
}) => {
349350
// Lower the "impl header" first. This ordering is important
350351
// for in-band lifetimes! Consider `'a` here:
@@ -378,11 +379,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
378379
.arena
379380
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
380381

382+
let constness = self.lower_constness(*constness);
383+
381384
hir::ItemKind::Impl(hir::Impl {
382385
generics,
383386
of_trait,
384387
self_ty: lowered_ty,
385388
items: new_impl_items,
389+
constness,
386390
})
387391
}
388392
ItemKind::Trait(box Trait {
@@ -970,9 +974,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
970974
&mut self,
971975
trait_impl_header: &TraitImplHeader,
972976
) -> &'hir hir::TraitImplHeader<'hir> {
973-
let TraitImplHeader { constness, safety, polarity, defaultness, ref trait_ref } =
974-
*trait_impl_header;
975-
let constness = self.lower_constness(constness);
977+
let TraitImplHeader { safety, polarity, defaultness, ref trait_ref } = *trait_impl_header;
976978
let safety = self.lower_safety(safety, hir::Safety::Safe);
977979
let polarity = match polarity {
978980
ImplPolarity::Positive => ImplPolarity::Positive,
@@ -995,7 +997,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
995997
);
996998

997999
self.arena.alloc(hir::TraitImplHeader {
998-
constness,
9991000
safety,
10001001
polarity,
10011002
defaultness,

compiler/rustc_ast_passes/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ ast_passes_generic_before_constraints = generic arguments must come before the f
200200
201201
ast_passes_generic_default_trailing = generic parameters with a default must be trailing
202202
203+
ast_passes_impl_fn_const =
204+
redundant `const` fn marker in const impl
205+
.parent_constness = this declares all associated functions implicitly const
206+
.label = remove the `const`
207+
203208
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
204209
.help = remove one of these features
205210

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 93 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,17 @@ enum SelfSemantic {
4747
No,
4848
}
4949

50-
enum TraitOrTraitImpl {
50+
enum TraitOrImpl {
5151
Trait { span: Span, constness: Const },
5252
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span },
53+
Impl { constness: Const },
5354
}
5455

55-
impl TraitOrTraitImpl {
56+
impl TraitOrImpl {
5657
fn constness(&self) -> Option<Span> {
5758
match self {
5859
Self::Trait { constness: Const::Yes(span), .. }
60+
| Self::Impl { constness: Const::Yes(span), .. }
5961
| Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span),
6062
_ => None,
6163
}
@@ -69,7 +71,7 @@ struct AstValidator<'a> {
6971
/// The span of the `extern` in an `extern { ... }` block, if any.
7072
extern_mod_span: Option<Span>,
7173

72-
outer_trait_or_trait_impl: Option<TraitOrTraitImpl>,
74+
outer_trait_or_trait_impl: Option<TraitOrImpl>,
7375

7476
has_proc_macro_decls: bool,
7577

@@ -92,28 +94,12 @@ struct AstValidator<'a> {
9294
}
9395

9496
impl<'a> AstValidator<'a> {
95-
fn with_in_trait_impl(
97+
fn with_in_trait_or_impl(
9698
&mut self,
97-
trait_: Option<(Const, ImplPolarity, &'a TraitRef)>,
99+
in_trait_or_impl: Option<TraitOrImpl>,
98100
f: impl FnOnce(&mut Self),
99101
) {
100-
let old = mem::replace(
101-
&mut self.outer_trait_or_trait_impl,
102-
trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl {
103-
constness,
104-
polarity,
105-
trait_ref_span: trait_ref.path.span,
106-
}),
107-
);
108-
f(self);
109-
self.outer_trait_or_trait_impl = old;
110-
}
111-
112-
fn with_in_trait(&mut self, span: Span, constness: Const, f: impl FnOnce(&mut Self)) {
113-
let old = mem::replace(
114-
&mut self.outer_trait_or_trait_impl,
115-
Some(TraitOrTraitImpl::Trait { span, constness }),
116-
);
102+
let old = mem::replace(&mut self.outer_trait_or_trait_impl, in_trait_or_impl);
117103
f(self);
118104
self.outer_trait_or_trait_impl = old;
119105
}
@@ -246,14 +232,26 @@ impl<'a> AstValidator<'a> {
246232
}
247233
}
248234

249-
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) {
235+
fn check_impl_fn_not_const(&self, constness: Const, parent_constness: Const) {
236+
let Const::Yes(span) = constness else {
237+
return;
238+
};
239+
240+
let Const::Yes(parent_constness) = parent_constness else {
241+
return;
242+
};
243+
244+
self.dcx().emit_err(errors::ImplFnConst { span, parent_constness });
245+
}
246+
247+
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrImpl) {
250248
let Const::Yes(span) = constness else {
251249
return;
252250
};
253251

254252
let const_trait_impl = self.features.const_trait_impl();
255253
let make_impl_const_sugg = if const_trait_impl
256-
&& let TraitOrTraitImpl::TraitImpl {
254+
&& let TraitOrImpl::TraitImpl {
257255
constness: Const::No,
258256
polarity: ImplPolarity::Positive,
259257
trait_ref_span,
@@ -266,7 +264,7 @@ impl<'a> AstValidator<'a> {
266264
};
267265

268266
let make_trait_const_sugg = if const_trait_impl
269-
&& let TraitOrTraitImpl::Trait { span, constness: ast::Const::No } = parent
267+
&& let TraitOrImpl::Trait { span, constness: ast::Const::No } = parent
270268
{
271269
Some(span.shrink_to_lo())
272270
} else {
@@ -276,7 +274,7 @@ impl<'a> AstValidator<'a> {
276274
let parent_constness = parent.constness();
277275
self.dcx().emit_err(errors::TraitFnConst {
278276
span,
279-
in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }),
277+
in_impl: matches!(parent, TraitOrImpl::TraitImpl { .. }),
280278
const_context_label: parent_constness,
281279
remove_const_sugg: (
282280
self.sess.source_map().span_extend_while_whitespace(span),
@@ -292,7 +290,7 @@ impl<'a> AstValidator<'a> {
292290
});
293291
}
294292

295-
fn check_async_fn_in_const_trait_or_impl(&self, sig: &FnSig, parent: &TraitOrTraitImpl) {
293+
fn check_async_fn_in_const_trait_or_impl(&self, sig: &FnSig, parent: &TraitOrImpl) {
296294
let Some(const_keyword) = parent.constness() else { return };
297295

298296
let Some(CoroutineKind::Async { span: async_keyword, .. }) = sig.header.coroutine_kind
@@ -302,7 +300,7 @@ impl<'a> AstValidator<'a> {
302300

303301
self.dcx().emit_err(errors::AsyncFnInConstTraitOrTraitImpl {
304302
async_keyword,
305-
in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }),
303+
in_impl: matches!(parent, TraitOrImpl::TraitImpl { .. }),
306304
const_keyword,
307305
});
308306
}
@@ -1011,14 +1009,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10111009
match &item.kind {
10121010
ItemKind::Impl(Impl {
10131011
generics,
1012+
constness,
10141013
of_trait:
1015-
Some(box TraitImplHeader {
1016-
safety,
1017-
polarity,
1018-
defaultness: _,
1019-
constness,
1020-
trait_ref: t,
1021-
}),
1014+
Some(box TraitImplHeader { safety, polarity, defaultness: _, trait_ref: t }),
10221015
self_ty,
10231016
items,
10241017
}) => {
@@ -1046,24 +1039,46 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10461039
self.visit_trait_ref(t);
10471040
self.visit_ty(self_ty);
10481041

1049-
self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| {
1050-
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: true });
1051-
});
1042+
self.with_in_trait_or_impl(
1043+
Some(TraitOrImpl::TraitImpl {
1044+
constness: *constness,
1045+
polarity: *polarity,
1046+
trait_ref_span: t.path.span,
1047+
}),
1048+
|this| {
1049+
walk_list!(
1050+
this,
1051+
visit_assoc_item,
1052+
items,
1053+
AssocCtxt::Impl { of_trait: true }
1054+
);
1055+
},
1056+
);
10521057
}
1053-
ItemKind::Impl(Impl { generics, of_trait: None, self_ty, items }) => {
1058+
ItemKind::Impl(Impl { generics, of_trait: None, self_ty, items, constness }) => {
10541059
self.visit_attrs_vis(&item.attrs, &item.vis);
10551060
self.visibility_not_permitted(
10561061
&item.vis,
10571062
errors::VisibilityNotPermittedNote::IndividualImplItems,
10581063
);
10591064

1060-
self.with_tilde_const(Some(TildeConstReason::Impl { span: item.span }), |this| {
1061-
this.visit_generics(generics)
1062-
});
1065+
let disallowed = matches!(constness, ast::Const::No)
1066+
.then(|| TildeConstReason::Impl { span: item.span });
1067+
1068+
self.with_tilde_const(disallowed, |this| this.visit_generics(generics));
1069+
10631070
self.visit_ty(self_ty);
1064-
self.with_in_trait_impl(None, |this| {
1065-
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: false });
1066-
});
1071+
self.with_in_trait_or_impl(
1072+
Some(TraitOrImpl::Impl { constness: *constness }),
1073+
|this| {
1074+
walk_list!(
1075+
this,
1076+
visit_assoc_item,
1077+
items,
1078+
AssocCtxt::Impl { of_trait: false }
1079+
);
1080+
},
1081+
);
10671082
}
10681083
ItemKind::Fn(
10691084
func @ box Fn {
@@ -1188,9 +1203,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11881203
this.visit_generics(generics);
11891204
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
11901205
});
1191-
self.with_in_trait(item.span, constness, |this| {
1192-
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
1193-
});
1206+
self.with_in_trait_or_impl(
1207+
Some(TraitOrImpl::Trait { span: item.span, constness }),
1208+
|this| {
1209+
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
1210+
},
1211+
);
11941212
}
11951213
ItemKind::TraitAlias(box TraitAlias { constness, generics, bounds, .. }) => {
11961214
let disallowed = matches!(constness, ast::Const::No)
@@ -1558,7 +1576,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15581576
&& self
15591577
.outer_trait_or_trait_impl
15601578
.as_ref()
1561-
.and_then(TraitOrTraitImpl::constness)
1579+
.and_then(TraitOrImpl::constness)
15621580
.is_some();
15631581

15641582
let disallowed = (!tilde_const_allowed).then(|| match fk {
@@ -1625,20 +1643,31 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
16251643
);
16261644
}
16271645

1628-
if let Some(parent) = &self.outer_trait_or_trait_impl {
1629-
self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
1630-
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
1631-
self.check_trait_fn_not_const(sig.header.constness, parent);
1632-
self.check_async_fn_in_const_trait_or_impl(sig, parent);
1646+
match &self.outer_trait_or_trait_impl {
1647+
Some(parent @ (TraitOrImpl::Trait { .. } | TraitOrImpl::TraitImpl { .. })) => {
1648+
self.visibility_not_permitted(
1649+
&item.vis,
1650+
errors::VisibilityNotPermittedNote::TraitImpl,
1651+
);
1652+
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
1653+
self.check_trait_fn_not_const(sig.header.constness, parent);
1654+
self.check_async_fn_in_const_trait_or_impl(sig, parent);
1655+
}
1656+
}
1657+
Some(TraitOrImpl::Impl { constness }) => {
1658+
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
1659+
self.check_impl_fn_not_const(sig.header.constness, *constness);
1660+
}
16331661
}
1662+
None => {}
16341663
}
16351664

16361665
if let AssocItemKind::Const(ci) = &item.kind {
16371666
self.check_item_named(ci.ident, "const");
16381667
}
16391668

16401669
let parent_is_const =
1641-
self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some();
1670+
self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrImpl::constness).is_some();
16421671

16431672
match &item.kind {
16441673
AssocItemKind::Fn(func)
@@ -1652,19 +1681,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
16521681
}
16531682
AssocItemKind::Type(_) => {
16541683
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
1655-
Some(TraitOrTraitImpl::Trait { .. }) => {
1684+
Some(TraitOrImpl::Trait { .. }) => {
16561685
TildeConstReason::TraitAssocTy { span: item.span }
16571686
}
1658-
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
1687+
Some(TraitOrImpl::TraitImpl { .. }) => {
16591688
TildeConstReason::TraitImplAssocTy { span: item.span }
16601689
}
1661-
None => TildeConstReason::InherentAssocTy { span: item.span },
1690+
Some(TraitOrImpl::Impl { .. }) | None => {
1691+
TildeConstReason::InherentAssocTy { span: item.span }
1692+
}
16621693
});
16631694
self.with_tilde_const(disallowed, |this| {
1664-
this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
1695+
this.with_in_trait_or_impl(None, |this| {
1696+
visit::walk_assoc_item(this, item, ctxt)
1697+
})
16651698
})
16661699
}
1667-
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
1700+
_ => self.with_in_trait_or_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
16681701
}
16691702
}
16701703

0 commit comments

Comments
 (0)