Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #124264

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d34be93
Prevent creating the same `Instance::mono` multiple times
GuillaumeGomez Apr 19, 2024
86756c1
Stop taking ParamTy/ParamConst/EarlyParamRegion/AliasTy by ref
compiler-errors Apr 20, 2024
875f0c2
Miri: detect wrong vtables in wide pointers
RalfJung Apr 21, 2024
c373ec0
Improve ICE message for forbidden dep-graph reads.
michaelwoerister Apr 22, 2024
4f7a477
coverage: Branch coverage test for let-else
Zalathar Apr 17, 2024
7f432df
coverage: Branch coverage test for if-let and let-chains
Zalathar Apr 17, 2024
3de87fe
coverage: Branch coverage tests for match arms
Zalathar Apr 17, 2024
da37b14
coverage: Move mir-opt coverage tests into a subdirectory
Zalathar Apr 19, 2024
a892c23
coverage: Add a mir-opt test for branch coverage of match arms
Zalathar Apr 19, 2024
97bf553
coverage: Detach MC/DC branch spans from regular branch spans
Zalathar Apr 21, 2024
b5a22be
coverage: Move some helper code into `BranchInfoBuilder`
Zalathar Apr 21, 2024
2b6adb0
coverage: Separate branch pairs from other mapping kinds
Zalathar Apr 21, 2024
6146a51
Add more context to the forbidden dep-graph read ICE error message.
michaelwoerister Apr 22, 2024
7d39eaa
Rollup merge of #124178 - GuillaumeGomez:llvm-backend, r=oli-obk
GuillaumeGomez Apr 22, 2024
2a7ec56
Rollup merge of #124183 - compiler-errors:unnecessary-by-ref, r=oli-obk
GuillaumeGomez Apr 22, 2024
4be17d1
Rollup merge of #124217 - Zalathar:pre-branch, r=oli-obk
GuillaumeGomez Apr 22, 2024
c0ca632
Rollup merge of #124220 - RalfJung:interpret-wrong-vtable, r=oli-obk
GuillaumeGomez Apr 22, 2024
201d60e
Rollup merge of #124252 - michaelwoerister:better-forbidden-read-ice,…
GuillaumeGomez Apr 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1320,7 +1320,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.into_iter()
.map(|err| match err.obligation.predicate.kind().skip_binder() {
PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
match predicate.self_ty().kind() {
match *predicate.self_ty().kind() {
ty::Param(param_ty) => Ok((
generics.type_param(param_ty, tcx),
predicate.trait_ref.print_only_trait_path().to_string(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// LL | blk();
// | ----- this value implements `FnOnce`, which causes it to be moved when called
// ```
if let ty::Param(param_ty) = self_ty.kind()
if let ty::Param(param_ty) = *self_ty.kind()
&& let generics = self.infcx.tcx.generics_of(self.mir_def_id())
&& let param = generics.type_param(param_ty, self.infcx.tcx)
&& let Some(hir_generics) = self
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_codegen_llvm/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ impl<'ll> CodegenCx<'ll, '_> {

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

let sym = self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name;
let sym = self.tcx.symbol_name(instance).name;
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);

debug!(?sym, ?fn_attrs);
Expand Down Expand Up @@ -363,7 +364,7 @@ impl<'ll> CodegenCx<'ll, '_> {
}
}

self.instances.borrow_mut().insert(Instance::mono(self.tcx, def_id), g);
self.instances.borrow_mut().insert(instance, g);
g
}

Expand Down
12 changes: 3 additions & 9 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,6 @@ const_eval_double_storage_live =
const_eval_dyn_call_not_a_method =
`dyn` call trying to call something that is not a method

const_eval_dyn_call_vtable_mismatch =
`dyn` call on a pointer whose vtable does not match its type

const_eval_dyn_star_call_vtable_mismatch =
`dyn*` call on a pointer whose vtable does not match its type

const_eval_error = {$error_kind ->
[static] could not evaluate static initializer
[const] evaluation of constant value failed
Expand Down Expand Up @@ -192,6 +186,8 @@ const_eval_invalid_uninit_bytes_unknown =
const_eval_invalid_vtable_pointer =
using {$pointer} as vtable pointer but it does not point to a vtable

const_eval_invalid_vtable_trait =
using vtable for trait `{$vtable_trait}` but trait `{$expected_trait}` was expected

const_eval_live_drop =
destructor of `{$dropped_ty}` cannot be evaluated at compile-time
Expand Down Expand Up @@ -401,9 +397,6 @@ const_eval_unterminated_c_string =
const_eval_unwind_past_top =
unwinding past the topmost frame of the stack

const_eval_upcast_mismatch =
upcast on a pointer whose vtable does not match its type

## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`.
## (We'd love to sort this differently to make that more clear but tidy won't let us...)
const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
Expand Down Expand Up @@ -450,6 +443,7 @@ const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, bu
const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$ref_trait}`, but encountered `{$vtable_trait}`
const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
const_eval_validation_null_box = {$front_matter}: encountered a null box
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
InvalidTag(_) => const_eval_invalid_tag,
InvalidFunctionPointer(_) => const_eval_invalid_function_pointer,
InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer,
InvalidVTableTrait { .. } => const_eval_invalid_vtable_trait,
InvalidStr(_) => const_eval_invalid_str,
InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown,
InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes,
Expand Down Expand Up @@ -537,13 +538,21 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
| DeadLocal
| UninhabitedEnumVariantWritten(_)
| UninhabitedEnumVariantRead(_) => {}

BoundsCheckFailed { len, index } => {
diag.arg("len", len);
diag.arg("index", index);
}
UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
diag.arg("pointer", ptr);
}
InvalidVTableTrait { expected_trait, vtable_trait } => {
diag.arg("expected_trait", expected_trait.to_string());
diag.arg(
"vtable_trait",
vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
);
}
PointerUseAfterFree(alloc_id, msg) => {
diag.arg("alloc_id", alloc_id)
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
Expand Down Expand Up @@ -634,6 +643,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
Uninit { .. } => const_eval_validation_uninit,
InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr,
InvalidMetaWrongTrait { .. } => const_eval_validation_invalid_vtable_trait,
InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
const_eval_validation_invalid_box_slice_meta
}
Expand Down Expand Up @@ -773,6 +783,13 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
DanglingPtrNoProvenance { pointer, .. } => {
err.arg("pointer", pointer);
}
InvalidMetaWrongTrait { expected_trait: ref_trait, vtable_trait } => {
err.arg("ref_trait", ref_trait.to_string());
err.arg(
"vtable_trait",
vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
);
}
NullPtr { .. }
| PtrToStatic { .. }
| ConstRefToMutable
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_const_eval/src/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,14 +393,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let val = self.read_immediate(src)?;
if data_a.principal() == data_b.principal() {
// A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables.
// (But currently mismatching vtables violate the validity invariant so UB is triggered anyway.)
return self.write_immediate(*val, dest);
}
let (old_data, old_vptr) = val.to_scalar_pair();
let old_data = old_data.to_pointer(self)?;
let old_vptr = old_vptr.to_pointer(self)?;
let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?;
if old_trait != data_a.principal() {
throw_ub_custom!(fluent::const_eval_upcast_mismatch);
throw_ub!(InvalidVTableTrait {
expected_trait: data_a,
vtable_trait: old_trait,
});
}
let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
Expand Down
17 changes: 12 additions & 5 deletions compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,16 +1020,20 @@ where
pub(super) fn unpack_dyn_trait(
&self,
mplace: &MPlaceTy<'tcx, M::Provenance>,
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, Pointer<Option<M::Provenance>>)> {
assert!(
matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _, ty::Dyn)),
"`unpack_dyn_trait` only makes sense on `dyn*` types"
);
let vtable = mplace.meta().unwrap_meta().to_pointer(self)?;
let (ty, _) = self.get_ptr_vtable(vtable)?;
let layout = self.layout_of(ty)?;
let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
if expected_trait.principal() != vtable_trait {
throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
}
// This is a kind of transmute, from a place with unsized type and metadata to
// a place with sized type and no metadata.
let layout = self.layout_of(ty)?;
let mplace =
MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..mplace.mplace }, layout };
Ok((mplace, vtable))
Expand All @@ -1040,6 +1044,7 @@ where
pub(super) fn unpack_dyn_star<P: Projectable<'tcx, M::Provenance>>(
&self,
val: &P,
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
) -> InterpResult<'tcx, (P, Pointer<Option<M::Provenance>>)> {
assert!(
matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
Expand All @@ -1048,10 +1053,12 @@ where
let data = self.project_field(val, 0)?;
let vtable = self.project_field(val, 1)?;
let vtable = self.read_pointer(&vtable.to_op(self)?)?;
let (ty, _) = self.get_ptr_vtable(vtable)?;
let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
if expected_trait.principal() != vtable_trait {
throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
}
// `data` is already the right thing but has the wrong type. So we transmute it.
let layout = self.layout_of(ty)?;
// `data` is already the right thing but has the wrong type. So we transmute it, by
// projecting with offset 0.
let data = data.transmute(layout, self)?;
Ok((data, vtable))
}
Expand Down
20 changes: 10 additions & 10 deletions compiler/rustc_const_eval/src/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,11 +802,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
receiver_place.layout.ty.kind()
{
let (recv, vptr) = self.unpack_dyn_star(&receiver_place)?;
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
if dyn_trait != data.principal() {
throw_ub_custom!(fluent::const_eval_dyn_star_call_vtable_mismatch);
}
let (recv, vptr) = self.unpack_dyn_star(&receiver_place, data)?;
let (dyn_ty, _dyn_trait) = self.get_ptr_vtable(vptr)?;

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

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

let place = match place.layout.ty.kind() {
ty::Dynamic(_, _, ty::Dyn) => {
ty::Dynamic(data, _, ty::Dyn) => {
// Dropping a trait object. Need to find actual drop fn.
self.unpack_dyn_trait(&place)?.0
self.unpack_dyn_trait(&place, data)?.0
}
ty::Dynamic(_, _, ty::DynStar) => {
ty::Dynamic(data, _, ty::DynStar) => {
// Dropping a `dyn*`. Need to find actual drop fn.
self.unpack_dyn_star(&place)?.0
self.unpack_dyn_star(&place, data)?.0
}
_ => {
debug_assert_eq!(
Expand Down
23 changes: 19 additions & 4 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,16 +339,22 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
) -> InterpResult<'tcx> {
let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env);
match tail.kind() {
ty::Dynamic(_, _, ty::Dyn) => {
ty::Dynamic(data, _, ty::Dyn) => {
let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
// Make sure it is a genuine vtable pointer.
let (_ty, _trait) = try_validation!(
let (_dyn_ty, dyn_trait) = try_validation!(
self.ecx.get_ptr_vtable(vtable),
self.path,
Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
InvalidVTablePtr { value: format!("{vtable}") }
);
// FIXME: check if the type/trait match what ty::Dynamic says?
// Make sure it is for the right trait.
if dyn_trait != data.principal() {
throw_validation_failure!(
self.path,
InvalidMetaWrongTrait { expected_trait: data, vtable_trait: dyn_trait }
);
}
}
ty::Slice(..) | ty::Str => {
let _len = meta.unwrap_meta().to_target_usize(self.ecx)?;
Expand Down Expand Up @@ -933,7 +939,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
}
}
_ => {
self.walk_value(op)?; // default handler
// default handler
try_validation!(
self.walk_value(op),
self.path,
// It's not great to catch errors here, since we can't give a very good path,
// but it's better than ICEing.
Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
},
);
}
}

Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_const_eval/src/interpret/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,22 @@ pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
// Special treatment for special types, where the (static) layout is not sufficient.
match *ty.kind() {
// If it is a trait object, switch to the real type that was used to create it.
ty::Dynamic(_, _, ty::Dyn) => {
ty::Dynamic(data, _, ty::Dyn) => {
// Dyn types. This is unsized, and the actual dynamic type of the data is given by the
// vtable stored in the place metadata.
// unsized values are never immediate, so we can assert_mem_place
let op = v.to_op(self.ecx())?;
let dest = op.assert_mem_place();
let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?.0;
let inner_mplace = self.ecx().unpack_dyn_trait(&dest, data)?.0;
trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout);
// recurse with the inner type
return self.visit_field(v, 0, &inner_mplace.into());
}
ty::Dynamic(_, _, ty::DynStar) => {
ty::Dynamic(data, _, ty::DynStar) => {
// DynStar types. Very different from a dyn type (but strangely part of the
// same variant in `TyKind`): These are pairs where the 2nd component is the
// vtable, and the first component is the data (which must be ptr-sized).
let data = self.ecx().unpack_dyn_star(v)?.0;
let data = self.ecx().unpack_dyn_star(v, data)?.0;
return self.visit_field(v, 0, &data);
}
// Slices do not need special handling here: they have `Array` field
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2697,7 +2697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

fn point_at_param_definition(&self, err: &mut Diag<'_>, param: ty::ParamTy) {
let generics = self.tcx.generics_of(self.body_id);
let generic_param = generics.type_param(&param, self.tcx);
let generic_param = generics.type_param(param, self.tcx);
if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param.kind {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2144,7 +2144,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let callee_ty = callee_ty.peel_refs();
match *callee_ty.kind() {
ty::Param(param) => {
let param = self.tcx.generics_of(self.body_id).type_param(&param, self.tcx);
let param = self.tcx.generics_of(self.body_id).type_param(param, self.tcx);
if param.kind.is_synthetic() {
// if it's `impl Fn() -> ..` then just fall down to the def-id based logic
def_id = param.def_id;
Expand Down
Loading
Loading