1
Fork 0

Remove CheckConstTraitVisitor

Signed-off-by: Miguel Guarniz <mi9uel9@gmail.com>
This commit is contained in:
Miguel Guarniz 2022-05-03 13:27:13 -04:00
parent a7d6408b05
commit bd2b210c59

View file

@ -10,6 +10,7 @@
use rustc_attr as attr; use rustc_attr as attr;
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
@ -58,88 +59,73 @@ impl NonConstExpr {
fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
let mut vis = CheckConstVisitor::new(tcx); let mut vis = CheckConstVisitor::new(tcx);
tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis.as_deep_visitor()); tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis.as_deep_visitor());
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckConstTraitVisitor::new(tcx)); for id in tcx.hir_module_items(module_def_id).items() {
check_item(tcx, id);
}
} }
pub(crate) fn provide(providers: &mut Providers) { pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_const_bodies, ..*providers }; *providers = Providers { check_mod_const_bodies, ..*providers };
} }
struct CheckConstTraitVisitor<'tcx> { fn check_item<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
tcx: TyCtxt<'tcx>, let _: Option<_> = try {
} if !matches!(tcx.hir().def_kind(id.def_id), DefKind::Impl) {
None?
}
impl<'tcx> CheckConstTraitVisitor<'tcx> { let item = tcx.hir().item(id);
fn new(tcx: TyCtxt<'tcx>) -> Self { if let hir::ItemKind::Impl(ref imp) = item.kind && let hir::Constness::Const = imp.constness {
CheckConstTraitVisitor { tcx } let trait_def_id = imp.of_trait.as_ref()?.trait_def_id()?;
} let ancestors = tcx
} .trait_def(trait_def_id)
.ancestors(tcx, item.def_id.to_def_id())
.ok()?;
let mut to_implement = Vec::new();
impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<'tcx> { for trait_item in tcx.associated_items(trait_def_id).in_definition_order()
/// check for const trait impls, and errors if the impl uses provided/default functions {
/// of the trait being implemented; as those provided functions can be non-const. if let ty::AssocItem {
fn visit_item<'hir>(&mut self, item: &'hir hir::Item<'hir>) { kind: ty::AssocKind::Fn,
let _: Option<_> = try { defaultness,
if let hir::ItemKind::Impl(ref imp) = item.kind && let hir::Constness::Const = imp.constness { def_id: trait_item_id,
let trait_def_id = imp.of_trait.as_ref()?.trait_def_id()?; ..
let ancestors = self } = *trait_item
.tcx {
.trait_def(trait_def_id) // we can ignore functions that do not have default bodies:
.ancestors(self.tcx, item.def_id.to_def_id()) // if those are unimplemented it will be caught by typeck.
.ok()?; if !defaultness.has_value()
let mut to_implement = Vec::new(); || tcx
.has_attr(trait_item_id, sym::default_method_body_is_const)
for trait_item in self.tcx.associated_items(trait_def_id).in_definition_order()
{ {
if let ty::AssocItem { continue;
kind: ty::AssocKind::Fn,
defaultness,
def_id: trait_item_id,
..
} = *trait_item
{
// we can ignore functions that do not have default bodies:
// if those are unimplemented it will be caught by typeck.
if !defaultness.has_value()
|| self
.tcx
.has_attr(trait_item_id, sym::default_method_body_is_const)
{
continue;
}
let is_implemented = ancestors
.leaf_def(self.tcx, trait_item_id)
.map(|node_item| !node_item.defining_node.is_from_trait())
.unwrap_or(false);
if !is_implemented {
to_implement.push(self.tcx.item_name(trait_item_id).to_string());
}
}
} }
// all nonconst trait functions (not marked with #[default_method_body_is_const]) let is_implemented = ancestors
// must be implemented .leaf_def(tcx, trait_item_id)
if !to_implement.is_empty() { .map(|node_item| !node_item.defining_node.is_from_trait())
self.tcx .unwrap_or(false);
.sess
.struct_span_err( if !is_implemented {
item.span, to_implement.push(tcx.item_name(trait_item_id).to_string());
"const trait implementations may not use non-const default functions",
)
.note(&format!("`{}` not implemented", to_implement.join("`, `")))
.emit();
} }
}
} }
};
}
fn visit_trait_item<'hir>(&mut self, _: &'hir hir::TraitItem<'hir>) {} // all nonconst trait functions (not marked with #[default_method_body_is_const])
// must be implemented
fn visit_impl_item<'hir>(&mut self, _: &'hir hir::ImplItem<'hir>) {} if !to_implement.is_empty() {
tcx
fn visit_foreign_item<'hir>(&mut self, _: &'hir hir::ForeignItem<'hir>) {} .sess
.struct_span_err(
item.span,
"const trait implementations may not use non-const default functions",
)
.note(&format!("`{}` not implemented", to_implement.join("`, `")))
.emit();
}
}
};
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]