Skip to content

Commit

Permalink
hacking
Browse files Browse the repository at this point in the history
  • Loading branch information
Grant Wuerker committed Nov 28, 2023
1 parent f822ca2 commit 258a3c5
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 47 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/hir-analysis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ either = "1.8"
derive_more = "0.99"
itertools = "0.10"
ena = "0.14"

indexmap = "1.6.2"
hir = { path = "../hir", package = "fe-hir" }
common = { path = "../common2", package = "fe-common2" }
macros = { path = "../macros", package = "fe-macros" }
Expand Down
1 change: 1 addition & 0 deletions crates/hir-analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub struct Jar(
ty::diagnostics::TypeAliasDefDiagAccumulator,
ty::diagnostics::TraitDefDiagAccumulator,
ty::diagnostics::ImplTraitDefDiagAccumulator,
ty::CycleAccumulator,
);

pub trait HirAnalysisDb: salsa::DbWithJar<Jar> + HirDb {
Expand Down
20 changes: 8 additions & 12 deletions crates/hir-analysis/src/ty/def_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ use super::{
ty_def::{AdtDef, AdtRefId, TyId},
ty_lower::{lower_adt, lower_hir_ty, lower_kind},
visitor::{walk_ty, TyVisitor},
Cycle,
};
use crate::ty::CycleAccumulator;

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

if let Some(diag) = check_recursive_adt(db, adt_ref) {
AdtDefDiagAccumulator::push(db, diag);
if let Some(cycle) = check_recursive_adt(db, adt_ref) {
CycleAccumulator::push(db, cycle);
}
}

Expand Down Expand Up @@ -408,10 +410,7 @@ impl<'db> Visitor for DefAnalyzer<'db> {
}

#[salsa::tracked(recovery_fn = check_recursive_adt_impl)]
pub(crate) fn check_recursive_adt(
db: &dyn HirAnalysisDb,
adt: AdtRefId,
) -> Option<TyDiagCollection> {
pub(crate) fn check_recursive_adt(db: &dyn HirAnalysisDb, adt: AdtRefId) -> Option<Cycle> {
let adt_def = lower_adt(db, adt);
for field in adt_def.fields(db) {
for ty in field.iter_types(db) {
Expand All @@ -428,7 +427,7 @@ fn check_recursive_adt_impl(
db: &dyn HirAnalysisDb,
cycle: &salsa::Cycle,
adt: AdtRefId,
) -> Option<TyDiagCollection> {
) -> Option<Cycle> {
let participants: FxHashSet<_> = cycle
.participant_keys()
.map(|key| check_recursive_adt::key_from_id(key.key_index()))
Expand All @@ -439,11 +438,8 @@ fn check_recursive_adt_impl(
for (ty_idx, ty) in field.iter_types(db).enumerate() {
for field_adt_ref in ty.collect_direct_adts(db) {
if participants.contains(&field_adt_ref) && participants.contains(&adt) {
let diag = TyLowerDiag::recursive_type(
adt.name_span(db),
adt_def.variant_ty_span(db, field_idx, ty_idx),
);
return Some(diag.into());
let cycle = Cycle::new(field_adt_ref, adt);
return Some(cycle);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-analysis/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::HirAnalysisDb;

use super::{
constraint::PredicateId,
ty_def::{Kind, TyId},
ty_def::{AdtRefId, Kind, TyId},
};

#[salsa::accumulator]
Expand Down
94 changes: 88 additions & 6 deletions crates/hir-analysis/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use self::{
def_analysis::{analyze_adt, analyze_impl_trait, analyze_trait, analyze_type_alias},
diagnostics::{
AdtDefDiagAccumulator, ImplTraitDefDiagAccumulator, TraitDefDiagAccumulator,
TypeAliasDefDiagAccumulator,
TyDiagCollection, TyLowerDiag, TypeAliasDefDiagAccumulator,
},
ty_def::AdtRefId,
};
Expand Down Expand Up @@ -56,12 +56,94 @@ impl<'db> ModuleAnalysisPass for TypeDefAnalysisPass<'db> {
.iter()
.map(|c| AdtRefId::from_contract(self.db, *c)),
);
let mut cycles = vec![];
let mut diags = adts
.flat_map(|adt| {
cycles.append(&mut analyze_adt::accumulated::<CycleAccumulator>(
self.db, adt,
));
analyze_adt::accumulated::<AdtDefDiagAccumulator>(self.db, adt).into_iter()
})
.map(|diag| diag.to_voucher())
.collect();

if cycles.is_empty() {
diags
} else {
merge_cycles(&mut cycles);
// panic!("{:#?}", cycles);
let mut recursive_diags = cycles
.iter()
.map(|cycle| {
let span = cycle.path[0].0.name_span(self.db);
TyDiagCollection::Ty(TyLowerDiag::RecursiveType {
primary_span: span.clone(),
field_span: span,
})
.to_voucher()
})
.collect();
diags.append(&mut recursive_diags);
diags
}
}
}

#[salsa::accumulator]
pub struct CycleAccumulator(pub(super) Cycle);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Cycle {
pub path: Vec<(AdtRefId, AdtRefId)>,
}

impl Cycle {
pub fn new(a: AdtRefId, b: AdtRefId) -> Self {
Self { path: vec![(a, b)] }
}

pub fn merge(&mut self, other: &mut Self) {
assert_eq!(self.end(), other.start());
self.path.append(&mut other.path);
}

pub fn is_complete(&self) -> bool {
self.start() == self.end()
}

pub fn start(&self) -> AdtRefId {
self.path[0].0
}

pub fn end(&self) -> AdtRefId {
self.path[self.path.len() - 1].1
}
}

adts.flat_map(|adt| {
analyze_adt::accumulated::<AdtDefDiagAccumulator>(self.db, adt).into_iter()
})
.map(|diag| diag.to_voucher())
.collect()
fn merge_cycles(cycles: &mut Vec<Cycle>) {
let mut complete = false;

while !complete {
complete = true;

for i in 0..cycles.len() {
if !cycles[i].is_complete() {
complete = false;

for j in 0..cycles.len() {
if cycles[i].end() == cycles[j].start() {
let mut j_clone = cycles[j].clone();
cycles[i].merge(&mut j_clone);
cycles.remove(j);
break;
}
}

if !complete {
break;
}
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/uitest/fixtures/ty/def/recursive_type.fe
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ pub struct S5<T> {

pub struct S6 {
s: S5<S6>
}
}
39 changes: 13 additions & 26 deletions crates/uitest/fixtures/ty/def/recursive_type.snap
Original file line number Diff line number Diff line change
@@ -1,46 +1,33 @@
---
source: crates/uitest/tests/ty.rs
expression: diags
input_file: crates/uitest/fixtures/ty/recursive_type.fe
input_file: crates/uitest/fixtures/ty/def/recursive_type.fe
---
error[3-0002]: recursive type is not allowed
┌─ recursive_type.fe:1:12
1pub struct S1 {
│ ^^ recursive type definition
2 │ s: S1
│ -- recursion occurs here
│ ^^
│ │
│ recursive type definition
│ recursion occurs here

error[3-0002]: recursive type is not allowed
┌─ recursive_type.fe:5:12
5 │ pub struct S2 {
│ ^^ recursive type definition
6 │ s: S3
│ -- recursion occurs here

error[3-0002]: recursive type is not allowed
┌─ recursive_type.fe:9:12
9 │ pub struct S3 {
│ ^^ recursive type definition
10 │ s: S4
│ -- recursion occurs here

error[3-0002]: recursive type is not allowed
┌─ recursive_type.fe:13:12
13 │ pub struct S4 {
│ ^^ recursive type definition
14 │ s: S2
│ -- recursion occurs here
│ ^^
│ │
│ recursive type definition
│ recursion occurs here

error[3-0002]: recursive type is not allowed
┌─ recursive_type.fe:22:12
22 │ pub struct S6 {
│ ^^ recursive type definition
23 │ s: S5<S6>
│ ------ recursion occurs here
│ ^^
│ │
│ recursive type definition
│ recursion occurs here


0 comments on commit 258a3c5

Please sign in to comment.