From 87b37f27dcffd44481e6258a576164ef96ec32dc Mon Sep 17 00:00:00 2001 From: Grant Wuerker Date: Sat, 25 Nov 2023 22:25:37 +0300 Subject: [PATCH] hacking --- crates/hir-analysis/Cargo.toml | 2 +- crates/hir-analysis/src/ty/def_analysis.rs | 5 +- crates/hir-analysis/src/ty/diagnostics.rs | 38 ++++---- crates/hir-analysis/src/ty/mod.rs | 86 +++++++++++++++++-- .../uitest/fixtures/ty/def/recursive_type.fe | 2 +- .../fixtures/ty/def/recursive_type.snap.new | 7 ++ 6 files changed, 106 insertions(+), 34 deletions(-) create mode 100644 crates/uitest/fixtures/ty/def/recursive_type.snap.new 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/ty/def_analysis.rs b/crates/hir-analysis/src/ty/def_analysis.rs index 05c8a727f..219f66f66 100644 --- a/crates/hir-analysis/src/ty/def_analysis.rs +++ b/crates/hir-analysis/src/ty/def_analysis.rs @@ -439,10 +439,7 @@ 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), - ); + let diag = TyLowerDiag::recursive_type(field_adt_ref, adt); return Some(diag.into()); } } diff --git a/crates/hir-analysis/src/ty/diagnostics.rs b/crates/hir-analysis/src/ty/diagnostics.rs index 699e5b265..a07e097cb 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] @@ -46,8 +46,8 @@ pub enum TyLowerDiag { NotFullyAppliedType(DynLazySpan), InvalidTypeArgKind(DynLazySpan, String), RecursiveType { - primary_span: DynLazySpan, - field_span: DynLazySpan, + to: AdtRefId, + from: AdtRefId, }, UnboundTypeAliasParam { @@ -95,11 +95,8 @@ impl TyLowerDiag { Self::InvalidTypeArgKind(span, msg) } - pub(super) fn recursive_type(primary_span: DynLazySpan, field_span: DynLazySpan) -> Self { - Self::RecursiveType { - primary_span, - field_span, - } + pub(super) fn recursive_type(to: AdtRefId, from: AdtRefId) -> Self { + Self::RecursiveType { to, from } } pub(super) fn unbound_type_alias_param( @@ -179,21 +176,18 @@ impl TyLowerDiag { span.resolve(db), )], - Self::RecursiveType { - primary_span, - field_span, - } => { + Self::RecursiveType { to, from } => { vec![ - SubDiagnostic::new( - LabelStyle::Primary, - "recursive type definition".to_string(), - primary_span.resolve(db), - ), - SubDiagnostic::new( - LabelStyle::Secondary, - "recursion occurs here".to_string(), - field_span.resolve(db), - ), + // SubDiagnostic::new( + // LabelStyle::Primary, + // "recursive type definition".to_string(), + // primary_span.resolve(db), + // ), + // SubDiagnostic::new( + // LabelStyle::Secondary, + // "recursion occurs here".to_string(), + // field_span.resolve(db), + // ), ] } diff --git a/crates/hir-analysis/src/ty/mod.rs b/crates/hir-analysis/src/ty/mod.rs index 1600c512f..3be341780 100644 --- a/crates/hir-analysis/src/ty/mod.rs +++ b/crates/hir-analysis/src/ty/mod.rs @@ -1,10 +1,11 @@ use crate::HirAnalysisDb; use hir::{analysis_pass::ModuleAnalysisPass, hir_def::TopLevelMod}; +use indexmap::{indexmap, IndexMap}; use self::{ def_analysis::{analyze_adt, analyze_impl_trait, analyze_trait, analyze_type_alias}, diagnostics::{ - AdtDefDiagAccumulator, ImplTraitDefDiagAccumulator, TraitDefDiagAccumulator, + AdtDefDiagAccumulator, ImplTraitDefDiagAccumulator, TraitDefDiagAccumulator, TyLowerDiag, TypeAliasDefDiagAccumulator, }, ty_def::AdtRefId, @@ -57,11 +58,84 @@ impl<'db> ModuleAnalysisPass for TypeDefAnalysisPass<'db> { .map(|c| AdtRefId::from_contract(self.db, *c)), ); - adts.flat_map(|adt| { - analyze_adt::accumulated::(self.db, adt).into_iter() - }) - .map(|diag| diag.to_voucher()) - .collect() + let mut cycles = vec![]; + let mut diags = adts + .flat_map(|adt| { + analyze_adt::accumulated::(self.db, adt).into_iter() + }) + .fold(vec![], |mut accum, diag| match diag { + diagnostics::TyDiagCollection::Ty(TyLowerDiag::RecursiveType { to, from }) => { + cycles.push(Cycle::new(to, from)); + accum + } + _ => { + accum.push(diag); + accum + } + }) + .iter() + .map(|diag| diag.to_voucher()) + .collect(); + if !cycles.is_empty() { + merge_cycles(&mut cycles); + panic!("{:#?}", cycles); + } + diags + } +} + +#[derive(Clone, Debug)] +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 + } +} + +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.new b/crates/uitest/fixtures/ty/def/recursive_type.snap.new new file mode 100644 index 000000000..61a94bbd7 --- /dev/null +++ b/crates/uitest/fixtures/ty/def/recursive_type.snap.new @@ -0,0 +1,7 @@ +--- +source: crates/uitest/tests/ty.rs +assertion_line: 17 +expression: diags +input_file: crates/uitest/fixtures/ty/def/recursive_type.fe +--- +