Skip to content

Commit a7c8f57

Browse files
committed
Auto merge of rust-lang#124264 - GuillaumeGomez:rollup-l0i1t6q, r=GuillaumeGomez
Rollup of 5 pull requests Successful merges: - rust-lang#124178 ([cleanup] [llvm backend] Prevent creating the same `Instance::mono` multiple times) - rust-lang#124183 (Stop taking `ParamTy`/`ParamConst`/`EarlyParamRegion`/`AliasTy` by ref) - rust-lang#124217 (coverage: Prepare for improved branch coverage) - rust-lang#124220 (Miri: detect wrong vtables in wide pointers) - rust-lang#124252 (Improve ICE message for forbidden dep-graph reads.) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7f2fc33 + 201d60e commit a7c8f57

File tree

63 files changed

+1344
-221
lines changed

Some content is hidden

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

63 files changed

+1344
-221
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1320,7 +1320,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
13201320
.into_iter()
13211321
.map(|err| match err.obligation.predicate.kind().skip_binder() {
13221322
PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
1323-
match predicate.self_ty().kind() {
1323+
match *predicate.self_ty().kind() {
13241324
ty::Param(param_ty) => Ok((
13251325
generics.type_param(param_ty, tcx),
13261326
predicate.trait_ref.print_only_trait_path().to_string(),

compiler/rustc_borrowck/src/diagnostics/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1070,7 +1070,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10701070
// LL | blk();
10711071
// | ----- this value implements `FnOnce`, which causes it to be moved when called
10721072
// ```
1073-
if let ty::Param(param_ty) = self_ty.kind()
1073+
if let ty::Param(param_ty) = *self_ty.kind()
10741074
&& let generics = self.infcx.tcx.generics_of(self.mir_def_id())
10751075
&& let param = generics.type_param(param_ty, self.infcx.tcx)
10761076
&& let Some(hir_generics) = self

compiler/rustc_codegen_llvm/src/consts.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ impl<'ll> CodegenCx<'ll, '_> {
260260

261261
#[instrument(level = "debug", skip(self, llty))]
262262
pub(crate) fn get_static_inner(&self, def_id: DefId, llty: &'ll Type) -> &'ll Value {
263-
if let Some(&g) = self.instances.borrow().get(&Instance::mono(self.tcx, def_id)) {
263+
let instance = Instance::mono(self.tcx, def_id);
264+
if let Some(&g) = self.instances.borrow().get(&instance) {
264265
trace!("used cached value");
265266
return g;
266267
}
@@ -273,7 +274,7 @@ impl<'ll> CodegenCx<'ll, '_> {
273274
statics defined in the same CGU, but did not for `{def_id:?}`"
274275
);
275276

276-
let sym = self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name;
277+
let sym = self.tcx.symbol_name(instance).name;
277278
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
278279

279280
debug!(?sym, ?fn_attrs);
@@ -363,7 +364,7 @@ impl<'ll> CodegenCx<'ll, '_> {
363364
}
364365
}
365366

366-
self.instances.borrow_mut().insert(Instance::mono(self.tcx, def_id), g);
367+
self.instances.borrow_mut().insert(instance, g);
367368
g
368369
}
369370

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
@@ -802,11 +802,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
802802
let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
803803
receiver_place.layout.ty.kind()
804804
{
805-
let (recv, vptr) = self.unpack_dyn_star(&receiver_place)?;
806-
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
807-
if dyn_trait != data.principal() {
808-
throw_ub_custom!(fluent::const_eval_dyn_star_call_vtable_mismatch);
809-
}
805+
let (recv, vptr) = self.unpack_dyn_star(&receiver_place, data)?;
806+
let (dyn_ty, _dyn_trait) = self.get_ptr_vtable(vptr)?;
810807

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

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

940940
let place = match place.layout.ty.kind() {
941-
ty::Dynamic(_, _, ty::Dyn) => {
941+
ty::Dynamic(data, _, ty::Dyn) => {
942942
// Dropping a trait object. Need to find actual drop fn.
943-
self.unpack_dyn_trait(&place)?.0
943+
self.unpack_dyn_trait(&place, data)?.0
944944
}
945-
ty::Dynamic(_, _, ty::DynStar) => {
945+
ty::Dynamic(data, _, ty::DynStar) => {
946946
// Dropping a `dyn*`. Need to find actual drop fn.
947-
self.unpack_dyn_star(&place)?.0
947+
self.unpack_dyn_star(&place, data)?.0
948948
}
949949
_ => {
950950
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

compiler/rustc_hir_typeck/src/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2697,7 +2697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26972697

26982698
fn point_at_param_definition(&self, err: &mut Diag<'_>, param: ty::ParamTy) {
26992699
let generics = self.tcx.generics_of(self.body_id);
2700-
let generic_param = generics.type_param(&param, self.tcx);
2700+
let generic_param = generics.type_param(param, self.tcx);
27012701
if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param.kind {
27022702
return;
27032703
}

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2144,7 +2144,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21442144
let callee_ty = callee_ty.peel_refs();
21452145
match *callee_ty.kind() {
21462146
ty::Param(param) => {
2147-
let param = self.tcx.generics_of(self.body_id).type_param(&param, self.tcx);
2147+
let param = self.tcx.generics_of(self.body_id).type_param(param, self.tcx);
21482148
if param.kind.is_synthetic() {
21492149
// if it's `impl Fn() -> ..` then just fall down to the def-id based logic
21502150
def_id = param.def_id;

0 commit comments

Comments
 (0)