Skip to content

Commit 258a3c5

Browse files
author
Grant Wuerker
committed
hacking
1 parent f822ca2 commit 258a3c5

File tree

8 files changed

+114
-47
lines changed

8 files changed

+114
-47
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir-analysis/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ either = "1.8"
1515
derive_more = "0.99"
1616
itertools = "0.10"
1717
ena = "0.14"
18-
18+
indexmap = "1.6.2"
1919
hir = { path = "../hir", package = "fe-hir" }
2020
common = { path = "../common2", package = "fe-common2" }
2121
macros = { path = "../macros", package = "fe-macros" }

crates/hir-analysis/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub struct Jar(
5555
ty::diagnostics::TypeAliasDefDiagAccumulator,
5656
ty::diagnostics::TraitDefDiagAccumulator,
5757
ty::diagnostics::ImplTraitDefDiagAccumulator,
58+
ty::CycleAccumulator,
5859
);
5960

6061
pub trait HirAnalysisDb: salsa::DbWithJar<Jar> + HirDb {

crates/hir-analysis/src/ty/def_analysis.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ use super::{
3434
ty_def::{AdtDef, AdtRefId, TyId},
3535
ty_lower::{lower_adt, lower_hir_ty, lower_kind},
3636
visitor::{walk_ty, TyVisitor},
37+
Cycle,
3738
};
39+
use crate::ty::CycleAccumulator;
3840

3941
/// This function implements analysis for the ADT definition.
4042
/// The analysis includes the following:
@@ -55,8 +57,8 @@ pub fn analyze_adt(db: &dyn HirAnalysisDb, adt_ref: AdtRefId) {
5557
AdtDefDiagAccumulator::push(db, diag);
5658
}
5759

58-
if let Some(diag) = check_recursive_adt(db, adt_ref) {
59-
AdtDefDiagAccumulator::push(db, diag);
60+
if let Some(cycle) = check_recursive_adt(db, adt_ref) {
61+
CycleAccumulator::push(db, cycle);
6062
}
6163
}
6264

@@ -408,10 +410,7 @@ impl<'db> Visitor for DefAnalyzer<'db> {
408410
}
409411

410412
#[salsa::tracked(recovery_fn = check_recursive_adt_impl)]
411-
pub(crate) fn check_recursive_adt(
412-
db: &dyn HirAnalysisDb,
413-
adt: AdtRefId,
414-
) -> Option<TyDiagCollection> {
413+
pub(crate) fn check_recursive_adt(db: &dyn HirAnalysisDb, adt: AdtRefId) -> Option<Cycle> {
415414
let adt_def = lower_adt(db, adt);
416415
for field in adt_def.fields(db) {
417416
for ty in field.iter_types(db) {
@@ -428,7 +427,7 @@ fn check_recursive_adt_impl(
428427
db: &dyn HirAnalysisDb,
429428
cycle: &salsa::Cycle,
430429
adt: AdtRefId,
431-
) -> Option<TyDiagCollection> {
430+
) -> Option<Cycle> {
432431
let participants: FxHashSet<_> = cycle
433432
.participant_keys()
434433
.map(|key| check_recursive_adt::key_from_id(key.key_index()))
@@ -439,11 +438,8 @@ fn check_recursive_adt_impl(
439438
for (ty_idx, ty) in field.iter_types(db).enumerate() {
440439
for field_adt_ref in ty.collect_direct_adts(db) {
441440
if participants.contains(&field_adt_ref) && participants.contains(&adt) {
442-
let diag = TyLowerDiag::recursive_type(
443-
adt.name_span(db),
444-
adt_def.variant_ty_span(db, field_idx, ty_idx),
445-
);
446-
return Some(diag.into());
441+
let cycle = Cycle::new(field_adt_ref, adt);
442+
return Some(cycle);
447443
}
448444
}
449445
}

crates/hir-analysis/src/ty/diagnostics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::HirAnalysisDb;
1212

1313
use super::{
1414
constraint::PredicateId,
15-
ty_def::{Kind, TyId},
15+
ty_def::{AdtRefId, Kind, TyId},
1616
};
1717

1818
#[salsa::accumulator]

crates/hir-analysis/src/ty/mod.rs

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use self::{
55
def_analysis::{analyze_adt, analyze_impl_trait, analyze_trait, analyze_type_alias},
66
diagnostics::{
77
AdtDefDiagAccumulator, ImplTraitDefDiagAccumulator, TraitDefDiagAccumulator,
8-
TypeAliasDefDiagAccumulator,
8+
TyDiagCollection, TyLowerDiag, TypeAliasDefDiagAccumulator,
99
},
1010
ty_def::AdtRefId,
1111
};
@@ -56,12 +56,94 @@ impl<'db> ModuleAnalysisPass for TypeDefAnalysisPass<'db> {
5656
.iter()
5757
.map(|c| AdtRefId::from_contract(self.db, *c)),
5858
);
59+
let mut cycles = vec![];
60+
let mut diags = adts
61+
.flat_map(|adt| {
62+
cycles.append(&mut analyze_adt::accumulated::<CycleAccumulator>(
63+
self.db, adt,
64+
));
65+
analyze_adt::accumulated::<AdtDefDiagAccumulator>(self.db, adt).into_iter()
66+
})
67+
.map(|diag| diag.to_voucher())
68+
.collect();
69+
70+
if cycles.is_empty() {
71+
diags
72+
} else {
73+
merge_cycles(&mut cycles);
74+
// panic!("{:#?}", cycles);
75+
let mut recursive_diags = cycles
76+
.iter()
77+
.map(|cycle| {
78+
let span = cycle.path[0].0.name_span(self.db);
79+
TyDiagCollection::Ty(TyLowerDiag::RecursiveType {
80+
primary_span: span.clone(),
81+
field_span: span,
82+
})
83+
.to_voucher()
84+
})
85+
.collect();
86+
diags.append(&mut recursive_diags);
87+
diags
88+
}
89+
}
90+
}
91+
92+
#[salsa::accumulator]
93+
pub struct CycleAccumulator(pub(super) Cycle);
94+
95+
#[derive(Clone, Debug, Eq, PartialEq)]
96+
pub struct Cycle {
97+
pub path: Vec<(AdtRefId, AdtRefId)>,
98+
}
99+
100+
impl Cycle {
101+
pub fn new(a: AdtRefId, b: AdtRefId) -> Self {
102+
Self { path: vec![(a, b)] }
103+
}
104+
105+
pub fn merge(&mut self, other: &mut Self) {
106+
assert_eq!(self.end(), other.start());
107+
self.path.append(&mut other.path);
108+
}
109+
110+
pub fn is_complete(&self) -> bool {
111+
self.start() == self.end()
112+
}
113+
114+
pub fn start(&self) -> AdtRefId {
115+
self.path[0].0
116+
}
117+
118+
pub fn end(&self) -> AdtRefId {
119+
self.path[self.path.len() - 1].1
120+
}
121+
}
59122

60-
adts.flat_map(|adt| {
61-
analyze_adt::accumulated::<AdtDefDiagAccumulator>(self.db, adt).into_iter()
62-
})
63-
.map(|diag| diag.to_voucher())
64-
.collect()
123+
fn merge_cycles(cycles: &mut Vec<Cycle>) {
124+
let mut complete = false;
125+
126+
while !complete {
127+
complete = true;
128+
129+
for i in 0..cycles.len() {
130+
if !cycles[i].is_complete() {
131+
complete = false;
132+
133+
for j in 0..cycles.len() {
134+
if cycles[i].end() == cycles[j].start() {
135+
let mut j_clone = cycles[j].clone();
136+
cycles[i].merge(&mut j_clone);
137+
cycles.remove(j);
138+
break;
139+
}
140+
}
141+
142+
if !complete {
143+
break;
144+
}
145+
}
146+
}
65147
}
66148
}
67149

crates/uitest/fixtures/ty/def/recursive_type.fe

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ pub struct S5<T> {
2121

2222
pub struct S6 {
2323
s: S5<S6>
24-
}
24+
}
Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,33 @@
11
---
22
source: crates/uitest/tests/ty.rs
33
expression: diags
4-
input_file: crates/uitest/fixtures/ty/recursive_type.fe
4+
input_file: crates/uitest/fixtures/ty/def/recursive_type.fe
55
---
66
error[3-0002]: recursive type is not allowed
77
┌─ recursive_type.fe:1:12
88
99
1pub struct S1 {
10-
│ ^^ recursive type definition
11-
2 │ s: S1
12-
│ -- recursion occurs here
10+
│ ^^
11+
│ │
12+
│ recursive type definition
13+
│ recursion occurs here
1314

1415
error[3-0002]: recursive type is not allowed
1516
┌─ recursive_type.fe:5:12
1617
1718
5 │ pub struct S2 {
18-
│ ^^ recursive type definition
19-
6 │ s: S3
20-
│ -- recursion occurs here
21-
22-
error[3-0002]: recursive type is not allowed
23-
┌─ recursive_type.fe:9:12
24-
25-
9 │ pub struct S3 {
26-
│ ^^ recursive type definition
27-
10 │ s: S4
28-
│ -- recursion occurs here
29-
30-
error[3-0002]: recursive type is not allowed
31-
┌─ recursive_type.fe:13:12
32-
33-
13 │ pub struct S4 {
34-
│ ^^ recursive type definition
35-
14 │ s: S2
36-
│ -- recursion occurs here
19+
│ ^^
20+
│ │
21+
│ recursive type definition
22+
│ recursion occurs here
3723

3824
error[3-0002]: recursive type is not allowed
3925
┌─ recursive_type.fe:22:12
4026
4127
22 │ pub struct S6 {
42-
│ ^^ recursive type definition
43-
23 │ s: S5<S6>
44-
│ ------ recursion occurs here
28+
│ ^^
29+
│ │
30+
│ recursive type definition
31+
│ recursion occurs here
4532

4633

0 commit comments

Comments
 (0)