Skip to content

Commit 2f6c77f

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

4 files changed

Lines changed: 99 additions & 77 deletions

File tree

src/analyze.rs

Lines changed: 6 additions & 2 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());
@@ -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,7 @@ 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) = self.formula_fn_with_args(formula_def_id, generic_args, owner_fn_id) else {
688691
panic!(
689692
"require annotation {:?} is not a formula function",
690693
formula_def_id
@@ -703,6 +706,7 @@ impl<'tcx> Analyzer<'tcx> {
703706
resolver: T,
704707
self_type_name: Option<String>,
705708
generic_args: mir_ty::GenericArgsRef<'tcx>,
709+
owner_fn_id: DefId
706710
) -> Option<AnnotFormula<T::Output>>
707711
where
708712
T: Resolver<Output = rty::RefinedTypeVar<rty::FunctionParamIdx>>,
@@ -734,7 +738,7 @@ impl<'tcx> Analyzer<'tcx> {
734738
if ensure_annot.is_some() {
735739
unimplemented!();
736740
}
737-
let Some(formula_fn) = self.formula_fn_with_args(formula_def_id, generic_args) else {
741+
let Some(formula_fn) = self.formula_fn_with_args(formula_def_id, generic_args, owner_fn_id) else {
738742
panic!(
739743
"ensure annotation {:?} is not a formula function",
740744
formula_def_id

src/analyze/annot_fn.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ 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::{def_id::{LocalDefId, DefId}, HirId};
77
use rustc_index::IndexVec;
88
use rustc_middle::ty::{self as mir_ty, TyCtxt, TypeFoldable};
99

@@ -150,6 +150,7 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
150150
local_def_id: LocalDefId,
151151
type_params: Rc<RefCell<TypeParamMap>>,
152152
system: Rc<RefCell<System>>,
153+
owner_fn_id: DefId,
153154
) -> Self {
154155
let body = tcx.hir_body_owned_by(local_def_id);
155156
let generic_args = tcx.mk_args(&[]);
@@ -158,7 +159,7 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
158159
let type_builder = TypeBuilder::new(
159160
tcx,
160161
def_ids.clone(),
161-
local_def_id.to_def_id(),
162+
owner_fn_id,
162163
type_params.clone(),
163164
system.clone(),
164165
);

src/analyze/crate_.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,10 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
110110
return;
111111
}
112112
}
113-
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-
113+
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: 87 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,79 @@ fn stmt_str_literal(stmt: &rustc_hir::Stmt) -> Option<String> {
3737
}
3838
}
3939

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

48121
local_def_id: LocalDefId,
122+
pub owner_fn_id: DefId,
49123

50124
body: Body<'tcx>,
51125
/// to substitute HIR types during translation in [`crate::analyze::annot_fn`]
@@ -201,13 +275,7 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
201275
}
202276

203277
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()
278+
is_annotated_as_extern_spec_fn_impl(&self.tcx, &self.local_def_id)
211279
}
212280

213281
pub fn is_annotated_as_predicate(&self) -> bool {
@@ -358,13 +426,15 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
358426
&param_resolver,
359427
self_type_name.clone(),
360428
self.generic_args,
429+
self.owner_fn_id,
361430
);
362431

363432
let mut ensure_annot = self.ctx.extract_ensure_annot(
364433
self.local_def_id,
365434
&result_param_resolver,
366435
self_type_name.clone(),
367436
self.generic_args,
437+
self.owner_fn_id,
368438
);
369439

370440
if let Some(trait_item_id) = self.local_trait_item_id() {
@@ -374,12 +444,14 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
374444
&param_resolver,
375445
self_type_name.clone(),
376446
self.generic_args,
447+
self.owner_fn_id,
377448
);
378449
let trait_ensure_annot = self.ctx.extract_ensure_annot(
379450
trait_item_id,
380451
&result_param_resolver,
381452
self_type_name.clone(),
382453
self.generic_args,
454+
self.owner_fn_id,
383455
);
384456

385457
assert!(require_annot.is_none() || trait_require_annot.is_none());
@@ -447,62 +519,7 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
447519
/// The target is identified as the tail call expression (last expression without
448520
/// semicolon) in the function body block.
449521
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-
}
522+
extern_spec_fn_target_def_id_impl(&self.tcx, &self.local_def_id, &self.body)
506523
}
507524

508525
fn is_mut_param(&self, param_idx: rty::FunctionParamIdx) -> bool {
@@ -973,12 +990,18 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
973990
let tcx = ctx.tcx;
974991
let body = tcx.optimized_mir(local_def_id.to_def_id()).clone();
975992
let drop_points = Default::default();
976-
let type_builder = ctx.type_builder(ctx.def_ids(), local_def_id.to_def_id());
993+
let owner_fn_id = if is_annotated_as_extern_spec_fn_impl(&tcx, &local_def_id) {
994+
extern_spec_fn_target_def_id_impl(&tcx, &local_def_id, &body)
995+
} else {
996+
local_def_id.to_def_id()
997+
};
998+
let type_builder = ctx.type_builder(ctx.def_ids(), owner_fn_id);
977999
let generic_args = tcx.mk_args(&[]);
9781000
Self {
9791001
ctx,
9801002
tcx,
9811003
local_def_id,
1004+
owner_fn_id,
9821005
body,
9831006
generic_args,
9841007
drop_points,

0 commit comments

Comments
 (0)