Skip to content

Commit c672773

Browse files
committed
Auto merge of rust-lang#124277 - matthiaskrgr:rollup-zdb93i4, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#123680 (Deny gen keyword in `edition_2024_compat` lints) - rust-lang#124057 (Fix ICE when ADT tail has type error) - rust-lang#124168 (Use `DefiningOpaqueTypes::Yes` in rustdoc, where the `InferCtxt` is guaranteed to have no opaque types it can define) - rust-lang#124197 (Move duplicated code in functions in `tests/rustdoc-gui/notable-trait.goml`) - rust-lang#124200 (Improve handling of expr->field errors) - rust-lang#124220 (Miri: detect wrong vtables in wide pointers) - rust-lang#124266 (remove an unused type from the reentrant lock tests) r? `@ghost` `@rustbot` modify labels: rollup
2 parents a77f76e + 819b4d5 commit c672773

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+674
-254
lines changed

compiler/rustc_const_eval/messages.ftl

+3-9
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,6 @@ const_eval_double_storage_live =
8282
const_eval_dyn_call_not_a_method =
8383
`dyn` call trying to call something that is not a method
8484
85-
const_eval_dyn_call_vtable_mismatch =
86-
`dyn` call on a pointer whose vtable does not match its type
87-
88-
const_eval_dyn_star_call_vtable_mismatch =
89-
`dyn*` call on a pointer whose vtable does not match its type
90-
9185
const_eval_error = {$error_kind ->
9286
[static] could not evaluate static initializer
9387
[const] evaluation of constant value failed
@@ -192,6 +186,8 @@ const_eval_invalid_uninit_bytes_unknown =
192186
const_eval_invalid_vtable_pointer =
193187
using {$pointer} as vtable pointer but it does not point to a vtable
194188
189+
const_eval_invalid_vtable_trait =
190+
using vtable for trait `{$vtable_trait}` but trait `{$expected_trait}` was expected
195191
196192
const_eval_live_drop =
197193
destructor of `{$dropped_ty}` cannot be evaluated at compile-time
@@ -401,9 +397,6 @@ const_eval_unterminated_c_string =
401397
const_eval_unwind_past_top =
402398
unwinding past the topmost frame of the stack
403399
404-
const_eval_upcast_mismatch =
405-
upcast on a pointer whose vtable does not match its type
406-
407400
## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`.
408401
## (We'd love to sort this differently to make that more clear but tidy won't let us...)
409402
const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
@@ -450,6 +443,7 @@ const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, bu
450443
const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
451444
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
452445
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
446+
const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$ref_trait}`, but encountered `{$vtable_trait}`
453447
const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
454448
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
455449
const_eval_validation_null_box = {$front_matter}: encountered a null box

compiler/rustc_const_eval/src/errors.rs

+17
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
498498
InvalidTag(_) => const_eval_invalid_tag,
499499
InvalidFunctionPointer(_) => const_eval_invalid_function_pointer,
500500
InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer,
501+
InvalidVTableTrait { .. } => const_eval_invalid_vtable_trait,
501502
InvalidStr(_) => const_eval_invalid_str,
502503
InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown,
503504
InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes,
@@ -537,13 +538,21 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
537538
| DeadLocal
538539
| UninhabitedEnumVariantWritten(_)
539540
| UninhabitedEnumVariantRead(_) => {}
541+
540542
BoundsCheckFailed { len, index } => {
541543
diag.arg("len", len);
542544
diag.arg("index", index);
543545
}
544546
UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
545547
diag.arg("pointer", ptr);
546548
}
549+
InvalidVTableTrait { expected_trait, vtable_trait } => {
550+
diag.arg("expected_trait", expected_trait.to_string());
551+
diag.arg(
552+
"vtable_trait",
553+
vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
554+
);
555+
}
547556
PointerUseAfterFree(alloc_id, msg) => {
548557
diag.arg("alloc_id", alloc_id)
549558
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
@@ -634,6 +643,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
634643
UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
635644
Uninit { .. } => const_eval_validation_uninit,
636645
InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr,
646+
InvalidMetaWrongTrait { .. } => const_eval_validation_invalid_vtable_trait,
637647
InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
638648
const_eval_validation_invalid_box_slice_meta
639649
}
@@ -773,6 +783,13 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
773783
DanglingPtrNoProvenance { pointer, .. } => {
774784
err.arg("pointer", pointer);
775785
}
786+
InvalidMetaWrongTrait { expected_trait: ref_trait, vtable_trait } => {
787+
err.arg("ref_trait", ref_trait.to_string());
788+
err.arg(
789+
"vtable_trait",
790+
vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
791+
);
792+
}
776793
NullPtr { .. }
777794
| PtrToStatic { .. }
778795
| ConstRefToMutable

compiler/rustc_const_eval/src/interpret/cast.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -393,14 +393,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
393393
let val = self.read_immediate(src)?;
394394
if data_a.principal() == data_b.principal() {
395395
// A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables.
396+
// (But currently mismatching vtables violate the validity invariant so UB is triggered anyway.)
396397
return self.write_immediate(*val, dest);
397398
}
398399
let (old_data, old_vptr) = val.to_scalar_pair();
399400
let old_data = old_data.to_pointer(self)?;
400401
let old_vptr = old_vptr.to_pointer(self)?;
401402
let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?;
402403
if old_trait != data_a.principal() {
403-
throw_ub_custom!(fluent::const_eval_upcast_mismatch);
404+
throw_ub!(InvalidVTableTrait {
405+
expected_trait: data_a,
406+
vtable_trait: old_trait,
407+
});
404408
}
405409
let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
406410
self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)

compiler/rustc_const_eval/src/interpret/place.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -1020,16 +1020,20 @@ where
10201020
pub(super) fn unpack_dyn_trait(
10211021
&self,
10221022
mplace: &MPlaceTy<'tcx, M::Provenance>,
1023+
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
10231024
) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, Pointer<Option<M::Provenance>>)> {
10241025
assert!(
10251026
matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _, ty::Dyn)),
10261027
"`unpack_dyn_trait` only makes sense on `dyn*` types"
10271028
);
10281029
let vtable = mplace.meta().unwrap_meta().to_pointer(self)?;
1029-
let (ty, _) = self.get_ptr_vtable(vtable)?;
1030-
let layout = self.layout_of(ty)?;
1030+
let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
1031+
if expected_trait.principal() != vtable_trait {
1032+
throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
1033+
}
10311034
// This is a kind of transmute, from a place with unsized type and metadata to
10321035
// a place with sized type and no metadata.
1036+
let layout = self.layout_of(ty)?;
10331037
let mplace =
10341038
MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..mplace.mplace }, layout };
10351039
Ok((mplace, vtable))
@@ -1040,6 +1044,7 @@ where
10401044
pub(super) fn unpack_dyn_star<P: Projectable<'tcx, M::Provenance>>(
10411045
&self,
10421046
val: &P,
1047+
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
10431048
) -> InterpResult<'tcx, (P, Pointer<Option<M::Provenance>>)> {
10441049
assert!(
10451050
matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
@@ -1048,10 +1053,12 @@ where
10481053
let data = self.project_field(val, 0)?;
10491054
let vtable = self.project_field(val, 1)?;
10501055
let vtable = self.read_pointer(&vtable.to_op(self)?)?;
1051-
let (ty, _) = self.get_ptr_vtable(vtable)?;
1056+
let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
1057+
if expected_trait.principal() != vtable_trait {
1058+
throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
1059+
}
1060+
// `data` is already the right thing but has the wrong type. So we transmute it.
10521061
let layout = self.layout_of(ty)?;
1053-
// `data` is already the right thing but has the wrong type. So we transmute it, by
1054-
// projecting with offset 0.
10551062
let data = data.transmute(layout, self)?;
10561063
Ok((data, vtable))
10571064
}

compiler/rustc_const_eval/src/interpret/terminator.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -803,11 +803,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
803803
let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
804804
receiver_place.layout.ty.kind()
805805
{
806-
let (recv, vptr) = self.unpack_dyn_star(&receiver_place)?;
807-
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
808-
if dyn_trait != data.principal() {
809-
throw_ub_custom!(fluent::const_eval_dyn_star_call_vtable_mismatch);
810-
}
806+
let (recv, vptr) = self.unpack_dyn_star(&receiver_place, data)?;
807+
let (dyn_ty, _dyn_trait) = self.get_ptr_vtable(vptr)?;
811808

812809
(vptr, dyn_ty, recv.ptr())
813810
} else {
@@ -829,7 +826,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
829826
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
830827
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
831828
if dyn_trait != data.principal() {
832-
throw_ub_custom!(fluent::const_eval_dyn_call_vtable_mismatch);
829+
throw_ub!(InvalidVTableTrait {
830+
expected_trait: data,
831+
vtable_trait: dyn_trait,
832+
});
833833
}
834834

835835
// It might be surprising that we use a pointer as the receiver even if this
@@ -939,13 +939,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
939939
let place = self.force_allocation(place)?;
940940

941941
let place = match place.layout.ty.kind() {
942-
ty::Dynamic(_, _, ty::Dyn) => {
942+
ty::Dynamic(data, _, ty::Dyn) => {
943943
// Dropping a trait object. Need to find actual drop fn.
944-
self.unpack_dyn_trait(&place)?.0
944+
self.unpack_dyn_trait(&place, data)?.0
945945
}
946-
ty::Dynamic(_, _, ty::DynStar) => {
946+
ty::Dynamic(data, _, ty::DynStar) => {
947947
// Dropping a `dyn*`. Need to find actual drop fn.
948-
self.unpack_dyn_star(&place)?.0
948+
self.unpack_dyn_star(&place, data)?.0
949949
}
950950
_ => {
951951
debug_assert_eq!(

compiler/rustc_const_eval/src/interpret/validity.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -339,16 +339,22 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
339339
) -> InterpResult<'tcx> {
340340
let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env);
341341
match tail.kind() {
342-
ty::Dynamic(_, _, ty::Dyn) => {
342+
ty::Dynamic(data, _, ty::Dyn) => {
343343
let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
344344
// Make sure it is a genuine vtable pointer.
345-
let (_ty, _trait) = try_validation!(
345+
let (_dyn_ty, dyn_trait) = try_validation!(
346346
self.ecx.get_ptr_vtable(vtable),
347347
self.path,
348348
Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
349349
InvalidVTablePtr { value: format!("{vtable}") }
350350
);
351-
// FIXME: check if the type/trait match what ty::Dynamic says?
351+
// Make sure it is for the right trait.
352+
if dyn_trait != data.principal() {
353+
throw_validation_failure!(
354+
self.path,
355+
InvalidMetaWrongTrait { expected_trait: data, vtable_trait: dyn_trait }
356+
);
357+
}
352358
}
353359
ty::Slice(..) | ty::Str => {
354360
let _len = meta.unwrap_meta().to_target_usize(self.ecx)?;
@@ -933,7 +939,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
933939
}
934940
}
935941
_ => {
936-
self.walk_value(op)?; // default handler
942+
// default handler
943+
try_validation!(
944+
self.walk_value(op),
945+
self.path,
946+
// It's not great to catch errors here, since we can't give a very good path,
947+
// but it's better than ICEing.
948+
Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
949+
InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
950+
},
951+
);
937952
}
938953
}
939954

compiler/rustc_const_eval/src/interpret/visitor.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -88,22 +88,22 @@ pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
8888
// Special treatment for special types, where the (static) layout is not sufficient.
8989
match *ty.kind() {
9090
// If it is a trait object, switch to the real type that was used to create it.
91-
ty::Dynamic(_, _, ty::Dyn) => {
91+
ty::Dynamic(data, _, ty::Dyn) => {
9292
// Dyn types. This is unsized, and the actual dynamic type of the data is given by the
9393
// vtable stored in the place metadata.
9494
// unsized values are never immediate, so we can assert_mem_place
9595
let op = v.to_op(self.ecx())?;
9696
let dest = op.assert_mem_place();
97-
let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?.0;
97+
let inner_mplace = self.ecx().unpack_dyn_trait(&dest, data)?.0;
9898
trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout);
9999
// recurse with the inner type
100100
return self.visit_field(v, 0, &inner_mplace.into());
101101
}
102-
ty::Dynamic(_, _, ty::DynStar) => {
102+
ty::Dynamic(data, _, ty::DynStar) => {
103103
// DynStar types. Very different from a dyn type (but strangely part of the
104104
// same variant in `TyKind`): These are pairs where the 2nd component is the
105105
// vtable, and the first component is the data (which must be ptr-sized).
106-
let data = self.ecx().unpack_dyn_star(v)?.0;
106+
let data = self.ecx().unpack_dyn_star(v, data)?.0;
107107
return self.visit_field(v, 0, &data);
108108
}
109109
// Slices do not need special handling here: they have `Array` field

0 commit comments

Comments
 (0)