Skip to content

Commit ef001a9

Browse files
Auto merge of #147695 - cjgillot:deduce-param-freeze, r=<try>
deduced_param_attrs: check Freeze on monomorphic types.
2 parents 844264a + 6b2ed9d commit ef001a9

File tree

3 files changed

+35
-18
lines changed

3 files changed

+35
-18
lines changed

compiler/rustc_mir_transform/src/deduce_param_attrs.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -169,20 +169,9 @@ pub(super) fn deduced_param_attrs<'tcx>(
169169
// see [1].
170170
//
171171
// [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
172-
let typing_env = body.typing_env(tcx);
173-
let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
174-
body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
175-
|(arg_index, local_decl)| DeducedParamAttrs {
176-
read_only: !deduce_read_only.mutable_args.contains(arg_index)
177-
// We must normalize here to reveal opaques and normalize
178-
// their generic parameters, otherwise we'll see exponential
179-
// blow-up in compile times: #113372
180-
&& tcx
181-
.normalize_erasing_regions(typing_env, local_decl.ty)
182-
.is_freeze(tcx, typing_env),
183-
},
184-
),
185-
);
172+
let mut deduced_param_attrs = tcx.arena.alloc_from_iter((0..body.arg_count).map(|arg_index| {
173+
DeducedParamAttrs { read_only: !deduce_read_only.mutable_args.contains(arg_index) }
174+
}));
186175

187176
// Trailing parameters past the size of the `deduced_param_attrs` array are assumed to have the
188177
// default set of attributes, so we don't have to store them explicitly. Pop them off to save a

compiler/rustc_ty_utils/src/abi.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,10 @@ fn fn_abi_adjust_for_abi<'tcx>(
641641
// bounds.
642642
if let Some(deduced_param_attrs) = deduced_param_attrs.get(arg_idx)
643643
&& deduced_param_attrs.read_only
644+
// We must normalize here to reveal opaques and normalize
645+
// their generic parameters, otherwise we'll see exponential
646+
// blow-up in compile times: #113372
647+
&& arg.layout.ty.is_freeze(tcx, cx.typing_env)
644648
{
645649
attrs.regular.insert(ArgAttribute::ReadOnly);
646650
debug!("added deduced read-only attribute");

tests/codegen-llvm/deduced-param-attrs.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@ compile-flags: -Copt-level=3
1+
//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes
22

33
#![crate_type = "lib"]
44
#![allow(internal_features)]
@@ -28,7 +28,9 @@ pub fn use_big_struct_immutably(big_struct: BigStruct) {
2828

2929
// The by-value parameter for this big struct can't be marked readonly, because we mutate it.
3030
//
31-
// CHECK-NOT: @use_big_struct_mutably({{.*}} readonly {{.*}} %big_struct)
31+
// CHECK: @use_big_struct_mutably(
32+
// CHECK-NOT: readonly
33+
// CHECK-SAME: %big_struct)
3234
#[no_mangle]
3335
pub fn use_big_struct_mutably(mut big_struct: BigStruct) {
3436
big_struct.blah[987] = 654;
@@ -38,7 +40,9 @@ pub fn use_big_struct_mutably(mut big_struct: BigStruct) {
3840
// The by-value parameter for this big struct can't be marked readonly, because it contains
3941
// UnsafeCell.
4042
//
41-
// CHECK-NOT: @use_big_cell_container({{.*}} readonly {{.*}} %big_cell_container)
43+
// CHECK: @use_big_cell_container(
44+
// CHECK-NOT: readonly
45+
// CHECK-SAME: %big_cell_container)
4246
#[no_mangle]
4347
pub fn use_big_cell_container(big_cell_container: BigCellContainer) {
4448
hint::black_box(&big_cell_container);
@@ -47,14 +51,34 @@ pub fn use_big_cell_container(big_cell_container: BigCellContainer) {
4751
// Make sure that we don't mistakenly mark a big struct as `readonly` when passed through a generic
4852
// type parameter if it contains UnsafeCell.
4953
//
50-
// CHECK-NOT: @use_something({{.*}} readonly {{.*}} %something)
54+
// CHECK: @use_something(
55+
// CHECK-NOT: readonly
56+
// CHECK-SAME: %something)
5157
#[no_mangle]
5258
#[inline(never)]
5359
pub fn use_something<T>(something: T) {
5460
hint::black_box(&something);
5561
}
5662

63+
// Make sure that we still mark a big `Freeze` struct as `readonly` when passed through a generic
64+
// type parameter.
65+
//
66+
// CHECK: @use_something_freeze(
67+
// CHECK-SAME: readonly
68+
// CHECK-SAME: %x)
69+
#[no_mangle]
70+
#[inline(never)]
71+
pub fn use_something_freeze<T>(x: T) {
72+
// `Drop` counts as a mutable use.
73+
std::mem::forget(x)
74+
}
75+
5776
#[no_mangle]
5877
pub fn forward_big_cell_container(big_cell_container: BigCellContainer) {
5978
use_something(big_cell_container)
6079
}
80+
81+
#[no_mangle]
82+
pub fn forward_big_container(big_struct: BigStruct) {
83+
use_something_freeze(big_struct)
84+
}

0 commit comments

Comments
 (0)