1
+ use std:: collections:: LinkedList ;
2
+
1
3
use crate :: HirAnalysisDb ;
2
- use hir:: { analysis_pass:: ModuleAnalysisPass , hir_def:: TopLevelMod } ;
4
+ use hir:: {
5
+ analysis_pass:: ModuleAnalysisPass ,
6
+ hir_def:: { FieldDef , FieldDefListId , TopLevelMod } ,
7
+ span:: DynLazySpan ,
8
+ } ;
9
+ use indexmap:: { indexmap, indexset, IndexMap } ;
3
10
4
11
use self :: {
5
12
def_analysis:: {
@@ -11,7 +18,7 @@ use self::{
11
18
ImplTraitDefDiagAccumulator , TraitDefDiagAccumulator , TyDiagCollection , TyLowerDiag ,
12
19
TypeAliasDefDiagAccumulator ,
13
20
} ,
14
- ty_def:: AdtRefId ,
21
+ ty_def:: { AdtField , AdtRefId } ,
15
22
} ;
16
23
17
24
pub mod constraint_solver;
@@ -64,9 +71,9 @@ impl<'db> ModuleAnalysisPass for TypeDefAnalysisPass<'db> {
64
71
let mut cycles = vec ! [ ] ;
65
72
let mut diags = adts
66
73
. flat_map ( |adt| {
67
- cycles. append ( & mut analyze_adt:: accumulated :: < CycleAccumulator > (
68
- self . db , adt ,
69
- ) ) ;
74
+ cycles. append ( & mut analyze_adt:: accumulated :: <
75
+ RecursiveAdtConstituentAccumulator ,
76
+ > ( self . db , adt ) ) ;
70
77
analyze_adt:: accumulated :: < AdtDefDiagAccumulator > ( self . db , adt) . into_iter ( )
71
78
} )
72
79
. map ( |diag| diag. to_voucher ( ) )
@@ -75,75 +82,67 @@ impl<'db> ModuleAnalysisPass for TypeDefAnalysisPass<'db> {
75
82
if cycles. is_empty ( ) {
76
83
diags
77
84
} else {
78
- merge_cycles ( & mut cycles) ;
79
- // panic!("{:#?}", cycles);
80
- let mut recursive_diags = cycles
81
- . iter ( )
82
- . map ( |cycle| {
83
- let span = cycle. path [ 0 ] . 0 . name_span ( self . db ) ;
84
- TyDiagCollection :: Ty ( TyLowerDiag :: RecursiveType ) . to_voucher ( )
85
- } )
86
- . collect ( ) ;
87
- diags. append ( & mut recursive_diags) ;
85
+ diags. append (
86
+ & mut recursive_adt_diags ( & cycles)
87
+ . into_iter ( )
88
+ . map ( |constituent| TyDiagCollection :: Ty ( constituent) . to_voucher ( ) )
89
+ . collect ( ) ,
90
+ ) ;
88
91
diags
89
92
}
90
93
}
91
94
}
92
95
93
96
#[ salsa:: accumulator]
94
- pub struct CycleAccumulator ( pub ( super ) Cycle ) ;
95
-
96
- #[ derive( Clone , Debug , Eq , PartialEq ) ]
97
- pub struct Cycle {
98
- pub path : Vec < ( AdtRefId , AdtRefId ) > ,
99
- }
100
-
101
- impl Cycle {
102
- pub fn new ( a : AdtRefId , b : AdtRefId ) -> Self {
103
- Self { path : vec ! [ ( a, b) ] }
104
- }
105
-
106
- pub fn merge ( & mut self , other : & mut Self ) {
107
- assert_eq ! ( self . end( ) , other. start( ) ) ;
108
- self . path . append ( & mut other. path ) ;
109
- }
110
-
111
- pub fn is_complete ( & self ) -> bool {
112
- self . start ( ) == self . end ( )
113
- }
97
+ pub struct RecursiveAdtConstituentAccumulator ( pub ( super ) AdtRecursionConstituent ) ;
98
+
99
+ pub fn recursive_adt_diags ( constituents : & [ AdtRecursionConstituent ] ) -> Vec < TyLowerDiag > {
100
+ let mut diags = vec ! [ ] ;
101
+ let mut unified_constituents = indexset ! { } ;
102
+
103
+ while let Some ( mut cur) =
104
+ ( 0 ..constituents. len ( ) ) . find ( |index| !unified_constituents. contains ( index) )
105
+ {
106
+ unified_constituents. insert ( cur) ;
107
+ let mut recursion = vec ! [ cur] ;
108
+
109
+ while constituents[ recursion[ 0 ] ] . from . 0 != constituents[ cur] . to {
110
+ if let Some ( index) = ( 0 ..constituents. len ( ) ) . find ( |index| {
111
+ !unified_constituents. contains ( index)
112
+ && constituents[ cur] . to == constituents[ * index] . from . 0
113
+ } ) {
114
+ cur = index;
115
+ unified_constituents. insert ( index) ;
116
+ recursion. push ( index) ;
117
+ } else {
118
+ break ;
119
+ } ;
120
+ }
114
121
115
- pub fn start ( & self ) -> AdtRefId {
116
- self . path [ 0 ] . 0
122
+ diags. push ( TyLowerDiag :: recursive_type (
123
+ recursion
124
+ . iter ( )
125
+ . map ( |index| constituents[ * index] . to_owned ( ) )
126
+ . collect ( ) ,
127
+ ) ) ;
117
128
}
118
129
119
- pub fn end ( & self ) -> AdtRefId {
120
- self . path [ self . path . len ( ) - 1 ] . 1
121
- }
130
+ diags
122
131
}
123
132
124
- fn merge_cycles ( cycles : & mut Vec < Cycle > ) {
125
- let mut complete = false ;
126
-
127
- while !complete {
128
- complete = true ;
129
-
130
- for i in 0 ..cycles. len ( ) {
131
- if !cycles[ i] . is_complete ( ) {
132
- complete = false ;
133
-
134
- for j in 0 ..cycles. len ( ) {
135
- if cycles[ i] . end ( ) == cycles[ j] . start ( ) {
136
- let mut j_clone = cycles[ j] . clone ( ) ;
137
- cycles[ i] . merge ( & mut j_clone) ;
138
- cycles. remove ( j) ;
139
- break ;
140
- }
141
- }
133
+ #[ derive( Clone , Debug , Eq , PartialEq , Hash ) ]
134
+ pub struct AdtRecursionConstituent {
135
+ pub from : ( AdtRefId , DynLazySpan ) ,
136
+ pub to : AdtRefId ,
137
+ pub field_span : DynLazySpan ,
138
+ }
142
139
143
- if !complete {
144
- break ;
145
- }
146
- }
140
+ impl AdtRecursionConstituent {
141
+ pub fn new ( from : ( AdtRefId , DynLazySpan ) , to : AdtRefId , field_span : DynLazySpan ) -> Self {
142
+ Self {
143
+ from,
144
+ to,
145
+ field_span,
147
146
}
148
147
}
149
148
}
0 commit comments