mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-13 13:57:25 +00:00
Merge pull request #19036 from Veykril/push-nprltlwvryxw
Split out `ExpressionStore` from `Body`
This commit is contained in:
commit
35b55fd67f
38 changed files with 649 additions and 530 deletions
|
@ -10,12 +10,12 @@ use triomphe::Arc;
|
|||
|
||||
use crate::{
|
||||
attr::{Attrs, AttrsWithOwner},
|
||||
body::{scope::ExprScopes, Body, BodySourceMap},
|
||||
data::{
|
||||
adt::{EnumData, EnumVariantData, StructData, VariantData},
|
||||
ConstData, ExternCrateDeclData, FunctionData, ImplData, Macro2Data, MacroRulesData,
|
||||
ProcMacroData, StaticData, TraitAliasData, TraitData, TypeAliasData,
|
||||
},
|
||||
expr_store::{scope::ExprScopes, Body, BodySourceMap},
|
||||
generics::GenericParams,
|
||||
import_map::ImportMap,
|
||||
item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps},
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
//! Defines `Body`: a lowered representation of bodies of functions, statics and
|
||||
//! Defines `ExpressionStore`: a lowered representation of functions, statics and
|
||||
//! consts.
|
||||
mod body;
|
||||
mod lower;
|
||||
mod pretty;
|
||||
pub mod scope;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use std::ops::{Deref, Index};
|
||||
|
||||
use base_db::CrateId;
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use either::Either;
|
||||
use hir_expand::{name::Name, ExpandError, InFile};
|
||||
use la_arena::{Arena, ArenaMap, Idx, RawIdx};
|
||||
use la_arena::{Arena, ArenaMap};
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use span::{Edition, MacroFileId, SyntaxContextData};
|
||||
|
@ -22,19 +23,18 @@ use tt::TextRange;
|
|||
|
||||
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,
|
||||
path::{ModPath, Path},
|
||||
src::HasSource,
|
||||
type_ref::{TypeRef, TypeRefId, TypesMap, TypesSourceMap},
|
||||
BlockId, DefWithBodyId, HasModule, Lookup, SyntheticSyntax,
|
||||
BlockId, DefWithBodyId, Lookup, SyntheticSyntax,
|
||||
};
|
||||
|
||||
pub use self::body::{Body, BodySourceMap};
|
||||
|
||||
/// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct HygieneId(span::SyntaxContextId);
|
||||
|
@ -58,47 +58,6 @@ impl HygieneId {
|
|||
}
|
||||
}
|
||||
|
||||
/// The body of an item (function, const etc.).
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Body {
|
||||
pub exprs: Arena<Expr>,
|
||||
pub pats: Arena<Pat>,
|
||||
pub bindings: Arena<Binding>,
|
||||
pub labels: Arena<Label>,
|
||||
/// Id of the closure/coroutine 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).
|
||||
///
|
||||
/// If this `Body` is for the body of a constant, this will just be
|
||||
/// empty.
|
||||
pub params: Box<[PatId]>,
|
||||
pub self_param: Option<BindingId>,
|
||||
/// The `ExprId` of the actual body expression.
|
||||
pub body_expr: ExprId,
|
||||
pub types: TypesMap,
|
||||
/// Block expressions in this body that may contain inner items.
|
||||
block_scopes: Vec<BlockId>,
|
||||
|
||||
/// A map from binding to its hygiene ID.
|
||||
///
|
||||
/// Bindings that don't come from macro expansion are not allocated to save space, so not all bindings appear here.
|
||||
/// If a binding does not appear here it has `SyntaxContextId::ROOT`.
|
||||
///
|
||||
/// Note that this may not be the direct `SyntaxContextId` of the binding's expansion, because transparent
|
||||
/// expansions are attributed to their parent expansion (recursively).
|
||||
binding_hygiene: FxHashMap<BindingId, HygieneId>,
|
||||
/// A map from an variable usages to their hygiene ID.
|
||||
///
|
||||
/// Expressions that can be recorded here are single segment path, although not all single segments path refer
|
||||
/// to variables and have hygiene (some refer to items, we don't know at this stage).
|
||||
expr_hygiene: FxHashMap<ExprId, HygieneId>,
|
||||
/// A map from a destructuring assignment possible variable usages to their hygiene ID.
|
||||
pat_hygiene: FxHashMap<PatId, HygieneId>,
|
||||
}
|
||||
|
||||
pub type ExprPtr = AstPtr<ast::Expr>;
|
||||
pub type ExprSource = InFile<ExprPtr>;
|
||||
|
||||
|
@ -117,19 +76,39 @@ pub type PatFieldSource = InFile<PatFieldPtr>;
|
|||
pub type ExprOrPatPtr = AstPtr<Either<ast::Expr, ast::Pat>>;
|
||||
pub type ExprOrPatSource = InFile<ExprOrPatPtr>;
|
||||
|
||||
/// An item body together with the mapping from syntax nodes to HIR expression
|
||||
/// IDs. This is needed to go from e.g. a position in a file to the HIR
|
||||
/// expression containing it; but for type inference etc., we want to operate on
|
||||
/// a structure that is agnostic to the actual positions of expressions in the
|
||||
/// file, so that we don't recompute types whenever some whitespace is typed.
|
||||
///
|
||||
/// One complication here is that, due to macro expansion, a single `Body` might
|
||||
/// be spread across several files. So, for each ExprId and PatId, we record
|
||||
/// both the HirFileId and the position inside the file. However, we only store
|
||||
/// AST -> ExprId mapping for non-macro files, as it is not clear how to handle
|
||||
/// this properly for macros.
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
pub struct BodySourceMap {
|
||||
pub type SelfParamPtr = AstPtr<ast::SelfParam>;
|
||||
pub type MacroCallPtr = AstPtr<ast::MacroCall>;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct ExpressionStore {
|
||||
pub exprs: Arena<Expr>,
|
||||
pub pats: Arena<Pat>,
|
||||
pub bindings: Arena<Binding>,
|
||||
pub labels: Arena<Label>,
|
||||
/// Id of the closure/coroutine 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>,
|
||||
pub types: TypesMap,
|
||||
/// Block expressions in this store that may contain inner items.
|
||||
block_scopes: Box<[BlockId]>,
|
||||
|
||||
/// A map from binding to its hygiene ID.
|
||||
///
|
||||
/// Bindings that don't come from macro expansion are not allocated to save space, so not all bindings appear here.
|
||||
/// If a binding does not appear here it has `SyntaxContextId::ROOT`.
|
||||
///
|
||||
/// Note that this may not be the direct `SyntaxContextId` of the binding's expansion, because transparent
|
||||
/// expansions are attributed to their parent expansion (recursively).
|
||||
binding_hygiene: FxHashMap<BindingId, HygieneId>,
|
||||
/// A map from an variable usages to their hygiene ID.
|
||||
///
|
||||
/// Expressions (and destructuing patterns) that can be recorded here are single segment path, although not all single segments path refer
|
||||
/// to variables and have hygiene (some refer to items, we don't know at this stage).
|
||||
ident_hygiene: FxHashMap<ExprOrPatId, HygieneId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Default)]
|
||||
pub struct ExpressionStoreSourceMap {
|
||||
// AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map
|
||||
// to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected).
|
||||
expr_map: FxHashMap<ExprSource, ExprOrPatId>,
|
||||
|
@ -141,7 +120,6 @@ pub struct BodySourceMap {
|
|||
label_map: FxHashMap<LabelSource, LabelId>,
|
||||
label_map_back: ArenaMap<LabelId, LabelSource>,
|
||||
|
||||
self_param: Option<InFile<AstPtr<ast::SelfParam>>>,
|
||||
binding_definitions: FxHashMap<BindingId, SmallVec<[PatId; 4]>>,
|
||||
|
||||
/// We don't create explicit nodes for record fields (`S { record_field: 92 }`).
|
||||
|
@ -153,11 +131,25 @@ pub struct BodySourceMap {
|
|||
|
||||
template_map: Option<Box<FormatTemplate>>,
|
||||
|
||||
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, MacroFileId>,
|
||||
expansions: FxHashMap<InFile<MacroCallPtr>, MacroFileId>,
|
||||
|
||||
/// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in
|
||||
/// Diagnostics accumulated during lowering. These contain `AstPtr`s and so are stored in
|
||||
/// the source map (since they're just as volatile).
|
||||
diagnostics: Vec<BodyDiagnostic>,
|
||||
diagnostics: Vec<ExpressionStoreDiagnostics>,
|
||||
}
|
||||
|
||||
/// The body of an item (function, const etc.).
|
||||
#[derive(Debug, Eq, PartialEq, Default)]
|
||||
pub struct ExpressionStoreBuilder {
|
||||
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>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
|
@ -171,166 +163,62 @@ struct FormatTemplate {
|
|||
/// The value stored for each capture is its template literal and offset inside it. The template literal
|
||||
/// is from the `format_args[_nl]!()` macro and so needs to be mapped up once to go to the user-written
|
||||
/// template.
|
||||
implicit_capture_to_source: FxHashMap<ExprId, InFile<(AstPtr<ast::Expr>, TextRange)>>,
|
||||
implicit_capture_to_source: FxHashMap<ExprId, InFile<(ExprPtr, TextRange)>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum BodyDiagnostic {
|
||||
pub enum ExpressionStoreDiagnostics {
|
||||
InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
|
||||
MacroError { node: InFile<AstPtr<ast::MacroCall>>, err: ExpandError },
|
||||
UnresolvedMacroCall { node: InFile<AstPtr<ast::MacroCall>>, path: ModPath },
|
||||
MacroError { node: InFile<MacroCallPtr>, err: ExpandError },
|
||||
UnresolvedMacroCall { node: InFile<MacroCallPtr>, path: ModPath },
|
||||
UnreachableLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
|
||||
AwaitOutsideOfAsync { node: InFile<AstPtr<ast::AwaitExpr>>, location: String },
|
||||
UndeclaredLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
|
||||
}
|
||||
|
||||
impl Body {
|
||||
pub(crate) fn body_with_source_map_query(
|
||||
db: &dyn DefDatabase,
|
||||
def: DefWithBodyId,
|
||||
) -> (Arc<Body>, Arc<BodySourceMap>) {
|
||||
let _p = tracing::info_span!("body_with_source_map_query").entered();
|
||||
let mut params = None;
|
||||
|
||||
let mut is_async_fn = false;
|
||||
let InFile { file_id, value: body } = {
|
||||
match def {
|
||||
DefWithBodyId::FunctionId(f) => {
|
||||
let data = db.function_data(f);
|
||||
let f = f.lookup(db);
|
||||
let src = f.source(db);
|
||||
params = src.value.param_list().map(move |param_list| {
|
||||
let item_tree = f.id.item_tree(db);
|
||||
let func = &item_tree[f.id.value];
|
||||
let krate = f.container.module(db).krate;
|
||||
let crate_graph = db.crate_graph();
|
||||
(
|
||||
param_list,
|
||||
(0..func.params.len()).map(move |idx| {
|
||||
item_tree
|
||||
.attrs(
|
||||
db,
|
||||
krate,
|
||||
AttrOwner::Param(
|
||||
f.id.value,
|
||||
Idx::from_raw(RawIdx::from(idx as u32)),
|
||||
),
|
||||
)
|
||||
.is_cfg_enabled(&crate_graph[krate].cfg_options)
|
||||
}),
|
||||
)
|
||||
});
|
||||
is_async_fn = data.is_async();
|
||||
src.map(|it| it.body().map(ast::Expr::from))
|
||||
}
|
||||
DefWithBodyId::ConstId(c) => {
|
||||
let c = c.lookup(db);
|
||||
let src = c.source(db);
|
||||
src.map(|it| it.body())
|
||||
}
|
||||
DefWithBodyId::StaticId(s) => {
|
||||
let s = s.lookup(db);
|
||||
let src = s.source(db);
|
||||
src.map(|it| it.body())
|
||||
}
|
||||
DefWithBodyId::VariantId(v) => {
|
||||
let s = v.lookup(db);
|
||||
let src = s.source(db);
|
||||
src.map(|it| it.expr())
|
||||
}
|
||||
DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()),
|
||||
}
|
||||
};
|
||||
let module = def.module(db);
|
||||
let expander = Expander::new(db, file_id, module);
|
||||
let (mut 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))
|
||||
}
|
||||
|
||||
pub(crate) fn body_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<Body> {
|
||||
db.body_with_source_map(def).0
|
||||
}
|
||||
|
||||
/// Returns an iterator over all block expressions in this body that define inner items.
|
||||
pub fn blocks<'a>(
|
||||
&'a self,
|
||||
db: &'a dyn DefDatabase,
|
||||
) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + 'a {
|
||||
self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block)))
|
||||
}
|
||||
|
||||
pub fn pretty_print(
|
||||
&self,
|
||||
db: &dyn DefDatabase,
|
||||
owner: DefWithBodyId,
|
||||
edition: Edition,
|
||||
) -> String {
|
||||
pretty::print_body_hir(db, self, owner, edition)
|
||||
}
|
||||
|
||||
pub fn pretty_print_expr(
|
||||
&self,
|
||||
db: &dyn DefDatabase,
|
||||
owner: DefWithBodyId,
|
||||
expr: ExprId,
|
||||
edition: Edition,
|
||||
) -> String {
|
||||
pretty::print_expr_hir(db, self, owner, expr, edition)
|
||||
}
|
||||
|
||||
pub fn pretty_print_pat(
|
||||
&self,
|
||||
db: &dyn DefDatabase,
|
||||
owner: DefWithBodyId,
|
||||
pat: PatId,
|
||||
oneline: bool,
|
||||
edition: Edition,
|
||||
) -> String {
|
||||
pretty::print_pat_hir(db, self, owner, pat, oneline, edition)
|
||||
}
|
||||
|
||||
fn new(
|
||||
db: &dyn DefDatabase,
|
||||
owner: DefWithBodyId,
|
||||
expander: Expander,
|
||||
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
||||
body: Option<ast::Expr>,
|
||||
krate: CrateId,
|
||||
is_async_fn: bool,
|
||||
) -> (Body, BodySourceMap) {
|
||||
lower::lower(db, owner, expander, params, body, krate, is_async_fn)
|
||||
}
|
||||
|
||||
fn shrink_to_fit(&mut self) {
|
||||
impl ExpressionStoreBuilder {
|
||||
fn finish(self) -> ExpressionStore {
|
||||
let Self {
|
||||
body_expr: _,
|
||||
params: _,
|
||||
self_param: _,
|
||||
block_scopes,
|
||||
exprs,
|
||||
labels,
|
||||
pats,
|
||||
bindings,
|
||||
binding_owners,
|
||||
binding_hygiene,
|
||||
expr_hygiene,
|
||||
pat_hygiene,
|
||||
types,
|
||||
mut exprs,
|
||||
mut labels,
|
||||
mut pats,
|
||||
mut bindings,
|
||||
mut binding_owners,
|
||||
mut binding_hygiene,
|
||||
mut ident_hygiene,
|
||||
mut 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();
|
||||
expr_hygiene.shrink_to_fit();
|
||||
pat_hygiene.shrink_to_fit();
|
||||
ident_hygiene.shrink_to_fit();
|
||||
types.shrink_to_fit();
|
||||
|
||||
ExpressionStore {
|
||||
exprs,
|
||||
pats,
|
||||
bindings,
|
||||
labels,
|
||||
binding_owners,
|
||||
types,
|
||||
block_scopes: block_scopes.into_boxed_slice(),
|
||||
binding_hygiene,
|
||||
ident_hygiene,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExpressionStore {
|
||||
/// Returns an iterator over all block expressions in this store that define inner items.
|
||||
pub fn blocks<'a>(
|
||||
&'a self,
|
||||
db: &'a dyn DefDatabase,
|
||||
) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + 'a {
|
||||
self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block)))
|
||||
}
|
||||
|
||||
pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
|
||||
|
@ -658,11 +546,11 @@ impl Body {
|
|||
}
|
||||
|
||||
pub fn expr_path_hygiene(&self, expr: ExprId) -> HygieneId {
|
||||
self.expr_hygiene.get(&expr).copied().unwrap_or(HygieneId::ROOT)
|
||||
self.ident_hygiene.get(&expr.into()).copied().unwrap_or(HygieneId::ROOT)
|
||||
}
|
||||
|
||||
pub fn pat_path_hygiene(&self, pat: PatId) -> HygieneId {
|
||||
self.pat_hygiene.get(&pat).copied().unwrap_or(HygieneId::ROOT)
|
||||
self.ident_hygiene.get(&pat.into()).copied().unwrap_or(HygieneId::ROOT)
|
||||
}
|
||||
|
||||
pub fn expr_or_pat_path_hygiene(&self, id: ExprOrPatId) -> HygieneId {
|
||||
|
@ -673,27 +561,7 @@ 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(),
|
||||
expr_hygiene: Default::default(),
|
||||
pat_hygiene: Default::default(),
|
||||
types: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<ExprId> for Body {
|
||||
impl Index<ExprId> for ExpressionStore {
|
||||
type Output = Expr;
|
||||
|
||||
fn index(&self, expr: ExprId) -> &Expr {
|
||||
|
@ -701,7 +569,7 @@ impl Index<ExprId> for Body {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<PatId> for Body {
|
||||
impl Index<PatId> for ExpressionStore {
|
||||
type Output = Pat;
|
||||
|
||||
fn index(&self, pat: PatId) -> &Pat {
|
||||
|
@ -709,7 +577,7 @@ impl Index<PatId> for Body {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<LabelId> for Body {
|
||||
impl Index<LabelId> for ExpressionStore {
|
||||
type Output = Label;
|
||||
|
||||
fn index(&self, label: LabelId) -> &Label {
|
||||
|
@ -717,7 +585,7 @@ impl Index<LabelId> for Body {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<BindingId> for Body {
|
||||
impl Index<BindingId> for ExpressionStore {
|
||||
type Output = Binding;
|
||||
|
||||
fn index(&self, b: BindingId) -> &Binding {
|
||||
|
@ -725,7 +593,7 @@ impl Index<BindingId> for Body {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<TypeRefId> for Body {
|
||||
impl Index<TypeRefId> for ExpressionStore {
|
||||
type Output = TypeRef;
|
||||
|
||||
fn index(&self, b: TypeRefId) -> &TypeRef {
|
||||
|
@ -735,7 +603,7 @@ impl Index<TypeRefId> for Body {
|
|||
|
||||
// FIXME: Change `node_` prefix to something more reasonable.
|
||||
// Perhaps `expr_syntax` and `expr_id`?
|
||||
impl BodySourceMap {
|
||||
impl ExpressionStoreSourceMap {
|
||||
pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
|
||||
match id {
|
||||
ExprOrPatId::ExprId(id) => self.expr_syntax(id).map(|it| it.map(AstPtr::wrap_left)),
|
||||
|
@ -757,9 +625,7 @@ impl BodySourceMap {
|
|||
self.expansions.get(&src).cloned()
|
||||
}
|
||||
|
||||
pub fn macro_calls(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (InFile<AstPtr<ast::MacroCall>>, MacroFileId)> + '_ {
|
||||
pub fn macro_calls(&self) -> impl Iterator<Item = (InFile<MacroCallPtr>, MacroFileId)> + '_ {
|
||||
self.expansions.iter().map(|(&a, &b)| (a, b))
|
||||
}
|
||||
|
||||
|
@ -767,10 +633,6 @@ impl BodySourceMap {
|
|||
self.pat_map_back.get(pat).cloned().ok_or(SyntheticSyntax)
|
||||
}
|
||||
|
||||
pub fn self_param_syntax(&self) -> Option<InFile<AstPtr<ast::SelfParam>>> {
|
||||
self.self_param
|
||||
}
|
||||
|
||||
pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> {
|
||||
self.pat_map.get(&node.map(AstPtr::new)).cloned()
|
||||
}
|
||||
|
@ -801,9 +663,7 @@ impl BodySourceMap {
|
|||
self.expr_map.get(&src).copied()
|
||||
}
|
||||
|
||||
pub fn expansions(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&InFile<AstPtr<ast::MacroCall>>, &MacroFileId)> {
|
||||
pub fn expansions(&self) -> impl Iterator<Item = (&InFile<MacroCallPtr>, &MacroFileId)> {
|
||||
self.expansions.iter()
|
||||
}
|
||||
|
||||
|
@ -823,7 +683,7 @@ impl BodySourceMap {
|
|||
pub fn format_args_implicit_capture(
|
||||
&self,
|
||||
capture_expr: ExprId,
|
||||
) -> Option<InFile<(AstPtr<ast::Expr>, TextRange)>> {
|
||||
) -> Option<InFile<(ExprPtr, TextRange)>> {
|
||||
self.template_map.as_ref()?.implicit_capture_to_source.get(&capture_expr).copied()
|
||||
}
|
||||
|
||||
|
@ -837,14 +697,13 @@ impl BodySourceMap {
|
|||
.zip(self.template_map.as_ref()?.asm_to_captures.get(&expr).map(std::ops::Deref::deref))
|
||||
}
|
||||
|
||||
/// Get a reference to the body source map's diagnostics.
|
||||
pub fn diagnostics(&self) -> &[BodyDiagnostic] {
|
||||
/// Get a reference to the source map's diagnostics.
|
||||
pub fn diagnostics(&self) -> &[ExpressionStoreDiagnostics] {
|
||||
&self.diagnostics
|
||||
}
|
||||
|
||||
fn shrink_to_fit(&mut self) {
|
||||
let Self {
|
||||
self_param: _,
|
||||
expr_map,
|
||||
expr_map_back,
|
||||
pat_map,
|
175
crates/hir-def/src/expr_store/body.rs
Normal file
175
crates/hir-def/src/expr_store/body.rs
Normal file
|
@ -0,0 +1,175 @@
|
|||
//! Defines `Body`: a lowered representation of functions, statics and
|
||||
//! consts.
|
||||
use std::ops;
|
||||
|
||||
use hir_expand::{InFile, Lookup};
|
||||
use la_arena::{Idx, RawIdx};
|
||||
use span::Edition;
|
||||
use syntax::ast;
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase,
|
||||
expander::Expander,
|
||||
expr_store::{lower, pretty, ExpressionStore, ExpressionStoreSourceMap, SelfParamPtr},
|
||||
hir::{BindingId, ExprId, PatId},
|
||||
item_tree::AttrOwner,
|
||||
src::HasSource,
|
||||
DefWithBodyId, HasModule,
|
||||
};
|
||||
|
||||
/// The body of an item (function, const etc.).
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct Body {
|
||||
pub store: ExpressionStore,
|
||||
/// 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).
|
||||
///
|
||||
/// If this `Body` is for the body of a constant, this will just be
|
||||
/// empty.
|
||||
pub params: Box<[PatId]>,
|
||||
pub self_param: Option<BindingId>,
|
||||
/// The `ExprId` of the actual body expression.
|
||||
pub body_expr: ExprId,
|
||||
}
|
||||
|
||||
impl ops::Deref for Body {
|
||||
type Target = ExpressionStore;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.store
|
||||
}
|
||||
}
|
||||
|
||||
/// An item body together with the mapping from syntax nodes to HIR expression
|
||||
/// IDs. This is needed to go from e.g. a position in a file to the HIR
|
||||
/// expression containing it; but for type inference etc., we want to operate on
|
||||
/// a structure that is agnostic to the actual positions of expressions in the
|
||||
/// file, so that we don't recompute types whenever some whitespace is typed.
|
||||
///
|
||||
/// One complication here is that, due to macro expansion, a single `Body` might
|
||||
/// be spread across several files. So, for each ExprId and PatId, we record
|
||||
/// both the HirFileId and the position inside the file. However, we only store
|
||||
/// AST -> ExprId mapping for non-macro files, as it is not clear how to handle
|
||||
/// this properly for macros.
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
pub struct BodySourceMap {
|
||||
pub self_param: Option<InFile<SelfParamPtr>>,
|
||||
pub store: ExpressionStoreSourceMap,
|
||||
}
|
||||
|
||||
impl ops::Deref for BodySourceMap {
|
||||
type Target = ExpressionStoreSourceMap;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.store
|
||||
}
|
||||
}
|
||||
|
||||
impl Body {
|
||||
pub(crate) fn body_with_source_map_query(
|
||||
db: &dyn DefDatabase,
|
||||
def: DefWithBodyId,
|
||||
) -> (Arc<Body>, Arc<BodySourceMap>) {
|
||||
let _p = tracing::info_span!("body_with_source_map_query").entered();
|
||||
let mut params = None;
|
||||
|
||||
let mut is_async_fn = false;
|
||||
let InFile { file_id, value: body } = {
|
||||
match def {
|
||||
DefWithBodyId::FunctionId(f) => {
|
||||
let data = db.function_data(f);
|
||||
let f = f.lookup(db);
|
||||
let src = f.source(db);
|
||||
params = src.value.param_list().map(move |param_list| {
|
||||
let item_tree = f.id.item_tree(db);
|
||||
let func = &item_tree[f.id.value];
|
||||
let krate = f.container.module(db).krate;
|
||||
let crate_graph = db.crate_graph();
|
||||
(
|
||||
param_list,
|
||||
(0..func.params.len()).map(move |idx| {
|
||||
item_tree
|
||||
.attrs(
|
||||
db,
|
||||
krate,
|
||||
AttrOwner::Param(
|
||||
f.id.value,
|
||||
Idx::from_raw(RawIdx::from(idx as u32)),
|
||||
),
|
||||
)
|
||||
.is_cfg_enabled(&crate_graph[krate].cfg_options)
|
||||
}),
|
||||
)
|
||||
});
|
||||
is_async_fn = data.is_async();
|
||||
src.map(|it| it.body().map(ast::Expr::from))
|
||||
}
|
||||
DefWithBodyId::ConstId(c) => {
|
||||
let c = c.lookup(db);
|
||||
let src = c.source(db);
|
||||
src.map(|it| it.body())
|
||||
}
|
||||
DefWithBodyId::StaticId(s) => {
|
||||
let s = s.lookup(db);
|
||||
let src = s.source(db);
|
||||
src.map(|it| it.body())
|
||||
}
|
||||
DefWithBodyId::VariantId(v) => {
|
||||
let s = v.lookup(db);
|
||||
let src = s.source(db);
|
||||
src.map(|it| it.expr())
|
||||
}
|
||||
DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()),
|
||||
}
|
||||
};
|
||||
let module = def.module(db);
|
||||
let expander = Expander::new(db, file_id, module);
|
||||
let (body, mut source_map) =
|
||||
lower::lower_body(db, def, expander, params, body, module.krate, is_async_fn);
|
||||
source_map.store.shrink_to_fit();
|
||||
|
||||
(Arc::new(body), Arc::new(source_map))
|
||||
}
|
||||
|
||||
pub(crate) fn body_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<Body> {
|
||||
db.body_with_source_map(def).0
|
||||
}
|
||||
|
||||
pub fn pretty_print(
|
||||
&self,
|
||||
db: &dyn DefDatabase,
|
||||
owner: DefWithBodyId,
|
||||
edition: Edition,
|
||||
) -> String {
|
||||
pretty::print_body_hir(db, self, owner, edition)
|
||||
}
|
||||
|
||||
pub fn pretty_print_expr(
|
||||
&self,
|
||||
db: &dyn DefDatabase,
|
||||
owner: DefWithBodyId,
|
||||
expr: ExprId,
|
||||
edition: Edition,
|
||||
) -> String {
|
||||
pretty::print_expr_hir(db, self, owner, expr, edition)
|
||||
}
|
||||
|
||||
pub fn pretty_print_pat(
|
||||
&self,
|
||||
db: &dyn DefDatabase,
|
||||
owner: DefWithBodyId,
|
||||
pat: PatId,
|
||||
oneline: bool,
|
||||
edition: Edition,
|
||||
) -> String {
|
||||
pretty::print_pat_hir(db, self, owner, pat, oneline, edition)
|
||||
}
|
||||
}
|
||||
|
||||
impl BodySourceMap {
|
||||
pub fn self_param_syntax(&self) -> Option<InFile<SelfParamPtr>> {
|
||||
self.self_param
|
||||
}
|
||||
}
|
|
@ -29,11 +29,14 @@ use triomphe::Arc;
|
|||
|
||||
use crate::{
|
||||
attr::Attrs,
|
||||
body::{Body, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr},
|
||||
builtin_type::BuiltinUint,
|
||||
data::adt::StructKind,
|
||||
db::DefDatabase,
|
||||
expander::Expander,
|
||||
expr_store::{
|
||||
Body, BodySourceMap, ExprPtr, ExpressionStore, ExpressionStoreBuilder,
|
||||
ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, PatPtr,
|
||||
},
|
||||
hir::{
|
||||
format_args::{
|
||||
self, FormatAlignment, FormatArgs, FormatArgsPiece, FormatArgument, FormatArgumentKind,
|
||||
|
@ -55,11 +58,11 @@ use crate::{
|
|||
|
||||
type FxIndexSet<K> = indexmap::IndexSet<K, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
|
||||
|
||||
pub(super) fn lower(
|
||||
pub(super) fn lower_body(
|
||||
db: &dyn DefDatabase,
|
||||
owner: DefWithBodyId,
|
||||
expander: Expander,
|
||||
params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
||||
parameters: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
||||
body: Option<ast::Expr>,
|
||||
krate: CrateId,
|
||||
is_async_fn: bool,
|
||||
|
@ -75,35 +78,146 @@ pub(super) fn lower(
|
|||
};
|
||||
Arc::clone(span_map)
|
||||
});
|
||||
ExprCollector {
|
||||
db,
|
||||
owner,
|
||||
krate,
|
||||
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(),
|
||||
expander,
|
||||
current_try_block_label: None,
|
||||
is_lowering_coroutine: false,
|
||||
label_ribs: Vec::new(),
|
||||
current_binding_owner: None,
|
||||
awaitable_context: None,
|
||||
current_span_map: span_map,
|
||||
current_block_legacy_macro_defs_count: FxHashMap::default(),
|
||||
|
||||
let mut self_param = None;
|
||||
let mut source_map_self_param = None;
|
||||
let mut params = vec![];
|
||||
let mut collector = ExprCollector::new(db, owner, expander, krate, span_map);
|
||||
|
||||
let skip_body = match owner {
|
||||
DefWithBodyId::FunctionId(it) => db.attrs(it.into()),
|
||||
DefWithBodyId::StaticId(it) => db.attrs(it.into()),
|
||||
DefWithBodyId::ConstId(it) => db.attrs(it.into()),
|
||||
DefWithBodyId::InTypeConstId(_) => Attrs::EMPTY,
|
||||
DefWithBodyId::VariantId(it) => db.attrs(it.into()),
|
||||
}
|
||||
.collect(params, body, is_async_fn)
|
||||
.rust_analyzer_tool()
|
||||
.any(|attr| *attr.path() == tool_path![skip]);
|
||||
// If #[rust_analyzer::skip] annotated, only construct enough information for the signature
|
||||
// and skip the body.
|
||||
if skip_body {
|
||||
if let Some((param_list, mut attr_enabled)) = parameters {
|
||||
if let Some(self_param_syn) =
|
||||
param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
|
||||
{
|
||||
let is_mutable =
|
||||
self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
|
||||
let binding_id: la_arena::Idx<Binding> = collector.alloc_binding(
|
||||
Name::new_symbol_root(sym::self_.clone()),
|
||||
BindingAnnotation::new(is_mutable, false),
|
||||
);
|
||||
self_param = Some(binding_id);
|
||||
source_map_self_param =
|
||||
Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
|
||||
}
|
||||
params = param_list
|
||||
.params()
|
||||
.zip(attr_enabled)
|
||||
.filter(|(_, enabled)| *enabled)
|
||||
.map(|_| collector.missing_pat())
|
||||
.collect();
|
||||
};
|
||||
let body_expr = collector.missing_expr();
|
||||
return (
|
||||
Body {
|
||||
store: collector.store.finish(),
|
||||
params: params.into_boxed_slice(),
|
||||
self_param,
|
||||
body_expr,
|
||||
},
|
||||
BodySourceMap { self_param: source_map_self_param, store: collector.source_map },
|
||||
);
|
||||
}
|
||||
|
||||
if let Some((param_list, mut attr_enabled)) = parameters {
|
||||
if let Some(self_param_syn) =
|
||||
param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
|
||||
{
|
||||
let is_mutable =
|
||||
self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
|
||||
let binding_id: la_arena::Idx<Binding> = collector.alloc_binding(
|
||||
Name::new_symbol_root(sym::self_.clone()),
|
||||
BindingAnnotation::new(is_mutable, false),
|
||||
);
|
||||
let hygiene = self_param_syn
|
||||
.name()
|
||||
.map(|name| collector.hygiene_id_for(name.syntax().text_range().start()))
|
||||
.unwrap_or(HygieneId::ROOT);
|
||||
if !hygiene.is_root() {
|
||||
collector.store.binding_hygiene.insert(binding_id, hygiene);
|
||||
}
|
||||
self_param = Some(binding_id);
|
||||
source_map_self_param = Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
|
||||
}
|
||||
|
||||
for (param, _) in param_list.params().zip(attr_enabled).filter(|(_, enabled)| *enabled) {
|
||||
let param_pat = collector.collect_pat_top(param.pat());
|
||||
params.push(param_pat);
|
||||
}
|
||||
};
|
||||
|
||||
let body_expr = collector.collect(
|
||||
body,
|
||||
if is_async_fn {
|
||||
Awaitable::Yes
|
||||
} else {
|
||||
match owner {
|
||||
DefWithBodyId::FunctionId(..) => Awaitable::No("non-async function"),
|
||||
DefWithBodyId::StaticId(..) => Awaitable::No("static"),
|
||||
DefWithBodyId::ConstId(..) | DefWithBodyId::InTypeConstId(..) => {
|
||||
Awaitable::No("constant")
|
||||
}
|
||||
DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"),
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
(
|
||||
Body {
|
||||
store: collector.store.finish(),
|
||||
params: params.into_boxed_slice(),
|
||||
self_param,
|
||||
body_expr,
|
||||
},
|
||||
BodySourceMap { self_param: source_map_self_param, store: collector.source_map },
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(super) fn lower(
|
||||
db: &dyn DefDatabase,
|
||||
owner: ExprStoreOwnerId,
|
||||
expander: Expander,
|
||||
body: Option<ast::Expr>,
|
||||
krate: CrateId,
|
||||
) -> (ExpressionStore, ExpressionStoreSourceMap) {
|
||||
// We cannot leave the root span map empty and let any identifier from it be treated as root,
|
||||
// because when inside nested macros `SyntaxContextId`s from the outer macro will be interleaved
|
||||
// with the inner macro, and that will cause confusion because they won't be the same as `ROOT`
|
||||
// even though they should be the same. Also, when the body comes from multiple expansions, their
|
||||
// hygiene is different.
|
||||
let span_map = expander.current_file_id().macro_file().map(|_| {
|
||||
let SpanMap::ExpansionSpanMap(span_map) = expander.span_map(db) else {
|
||||
panic!("in a macro file there should be `ExpansionSpanMap`");
|
||||
};
|
||||
Arc::clone(span_map)
|
||||
});
|
||||
let mut expr_collector = ExprCollector::new(db, owner, expander, krate, span_map);
|
||||
expr_collector.collect(body, Awaitable::No("?"));
|
||||
(expr_collector.store.finish(), expr_collector.source_map)
|
||||
}
|
||||
|
||||
type ExprStoreOwnerId = DefWithBodyId;
|
||||
|
||||
struct ExprCollector<'a> {
|
||||
db: &'a dyn DefDatabase,
|
||||
expander: Expander,
|
||||
owner: DefWithBodyId,
|
||||
owner: ExprStoreOwnerId,
|
||||
def_map: Arc<DefMap>,
|
||||
ast_id_map: Arc<AstIdMap>,
|
||||
krate: CrateId,
|
||||
body: Body,
|
||||
source_map: BodySourceMap,
|
||||
store: ExpressionStoreBuilder,
|
||||
source_map: ExpressionStoreSourceMap,
|
||||
|
||||
is_lowering_coroutine: bool,
|
||||
|
||||
|
@ -157,6 +271,7 @@ impl RibKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||
enum Awaitable {
|
||||
Yes,
|
||||
No(&'static str),
|
||||
|
@ -180,12 +295,12 @@ impl BindingList {
|
|||
let id = *self.map.entry((name, hygiene)).or_insert_with_key(|(name, _)| {
|
||||
let id = ec.alloc_binding(name.clone(), mode);
|
||||
if !hygiene.is_root() {
|
||||
ec.body.binding_hygiene.insert(id, hygiene);
|
||||
ec.store.binding_hygiene.insert(id, hygiene);
|
||||
}
|
||||
id
|
||||
});
|
||||
if ec.body.bindings[id].mode != mode {
|
||||
ec.body.bindings[id].problems = Some(BindingProblems::BoundInconsistently);
|
||||
if ec.store.bindings[id].mode != mode {
|
||||
ec.store.bindings[id].problems = Some(BindingProblems::BoundInconsistently);
|
||||
}
|
||||
self.check_is_used(ec, id);
|
||||
id
|
||||
|
@ -195,11 +310,11 @@ impl BindingList {
|
|||
match self.is_used.get(&id) {
|
||||
None => {
|
||||
if self.reject_new {
|
||||
ec.body.bindings[id].problems = Some(BindingProblems::NotBoundAcrossAll);
|
||||
ec.store.bindings[id].problems = Some(BindingProblems::NotBoundAcrossAll);
|
||||
}
|
||||
}
|
||||
Some(true) => {
|
||||
ec.body.bindings[id].problems = Some(BindingProblems::BoundMoreThanOnce);
|
||||
ec.store.bindings[id].problems = Some(BindingProblems::BoundMoreThanOnce);
|
||||
}
|
||||
Some(false) => {}
|
||||
}
|
||||
|
@ -208,93 +323,37 @@ impl BindingList {
|
|||
}
|
||||
|
||||
impl ExprCollector<'_> {
|
||||
fn collect(
|
||||
mut self,
|
||||
param_list: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
|
||||
body: Option<ast::Expr>,
|
||||
is_async_fn: bool,
|
||||
) -> (Body, BodySourceMap) {
|
||||
let skip_body = match self.owner {
|
||||
DefWithBodyId::FunctionId(it) => self.db.attrs(it.into()),
|
||||
DefWithBodyId::StaticId(it) => self.db.attrs(it.into()),
|
||||
DefWithBodyId::ConstId(it) => self.db.attrs(it.into()),
|
||||
DefWithBodyId::InTypeConstId(_) => Attrs::EMPTY,
|
||||
DefWithBodyId::VariantId(it) => self.db.attrs(it.into()),
|
||||
}
|
||||
.rust_analyzer_tool()
|
||||
.any(|attr| *attr.path() == tool_path![skip]);
|
||||
// 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) =
|
||||
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 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.source_map.self_param =
|
||||
Some(self.expander.in_file(AstPtr::new(&self_param)));
|
||||
}
|
||||
self.body.params = param_list
|
||||
.params()
|
||||
.zip(attr_enabled)
|
||||
.filter(|(_, enabled)| *enabled)
|
||||
.map(|_| self.missing_pat())
|
||||
.collect();
|
||||
};
|
||||
return (self.body, self.source_map);
|
||||
fn new(
|
||||
db: &dyn DefDatabase,
|
||||
owner: ExprStoreOwnerId,
|
||||
expander: Expander,
|
||||
krate: CrateId,
|
||||
span_map: Option<Arc<ExpansionSpanMap>>,
|
||||
) -> ExprCollector<'_> {
|
||||
ExprCollector {
|
||||
db,
|
||||
owner,
|
||||
krate,
|
||||
def_map: expander.module.def_map(db),
|
||||
source_map: ExpressionStoreSourceMap::default(),
|
||||
ast_id_map: db.ast_id_map(expander.current_file_id()),
|
||||
store: ExpressionStoreBuilder::default(),
|
||||
expander,
|
||||
current_try_block_label: None,
|
||||
is_lowering_coroutine: false,
|
||||
label_ribs: Vec::new(),
|
||||
current_binding_owner: None,
|
||||
awaitable_context: None,
|
||||
current_span_map: span_map,
|
||||
current_block_legacy_macro_defs_count: FxHashMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
self.awaitable_context.replace(if is_async_fn {
|
||||
Awaitable::Yes
|
||||
} else {
|
||||
match self.owner {
|
||||
DefWithBodyId::FunctionId(..) => Awaitable::No("non-async function"),
|
||||
DefWithBodyId::StaticId(..) => Awaitable::No("static"),
|
||||
DefWithBodyId::ConstId(..) | DefWithBodyId::InTypeConstId(..) => {
|
||||
Awaitable::No("constant")
|
||||
}
|
||||
DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"),
|
||||
}
|
||||
});
|
||||
if let Some((param_list, mut attr_enabled)) = param_list {
|
||||
let mut params = vec![];
|
||||
if let Some(self_param) =
|
||||
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 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
|
||||
.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)));
|
||||
}
|
||||
|
||||
for (param, _) in param_list.params().zip(attr_enabled).filter(|(_, enabled)| *enabled)
|
||||
{
|
||||
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| {
|
||||
if is_async_fn {
|
||||
match body {
|
||||
fn collect(&mut self, expr: Option<ast::Expr>, awaitable: Awaitable) -> ExprId {
|
||||
self.awaitable_context.replace(awaitable);
|
||||
self.with_label_rib(RibKind::Closure, |this| {
|
||||
if awaitable == Awaitable::Yes {
|
||||
match expr {
|
||||
Some(e) => {
|
||||
let syntax_ptr = AstPtr::new(&e);
|
||||
let expr = this.collect_expr(e);
|
||||
|
@ -306,15 +365,13 @@ impl ExprCollector<'_> {
|
|||
None => this.missing_expr(),
|
||||
}
|
||||
} else {
|
||||
this.collect_expr_opt(body)
|
||||
this.collect_expr_opt(expr)
|
||||
}
|
||||
});
|
||||
|
||||
(self.body, self.source_map)
|
||||
})
|
||||
}
|
||||
|
||||
fn ctx(&mut self) -> LowerCtx<'_> {
|
||||
self.expander.ctx(self.db, &mut self.body.types, &mut self.source_map.types)
|
||||
self.expander.ctx(self.db, &mut self.store.types, &mut self.source_map.types)
|
||||
}
|
||||
|
||||
fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
|
||||
|
@ -390,7 +447,7 @@ impl ExprCollector<'_> {
|
|||
parent: this.owner,
|
||||
root: inner_expr,
|
||||
});
|
||||
this.body.exprs[result_expr_id] = Expr::Const(it);
|
||||
this.store.exprs[result_expr_id] = Expr::Const(it);
|
||||
this.current_binding_owner = prev_binding_owner;
|
||||
result_expr_id
|
||||
})
|
||||
|
@ -480,7 +537,7 @@ impl ExprCollector<'_> {
|
|||
.unwrap_or((Expr::Missing, HygieneId::ROOT));
|
||||
let expr_id = self.alloc_expr(path, syntax_ptr);
|
||||
if !hygiene.is_root() {
|
||||
self.body.expr_hygiene.insert(expr_id, hygiene);
|
||||
self.store.ident_hygiene.insert(expr_id.into(), hygiene);
|
||||
}
|
||||
expr_id
|
||||
}
|
||||
|
@ -562,10 +619,12 @@ impl ExprCollector<'_> {
|
|||
ast::Expr::AwaitExpr(e) => {
|
||||
let expr = self.collect_expr_opt(e.expr());
|
||||
if let Awaitable::No(location) = self.is_lowering_awaitable_block() {
|
||||
self.source_map.diagnostics.push(BodyDiagnostic::AwaitOutsideOfAsync {
|
||||
node: InFile::new(self.expander.current_file_id(), AstPtr::new(&e)),
|
||||
location: location.to_string(),
|
||||
});
|
||||
self.source_map.diagnostics.push(
|
||||
ExpressionStoreDiagnostics::AwaitOutsideOfAsync {
|
||||
node: InFile::new(self.expander.current_file_id(), AstPtr::new(&e)),
|
||||
location: location.to_string(),
|
||||
},
|
||||
);
|
||||
}
|
||||
self.alloc_expr(Expr::Await { expr }, syntax_ptr)
|
||||
}
|
||||
|
@ -646,7 +705,7 @@ impl ExprCollector<'_> {
|
|||
this.is_lowering_coroutine = prev_is_lowering_coroutine;
|
||||
this.current_binding_owner = prev_binding_owner;
|
||||
this.current_try_block_label = prev_try_block_label;
|
||||
this.body.exprs[result_expr_id] = Expr::Closure {
|
||||
this.store.exprs[result_expr_id] = Expr::Closure {
|
||||
args: args.into(),
|
||||
arg_types: arg_types.into(),
|
||||
ret_type,
|
||||
|
@ -752,7 +811,7 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
|
||||
fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
|
||||
self.expander.parse_path(self.db, path, &mut self.body.types, &mut self.source_map.types)
|
||||
self.expander.parse_path(self.db, path, &mut self.store.types, &mut self.source_map.types)
|
||||
}
|
||||
|
||||
fn collect_expr_path(&mut self, e: ast::PathExpr) -> Option<(Path, HygieneId)> {
|
||||
|
@ -781,7 +840,7 @@ impl ExprCollector<'_> {
|
|||
let src = self.expander.in_file(AstPtr::new(&expr).wrap_left());
|
||||
let expr = self.collect_expr(expr);
|
||||
// Do not use `alloc_pat_from_expr()` here, it will override the entry in `expr_map`.
|
||||
let id = self.body.pats.alloc(Pat::Expr(expr));
|
||||
let id = self.store.pats.alloc(Pat::Expr(expr));
|
||||
self.source_map.pat_map_back.insert(id, src);
|
||||
id
|
||||
})
|
||||
|
@ -835,7 +894,7 @@ impl ExprCollector<'_> {
|
|||
.unwrap_or((Pat::Missing, HygieneId::ROOT));
|
||||
let pat_id = self.alloc_pat_from_expr(path, syntax_ptr);
|
||||
if !hygiene.is_root() {
|
||||
self.body.pat_hygiene.insert(pat_id, hygiene);
|
||||
self.store.ident_hygiene.insert(pat_id.into(), hygiene);
|
||||
}
|
||||
pat_id
|
||||
}
|
||||
|
@ -967,7 +1026,7 @@ impl ExprCollector<'_> {
|
|||
) -> ExprId {
|
||||
let (id, prev_owner) = self.initialize_binding_owner(syntax_ptr);
|
||||
let tmp = job(self);
|
||||
self.body.exprs[id] = mem::replace(&mut self.body.exprs[tmp], Expr::Missing);
|
||||
self.store.exprs[id] = mem::replace(&mut self.store.exprs[tmp], Expr::Missing);
|
||||
self.current_binding_owner = prev_owner;
|
||||
id
|
||||
}
|
||||
|
@ -979,8 +1038,9 @@ impl ExprCollector<'_> {
|
|||
let Some(try_from_output) = self.lang_path(LangItem::TryTraitFromOutput) else {
|
||||
return self.collect_block(e);
|
||||
};
|
||||
let label = self
|
||||
.alloc_label_desugared(Label { name: Name::generate_new_name(self.body.labels.len()) });
|
||||
let label = self.alloc_label_desugared(Label {
|
||||
name: Name::generate_new_name(self.store.labels.len()),
|
||||
});
|
||||
let old_label = self.current_try_block_label.replace(label);
|
||||
|
||||
let ptr = AstPtr::new(&e).upcast();
|
||||
|
@ -1006,7 +1066,7 @@ impl ExprCollector<'_> {
|
|||
)
|
||||
}
|
||||
};
|
||||
let Expr::Block { tail, .. } = &mut self.body.exprs[expr_id] else {
|
||||
let Expr::Block { tail, .. } = &mut self.store.exprs[expr_id] else {
|
||||
unreachable!("block was lowered to non-block");
|
||||
};
|
||||
*tail = Some(next_tail);
|
||||
|
@ -1112,7 +1172,7 @@ impl ExprCollector<'_> {
|
|||
this.collect_expr_opt(e.loop_body().map(|it| it.into()))
|
||||
}),
|
||||
};
|
||||
let iter_name = Name::generate_new_name(self.body.exprs.len());
|
||||
let iter_name = Name::generate_new_name(self.store.exprs.len());
|
||||
let iter_expr = self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr);
|
||||
let iter_expr_mut = self.alloc_expr(
|
||||
Expr::Ref { expr: iter_expr, rawness: Rawness::Ref, mutability: Mutability::Mut },
|
||||
|
@ -1177,7 +1237,7 @@ impl ExprCollector<'_> {
|
|||
let try_branch = self.alloc_expr(Expr::Path(try_branch), syntax_ptr);
|
||||
let expr = self
|
||||
.alloc_expr(Expr::Call { callee: try_branch, args: Box::new([operand]) }, syntax_ptr);
|
||||
let continue_name = Name::generate_new_name(self.body.bindings.len());
|
||||
let continue_name = Name::generate_new_name(self.store.bindings.len());
|
||||
let continue_binding =
|
||||
self.alloc_binding(continue_name.clone(), BindingAnnotation::Unannotated);
|
||||
let continue_bpat =
|
||||
|
@ -1192,7 +1252,7 @@ impl ExprCollector<'_> {
|
|||
guard: None,
|
||||
expr: self.alloc_expr(Expr::Path(Path::from(continue_name)), syntax_ptr),
|
||||
};
|
||||
let break_name = Name::generate_new_name(self.body.bindings.len());
|
||||
let break_name = Name::generate_new_name(self.store.bindings.len());
|
||||
let break_binding = self.alloc_binding(break_name.clone(), BindingAnnotation::Unannotated);
|
||||
let break_bpat = self.alloc_pat_desugared(Pat::Bind { id: break_binding, subpat: None });
|
||||
self.add_definition_to_binding(break_binding, break_bpat);
|
||||
|
@ -1261,17 +1321,19 @@ impl ExprCollector<'_> {
|
|||
Ok(res) => res,
|
||||
Err(UnresolvedMacro { path }) => {
|
||||
if record_diagnostics {
|
||||
self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedMacroCall {
|
||||
node: InFile::new(outer_file, syntax_ptr),
|
||||
path,
|
||||
});
|
||||
self.source_map.diagnostics.push(
|
||||
ExpressionStoreDiagnostics::UnresolvedMacroCall {
|
||||
node: InFile::new(outer_file, syntax_ptr),
|
||||
path,
|
||||
},
|
||||
);
|
||||
}
|
||||
return collector(self, None);
|
||||
}
|
||||
};
|
||||
if record_diagnostics {
|
||||
if let Some(err) = res.err {
|
||||
self.source_map.diagnostics.push(BodyDiagnostic::MacroError {
|
||||
self.source_map.diagnostics.push(ExpressionStoreDiagnostics::MacroError {
|
||||
node: InFile::new(outer_file, syntax_ptr),
|
||||
err,
|
||||
});
|
||||
|
@ -1464,7 +1526,7 @@ impl ExprCollector<'_> {
|
|||
let (module, def_map) =
|
||||
match block_id.map(|block_id| (self.db.block_def_map(block_id), block_id)) {
|
||||
Some((def_map, block_id)) => {
|
||||
self.body.block_scopes.push(block_id);
|
||||
self.store.block_scopes.push(block_id);
|
||||
(def_map.module_id(DefMap::ROOT), def_map)
|
||||
}
|
||||
None => (self.expander.module, self.def_map.clone()),
|
||||
|
@ -1621,7 +1683,7 @@ impl ExprCollector<'_> {
|
|||
pats.push(self.collect_pat(rest, binding_list));
|
||||
for (&id, &is_used) in binding_list.is_used.iter() {
|
||||
if !is_used {
|
||||
self.body.bindings[id].problems =
|
||||
self.store.bindings[id].problems =
|
||||
Some(BindingProblems::NotBoundAcrossAll);
|
||||
}
|
||||
}
|
||||
|
@ -1825,7 +1887,7 @@ impl ExprCollector<'_> {
|
|||
return Some(());
|
||||
}
|
||||
|
||||
self.source_map.diagnostics.push(BodyDiagnostic::InactiveCode {
|
||||
self.source_map.diagnostics.push(ExpressionStoreDiagnostics::InactiveCode {
|
||||
node: self.expander.in_file(SyntaxNodePtr::new(owner.syntax())),
|
||||
cfg,
|
||||
opts: self.expander.cfg_options().clone(),
|
||||
|
@ -1853,7 +1915,7 @@ impl ExprCollector<'_> {
|
|||
fn resolve_label(
|
||||
&self,
|
||||
lifetime: Option<ast::Lifetime>,
|
||||
) -> Result<Option<LabelId>, BodyDiagnostic> {
|
||||
) -> Result<Option<LabelId>, ExpressionStoreDiagnostics> {
|
||||
let Some(lifetime) = lifetime else { return Ok(None) };
|
||||
let (mut hygiene_id, mut hygiene_info) = match &self.current_span_map {
|
||||
None => (HygieneId::ROOT, None),
|
||||
|
@ -1877,7 +1939,7 @@ impl ExprCollector<'_> {
|
|||
return if self.is_label_valid_from_rib(rib_idx) {
|
||||
Ok(Some(*id))
|
||||
} else {
|
||||
Err(BodyDiagnostic::UnreachableLabel {
|
||||
Err(ExpressionStoreDiagnostics::UnreachableLabel {
|
||||
name,
|
||||
node: self.expander.in_file(AstPtr::new(&lifetime)),
|
||||
})
|
||||
|
@ -1903,7 +1965,7 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
Err(BodyDiagnostic::UndeclaredLabel {
|
||||
Err(ExpressionStoreDiagnostics::UndeclaredLabel {
|
||||
name,
|
||||
node: self.expander.in_file(AstPtr::new(&lifetime)),
|
||||
})
|
||||
|
@ -1934,7 +1996,7 @@ impl ExprCollector<'_> {
|
|||
f: impl FnOnce(&mut Self) -> T,
|
||||
) -> T {
|
||||
self.label_ribs.push(LabelRib::new(RibKind::Normal(
|
||||
self.body[label].name.clone(),
|
||||
self.store.labels[label].name.clone(),
|
||||
label,
|
||||
hygiene,
|
||||
)));
|
||||
|
@ -2023,7 +2085,7 @@ impl ExprCollector<'_> {
|
|||
);
|
||||
}
|
||||
if !hygiene.is_root() {
|
||||
self.body.expr_hygiene.insert(expr_id, hygiene);
|
||||
self.store.ident_hygiene.insert(expr_id.into(), hygiene);
|
||||
}
|
||||
expr_id
|
||||
},
|
||||
|
@ -2417,7 +2479,7 @@ fn pat_literal_to_hir(lit: &ast::LiteralPat) -> Option<(Literal, ast::Literal)>
|
|||
impl ExprCollector<'_> {
|
||||
fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
|
||||
let src = self.expander.in_file(ptr);
|
||||
let id = self.body.exprs.alloc(expr);
|
||||
let id = self.store.exprs.alloc(expr);
|
||||
self.source_map.expr_map_back.insert(id, src);
|
||||
self.source_map.expr_map.insert(src, id.into());
|
||||
id
|
||||
|
@ -2425,11 +2487,11 @@ impl ExprCollector<'_> {
|
|||
// FIXME: desugared exprs don't have ptr, that's wrong and should be fixed.
|
||||
// Migrate to alloc_expr_desugared_with_ptr and then rename back
|
||||
fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
|
||||
self.body.exprs.alloc(expr)
|
||||
self.store.exprs.alloc(expr)
|
||||
}
|
||||
fn alloc_expr_desugared_with_ptr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
|
||||
let src = self.expander.in_file(ptr);
|
||||
let id = self.body.exprs.alloc(expr);
|
||||
let id = self.store.exprs.alloc(expr);
|
||||
self.source_map.expr_map_back.insert(id, src);
|
||||
// We intentionally don't fill this as it could overwrite a non-desugared entry
|
||||
// self.source_map.expr_map.insert(src, id);
|
||||
|
@ -2440,45 +2502,45 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
|
||||
fn alloc_binding(&mut self, name: Name, mode: BindingAnnotation) -> BindingId {
|
||||
let binding = self.body.bindings.alloc(Binding { name, mode, problems: None });
|
||||
let binding = self.store.bindings.alloc(Binding { name, mode, problems: None });
|
||||
if let Some(owner) = self.current_binding_owner {
|
||||
self.body.binding_owners.insert(binding, owner);
|
||||
self.store.binding_owners.insert(binding, owner);
|
||||
}
|
||||
binding
|
||||
}
|
||||
|
||||
fn alloc_pat_from_expr(&mut self, pat: Pat, ptr: ExprPtr) -> PatId {
|
||||
let src = self.expander.in_file(ptr);
|
||||
let id = self.body.pats.alloc(pat);
|
||||
let id = self.store.pats.alloc(pat);
|
||||
self.source_map.expr_map.insert(src, id.into());
|
||||
self.source_map.pat_map_back.insert(id, src.map(AstPtr::wrap_left));
|
||||
id
|
||||
}
|
||||
fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
|
||||
let src = self.expander.in_file(ptr);
|
||||
let id = self.body.pats.alloc(pat);
|
||||
let id = self.store.pats.alloc(pat);
|
||||
self.source_map.pat_map_back.insert(id, src.map(AstPtr::wrap_right));
|
||||
self.source_map.pat_map.insert(src, id);
|
||||
id
|
||||
}
|
||||
// FIXME: desugared pats don't have ptr, that's wrong and should be fixed somehow.
|
||||
fn alloc_pat_desugared(&mut self, pat: Pat) -> PatId {
|
||||
self.body.pats.alloc(pat)
|
||||
self.store.pats.alloc(pat)
|
||||
}
|
||||
fn missing_pat(&mut self) -> PatId {
|
||||
self.body.pats.alloc(Pat::Missing)
|
||||
self.store.pats.alloc(Pat::Missing)
|
||||
}
|
||||
|
||||
fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId {
|
||||
let src = self.expander.in_file(ptr);
|
||||
let id = self.body.labels.alloc(label);
|
||||
let id = self.store.labels.alloc(label);
|
||||
self.source_map.label_map_back.insert(id, src);
|
||||
self.source_map.label_map.insert(src, id);
|
||||
id
|
||||
}
|
||||
// FIXME: desugared labels don't have ptr, that's wrong and should be fixed somehow.
|
||||
fn alloc_label_desugared(&mut self, label: Label) -> LabelId {
|
||||
self.body.labels.alloc(label)
|
||||
self.store.labels.alloc(label)
|
||||
}
|
||||
|
||||
fn is_lowering_awaitable_block(&self) -> &Awaitable {
|
|
@ -9,7 +9,7 @@ use syntax::{
|
|||
use tt::TextRange;
|
||||
|
||||
use crate::{
|
||||
body::lower::{ExprCollector, FxIndexSet},
|
||||
expr_store::lower::{ExprCollector, FxIndexSet},
|
||||
hir::{AsmOperand, AsmOptions, Expr, ExprId, InlineAsm, InlineAsmRegOrRegClass},
|
||||
};
|
||||
|
|
@ -60,7 +60,7 @@ pub(super) fn print_body_hir(
|
|||
|
||||
let mut p = Printer {
|
||||
db,
|
||||
body,
|
||||
store: body,
|
||||
buf: header,
|
||||
indent_level: 0,
|
||||
line_format: LineFormat::Newline,
|
||||
|
@ -103,14 +103,14 @@ pub(super) fn print_body_hir(
|
|||
|
||||
pub(super) fn print_expr_hir(
|
||||
db: &dyn DefDatabase,
|
||||
body: &Body,
|
||||
store: &ExpressionStore,
|
||||
_owner: DefWithBodyId,
|
||||
expr: ExprId,
|
||||
edition: Edition,
|
||||
) -> String {
|
||||
let mut p = Printer {
|
||||
db,
|
||||
body,
|
||||
store,
|
||||
buf: String::new(),
|
||||
indent_level: 0,
|
||||
line_format: LineFormat::Newline,
|
||||
|
@ -122,7 +122,7 @@ pub(super) fn print_expr_hir(
|
|||
|
||||
pub(super) fn print_pat_hir(
|
||||
db: &dyn DefDatabase,
|
||||
body: &Body,
|
||||
store: &ExpressionStore,
|
||||
_owner: DefWithBodyId,
|
||||
pat: PatId,
|
||||
oneline: bool,
|
||||
|
@ -130,7 +130,7 @@ pub(super) fn print_pat_hir(
|
|||
) -> String {
|
||||
let mut p = Printer {
|
||||
db,
|
||||
body,
|
||||
store,
|
||||
buf: String::new(),
|
||||
indent_level: 0,
|
||||
line_format: if oneline { LineFormat::Oneline } else { LineFormat::Newline },
|
||||
|
@ -157,7 +157,7 @@ macro_rules! wln {
|
|||
|
||||
struct Printer<'a> {
|
||||
db: &'a dyn DefDatabase,
|
||||
body: &'a Body,
|
||||
store: &'a ExpressionStore,
|
||||
buf: String,
|
||||
indent_level: usize,
|
||||
line_format: LineFormat,
|
||||
|
@ -233,7 +233,7 @@ impl Printer<'_> {
|
|||
}
|
||||
|
||||
fn print_expr(&mut self, expr: ExprId) {
|
||||
let expr = &self.body[expr];
|
||||
let expr = &self.store[expr];
|
||||
|
||||
match expr {
|
||||
Expr::Missing => w!(self, "<EFBFBD>"),
|
||||
|
@ -241,7 +241,7 @@ impl Printer<'_> {
|
|||
Expr::InlineAsm(_) => w!(self, "builtin#asm(_)"),
|
||||
Expr::OffsetOf(offset_of) => {
|
||||
w!(self, "builtin#offset_of(");
|
||||
self.print_type_ref(offset_of.container, &self.body.types);
|
||||
self.print_type_ref(offset_of.container, &self.store.types);
|
||||
let edition = self.edition;
|
||||
w!(
|
||||
self,
|
||||
|
@ -271,7 +271,7 @@ impl Printer<'_> {
|
|||
}
|
||||
Expr::Loop { body, label } => {
|
||||
if let Some(lbl) = label {
|
||||
w!(self, "{}: ", self.body[*lbl].name.display(self.db.upcast(), self.edition));
|
||||
w!(self, "{}: ", self.store[*lbl].name.display(self.db.upcast(), self.edition));
|
||||
}
|
||||
w!(self, "loop ");
|
||||
self.print_expr(*body);
|
||||
|
@ -295,7 +295,7 @@ impl Printer<'_> {
|
|||
if let Some(args) = generic_args {
|
||||
w!(self, "::<");
|
||||
let edition = self.edition;
|
||||
print_generic_args(self.db, args, &self.body.types, self, edition).unwrap();
|
||||
print_generic_args(self.db, args, &self.store.types, self, edition).unwrap();
|
||||
w!(self, ">");
|
||||
}
|
||||
w!(self, "(");
|
||||
|
@ -330,13 +330,13 @@ impl Printer<'_> {
|
|||
Expr::Continue { label } => {
|
||||
w!(self, "continue");
|
||||
if let Some(lbl) = label {
|
||||
w!(self, " {}", self.body[*lbl].name.display(self.db.upcast(), self.edition));
|
||||
w!(self, " {}", self.store[*lbl].name.display(self.db.upcast(), self.edition));
|
||||
}
|
||||
}
|
||||
Expr::Break { expr, label } => {
|
||||
w!(self, "break");
|
||||
if let Some(lbl) = label {
|
||||
w!(self, " {}", self.body[*lbl].name.display(self.db.upcast(), self.edition));
|
||||
w!(self, " {}", self.store[*lbl].name.display(self.db.upcast(), self.edition));
|
||||
}
|
||||
if let Some(expr) = expr {
|
||||
self.whitespace();
|
||||
|
@ -404,7 +404,7 @@ impl Printer<'_> {
|
|||
Expr::Cast { expr, type_ref } => {
|
||||
self.print_expr(*expr);
|
||||
w!(self, " as ");
|
||||
self.print_type_ref(*type_ref, &self.body.types);
|
||||
self.print_type_ref(*type_ref, &self.store.types);
|
||||
}
|
||||
Expr::Ref { expr, rawness, mutability } => {
|
||||
w!(self, "&");
|
||||
|
@ -492,13 +492,13 @@ impl Printer<'_> {
|
|||
self.print_pat(*pat);
|
||||
if let Some(ty) = ty {
|
||||
w!(self, ": ");
|
||||
self.print_type_ref(*ty, &self.body.types);
|
||||
self.print_type_ref(*ty, &self.store.types);
|
||||
}
|
||||
}
|
||||
w!(self, "|");
|
||||
if let Some(ret_ty) = ret_type {
|
||||
w!(self, " -> ");
|
||||
self.print_type_ref(*ret_ty, &self.body.types);
|
||||
self.print_type_ref(*ret_ty, &self.store.types);
|
||||
}
|
||||
self.whitespace();
|
||||
self.print_expr(*body);
|
||||
|
@ -534,7 +534,7 @@ impl Printer<'_> {
|
|||
Expr::Literal(lit) => self.print_literal(lit),
|
||||
Expr::Block { id: _, statements, tail, label } => {
|
||||
let label = label.map(|lbl| {
|
||||
format!("{}: ", self.body[lbl].name.display(self.db.upcast(), self.edition))
|
||||
format!("{}: ", self.store[lbl].name.display(self.db.upcast(), self.edition))
|
||||
});
|
||||
self.print_block(label.as_deref(), statements, tail);
|
||||
}
|
||||
|
@ -581,7 +581,7 @@ impl Printer<'_> {
|
|||
}
|
||||
|
||||
fn print_pat(&mut self, pat: PatId) {
|
||||
let pat = &self.body[pat];
|
||||
let pat = &self.store[pat];
|
||||
|
||||
match pat {
|
||||
Pat::Missing => w!(self, "<EFBFBD>"),
|
||||
|
@ -623,9 +623,9 @@ impl Printer<'_> {
|
|||
let field_name = arg.name.display(self.db.upcast(), edition).to_string();
|
||||
|
||||
let mut same_name = false;
|
||||
if let Pat::Bind { id, subpat: None } = &self.body[arg.pat] {
|
||||
if let Pat::Bind { id, subpat: None } = &self.store[arg.pat] {
|
||||
if let Binding { name, mode: BindingAnnotation::Unannotated, .. } =
|
||||
&self.body.bindings[*id]
|
||||
&self.store.bindings[*id]
|
||||
{
|
||||
if name.as_str() == field_name {
|
||||
same_name = true;
|
||||
|
@ -734,7 +734,7 @@ impl Printer<'_> {
|
|||
self.print_pat(*pat);
|
||||
if let Some(ty) = type_ref {
|
||||
w!(self, ": ");
|
||||
self.print_type_ref(*ty, &self.body.types);
|
||||
self.print_type_ref(*ty, &self.store.types);
|
||||
}
|
||||
if let Some(init) = initializer {
|
||||
w!(self, " = ");
|
||||
|
@ -799,11 +799,11 @@ impl Printer<'_> {
|
|||
|
||||
fn print_path(&mut self, path: &Path) {
|
||||
let edition = self.edition;
|
||||
print_path(self.db, path, &self.body.types, self, edition).unwrap();
|
||||
print_path(self.db, path, &self.store.types, self, edition).unwrap();
|
||||
}
|
||||
|
||||
fn print_binding(&mut self, id: BindingId) {
|
||||
let Binding { name, mode, .. } = &self.body.bindings[id];
|
||||
let Binding { name, mode, .. } = &self.store.bindings[id];
|
||||
let mode = match mode {
|
||||
BindingAnnotation::Unannotated => "",
|
||||
BindingAnnotation::Mutable => "mut ",
|
|
@ -4,8 +4,8 @@ use la_arena::{Arena, ArenaMap, Idx, IdxRange, RawIdx};
|
|||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
body::{Body, HygieneId},
|
||||
db::DefDatabase,
|
||||
expr_store::{Body, ExpressionStore, HygieneId},
|
||||
hir::{Binding, BindingId, Expr, ExprId, Item, LabelId, Pat, PatId, Statement},
|
||||
BlockId, ConstBlockId, DefWithBodyId,
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ pub struct ScopeData {
|
|||
impl ExprScopes {
|
||||
pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> {
|
||||
let body = db.body(def);
|
||||
let mut scopes = ExprScopes::new(&body, |const_block| {
|
||||
let mut scopes = ExprScopes::new_body(&body, |const_block| {
|
||||
db.lookup_intern_anonymous_const(const_block).root
|
||||
});
|
||||
scopes.shrink_to_fit();
|
||||
|
@ -104,7 +104,7 @@ fn empty_entries(idx: usize) -> IdxRange<ScopeEntry> {
|
|||
}
|
||||
|
||||
impl ExprScopes {
|
||||
fn new(
|
||||
fn new_body(
|
||||
body: &Body,
|
||||
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
|
||||
) -> ExprScopes {
|
||||
|
@ -179,28 +179,28 @@ impl ExprScopes {
|
|||
|
||||
fn add_bindings(
|
||||
&mut self,
|
||||
body: &Body,
|
||||
store: &ExpressionStore,
|
||||
scope: ScopeId,
|
||||
binding: BindingId,
|
||||
hygiene: HygieneId,
|
||||
) {
|
||||
let Binding { name, .. } = &body.bindings[binding];
|
||||
let Binding { name, .. } = &store.bindings[binding];
|
||||
let entry = self.scope_entries.alloc(ScopeEntry { name: name.clone(), binding, hygiene });
|
||||
self.scopes[scope].entries =
|
||||
IdxRange::new_inclusive(self.scopes[scope].entries.start()..=entry);
|
||||
}
|
||||
|
||||
fn add_pat_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
|
||||
let pattern = &body[pat];
|
||||
fn add_pat_bindings(&mut self, store: &ExpressionStore, scope: ScopeId, pat: PatId) {
|
||||
let pattern = &store[pat];
|
||||
if let Pat::Bind { id, .. } = *pattern {
|
||||
self.add_bindings(body, scope, id, body.binding_hygiene(id));
|
||||
self.add_bindings(store, scope, id, store.binding_hygiene(id));
|
||||
}
|
||||
|
||||
pattern.walk_child_pats(|pat| self.add_pat_bindings(body, scope, pat));
|
||||
pattern.walk_child_pats(|pat| self.add_pat_bindings(store, scope, pat));
|
||||
}
|
||||
|
||||
fn add_params_bindings(&mut self, body: &Body, scope: ScopeId, params: &[PatId]) {
|
||||
params.iter().for_each(|pat| self.add_pat_bindings(body, scope, *pat));
|
||||
fn add_params_bindings(&mut self, store: &ExpressionStore, scope: ScopeId, params: &[PatId]) {
|
||||
params.iter().for_each(|pat| self.add_pat_bindings(store, scope, *pat));
|
||||
}
|
||||
|
||||
fn set_scope(&mut self, node: ExprId, scope: ScopeId) {
|
||||
|
@ -218,7 +218,7 @@ impl ExprScopes {
|
|||
fn compute_block_scopes(
|
||||
statements: &[Statement],
|
||||
tail: Option<ExprId>,
|
||||
body: &Body,
|
||||
store: &ExpressionStore,
|
||||
scopes: &mut ExprScopes,
|
||||
scope: &mut ScopeId,
|
||||
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
|
||||
|
@ -227,17 +227,17 @@ fn compute_block_scopes(
|
|||
match stmt {
|
||||
Statement::Let { pat, initializer, else_branch, .. } => {
|
||||
if let Some(expr) = initializer {
|
||||
compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
|
||||
compute_expr_scopes(*expr, store, scopes, scope, resolve_const_block);
|
||||
}
|
||||
if let Some(expr) = else_branch {
|
||||
compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
|
||||
compute_expr_scopes(*expr, store, scopes, scope, resolve_const_block);
|
||||
}
|
||||
|
||||
*scope = scopes.new_scope(*scope);
|
||||
scopes.add_pat_bindings(body, *scope, *pat);
|
||||
scopes.add_pat_bindings(store, *scope, *pat);
|
||||
}
|
||||
Statement::Expr { expr, .. } => {
|
||||
compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
|
||||
compute_expr_scopes(*expr, store, scopes, scope, resolve_const_block);
|
||||
}
|
||||
Statement::Item(Item::MacroDef(macro_id)) => {
|
||||
*scope = scopes.new_macro_def_scope(*scope, macro_id.clone());
|
||||
|
@ -246,32 +246,32 @@ fn compute_block_scopes(
|
|||
}
|
||||
}
|
||||
if let Some(expr) = tail {
|
||||
compute_expr_scopes(expr, body, scopes, scope, resolve_const_block);
|
||||
compute_expr_scopes(expr, store, scopes, scope, resolve_const_block);
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_expr_scopes(
|
||||
expr: ExprId,
|
||||
body: &Body,
|
||||
store: &ExpressionStore,
|
||||
scopes: &mut ExprScopes,
|
||||
scope: &mut ScopeId,
|
||||
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
|
||||
) {
|
||||
let make_label =
|
||||
|label: &Option<LabelId>| label.map(|label| (label, body.labels[label].name.clone()));
|
||||
|label: &Option<LabelId>| label.map(|label| (label, store.labels[label].name.clone()));
|
||||
|
||||
let compute_expr_scopes = |scopes: &mut ExprScopes, expr: ExprId, scope: &mut ScopeId| {
|
||||
compute_expr_scopes(expr, body, scopes, scope, resolve_const_block)
|
||||
compute_expr_scopes(expr, store, scopes, scope, resolve_const_block)
|
||||
};
|
||||
|
||||
scopes.set_scope(expr, *scope);
|
||||
match &body[expr] {
|
||||
match &store[expr] {
|
||||
Expr::Block { statements, tail, id, label } => {
|
||||
let mut scope = scopes.new_block_scope(*scope, *id, make_label(label));
|
||||
// Overwrite the old scope for the block expr, so that every block scope can be found
|
||||
// via the block itself (important for blocks that only contain items, no expressions).
|
||||
scopes.set_scope(expr, scope);
|
||||
compute_block_scopes(statements, *tail, body, scopes, &mut scope, resolve_const_block);
|
||||
compute_block_scopes(statements, *tail, store, scopes, &mut scope, resolve_const_block);
|
||||
}
|
||||
Expr::Const(id) => {
|
||||
let mut scope = scopes.root_scope();
|
||||
|
@ -282,7 +282,7 @@ fn compute_expr_scopes(
|
|||
// Overwrite the old scope for the block expr, so that every block scope can be found
|
||||
// via the block itself (important for blocks that only contain items, no expressions).
|
||||
scopes.set_scope(expr, scope);
|
||||
compute_block_scopes(statements, *tail, body, scopes, &mut scope, resolve_const_block);
|
||||
compute_block_scopes(statements, *tail, store, scopes, &mut scope, resolve_const_block);
|
||||
}
|
||||
Expr::Loop { body: body_expr, label } => {
|
||||
let mut scope = scopes.new_labeled_scope(*scope, make_label(label));
|
||||
|
@ -290,14 +290,14 @@ fn compute_expr_scopes(
|
|||
}
|
||||
Expr::Closure { args, body: body_expr, .. } => {
|
||||
let mut scope = scopes.new_scope(*scope);
|
||||
scopes.add_params_bindings(body, scope, args);
|
||||
scopes.add_params_bindings(store, scope, args);
|
||||
compute_expr_scopes(scopes, *body_expr, &mut scope);
|
||||
}
|
||||
Expr::Match { expr, arms } => {
|
||||
compute_expr_scopes(scopes, *expr, scope);
|
||||
for arm in arms.iter() {
|
||||
let mut scope = scopes.new_scope(*scope);
|
||||
scopes.add_pat_bindings(body, scope, arm.pat);
|
||||
scopes.add_pat_bindings(store, scope, arm.pat);
|
||||
if let Some(guard) = arm.guard {
|
||||
scope = scopes.new_scope(scope);
|
||||
compute_expr_scopes(scopes, guard, &mut scope);
|
||||
|
@ -316,9 +316,9 @@ fn compute_expr_scopes(
|
|||
&Expr::Let { pat, expr } => {
|
||||
compute_expr_scopes(scopes, expr, scope);
|
||||
*scope = scopes.new_scope(*scope);
|
||||
scopes.add_pat_bindings(body, *scope, pat);
|
||||
scopes.add_pat_bindings(store, *scope, pat);
|
||||
}
|
||||
_ => body.walk_child_exprs(expr, |e| compute_expr_scopes(scopes, e, scope)),
|
||||
_ => store.walk_child_exprs(expr, |e| compute_expr_scopes(scopes, e, scope)),
|
||||
};
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
mod block;
|
||||
|
||||
use expect_test::{expect, Expect};
|
||||
use la_arena::RawIdx;
|
||||
use test_fixture::WithFixture;
|
||||
|
||||
use crate::{test_db::TestDB, ModuleDefId};
|
|
@ -433,7 +433,7 @@ impl GenericParams {
|
|||
GenericDefId::TraitAliasId(id) => id_to_generics(db, id, enabled_params),
|
||||
GenericDefId::TypeAliasId(id) => id_to_generics(db, id, enabled_params),
|
||||
GenericDefId::ImplId(id) => id_to_generics(db, id, enabled_params),
|
||||
GenericDefId::ConstId(_) => (
|
||||
GenericDefId::ConstId(_) | GenericDefId::StaticId(_) => (
|
||||
Arc::new(GenericParams {
|
||||
type_or_consts: Default::default(),
|
||||
lifetimes: Default::default(),
|
||||
|
|
|
@ -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,13 +37,10 @@ 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
|
||||
// are local to the body.
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum ExprOrPatId {
|
||||
ExprId(ExprId),
|
||||
|
|
|
@ -42,7 +42,7 @@ pub mod lang_item;
|
|||
|
||||
pub mod hir;
|
||||
pub use self::hir::type_ref;
|
||||
pub mod body;
|
||||
pub mod expr_store;
|
||||
pub mod resolver;
|
||||
|
||||
pub mod nameres;
|
||||
|
@ -693,6 +693,7 @@ impl TypeOwnerId {
|
|||
Some(match self {
|
||||
TypeOwnerId::FunctionId(it) => GenericDefId::FunctionId(it),
|
||||
TypeOwnerId::ConstId(it) => GenericDefId::ConstId(it),
|
||||
TypeOwnerId::StaticId(it) => GenericDefId::StaticId(it),
|
||||
TypeOwnerId::AdtId(it) => GenericDefId::AdtId(it),
|
||||
TypeOwnerId::TraitId(it) => GenericDefId::TraitId(it),
|
||||
TypeOwnerId::TraitAliasId(it) => GenericDefId::TraitAliasId(it),
|
||||
|
@ -701,7 +702,7 @@ impl TypeOwnerId {
|
|||
TypeOwnerId::EnumVariantId(it) => {
|
||||
GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent))
|
||||
}
|
||||
TypeOwnerId::InTypeConstId(_) | TypeOwnerId::StaticId(_) => return None,
|
||||
TypeOwnerId::InTypeConstId(_) => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -743,6 +744,7 @@ impl From<GenericDefId> for TypeOwnerId {
|
|||
GenericDefId::TypeAliasId(it) => it.into(),
|
||||
GenericDefId::ImplId(it) => it.into(),
|
||||
GenericDefId::ConstId(it) => it.into(),
|
||||
GenericDefId::StaticId(it) => it.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -851,7 +853,7 @@ impl GeneralConstId {
|
|||
pub fn generic_def(self, db: &dyn DefDatabase) -> Option<GenericDefId> {
|
||||
match self {
|
||||
GeneralConstId::ConstId(it) => Some(it.into()),
|
||||
GeneralConstId::StaticId(_) => None,
|
||||
GeneralConstId::StaticId(it) => Some(it.into()),
|
||||
GeneralConstId::ConstBlockId(it) => it.lookup(db).parent.as_generic_def_id(db),
|
||||
GeneralConstId::InTypeConstId(it) => it.lookup(db).owner.as_generic_def_id(db),
|
||||
}
|
||||
|
@ -897,7 +899,7 @@ impl DefWithBodyId {
|
|||
pub fn as_generic_def_id(self, db: &dyn DefDatabase) -> Option<GenericDefId> {
|
||||
match self {
|
||||
DefWithBodyId::FunctionId(f) => Some(f.into()),
|
||||
DefWithBodyId::StaticId(_) => None,
|
||||
DefWithBodyId::StaticId(s) => Some(s.into()),
|
||||
DefWithBodyId::ConstId(c) => Some(c.into()),
|
||||
DefWithBodyId::VariantId(c) => Some(c.lookup(db).parent.into()),
|
||||
// FIXME: stable rust doesn't allow generics in constants, but we should
|
||||
|
@ -922,23 +924,28 @@ impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId);
|
|||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum GenericDefId {
|
||||
FunctionId(FunctionId),
|
||||
AdtId(AdtId),
|
||||
TraitId(TraitId),
|
||||
TraitAliasId(TraitAliasId),
|
||||
TypeAliasId(TypeAliasId),
|
||||
ImplId(ImplId),
|
||||
// consts can have type parameters from their parents (i.e. associated consts of traits)
|
||||
ConstId(ConstId),
|
||||
FunctionId(FunctionId),
|
||||
ImplId(ImplId),
|
||||
// can't actually have generics currently, but they might in the future
|
||||
// More importantly, this completes the set of items that contain type references
|
||||
// which is to be used by the signature expression store in the future.
|
||||
StaticId(StaticId),
|
||||
TraitAliasId(TraitAliasId),
|
||||
TraitId(TraitId),
|
||||
TypeAliasId(TypeAliasId),
|
||||
}
|
||||
impl_from!(
|
||||
FunctionId,
|
||||
AdtId(StructId, EnumId, UnionId),
|
||||
TraitId,
|
||||
TraitAliasId,
|
||||
TypeAliasId,
|
||||
ConstId,
|
||||
FunctionId,
|
||||
ImplId,
|
||||
ConstId
|
||||
StaticId,
|
||||
TraitAliasId,
|
||||
TraitId,
|
||||
TypeAliasId
|
||||
for GenericDefId
|
||||
);
|
||||
|
||||
|
@ -969,6 +976,7 @@ impl GenericDefId {
|
|||
GenericDefId::TraitAliasId(it) => file_id_and_params_of_item_loc(db, it),
|
||||
GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it),
|
||||
GenericDefId::ConstId(it) => (it.lookup(db).id.file_id(), None),
|
||||
GenericDefId::StaticId(it) => (it.lookup(db).id.file_id(), None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1350,6 +1358,7 @@ impl HasModule for GenericDefId {
|
|||
GenericDefId::TypeAliasId(it) => it.module(db),
|
||||
GenericDefId::ImplId(it) => it.module(db),
|
||||
GenericDefId::ConstId(it) => it.module(db),
|
||||
GenericDefId::StaticId(it) => it.module(db),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ use smallvec::{smallvec, SmallVec};
|
|||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
body::{
|
||||
scope::{ExprScopes, ScopeId},
|
||||
HygieneId,
|
||||
},
|
||||
builtin_type::BuiltinType,
|
||||
data::ExternCrateDeclData,
|
||||
db::DefDatabase,
|
||||
expr_store::{
|
||||
scope::{ExprScopes, ScopeId},
|
||||
HygieneId,
|
||||
},
|
||||
generics::{GenericParams, TypeOrConstParamData},
|
||||
hir::{BindingId, ExprId, LabelId},
|
||||
item_scope::{BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, BUILTIN_SCOPE},
|
||||
|
@ -1264,6 +1264,7 @@ impl HasResolver for GenericDefId {
|
|||
GenericDefId::TypeAliasId(inner) => inner.resolver(db),
|
||||
GenericDefId::ImplId(inner) => inner.resolver(db),
|
||||
GenericDefId::ConstId(inner) => inner.resolver(db),
|
||||
GenericDefId::StaticId(inner) => inner.resolver(db),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use base_db::{ra_salsa::Cycle, CrateId};
|
||||
use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex};
|
||||
use hir_def::{
|
||||
body::{Body, HygieneId},
|
||||
expr_store::{Body, HygieneId},
|
||||
hir::{Expr, ExprId},
|
||||
path::Path,
|
||||
resolver::{Resolver, ValueNs},
|
||||
|
|
|
@ -36,7 +36,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub(crate) use hir_def::{
|
||||
body::Body,
|
||||
expr_store::Body,
|
||||
hir::{Expr, ExprId, MatchArm, Pat, PatId, Statement},
|
||||
LocalFieldId, VariantId,
|
||||
};
|
||||
|
|
|
@ -11,7 +11,8 @@ pub(crate) mod pat_analysis;
|
|||
|
||||
use chalk_ir::Mutability;
|
||||
use hir_def::{
|
||||
body::Body, data::adt::VariantData, hir::PatId, AdtId, EnumVariantId, LocalFieldId, VariantId,
|
||||
data::adt::VariantData, expr_store::Body, hir::PatId, AdtId, EnumVariantId, LocalFieldId,
|
||||
VariantId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use span::Edition;
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::mem;
|
|||
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
body::Body,
|
||||
expr_store::Body,
|
||||
hir::{Expr, ExprId, ExprOrPatId, Pat, PatId, Statement, UnaryOp},
|
||||
path::Path,
|
||||
resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
|
||||
|
|
|
@ -262,7 +262,8 @@ fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<Generic
|
|||
GenericDefId::FunctionId(it) => it.lookup(db).container,
|
||||
GenericDefId::TypeAliasId(it) => it.lookup(db).container,
|
||||
GenericDefId::ConstId(it) => it.lookup(db).container,
|
||||
GenericDefId::AdtId(_)
|
||||
GenericDefId::StaticId(_)
|
||||
| GenericDefId::AdtId(_)
|
||||
| GenericDefId::TraitId(_)
|
||||
| GenericDefId::ImplId(_)
|
||||
| GenericDefId::TraitAliasId(_) => return None,
|
||||
|
|
|
@ -34,9 +34,9 @@ use chalk_ir::{
|
|||
};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
body::{Body, HygieneId},
|
||||
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
|
||||
data::{ConstData, StaticData},
|
||||
expr_store::{Body, HygieneId},
|
||||
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
|
||||
lang_item::{LangItem, LangItemTarget},
|
||||
layout::Integer,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use hir_def::body::HygieneId;
|
||||
use hir_def::expr_store::HygieneId;
|
||||
use hir_def::hir::ExprOrPatId;
|
||||
use hir_def::path::{Path, PathSegment, PathSegments};
|
||||
use hir_def::resolver::{ResolveValueResult, Resolver, TypeNs};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::iter::repeat_with;
|
||||
|
||||
use hir_def::{
|
||||
body::Body,
|
||||
expr_store::Body,
|
||||
hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, Literal, Pat, PatId},
|
||||
path::Path,
|
||||
};
|
||||
|
@ -528,7 +528,7 @@ impl InferenceContext<'_> {
|
|||
self.infer_expr(expr, &Expectation::has_type(expected.clone()), ExprIsRead::Yes)
|
||||
}
|
||||
|
||||
fn is_non_ref_pat(&mut self, body: &hir_def::body::Body, pat: PatId) -> bool {
|
||||
fn is_non_ref_pat(&mut self, body: &hir_def::expr_store::Body, pat: PatId) -> bool {
|
||||
match &body[pat] {
|
||||
Pat::Tuple { .. }
|
||||
| Pat::TupleStruct { .. }
|
||||
|
|
|
@ -86,10 +86,9 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
};
|
||||
|
||||
let generic_def_id = value_def.to_generic_def_id(self.db);
|
||||
let Some(generic_def) = generic_def_id else {
|
||||
// `value_def` is the kind of item that can never be generic (i.e. statics, at least
|
||||
// currently). We can just skip the binders to get its type.
|
||||
let generic_def = value_def.to_generic_def_id(self.db);
|
||||
if let GenericDefId::StaticId(_) = generic_def {
|
||||
// `Static` is the kind of item that can never be generic currently. We can just skip the binders to get its type.
|
||||
let (ty, binders) = self.db.value_ty(value_def)?.into_value_and_skipped_binders();
|
||||
stdx::always!(binders.is_empty(Interner), "non-empty binders for non-generic def",);
|
||||
return Some(ValuePathResolution::NonGeneric(ty));
|
||||
|
@ -122,7 +121,7 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
|
||||
let parent_substs = self_subst.or_else(|| {
|
||||
let generics = generics(self.db.upcast(), generic_def_id?);
|
||||
let generics = generics(self.db.upcast(), generic_def);
|
||||
let parent_params_len = generics.parent_generics()?.len();
|
||||
let parent_args = &substs[substs.len() - parent_params_len..];
|
||||
Some(Substitution::from_iter(Interner, parent_args))
|
||||
|
|
|
@ -23,10 +23,10 @@ use chalk_ir::{
|
|||
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
body::HygieneId,
|
||||
builtin_type::BuiltinType,
|
||||
data::{adt::StructKind, TraitFlags},
|
||||
expander::Expander,
|
||||
expr_store::HygieneId,
|
||||
generics::{
|
||||
GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
|
||||
WherePredicateTypeTarget,
|
||||
|
@ -2471,14 +2471,14 @@ pub enum ValueTyDefId {
|
|||
impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
|
||||
|
||||
impl ValueTyDefId {
|
||||
pub(crate) fn to_generic_def_id(self, db: &dyn HirDatabase) -> Option<GenericDefId> {
|
||||
pub(crate) fn to_generic_def_id(self, db: &dyn HirDatabase) -> GenericDefId {
|
||||
match self {
|
||||
Self::FunctionId(id) => Some(id.into()),
|
||||
Self::StructId(id) => Some(id.into()),
|
||||
Self::UnionId(id) => Some(id.into()),
|
||||
Self::EnumVariantId(var) => Some(var.lookup(db.upcast()).parent.into()),
|
||||
Self::ConstId(id) => Some(id.into()),
|
||||
Self::StaticId(_) => None,
|
||||
Self::FunctionId(id) => id.into(),
|
||||
Self::StructId(id) => id.into(),
|
||||
Self::UnionId(id) => id.into(),
|
||||
Self::EnumVariantId(var) => var.lookup(db.upcast()).parent.into(),
|
||||
Self::ConstId(id) => id.into(),
|
||||
Self::StaticId(id) => id.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use base_db::CrateId;
|
|||
use chalk_ir::Mutability;
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
body::Body,
|
||||
expr_store::Body,
|
||||
hir::{BindingAnnotation, BindingId, Expr, ExprId, Ordering, PatId},
|
||||
DefWithBodyId, FieldId, StaticId, TupleFieldId, UnionId, VariantId,
|
||||
};
|
||||
|
|
|
@ -6,9 +6,9 @@ use base_db::CrateId;
|
|||
use chalk_ir::{cast::Cast, Mutability};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
body::HygieneId,
|
||||
builtin_type::BuiltinType,
|
||||
data::adt::{StructFlags, VariantData},
|
||||
expr_store::HygieneId,
|
||||
lang_item::LangItem,
|
||||
layout::{TagEncoding, Variants},
|
||||
resolver::{HasResolver, TypeNs, ValueNs},
|
||||
|
|
|
@ -5,8 +5,8 @@ use std::{fmt::Write, iter, mem};
|
|||
use base_db::ra_salsa::Cycle;
|
||||
use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind};
|
||||
use hir_def::{
|
||||
body::{Body, HygieneId},
|
||||
data::adt::{StructKind, VariantData},
|
||||
expr_store::{Body, HygieneId},
|
||||
hir::{
|
||||
ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal,
|
||||
LiteralOrConst, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField,
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
|||
};
|
||||
|
||||
use either::Either;
|
||||
use hir_def::{body::Body, hir::BindingId};
|
||||
use hir_def::{expr_store::Body, hir::BindingId};
|
||||
use hir_expand::{name::Name, Lookup};
|
||||
use la_arena::ArenaMap;
|
||||
use span::Edition;
|
||||
|
|
|
@ -18,8 +18,8 @@ use std::sync::LazyLock;
|
|||
use base_db::SourceDatabaseFileInputExt as _;
|
||||
use expect_test::Expect;
|
||||
use hir_def::{
|
||||
body::{Body, BodySourceMap},
|
||||
db::DefDatabase,
|
||||
expr_store::{Body, BodySourceMap},
|
||||
hir::{ExprId, Pat, PatId},
|
||||
item_scope::ItemScope,
|
||||
nameres::DefMap,
|
||||
|
|
|
@ -1028,6 +1028,7 @@ struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
|
|||
}
|
||||
GenericDefId::ImplId(_) => return None,
|
||||
GenericDefId::ConstId(_) => return None,
|
||||
GenericDefId::StaticId(_) => return None,
|
||||
},
|
||||
))
|
||||
})
|
||||
|
|
|
@ -411,7 +411,7 @@ impl AnyDiagnostic {
|
|||
pub(crate) fn body_validation_diagnostic(
|
||||
db: &dyn HirDatabase,
|
||||
diagnostic: BodyValidationDiagnostic,
|
||||
source_map: &hir_def::body::BodySourceMap,
|
||||
source_map: &hir_def::expr_store::BodySourceMap,
|
||||
) -> Option<AnyDiagnostic> {
|
||||
match diagnostic {
|
||||
BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => {
|
||||
|
@ -547,7 +547,7 @@ impl AnyDiagnostic {
|
|||
def: DefWithBodyId,
|
||||
d: &InferenceDiagnostic,
|
||||
outer_types_source_map: &TypesSourceMap,
|
||||
source_map: &hir_def::body::BodySourceMap,
|
||||
source_map: &hir_def::expr_store::BodySourceMap,
|
||||
) -> Option<AnyDiagnostic> {
|
||||
let expr_syntax = |expr| {
|
||||
source_map.expr_syntax(expr).inspect_err(|_| stdx::never!("synthetic syntax")).ok()
|
||||
|
|
|
@ -183,6 +183,7 @@ impl From<GenericDef> for GenericDefId {
|
|||
GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
|
||||
GenericDef::Impl(it) => GenericDefId::ImplId(it.id),
|
||||
GenericDef::Const(it) => GenericDefId::ConstId(it.id),
|
||||
GenericDef::Static(it) => GenericDefId::StaticId(it.id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -197,6 +198,7 @@ impl From<GenericDefId> for GenericDef {
|
|||
GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
|
||||
GenericDefId::ImplId(it) => GenericDef::Impl(it.into()),
|
||||
GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
|
||||
GenericDefId::StaticId(it) => GenericDef::Static(it.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ use arrayvec::ArrayVec;
|
|||
use base_db::{CrateDisplayName, CrateId, CrateOrigin};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
body::BodyDiagnostic,
|
||||
data::{adt::VariantData, TraitFlags},
|
||||
expr_store::ExpressionStoreDiagnostics,
|
||||
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
|
||||
hir::{BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat},
|
||||
item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
|
||||
|
@ -1892,10 +1892,10 @@ impl DefWithBody {
|
|||
|
||||
for diag in source_map.diagnostics() {
|
||||
acc.push(match diag {
|
||||
BodyDiagnostic::InactiveCode { node, cfg, opts } => {
|
||||
ExpressionStoreDiagnostics::InactiveCode { node, cfg, opts } => {
|
||||
InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into()
|
||||
}
|
||||
BodyDiagnostic::MacroError { node, err } => {
|
||||
ExpressionStoreDiagnostics::MacroError { node, err } => {
|
||||
let RenderedExpandError { message, error, kind } =
|
||||
err.render_to_string(db.upcast());
|
||||
|
||||
|
@ -1919,20 +1919,22 @@ impl DefWithBody {
|
|||
}
|
||||
.into()
|
||||
}
|
||||
BodyDiagnostic::UnresolvedMacroCall { node, path } => UnresolvedMacroCall {
|
||||
macro_call: (*node).map(|ast_ptr| ast_ptr.into()),
|
||||
precise_location: None,
|
||||
path: path.clone(),
|
||||
is_bang: true,
|
||||
ExpressionStoreDiagnostics::UnresolvedMacroCall { node, path } => {
|
||||
UnresolvedMacroCall {
|
||||
macro_call: (*node).map(|ast_ptr| ast_ptr.into()),
|
||||
precise_location: None,
|
||||
path: path.clone(),
|
||||
is_bang: true,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
.into(),
|
||||
BodyDiagnostic::AwaitOutsideOfAsync { node, location } => {
|
||||
ExpressionStoreDiagnostics::AwaitOutsideOfAsync { node, location } => {
|
||||
AwaitOutsideOfAsync { node: *node, location: location.clone() }.into()
|
||||
}
|
||||
BodyDiagnostic::UnreachableLabel { node, name } => {
|
||||
ExpressionStoreDiagnostics::UnreachableLabel { node, name } => {
|
||||
UnreachableLabel { node: *node, name: name.clone() }.into()
|
||||
}
|
||||
BodyDiagnostic::UndeclaredLabel { node, name } => {
|
||||
ExpressionStoreDiagnostics::UndeclaredLabel { node, name } => {
|
||||
UndeclaredLabel { node: *node, name: name.clone() }.into()
|
||||
}
|
||||
});
|
||||
|
@ -3456,6 +3458,7 @@ pub enum GenericDef {
|
|||
Impl(Impl),
|
||||
// consts can have type parameters from their parents (i.e. associated consts of traits)
|
||||
Const(Const),
|
||||
Static(Static),
|
||||
}
|
||||
impl_from!(
|
||||
Function,
|
||||
|
@ -3464,7 +3467,8 @@ impl_from!(
|
|||
TraitAlias,
|
||||
TypeAlias,
|
||||
Impl,
|
||||
Const
|
||||
Const,
|
||||
Static
|
||||
for GenericDef
|
||||
);
|
||||
|
||||
|
@ -3514,6 +3518,7 @@ impl GenericDef {
|
|||
GenericDef::TypeAlias(it) => it.id.into(),
|
||||
GenericDef::Impl(it) => it.id.into(),
|
||||
GenericDef::Const(it) => it.id.into(),
|
||||
GenericDef::Static(it) => it.id.into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3571,6 +3576,7 @@ impl GenericDef {
|
|||
item_tree_source_maps.impl_(id.value).generics()
|
||||
}
|
||||
GenericDefId::ConstId(_) => return,
|
||||
GenericDefId::StaticId(_) => return,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
body::{
|
||||
expr_store::{
|
||||
scope::{ExprScopes, ScopeId},
|
||||
Body, BodySourceMap, HygieneId,
|
||||
},
|
||||
|
|
|
@ -986,6 +986,7 @@ impl From<GenericDef> for Definition {
|
|||
GenericDef::TypeAlias(it) => it.into(),
|
||||
GenericDef::Impl(it) => it.into(),
|
||||
GenericDef::Const(it) => it.into(),
|
||||
GenericDef::Static(it) => it.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -354,6 +354,7 @@ impl Definition {
|
|||
hir::GenericDef::TypeAlias(it) => it.source(db).map(|src| src.syntax().cloned()),
|
||||
hir::GenericDef::Impl(it) => it.source(db).map(|src| src.syntax().cloned()),
|
||||
hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()),
|
||||
hir::GenericDef::Static(it) => it.source(db).map(|src| src.syntax().cloned()),
|
||||
};
|
||||
return match def {
|
||||
Some(def) => SearchScope::file_range(
|
||||
|
|
|
@ -434,6 +434,7 @@ fn definition_owner_name(db: &RootDatabase, def: Definition, edition: Edition) -
|
|||
None => it.name(db),
|
||||
}
|
||||
}
|
||||
hir::GenericDef::Static(it) => Some(it.name(db)),
|
||||
},
|
||||
Definition::DeriveHelper(derive_helper) => Some(derive_helper.derive().name(db)),
|
||||
d => {
|
||||
|
|
|
@ -321,7 +321,9 @@ fn signature_help_for_generics(
|
|||
format_to!(res.signature, "type {}", it.name(db).display(db, edition));
|
||||
}
|
||||
// These don't have generic args that can be specified
|
||||
hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) => return None,
|
||||
hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) | hir::GenericDef::Static(_) => {
|
||||
return None
|
||||
}
|
||||
}
|
||||
|
||||
let params = generics_def.params(sema.db);
|
||||
|
|
|
@ -13,7 +13,7 @@ use hir::{
|
|||
ModuleDef, Name,
|
||||
};
|
||||
use hir_def::{
|
||||
body::BodySourceMap,
|
||||
expr_store::BodySourceMap,
|
||||
hir::{ExprId, PatId},
|
||||
SyntheticSyntax,
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue