1
Fork 0

Lower generic const items to HIR

This commit is contained in:
León Orell Valerian Liehr 2023-05-04 16:40:57 +02:00
parent afd009a8d8
commit 9213aec762
No known key found for this signature in database
GPG key ID: D17A07215F68E713
16 changed files with 84 additions and 41 deletions

View file

@ -231,9 +231,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
hir::ItemKind::Static(ty, *m, body_id) hir::ItemKind::Static(ty, *m, body_id)
} }
ItemKind::Const(box ast::ConstItem { ty, expr, .. }) => { ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
let (ty, body_id) = self.lower_const_item(ty, span, expr.as_deref()); let (generics, (ty, body_id)) = self.lower_generics(
hir::ItemKind::Const(ty, body_id) generics,
Const::No,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_const_item(ty, span, expr.as_deref()),
);
hir::ItemKind::Const(ty, generics, body_id)
} }
ItemKind::Fn(box Fn { ItemKind::Fn(box Fn {
sig: FnSig { decl, header, span: fn_sig_span }, sig: FnSig { decl, header, span: fn_sig_span },
@ -715,11 +721,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
let trait_item_def_id = hir_id.expect_owner(); let trait_item_def_id = hir_id.expect_owner();
let (generics, kind, has_default) = match &i.kind { let (generics, kind, has_default) = match &i.kind {
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => { AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
let ty = let (generics, kind) = self.lower_generics(
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); &generics,
let body = expr.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); Const::No,
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) i.id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
let ty = this.lower_ty(
ty,
&ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
);
let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x)));
hir::TraitItemKind::Const(ty, body)
},
);
(generics, kind, expr.is_some())
} }
AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => { AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
let asyncness = sig.header.asyncness; let asyncness = sig.header.asyncness;
@ -817,14 +835,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_attrs(hir_id, &i.attrs); self.lower_attrs(hir_id, &i.attrs);
let (generics, kind) = match &i.kind { let (generics, kind) = match &i.kind {
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => { AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
let ty = &generics,
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); Const::No,
( i.id,
hir::Generics::empty(), &ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), |this| {
) let ty = this
} .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = this.lower_const_body(i.span, expr.as_deref());
hir::ImplItemKind::Const(ty, body)
},
),
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => { AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
self.current_item = Some(i.span); self.current_item = Some(i.span);
let asyncness = sig.header.asyncness; let asyncness = sig.header.asyncness;

View file

@ -3130,9 +3130,9 @@ impl<'hir> Item<'hir> {
} }
/// Expect an [`ItemKind::Const`] or panic. /// Expect an [`ItemKind::Const`] or panic.
#[track_caller] #[track_caller]
pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) { pub fn expect_const(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId) {
let ItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") }; let ItemKind::Const(ty, gen, body) = self.kind else { self.expect_failed("a constant") };
(ty, body) (ty, gen, body)
} }
/// Expect an [`ItemKind::Fn`] or panic. /// Expect an [`ItemKind::Fn`] or panic.
#[track_caller] #[track_caller]
@ -3319,7 +3319,7 @@ pub enum ItemKind<'hir> {
/// A `static` item. /// A `static` item.
Static(&'hir Ty<'hir>, Mutability, BodyId), Static(&'hir Ty<'hir>, Mutability, BodyId),
/// A `const` item. /// A `const` item.
Const(&'hir Ty<'hir>, BodyId), Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
/// A function declaration. /// A function declaration.
Fn(FnSig<'hir>, &'hir Generics<'hir>, BodyId), Fn(FnSig<'hir>, &'hir Generics<'hir>, BodyId),
/// A MBE macro definition (`macro_rules!` or `macro`). /// A MBE macro definition (`macro_rules!` or `macro`).
@ -3372,6 +3372,7 @@ impl ItemKind<'_> {
Some(match *self { Some(match *self {
ItemKind::Fn(_, ref generics, _) ItemKind::Fn(_, ref generics, _)
| ItemKind::TyAlias(_, ref generics) | ItemKind::TyAlias(_, ref generics)
| ItemKind::Const(_, ref generics, _)
| ItemKind::OpaqueTy(OpaqueTy { ref generics, .. }) | ItemKind::OpaqueTy(OpaqueTy { ref generics, .. })
| ItemKind::Enum(_, ref generics) | ItemKind::Enum(_, ref generics)
| ItemKind::Struct(_, ref generics) | ItemKind::Struct(_, ref generics)
@ -3567,7 +3568,9 @@ impl<'hir> OwnerNode<'hir> {
match self { match self {
OwnerNode::Item(Item { OwnerNode::Item(Item {
kind: kind:
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body), ItemKind::Static(_, _, body)
| ItemKind::Const(_, _, body)
| ItemKind::Fn(_, _, body),
.. ..
}) })
| OwnerNode::TraitItem(TraitItem { | OwnerNode::TraitItem(TraitItem {
@ -3770,9 +3773,9 @@ impl<'hir> Node<'hir> {
pub fn ty(self) -> Option<&'hir Ty<'hir>> { pub fn ty(self) -> Option<&'hir Ty<'hir>> {
match self { match self {
Node::Item(it) => match it.kind { Node::Item(it) => match it.kind {
ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => { ItemKind::TyAlias(ty, _)
Some(ty) | ItemKind::Static(ty, _, _)
} | ItemKind::Const(ty, _, _) => Some(ty),
_ => None, _ => None,
}, },
Node::TraitItem(it) => match it.kind { Node::TraitItem(it) => match it.kind {
@ -3800,7 +3803,9 @@ impl<'hir> Node<'hir> {
match self { match self {
Node::Item(Item { Node::Item(Item {
kind: kind:
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body), ItemKind::Static(_, _, body)
| ItemKind::Const(_, _, body)
| ItemKind::Fn(_, _, body),
.. ..
}) })
| Node::TraitItem(TraitItem { | Node::TraitItem(TraitItem {

View file

@ -467,11 +467,17 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
ItemKind::Use(ref path, _) => { ItemKind::Use(ref path, _) => {
visitor.visit_use(path, item.hir_id()); visitor.visit_use(path, item.hir_id());
} }
ItemKind::Static(ref typ, _, body) | ItemKind::Const(ref typ, body) => { ItemKind::Static(ref typ, _, body) => {
visitor.visit_id(item.hir_id()); visitor.visit_id(item.hir_id());
visitor.visit_ty(typ); visitor.visit_ty(typ);
visitor.visit_nested_body(body); visitor.visit_nested_body(body);
} }
ItemKind::Const(ref typ, ref generics, body) => {
visitor.visit_id(item.hir_id());
visitor.visit_ty(typ);
visitor.visit_generics(generics);
visitor.visit_nested_body(body);
}
ItemKind::Fn(ref sig, ref generics, body_id) => { ItemKind::Fn(ref sig, ref generics, body_id) => {
visitor.visit_id(item.hir_id()); visitor.visit_id(item.hir_id());
visitor.visit_fn( visitor.visit_fn(

View file

@ -404,7 +404,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
icx.to_ty(ty) icx.to_ty(ty)
} }
} }
ItemKind::Const(ty, body_id) => { ItemKind::Const(ty, _, body_id) => {
if is_suggestable_infer_ty(ty) { if is_suggestable_infer_ty(ty) {
infer_placeholder_type( infer_placeholder_type(
tcx, def_id, body_id, ty.span, item.ident, "constant", tcx, def_id, body_id, ty.span, item.ident, "constant",

View file

@ -130,7 +130,7 @@ fn diagnostic_hir_wf_check<'tcx>(
hir::Node::Item(item) => match item.kind { hir::Node::Item(item) => match item.kind {
hir::ItemKind::TyAlias(ty, _) hir::ItemKind::TyAlias(ty, _)
| hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Static(ty, _, _)
| hir::ItemKind::Const(ty, _) => vec![ty], | hir::ItemKind::Const(ty, _, _) => vec![ty],
hir::ItemKind::Impl(impl_) => match &impl_.of_trait { hir::ItemKind::Impl(impl_) => match &impl_.of_trait {
Some(t) => t Some(t) => t
.path .path

View file

@ -420,12 +420,13 @@ impl<'a> State<'a> {
fn print_associated_const( fn print_associated_const(
&mut self, &mut self,
ident: Ident, ident: Ident,
generics: &hir::Generics<'_>,
ty: &hir::Ty<'_>, ty: &hir::Ty<'_>,
default: Option<hir::BodyId>, default: Option<hir::BodyId>,
) { ) {
self.head("");
self.word_space("const"); self.word_space("const");
self.print_ident(ident); self.print_ident(ident);
self.print_generic_params(generics.params);
self.word_space(":"); self.word_space(":");
self.print_type(ty); self.print_type(ty);
if let Some(expr) = default { if let Some(expr) = default {
@ -433,6 +434,7 @@ impl<'a> State<'a> {
self.word_space("="); self.word_space("=");
self.ann.nested(self, Nested::Body(expr)); self.ann.nested(self, Nested::Body(expr));
} }
self.print_where_clause(generics);
self.word(";") self.word(";")
} }
@ -532,9 +534,10 @@ impl<'a> State<'a> {
self.word(";"); self.word(";");
self.end(); // end the outer cbox self.end(); // end the outer cbox
} }
hir::ItemKind::Const(ty, expr) => { hir::ItemKind::Const(ty, generics, expr) => {
self.head("const"); self.head("const");
self.print_ident(item.ident); self.print_ident(item.ident);
self.print_generic_params(generics.params);
self.word_space(":"); self.word_space(":");
self.print_type(ty); self.print_type(ty);
self.space(); self.space();
@ -542,6 +545,7 @@ impl<'a> State<'a> {
self.word_space("="); self.word_space("=");
self.ann.nested(self, Nested::Body(expr)); self.ann.nested(self, Nested::Body(expr));
self.print_where_clause(generics);
self.word(";"); self.word(";");
self.end(); // end the outer cbox self.end(); // end the outer cbox
} }
@ -836,7 +840,7 @@ impl<'a> State<'a> {
self.print_outer_attributes(self.attrs(ti.hir_id())); self.print_outer_attributes(self.attrs(ti.hir_id()));
match ti.kind { match ti.kind {
hir::TraitItemKind::Const(ty, default) => { hir::TraitItemKind::Const(ty, default) => {
self.print_associated_const(ti.ident, ty, default); self.print_associated_const(ti.ident, ti.generics, ty, default);
} }
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_names)) => { hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_names)) => {
self.print_method_sig(ti.ident, sig, ti.generics, arg_names, None); self.print_method_sig(ti.ident, sig, ti.generics, arg_names, None);
@ -865,7 +869,7 @@ impl<'a> State<'a> {
match ii.kind { match ii.kind {
hir::ImplItemKind::Const(ty, expr) => { hir::ImplItemKind::Const(ty, expr) => {
self.print_associated_const(ii.ident, ty, Some(expr)); self.print_associated_const(ii.ident, ii.generics, ty, Some(expr));
} }
hir::ImplItemKind::Fn(ref sig, body) => { hir::ImplItemKind::Fn(ref sig, body) => {
self.head(""); self.head("");

View file

@ -1394,7 +1394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let Some(( let Some((
_, _,
hir::Node::Local(hir::Local { ty: Some(ty), .. }) hir::Node::Local(hir::Local { ty: Some(ty), .. })
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. }), | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. }),
)) = parent_node )) = parent_node
else { else {
return; return;

View file

@ -101,7 +101,7 @@ fn primary_body_of(
) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> { ) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
match node { match node {
Node::Item(item) => match item.kind { Node::Item(item) => match item.kind {
hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => { hir::ItemKind::Const(ty, _, body) | hir::ItemKind::Static(ty, _, body) => {
Some((body, Some(ty), None)) Some((body, Some(ty), None))
} }
hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))), hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),

View file

@ -924,7 +924,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match opt_def_id { match opt_def_id {
Some(def_id) => match self.tcx.hir().get_if_local(def_id) { Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
Some(hir::Node::Item(hir::Item { Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Const(_, body_id), .. kind: hir::ItemKind::Const(_, _, body_id),
..
})) => match self.tcx.hir().get(body_id.hir_id) { })) => match self.tcx.hir().get(body_id.hir_id) {
hir::Node::Expr(expr) => { hir::Node::Expr(expr) => {
if hir::is_range_literal(expr) { if hir::is_range_literal(expr) {

View file

@ -2068,7 +2068,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
visitor.visit_body(body); visitor.visit_body(body);
visitor.result.map(|r| &r.peel_refs().kind) visitor.result.map(|r| &r.peel_refs().kind)
} }
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. })) => { Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. })) => {
Some(&ty.peel_refs().kind) Some(&ty.peel_refs().kind)
} }
_ => None, _ => None,

View file

@ -1529,9 +1529,10 @@ declare_lint_pass!(
impl<'tcx> LateLintPass<'tcx> for UnusedBrokenConst { impl<'tcx> LateLintPass<'tcx> for UnusedBrokenConst {
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
match it.kind { match it.kind {
hir::ItemKind::Const(_, body_id) => { hir::ItemKind::Const(_, _, body_id) => {
let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id(); let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id();
// trigger the query once for all constants since that will already report the errors // trigger the query once for all constants since that will already report the errors
// FIXME(generic_const_items): Does this work properly with generic const items?
cx.tcx.ensure().const_eval_poly(def_id); cx.tcx.ensure().const_eval_poly(def_id);
} }
hir::ItemKind::Static(_, _, body_id) => { hir::ItemKind::Static(_, _, body_id) => {

View file

@ -24,7 +24,7 @@ pub fn associated_body(node: Node<'_>) -> Option<(LocalDefId, BodyId)> {
match node { match node {
Node::Item(Item { Node::Item(Item {
owner_id, owner_id,
kind: ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body), kind: ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
.. ..
}) })
| Node::TraitItem(TraitItem { | Node::TraitItem(TraitItem {

View file

@ -570,7 +570,7 @@ fn construct_const<'a, 'tcx>(
// Figure out what primary body this item has. // Figure out what primary body this item has.
let (span, const_ty_span) = match tcx.hir().get(hir_id) { let (span, const_ty_span) = match tcx.hir().get(hir_id) {
Node::Item(hir::Item { Node::Item(hir::Item {
kind: hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _), kind: hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _, _),
span, span,
.. ..
}) })

View file

@ -236,7 +236,7 @@ impl<'tcx> ReachableContext<'tcx> {
// Reachable constants will be inlined into other crates // Reachable constants will be inlined into other crates
// unconditionally, so we need to make sure that their // unconditionally, so we need to make sure that their
// contents are also reachable. // contents are also reachable.
hir::ItemKind::Const(_, init) | hir::ItemKind::Static(_, _, init) => { hir::ItemKind::Const(_, _, init) | hir::ItemKind::Static(_, _, init) => {
self.visit_nested_body(init); self.visit_nested_body(init);
} }

View file

@ -655,6 +655,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Impl(hir::Impl { generics, .. })
| hir::ItemKind::Fn(_, generics, _) | hir::ItemKind::Fn(_, generics, _)
| hir::ItemKind::TyAlias(_, generics) | hir::ItemKind::TyAlias(_, generics)
| hir::ItemKind::Const(_, generics, _)
| hir::ItemKind::TraitAlias(generics, _) | hir::ItemKind::TraitAlias(generics, _)
| hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), | hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
.. ..
@ -720,6 +721,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Impl(hir::Impl { generics, .. })
| hir::ItemKind::Fn(_, generics, _) | hir::ItemKind::Fn(_, generics, _)
| hir::ItemKind::TyAlias(_, generics) | hir::ItemKind::TyAlias(_, generics)
| hir::ItemKind::Const(_, generics, _)
| hir::ItemKind::TraitAlias(generics, _) | hir::ItemKind::TraitAlias(generics, _)
| hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), | hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
.. ..

View file

@ -2603,7 +2603,8 @@ fn clean_maybe_renamed_item<'tcx>(
ItemKind::Static(ty, mutability, body_id) => { ItemKind::Static(ty, mutability, body_id) => {
StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) }) StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) })
} }
ItemKind::Const(ty, body_id) => ConstantItem(Constant { // FIXME(fmease): rustdoc integration
ItemKind::Const(ty, _generics, body_id) => ConstantItem(Constant {
type_: clean_ty(ty, cx), type_: clean_ty(ty, cx),
kind: ConstantKind::Local { body: body_id, def_id }, kind: ConstantKind::Local { body: body_id, def_id },
}), }),