rapx/analysis/core/api_dependency/
extract.rs1extern crate rustc_infer;
2use crate::rap_debug;
3use rustc_hir::def_id::DefId;
4use rustc_infer::infer::region_constraints::{Constraint, ConstraintKind};
5use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
6use rustc_infer::traits::ObligationCause;
7use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypingMode};
8
9use rustc_span::Span;
10struct FreeVarFolder<'tcx, 'a> {
11 cx: TyCtxt<'tcx>,
12 free_var_cnt: usize,
13 infcx: &'a InferCtxt<'tcx>,
14 span: Span,
15}
16
17impl<'tcx, 'a> FreeVarFolder<'tcx, 'a> {
18 pub fn new(
19 cx: TyCtxt<'tcx>,
20 infcx: &'a InferCtxt<'tcx>,
21 span: Span,
22 ) -> FreeVarFolder<'tcx, 'a> {
23 FreeVarFolder {
24 cx,
25 free_var_cnt: 0,
26 infcx,
27 span,
28 }
29 }
30}
31
32impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for FreeVarFolder<'tcx, '_> {
33 fn cx(&self) -> TyCtxt<'tcx> {
34 self.cx
35 }
36 fn fold_region(&mut self, _: ty::Region<'tcx>) -> ty::Region<'tcx> {
37 self.free_var_cnt += 1;
38 self.infcx
39 .next_region_var(infer::RegionVariableOrigin::BorrowRegion(self.span))
40 }
41}
42
43fn region_vid_str(vid: ty::RegionVid) -> String {
44 format!("{:?}", vid)
45}
46
47fn region_str<'tcx>(tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>) -> String {
48 region.get_name_or_anon(tcx).to_string()
49}
50
51fn constraint_str<'tcx>(constraint: Constraint<'tcx>, tcx: TyCtxt<'tcx>) -> String {
52 let (a, b) = match constraint.kind {
53 ConstraintKind::VarSubVar => (
54 region_vid_str(constraint.sub.as_var()),
55 region_vid_str(constraint.sup.as_var()),
56 ),
57 ConstraintKind::RegSubVar => (
58 region_str(tcx, constraint.sub),
59 region_vid_str(constraint.sup.as_var()),
60 ),
61 ConstraintKind::VarSubReg => (
62 region_vid_str(constraint.sub.as_var()),
63 region_str(tcx, constraint.sup),
64 ),
65 ConstraintKind::RegSubReg => (
66 region_str(tcx, constraint.sub),
67 region_str(tcx, constraint.sup),
68 ),
69 };
70 format!("{} <= {}", a, b)
71}
72
73pub fn extract_constraints(fn_did: DefId, tcx: TyCtxt<'_>) {
74 let early_fn_sig = tcx.fn_sig(fn_did);
75 let span = tcx.def_span(fn_did);
76 let binder_fn_sig = early_fn_sig.instantiate_identity();
77
78 let param_env = tcx.param_env(fn_did);
79 rap_debug!("param_env: {param_env:?}");
80
81 let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
83 let mut folder = FreeVarFolder::new(tcx, &infcx, span);
84 let fn_sig = tcx.liberate_late_bound_regions(fn_did, binder_fn_sig);
85 let binder_with_free_vars = fn_sig.fold_with(&mut folder);
86
87 let res = infcx
88 .at(&ObligationCause::dummy(), param_env)
89 .sub(infer::DefineOpaqueTypes::Yes, fn_sig, binder_with_free_vars)
90 .unwrap();
91 res.obligations.into_iter().for_each(|obligation| {
92 rap_debug!("obligation: {obligation:?}");
93 });
94
95 rap_debug!("free binder: {binder_with_free_vars:?}");
97 let region_constraint_data = infcx.take_and_reset_region_constraints();
98 for (constraint, _origin) in region_constraint_data.constraints {
99 rap_debug!("constraint: {}", constraint_str(constraint, tcx));
100 }
101}