From 33d45a839515ee59d681a4da240755b2512faa70 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 14 Oct 2024 15:39:42 +0200 Subject: [PATCH 1/4] Implement `FullDef: SInto` by hand --- frontend/exporter/src/types/new/full_def.rs | 44 ++++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 784de0a67..c664967a8 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -6,36 +6,51 @@ use rustc_middle::ty; use rustc_span::def_id::DefId as RDefId; /// Gathers a lot of definition information about a [`rustc_hir::def_id::DefId`]. -#[derive(AdtInto)] -#[args(<'tcx, S: BaseState<'tcx>>, from: rustc_hir::def_id::DefId, state: S as s)] #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] pub struct FullDef { - #[value(self.sinto(s))] pub def_id: DefId, - #[value(s.base().tcx.opt_parent(*self).sinto(s))] + /// The enclosing item. pub parent: Option, - #[value(s.base().tcx.def_span(*self).sinto(s))] pub span: Span, - #[value(s.base().tcx.get_attrs_unchecked(*self).sinto(s))] /// Attributes on this definition, if applicable. pub attributes: Vec, - #[value(get_def_visibility(s, *self))] /// Visibility of the definition, for definitions where this makes sense. pub visibility: Option, - #[value(s.base().tcx.as_lang_item(*self).map(|litem| litem.name()).sinto(s))] /// If this definition is a lang item, we store the identifier, e.g. `sized`. pub lang_item: Option, - #[value(s.base().tcx.get_diagnostic_name(*self).sinto(s))] /// If this definition is a diagnostic item, we store the identifier, e.g. `box_new`. pub diagnostic_item: Option, - #[value({ - let state_with_id = State { thir: (), mir: (), owner_id: *self, binder: (), base: s.base() }; - s.base().tcx.def_kind(*self).sinto(&state_with_id) - })] pub kind: FullDefKind, } +#[cfg(feature = "rustc")] +impl<'tcx, S: BaseState<'tcx>> SInto for RDefId { + fn sinto(&self, s: &S) -> FullDef { + let tcx = s.base().tcx; + let def_id = *self; + let kind = { + let state_with_id = with_owner_id(s.base(), (), (), def_id); + tcx.def_kind(def_id).sinto(&state_with_id) + }; + FullDef { + def_id: self.sinto(s), + parent: tcx.opt_parent(def_id).sinto(s), + span: tcx.def_span(def_id).sinto(s), + attributes: tcx.get_attrs_unchecked(def_id).sinto(s), + visibility: get_def_visibility(tcx, def_id), + lang_item: s + .base() + .tcx + .as_lang_item(def_id) + .map(|litem| litem.name()) + .sinto(s), + diagnostic_item: tcx.get_diagnostic_name(def_id).sinto(s), + kind, + } + } +} + /// Imbues [`rustc_hir::def::DefKind`] with a lot of extra information. /// Important: the `owner_id()` must be the id of this definition. #[derive(AdtInto)] @@ -330,9 +345,8 @@ impl FullDef { /// Gets the visibility (`pub` or not) of the definition. Returns `None` for defs that don't have a /// meaningful visibility. #[cfg(feature = "rustc")] -fn get_def_visibility<'tcx, S: BaseState<'tcx>>(s: &S, def_id: RDefId) -> Option { +fn get_def_visibility<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> Option { use rustc_hir::def::DefKind::*; - let tcx = s.base().tcx; match tcx.def_kind(def_id) { AssocConst | AssocFn From 9aac819484c93ffbfecee44ba6a3939623ee3f7a Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 14 Oct 2024 14:56:45 +0200 Subject: [PATCH 2/4] Cache `FullDef` translation --- frontend/exporter/src/state.rs | 4 +++- frontend/exporter/src/types/new/full_def.rs | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index f6a2a053a..cb3aa5254 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -99,7 +99,7 @@ macro_rules! mk { mod types { use crate::prelude::*; use rustc_middle::ty; - use std::cell::RefCell; + use std::{cell::RefCell, sync::Arc}; pub struct LocalContextS { pub vars: HashMap, @@ -133,6 +133,8 @@ mod types { pub struct ItemCache<'tcx> { /// The translated `DefId`. pub def_id: Option, + /// The translated definition. + pub full_def: Option>, /// Cache the `Ty` translations. pub tys: HashMap, Ty>, /// Cache the trait resolution engine for each item. diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index c664967a8..15861be4c 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -4,6 +4,8 @@ use crate::prelude::*; use rustc_middle::ty; #[cfg(feature = "rustc")] use rustc_span::def_id::DefId as RDefId; +#[cfg(feature = "rustc")] +use std::sync::Arc; /// Gathers a lot of definition information about a [`rustc_hir::def_id::DefId`]. #[derive_group(Serializers)] @@ -25,15 +27,18 @@ pub struct FullDef { } #[cfg(feature = "rustc")] -impl<'tcx, S: BaseState<'tcx>> SInto for RDefId { - fn sinto(&self, s: &S) -> FullDef { +impl<'tcx, S: BaseState<'tcx>> SInto> for RDefId { + fn sinto(&self, s: &S) -> Arc { + if let Some(full_def) = s.with_item_cache(*self, |cache| cache.full_def.clone()) { + return full_def; + } let tcx = s.base().tcx; let def_id = *self; let kind = { let state_with_id = with_owner_id(s.base(), (), (), def_id); tcx.def_kind(def_id).sinto(&state_with_id) }; - FullDef { + let full_def = FullDef { def_id: self.sinto(s), parent: tcx.opt_parent(def_id).sinto(s), span: tcx.def_span(def_id).sinto(s), @@ -47,7 +52,10 @@ impl<'tcx, S: BaseState<'tcx>> SInto for RDefId { .sinto(s), diagnostic_item: tcx.get_diagnostic_name(def_id).sinto(s), kind, - } + }; + let full_def: Arc = Arc::new(full_def); + s.with_item_cache(*self, |cache| cache.full_def = Some(full_def.clone())); + full_def } } From 200fef4981f3d0883aed80ab0544977f7492f5aa Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 14 Oct 2024 15:01:18 +0200 Subject: [PATCH 3/4] Include the `FullDef` of associated items in `FullDefKind::Trait/Impl` --- frontend/exporter/src/types/new/full_def.rs | 29 ++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 15861be4c..565c21f32 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -1,11 +1,10 @@ use crate::prelude::*; +use std::sync::Arc; #[cfg(feature = "rustc")] use rustc_middle::ty; #[cfg(feature = "rustc")] use rustc_span::def_id::DefId as RDefId; -#[cfg(feature = "rustc")] -use std::sync::Arc; /// Gathers a lot of definition information about a [`rustc_hir::def_id::DefId`]. #[derive_group(Serializers)] @@ -109,8 +108,17 @@ pub enum FullDefKind { })] self_predicate: TraitPredicate, /// Associated items, in definition order. - #[value(s.base().tcx.associated_items(s.owner_id()).in_definition_order().collect::>().sinto(s))] - items: Vec, + #[value( + s + .base() + .tcx + .associated_items(s.owner_id()) + .in_definition_order() + .map(|assoc| (assoc, assoc.def_id)) + .collect::>() + .sinto(s) + )] + items: Vec<(AssocItem, Arc)>, }, /// Type alias: `type Foo = Bar;` TyAlias { @@ -263,8 +271,17 @@ pub enum FullDefKind { #[value(s.base().tcx.impl_subject(s.owner_id()).instantiate_identity().sinto(s))] impl_subject: ImplSubject, /// Associated items, in definition order. - #[value(s.base().tcx.associated_items(s.owner_id()).in_definition_order().collect::>().sinto(s))] - items: Vec, + #[value( + s + .base() + .tcx + .associated_items(s.owner_id()) + .in_definition_order() + .map(|assoc| (assoc, assoc.def_id)) + .collect::>() + .sinto(s) + )] + items: Vec<(AssocItem, Arc)>, }, /// A field in a struct, enum or union. e.g. /// - `bar` in `struct Foo { bar: u8 }` From 651ae5a7d12cf20dd84d5b3aa0534a810d5e098d Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 14 Oct 2024 15:44:57 +0200 Subject: [PATCH 4/4] Add more information to `FullDef` --- frontend/exporter/src/types/copied.rs | 47 +++++++++++++++------ frontend/exporter/src/types/new/full_def.rs | 19 ++++++++- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/frontend/exporter/src/types/copied.rs b/frontend/exporter/src/types/copied.rs index f52897b03..453d95d10 100644 --- a/frontend/exporter/src/types/copied.rs +++ b/frontend/exporter/src/types/copied.rs @@ -3879,25 +3879,46 @@ pub enum PredicateKind { } /// Reflects [`rustc_middle::ty::ImplSubject`] -#[derive(AdtInto)] -#[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::ImplSubject<'tcx>, state: S as s)] #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum ImplSubject { - Trait( - // Also record the polarity. - #[map({ - let polarity = s.base().tcx.impl_polarity(s.owner_id()); - TraitPredicate { - trait_ref: x.sinto(s), - is_positive: matches!(polarity, rustc_middle::ty::ImplPolarity::Positive), - } - })] - TraitPredicate, - ), + Trait { + /// The trait that is implemented by this impl block. + trait_pred: TraitPredicate, + /// The `ImplExpr`s required to satisfy the predicates on the trait declaration. E.g.: + /// ```ignore + /// trait Foo: Bar {} + /// impl Foo for () {} // would supply an `ImplExpr` for `Self: Bar`. + /// ``` + required_impl_exprs: Vec, + }, Inherent(Ty), } +#[cfg(feature = "rustc")] +impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::ImplSubject<'tcx> { + fn sinto(&self, s: &S) -> ImplSubject { + let tcx = s.base().tcx; + match self { + ty::ImplSubject::Inherent(ty) => ImplSubject::Inherent(ty.sinto(s)), + ty::ImplSubject::Trait(trait_ref) => { + // Also record the polarity. + let polarity = tcx.impl_polarity(s.owner_id()); + let trait_pred = TraitPredicate { + trait_ref: trait_ref.sinto(s), + is_positive: matches!(polarity, rustc_middle::ty::ImplPolarity::Positive), + }; + let required_impl_exprs = + solve_item_traits(s, trait_ref.def_id, trait_ref.args, None); + ImplSubject::Trait { + trait_pred, + required_impl_exprs, + } + } + } + } +} + /// Reflects [`rustc_hir::GenericBounds`] type GenericBounds = Vec; diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 565c21f32..a24e9b357 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -13,7 +13,12 @@ pub struct FullDef { pub def_id: DefId, /// The enclosing item. pub parent: Option, + /// The span of the definition of this item (e.g. for a function this is is signature). pub span: Span, + /// The span of the whole definition (including e.g. the function body). + pub source_span: Option, + /// The text of the whole definition. + pub source_text: Option, /// Attributes on this definition, if applicable. pub attributes: Vec, /// Visibility of the definition, for definitions where this makes sense. @@ -37,10 +42,17 @@ impl<'tcx, S: BaseState<'tcx>> SInto> for RDefId { let state_with_id = with_owner_id(s.base(), (), (), def_id); tcx.def_kind(def_id).sinto(&state_with_id) }; + + let source_span = def_id.as_local().map(|ldid| tcx.source_span(ldid)); + let source_text = source_span + .filter(|source_span| source_span.ctxt().is_root()) + .and_then(|source_span| tcx.sess.source_map().span_to_snippet(source_span).ok()); let full_def = FullDef { def_id: self.sinto(s), parent: tcx.opt_parent(def_id).sinto(s), span: tcx.def_span(def_id).sinto(s), + source_span: source_span.sinto(s), + source_text, attributes: tcx.get_attrs_unchecked(def_id).sinto(s), visibility: get_def_visibility(tcx, def_id), lang_item: s @@ -99,7 +111,7 @@ pub enum FullDefKind { generics: TyGenerics, #[value(get_generic_predicates(s, s.owner_id()))] predicates: GenericPredicates, - // `predicates_of` has the special `Self: Trait` clause as its last element. + /// The special `Self: Trait` clause. #[value({ use ty::Upcast; let tcx = s.base().tcx; @@ -294,6 +306,11 @@ pub enum FullDefKind { } impl FullDef { + #[cfg(feature = "rustc")] + pub fn rust_def_id(&self) -> RDefId { + (&self.def_id).into() + } + pub fn kind(&self) -> &FullDefKind { &self.kind }