From 0c49cee9f31e679b0e80466351c60f59f9d975a5 Mon Sep 17 00:00:00 2001 From: Ariel Davis Date: Thu, 7 Dec 2023 03:28:11 -0800 Subject: [PATCH] Store many defs for everything, pass test --- crates/analysis/src/lib.rs | 31 +++--- crates/sml-statics-types/src/env.rs | 12 ++- crates/sml-statics-types/src/info.rs | 8 +- crates/sml-statics-types/src/sym.rs | 4 +- crates/sml-statics/src/basis.rs | 21 ++-- crates/sml-statics/src/dec.rs | 11 +- crates/sml-statics/src/info.rs | 145 ++++++++++++++------------- crates/sml-statics/src/st.rs | 10 +- crates/sml-statics/src/top_dec.rs | 42 ++++---- crates/sml-statics/src/ty.rs | 10 +- crates/tests/src/hover/doc.rs | 2 +- docs/CHANGELOG.md | 2 +- 12 files changed, 158 insertions(+), 140 deletions(-) diff --git a/crates/analysis/src/lib.rs b/crates/analysis/src/lib.rs index fd1b08dd2..c3c1dc00e 100644 --- a/crates/analysis/src/lib.rs +++ b/crates/analysis/src/lib.rs @@ -20,6 +20,8 @@ pub use mlb_statics::StdBasis; /// The url to go to for information about diagnostics. pub const URL: &str = "https://github.com/azdavis/millet/blob/main/docs/diagnostics"; +const DOC_SEPARATOR: &str = "\n\n---\n\n"; + /// Performs analysis. #[derive(Debug)] pub struct Analysis { @@ -140,7 +142,7 @@ impl Analysis { let this = def::Def::Path(def::Path::Regular(pos.path), idx); parts.extend(self.get_doc(this)); let defs = ft.file.info.get_defs(idx); - parts.extend(defs.into_iter().filter_map(|def| self.get_doc(def))); + parts.extend(defs.into_iter().flatten().filter_map(|&def| self.get_doc(def))); ptr.text_range() } None => ft.token.text_range(), @@ -152,7 +154,7 @@ impl Analysis { return None; } let range = ft.file.syntax.pos_db.range_utf16(range)?; - Some((parts.join("\n\n---\n\n"), range)) + Some((parts.join(DOC_SEPARATOR), range)) } fn get_doc(&self, def: def::Def) -> Option<&str> { @@ -178,6 +180,7 @@ impl Analysis { .info .get_defs(idx) .into_iter() + .flatten() .filter_map(|def| source_files::path_and_range(&self.source_files, def.to_regular_idx()?)); Some(iter.collect()) } @@ -342,7 +345,7 @@ impl Analysis { label: name.as_str().to_owned(), kind: sml_namespace::SymbolKind::Structure, detail: None, - documentation: env.def.and_then(|d| self.get_doc(d)).map(ToOwned::to_owned), + documentation: self.get_defs_doc(&env.defs), })); ac.extend(env.val_env.iter().map(|(name, val_info)| { let ty_scheme = val_info.ty_scheme.display(&self.syms_tys, config::DiagnosticLines::Many); @@ -350,20 +353,22 @@ impl Analysis { label: name.as_str().to_owned(), kind: sml_symbol_kind::get(&self.syms_tys.tys, val_info), detail: Some(ty_scheme.to_string()), - documentation: val_info.defs.iter().filter_map(|&x| self.get_doc(x)).fold(None, |ac, x| { - match ac { - None => Some(x.to_owned()), - Some(mut ac) => { - ac.push_str("\n\n---\n\n"); - ac.push_str(x); - Some(ac) - } - } - }), + documentation: self.get_defs_doc(&val_info.defs), } })); } + fn get_defs_doc(&self, defs: &FxHashSet) -> Option { + defs.iter().filter_map(|&x| self.get_doc(x)).fold(None, |ac, x| match ac { + None => Some(x.to_owned()), + Some(mut ac) => { + ac.push_str("\n\n---\n\n"); + ac.push_str(x); + Some(ac) + } + }) + } + /// Returns all inlay hints for the range. #[must_use] pub fn inlay_hints(&self, range: WithPath) -> Option> { diff --git a/crates/sml-statics-types/src/env.rs b/crates/sml-statics-types/src/env.rs index 2b5a049d8..bac4a1169 100644 --- a/crates/sml-statics-types/src/env.rs +++ b/crates/sml-statics-types/src/env.rs @@ -20,17 +20,19 @@ pub struct Env { pub ty_env: TyEnv, /// The value env. pub val_env: ValEnv, - /// The def site for this env. - pub def: Option, + /// The definitions. + /// + /// It's a set, because we can have structures ascribing to signatures. + pub defs: FxHashSet, /// Whether everything in this env is disallowed. pub disallow: Option, } impl Env { - /// Returns an empty `Env` with the given def. + /// Returns an empty `Env` with the given defs. #[must_use] - pub fn new(def: Option) -> Env { - Env { def, ..Env::default() } + pub fn new(defs: FxHashSet) -> Env { + Env { defs, ..Env::default() } } /// Appends other onto self, emptying other. diff --git a/crates/sml-statics-types/src/info.rs b/crates/sml-statics-types/src/info.rs index 459038597..2f98cf19d 100644 --- a/crates/sml-statics-types/src/info.rs +++ b/crates/sml-statics-types/src/info.rs @@ -17,8 +17,10 @@ pub struct TyInfo { pub ty_scheme: TyScheme, /// The val environment. pub val_env: VE, - /// The def. - pub def: Option, + /// The definitions. + /// + /// It's a set, because we can have structures ascribing to signatures. + pub defs: FxHashSet, /// Whether this is disallowed. pub disallow: Option, } @@ -32,7 +34,7 @@ where TyInfo { ty_scheme: self.ty_scheme, val_env: self.val_env.into(), - def: self.def, + defs: self.defs, disallow: self.disallow, } } diff --git a/crates/sml-statics-types/src/sym.rs b/crates/sml-statics-types/src/sym.rs index fbc05d8b0..c35b06189 100644 --- a/crates/sml-statics-types/src/sym.rs +++ b/crates/sml-statics-types/src/sym.rs @@ -6,7 +6,7 @@ use crate::info::{TyInfo, ValEnv, ValInfo}; use crate::ty::{Ty, TyKind, TyScheme}; use crate::{def, overload}; use drop_bomb::DropBomb; -use fast_hash::FxHashMap; +use fast_hash::{FxHashMap, FxHashSet}; use std::fmt; /// A symbol, aka a type name. Definition: `TyName` @@ -245,7 +245,7 @@ impl Syms { let ty_info = TyInfo { ty_scheme: TyScheme::zero(Ty::NONE), val_env: SymValEnv::default(), - def: None, + defs: FxHashSet::default(), disallow: None, }; // must start with sometimes equality, as an assumption for constructing datatypes. we may diff --git a/crates/sml-statics/src/basis.rs b/crates/sml-statics/src/basis.rs index a05b15215..e6eec5b9a 100644 --- a/crates/sml-statics/src/basis.rs +++ b/crates/sml-statics/src/basis.rs @@ -1,7 +1,7 @@ //! Bases. (The plural of "basis".) use crate::get_env::get_mut_env; -use fast_hash::FxHashMap; +use fast_hash::{FxHashMap, FxHashSet}; use sml_statics_types::disallow::{self, Disallow}; use sml_statics_types::env::{Cx, Env, FunEnv, SigEnv, StrEnv}; use sml_statics_types::info::{IdStatus, TyEnv, TyInfo, ValEnv, ValInfo}; @@ -153,7 +153,7 @@ pub fn minimal() -> (sml_statics_types::St, Bs) { TyInfo { ty_scheme: alpha_list.clone(), val_env: datatype_ve([(Primitive::Nil, alpha_list), (Primitive::Cons, cons)]), - def: Some(Primitive::List.into()), + defs: FxHashSet::from_iter([Primitive::List.into()]), disallow: None, } }; @@ -167,7 +167,7 @@ pub fn minimal() -> (sml_statics_types::St, Bs) { TyInfo { ty_scheme: ty_scheme_one(&mut tys, TyVarKind::Regular, ref_), val_env: datatype_ve([(Primitive::RefVal, con)]), - def: Some(Primitive::RefTy.into()), + defs: FxHashSet::from_iter([Primitive::RefTy.into()]), disallow: None, } }; @@ -175,7 +175,7 @@ pub fn minimal() -> (sml_statics_types::St, Bs) { let vector_info = TyInfo { ty_scheme: ty_scheme_one(&mut tys, TyVarKind::Regular, |tys, a| tys.con(vec![a], Sym::VECTOR)), val_env: SymValEnv::default(), - def: Some(Primitive::Vector.into()), + defs: FxHashSet::from_iter([Primitive::Vector.into()]), disallow: None, }; insert_special(&mut syms, Sym::VECTOR, vector_info); @@ -190,7 +190,7 @@ pub fn minimal() -> (sml_statics_types::St, Bs) { let ti = TyInfo { ty_scheme: TyScheme::zero(ty), val_env: ValEnv::default(), - def: Some(name.into()), + defs: FxHashSet::from_iter([name.into()]), disallow: None, }; (str_util::Name::new(name.as_str()), ti) @@ -244,7 +244,13 @@ pub fn minimal() -> (sml_statics_types::St, Bs) { let bs = Bs { fun_env: FunEnv::default(), sig_env: SigEnv::default(), - env: Env { str_env: StrEnv::default(), ty_env, val_env, def: None, disallow: None }, + env: Env { + str_env: StrEnv::default(), + ty_env, + val_env, + defs: FxHashSet::default(), + disallow: None, + }, }; (sml_statics_types::St { syms, tys }, bs) } @@ -267,7 +273,8 @@ fn insert_special(syms: &mut Syms, sym: Sym, ty_info: SymTyInfo) { fn basic_datatype(tys: &mut Tys, sym: Sym, ctors: &'static [Primitive]) -> SymTyInfo { let ty_scheme = TyScheme::zero(tys.con(Vec::new(), sym)); let val_env = datatype_ve(ctors.iter().map(|&x| (x, ty_scheme.clone()))); - TyInfo { ty_scheme, val_env, def: Some(sym.primitive().unwrap().into()), disallow: None } + let defs = FxHashSet::from_iter([sym.primitive().unwrap().into()]); + TyInfo { ty_scheme, val_env, defs, disallow: None } } fn datatype_ve(xs: I) -> SymValEnv diff --git a/crates/sml-statics/src/dec.rs b/crates/sml-statics/src/dec.rs index 4ccd36bb6..da8a4923c 100644 --- a/crates/sml-statics/src/dec.rs +++ b/crates/sml-statics/src/dec.rs @@ -206,9 +206,8 @@ fn get_one( IdStatus::Exn(_) => { match ins_no_dupe(&mut val_env, name.clone(), val_info.clone(), Item::Val) { None => { - if let Some(&def) = val_info.defs.iter().next() { - st.info.entries.defs.dec.insert(dec, def); - } + let dec_defs = st.info.entries.defs.dec.entry(dec).or_default(); + dec_defs.extend(val_info.defs.iter()); } Some(e) => st.err(dec, e), } @@ -299,7 +298,7 @@ fn get_ty_binds( let ty = ty::get(st, cx, ars, ty::Mode::TyRhs, ty_bind.ty); let ty_scheme = generalize::get_fixed(&mut st.syms_tys.tys, fixed, ty); let ty_info = - TyInfo { ty_scheme, val_env: ValEnv::default(), def: st.def(idx), disallow: None }; + TyInfo { ty_scheme, val_env: ValEnv::default(), defs: st.def(idx), disallow: None }; if let Some(e) = ins_no_dupe(ty_env, ty_bind.name.clone(), ty_info, Item::Ty) { st.err(idx, e); } @@ -345,7 +344,7 @@ pub(crate) fn get_dat_binds( let ty_info = TyInfo { ty_scheme: ty_scheme.clone(), val_env: ValEnv::default(), - def: st.def(idx), + defs: st.def(idx), disallow: None, }; if let Some(e) = ins_no_dupe(&mut fake_ty_env, dat_bind.name.clone(), ty_info, Item::Ty) { @@ -414,7 +413,7 @@ pub(crate) fn get_dat_binds( // NOTE: no checking for duplicates here big_val_env.append(&mut val_env.clone().into()); let ty_info = - TyInfo { ty_scheme: datatype.ty_scheme, val_env, def: st.def(idx), disallow: None }; + TyInfo { ty_scheme: datatype.ty_scheme, val_env, defs: st.def(idx), disallow: None }; let ty_info_dve = ty_info.clone().with_default_val_env_type(); let equality = equality::get_ty_info( st.info.mode, diff --git a/crates/sml-statics/src/info.rs b/crates/sml-statics/src/info.rs index 0ce272870..7d15694ee 100644 --- a/crates/sml-statics/src/info.rs +++ b/crates/sml-statics/src/info.rs @@ -10,37 +10,40 @@ use std::fmt; pub(crate) type IdxMap = la_arena::ArenaMap, V>; +pub(crate) type DefMap = IdxMap>; + #[derive(Debug, Default, Clone)] pub(crate) struct Defs { - pub(crate) str_exp: IdxMap, - pub(crate) sig_exp: IdxMap, - pub(crate) dec: IdxMap, - pub(crate) exp: IdxMap>, - pub(crate) pat: IdxMap>, - pub(crate) ty: IdxMap, + pub(crate) str_exp: DefMap, + pub(crate) sig_exp: DefMap, + pub(crate) dec: DefMap, + pub(crate) exp: DefMap, + pub(crate) pat: DefMap, + pub(crate) ty: DefMap, } impl Defs { - fn get(&self, idx: sml_hir::Idx) -> FxHashSet { + fn get(&self, idx: sml_hir::Idx) -> Option<&FxHashSet> { match idx { - sml_hir::Idx::StrDec(_) | sml_hir::Idx::Spec(_) => FxHashSet::default(), - sml_hir::Idx::StrExp(idx) => self.str_exp.get(idx).into_iter().copied().collect(), - sml_hir::Idx::SigExp(idx) => self.sig_exp.get(idx).into_iter().copied().collect(), - sml_hir::Idx::Dec(idx) => self.dec.get(idx).into_iter().copied().collect(), - sml_hir::Idx::Exp(idx) => self.exp.get(idx).into_iter().flatten().copied().collect(), - sml_hir::Idx::Pat(idx) => self.pat.get(idx).into_iter().flatten().copied().collect(), - sml_hir::Idx::Ty(idx) => self.ty.get(idx).into_iter().copied().collect(), + sml_hir::Idx::StrDec(_) | sml_hir::Idx::Spec(_) => None, + sml_hir::Idx::StrExp(idx) => self.str_exp.get(idx), + sml_hir::Idx::SigExp(idx) => self.sig_exp.get(idx), + sml_hir::Idx::Dec(idx) => self.dec.get(idx), + sml_hir::Idx::Exp(idx) => self.exp.get(idx), + sml_hir::Idx::Pat(idx) => self.pat.get(idx), + sml_hir::Idx::Ty(idx) => self.ty.get(idx), } } fn with_def(&self, def: def::Def) -> impl Iterator + '_ { - std::iter::empty::<(sml_hir::Idx, def::Def)>() - .chain(self.str_exp.iter().map(|(idx, &d)| (idx.into(), d))) - .chain(self.sig_exp.iter().map(|(idx, &d)| (idx.into(), d))) - .chain(self.dec.iter().map(|(idx, &d)| (idx.into(), d))) - .chain(self.exp.iter().flat_map(|(idx, ds)| ds.iter().map(move |&d| (idx.into(), d)))) - .chain(self.pat.iter().flat_map(|(idx, ds)| ds.iter().map(move |&d| (idx.into(), d)))) - .chain(self.ty.iter().map(|(idx, &d)| (idx.into(), d))) + std::iter::empty::<(sml_hir::Idx, &FxHashSet)>() + .chain(self.str_exp.iter().map(|(idx, set)| (idx.into(), set))) + .chain(self.sig_exp.iter().map(|(idx, set)| (idx.into(), set))) + .chain(self.dec.iter().map(|(idx, set)| (idx.into(), set))) + .chain(self.exp.iter().map(|(idx, set)| (idx.into(), set))) + .chain(self.pat.iter().map(|(idx, set)| (idx.into(), set))) + .chain(self.ty.iter().map(|(idx, set)| (idx.into(), set))) + .flat_map(|(idx, defs)| defs.iter().map(move |&def| (idx, def))) .filter_map(move |(idx, d)| (d == def).then_some(idx)) } } @@ -154,11 +157,11 @@ impl Info { /// Returns the definition sites of the idx. #[must_use] - pub fn get_defs(&self, idx: sml_hir::Idx) -> FxHashSet { + pub fn get_defs(&self, idx: sml_hir::Idx) -> Option<&FxHashSet> { self.entries.defs.get(idx) } - /// Returns the definition site of the type for the idx. + /// Returns the definition sites of the type for the idx. #[must_use] pub fn get_ty_defs( &self, @@ -167,12 +170,10 @@ impl Info { ) -> Option> { let ty_entry = self.entries.tys.get(idx)?; let mut ret = Vec::::new(); - ty_syms(&st.tys, ty_entry.ty, &mut |sym| match st.syms.get(sym) { - None => {} - Some(sym_info) => match sym_info.ty_info.def { - None => {} - Some(def) => ret.push(def), - }, + ty_syms(&st.tys, ty_entry.ty, &mut |sym| { + let sym_info = st.syms.get(sym); + let defs = sym_info.iter().flat_map(|sym_info| sym_info.ty_info.defs.iter()).copied(); + ret.extend(defs); }); Some(ret) } @@ -214,28 +215,32 @@ impl Info { path: paths::PathId, ) -> Vec { let mut ret = Vec::::new(); - ret.extend(self.bs.fun_env.iter().filter_map(|(name, fun_sig)| { - let idx = def_idx(path, fun_sig.body_env.def?)?; - let mut children = Vec::::new(); - env_syms(&mut children, st, path, &fun_sig.body_env); - Some(DocumentSymbol { - name: name.as_str().to_owned(), - kind: sml_namespace::SymbolKind::Functor, - detail: None, - idx, - children, + ret.extend(self.bs.fun_env.iter().flat_map(|(name, fun_sig)| { + fun_sig.body_env.defs.iter().filter_map(|&def| { + let idx = def_idx(path, def)?; + let mut children = Vec::::new(); + env_syms(&mut children, st, path, &fun_sig.body_env); + Some(DocumentSymbol { + name: name.as_str().to_owned(), + kind: sml_namespace::SymbolKind::Functor, + detail: None, + idx, + children, + }) }) })); - ret.extend(self.bs.sig_env.iter().filter_map(|(name, sig)| { - let idx = def_idx(path, sig.env.def?)?; - let mut children = Vec::::new(); - env_syms(&mut children, st, path, &sig.env); - Some(DocumentSymbol { - name: name.as_str().to_owned(), - kind: sml_namespace::SymbolKind::Signature, - detail: None, - idx, - children, + ret.extend(self.bs.sig_env.iter().flat_map(|(name, sig)| { + sig.env.defs.iter().filter_map(|&def| { + let idx = def_idx(path, def)?; + let mut children = Vec::::new(); + env_syms(&mut children, st, path, &sig.env); + Some(DocumentSymbol { + name: name.as_str().to_owned(), + kind: sml_namespace::SymbolKind::Signature, + detail: None, + idx, + children, + }) }) })); env_syms(&mut ret, st, path, &self.bs.env); @@ -315,27 +320,31 @@ fn env_syms( path: paths::PathId, env: &Env, ) { - ac.extend(env.str_env.iter().filter_map(|(name, env)| { - let idx = def_idx(path, env.def?)?; - let mut children = Vec::::new(); - env_syms(&mut children, st, path, env); - Some(DocumentSymbol { - name: name.as_str().to_owned(), - kind: sml_namespace::SymbolKind::Structure, - detail: None, - idx, - children, + ac.extend(env.str_env.iter().flat_map(|(name, env)| { + env.defs.iter().filter_map(|&def| { + let idx = def_idx(path, def)?; + let mut children = Vec::::new(); + env_syms(&mut children, st, path, env); + Some(DocumentSymbol { + name: name.as_str().to_owned(), + kind: sml_namespace::SymbolKind::Structure, + detail: None, + idx, + children, + }) }) })); - ac.extend(env.ty_env.iter().filter_map(|(name, ty_info)| { - let idx = def_idx(path, ty_info.def?)?; - let ty_scheme = ty_info.ty_scheme.display(st, config::DiagnosticLines::Many); - Some(DocumentSymbol { - name: name.as_str().to_owned(), - kind: sml_namespace::SymbolKind::Type, - detail: Some(ty_scheme.to_string()), - idx, - children: Vec::new(), + ac.extend(env.ty_env.iter().flat_map(|(name, ty_info)| { + ty_info.defs.iter().filter_map(|&def| { + let idx = def_idx(path, def)?; + let ty_scheme = ty_info.ty_scheme.display(st, config::DiagnosticLines::Many); + Some(DocumentSymbol { + name: name.as_str().to_owned(), + kind: sml_namespace::SymbolKind::Type, + detail: Some(ty_scheme.to_string()), + idx, + children: Vec::new(), + }) }) })); ac.extend(env.val_env.iter().flat_map(|(name, val_info)| { diff --git a/crates/sml-statics/src/st.rs b/crates/sml-statics/src/st.rs index 1ce62510f..8931208e6 100644 --- a/crates/sml-statics/src/st.rs +++ b/crates/sml-statics/src/st.rs @@ -44,15 +44,19 @@ impl<'a> St<'a> { } } - pub(crate) fn def(&self, idx: sml_hir::Idx) -> Option { + pub(crate) fn def_opt(&self, idx: sml_hir::Idx) -> Option { let path = match self.info.mode { - Mode::Regular(p) => def::Path::Regular(p?), + Mode::Regular(Some(p)) => def::Path::Regular(p), Mode::BuiltinLib(p) => def::Path::BuiltinLib(p), - Mode::PathOrder | Mode::Dynamics => return None, + Mode::Regular(None) | Mode::PathOrder | Mode::Dynamics => return None, }; Some(def::Def::Path(path, idx)) } + pub(crate) fn def(&self, idx: sml_hir::Idx) -> FxHashSet { + self.def_opt(idx).into_iter().collect() + } + pub(crate) fn err(&mut self, idx: I, kind: ErrorKind) where I: Into, diff --git a/crates/sml-statics/src/top_dec.rs b/crates/sml-statics/src/top_dec.rs index 6cea3cb51..582c2b5f2 100644 --- a/crates/sml-statics/src/top_dec.rs +++ b/crates/sml-statics/src/top_dec.rs @@ -208,9 +208,8 @@ fn get_str_exp( } match got_env.val { Ok(got_env) => { - if let Some(def) = got_env.def { - st.info.entries.defs.str_exp.insert(str_exp, def); - } + let defs = st.info.entries.defs.str_exp.entry(str_exp).or_default(); + defs.extend(got_env.defs.iter().copied()); ac.append(&mut got_env.clone()); } Err(e) => st.err(str_exp, e.into()), @@ -246,7 +245,7 @@ fn get_str_exp( if let Some(sml_hir::StrExp::Struct(decs)) = inner_str_exp.map(|x| &ars.str_exp[x]) { if let Some(sml_hir::SigExp::Name(_)) = sig_exp.map(|x| &ars.sig_exp[x]) { if decs.is_empty() { - ac.def = to_add.def; + ac.defs.extend(to_add.defs.iter().copied()); } } } @@ -302,20 +301,18 @@ fn get_str_exp( let mut param_env = fun_sig.param.env.clone(); realize::get_env(&mut st.syms_tys.tys, &subst, &mut param_env); enrich::get_env(st, arg_idx, &arg_env, ¶m_env); - let def = st.def(idx); + let def = st.def_opt(idx); for (_, env) in to_add.str_env.iter_mut() { - env.def = def; + env.defs.extend(def.iter().copied()); } for (_, ty_env) in to_add.ty_env.iter_mut() { - ty_env.def = def; + ty_env.defs.extend(def.iter().copied()); } for (_, val_info) in to_add.val_env.iter_mut() { - // TODO add to the set? - val_info.defs = def.into_iter().collect(); - } - if let Some(def) = fun_sig.body_env.def { - st.info.entries.defs.str_exp.insert(str_exp, def); + val_info.defs.extend(def.iter().copied()); } + let str_exp_defs = st.info.entries.defs.str_exp.entry(str_exp).or_default(); + str_exp_defs.extend(fun_sig.body_env.defs.iter().copied()); ac.append(&mut to_add); } // @def(55) @@ -332,18 +329,14 @@ fn get_str_exp( /// helps get the defs (and therefore e.g. docs) from a structure that ascribes to a signature, not /// just the docs from the signature fn enrich_defs(general: &Env, specific: &mut Env) { - if specific.def.is_none() { - specific.def = general.def; - } + specific.defs.extend(general.defs.iter().copied()); for (name, specific) in specific.str_env.iter_mut() { let Some(general) = general.str_env.get(name) else { continue }; enrich_defs(general, specific); } for (name, specific) in specific.ty_env.iter_mut() { let Some(general) = general.ty_env.get(name) else { continue }; - if specific.def.is_none() { - specific.def = general.def; - } + specific.defs.extend(general.defs.iter().copied()); for (name, specific) in specific.val_env.iter_mut() { let Some(general) = general.val_env.get(name) else { continue }; specific.defs.extend(general.defs.iter().copied()); @@ -382,12 +375,11 @@ fn get_sig_exp( gen_fresh_syms(st, &mut subst, &sig.ty_names); let mut sig_env = sig.env.clone(); realize::get_env(&mut st.syms_tys.tys, &subst, &mut sig_env); - if let Some(def) = sig.env.def { - st.info.entries.defs.sig_exp.insert(sig_exp, def); - // @test(hover::doc::std_basis_structure) - if matches!(st.info.mode, Mode::BuiltinLib(_)) { - ac.def = sig_env.def; - } + let sig_exp_defs = st.info.entries.defs.sig_exp.entry(sig_exp).or_default(); + sig_exp_defs.extend(sig.env.defs.iter().copied()); + // @test(hover::doc::std_basis_structure) + if matches!(st.info.mode, Mode::BuiltinLib(_)) { + ac.defs.extend(sig.env.defs.iter().copied()); } ac.append(&mut sig_env); match st.info.mode { @@ -661,7 +653,7 @@ fn get_ty_desc( let ty_info = TyInfo { ty_scheme: n_ary_con(&mut st.syms_tys.tys, bound_vars, started.sym()), val_env: SymValEnv::default(), - def: st.def(idx), + defs: st.def(idx), disallow: None, }; st.syms_tys.syms.finish(started, ty_info.clone(), equality); diff --git a/crates/sml-statics/src/ty.rs b/crates/sml-statics/src/ty.rs index 11d743317..148d7e40f 100644 --- a/crates/sml-statics/src/ty.rs +++ b/crates/sml-statics/src/ty.rs @@ -3,7 +3,7 @@ use crate::{error::ErrorKind, util::record}; use crate::{get_env::get_ty_info, info::TyEntry, st::St}; use sml_statics_types::ty::{Ty, TyData, TyScheme, TyVarSrc}; -use sml_statics_types::{def, env::Cx, item::Item, util::apply_bv}; +use sml_statics_types::{env::Cx, item::Item, util::apply_bv}; /// The mode for how we're checking this type. #[derive(Debug, Clone, Copy)] @@ -24,7 +24,7 @@ pub(crate) fn get( let Some(ty) = ty else { return Ty::NONE }; // NOTE: do not early return, since we add to the Info at the bottom. let mut ty_scheme = None::; - let mut def = None::; + // let mut defs = FxH let ret = match &ars.ty[ty] { sml_hir::Ty::Hole => { st.err(ty, ErrorKind::TyHole); @@ -66,7 +66,8 @@ pub(crate) fn get( let want_len = ty_info.ty_scheme.bound_vars.len(); if want_len == arguments.len() { ty_scheme = Some(ty_info.ty_scheme.clone()); - def = ty_info.def; + let defs = st.info.entries.defs.ty.entry(ty).or_default(); + defs.extend(ty_info.defs.iter().copied()); let mut ret = ty_info.ty_scheme.ty; let subst: Vec<_> = arguments.iter().map(|&ty| get(st, cx, ars, mode, ty)).collect(); apply_bv(&mut st.syms_tys.tys, &subst, &mut ret); @@ -93,8 +94,5 @@ pub(crate) fn get( } }; st.info.entries.tys.ty.insert(ty, TyEntry::new(ret, ty_scheme)); - if let Some(def) = def { - st.info.entries.defs.ty.insert(ty, def); - } ret } diff --git a/crates/tests/src/hover/doc.rs b/crates/tests/src/hover/doc.rs index e8d76d179..aff3c62c8 100644 --- a/crates/tests/src/hover/doc.rs +++ b/crates/tests/src/hover/doc.rs @@ -172,7 +172,7 @@ val bar = Example.bar #[test] fn override_sig_docs_with_structure_type() { - fail( + check( r" signature SIG = sig (*! diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5bd34e80b..41bf68b77 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -15,7 +15,7 @@ The versioning system is basically the following: ## main -- Given `structure Foo : FOO = struct ... end`, where there are documentation comments inside the `...`, show those documentation comments on usages of items in `Foo`, in addition to any documentation from `FOO`. +- Documentation and go-to-def for structures ascribing to signatures works for both the structure and the signature parts of the definitions contained inside. ## v0.14.1