mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	Shrink size of hir::Binding
This commit is contained in:
		
							parent
							
								
									83d7724629
								
							
						
					
					
						commit
						c3186202a2
					
				@ -37,6 +37,9 @@ pub struct Body {
 | 
			
		||||
    pub pats: Arena<Pat>,
 | 
			
		||||
    pub bindings: Arena<Binding>,
 | 
			
		||||
    pub labels: Arena<Label>,
 | 
			
		||||
    /// Id of the closure/generator that owns the corresponding binding. If a binding is owned by the
 | 
			
		||||
    /// top level expression, it will not be listed in here.
 | 
			
		||||
    pub binding_owners: FxHashMap<BindingId, ExprId>,
 | 
			
		||||
    /// The patterns for the function's parameters. While the parameter types are
 | 
			
		||||
    /// part of the function signature, the patterns are not (they don't change
 | 
			
		||||
    /// the external type of the function).
 | 
			
		||||
@ -206,14 +209,24 @@ impl Body {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn shrink_to_fit(&mut self) {
 | 
			
		||||
        let Self { _c: _, body_expr: _, block_scopes, exprs, labels, params, pats, bindings } =
 | 
			
		||||
            self;
 | 
			
		||||
        let Self {
 | 
			
		||||
            _c: _,
 | 
			
		||||
            body_expr: _,
 | 
			
		||||
            block_scopes,
 | 
			
		||||
            exprs,
 | 
			
		||||
            labels,
 | 
			
		||||
            params,
 | 
			
		||||
            pats,
 | 
			
		||||
            bindings,
 | 
			
		||||
            binding_owners,
 | 
			
		||||
        } = self;
 | 
			
		||||
        block_scopes.shrink_to_fit();
 | 
			
		||||
        exprs.shrink_to_fit();
 | 
			
		||||
        labels.shrink_to_fit();
 | 
			
		||||
        params.shrink_to_fit();
 | 
			
		||||
        pats.shrink_to_fit();
 | 
			
		||||
        bindings.shrink_to_fit();
 | 
			
		||||
        binding_owners.shrink_to_fit();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
 | 
			
		||||
@ -257,6 +270,17 @@ impl Body {
 | 
			
		||||
        f(pat_id);
 | 
			
		||||
        self.walk_pats_shallow(pat_id, |p| self.walk_pats(p, f));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn is_binding_upvar(&self, binding: BindingId, relative_to: ExprId) -> bool {
 | 
			
		||||
        match self.binding_owners.get(&binding) {
 | 
			
		||||
            Some(x) => {
 | 
			
		||||
                // We assign expression ids in a way that outer closures will receive
 | 
			
		||||
                // a lower id
 | 
			
		||||
                x.into_raw() < relative_to.into_raw()
 | 
			
		||||
            }
 | 
			
		||||
            None => true,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for Body {
 | 
			
		||||
@ -269,6 +293,7 @@ impl Default for Body {
 | 
			
		||||
            labels: Default::default(),
 | 
			
		||||
            params: Default::default(),
 | 
			
		||||
            block_scopes: Default::default(),
 | 
			
		||||
            binding_owners: Default::default(),
 | 
			
		||||
            _c: Default::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,6 @@ use hir_expand::{
 | 
			
		||||
    AstId, ExpandError, InFile,
 | 
			
		||||
};
 | 
			
		||||
use intern::Interned;
 | 
			
		||||
use la_arena::Arena;
 | 
			
		||||
use profile::Count;
 | 
			
		||||
use rustc_hash::FxHashMap;
 | 
			
		||||
use smallvec::SmallVec;
 | 
			
		||||
@ -60,10 +59,11 @@ pub(super) fn lower(
 | 
			
		||||
        source_map: BodySourceMap::default(),
 | 
			
		||||
        ast_id_map: db.ast_id_map(expander.current_file_id),
 | 
			
		||||
        body: Body {
 | 
			
		||||
            exprs: Arena::default(),
 | 
			
		||||
            pats: Arena::default(),
 | 
			
		||||
            bindings: Arena::default(),
 | 
			
		||||
            labels: Arena::default(),
 | 
			
		||||
            exprs: Default::default(),
 | 
			
		||||
            pats: Default::default(),
 | 
			
		||||
            bindings: Default::default(),
 | 
			
		||||
            binding_owners: Default::default(),
 | 
			
		||||
            labels: Default::default(),
 | 
			
		||||
            params: Vec::new(),
 | 
			
		||||
            body_expr: dummy_expr_id(),
 | 
			
		||||
            block_scopes: Vec::new(),
 | 
			
		||||
@ -1540,13 +1540,16 @@ impl ExprCollector<'_> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn alloc_binding(&mut self, name: Name, mode: BindingAnnotation) -> BindingId {
 | 
			
		||||
        self.body.bindings.alloc(Binding {
 | 
			
		||||
        let binding = self.body.bindings.alloc(Binding {
 | 
			
		||||
            name,
 | 
			
		||||
            mode,
 | 
			
		||||
            definitions: SmallVec::new(),
 | 
			
		||||
            owner: self.current_binding_owner,
 | 
			
		||||
            problems: None,
 | 
			
		||||
        })
 | 
			
		||||
        });
 | 
			
		||||
        if let Some(owner) = self.current_binding_owner {
 | 
			
		||||
            self.body.binding_owners.insert(binding, owner);
 | 
			
		||||
        }
 | 
			
		||||
        binding
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
 | 
			
		||||
 | 
			
		||||
@ -501,25 +501,9 @@ pub struct Binding {
 | 
			
		||||
    pub name: Name,
 | 
			
		||||
    pub mode: BindingAnnotation,
 | 
			
		||||
    pub definitions: SmallVec<[PatId; 1]>,
 | 
			
		||||
    /// Id of the closure/generator that owns this binding. If it is owned by the
 | 
			
		||||
    /// top level expression, this field would be `None`.
 | 
			
		||||
    pub owner: Option<ExprId>,
 | 
			
		||||
    pub problems: Option<BindingProblems>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Binding {
 | 
			
		||||
    pub fn is_upvar(&self, relative_to: ExprId) -> bool {
 | 
			
		||||
        match self.owner {
 | 
			
		||||
            Some(x) => {
 | 
			
		||||
                // We assign expression ids in a way that outer closures will receive
 | 
			
		||||
                // a lower id
 | 
			
		||||
                x.into_raw() < relative_to.into_raw()
 | 
			
		||||
            }
 | 
			
		||||
            None => true,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Eq, PartialEq)]
 | 
			
		||||
pub struct RecordFieldPat {
 | 
			
		||||
    pub name: Name,
 | 
			
		||||
 | 
			
		||||
@ -715,10 +715,9 @@ impl InferenceContext<'_> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn is_upvar(&self, place: &HirPlace) -> bool {
 | 
			
		||||
        let b = &self.body[place.local];
 | 
			
		||||
        if let Some(c) = self.current_closure {
 | 
			
		||||
            let (_, root) = self.db.lookup_intern_closure(c.into());
 | 
			
		||||
            return b.is_upvar(root);
 | 
			
		||||
            return self.body.is_binding_upvar(place.local, root);
 | 
			
		||||
        }
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1853,7 +1853,7 @@ pub fn mir_body_for_closure_query(
 | 
			
		||||
        .result
 | 
			
		||||
        .binding_locals
 | 
			
		||||
        .into_iter()
 | 
			
		||||
        .filter(|x| ctx.body[x.0].owner == Some(expr))
 | 
			
		||||
        .filter(|it| ctx.body.binding_owners.get(&it.0).copied() == Some(expr))
 | 
			
		||||
        .collect();
 | 
			
		||||
    if let Some(err) = err {
 | 
			
		||||
        return Err(MirLowerError::UnresolvedUpvar(err));
 | 
			
		||||
@ -1909,10 +1909,11 @@ pub fn lower_to_mir(
 | 
			
		||||
    // 0 is return local
 | 
			
		||||
    ctx.result.locals.alloc(Local { ty: ctx.expr_ty_after_adjustments(root_expr) });
 | 
			
		||||
    let binding_picker = |b: BindingId| {
 | 
			
		||||
        let owner = ctx.body.binding_owners.get(&b).copied();
 | 
			
		||||
        if root_expr == body.body_expr {
 | 
			
		||||
            body[b].owner.is_none()
 | 
			
		||||
            owner.is_none()
 | 
			
		||||
        } else {
 | 
			
		||||
            body[b].owner == Some(root_expr)
 | 
			
		||||
            owner == Some(root_expr)
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    // 1 to param_len is for params
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user