Skip to content

Commit 6346387

Browse files
committed
Switch to store Instance directly within VtblEntry, fix TraitVPtr representation.
1 parent ab171c5 commit 6346387

File tree

7 files changed

+98
-116
lines changed

7 files changed

+98
-116
lines changed

compiler/rustc_middle/src/ty/vtable.rs

+29-21
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,33 @@
11
use std::convert::TryFrom;
2+
use std::fmt;
23

34
use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar, ScalarMaybeUninit};
4-
use crate::ty::fold::TypeFoldable;
5-
use crate::ty::{self, DefId, PolyExistentialTraitRef, SubstsRef, Ty, TyCtxt};
5+
use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
66
use rustc_ast::Mutability;
77

8-
#[derive(Clone, Copy, Debug, PartialEq, HashStable)]
8+
#[derive(Clone, Copy, PartialEq, HashStable)]
99
pub enum VtblEntry<'tcx> {
1010
MetadataDropInPlace,
1111
MetadataSize,
1212
MetadataAlign,
1313
Vacant,
14-
Method(DefId, SubstsRef<'tcx>),
15-
TraitVPtr(PolyExistentialTraitRef<'tcx>),
14+
Method(Instance<'tcx>),
15+
TraitVPtr(PolyTraitRef<'tcx>),
16+
}
17+
18+
impl<'tcx> fmt::Debug for VtblEntry<'tcx> {
19+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20+
// We want to call `Display` on `Instance` and `PolyTraitRef`,
21+
// so we implement this manually.
22+
match self {
23+
VtblEntry::MetadataDropInPlace => write!(f, "MetadataDropInPlace"),
24+
VtblEntry::MetadataSize => write!(f, "MetadataSize"),
25+
VtblEntry::MetadataAlign => write!(f, "MetadataAlign"),
26+
VtblEntry::Vacant => write!(f, "Vacant"),
27+
VtblEntry::Method(instance) => write!(f, "Method({})", instance),
28+
VtblEntry::TraitVPtr(trait_ref) => write!(f, "TraitVPtr({})", trait_ref),
29+
}
30+
}
1631
}
1732

1833
pub const COMMON_VTABLE_ENTRIES: &[VtblEntry<'_>] =
@@ -37,11 +52,6 @@ impl<'tcx> TyCtxt<'tcx> {
3752
}
3853
drop(vtables_cache);
3954

40-
// See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
41-
assert!(
42-
!ty.needs_subst() && !poly_trait_ref.map_or(false, |trait_ref| trait_ref.needs_subst())
43-
);
44-
let param_env = ty::ParamEnv::reveal_all();
4555
let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
4656
let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
4757
let trait_ref = tcx.erase_regions(trait_ref);
@@ -51,8 +61,9 @@ impl<'tcx> TyCtxt<'tcx> {
5161
COMMON_VTABLE_ENTRIES
5262
};
5363

54-
let layout =
55-
tcx.layout_of(param_env.and(ty)).expect("failed to build vtable representation");
64+
let layout = tcx
65+
.layout_of(ty::ParamEnv::reveal_all().and(ty))
66+
.expect("failed to build vtable representation");
5667
assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
5768
let size = layout.size.bytes();
5869
let align = layout.align.abi.bytes();
@@ -80,21 +91,18 @@ impl<'tcx> TyCtxt<'tcx> {
8091
VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
8192
VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
8293
VtblEntry::Vacant => continue,
83-
VtblEntry::Method(def_id, substs) => {
84-
// See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
85-
assert!(!substs.needs_subst());
86-
94+
VtblEntry::Method(instance) => {
8795
// Prepare the fn ptr we write into the vtable.
88-
let instance =
89-
ty::Instance::resolve_for_vtable(tcx, param_env, *def_id, substs)
90-
.expect("resolution failed during building vtable representation")
91-
.polymorphize(tcx);
96+
let instance = instance.polymorphize(tcx);
9297
let fn_alloc_id = tcx.create_fn_alloc(instance);
9398
let fn_ptr = Pointer::from(fn_alloc_id);
9499
ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
95100
}
96101
VtblEntry::TraitVPtr(trait_ref) => {
97-
let supertrait_alloc_id = self.vtable_allocation(ty, Some(*trait_ref));
102+
let super_trait_ref = trait_ref.map_bound(|trait_ref| {
103+
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
104+
});
105+
let supertrait_alloc_id = self.vtable_allocation(ty, Some(super_trait_ref));
98106
let vptr = Pointer::from(supertrait_alloc_id);
99107
ScalarMaybeUninit::from_pointer(vptr, &tcx)
100108
}

compiler/rustc_mir/src/monomorphize/collector.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1120,13 +1120,9 @@ fn create_mono_items_for_vtable_methods<'tcx>(
11201120
// all super trait items already covered, so skip them.
11211121
None
11221122
}
1123-
VtblEntry::Method(def_id, substs) => ty::Instance::resolve_for_vtable(
1124-
tcx,
1125-
ty::ParamEnv::reveal_all(),
1126-
*def_id,
1127-
substs,
1128-
)
1129-
.filter(|instance| should_codegen_locally(tcx, instance)),
1123+
VtblEntry::Method(instance) => {
1124+
Some(*instance).filter(|instance| should_codegen_locally(tcx, instance))
1125+
}
11301126
})
11311127
.map(|item| create_fn_mono_item(tcx, item, source));
11321128
output.extend(methods);

compiler/rustc_trait_selection/src/traits/mod.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,14 @@ fn prepare_vtable_segments<'tcx, T>(
614614
}
615615
}
616616

617-
fn dump_vtable_entries<'tcx>(tcx: TyCtxt<'tcx>, entries: &[VtblEntry<'tcx>]) {
618-
let msg = format!("Vtable Entries: {:#?}", entries);
619-
tcx.sess.struct_span_err(rustc_span::DUMMY_SP, &msg).emit();
617+
fn dump_vtable_entries<'tcx>(
618+
tcx: TyCtxt<'tcx>,
619+
sp: Span,
620+
trait_ref: ty::PolyTraitRef<'tcx>,
621+
entries: &[VtblEntry<'tcx>],
622+
) {
623+
let msg = format!("Vtable entries for `{}`: {:#?}", trait_ref, entries);
624+
tcx.sess.struct_span_err(sp, &msg).emit();
620625
}
621626

622627
/// Given a trait `trait_ref`, iterates the vtable entries
@@ -678,15 +683,19 @@ fn vtable_entries<'tcx>(
678683
return VtblEntry::Vacant;
679684
}
680685

681-
VtblEntry::Method(def_id, substs)
686+
let instance = ty::Instance::resolve_for_vtable(
687+
tcx,
688+
ty::ParamEnv::reveal_all(),
689+
def_id,
690+
substs,
691+
)
692+
.expect("resolution failed during building vtable representation");
693+
VtblEntry::Method(instance)
682694
});
683695

684696
entries.extend(own_entries);
685697

686698
if emit_vptr {
687-
let trait_ref = trait_ref.map_bound(|trait_ref| {
688-
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
689-
});
690699
entries.push(VtblEntry::TraitVPtr(trait_ref));
691700
}
692701
}
@@ -698,7 +707,8 @@ fn vtable_entries<'tcx>(
698707
let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
699708

700709
if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) {
701-
dump_vtable_entries(tcx, &entries);
710+
let sp = tcx.def_span(trait_ref.def_id());
711+
dump_vtable_entries(tcx, sp, trait_ref, &entries);
702712
}
703713

704714
tcx.arena.alloc_from_iter(entries.into_iter())

src/test/ui/traits/vtable/vtable-diamond.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
// build-fail
2-
//~^ error Vtable
3-
//~^^ error Vtable
42
#![feature(rustc_attrs)]
53

64
#[rustc_dump_vtable]
@@ -15,11 +13,13 @@ trait B: A {
1513

1614
#[rustc_dump_vtable]
1715
trait C: A {
16+
//~^ error Vtable
1817
fn foo_c(&self) {}
1918
}
2019

2120
#[rustc_dump_vtable]
2221
trait D: B + C {
22+
//~^ error Vtable
2323
fn foo_d(&self) {}
2424
}
2525

Original file line numberDiff line numberDiff line change
@@ -1,56 +1,35 @@
1-
error: Vtable Entries: [
1+
error: Vtable entries for `<S as D>`: [
22
MetadataDropInPlace,
33
MetadataSize,
44
MetadataAlign,
5-
Method(
6-
DefId(0:4 ~ vtable_diamond[4564]::A::foo_a),
7-
[
8-
S,
9-
],
10-
),
11-
Method(
12-
DefId(0:6 ~ vtable_diamond[4564]::B::foo_b),
13-
[
14-
S,
15-
],
16-
),
17-
Method(
18-
DefId(0:8 ~ vtable_diamond[4564]::C::foo_c),
19-
[
20-
S,
21-
],
22-
),
23-
TraitVPtr(
24-
Binder(
25-
C,
26-
[],
27-
),
28-
),
29-
Method(
30-
DefId(0:10 ~ vtable_diamond[4564]::D::foo_d),
31-
[
32-
S,
33-
],
34-
),
5+
Method(<S as A>::foo_a),
6+
Method(<S as B>::foo_b),
7+
Method(<S as C>::foo_c),
8+
TraitVPtr(<S as C>),
9+
Method(<S as D>::foo_d),
3510
]
11+
--> $DIR/vtable-diamond.rs:21:1
12+
|
13+
LL | / trait D: B + C {
14+
LL | |
15+
LL | | fn foo_d(&self) {}
16+
LL | | }
17+
| |_^
3618

37-
error: Vtable Entries: [
19+
error: Vtable entries for `<S as C>`: [
3820
MetadataDropInPlace,
3921
MetadataSize,
4022
MetadataAlign,
41-
Method(
42-
DefId(0:4 ~ vtable_diamond[4564]::A::foo_a),
43-
[
44-
S,
45-
],
46-
),
47-
Method(
48-
DefId(0:8 ~ vtable_diamond[4564]::C::foo_c),
49-
[
50-
S,
51-
],
52-
),
23+
Method(<S as A>::foo_a),
24+
Method(<S as C>::foo_c),
5325
]
26+
--> $DIR/vtable-diamond.rs:15:1
27+
|
28+
LL | / trait C: A {
29+
LL | |
30+
LL | | fn foo_c(&self) {}
31+
LL | | }
32+
| |_^
5433

5534
error: aborting due to 2 previous errors
5635

src/test/ui/traits/vtable/vtable-multiple.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
// build-fail
2-
//~^ error Vtable
3-
//~^^ error Vtable
42
#![feature(rustc_attrs)]
53

64
#[rustc_dump_vtable]
@@ -10,11 +8,13 @@ trait A {
108

119
#[rustc_dump_vtable]
1210
trait B {
11+
//~^ error Vtable
1312
fn foo_b(&self) {}
1413
}
1514

1615
#[rustc_dump_vtable]
1716
trait C: A + B {
17+
//~^ error Vtable
1818
fn foo_c(&self) {}
1919
}
2020

Original file line numberDiff line numberDiff line change
@@ -1,44 +1,33 @@
1-
error: Vtable Entries: [
1+
error: Vtable entries for `<S as C>`: [
22
MetadataDropInPlace,
33
MetadataSize,
44
MetadataAlign,
5-
Method(
6-
DefId(0:4 ~ vtable_multiple[5246]::A::foo_a),
7-
[
8-
S,
9-
],
10-
),
11-
Method(
12-
DefId(0:6 ~ vtable_multiple[5246]::B::foo_b),
13-
[
14-
S,
15-
],
16-
),
17-
TraitVPtr(
18-
Binder(
19-
B,
20-
[],
21-
),
22-
),
23-
Method(
24-
DefId(0:8 ~ vtable_multiple[5246]::C::foo_c),
25-
[
26-
S,
27-
],
28-
),
5+
Method(<S as A>::foo_a),
6+
Method(<S as B>::foo_b),
7+
TraitVPtr(<S as B>),
8+
Method(<S as C>::foo_c),
299
]
10+
--> $DIR/vtable-multiple.rs:16:1
11+
|
12+
LL | / trait C: A + B {
13+
LL | |
14+
LL | | fn foo_c(&self) {}
15+
LL | | }
16+
| |_^
3017

31-
error: Vtable Entries: [
18+
error: Vtable entries for `<S as B>`: [
3219
MetadataDropInPlace,
3320
MetadataSize,
3421
MetadataAlign,
35-
Method(
36-
DefId(0:6 ~ vtable_multiple[5246]::B::foo_b),
37-
[
38-
S,
39-
],
40-
),
22+
Method(<S as B>::foo_b),
4123
]
24+
--> $DIR/vtable-multiple.rs:10:1
25+
|
26+
LL | / trait B {
27+
LL | |
28+
LL | | fn foo_b(&self) {}
29+
LL | | }
30+
| |_^
4231

4332
error: aborting due to 2 previous errors
4433

0 commit comments

Comments
 (0)