mirror of
https://github.com/rust-lang/rust
synced 2024-10-21 16:03:40 +00:00
deny using default function in impl const Trait
This commit is contained in:
parent
4573a4a879
commit
22a8d46ed3
|
@ -13,6 +13,7 @@
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
|
@ -59,12 +60,70 @@ fn required_feature_gates(self) -> Option<&'static [Symbol]> {
|
||||||
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());
|
||||||
|
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) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
*providers = Providers { check_mod_const_bodies, ..*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)]
|
#[derive(Copy, Clone)]
|
||||||
struct CheckConstVisitor<'tcx> {
|
struct CheckConstVisitor<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
|
#![feature(try_blocks)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -53,6 +53,9 @@ impl const PartialEq<NonDet> for bool {
|
||||||
fn eq(&self, _: &NonDet) -> bool {
|
fn eq(&self, _: &NonDet) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
fn ne(&self, _: &NonDet) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The result of the `is_sign` methods are not checked for correctness, since LLVM does not
|
// The result of the `is_sign` methods are not checked for correctness, since LLVM does not
|
||||||
|
|
|
@ -17,6 +17,9 @@ impl const PartialEq for Int {
|
||||||
fn eq(&self, rhs: &Self) -> bool {
|
fn eq(&self, rhs: &Self) -> bool {
|
||||||
self.0 == rhs.0
|
self.0 == rhs.0
|
||||||
}
|
}
|
||||||
|
fn ne(&self, other: &Self) -> bool {
|
||||||
|
!self.eq(other)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Plus {
|
pub trait Plus {
|
||||||
|
|
|
@ -12,6 +12,9 @@ impl const PartialEq for S {
|
||||||
fn eq(&self, _: &S) -> bool {
|
fn eq(&self, _: &S) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
fn ne(&self, other: &S) -> bool {
|
||||||
|
!self.eq(other)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn equals_self<T: PartialEq>(t: &T) -> bool {
|
const fn equals_self<T: PartialEq>(t: &T) -> bool {
|
||||||
|
|
|
@ -11,6 +11,9 @@ impl const PartialEq for S {
|
||||||
fn eq(&self, _: &S) -> bool {
|
fn eq(&self, _: &S) -> bool {
|
||||||
true
|
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
|
// This duplicate bound should not result in ambiguities. It should be equivalent to a single const
|
||||||
|
|
|
@ -12,6 +12,9 @@ impl const PartialEq for S {
|
||||||
fn eq(&self, _: &S) -> bool {
|
fn eq(&self, _: &S) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
fn ne(&self, other: &S) -> bool {
|
||||||
|
!self.eq(other)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn equals_self<T: PartialEq>(t: &T) -> bool {
|
const fn equals_self<T: PartialEq>(t: &T) -> bool {
|
||||||
|
|
|
@ -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() {}
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue