Skip to content

Commit 7037eae

Browse files
committed
Auto merge of rust-lang#124258 - GuillaumeGomez:rollup-2d3albo, r=GuillaumeGomez
Rollup of 5 pull requests Successful merges: - rust-lang#104087 (Stabilise inline_const) - rust-lang#123792 (Require explicitly marking closures as coroutines) - rust-lang#124057 (Fix ICE when ADT tail has type error) - rust-lang#124178 ([cleanup] [llvm backend] Prevent creating the same `Instance::mono` multiple times) - rust-lang#124220 (Miri: detect wrong vtables in wide pointers) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7f2fc33 + 23e24c7 commit 7037eae

File tree

397 files changed

+1784
-1279
lines changed

Some content is hidden

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

397 files changed

+1784
-1279
lines changed

compiler/rustc_ast_lowering/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,6 @@ ast_lowering_underscore_expr_lhs_assign =
163163
.label = `_` not allowed here
164164
165165
ast_lowering_use_angle_brackets = use angle brackets instead
166+
ast_lowering_yield_in_closure =
167+
`yield` can only be used in `#[coroutine]` closures, or `gen` blocks
168+
.suggestion = use `#[coroutine]` to make this closure a coroutine

compiler/rustc_ast_lowering/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,12 @@ pub(crate) struct NoPreciseCapturesOnApit {
421421
#[primary_span]
422422
pub span: Span,
423423
}
424+
425+
#[derive(Diagnostic)]
426+
#[diag(ast_lowering_yield_in_closure)]
427+
pub(crate) struct YieldInClosure {
428+
#[primary_span]
429+
pub span: Span,
430+
#[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")]
431+
pub suggestion: Option<Span>,
432+
}

compiler/rustc_ast_lowering/src/expr.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use super::errors::{
88
};
99
use super::ResolverAstLoweringExt;
1010
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
11+
use crate::errors::YieldInClosure;
1112
use crate::{FnDeclKind, ImplTraitPosition};
1213
use rustc_ast::ptr::P as AstP;
1314
use rustc_ast::*;
@@ -217,6 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
217218
binder,
218219
*capture_clause,
219220
e.id,
221+
hir_id,
220222
*constness,
221223
*movability,
222224
fn_decl,
@@ -955,6 +957,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
955957
binder: &ClosureBinder,
956958
capture_clause: CaptureBy,
957959
closure_id: NodeId,
960+
closure_hir_id: hir::HirId,
958961
constness: Const,
959962
movability: Movability,
960963
decl: &FnDecl,
@@ -965,8 +968,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
965968
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
966969

967970
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
968-
let mut coroutine_kind = None;
971+
let mut coroutine_kind = if this
972+
.attrs
973+
.get(&closure_hir_id.local_id)
974+
.is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
975+
{
976+
Some(hir::CoroutineKind::Coroutine(Movability::Movable))
977+
} else {
978+
None
979+
};
969980
let body_id = this.lower_fn_body(decl, |this| {
981+
this.coroutine_kind = coroutine_kind;
970982
let e = this.lower_expr_mut(body);
971983
coroutine_kind = this.coroutine_kind;
972984
e
@@ -1565,7 +1577,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
15651577
)
15661578
.emit();
15671579
}
1580+
let suggestion = self.current_item.map(|s| s.shrink_to_lo());
1581+
self.dcx().emit_err(YieldInClosure { span, suggestion });
15681582
self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable));
1583+
15691584
false
15701585
}
15711586
};

compiler/rustc_ast_lowering/src/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
203203
body,
204204
..
205205
}) => {
206-
self.with_new_scopes(ident.span, |this| {
206+
self.with_new_scopes(*fn_sig_span, |this| {
207207
// Note: we don't need to change the return type from `T` to
208208
// `impl Future<Output = T>` here because lower_body
209209
// only cares about the input argument patterns in the function

compiler/rustc_ast_passes/src/feature_gate.rs

-1
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
556556
half_open_range_patterns_in_slices,
557557
"half-open range patterns in slices are unstable"
558558
);
559-
gate_all!(inline_const, "inline-const is experimental");
560559
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
561560
gate_all!(associated_const_equality, "associated const equality is incomplete");
562561
gate_all!(yeet_expr, "`do yeet` expression is experimental");

compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(coroutines, coroutine_trait)]
1+
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
22

33
use std::ops::Coroutine;
44
use std::pin::Pin;
@@ -8,7 +8,8 @@ fn main() {
88
}
99

1010
fn run_coroutine<T>() {
11-
let mut coroutine = || {
11+
let mut coroutine = #[coroutine]
12+
|| {
1213
yield;
1314
return;
1415
};

compiler/rustc_codegen_cranelift/example/std_example.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(
22
core_intrinsics,
33
coroutines,
4+
stmt_expr_attributes,
45
coroutine_trait,
56
is_sorted,
67
repr_simd,
@@ -122,9 +123,12 @@ fn main() {
122123
test_simd();
123124
}
124125

125-
Box::pin(move |mut _task_context| {
126-
yield ();
127-
})
126+
Box::pin(
127+
#[coroutine]
128+
move |mut _task_context| {
129+
yield ();
130+
},
131+
)
128132
.as_mut()
129133
.resume(0);
130134

compiler/rustc_codegen_gcc/example/std_example.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![allow(internal_features)]
2-
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)]
2+
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted, stmt_expr_attributes)]
33

44
#[cfg(feature="master")]
55
#[cfg(target_arch="x86_64")]
@@ -103,7 +103,7 @@ fn main() {
103103
test_simd();
104104
}
105105

106-
Box::pin(move |mut _task_context| {
106+
Box::pin(#[coroutine] move |mut _task_context| {
107107
yield ();
108108
}).as_mut().resume(0);
109109

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!(

0 commit comments

Comments
 (0)