Skip to content

Commit 412301b

Browse files
authored
Rollup merge of #89471 - nbdd0121:const3, r=fee1-dead
Use Ancestory to check default fn in const impl instead of comparing idents Fixes https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/topic/Const.20trait.20impl.20inside.20macro
2 parents 5b21064 + 0a03f8c commit 412301b

File tree

4 files changed

+64
-26
lines changed

4 files changed

+64
-26
lines changed

Diff for: compiler/rustc_passes/src/check_const.rs

+26-18
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
//! through, but errors for structured control flow in a `const` should be emitted here.
99
1010
use rustc_attr as attr;
11-
use rustc_data_structures::stable_set::FxHashSet;
1211
use rustc_errors::struct_span_err;
1312
use rustc_hir as hir;
1413
use rustc_hir::def_id::LocalDefId;
@@ -83,30 +82,39 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<
8382
let _: Option<_> = try {
8483
if let hir::ItemKind::Impl(ref imp) = item.kind {
8584
if let hir::Constness::Const = imp.constness {
86-
let did = imp.of_trait.as_ref()?.trait_def_id()?;
87-
let mut to_implement = FxHashSet::default();
88-
89-
for did in self.tcx.associated_item_def_ids(did) {
85+
let trait_def_id = imp.of_trait.as_ref()?.trait_def_id()?;
86+
let ancestors = self
87+
.tcx
88+
.trait_def(trait_def_id)
89+
.ancestors(self.tcx, item.def_id.to_def_id())
90+
.ok()?;
91+
let mut to_implement = Vec::new();
92+
93+
for trait_item in self.tcx.associated_items(trait_def_id).in_definition_order()
94+
{
9095
if let ty::AssocItem {
9196
kind: ty::AssocKind::Fn, ident, defaultness, ..
92-
} = self.tcx.associated_item(*did)
97+
} = trait_item
9398
{
9499
// we can ignore functions that do not have default bodies:
95100
// if those are unimplemented it will be catched by typeck.
96-
if defaultness.has_value()
97-
&& !self.tcx.has_attr(*did, sym::default_method_body_is_const)
101+
if !defaultness.has_value()
102+
|| self
103+
.tcx
104+
.has_attr(trait_item.def_id, sym::default_method_body_is_const)
98105
{
99-
to_implement.insert(ident);
106+
continue;
100107
}
101-
}
102-
}
103108

104-
for it in imp
105-
.items
106-
.iter()
107-
.filter(|it| matches!(it.kind, hir::AssocItemKind::Fn { .. }))
108-
{
109-
to_implement.remove(&it.ident);
109+
let is_implemented = ancestors
110+
.leaf_def(self.tcx, trait_item.ident, trait_item.kind)
111+
.map(|node_item| !node_item.defining_node.is_from_trait())
112+
.unwrap_or(false);
113+
114+
if !is_implemented {
115+
to_implement.push(ident.to_string());
116+
}
117+
}
110118
}
111119

112120
// all nonconst trait functions (not marked with #[default_method_body_is_const])
@@ -118,7 +126,7 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<
118126
item.span,
119127
"const trait implementations may not use non-const default functions",
120128
)
121-
.note(&format!("`{}` not implemented", to_implement.into_iter().map(|id| id.to_string()).collect::<Vec<_>>().join("`, `")))
129+
.note(&format!("`{}` not implemented", to_implement.join("`, `")))
122130
.emit();
123131
}
124132
}

Diff for: src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs renamed to src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![feature(const_trait_impl)]
2+
#![feature(const_fn_trait_bound)]
23

34
trait Tr {
45
fn req(&self);
@@ -18,11 +19,6 @@ impl const Tr for S {
1819
fn req(&self) {}
1920
} //~^^ ERROR const trait implementations may not use non-const default functions
2021

21-
impl const Tr for u8 {
22-
fn req(&self) {}
23-
fn prov(&self) {}
24-
}
25-
2622
impl const Tr for u16 {
2723
fn prov(&self) {}
2824
fn default() {}

Diff for: src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr renamed to src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: const trait implementations may not use non-const default functions
2-
--> $DIR/impl-with-default-fn.rs:17:1
2+
--> $DIR/impl-with-default-fn-fail.rs:18:1
33
|
44
LL | / impl const Tr for S {
55
LL | | fn req(&self) {}
@@ -9,7 +9,7 @@ LL | | }
99
= note: `prov` not implemented
1010

1111
error: const trait implementations may not use non-const default functions
12-
--> $DIR/impl-with-default-fn.rs:32:1
12+
--> $DIR/impl-with-default-fn-fail.rs:28:1
1313
|
1414
LL | / impl const Tr for u32 {
1515
LL | | fn req(&self) {}
@@ -20,7 +20,7 @@ LL | | }
2020
= note: `prov` not implemented
2121

2222
error[E0046]: not all trait items implemented, missing: `req`
23-
--> $DIR/impl-with-default-fn.rs:26:1
23+
--> $DIR/impl-with-default-fn-fail.rs:22:1
2424
|
2525
LL | fn req(&self);
2626
| -------------- `req` from trait
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// check-pass
2+
3+
#![feature(const_trait_impl)]
4+
#![feature(const_fn_trait_bound)]
5+
6+
trait Tr {
7+
fn req(&self);
8+
9+
fn prov(&self) {
10+
println!("lul");
11+
self.req();
12+
}
13+
14+
#[default_method_body_is_const]
15+
fn default() {}
16+
}
17+
18+
impl const Tr for u8 {
19+
fn req(&self) {}
20+
fn prov(&self) {}
21+
}
22+
23+
macro_rules! impl_tr {
24+
($ty: ty) => {
25+
impl const Tr for $ty {
26+
fn req(&self) {}
27+
fn prov(&self) {}
28+
}
29+
}
30+
}
31+
32+
impl_tr!(u64);
33+
34+
fn main() {}

0 commit comments

Comments
 (0)