Skip to content

Commit

Permalink
deny using default function in impl const Trait
Browse files Browse the repository at this point in the history
  • Loading branch information
fee1-dead committed Jun 23, 2021
1 parent 4573a4a commit 22a8d46
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 0 deletions.
59 changes: 59 additions & 0 deletions compiler/rustc_passes/src/check_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_middle::hir::map::Map;
use rustc_middle::ty;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
Expand Down Expand Up @@ -59,12 +60,70 @@ impl NonConstExpr {
fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
let mut vis = CheckConstVisitor::new(tcx);
tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis.as_deep_visitor());
if tcx.features().enabled(sym::const_trait_impl) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckConstTraitVisitor::new(tcx));
}
}

pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_const_bodies, ..*providers };
}

struct CheckConstTraitVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}

impl<'tcx> CheckConstTraitVisitor<'tcx> {
fn new(tcx: TyCtxt<'tcx>) -> Self {
CheckConstTraitVisitor { tcx }
}
}

impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<'tcx> {
fn visit_item(&mut self, item: &'hir hir::Item<'hir>) {
let _: Option<_> = try {
if let hir::ItemKind::Impl(ref imp) = item.kind {
if let hir::Constness::Const = imp.constness {
let did = imp.of_trait.as_ref()?.trait_def_id()?;
let trait_fn_cnt = self
.tcx
.associated_item_def_ids(did)
.iter()
.filter(|did| {
matches!(
self.tcx.associated_item(**did),
ty::AssocItem { kind: ty::AssocKind::Fn, .. }
)
})
.count();

let impl_fn_cnt = imp
.items
.iter()
.filter(|it| matches!(it.kind, hir::AssocItemKind::Fn { .. }))
.count();

if trait_fn_cnt != impl_fn_cnt {
self.tcx
.sess
.struct_span_err(
item.span,
"const trait implementations may not use default functions",
)
.emit();
}
}
}
};
}

fn visit_trait_item(&mut self, _: &'hir hir::TraitItem<'hir>) {}

fn visit_impl_item(&mut self, _: &'hir hir::ImplItem<'hir>) {}

fn visit_foreign_item(&mut self, _: &'hir hir::ForeignItem<'hir>) {}
}

#[derive(Copy, Clone)]
struct CheckConstVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#![feature(iter_zip)]
#![feature(nll)]
#![feature(min_specialization)]
#![feature(try_blocks)]
#![recursion_limit = "256"]

#[macro_use]
Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/consts/const-float-classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ impl const PartialEq<NonDet> for bool {
fn eq(&self, _: &NonDet) -> bool {
true
}
fn ne(&self, _: &NonDet) -> bool {
false
}
}

// The result of the `is_sign` methods are not checked for correctness, since LLVM does not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ impl const PartialEq for Int {
fn eq(&self, rhs: &Self) -> bool {
self.0 == rhs.0
}
fn ne(&self, other: &Self) -> bool {
!self.eq(other)
}
}

pub trait Plus {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ impl const PartialEq for S {
fn eq(&self, _: &S) -> bool {
true
}
fn ne(&self, other: &S) -> bool {
!self.eq(other)
}
}

const fn equals_self<T: PartialEq>(t: &T) -> bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ impl const PartialEq for S {
fn eq(&self, _: &S) -> bool {
true
}
fn ne(&self, other: &S) -> bool {
!self.eq(other)
}
}

// This duplicate bound should not result in ambiguities. It should be equivalent to a single const
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ impl const PartialEq for S {
fn eq(&self, _: &S) -> bool {
true
}
fn ne(&self, other: &S) -> bool {
!self.eq(other)
}
}

const fn equals_self<T: PartialEq>(t: &T) -> bool {
Expand Down
20 changes: 20 additions & 0 deletions src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#![feature(const_trait_impl)]
#![allow(incomplete_features)]

trait Tr {
fn req(&self);

fn prov(&self) {
println!("lul");
self.req();
}
}

struct S;

impl const Tr for S {
fn req(&self) {}
}
//~^^^ ERROR const trait implementations may not use default functions

fn main() {}
10 changes: 10 additions & 0 deletions src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: const trait implementations may not use default functions
--> $DIR/impl-with-default-fn.rs:15:1
|
LL | / impl const Tr for S {
LL | | fn req(&self) {}
LL | | }
| |_^

error: aborting due to previous error

0 comments on commit 22a8d46

Please sign in to comment.