Skip to content

Commit 6da0446

Browse files
committed
Fix and intern implementors list, bump to 0.1.18
1 parent 51531cd commit 6da0446

15 files changed

Lines changed: 272 additions & 164 deletions

File tree

crates/argus-cli/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "argus-cli"
3-
version = "0.1.17"
3+
version = "0.1.18"
44
edition = "2021"
55
authors = ["Gavin Gray <gavinleroy6@gmail.com>"]
66
repository = "https://github.com/cognitive-engineering-lab/argus"
@@ -10,8 +10,8 @@ license = "MIT"
1010
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1111

1212
[dependencies]
13-
argus-lib = { version = "0.1.17", path = "../argus" }
14-
argus-ext = { version = "0.1.17", path = "../argus-ext" }
13+
argus-lib = { version = "0.1.18", path = "../argus" }
14+
argus-ext = { version = "0.1.18", path = "../argus-ext" }
1515
rustc_plugin = "=0.13.0-nightly-2025-03-03"
1616

1717
rustc_utils.workspace = true

crates/argus-ext/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "argus-ext"
3-
version = "0.1.17"
3+
version = "0.1.18"
44
edition = "2021"
55
authors = ["Gavin Gray <gavinleroy6@gmail.com>"]
66
repository = "https://github.com/cognitive-engineering-lab/argus"

crates/argus-ext/src/rustc/mod.rs

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,9 @@ pub trait InferCtxtExt<'tcx> {
9494
error: ty::Predicate<'tcx>,
9595
) -> bool;
9696

97-
/// Private in TypeErrorCtxt
98-
fn find_similar_impl_candidates(
97+
fn all_impls(
9998
&self,
100-
trait_pred: ty::PolyTraitPredicate<'tcx>,
99+
def_id: rustc_span::def_id::DefId,
101100
) -> Vec<ImplCandidate<'tcx>>;
102101

103102
/// Public (wrapping for local `CandidateSimilarity`)
@@ -250,13 +249,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
250249
}
251250
}
252251

253-
fn find_similar_impl_candidates(
252+
fn all_impls(
254253
&self,
255-
trait_pred: ty::PolyTraitPredicate<'tcx>,
254+
def_id: rustc_span::def_id::DefId,
256255
) -> Vec<ImplCandidate<'tcx>> {
257-
let mut candidates: Vec<_> = self
256+
self
258257
.tcx
259-
.all_impls(trait_pred.def_id())
258+
.all_impls(def_id)
260259
.filter_map(|def_id| {
261260
let imp = self.tcx.impl_trait_header(def_id).unwrap();
262261

@@ -266,34 +265,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
266265
return None;
267266
}
268267

269-
let imp = imp.trait_ref.skip_binder();
270-
271-
self
272-
.fuzzy_match_tys(
273-
trait_pred.skip_binder().self_ty(),
274-
imp.self_ty(),
275-
false,
276-
)
277-
.map(|similarity| ImplCandidate {
278-
trait_ref: imp,
279-
similarity,
280-
impl_def_id: def_id,
281-
})
268+
Some(ImplCandidate {
269+
trait_ref: imp.trait_ref.skip_binder(),
270+
similarity: CandidateSimilarity::Other,
271+
impl_def_id: def_id,
272+
})
282273
})
283-
.collect();
284-
285-
if candidates
286-
.iter()
287-
.any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }))
288-
{
289-
// If any of the candidates is a perfect match, we don't want to show all of them.
290-
// This is particularly relevant for the case of numeric types (as they all have the
291-
// same category).
292-
candidates
293-
.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. }));
294-
}
295-
296-
candidates
274+
.collect()
297275
}
298276

299277
fn fuzzy_match_tys(

crates/argus-ser-macros/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "argus-ser-macros"
3-
version = "0.1.17"
3+
version = "0.1.18"
44
edition = "2021"
55
authors = ["Gavin Gray <gavinleroy6@gmail.com>"]
66
repository = "https://github.com/cognitive-engineering-lab/argus"

crates/argus-ser/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "argus-ser"
3-
version = "0.1.17"
3+
version = "0.1.18"
44
edition = "2021"
55
authors = ["Gavin Gray <gavinleroy6@gmail.com>"]
66
repository = "https://github.com/cognitive-engineering-lab/argus"
@@ -28,8 +28,8 @@ ts-rs = { version = "7.1.1", features = [
2828
"no-serde-warnings",
2929
], optional = true }
3030

31-
argus-ser-macros = { version = "0.1.17", path = "../argus-ser-macros" }
32-
argus-ext = { version = "0.1.17", path = "../argus-ext" }
31+
argus-ser-macros = { version = "0.1.18", path = "../argus-ser-macros" }
32+
argus-ext = { version = "0.1.18", path = "../argus-ext" }
3333

3434
[dev-dependencies]
3535
argus-ser = { path = ".", features = ["testing"] }

crates/argus-ser/src/interner.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
use std::collections::HashMap; // FIXME: change back to above
21
use std::{
32
cell::RefCell,
43
cmp::{Eq, PartialEq},
54
hash::Hash,
65
};
76

87
use index_vec::{Idx, IndexVec};
9-
// use rustc_data_structures::fx::FxHashMap as HashMap;
8+
use rustc_data_structures::fx::FxHashMap as HashMap;
109
use rustc_middle::ty;
1110

1211
crate::define_idx! {
@@ -62,3 +61,13 @@ where
6261
self.values
6362
}
6463
}
64+
65+
trait FxHashExt {
66+
fn with_capacity(capacity: usize) -> Self;
67+
}
68+
69+
impl<K, V> FxHashExt for HashMap<K, V> {
70+
fn with_capacity(capacity: usize) -> Self {
71+
HashMap::with_capacity_and_hasher(capacity, Default::default())
72+
}
73+
}

crates/argus/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "argus-lib"
3-
version = "0.1.17"
3+
version = "0.1.18"
44
edition = "2021"
55
authors = ["Gavin Gray <gavinleroy6@gmail.com>"]
66
repository = "https://github.com/cognitive-engineering-lab/argus"
@@ -22,8 +22,8 @@ serde.workspace = true
2222
serde_json.workspace = true
2323
itertools.workspace = true
2424

25-
argus-ext = { version = "0.1.17", path = "../argus-ext" }
26-
argus-ser = { version = "0.1.17", path = "../argus-ser" }
25+
argus-ext = { version = "0.1.18", path = "../argus-ext" }
26+
argus-ser = { version = "0.1.18", path = "../argus-ser" }
2727
index_vec = { version = "0.1.3", features = ["serde"] }
2828
smallvec = "1.14.0"
2929
indexmap = { version = "2.2", features = ["serde"] }
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//! Wrapper around `FxHashMap` that implements `ts_rs::TS`
2+
use std::{
3+
fmt::Debug,
4+
ops::{Deref, DerefMut},
5+
};
6+
7+
use rustc_data_structures::fx::FxHashMap;
8+
use serde::Serialize;
9+
#[cfg(feature = "testing")]
10+
use ts_rs::TS;
11+
12+
use super::topology::Idx;
13+
14+
#[cfg(not(feature = "testing"))]
15+
pub trait AllTheThings: Debug + Serialize {}
16+
17+
#[cfg(not(feature = "testing"))]
18+
impl<T> AllTheThings for T where T: Debug + Serialize {}
19+
20+
#[cfg(feature = "testing")]
21+
pub trait AllTheThings: Debug + Serialize + TS {}
22+
23+
#[cfg(feature = "testing")]
24+
impl<T> AllTheThings for T where T: Debug + Serialize + TS {}
25+
26+
#[derive(Clone, Debug, Serialize)]
27+
pub struct HashMap<K: Idx, V: AllTheThings>(FxHashMap<K, V>);
28+
29+
impl<K: Idx, V: AllTheThings> Deref for HashMap<K, V> {
30+
type Target = FxHashMap<K, V>;
31+
32+
fn deref(&self) -> &Self::Target {
33+
&self.0
34+
}
35+
}
36+
37+
impl<K: Idx, V: AllTheThings> DerefMut for HashMap<K, V> {
38+
fn deref_mut(&mut self) -> &mut Self::Target {
39+
&mut self.0
40+
}
41+
}
42+
43+
impl<K: Idx, V: AllTheThings> Default for HashMap<K, V> {
44+
fn default() -> Self {
45+
HashMap(FxHashMap::default())
46+
}
47+
}
48+
49+
#[cfg(feature = "testing")]
50+
impl<K: Idx, V: AllTheThings> TS for HashMap<K, V> {
51+
fn name() -> String {
52+
"Record".to_owned()
53+
}
54+
55+
fn name_with_type_args(args: Vec<String>) -> String {
56+
assert_eq!(
57+
args.len(),
58+
2,
59+
"called HashMap::name_with_type_args with {} args",
60+
args.len()
61+
);
62+
format!("Record<{}, {}>", args[0], args[1])
63+
}
64+
65+
fn inline() -> String {
66+
format!("Record<{}, {}>", K::inline(), V::inline())
67+
}
68+
69+
fn dependencies() -> Vec<ts_rs::Dependency>
70+
where
71+
Self: 'static,
72+
{
73+
[
74+
ts_rs::Dependency::from_ty::<K>(),
75+
ts_rs::Dependency::from_ty::<V>(),
76+
]
77+
.into_iter()
78+
.flatten()
79+
.collect()
80+
}
81+
82+
fn transparent() -> bool {
83+
true
84+
}
85+
}

crates/argus/src/proof_tree/interners.rs

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,18 @@ use crate::{
2828

2929
pub struct Interners {
3030
goals: Interner<(Hash64, ResultIdx), GoalIdx, GoalData>,
31+
implementors: Interner<DefId, ImplementorsIdx, Implementors>,
3132
candidates: Interner<CanKey, CandidateIdx, CandidateData>,
3233
results: Interner<EvaluationResult, ResultIdx, ResultData>,
3334
}
3435

36+
pub struct InternedData {
37+
pub goals: IndexVec<GoalIdx, GoalData>,
38+
pub implementors: IndexVec<ImplementorsIdx, Implementors>,
39+
pub candidates: IndexVec<CandidateIdx, CandidateData>,
40+
pub results: IndexVec<ResultIdx, ResultData>,
41+
}
42+
3543
#[derive(PartialEq, Eq, Hash)]
3644
enum CanKey {
3745
Impl(DefId),
@@ -43,23 +51,19 @@ impl Interners {
4351
pub fn default() -> Self {
4452
Self {
4553
goals: Interner::default(),
54+
implementors: Interner::default(),
4655
candidates: Interner::default(),
4756
results: Interner::default(),
4857
}
4958
}
5059

51-
pub fn take(
52-
self,
53-
) -> (
54-
IndexVec<GoalIdx, GoalData>,
55-
IndexVec<CandidateIdx, CandidateData>,
56-
IndexVec<ResultIdx, ResultData>,
57-
) {
58-
(
59-
self.goals.consume(),
60-
self.candidates.consume(),
61-
self.results.consume(),
62-
)
60+
pub fn take(self) -> InternedData {
61+
InternedData {
62+
goals: self.goals.consume(),
63+
implementors: self.implementors.consume(),
64+
candidates: self.candidates.consume(),
65+
results: self.results.consume(),
66+
}
6367
}
6468

6569
// NOTE: used in `test_utils`.
@@ -74,10 +78,6 @@ impl Interners {
7478
self.candidates.get_data(&c).expect("missing candidate idx")
7579
}
7680

77-
pub fn mk_result_node(&mut self, result: EvaluationResult) -> ProofNode {
78-
ProofNode::pack(ProofNodeUnpacked::Result(self.intern_result(result)))
79-
}
80-
8181
pub fn mk_goal_node(&mut self, goal: &InspectGoal) -> ProofNode {
8282
let infcx = goal.infcx();
8383
let result_idx = self.intern_result(goal.result());
@@ -213,4 +213,63 @@ impl Interners {
213213

214214
self.candidates.insert_no_key(CandidateData::from(string))
215215
}
216+
217+
pub(super) fn intern_implementors(
218+
&mut self,
219+
infcx: &InferCtxt,
220+
def_id: DefId,
221+
tp: ty::PolyTraitPredicate,
222+
) -> ImplementorsIdx {
223+
use argus_ext::{rustc::InferCtxtExt, ty::ImplCandidateExt};
224+
225+
if let Some(i) = self.implementors.get_idx(&def_id) {
226+
return i;
227+
}
228+
229+
let identity_trait_ref =
230+
ty::TraitRef::identity(infcx.tcx, tp.skip_binder().trait_ref.def_id);
231+
232+
let trait_ = ser::TraitRefPrintOnlyTraitPathDef(identity_trait_ref);
233+
let trait_ = tls::unsafe_access_interner(|ty_interner| {
234+
ser::to_value_expect(infcx, ty_interner, &trait_)
235+
});
236+
237+
// Gather all impls
238+
let mut impls = vec![];
239+
let mut inductive_impls = vec![];
240+
241+
let mut impl_candidates = infcx.all_impls(tp.def_id());
242+
243+
// HACK: Sort the `impl_candidates` by the number of *type* parameters. We use this
244+
// as a proxy for complexity, that is, complexity of reading the impl, we want
245+
// to show Argus users "simpler" impls first.
246+
// This probably shouldn't happen here, as it's a concern of the frontend, but this is
247+
// the last place we have all that information.
248+
macro_rules! sort_by_count {
249+
($field:ident, $vec:expr) => {
250+
$vec.sort_by_key(|c| {
251+
infcx.tcx.generics_of(c.impl_def_id).own_counts().$field
252+
})
253+
};
254+
}
255+
sort_by_count!(types, impl_candidates);
256+
sort_by_count!(lifetimes, impl_candidates);
257+
258+
for can in impl_candidates {
259+
let can_idx = self.intern_impl(infcx, can.impl_def_id);
260+
if can.is_inductive(infcx.tcx) {
261+
inductive_impls.push(can_idx);
262+
} else {
263+
impls.push(can_idx);
264+
}
265+
}
266+
267+
let impls = Implementors {
268+
trait_,
269+
impls,
270+
inductive_impls,
271+
};
272+
273+
self.implementors.insert(def_id, impls)
274+
}
216275
}

0 commit comments

Comments
 (0)