Resolve generic const items
This commit is contained in:
parent
9213aec762
commit
da17134be0
2 changed files with 109 additions and 69 deletions
|
@ -337,6 +337,7 @@ enum LifetimeBinderKind {
|
||||||
PolyTrait,
|
PolyTrait,
|
||||||
WhereBound,
|
WhereBound,
|
||||||
Item,
|
Item,
|
||||||
|
ConstItem,
|
||||||
Function,
|
Function,
|
||||||
Closure,
|
Closure,
|
||||||
ImplBlock,
|
ImplBlock,
|
||||||
|
@ -349,7 +350,7 @@ impl LifetimeBinderKind {
|
||||||
BareFnType => "type",
|
BareFnType => "type",
|
||||||
PolyTrait => "bound",
|
PolyTrait => "bound",
|
||||||
WhereBound => "bound",
|
WhereBound => "bound",
|
||||||
Item => "item",
|
Item | ConstItem => "item",
|
||||||
ImplBlock => "impl block",
|
ImplBlock => "impl block",
|
||||||
Function => "function",
|
Function => "function",
|
||||||
Closure => "closure",
|
Closure => "closure",
|
||||||
|
@ -2404,30 +2405,44 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. })
|
ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
|
||||||
| ItemKind::Const(box ast::ConstItem { ref ty, ref expr, .. }) => {
|
|
||||||
self.with_static_rib(|this| {
|
self.with_static_rib(|this| {
|
||||||
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
|
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
|
||||||
this.visit_ty(ty);
|
this.visit_ty(ty);
|
||||||
});
|
});
|
||||||
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
if let Some(expr) = expr {
|
||||||
|
// We already forbid generic params because of the above item rib,
|
||||||
|
// so it doesn't matter whether this is a trivial constant.
|
||||||
|
this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
|
||||||
|
self.with_generic_param_rib(
|
||||||
|
&generics.params,
|
||||||
|
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||||
|
LifetimeRibKind::Generics {
|
||||||
|
binder: item.id,
|
||||||
|
kind: LifetimeBinderKind::ConstItem,
|
||||||
|
span: generics.span,
|
||||||
|
},
|
||||||
|
|this| {
|
||||||
|
this.visit_generics(generics);
|
||||||
|
|
||||||
|
this.with_lifetime_rib(
|
||||||
|
LifetimeRibKind::Elided(LifetimeRes::Static),
|
||||||
|
|this| this.visit_ty(ty),
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(expr) = expr {
|
if let Some(expr) = expr {
|
||||||
let constant_item_kind = match item.kind {
|
this.resolve_const_body(
|
||||||
ItemKind::Const(..) => ConstantItemKind::Const,
|
expr,
|
||||||
ItemKind::Static(..) => ConstantItemKind::Static,
|
Some((item.ident, ConstantItemKind::Const)),
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
// We already forbid generic params because of the above item rib,
|
|
||||||
// so it doesn't matter whether this is a trivial constant.
|
|
||||||
this.with_constant_rib(
|
|
||||||
IsRepeatExpr::No,
|
|
||||||
ConstantHasGenerics::Yes,
|
|
||||||
Some((item.ident, constant_item_kind)),
|
|
||||||
|this| this.visit_expr(expr),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Use(ref use_tree) => {
|
ItemKind::Use(ref use_tree) => {
|
||||||
|
@ -2700,28 +2715,31 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
for item in trait_items {
|
for item in trait_items {
|
||||||
self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
|
self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
AssocItemKind::Const(box ast::ConstItem { ty, expr, .. }) => {
|
AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
|
||||||
self.visit_ty(ty);
|
self.with_generic_param_rib(
|
||||||
// Only impose the restrictions of `ConstRibKind` for an
|
&generics.params,
|
||||||
// actual constant expression in a provided default.
|
RibKind::AssocItem,
|
||||||
if let Some(expr) = expr {
|
LifetimeRibKind::Generics {
|
||||||
// We allow arbitrary const expressions inside of associated consts,
|
binder: item.id,
|
||||||
// even if they are potentially not const evaluatable.
|
span: generics.span,
|
||||||
//
|
kind: LifetimeBinderKind::ConstItem,
|
||||||
// Type parameters can already be used and as associated consts are
|
},
|
||||||
// not used as part of the type system, this is far less surprising.
|
|this| {
|
||||||
self.with_lifetime_rib(
|
this.visit_generics(generics);
|
||||||
LifetimeRibKind::Elided(LifetimeRes::Infer),
|
this.visit_ty(ty);
|
||||||
|this| {
|
|
||||||
this.with_constant_rib(
|
// Only impose the restrictions of `ConstRibKind` for an
|
||||||
IsRepeatExpr::No,
|
// actual constant expression in a provided default.
|
||||||
ConstantHasGenerics::Yes,
|
if let Some(expr) = expr {
|
||||||
None,
|
// We allow arbitrary const expressions inside of associated consts,
|
||||||
|this| this.visit_expr(expr),
|
// even if they are potentially not const evaluatable.
|
||||||
)
|
//
|
||||||
},
|
// Type parameters can already be used and as associated consts are
|
||||||
);
|
// not used as part of the type system, this is far less surprising.
|
||||||
}
|
this.resolve_const_body(expr, None);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { generics, .. }) => {
|
AssocItemKind::Fn(box Fn { generics, .. }) => {
|
||||||
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
|
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
|
||||||
|
@ -2876,36 +2894,42 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
use crate::ResolutionError::*;
|
use crate::ResolutionError::*;
|
||||||
self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
|
self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
AssocItemKind::Const(box ast::ConstItem { ty, expr, .. }) => {
|
AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
|
||||||
debug!("resolve_implementation AssocItemKind::Const");
|
debug!("resolve_implementation AssocItemKind::Const");
|
||||||
// If this is a trait impl, ensure the const
|
|
||||||
// exists in trait
|
|
||||||
self.check_trait_item(
|
|
||||||
item.id,
|
|
||||||
item.ident,
|
|
||||||
&item.kind,
|
|
||||||
ValueNS,
|
|
||||||
item.span,
|
|
||||||
seen_trait_items,
|
|
||||||
|i, s, c| ConstNotMemberOfTrait(i, s, c),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.visit_ty(ty);
|
self.with_generic_param_rib(
|
||||||
if let Some(expr) = expr {
|
&generics.params,
|
||||||
// We allow arbitrary const expressions inside of associated consts,
|
RibKind::AssocItem,
|
||||||
// even if they are potentially not const evaluatable.
|
LifetimeRibKind::Generics {
|
||||||
//
|
binder: item.id,
|
||||||
// Type parameters can already be used and as associated consts are
|
span: generics.span,
|
||||||
// not used as part of the type system, this is far less surprising.
|
kind: LifetimeBinderKind::ConstItem,
|
||||||
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
},
|
||||||
this.with_constant_rib(
|
|this| {
|
||||||
IsRepeatExpr::No,
|
// If this is a trait impl, ensure the const
|
||||||
ConstantHasGenerics::Yes,
|
// exists in trait
|
||||||
None,
|
this.check_trait_item(
|
||||||
|this| this.visit_expr(expr),
|
item.id,
|
||||||
)
|
item.ident,
|
||||||
});
|
&item.kind,
|
||||||
}
|
ValueNS,
|
||||||
|
item.span,
|
||||||
|
seen_trait_items,
|
||||||
|
|i, s, c| ConstNotMemberOfTrait(i, s, c),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.visit_generics(generics);
|
||||||
|
this.visit_ty(ty);
|
||||||
|
if let Some(expr) = expr {
|
||||||
|
// We allow arbitrary const expressions inside of associated consts,
|
||||||
|
// even if they are potentially not const evaluatable.
|
||||||
|
//
|
||||||
|
// Type parameters can already be used and as associated consts are
|
||||||
|
// not used as part of the type system, this is far less surprising.
|
||||||
|
this.resolve_const_body(expr, None);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { generics, .. }) => {
|
AssocItemKind::Fn(box Fn { generics, .. }) => {
|
||||||
debug!("resolve_implementation AssocItemKind::Fn");
|
debug!("resolve_implementation AssocItemKind::Fn");
|
||||||
|
@ -3063,6 +3087,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_const_body(&mut self, expr: &'ast Expr, item: Option<(Ident, ConstantItemKind)>) {
|
||||||
|
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
||||||
|
this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| {
|
||||||
|
this.visit_expr(expr)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_params(&mut self, params: &'ast [Param]) {
|
fn resolve_params(&mut self, params: &'ast [Param]) {
|
||||||
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
|
||||||
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
|
||||||
|
@ -4448,6 +4480,7 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
|
||||||
fn visit_item(&mut self, item: &'ast Item) {
|
fn visit_item(&mut self, item: &'ast Item) {
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
ItemKind::TyAlias(box TyAlias { ref generics, .. })
|
ItemKind::TyAlias(box TyAlias { ref generics, .. })
|
||||||
|
| ItemKind::Const(box ConstItem { ref generics, .. })
|
||||||
| ItemKind::Fn(box Fn { ref generics, .. })
|
| ItemKind::Fn(box Fn { ref generics, .. })
|
||||||
| ItemKind::Enum(_, ref generics)
|
| ItemKind::Enum(_, ref generics)
|
||||||
| ItemKind::Struct(_, ref generics)
|
| ItemKind::Struct(_, ref generics)
|
||||||
|
@ -4467,7 +4500,6 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
|
||||||
ItemKind::Mod(..)
|
ItemKind::Mod(..)
|
||||||
| ItemKind::ForeignMod(..)
|
| ItemKind::ForeignMod(..)
|
||||||
| ItemKind::Static(..)
|
| ItemKind::Static(..)
|
||||||
| ItemKind::Const(..)
|
|
||||||
| ItemKind::Use(..)
|
| ItemKind::Use(..)
|
||||||
| ItemKind::ExternCrate(..)
|
| ItemKind::ExternCrate(..)
|
||||||
| ItemKind::MacroDef(..)
|
| ItemKind::MacroDef(..)
|
||||||
|
|
|
@ -2348,6 +2348,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||||
let mut should_continue = true;
|
let mut should_continue = true;
|
||||||
match rib.kind {
|
match rib.kind {
|
||||||
LifetimeRibKind::Generics { binder: _, span, kind } => {
|
LifetimeRibKind::Generics { binder: _, span, kind } => {
|
||||||
|
// Avoid suggesting placing lifetime parameters on constant items unless the relevant
|
||||||
|
// feature is enabled. Suggest the parent item as a possible location if applicable.
|
||||||
|
if let LifetimeBinderKind::ConstItem = kind
|
||||||
|
&& !self.r.tcx().features().generic_const_items
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if !span.can_be_used_for_suggestions() && suggest_note && let Some(name) = name {
|
if !span.can_be_used_for_suggestions() && suggest_note && let Some(name) = name {
|
||||||
suggest_note = false; // Avoid displaying the same help multiple times.
|
suggest_note = false; // Avoid displaying the same help multiple times.
|
||||||
err.span_label(
|
err.span_label(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue