Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 64 additions & 8 deletions src/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,24 @@ impl<'tcx> ReplacePlacesVisitor<'tcx> {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum DeferredDefMode {
Analyze,
NoAnalyze,
}

impl DeferredDefMode {
fn should_analyze(&self) -> bool {
matches!(self, DeferredDefMode::Analyze)
}
}

#[derive(Debug, Clone)]
struct DeferredDefTy<'tcx> {
// this is different from a key in defs when the def is extern_spec_fn
local_def_id: LocalDefId,
cache: Rc<RefCell<HashMap<mir_ty::GenericArgsRef<'tcx>, rty::RefinedType>>>,
mode: DeferredDefMode,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -290,12 +305,40 @@ impl<'tcx> Analyzer<'tcx> {
self.defs.insert(def_id, DefTy::Concrete(rty));
}

pub fn register_deferred_def(&mut self, def_id: DefId) {
tracing::info!(def_id = ?def_id, "register_deferred_def");
pub fn register_deferred_def(&mut self, local_def_id: LocalDefId) {
self.register_deferred_def_impl(
local_def_id.to_def_id(),
local_def_id,
DeferredDefMode::Analyze,
);
}

pub fn register_deferred_def_without_analysis(
&mut self,
target_def_id: DefId,
local_def_id: LocalDefId,
) {
self.register_deferred_def_impl(target_def_id, local_def_id, DeferredDefMode::NoAnalyze);
}

fn register_deferred_def_impl(
&mut self,
target_def_id: DefId,
local_def_id: LocalDefId,
mode: DeferredDefMode,
) {
tracing::info!(
?target_def_id,
?local_def_id,
?mode,
"register_deferred_def"
);
self.defs.insert(
def_id,
target_def_id,
DefTy::Deferred(DeferredDefTy {
local_def_id,
cache: Rc::new(RefCell::new(HashMap::new())),
mode,
}),
);
}
Expand All @@ -312,10 +355,10 @@ impl<'tcx> Analyzer<'tcx> {
def_id: DefId,
generic_args: mir_ty::GenericArgsRef<'tcx>,
) -> Option<rty::RefinedType> {
let type_builder = TypeBuilder::new(self.tcx, def_id);

let deferred_ty = match self.defs.get(&def_id)? {
DefTy::Concrete(rty) => {
let type_builder = TypeBuilder::new(self.tcx, def_id);

let mut def_ty = rty.clone();
def_ty.instantiate_ty_params(
generic_args
Expand All @@ -333,16 +376,29 @@ impl<'tcx> Analyzer<'tcx> {
if let Some(rty) = deferred_ty_cache.borrow().get(&generic_args) {
return Some(rty.clone());
}
let deferred_ty_mode = deferred_ty.mode;

let mut analyzer = self.local_def_analyzer(def_id.as_local()?);
let mut analyzer = self.local_def_analyzer(deferred_ty.local_def_id);
analyzer.generic_args(generic_args);

let expected = analyzer.expected_ty();
let mut expected = analyzer.expected_ty();
// parameters in annotations are left as params
// TODO: remove this after annotation V2
expected.instantiate_ty_params(
generic_args
.types()
.map(|ty| type_builder.build(ty))
.map(rty::RefinedType::unrefined)
.collect(),
);
deferred_ty_cache
.borrow_mut()
.insert(generic_args, expected.clone());
tracing::info!(?def_id, rty = %expected.display(), ?generic_args, "deferred def");

analyzer.run(&expected);
if deferred_ty_mode.should_analyze() {
analyzer.run(&expected);
}
Some(expected)
}

Expand Down
20 changes: 13 additions & 7 deletions src/analyze/crate_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,22 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
return;
}

let target_def_id = if analyzer.is_annotated_as_extern_spec_fn() {
analyzer.extern_spec_fn_target_def_id()
} else {
local_def_id.to_def_id()
};

use mir_ty::TypeVisitableExt as _;
if sig.has_param() && !analyzer.is_fully_annotated() {
self.ctx.register_deferred_def(local_def_id.to_def_id());
if sig.has_param() {
if self.skip_analysis.contains(&local_def_id) {
self.ctx
.register_deferred_def_without_analysis(target_def_id, local_def_id);
} else {
self.ctx.register_deferred_def(local_def_id);
}
} else {
let expected = analyzer.expected_ty();
let target_def_id = if analyzer.is_annotated_as_extern_spec_fn() {
analyzer.extern_spec_fn_target_def_id()
} else {
local_def_id.to_def_id()
};
self.ctx.register_def(target_def_id, expected);
}
}
Expand Down