mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	BodyCollector
This commit is contained in:
		
							parent
							
								
									6012e961a7
								
							
						
					
					
						commit
						724455bf5a
					
				@ -25,8 +25,8 @@ use crate::{
 | 
			
		||||
    db::DefDatabase,
 | 
			
		||||
    expander::Expander,
 | 
			
		||||
    hir::{
 | 
			
		||||
        dummy_expr_id, Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label,
 | 
			
		||||
        LabelId, Pat, PatId, RecordFieldPat, Statement,
 | 
			
		||||
        Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label, LabelId, Pat,
 | 
			
		||||
        PatId, RecordFieldPat, Statement,
 | 
			
		||||
    },
 | 
			
		||||
    item_tree::AttrOwner,
 | 
			
		||||
    nameres::DefMap,
 | 
			
		||||
@ -81,7 +81,7 @@ pub struct Body {
 | 
			
		||||
    pub body_expr: ExprId,
 | 
			
		||||
    pub types: TypesMap,
 | 
			
		||||
    /// Block expressions in this body that may contain inner items.
 | 
			
		||||
    block_scopes: Vec<BlockId>,
 | 
			
		||||
    block_scopes: Box<[BlockId]>,
 | 
			
		||||
 | 
			
		||||
    /// A map from binding to its hygiene ID.
 | 
			
		||||
    ///
 | 
			
		||||
@ -98,6 +98,64 @@ pub struct Body {
 | 
			
		||||
    ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The body of an item (function, const etc.).
 | 
			
		||||
#[derive(Debug, Eq, PartialEq, Default)]
 | 
			
		||||
pub struct BodyCollector {
 | 
			
		||||
    pub exprs: Arena<Expr>,
 | 
			
		||||
    pub pats: Arena<Pat>,
 | 
			
		||||
    pub bindings: Arena<Binding>,
 | 
			
		||||
    pub labels: Arena<Label>,
 | 
			
		||||
    pub binding_owners: FxHashMap<BindingId, ExprId>,
 | 
			
		||||
    pub types: TypesMap,
 | 
			
		||||
    block_scopes: Vec<BlockId>,
 | 
			
		||||
    binding_hygiene: FxHashMap<BindingId, HygieneId>,
 | 
			
		||||
    ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl BodyCollector {
 | 
			
		||||
    fn finish(
 | 
			
		||||
        self,
 | 
			
		||||
        body_expr: ExprId,
 | 
			
		||||
        self_param: Option<BindingId>,
 | 
			
		||||
        params: Box<[PatId]>,
 | 
			
		||||
    ) -> Body {
 | 
			
		||||
        let Self {
 | 
			
		||||
            block_scopes,
 | 
			
		||||
            mut exprs,
 | 
			
		||||
            mut labels,
 | 
			
		||||
            mut pats,
 | 
			
		||||
            mut bindings,
 | 
			
		||||
            mut binding_owners,
 | 
			
		||||
            mut binding_hygiene,
 | 
			
		||||
            mut ident_hygiene,
 | 
			
		||||
            mut types,
 | 
			
		||||
        } = self;
 | 
			
		||||
        exprs.shrink_to_fit();
 | 
			
		||||
        labels.shrink_to_fit();
 | 
			
		||||
        pats.shrink_to_fit();
 | 
			
		||||
        bindings.shrink_to_fit();
 | 
			
		||||
        binding_owners.shrink_to_fit();
 | 
			
		||||
        binding_hygiene.shrink_to_fit();
 | 
			
		||||
        ident_hygiene.shrink_to_fit();
 | 
			
		||||
        types.shrink_to_fit();
 | 
			
		||||
 | 
			
		||||
        Body {
 | 
			
		||||
            exprs,
 | 
			
		||||
            pats,
 | 
			
		||||
            bindings,
 | 
			
		||||
            labels,
 | 
			
		||||
            binding_owners,
 | 
			
		||||
            params,
 | 
			
		||||
            self_param,
 | 
			
		||||
            body_expr,
 | 
			
		||||
            types,
 | 
			
		||||
            block_scopes: block_scopes.into_boxed_slice(),
 | 
			
		||||
            binding_hygiene,
 | 
			
		||||
            ident_hygiene,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub type ExprPtr = AstPtr<ast::Expr>;
 | 
			
		||||
pub type ExprSource = InFile<ExprPtr>;
 | 
			
		||||
 | 
			
		||||
@ -242,9 +300,8 @@ impl Body {
 | 
			
		||||
        };
 | 
			
		||||
        let module = def.module(db);
 | 
			
		||||
        let expander = Expander::new(db, file_id, module);
 | 
			
		||||
        let (mut body, mut source_map) =
 | 
			
		||||
        let (body, mut source_map) =
 | 
			
		||||
            Body::new(db, def, expander, params, body, module.krate, is_async_fn);
 | 
			
		||||
        body.shrink_to_fit();
 | 
			
		||||
        source_map.shrink_to_fit();
 | 
			
		||||
 | 
			
		||||
        (Arc::new(body), Arc::new(source_map))
 | 
			
		||||
@ -304,32 +361,6 @@ impl Body {
 | 
			
		||||
        lower::lower(db, owner, expander, params, body, krate, is_async_fn)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn shrink_to_fit(&mut self) {
 | 
			
		||||
        let Self {
 | 
			
		||||
            body_expr: _,
 | 
			
		||||
            params: _,
 | 
			
		||||
            self_param: _,
 | 
			
		||||
            block_scopes,
 | 
			
		||||
            exprs,
 | 
			
		||||
            labels,
 | 
			
		||||
            pats,
 | 
			
		||||
            bindings,
 | 
			
		||||
            binding_owners,
 | 
			
		||||
            binding_hygiene,
 | 
			
		||||
            ident_hygiene,
 | 
			
		||||
            types,
 | 
			
		||||
        } = self;
 | 
			
		||||
        block_scopes.shrink_to_fit();
 | 
			
		||||
        exprs.shrink_to_fit();
 | 
			
		||||
        labels.shrink_to_fit();
 | 
			
		||||
        pats.shrink_to_fit();
 | 
			
		||||
        bindings.shrink_to_fit();
 | 
			
		||||
        binding_owners.shrink_to_fit();
 | 
			
		||||
        binding_hygiene.shrink_to_fit();
 | 
			
		||||
        ident_hygiene.shrink_to_fit();
 | 
			
		||||
        types.shrink_to_fit();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
 | 
			
		||||
        self.walk_pats(pat_id, &mut |pat| {
 | 
			
		||||
            if let Pat::Bind { id, .. } = &self[pat] {
 | 
			
		||||
@ -670,25 +701,6 @@ impl Body {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for Body {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            body_expr: dummy_expr_id(),
 | 
			
		||||
            exprs: Default::default(),
 | 
			
		||||
            pats: Default::default(),
 | 
			
		||||
            bindings: Default::default(),
 | 
			
		||||
            labels: Default::default(),
 | 
			
		||||
            params: Default::default(),
 | 
			
		||||
            block_scopes: Default::default(),
 | 
			
		||||
            binding_owners: Default::default(),
 | 
			
		||||
            self_param: Default::default(),
 | 
			
		||||
            binding_hygiene: Default::default(),
 | 
			
		||||
            ident_hygiene: Default::default(),
 | 
			
		||||
            types: Default::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Index<ExprId> for Body {
 | 
			
		||||
    type Output = Expr;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,9 @@ use triomphe::Arc;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    attr::Attrs,
 | 
			
		||||
    body::{Body, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr},
 | 
			
		||||
    body::{
 | 
			
		||||
        Body, BodyCollector, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr,
 | 
			
		||||
    },
 | 
			
		||||
    builtin_type::BuiltinUint,
 | 
			
		||||
    data::adt::StructKind,
 | 
			
		||||
    db::DefDatabase,
 | 
			
		||||
@ -82,7 +84,7 @@ pub(super) fn lower(
 | 
			
		||||
        def_map: expander.module.def_map(db),
 | 
			
		||||
        source_map: BodySourceMap::default(),
 | 
			
		||||
        ast_id_map: db.ast_id_map(expander.current_file_id()),
 | 
			
		||||
        body: Body::default(),
 | 
			
		||||
        body: BodyCollector::default(),
 | 
			
		||||
        expander,
 | 
			
		||||
        current_try_block_label: None,
 | 
			
		||||
        is_lowering_coroutine: false,
 | 
			
		||||
@ -102,7 +104,7 @@ struct ExprCollector<'a> {
 | 
			
		||||
    def_map: Arc<DefMap>,
 | 
			
		||||
    ast_id_map: Arc<AstIdMap>,
 | 
			
		||||
    krate: CrateId,
 | 
			
		||||
    body: Body,
 | 
			
		||||
    body: BodyCollector,
 | 
			
		||||
    source_map: BodySourceMap,
 | 
			
		||||
 | 
			
		||||
    is_lowering_coroutine: bool,
 | 
			
		||||
@ -214,6 +216,9 @@ impl ExprCollector<'_> {
 | 
			
		||||
        body: Option<ast::Expr>,
 | 
			
		||||
        is_async_fn: bool,
 | 
			
		||||
    ) -> (Body, BodySourceMap) {
 | 
			
		||||
        let mut self_param = None;
 | 
			
		||||
        let mut params = vec![];
 | 
			
		||||
 | 
			
		||||
        let skip_body = match self.owner {
 | 
			
		||||
            DefWithBodyId::FunctionId(it) => self.db.attrs(it.into()),
 | 
			
		||||
            DefWithBodyId::StaticId(it) => self.db.attrs(it.into()),
 | 
			
		||||
@ -226,29 +231,32 @@ impl ExprCollector<'_> {
 | 
			
		||||
        // If #[rust_analyzer::skip] annotated, only construct enough information for the signature
 | 
			
		||||
        // and skip the body.
 | 
			
		||||
        if skip_body {
 | 
			
		||||
            self.body.body_expr = self.missing_expr();
 | 
			
		||||
            if let Some((param_list, mut attr_enabled)) = param_list {
 | 
			
		||||
                if let Some(self_param) =
 | 
			
		||||
                if let Some(self_param_syn) =
 | 
			
		||||
                    param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
 | 
			
		||||
                {
 | 
			
		||||
                    let is_mutable =
 | 
			
		||||
                        self_param.mut_token().is_some() && self_param.amp_token().is_none();
 | 
			
		||||
                    let is_mutable = self_param_syn.mut_token().is_some()
 | 
			
		||||
                        && self_param_syn.amp_token().is_none();
 | 
			
		||||
                    let binding_id: la_arena::Idx<Binding> = self.alloc_binding(
 | 
			
		||||
                        Name::new_symbol_root(sym::self_.clone()),
 | 
			
		||||
                        BindingAnnotation::new(is_mutable, false),
 | 
			
		||||
                    );
 | 
			
		||||
                    self.body.self_param = Some(binding_id);
 | 
			
		||||
                    self_param = Some(binding_id);
 | 
			
		||||
                    self.source_map.self_param =
 | 
			
		||||
                        Some(self.expander.in_file(AstPtr::new(&self_param)));
 | 
			
		||||
                        Some(self.expander.in_file(AstPtr::new(&self_param_syn)));
 | 
			
		||||
                }
 | 
			
		||||
                self.body.params = param_list
 | 
			
		||||
                params = param_list
 | 
			
		||||
                    .params()
 | 
			
		||||
                    .zip(attr_enabled)
 | 
			
		||||
                    .filter(|(_, enabled)| *enabled)
 | 
			
		||||
                    .map(|_| self.missing_pat())
 | 
			
		||||
                    .collect();
 | 
			
		||||
            };
 | 
			
		||||
            return (self.body, self.source_map);
 | 
			
		||||
            let body_expr = self.missing_expr();
 | 
			
		||||
            return (
 | 
			
		||||
                self.body.finish(body_expr, self_param, params.into_boxed_slice()),
 | 
			
		||||
                self.source_map,
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.awaitable_context.replace(if is_async_fn {
 | 
			
		||||
@ -264,25 +272,25 @@ impl ExprCollector<'_> {
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        if let Some((param_list, mut attr_enabled)) = param_list {
 | 
			
		||||
            let mut params = vec![];
 | 
			
		||||
            if let Some(self_param) =
 | 
			
		||||
            if let Some(self_param_syn) =
 | 
			
		||||
                param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
 | 
			
		||||
            {
 | 
			
		||||
                let is_mutable =
 | 
			
		||||
                    self_param.mut_token().is_some() && self_param.amp_token().is_none();
 | 
			
		||||
                    self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
 | 
			
		||||
                let binding_id: la_arena::Idx<Binding> = self.alloc_binding(
 | 
			
		||||
                    Name::new_symbol_root(sym::self_.clone()),
 | 
			
		||||
                    BindingAnnotation::new(is_mutable, false),
 | 
			
		||||
                );
 | 
			
		||||
                let hygiene = self_param
 | 
			
		||||
                let hygiene = self_param_syn
 | 
			
		||||
                    .name()
 | 
			
		||||
                    .map(|name| self.hygiene_id_for(name.syntax().text_range().start()))
 | 
			
		||||
                    .unwrap_or(HygieneId::ROOT);
 | 
			
		||||
                if !hygiene.is_root() {
 | 
			
		||||
                    self.body.binding_hygiene.insert(binding_id, hygiene);
 | 
			
		||||
                }
 | 
			
		||||
                self.body.self_param = Some(binding_id);
 | 
			
		||||
                self.source_map.self_param = Some(self.expander.in_file(AstPtr::new(&self_param)));
 | 
			
		||||
                self_param = Some(binding_id);
 | 
			
		||||
                self.source_map.self_param =
 | 
			
		||||
                    Some(self.expander.in_file(AstPtr::new(&self_param_syn)));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (param, _) in param_list.params().zip(attr_enabled).filter(|(_, enabled)| *enabled)
 | 
			
		||||
@ -290,9 +298,8 @@ impl ExprCollector<'_> {
 | 
			
		||||
                let param_pat = self.collect_pat_top(param.pat());
 | 
			
		||||
                params.push(param_pat);
 | 
			
		||||
            }
 | 
			
		||||
            self.body.params = params.into_boxed_slice();
 | 
			
		||||
        };
 | 
			
		||||
        self.body.body_expr = self.with_label_rib(RibKind::Closure, |this| {
 | 
			
		||||
        let body_expr = self.with_label_rib(RibKind::Closure, |this| {
 | 
			
		||||
            if is_async_fn {
 | 
			
		||||
                match body {
 | 
			
		||||
                    Some(e) => {
 | 
			
		||||
@ -310,7 +317,7 @@ impl ExprCollector<'_> {
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        (self.body, self.source_map)
 | 
			
		||||
        (self.body.finish(body_expr, self_param, params.into_boxed_slice()), self.source_map)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ctx(&mut self) -> LowerCtx<'_> {
 | 
			
		||||
@ -1934,7 +1941,7 @@ impl ExprCollector<'_> {
 | 
			
		||||
        f: impl FnOnce(&mut Self) -> T,
 | 
			
		||||
    ) -> T {
 | 
			
		||||
        self.label_ribs.push(LabelRib::new(RibKind::Normal(
 | 
			
		||||
            self.body[label].name.clone(),
 | 
			
		||||
            self.body.labels[label].name.clone(),
 | 
			
		||||
            label,
 | 
			
		||||
            hygiene,
 | 
			
		||||
        )));
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ use std::fmt;
 | 
			
		||||
 | 
			
		||||
use hir_expand::{name::Name, MacroDefId};
 | 
			
		||||
use intern::Symbol;
 | 
			
		||||
use la_arena::{Idx, RawIdx};
 | 
			
		||||
use la_arena::Idx;
 | 
			
		||||
use rustc_apfloat::ieee::{Half as f16, Quad as f128};
 | 
			
		||||
use syntax::ast;
 | 
			
		||||
use type_ref::TypeRefId;
 | 
			
		||||
@ -37,11 +37,6 @@ pub type BindingId = Idx<Binding>;
 | 
			
		||||
 | 
			
		||||
pub type ExprId = Idx<Expr>;
 | 
			
		||||
 | 
			
		||||
/// FIXME: this is a hacky function which should be removed
 | 
			
		||||
pub(crate) fn dummy_expr_id() -> ExprId {
 | 
			
		||||
    ExprId::from_raw(RawIdx::from(u32::MAX))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub type PatId = Idx<Pat>;
 | 
			
		||||
 | 
			
		||||
// FIXME: Encode this as a single u32, we won't ever reach all 32 bits especially given these counts
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user