Skip to content

Commit

Permalink
Attempt to find unreported errors when tainted.
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinleroy committed Mar 19, 2024
1 parent 60e3cdd commit 7df9aa0
Showing 1 changed file with 47 additions and 1 deletion.
48 changes: 47 additions & 1 deletion crates/argus/src/analysis/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use super::{
EvaluationResult,
};
use crate::{
ext::{InferCtxtExt, PredicateExt, TyCtxtExt},
ext::{InferCtxtExt, PredicateExt, TyCtxtExt, TypeckResultsExt},
types::{intermediate::*, *},
};

Expand Down Expand Up @@ -132,6 +132,17 @@ pub fn transform<'a, 'tcx: 'a>(
builder.relate_trait_bounds();
property_is_ok!(builder.is_valid(), "builder is invalid");

// Relating arbitrary errors in the HIR to failed obligations can overwhelm
// guaranteed reported errors. We only want to build these when no other errors
// where found but type-checking failed.
if builder.trait_errors.is_empty()
&& builder.ambiguity_errors.is_empty()
&& builder.typeck_results.tainted_by_errors.is_some()
{
builder.relate_unreported_errors();
property_is_ok!(builder.is_valid(), "builder is invalid");
}

let hir = tcx.hir();
let source_map = tcx.sess.source_map();
let body_range =
Expand Down Expand Up @@ -608,6 +619,41 @@ impl<'a, 'tcx: 'a> ObligationsBuilder<'a, 'tcx> {
))
}

/// Find error nodes in the HIR and search for failed obligation failures in the node.
fn relate_unreported_errors(&mut self) {
// for all error nodes in the HIR, find a binned failure in that same node.
for hir_id in self.typeck_results.error_nodes() {
let Some((eid, _)) =
self.exprs_to_hir_id.iter().find(|(_, hid)| **hid == hir_id)
else {
continue;
};

let expr = &self.exprs[*eid];
let span = self.tcx.hir().span(hir_id);
let range = CharRange::from_span(span, self.tcx.sess.source_map())
.expect("failed to get range for reported trait error");

let hashes = expr
.obligations
.iter()
.filter_map(|&idx| {
let obligation = &self.raw_obligations[idx];
match obligation.result {
Ok(..) => None,
Err(..) => Some(obligation.hash),
}
})
.collect::<Vec<_>>();

self.trait_errors.push(TraitError {
idx: *eid,
range,
hashes,
});
}
}

#[cfg(any(feature = "testing", debug_assertions))]
fn is_valid(&self) -> anyhow::Result<()> {
for obl in self.raw_obligations.iter() {
Expand Down

0 comments on commit 7df9aa0

Please sign in to comment.