mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
⬆️ rust-analyzer
This commit is contained in:
parent
3a57388d13
commit
4f55ebbd4f
122 changed files with 2885 additions and 1093 deletions
|
@ -1,12 +1,12 @@
|
|||
//! Defines hir-level representation of structs, enums and unions
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::{num::NonZeroU32, sync::Arc};
|
||||
|
||||
use base_db::CrateId;
|
||||
use either::Either;
|
||||
use hir_expand::{
|
||||
name::{AsName, Name},
|
||||
InFile,
|
||||
HirFileId, InFile,
|
||||
};
|
||||
use la_arena::{Arena, ArenaMap};
|
||||
use syntax::ast::{self, HasName, HasVisibility};
|
||||
|
@ -14,15 +14,18 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
|
|||
|
||||
use crate::{
|
||||
body::{CfgExpander, LowerCtx},
|
||||
builtin_type::{BuiltinInt, BuiltinUint},
|
||||
db::DefDatabase,
|
||||
intern::Interned,
|
||||
item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId},
|
||||
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
|
||||
nameres::diagnostics::DefDiagnostic,
|
||||
src::HasChildSource,
|
||||
src::HasSource,
|
||||
trace::Trace,
|
||||
type_ref::TypeRef,
|
||||
visibility::RawVisibility,
|
||||
EnumId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
|
||||
EnumId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId, UnionId,
|
||||
VariantId,
|
||||
};
|
||||
use cfg::CfgOptions;
|
||||
|
||||
|
@ -31,7 +34,7 @@ use cfg::CfgOptions;
|
|||
pub struct StructData {
|
||||
pub name: Name,
|
||||
pub variant_data: Arc<VariantData>,
|
||||
pub repr: Option<ReprKind>,
|
||||
pub repr: Option<ReprData>,
|
||||
pub visibility: RawVisibility,
|
||||
}
|
||||
|
||||
|
@ -39,6 +42,7 @@ pub struct StructData {
|
|||
pub struct EnumData {
|
||||
pub name: Name,
|
||||
pub variants: Arena<EnumVariantData>,
|
||||
pub repr: Option<ReprData>,
|
||||
pub visibility: RawVisibility,
|
||||
}
|
||||
|
||||
|
@ -63,10 +67,19 @@ pub struct FieldData {
|
|||
pub visibility: RawVisibility,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ReprKind {
|
||||
Packed,
|
||||
Other,
|
||||
C,
|
||||
BuiltinInt { builtin: Either<BuiltinInt, BuiltinUint>, is_c: bool },
|
||||
Transparent,
|
||||
Default,
|
||||
}
|
||||
|
||||
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ReprData {
|
||||
pub kind: ReprKind,
|
||||
pub packed: bool,
|
||||
pub align: Option<NonZeroU32>,
|
||||
}
|
||||
|
||||
fn repr_from_value(
|
||||
|
@ -74,25 +87,71 @@ fn repr_from_value(
|
|||
krate: CrateId,
|
||||
item_tree: &ItemTree,
|
||||
of: AttrOwner,
|
||||
) -> Option<ReprKind> {
|
||||
) -> Option<ReprData> {
|
||||
item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
|
||||
}
|
||||
|
||||
fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
|
||||
fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
|
||||
match tt.delimiter {
|
||||
Some(Delimiter { kind: DelimiterKind::Parenthesis, .. }) => {}
|
||||
_ => return None,
|
||||
}
|
||||
|
||||
let mut it = tt.token_trees.iter();
|
||||
match it.next()? {
|
||||
TokenTree::Leaf(Leaf::Ident(ident)) if ident.text == "packed" => Some(ReprKind::Packed),
|
||||
_ => Some(ReprKind::Other),
|
||||
let mut data = ReprData { kind: ReprKind::Default, packed: false, align: None };
|
||||
|
||||
let mut tts = tt.token_trees.iter().peekable();
|
||||
while let Some(tt) = tts.next() {
|
||||
if let TokenTree::Leaf(Leaf::Ident(ident)) = tt {
|
||||
match &*ident.text {
|
||||
"packed" => {
|
||||
data.packed = true;
|
||||
if let Some(TokenTree::Subtree(_)) = tts.peek() {
|
||||
tts.next();
|
||||
}
|
||||
}
|
||||
"align" => {
|
||||
if let Some(TokenTree::Subtree(tt)) = tts.peek() {
|
||||
tts.next();
|
||||
if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
|
||||
if let Ok(align) = lit.text.parse() {
|
||||
data.align = Some(align);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"C" => {
|
||||
if let ReprKind::BuiltinInt { is_c, .. } = &mut data.kind {
|
||||
*is_c = true;
|
||||
} else {
|
||||
data.kind = ReprKind::C;
|
||||
}
|
||||
}
|
||||
"transparent" => data.kind = ReprKind::Transparent,
|
||||
repr => {
|
||||
let is_c = matches!(data.kind, ReprKind::C);
|
||||
if let Some(builtin) = BuiltinInt::from_suffix(repr)
|
||||
.map(Either::Left)
|
||||
.or_else(|| BuiltinUint::from_suffix(repr).map(Either::Right))
|
||||
{
|
||||
data.kind = ReprKind::BuiltinInt { builtin, is_c };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(data)
|
||||
}
|
||||
|
||||
impl StructData {
|
||||
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
|
||||
db.struct_data_with_diagnostics(id).0
|
||||
}
|
||||
|
||||
pub(crate) fn struct_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
id: StructId,
|
||||
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
|
||||
let loc = id.lookup(db);
|
||||
let krate = loc.container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
|
@ -100,15 +159,35 @@ impl StructData {
|
|||
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||
|
||||
let strukt = &item_tree[loc.id.value];
|
||||
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
|
||||
Arc::new(StructData {
|
||||
name: strukt.name.clone(),
|
||||
variant_data: Arc::new(variant_data),
|
||||
repr,
|
||||
visibility: item_tree[strukt.visibility].clone(),
|
||||
})
|
||||
let (variant_data, diagnostics) = lower_fields(
|
||||
db,
|
||||
krate,
|
||||
loc.id.file_id(),
|
||||
loc.container.local_id,
|
||||
&item_tree,
|
||||
&cfg_options,
|
||||
&strukt.fields,
|
||||
None,
|
||||
);
|
||||
(
|
||||
Arc::new(StructData {
|
||||
name: strukt.name.clone(),
|
||||
variant_data: Arc::new(variant_data),
|
||||
repr,
|
||||
visibility: item_tree[strukt.visibility].clone(),
|
||||
}),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
|
||||
db.union_data_with_diagnostics(id).0
|
||||
}
|
||||
|
||||
pub(crate) fn union_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
id: UnionId,
|
||||
) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
|
||||
let loc = id.lookup(db);
|
||||
let krate = loc.container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
|
@ -116,56 +195,98 @@ impl StructData {
|
|||
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||
|
||||
let union = &item_tree[loc.id.value];
|
||||
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
|
||||
|
||||
Arc::new(StructData {
|
||||
name: union.name.clone(),
|
||||
variant_data: Arc::new(variant_data),
|
||||
repr,
|
||||
visibility: item_tree[union.visibility].clone(),
|
||||
})
|
||||
let (variant_data, diagnostics) = lower_fields(
|
||||
db,
|
||||
krate,
|
||||
loc.id.file_id(),
|
||||
loc.container.local_id,
|
||||
&item_tree,
|
||||
&cfg_options,
|
||||
&union.fields,
|
||||
None,
|
||||
);
|
||||
(
|
||||
Arc::new(StructData {
|
||||
name: union.name.clone(),
|
||||
variant_data: Arc::new(variant_data),
|
||||
repr,
|
||||
visibility: item_tree[union.visibility].clone(),
|
||||
}),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl EnumData {
|
||||
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
|
||||
db.enum_data_with_diagnostics(e).0
|
||||
}
|
||||
|
||||
pub(crate) fn enum_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
e: EnumId,
|
||||
) -> (Arc<EnumData>, Arc<[DefDiagnostic]>) {
|
||||
let loc = e.lookup(db);
|
||||
let krate = loc.container.krate;
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
|
||||
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
||||
|
||||
let enum_ = &item_tree[loc.id.value];
|
||||
let mut variants = Arena::new();
|
||||
let mut diagnostics = Vec::new();
|
||||
for tree_id in enum_.variants.clone() {
|
||||
if item_tree.attrs(db, krate, tree_id.into()).is_cfg_enabled(&cfg_options) {
|
||||
let var = &item_tree[tree_id];
|
||||
let var_data = lower_fields(
|
||||
let attrs = item_tree.attrs(db, krate, tree_id.into());
|
||||
let var = &item_tree[tree_id];
|
||||
if attrs.is_cfg_enabled(&cfg_options) {
|
||||
let (var_data, field_diagnostics) = lower_fields(
|
||||
db,
|
||||
krate,
|
||||
loc.id.file_id(),
|
||||
loc.container.local_id,
|
||||
&item_tree,
|
||||
&cfg_options,
|
||||
&var.fields,
|
||||
Some(enum_.visibility),
|
||||
);
|
||||
diagnostics.extend(field_diagnostics);
|
||||
|
||||
variants.alloc(EnumVariantData {
|
||||
name: var.name.clone(),
|
||||
variant_data: Arc::new(var_data),
|
||||
});
|
||||
} else {
|
||||
diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
loc.container.local_id,
|
||||
InFile::new(loc.id.file_id(), var.ast_id.upcast()),
|
||||
attrs.cfg().unwrap(),
|
||||
cfg_options.clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Arc::new(EnumData {
|
||||
name: enum_.name.clone(),
|
||||
variants,
|
||||
visibility: item_tree[enum_.visibility].clone(),
|
||||
})
|
||||
(
|
||||
Arc::new(EnumData {
|
||||
name: enum_.name.clone(),
|
||||
variants,
|
||||
repr,
|
||||
visibility: item_tree[enum_.visibility].clone(),
|
||||
}),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
|
||||
let (id, _) = self.variants.iter().find(|(_id, data)| &data.name == name)?;
|
||||
Some(id)
|
||||
}
|
||||
|
||||
pub fn variant_body_type(&self) -> Either<BuiltinInt, BuiltinUint> {
|
||||
match self.repr {
|
||||
Some(ReprData { kind: ReprKind::BuiltinInt { builtin, .. }, .. }) => builtin,
|
||||
_ => Either::Left(BuiltinInt::Isize),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasChildSource<LocalEnumVariantId> for EnumId {
|
||||
|
@ -324,31 +445,64 @@ fn lower_struct(
|
|||
fn lower_fields(
|
||||
db: &dyn DefDatabase,
|
||||
krate: CrateId,
|
||||
current_file_id: HirFileId,
|
||||
container: LocalModuleId,
|
||||
item_tree: &ItemTree,
|
||||
cfg_options: &CfgOptions,
|
||||
fields: &Fields,
|
||||
override_visibility: Option<RawVisibilityId>,
|
||||
) -> VariantData {
|
||||
) -> (VariantData, Vec<DefDiagnostic>) {
|
||||
let mut diagnostics = Vec::new();
|
||||
match fields {
|
||||
Fields::Record(flds) => {
|
||||
let mut arena = Arena::new();
|
||||
for field_id in flds.clone() {
|
||||
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
|
||||
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
|
||||
let attrs = item_tree.attrs(db, krate, field_id.into());
|
||||
let field = &item_tree[field_id];
|
||||
if attrs.is_cfg_enabled(cfg_options) {
|
||||
arena.alloc(lower_field(item_tree, field, override_visibility));
|
||||
} else {
|
||||
diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
container,
|
||||
InFile::new(
|
||||
current_file_id,
|
||||
match field.ast_id {
|
||||
FieldAstId::Record(it) => it.upcast(),
|
||||
FieldAstId::Tuple(it) => it.upcast(),
|
||||
},
|
||||
),
|
||||
attrs.cfg().unwrap(),
|
||||
cfg_options.clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
VariantData::Record(arena)
|
||||
(VariantData::Record(arena), diagnostics)
|
||||
}
|
||||
Fields::Tuple(flds) => {
|
||||
let mut arena = Arena::new();
|
||||
for field_id in flds.clone() {
|
||||
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
|
||||
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
|
||||
let attrs = item_tree.attrs(db, krate, field_id.into());
|
||||
let field = &item_tree[field_id];
|
||||
if attrs.is_cfg_enabled(cfg_options) {
|
||||
arena.alloc(lower_field(item_tree, field, override_visibility));
|
||||
} else {
|
||||
diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
container,
|
||||
InFile::new(
|
||||
current_file_id,
|
||||
match field.ast_id {
|
||||
FieldAstId::Record(it) => it.upcast(),
|
||||
FieldAstId::Tuple(it) => it.upcast(),
|
||||
},
|
||||
),
|
||||
attrs.cfg().unwrap(),
|
||||
cfg_options.clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
VariantData::Tuple(arena)
|
||||
(VariantData::Tuple(arena), diagnostics)
|
||||
}
|
||||
Fields::Unit => VariantData::Unit,
|
||||
Fields::Unit => (VariantData::Unit, diagnostics),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ use crate::{
|
|||
macro_id_to_def_id,
|
||||
nameres::DefMap,
|
||||
path::{ModPath, Path},
|
||||
src::HasSource,
|
||||
src::{HasChildSource, HasSource},
|
||||
AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, MacroId, ModuleId,
|
||||
UnresolvedMacro,
|
||||
};
|
||||
|
@ -324,6 +324,12 @@ impl Body {
|
|||
let src = s.source(db);
|
||||
(src.file_id, s.module(db), src.value.body())
|
||||
}
|
||||
DefWithBodyId::VariantId(v) => {
|
||||
let e = v.parent.lookup(db);
|
||||
let src = v.parent.child_source(db);
|
||||
let variant = &src.value[v.local_id];
|
||||
(src.file_id, e.container, variant.expr())
|
||||
}
|
||||
};
|
||||
let expander = Expander::new(db, file_id, module);
|
||||
let (mut body, source_map) = Body::new(db, expander, params, body);
|
||||
|
|
|
@ -29,8 +29,9 @@ use crate::{
|
|||
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
|
||||
db::DefDatabase,
|
||||
expr::{
|
||||
dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, FloatTypeWrapper, Label, LabelId,
|
||||
Literal, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
|
||||
dummy_expr_id, Array, BindingAnnotation, ClosureKind, Expr, ExprId, FloatTypeWrapper,
|
||||
Label, LabelId, Literal, MatchArm, Movability, Pat, PatId, RecordFieldPat, RecordLitField,
|
||||
Statement,
|
||||
},
|
||||
intern::Interned,
|
||||
item_scope::BuiltinShadowMode,
|
||||
|
@ -97,6 +98,7 @@ pub(super) fn lower(
|
|||
name_to_pat_grouping: Default::default(),
|
||||
is_lowering_inside_or_pat: false,
|
||||
is_lowering_assignee_expr: false,
|
||||
is_lowering_generator: false,
|
||||
}
|
||||
.collect(params, body)
|
||||
}
|
||||
|
@ -111,6 +113,7 @@ struct ExprCollector<'a> {
|
|||
name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>,
|
||||
is_lowering_inside_or_pat: bool,
|
||||
is_lowering_assignee_expr: bool,
|
||||
is_lowering_generator: bool,
|
||||
}
|
||||
|
||||
impl ExprCollector<'_> {
|
||||
|
@ -358,6 +361,7 @@ impl ExprCollector<'_> {
|
|||
self.alloc_expr(Expr::Return { expr }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::YieldExpr(e) => {
|
||||
self.is_lowering_generator = true;
|
||||
let expr = e.expr().map(|e| self.collect_expr(e));
|
||||
self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
|
||||
}
|
||||
|
@ -459,13 +463,31 @@ impl ExprCollector<'_> {
|
|||
.ret_type()
|
||||
.and_then(|r| r.ty())
|
||||
.map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
|
||||
|
||||
let prev_is_lowering_generator = self.is_lowering_generator;
|
||||
self.is_lowering_generator = false;
|
||||
|
||||
let body = self.collect_expr_opt(e.body());
|
||||
|
||||
let closure_kind = if self.is_lowering_generator {
|
||||
let movability = if e.static_token().is_some() {
|
||||
Movability::Static
|
||||
} else {
|
||||
Movability::Movable
|
||||
};
|
||||
ClosureKind::Generator(movability)
|
||||
} else {
|
||||
ClosureKind::Closure
|
||||
};
|
||||
self.is_lowering_generator = prev_is_lowering_generator;
|
||||
|
||||
self.alloc_expr(
|
||||
Expr::Closure {
|
||||
args: args.into(),
|
||||
arg_types: arg_types.into(),
|
||||
ret_type,
|
||||
body,
|
||||
closure_kind,
|
||||
},
|
||||
syntax_ptr,
|
||||
)
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
use syntax::ast::HasName;
|
||||
|
||||
use crate::{
|
||||
expr::{Array, BindingAnnotation, Literal, Statement},
|
||||
expr::{Array, BindingAnnotation, ClosureKind, Literal, Movability, Statement},
|
||||
pretty::{print_generic_args, print_path, print_type_ref},
|
||||
type_ref::TypeRef,
|
||||
};
|
||||
|
@ -32,6 +34,16 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
|
|||
};
|
||||
format!("const {} = ", name)
|
||||
}
|
||||
DefWithBodyId::VariantId(it) => {
|
||||
needs_semi = false;
|
||||
let src = it.parent.child_source(db);
|
||||
let variant = &src.value[it.local_id];
|
||||
let name = match &variant.name() {
|
||||
Some(name) => name.to_string(),
|
||||
None => "_".to_string(),
|
||||
};
|
||||
format!("{}", name)
|
||||
}
|
||||
};
|
||||
|
||||
let mut p = Printer { body, buf: header, indent_level: 0, needs_indent: false };
|
||||
|
@ -350,7 +362,10 @@ impl<'a> Printer<'a> {
|
|||
self.print_expr(*index);
|
||||
w!(self, "]");
|
||||
}
|
||||
Expr::Closure { args, arg_types, ret_type, body } => {
|
||||
Expr::Closure { args, arg_types, ret_type, body, closure_kind } => {
|
||||
if let ClosureKind::Generator(Movability::Static) = closure_kind {
|
||||
w!(self, "static ");
|
||||
}
|
||||
w!(self, "|");
|
||||
for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() {
|
||||
if i != 0 {
|
||||
|
|
|
@ -198,6 +198,10 @@ impl ChildBySource for EnumId {
|
|||
impl ChildBySource for DefWithBodyId {
|
||||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
||||
let body = db.body(*self);
|
||||
if let &DefWithBodyId::VariantId(v) = self {
|
||||
VariantId::EnumVariantId(v).child_by_source_to(db, res, file_id)
|
||||
}
|
||||
|
||||
for (_, def_map) in body.blocks(db) {
|
||||
// All block expressions are merged into the same map, because they logically all add
|
||||
// inner items to the containing `DefWithBodyId`.
|
||||
|
|
|
@ -219,7 +219,7 @@ impl TraitData {
|
|||
pub(crate) fn trait_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
tr: TraitId,
|
||||
) -> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>) {
|
||||
) -> (Arc<TraitData>, Arc<[DefDiagnostic]>) {
|
||||
let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
|
||||
let item_tree = tree_id.item_tree(db);
|
||||
let tr_def = &item_tree[tree_id.value];
|
||||
|
@ -251,7 +251,7 @@ impl TraitData {
|
|||
visibility,
|
||||
skip_array_during_method_dispatch,
|
||||
}),
|
||||
Arc::new(diagnostics),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ impl ImplData {
|
|||
pub(crate) fn impl_data_with_diagnostics_query(
|
||||
db: &dyn DefDatabase,
|
||||
id: ImplId,
|
||||
) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>) {
|
||||
) -> (Arc<ImplData>, Arc<[DefDiagnostic]>) {
|
||||
let _p = profile::span("impl_data_with_diagnostics_query");
|
||||
let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);
|
||||
|
||||
|
@ -318,7 +318,7 @@ impl ImplData {
|
|||
|
||||
(
|
||||
Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }),
|
||||
Arc::new(diagnostics),
|
||||
diagnostics.into(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -97,24 +97,33 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
|
|||
#[salsa::invoke(StructData::struct_data_query)]
|
||||
fn struct_data(&self, id: StructId) -> Arc<StructData>;
|
||||
|
||||
#[salsa::invoke(StructData::struct_data_with_diagnostics_query)]
|
||||
fn struct_data_with_diagnostics(&self, id: StructId)
|
||||
-> (Arc<StructData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(StructData::union_data_query)]
|
||||
fn union_data(&self, id: UnionId) -> Arc<StructData>;
|
||||
|
||||
#[salsa::invoke(StructData::union_data_with_diagnostics_query)]
|
||||
fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc<StructData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(EnumData::enum_data_query)]
|
||||
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
|
||||
|
||||
#[salsa::invoke(EnumData::enum_data_with_diagnostics_query)]
|
||||
fn enum_data_with_diagnostics(&self, e: EnumId) -> (Arc<EnumData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(ImplData::impl_data_query)]
|
||||
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
|
||||
|
||||
#[salsa::invoke(ImplData::impl_data_with_diagnostics_query)]
|
||||
fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>);
|
||||
fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(TraitData::trait_data_query)]
|
||||
fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
|
||||
|
||||
#[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
|
||||
fn trait_data_with_diagnostics(&self, tr: TraitId)
|
||||
-> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>);
|
||||
fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, Arc<[DefDiagnostic]>);
|
||||
|
||||
#[salsa::invoke(TypeAliasData::type_alias_data_query)]
|
||||
fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
|
||||
|
|
|
@ -198,6 +198,7 @@ pub enum Expr {
|
|||
arg_types: Box<[Option<Interned<TypeRef>>]>,
|
||||
ret_type: Option<Interned<TypeRef>>,
|
||||
body: ExprId,
|
||||
closure_kind: ClosureKind,
|
||||
},
|
||||
Tuple {
|
||||
exprs: Box<[ExprId]>,
|
||||
|
@ -211,6 +212,18 @@ pub enum Expr {
|
|||
Underscore,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ClosureKind {
|
||||
Closure,
|
||||
Generator(Movability),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Movability {
|
||||
Static,
|
||||
Movable,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum Array {
|
||||
ElementList { elements: Box<[ExprId]>, is_assignee_expr: bool },
|
||||
|
|
|
@ -333,8 +333,8 @@ fn calculate_best_path(
|
|||
db,
|
||||
def_map,
|
||||
visited_modules,
|
||||
from,
|
||||
crate_root,
|
||||
from,
|
||||
info.container,
|
||||
max_len - 1,
|
||||
prefixed,
|
||||
|
|
|
@ -943,6 +943,7 @@ impl AssocItem {
|
|||
pub struct Variant {
|
||||
pub name: Name,
|
||||
pub fields: Fields,
|
||||
pub ast_id: FileAstId<ast::Variant>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -952,10 +953,17 @@ pub enum Fields {
|
|||
Unit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum FieldAstId {
|
||||
Record(FileAstId<ast::RecordField>),
|
||||
Tuple(FileAstId<ast::TupleField>),
|
||||
}
|
||||
|
||||
/// A single field of an enum variant or struct
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Field {
|
||||
pub name: Name,
|
||||
pub type_ref: Interned<TypeRef>,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FieldAstId,
|
||||
}
|
||||
|
|
|
@ -184,7 +184,8 @@ impl<'a> Ctx<'a> {
|
|||
let name = field.name()?.as_name();
|
||||
let visibility = self.lower_visibility(field);
|
||||
let type_ref = self.lower_type_ref_opt(field.ty());
|
||||
let res = Field { name, type_ref, visibility };
|
||||
let ast_id = FieldAstId::Record(self.source_ast_id_map.ast_id(field));
|
||||
let res = Field { name, type_ref, visibility, ast_id };
|
||||
Some(res)
|
||||
}
|
||||
|
||||
|
@ -203,7 +204,8 @@ impl<'a> Ctx<'a> {
|
|||
let name = Name::new_tuple_field(idx);
|
||||
let visibility = self.lower_visibility(field);
|
||||
let type_ref = self.lower_type_ref_opt(field.ty());
|
||||
Field { name, type_ref, visibility }
|
||||
let ast_id = FieldAstId::Tuple(self.source_ast_id_map.ast_id(field));
|
||||
Field { name, type_ref, visibility, ast_id }
|
||||
}
|
||||
|
||||
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
|
||||
|
@ -247,7 +249,8 @@ impl<'a> Ctx<'a> {
|
|||
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
|
||||
let name = variant.name()?.as_name();
|
||||
let fields = self.lower_fields(&variant.kind());
|
||||
let res = Variant { name, fields };
|
||||
let ast_id = self.source_ast_id_map.ast_id(variant);
|
||||
let res = Variant { name, fields, ast_id };
|
||||
Some(res)
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ impl<'a> Printer<'a> {
|
|||
w!(self, "{{");
|
||||
self.indented(|this| {
|
||||
for field in fields.clone() {
|
||||
let Field { visibility, name, type_ref } = &this.tree[field];
|
||||
let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
|
||||
this.print_attrs_of(field);
|
||||
this.print_visibility(*visibility);
|
||||
w!(this, "{}: ", name);
|
||||
|
@ -129,7 +129,7 @@ impl<'a> Printer<'a> {
|
|||
w!(self, "(");
|
||||
self.indented(|this| {
|
||||
for field in fields.clone() {
|
||||
let Field { visibility, name, type_ref } = &this.tree[field];
|
||||
let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
|
||||
this.print_attrs_of(field);
|
||||
this.print_visibility(*visibility);
|
||||
w!(this, "{}: ", name);
|
||||
|
@ -323,7 +323,7 @@ impl<'a> Printer<'a> {
|
|||
self.print_where_clause_and_opening_brace(generic_params);
|
||||
self.indented(|this| {
|
||||
for variant in variants.clone() {
|
||||
let Variant { name, fields } = &this.tree[variant];
|
||||
let Variant { name, fields, ast_id: _ } = &this.tree[variant];
|
||||
this.print_attrs_of(variant);
|
||||
w!(this, "{}", name);
|
||||
this.print_fields(fields);
|
||||
|
|
|
@ -474,16 +474,24 @@ pub enum DefWithBodyId {
|
|||
FunctionId(FunctionId),
|
||||
StaticId(StaticId),
|
||||
ConstId(ConstId),
|
||||
VariantId(EnumVariantId),
|
||||
}
|
||||
|
||||
impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
|
||||
|
||||
impl From<EnumVariantId> for DefWithBodyId {
|
||||
fn from(id: EnumVariantId) -> Self {
|
||||
DefWithBodyId::VariantId(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl DefWithBodyId {
|
||||
pub fn as_generic_def_id(self) -> Option<GenericDefId> {
|
||||
match self {
|
||||
DefWithBodyId::FunctionId(f) => Some(f.into()),
|
||||
DefWithBodyId::StaticId(_) => None,
|
||||
DefWithBodyId::ConstId(c) => Some(c.into()),
|
||||
DefWithBodyId::VariantId(c) => Some(c.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -681,6 +689,7 @@ impl HasModule for DefWithBodyId {
|
|||
DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
|
||||
DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
|
||||
DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
|
||||
DefWithBodyId::VariantId(it) => it.parent.lookup(db).container,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -691,6 +700,7 @@ impl DefWithBodyId {
|
|||
DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(),
|
||||
DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(),
|
||||
DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(),
|
||||
DefWithBodyId::VariantId(it) => it.parent.lookup(db).id.value.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2122,7 +2122,7 @@ impl ModCollector<'_, '_> {
|
|||
fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
|
||||
let ast_id = item.ast_id(self.item_tree);
|
||||
|
||||
let ast_id = InFile::new(self.file_id(), ast_id);
|
||||
let ast_id = InFile::new(self.file_id(), ast_id.upcast());
|
||||
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
|
||||
self.module_id,
|
||||
ast_id,
|
||||
|
|
|
@ -4,7 +4,7 @@ use base_db::CrateId;
|
|||
use cfg::{CfgExpr, CfgOptions};
|
||||
use hir_expand::MacroCallKind;
|
||||
use la_arena::Idx;
|
||||
use syntax::ast;
|
||||
use syntax::ast::{self, AnyHasAttrs};
|
||||
|
||||
use crate::{
|
||||
attr::AttrId,
|
||||
|
@ -22,7 +22,7 @@ pub enum DefDiagnosticKind {
|
|||
|
||||
UnresolvedImport { id: ItemTreeId<item_tree::Import>, index: Idx<ast::UseTree> },
|
||||
|
||||
UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions },
|
||||
UnconfiguredCode { ast: AstId<AnyHasAttrs>, cfg: CfgExpr, opts: CfgOptions },
|
||||
|
||||
UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
|
||||
|
||||
|
@ -75,7 +75,7 @@ impl DefDiagnostic {
|
|||
|
||||
pub fn unconfigured_code(
|
||||
container: LocalModuleId,
|
||||
ast: AstId<ast::Item>,
|
||||
ast: AstId<ast::AnyHasAttrs>,
|
||||
cfg: CfgExpr,
|
||||
opts: CfgOptions,
|
||||
) -> Self {
|
||||
|
|
|
@ -839,6 +839,7 @@ impl HasResolver for DefWithBodyId {
|
|||
DefWithBodyId::ConstId(c) => c.resolver(db),
|
||||
DefWithBodyId::FunctionId(f) => f.resolver(db),
|
||||
DefWithBodyId::StaticId(s) => s.resolver(db),
|
||||
DefWithBodyId::VariantId(v) => v.parent.resolver(db),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue