Skip to content

Commit 897ebf0

Browse files
committed
Exclude final methods from dyn-compat check and vtable
1 parent e440a98 commit 897ebf0

4 files changed

Lines changed: 56 additions & 0 deletions

File tree

compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,11 @@ pub fn dyn_compatibility_violations_for_assoc_item(
314314
trait_def_id: DefId,
315315
item: ty::AssocItem,
316316
) -> Vec<DynCompatibilityViolation> {
317+
// `final` assoc functions don't prevent a trait from being dyn-compatible
318+
if tcx.defaultness(item.def_id).is_final() {
319+
return Vec::new();
320+
}
321+
317322
// Any item that has a `Self: Sized` requisite is otherwise exempt from the regulations.
318323
if tcx.generics_require_sized_self(item.def_id) {
319324
return Vec::new();

compiler/rustc_trait_selection/src/traits/vtable.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ fn own_existential_vtable_entries_iter(
210210
debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
211211
let def_id = trait_method.def_id;
212212

213+
// Final methods should not be included in the vtable.
214+
if trait_method.defaultness(tcx).is_final() {
215+
return None;
216+
}
217+
213218
// Some methods cannot be called on an object; skip those.
214219
if !is_vtable_safe_method(tcx, trait_def_id, trait_method) {
215220
debug!("own_existential_vtable_entry: not vtable safe");

compiler/rustc_ty_utils/src/instance.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,12 @@ fn resolve_associated_item<'tcx>(
237237
}
238238
traits::ImplSource::Builtin(BuiltinImplSource::Object(_), _) => {
239239
let trait_ref = ty::TraitRef::from_assoc(tcx, trait_id, rcvr_args);
240+
241+
// `final` methods should be called directly.
242+
if tcx.defaultness(trait_item_id).is_final() {
243+
return Ok(Some(ty::Instance::new_raw(trait_item_id, rcvr_args)));
244+
}
245+
240246
if trait_ref.has_non_region_infer() || trait_ref.has_non_region_param() {
241247
// We only resolve totally substituted vtable entries.
242248
None
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//@ run-pass
2+
3+
#![feature(final_associated_functions)]
4+
5+
trait FinalNoReceiver {
6+
final fn no_receiver() {}
7+
}
8+
9+
trait FinalGeneric {
10+
final fn generic<T>(&self, _value: T) {}
11+
}
12+
13+
trait FinalSelfParam {
14+
final fn self_param(&self, _other: &Self) {}
15+
}
16+
17+
trait FinalSelfReturn {
18+
final fn self_return(&self) -> &Self {
19+
self
20+
}
21+
}
22+
23+
struct S;
24+
25+
impl FinalNoReceiver for S {}
26+
impl FinalGeneric for S {}
27+
impl FinalSelfParam for S {}
28+
impl FinalSelfReturn for S {}
29+
30+
fn main() {
31+
let s = S;
32+
<S as FinalNoReceiver>::no_receiver();
33+
let obj_generic: &dyn FinalGeneric = &s;
34+
let obj_param: &dyn FinalSelfParam = &s;
35+
let obj_return: &dyn FinalSelfReturn = &s;
36+
obj_generic.generic(1u8);
37+
obj_param.self_param(obj_param);
38+
let _ = obj_return.self_return();
39+
let _: &dyn FinalNoReceiver = &s;
40+
}

0 commit comments

Comments
 (0)