Skip to content

Commit da17134

Browse files
committed
Resolve generic const items
1 parent 9213aec commit da17134

File tree

2 files changed

+109
-69
lines changed

2 files changed

+109
-69
lines changed

compiler/rustc_resolve/src/late.rs

Lines changed: 101 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ enum LifetimeBinderKind {
337337
PolyTrait,
338338
WhereBound,
339339
Item,
340+
ConstItem,
340341
Function,
341342
Closure,
342343
ImplBlock,
@@ -349,7 +350,7 @@ impl LifetimeBinderKind {
349350
BareFnType => "type",
350351
PolyTrait => "bound",
351352
WhereBound => "bound",
352-
Item => "item",
353+
Item | ConstItem => "item",
353354
ImplBlock => "impl block",
354355
Function => "function",
355356
Closure => "closure",
@@ -2404,30 +2405,44 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
24042405
});
24052406
}
24062407

2407-
ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. })
2408-
| ItemKind::Const(box ast::ConstItem { ref ty, ref expr, .. }) => {
2408+
ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
24092409
self.with_static_rib(|this| {
24102410
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
24112411
this.visit_ty(ty);
24122412
});
2413-
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
2413+
if let Some(expr) = expr {
2414+
// We already forbid generic params because of the above item rib,
2415+
// so it doesn't matter whether this is a trivial constant.
2416+
this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
2417+
}
2418+
});
2419+
}
2420+
2421+
ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
2422+
self.with_generic_param_rib(
2423+
&generics.params,
2424+
RibKind::Item(HasGenericParams::Yes(generics.span)),
2425+
LifetimeRibKind::Generics {
2426+
binder: item.id,
2427+
kind: LifetimeBinderKind::ConstItem,
2428+
span: generics.span,
2429+
},
2430+
|this| {
2431+
this.visit_generics(generics);
2432+
2433+
this.with_lifetime_rib(
2434+
LifetimeRibKind::Elided(LifetimeRes::Static),
2435+
|this| this.visit_ty(ty),
2436+
);
2437+
24142438
if let Some(expr) = expr {
2415-
let constant_item_kind = match item.kind {
2416-
ItemKind::Const(..) => ConstantItemKind::Const,
2417-
ItemKind::Static(..) => ConstantItemKind::Static,
2418-
_ => unreachable!(),
2419-
};
2420-
// We already forbid generic params because of the above item rib,
2421-
// so it doesn't matter whether this is a trivial constant.
2422-
this.with_constant_rib(
2423-
IsRepeatExpr::No,
2424-
ConstantHasGenerics::Yes,
2425-
Some((item.ident, constant_item_kind)),
2426-
|this| this.visit_expr(expr),
2439+
this.resolve_const_body(
2440+
expr,
2441+
Some((item.ident, ConstantItemKind::Const)),
24272442
);
24282443
}
2429-
});
2430-
});
2444+
},
2445+
);
24312446
}
24322447

24332448
ItemKind::Use(ref use_tree) => {
@@ -2700,28 +2715,31 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
27002715
for item in trait_items {
27012716
self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
27022717
match &item.kind {
2703-
AssocItemKind::Const(box ast::ConstItem { ty, expr, .. }) => {
2704-
self.visit_ty(ty);
2705-
// Only impose the restrictions of `ConstRibKind` for an
2706-
// actual constant expression in a provided default.
2707-
if let Some(expr) = expr {
2708-
// We allow arbitrary const expressions inside of associated consts,
2709-
// even if they are potentially not const evaluatable.
2710-
//
2711-
// Type parameters can already be used and as associated consts are
2712-
// not used as part of the type system, this is far less surprising.
2713-
self.with_lifetime_rib(
2714-
LifetimeRibKind::Elided(LifetimeRes::Infer),
2715-
|this| {
2716-
this.with_constant_rib(
2717-
IsRepeatExpr::No,
2718-
ConstantHasGenerics::Yes,
2719-
None,
2720-
|this| this.visit_expr(expr),
2721-
)
2722-
},
2723-
);
2724-
}
2718+
AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
2719+
self.with_generic_param_rib(
2720+
&generics.params,
2721+
RibKind::AssocItem,
2722+
LifetimeRibKind::Generics {
2723+
binder: item.id,
2724+
span: generics.span,
2725+
kind: LifetimeBinderKind::ConstItem,
2726+
},
2727+
|this| {
2728+
this.visit_generics(generics);
2729+
this.visit_ty(ty);
2730+
2731+
// Only impose the restrictions of `ConstRibKind` for an
2732+
// actual constant expression in a provided default.
2733+
if let Some(expr) = expr {
2734+
// We allow arbitrary const expressions inside of associated consts,
2735+
// even if they are potentially not const evaluatable.
2736+
//
2737+
// Type parameters can already be used and as associated consts are
2738+
// not used as part of the type system, this is far less surprising.
2739+
this.resolve_const_body(expr, None);
2740+
}
2741+
},
2742+
);
27252743
}
27262744
AssocItemKind::Fn(box Fn { generics, .. }) => {
27272745
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
@@ -2876,36 +2894,42 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
28762894
use crate::ResolutionError::*;
28772895
self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
28782896
match &item.kind {
2879-
AssocItemKind::Const(box ast::ConstItem { ty, expr, .. }) => {
2897+
AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
28802898
debug!("resolve_implementation AssocItemKind::Const");
2881-
// If this is a trait impl, ensure the const
2882-
// exists in trait
2883-
self.check_trait_item(
2884-
item.id,
2885-
item.ident,
2886-
&item.kind,
2887-
ValueNS,
2888-
item.span,
2889-
seen_trait_items,
2890-
|i, s, c| ConstNotMemberOfTrait(i, s, c),
2891-
);
28922899

2893-
self.visit_ty(ty);
2894-
if let Some(expr) = expr {
2895-
// We allow arbitrary const expressions inside of associated consts,
2896-
// even if they are potentially not const evaluatable.
2897-
//
2898-
// Type parameters can already be used and as associated consts are
2899-
// not used as part of the type system, this is far less surprising.
2900-
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
2901-
this.with_constant_rib(
2902-
IsRepeatExpr::No,
2903-
ConstantHasGenerics::Yes,
2904-
None,
2905-
|this| this.visit_expr(expr),
2906-
)
2907-
});
2908-
}
2900+
self.with_generic_param_rib(
2901+
&generics.params,
2902+
RibKind::AssocItem,
2903+
LifetimeRibKind::Generics {
2904+
binder: item.id,
2905+
span: generics.span,
2906+
kind: LifetimeBinderKind::ConstItem,
2907+
},
2908+
|this| {
2909+
// If this is a trait impl, ensure the const
2910+
// exists in trait
2911+
this.check_trait_item(
2912+
item.id,
2913+
item.ident,
2914+
&item.kind,
2915+
ValueNS,
2916+
item.span,
2917+
seen_trait_items,
2918+
|i, s, c| ConstNotMemberOfTrait(i, s, c),
2919+
);
2920+
2921+
this.visit_generics(generics);
2922+
this.visit_ty(ty);
2923+
if let Some(expr) = expr {
2924+
// We allow arbitrary const expressions inside of associated consts,
2925+
// even if they are potentially not const evaluatable.
2926+
//
2927+
// Type parameters can already be used and as associated consts are
2928+
// not used as part of the type system, this is far less surprising.
2929+
this.resolve_const_body(expr, None);
2930+
}
2931+
},
2932+
);
29092933
}
29102934
AssocItemKind::Fn(box Fn { generics, .. }) => {
29112935
debug!("resolve_implementation AssocItemKind::Fn");
@@ -3063,6 +3087,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
30633087
);
30643088
}
30653089

3090+
fn resolve_const_body(&mut self, expr: &'ast Expr, item: Option<(Ident, ConstantItemKind)>) {
3091+
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
3092+
this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| {
3093+
this.visit_expr(expr)
3094+
});
3095+
})
3096+
}
3097+
30663098
fn resolve_params(&mut self, params: &'ast [Param]) {
30673099
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
30683100
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
@@ -4448,6 +4480,7 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
44484480
fn visit_item(&mut self, item: &'ast Item) {
44494481
match &item.kind {
44504482
ItemKind::TyAlias(box TyAlias { ref generics, .. })
4483+
| ItemKind::Const(box ConstItem { ref generics, .. })
44514484
| ItemKind::Fn(box Fn { ref generics, .. })
44524485
| ItemKind::Enum(_, ref generics)
44534486
| ItemKind::Struct(_, ref generics)
@@ -4467,7 +4500,6 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
44674500
ItemKind::Mod(..)
44684501
| ItemKind::ForeignMod(..)
44694502
| ItemKind::Static(..)
4470-
| ItemKind::Const(..)
44714503
| ItemKind::Use(..)
44724504
| ItemKind::ExternCrate(..)
44734505
| ItemKind::MacroDef(..)

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,6 +2348,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
23482348
let mut should_continue = true;
23492349
match rib.kind {
23502350
LifetimeRibKind::Generics { binder: _, span, kind } => {
2351+
// Avoid suggesting placing lifetime parameters on constant items unless the relevant
2352+
// feature is enabled. Suggest the parent item as a possible location if applicable.
2353+
if let LifetimeBinderKind::ConstItem = kind
2354+
&& !self.r.tcx().features().generic_const_items
2355+
{
2356+
continue;
2357+
}
2358+
23512359
if !span.can_be_used_for_suggestions() && suggest_note && let Some(name) = name {
23522360
suggest_note = false; // Avoid displaying the same help multiple times.
23532361
err.span_label(

0 commit comments

Comments
 (0)