From 258a3c5f80eb9eae6ebd697b85dc406e8e5808f8 Mon Sep 17 00:00:00 2001 From: Grant Wuerker Date: Sat, 25 Nov 2023 22:25:37 +0300 Subject: [PATCH] hacking --- Cargo.lock | 1 + crates/hir-analysis/Cargo.toml | 2 +- crates/hir-analysis/src/lib.rs | 1 + crates/hir-analysis/src/ty/def_analysis.rs | 20 ++-- crates/hir-analysis/src/ty/diagnostics.rs | 2 +- crates/hir-analysis/src/ty/mod.rs | 94 +++++++++++++++++-- .../uitest/fixtures/ty/def/recursive_type.fe | 2 +- .../fixtures/ty/def/recursive_type.snap | 39 +++----- 8 files changed, 114 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc11dc0e6..ca80fbe88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1087,6 +1087,7 @@ dependencies = [ "fe-compiler-test-utils", "fe-hir", "fe-macros", + "indexmap", "itertools", "rustc-hash", "salsa-2022", diff --git a/crates/hir-analysis/Cargo.toml b/crates/hir-analysis/Cargo.toml index 31002b9d2..3801f274f 100644 --- a/crates/hir-analysis/Cargo.toml +++ b/crates/hir-analysis/Cargo.toml @@ -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" } diff --git a/crates/hir-analysis/src/lib.rs b/crates/hir-analysis/src/lib.rs index c07772146..7125f5fbf 100644 --- a/crates/hir-analysis/src/lib.rs +++ b/crates/hir-analysis/src/lib.rs @@ -55,6 +55,7 @@ pub struct Jar( ty::diagnostics::TypeAliasDefDiagAccumulator, ty::diagnostics::TraitDefDiagAccumulator, ty::diagnostics::ImplTraitDefDiagAccumulator, + ty::CycleAccumulator, ); pub trait HirAnalysisDb: salsa::DbWithJar + HirDb { diff --git a/crates/hir-analysis/src/ty/def_analysis.rs b/crates/hir-analysis/src/ty/def_analysis.rs index 05c8a727f..a4e5b7e10 100644 --- a/crates/hir-analysis/src/ty/def_analysis.rs +++ b/crates/hir-analysis/src/ty/def_analysis.rs @@ -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: @@ -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); } } @@ -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 { +pub(crate) fn check_recursive_adt(db: &dyn HirAnalysisDb, adt: AdtRefId) -> Option { let adt_def = lower_adt(db, adt); for field in adt_def.fields(db) { for ty in field.iter_types(db) { @@ -428,7 +427,7 @@ fn check_recursive_adt_impl( db: &dyn HirAnalysisDb, cycle: &salsa::Cycle, adt: AdtRefId, -) -> Option { +) -> Option { let participants: FxHashSet<_> = cycle .participant_keys() .map(|key| check_recursive_adt::key_from_id(key.key_index())) @@ -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); } } } diff --git a/crates/hir-analysis/src/ty/diagnostics.rs b/crates/hir-analysis/src/ty/diagnostics.rs index 699e5b265..92ff007b5 100644 --- a/crates/hir-analysis/src/ty/diagnostics.rs +++ b/crates/hir-analysis/src/ty/diagnostics.rs @@ -12,7 +12,7 @@ use crate::HirAnalysisDb; use super::{ constraint::PredicateId, - ty_def::{Kind, TyId}, + ty_def::{AdtRefId, Kind, TyId}, }; #[salsa::accumulator] diff --git a/crates/hir-analysis/src/ty/mod.rs b/crates/hir-analysis/src/ty/mod.rs index 1600c512f..5d1f15f16 100644 --- a/crates/hir-analysis/src/ty/mod.rs +++ b/crates/hir-analysis/src/ty/mod.rs @@ -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, }; @@ -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::( + self.db, adt, + )); + analyze_adt::accumulated::(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::(self.db, adt).into_iter() - }) - .map(|diag| diag.to_voucher()) - .collect() +fn merge_cycles(cycles: &mut Vec) { + 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; + } + } + } } } diff --git a/crates/uitest/fixtures/ty/def/recursive_type.fe b/crates/uitest/fixtures/ty/def/recursive_type.fe index 0a750cca7..c8c8592c9 100644 --- a/crates/uitest/fixtures/ty/def/recursive_type.fe +++ b/crates/uitest/fixtures/ty/def/recursive_type.fe @@ -21,4 +21,4 @@ pub struct S5 { pub struct S6 { s: S5 -} \ No newline at end of file +} diff --git a/crates/uitest/fixtures/ty/def/recursive_type.snap b/crates/uitest/fixtures/ty/def/recursive_type.snap index daf6f6bf1..a09c819a2 100644 --- a/crates/uitest/fixtures/ty/def/recursive_type.snap +++ b/crates/uitest/fixtures/ty/def/recursive_type.snap @@ -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 │ 1 │ pub 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 - │ ------ recursion occurs here + │ ^^ + │ │ + │ recursive type definition + │ recursion occurs here