Skip to content

Commit 9824e3a

Browse files
committed
fix: propagate the DefId for the owner function of formula_fn and
extern_spec_fn
1 parent 7deba43 commit 9824e3a

5 files changed

Lines changed: 115 additions & 79 deletions

File tree

src/analyze.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ impl<'tcx> Analyzer<'tcx> {
412412
&self,
413413
local_def_id: LocalDefId,
414414
generic_args: mir_ty::GenericArgsRef<'tcx>,
415+
owner_fn_id: DefId,
415416
) -> Option<annot_fn::FormulaFn<'tcx>> {
416417
let deferred_formula_fn = self.formula_fns.get(&local_def_id)?;
417418

@@ -425,6 +426,7 @@ impl<'tcx> Analyzer<'tcx> {
425426
local_def_id,
426427
self.type_params.clone(),
427428
self.system.clone(),
429+
owner_fn_id,
428430
)
429431
.with_generic_args(generic_args)
430432
.with_def_id_cache(self.def_ids());
@@ -548,7 +550,7 @@ impl<'tcx> Analyzer<'tcx> {
548550
&mut self,
549551
local_def_id: LocalDefId,
550552
bb: BasicBlock,
551-
owner_fn_id: DefId
553+
owner_fn_id: DefId,
552554
) -> basic_block::Analyzer<'tcx, '_> {
553555
basic_block::Analyzer::new(self, local_def_id, bb, owner_fn_id)
554556
}
@@ -654,6 +656,7 @@ impl<'tcx> Analyzer<'tcx> {
654656
resolver: T,
655657
self_type_name: Option<String>,
656658
generic_args: mir_ty::GenericArgsRef<'tcx>,
659+
owner_fn_id: DefId,
657660
) -> Option<AnnotFormula<T::Output>>
658661
where
659662
T: Resolver<Output = rty::FunctionParamIdx>,
@@ -684,7 +687,9 @@ impl<'tcx> Analyzer<'tcx> {
684687
if require_annot.is_some() {
685688
unimplemented!();
686689
}
687-
let Some(formula_fn) = self.formula_fn_with_args(formula_def_id, generic_args) else {
690+
let Some(formula_fn) =
691+
self.formula_fn_with_args(formula_def_id, generic_args, owner_fn_id)
692+
else {
688693
panic!(
689694
"require annotation {:?} is not a formula function",
690695
formula_def_id
@@ -703,6 +708,7 @@ impl<'tcx> Analyzer<'tcx> {
703708
resolver: T,
704709
self_type_name: Option<String>,
705710
generic_args: mir_ty::GenericArgsRef<'tcx>,
711+
owner_fn_id: DefId,
706712
) -> Option<AnnotFormula<T::Output>>
707713
where
708714
T: Resolver<Output = rty::RefinedTypeVar<rty::FunctionParamIdx>>,
@@ -734,7 +740,9 @@ impl<'tcx> Analyzer<'tcx> {
734740
if ensure_annot.is_some() {
735741
unimplemented!();
736742
}
737-
let Some(formula_fn) = self.formula_fn_with_args(formula_def_id, generic_args) else {
743+
let Some(formula_fn) =
744+
self.formula_fn_with_args(formula_def_id, generic_args, owner_fn_id)
745+
else {
738746
panic!(
739747
"ensure annotation {:?} is not a formula function",
740748
formula_def_id

src/analyze/annot_fn.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use std::collections::HashMap;
33
use std::rc::Rc;
44

55
use pretty::{termcolor, Pretty};
6-
use rustc_hir::{def_id::LocalDefId, HirId};
6+
use rustc_hir::{
7+
def_id::{DefId, LocalDefId},
8+
HirId,
9+
};
710
use rustc_index::IndexVec;
811
use rustc_middle::ty::{self as mir_ty, TyCtxt, TypeFoldable};
912

@@ -150,6 +153,7 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
150153
local_def_id: LocalDefId,
151154
type_params: Rc<RefCell<TypeParamMap>>,
152155
system: Rc<RefCell<System>>,
156+
owner_fn_id: DefId,
153157
) -> Self {
154158
let body = tcx.hir_body_owned_by(local_def_id);
155159
let generic_args = tcx.mk_args(&[]);
@@ -158,7 +162,7 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
158162
let type_builder = TypeBuilder::new(
159163
tcx,
160164
def_ids.clone(),
161-
local_def_id.to_def_id(),
165+
owner_fn_id,
162166
type_params.clone(),
163167
system.clone(),
164168
);

src/analyze/basic_block.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,10 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
649649
);
650650
}
651651
tracing::info!(?def_id, ?resolved_def_id, ?resolved_args, "resolved");
652-
let Some(def_ty) = self.ctx.def_ty_with_args(resolved_def_id, resolved_args, caller_def_id) else {
652+
let Some(def_ty) = self
653+
.ctx
654+
.def_ty_with_args(resolved_def_id, resolved_args, caller_def_id)
655+
else {
653656
panic!(
654657
"unknown def (resolved): {:?}, args: {:?}",
655658
resolved_def_id, resolved_args

src/analyze/crate_.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,9 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
111111
}
112112
}
113113

114-
let target_def_id = if analyzer.is_annotated_as_extern_spec_fn() {
115-
analyzer.extern_spec_fn_target_def_id()
116-
} else {
117-
local_def_id.to_def_id()
118-
};
119-
114+
let owner_fn_id = analyzer.owner_fn_id;
120115
let expected = analyzer.expected_ty();
121-
self.ctx.register_def(target_def_id, expected);
116+
self.ctx.register_def(owner_fn_id, expected);
122117
}
123118

124119
fn analyze_local_defs(&mut self) {
@@ -140,7 +135,6 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
140135
// check polymorphic function def by replacing type params with some opaque type
141136
// (and this is no-op if the function is mono)
142137
let expected = expected.clone();
143-
tracing::debug!("expected type of {:?} is {:#?}", local_def_id, expected);
144138
let generic_args = self.placeholder_generic_args(*local_def_id);
145139
self.ctx
146140
.local_def_analyzer(*local_def_id)

src/analyze/local_def.rs

Lines changed: 92 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,82 @@ fn stmt_str_literal(stmt: &rustc_hir::Stmt) -> Option<String> {
3737
}
3838
}
3939

40+
fn is_annotated_as_extern_spec_fn_impl(tcx: &TyCtxt, local_def_id: &LocalDefId) -> bool {
41+
tcx.get_attrs_by_path(
42+
local_def_id.to_def_id(),
43+
&analyze::annot::extern_spec_fn_path(),
44+
)
45+
.next()
46+
.is_some()
47+
}
48+
49+
/// Extract the target DefId from `#[thrust::extern_spec_fn]` function.
50+
///
51+
/// The target is identified as the tail call expression (last expression without
52+
/// semicolon) in the function body block.
53+
fn extern_spec_fn_target_def_id_impl<'tcx>(
54+
tcx: &TyCtxt<'tcx>,
55+
local_def_id: &LocalDefId,
56+
mir_body: &Body<'tcx>,
57+
) -> DefId {
58+
let hir_node = tcx.hir_node_by_def_id(*local_def_id);
59+
let hir_body_id = match hir_node {
60+
rustc_hir::Node::Item(item) => {
61+
let rustc_hir::ItemKind::Fn { body: body_id, .. } = item.kind else {
62+
panic!("extern_spec_fn must be a function");
63+
};
64+
body_id
65+
}
66+
rustc_hir::Node::ImplItem(impl_item) => {
67+
let rustc_hir::ImplItemKind::Fn(_, body_id) = impl_item.kind else {
68+
panic!("extern_spec_fn must be a function");
69+
};
70+
body_id
71+
}
72+
rustc_hir::Node::TraitItem(trait_item) => {
73+
let rustc_hir::TraitItemKind::Fn(_, rustc_hir::TraitFn::Provided(body_id)) =
74+
trait_item.kind
75+
else {
76+
panic!("extern_spec_fn must be a function with a body");
77+
};
78+
body_id
79+
}
80+
_ => panic!("extern_spec_fn must be a function item or impl item"),
81+
};
82+
83+
let hir_body = tcx.hir_body(hir_body_id);
84+
85+
// The body is a block; the tail expression is the function call to the target.
86+
let rustc_hir::ExprKind::Block(block, _) = &hir_body.value.kind else {
87+
panic!("extern_spec_fn body must be a block");
88+
};
89+
let tail_expr = block
90+
.expr
91+
.expect("extern_spec_fn block must end with a tail call expression");
92+
93+
let rustc_hir::ExprKind::Call(func_expr, _) = &tail_expr.kind else {
94+
panic!("extern_spec_fn tail expression must be a function call");
95+
};
96+
let rustc_hir::ExprKind::Path(qpath) = &func_expr.kind else {
97+
panic!("extern_spec_fn call must be a path expression");
98+
};
99+
100+
let typeck_result = tcx.typeck(local_def_id);
101+
let hir_id = func_expr.hir_id;
102+
let rustc_hir::def::Res::Def(_, def_id) = typeck_result.qpath_res(qpath, hir_id) else {
103+
panic!("extern_spec_fn call must resolve to a definition");
104+
};
105+
106+
let args = typeck_result.node_args(hir_id);
107+
let typing_env = mir_body.typing_env(*tcx);
108+
let instance = mir_ty::Instance::try_resolve(*tcx, typing_env, def_id, args).unwrap();
109+
if let Some(instance) = instance {
110+
instance.def_id()
111+
} else {
112+
def_id
113+
}
114+
}
115+
40116
/// An implementation of the typing of local definitions.
41117
///
42118
/// The current implementation only applies to function definitions. The entry point is
@@ -46,6 +122,7 @@ pub struct Analyzer<'tcx, 'ctx> {
46122
tcx: TyCtxt<'tcx>,
47123

48124
local_def_id: LocalDefId,
125+
pub owner_fn_id: DefId,
49126

50127
body: Body<'tcx>,
51128
/// to substitute HIR types during translation in [`crate::analyze::annot_fn`]
@@ -201,13 +278,7 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
201278
}
202279

203280
pub fn is_annotated_as_extern_spec_fn(&self) -> bool {
204-
self.tcx
205-
.get_attrs_by_path(
206-
self.local_def_id.to_def_id(),
207-
&analyze::annot::extern_spec_fn_path(),
208-
)
209-
.next()
210-
.is_some()
281+
is_annotated_as_extern_spec_fn_impl(&self.tcx, &self.local_def_id)
211282
}
212283

213284
pub fn is_annotated_as_predicate(&self) -> bool {
@@ -318,7 +389,8 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
318389
.associated_item(self.local_def_id.to_def_id())
319390
.trait_item_def_id
320391
.unwrap();
321-
self.ctx.def_ty_with_args(trait_item_did, trait_ref.args, trait_ref.def_id)
392+
self.ctx
393+
.def_ty_with_args(trait_item_did, trait_ref.args, trait_ref.def_id)
322394
}
323395

324396
// Note that we do not expect predicate variables to be generated here
@@ -358,13 +430,15 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
358430
&param_resolver,
359431
self_type_name.clone(),
360432
self.generic_args,
433+
self.owner_fn_id,
361434
);
362435

363436
let mut ensure_annot = self.ctx.extract_ensure_annot(
364437
self.local_def_id,
365438
&result_param_resolver,
366439
self_type_name.clone(),
367440
self.generic_args,
441+
self.owner_fn_id,
368442
);
369443

370444
if let Some(trait_item_id) = self.local_trait_item_id() {
@@ -374,12 +448,14 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
374448
&param_resolver,
375449
self_type_name.clone(),
376450
self.generic_args,
451+
self.owner_fn_id,
377452
);
378453
let trait_ensure_annot = self.ctx.extract_ensure_annot(
379454
trait_item_id,
380455
&result_param_resolver,
381456
self_type_name.clone(),
382457
self.generic_args,
458+
self.owner_fn_id,
383459
);
384460

385461
assert!(require_annot.is_none() || trait_require_annot.is_none());
@@ -447,62 +523,7 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
447523
/// The target is identified as the tail call expression (last expression without
448524
/// semicolon) in the function body block.
449525
pub fn extern_spec_fn_target_def_id(&self) -> DefId {
450-
let node = self.tcx.hir_node_by_def_id(self.local_def_id);
451-
let body_id = match node {
452-
rustc_hir::Node::Item(item) => {
453-
let rustc_hir::ItemKind::Fn { body: body_id, .. } = item.kind else {
454-
panic!("extern_spec_fn must be a function");
455-
};
456-
body_id
457-
}
458-
rustc_hir::Node::ImplItem(impl_item) => {
459-
let rustc_hir::ImplItemKind::Fn(_, body_id) = impl_item.kind else {
460-
panic!("extern_spec_fn must be a function");
461-
};
462-
body_id
463-
}
464-
rustc_hir::Node::TraitItem(trait_item) => {
465-
let rustc_hir::TraitItemKind::Fn(_, rustc_hir::TraitFn::Provided(body_id)) =
466-
trait_item.kind
467-
else {
468-
panic!("extern_spec_fn must be a function with a body");
469-
};
470-
body_id
471-
}
472-
_ => panic!("extern_spec_fn must be a function item or impl item"),
473-
};
474-
475-
let body = self.tcx.hir_body(body_id);
476-
477-
// The body is a block; the tail expression is the function call to the target.
478-
let rustc_hir::ExprKind::Block(block, _) = &body.value.kind else {
479-
panic!("extern_spec_fn body must be a block");
480-
};
481-
let tail_expr = block
482-
.expr
483-
.expect("extern_spec_fn block must end with a tail call expression");
484-
485-
let rustc_hir::ExprKind::Call(func_expr, _) = &tail_expr.kind else {
486-
panic!("extern_spec_fn tail expression must be a function call");
487-
};
488-
let rustc_hir::ExprKind::Path(qpath) = &func_expr.kind else {
489-
panic!("extern_spec_fn call must be a path expression");
490-
};
491-
492-
let typeck_result = self.tcx.typeck(self.local_def_id);
493-
let hir_id = func_expr.hir_id;
494-
let rustc_hir::def::Res::Def(_, def_id) = typeck_result.qpath_res(qpath, hir_id) else {
495-
panic!("extern_spec_fn call must resolve to a definition");
496-
};
497-
498-
let args = typeck_result.node_args(hir_id);
499-
let typing_env = self.body.typing_env(self.tcx);
500-
let instance = mir_ty::Instance::try_resolve(self.tcx, typing_env, def_id, args).unwrap();
501-
if let Some(instance) = instance {
502-
instance.def_id()
503-
} else {
504-
def_id
505-
}
526+
extern_spec_fn_target_def_id_impl(&self.tcx, &self.local_def_id, &self.body)
506527
}
507528

508529
fn is_mut_param(&self, param_idx: rty::FunctionParamIdx) -> bool {
@@ -973,12 +994,18 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
973994
let tcx = ctx.tcx;
974995
let body = tcx.optimized_mir(local_def_id.to_def_id()).clone();
975996
let drop_points = Default::default();
976-
let type_builder = ctx.type_builder(ctx.def_ids(), local_def_id.to_def_id());
997+
let owner_fn_id = if is_annotated_as_extern_spec_fn_impl(&tcx, &local_def_id) {
998+
extern_spec_fn_target_def_id_impl(&tcx, &local_def_id, &body)
999+
} else {
1000+
local_def_id.to_def_id()
1001+
};
1002+
let type_builder = ctx.type_builder(ctx.def_ids(), owner_fn_id);
9771003
let generic_args = tcx.mk_args(&[]);
9781004
Self {
9791005
ctx,
9801006
tcx,
9811007
local_def_id,
1008+
owner_fn_id,
9821009
body,
9831010
generic_args,
9841011
drop_points,

0 commit comments

Comments
 (0)