Skip to content

Commit b90b646

Browse files
committed
Addresses #948
Fixes an issue where we would rewrite structs and their fields even though they appear in extern blocks.
1 parent a4ab0bc commit b90b646

File tree

5 files changed

+84
-11
lines changed

5 files changed

+84
-11
lines changed

c2rust-analyze/src/context.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_middle::ty::{
2525
tls, AdtDef, FieldDef, GenericArgKind, GenericParamDefKind, Ty, TyCtxt, TyKind,
2626
};
2727
use rustc_type_ir::RegionKind::{ReEarlyBound, ReStatic};
28-
use std::collections::HashMap;
28+
use std::collections::{HashMap, HashSet};
2929
use std::fmt::Debug;
3030
use std::ops::Index;
3131

@@ -287,6 +287,8 @@ pub struct GlobalAnalysisCtxt<'tcx> {
287287
pub addr_of_static: HashMap<DefId, PointerId>,
288288

289289
pub adt_metadata: AdtMetadataTable<'tcx>,
290+
291+
pub foreign_mentioned_tys: HashSet<Ty<'tcx>>,
290292
}
291293

292294
pub struct AnalysisCtxt<'a, 'tcx> {
@@ -536,6 +538,7 @@ impl<'tcx> GlobalAnalysisCtxt<'tcx> {
536538
static_tys: HashMap::new(),
537539
addr_of_static: HashMap::new(),
538540
adt_metadata: construct_adt_metadata(tcx),
541+
foreign_mentioned_tys: HashSet::new(),
539542
}
540543
}
541544

@@ -582,6 +585,7 @@ impl<'tcx> GlobalAnalysisCtxt<'tcx> {
582585
ref mut static_tys,
583586
ref mut addr_of_static,
584587
adt_metadata: _,
588+
foreign_mentioned_tys: _,
585589
} = *self;
586590

587591
*ptr_info = remap_global_ptr_info(ptr_info, map, counter.num_pointers());

c2rust-analyze/src/main.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,24 @@ fn run(tcx: TyCtxt) {
474474
|| info.contains(PointerInfo::NOT_TEMPORARY_REF))
475475
}
476476

477+
// track all types mentioned in extern blocks, we
478+
// don't want to rewrite those
479+
let mut foreign_mentioned_tys = HashSet::new();
480+
for item in tcx.hir_crate_items(()).foreign_items() {
481+
let ldid = item.def_id.to_def_id();
482+
match tcx.def_kind(ldid) {
483+
DefKind::Fn | DefKind::AssocFn => {
484+
let sig = tcx.fn_sig(ldid);
485+
let sig = tcx.erase_late_bound_regions(sig);
486+
for ty in sig.inputs_and_output {
487+
foreign_mentioned_tys.insert(ty);
488+
}
489+
}
490+
_ => continue,
491+
}
492+
}
493+
gacx.foreign_mentioned_tys = foreign_mentioned_tys;
494+
477495
let mut gasn =
478496
GlobalAssignment::new(gacx.num_pointers(), PermissionSet::UNIQUE, FlagSet::empty());
479497
for (ptr, &info) in gacx.ptr_info().iter() {
@@ -482,6 +500,24 @@ fn run(tcx: TyCtxt) {
482500
}
483501
}
484502

503+
// FIX the fields of structs mentioned in extern blocks
504+
for adt_did in &gacx.adt_metadata.struct_dids {
505+
let ty = &tcx.type_of(adt_did);
506+
if gacx.foreign_mentioned_tys.contains(ty) {
507+
if let TyKind::Adt(adt_def, _) = tcx.type_of(adt_did).kind() {
508+
let fields = &adt_def.non_enum_variant().fields;
509+
for field in fields {
510+
let field_lty = gacx.field_ltys[&field.did];
511+
eprintln!(
512+
"adding FIX permission for {adt_did:?} field {:?}",
513+
field.did
514+
);
515+
make_ty_fixed(&mut gasn, field_lty);
516+
}
517+
}
518+
}
519+
}
520+
485521
for info in func_info.values_mut() {
486522
let num_pointers = info.acx_data.num_pointers();
487523
let mut lasn = LocalAssignment::new(num_pointers, PermissionSet::UNIQUE, FlagSet::empty());

c2rust-analyze/src/rewrite/ty.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,15 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for HirTyVisitor<'a, 'tcx> {
473473
#[allow(clippy::single_match)]
474474
match &item.kind {
475475
ItemKind::Struct(VariantData::Struct(field_defs, _), generics) => {
476+
if self
477+
.acx
478+
.gacx
479+
.foreign_mentioned_tys
480+
.contains(&self.acx.tcx().type_of(did))
481+
{
482+
eprintln!("Avoiding rewrite for foreign-mentioned type: {did:?}");
483+
return;
484+
}
476485
let adt_metadata = &self.acx.gacx.adt_metadata.table[&did];
477486
let updated_lifetime_params = &adt_metadata.lifetime_params;
478487

@@ -538,16 +547,14 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for HirTyVisitor<'a, 'tcx> {
538547
f_lty,
539548
field_metadata.origin_args,
540549
&mut |pointer_lty, lifetime_lty, args| {
541-
{
542-
create_rewrite_label(
543-
pointer_lty,
544-
args,
545-
&self.asn.perms(),
546-
&self.asn.flags(),
547-
lifetime_lty.label,
548-
&self.acx.gacx.adt_metadata,
549-
)
550-
}
550+
create_rewrite_label(
551+
pointer_lty,
552+
args,
553+
&self.asn.perms(),
554+
&self.asn.flags(),
555+
lifetime_lty.label,
556+
&self.acx.gacx.adt_metadata,
557+
)
551558
},
552559
);
553560

c2rust-analyze/tests/filecheck.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ define_tests! {
4848
fields,
4949
field_temp,
5050
fixed,
51+
foreign,
5152
insertion_sort,
5253
insertion_sort_driver,
5354
insertion_sort_rewrites,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
extern "Rust" {
2+
fn foo(bar: Alias) -> Baz;
3+
}
4+
5+
type Alias = Bar;
6+
7+
// CHECK-DAG: p: (g1) perms = UNIQUE, flags = FIXED
8+
// CHECK-DAG: p: (g2) perms = UNIQUE, flags = FIXED
9+
10+
// CHECK-DAG: struct Bar
11+
struct Bar {
12+
// CHECK-DAG: p: *mut i32
13+
p: *mut i32
14+
}
15+
16+
// CHECK-DAG: struct Baz
17+
struct Baz {
18+
// CHECK-DAG: p: *mut i32
19+
p: *mut i32
20+
}
21+
22+
// we need something to get rewritten in order
23+
// to check that `Bar` and `Baz` get output
24+
// in the rewrite string
25+
fn fizz(i: *const i32) {}

0 commit comments

Comments
 (0)