summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/hir-def
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/hir-def')
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/adt.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr.rs48
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body.rs71
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs202
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs103
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs50
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs22
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs70
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr.rs70
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs44
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/import_map.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs137
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs29
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/keys.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres.rs32
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs41
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs258
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/test_db.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs62
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/visibility.rs31
33 files changed, 890 insertions, 491 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/adt.rs
index 9bc1c54a3..b336f59ff 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/adt.rs
@@ -40,6 +40,7 @@ pub struct StructData {
pub repr: Option<ReprOptions>,
pub visibility: RawVisibility,
pub rustc_has_incoherent_inherent_impls: bool,
+ pub fundamental: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -173,10 +174,10 @@ impl StructData {
let item_tree = loc.id.item_tree(db);
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
- let rustc_has_incoherent_inherent_impls = item_tree
- .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
- .by_key("rustc_has_incoherent_inherent_impls")
- .exists();
+ let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
+ let rustc_has_incoherent_inherent_impls =
+ attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
+ let fundamental = attrs.by_key("fundamental").exists();
let strukt = &item_tree[loc.id.value];
let (variant_data, diagnostics) = lower_fields(
@@ -196,6 +197,7 @@ impl StructData {
repr,
visibility: item_tree[strukt.visibility].clone(),
rustc_has_incoherent_inherent_impls,
+ fundamental,
}),
diagnostics.into(),
)
@@ -215,10 +217,10 @@ impl StructData {
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
- let rustc_has_incoherent_inherent_impls = item_tree
- .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
- .by_key("rustc_has_incoherent_inherent_impls")
- .exists();
+ let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
+ let rustc_has_incoherent_inherent_impls =
+ attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
+ let fundamental = attrs.by_key("fundamental").exists();
let union = &item_tree[loc.id.value];
let (variant_data, diagnostics) = lower_fields(
@@ -238,6 +240,7 @@ impl StructData {
repr,
visibility: item_tree[union.visibility].clone(),
rustc_has_incoherent_inherent_impls,
+ fundamental,
}),
diagnostics.into(),
)
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index fcd92ad33..200072c17 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -300,6 +300,7 @@ impl AttrsWithOwner {
AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
},
AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db),
+ AttrDefId::TraitAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::MacroId(it) => match it {
MacroId::Macro2Id(it) => attrs_from_item_tree(it.lookup(db).id, db),
MacroId::MacroRulesId(it) => attrs_from_item_tree(it.lookup(db).id, db),
@@ -315,26 +316,14 @@ impl AttrsWithOwner {
let src = it.parent().child_source(db);
RawAttrs::from_attrs_owner(
db.upcast(),
- src.with_value(src.value[it.local_id()].as_ref().either(
- |it| match it {
- ast::TypeOrConstParam::Type(it) => it as _,
- ast::TypeOrConstParam::Const(it) => it as _,
- },
- |it| it as _,
- )),
+ src.with_value(&src.value[it.local_id()]),
)
}
GenericParamId::TypeParamId(it) => {
let src = it.parent().child_source(db);
RawAttrs::from_attrs_owner(
db.upcast(),
- src.with_value(src.value[it.local_id()].as_ref().either(
- |it| match it {
- ast::TypeOrConstParam::Type(it) => it as _,
- ast::TypeOrConstParam::Const(it) => it as _,
- },
- |it| it as _,
- )),
+ src.with_value(&src.value[it.local_id()]),
)
}
GenericParamId::LifetimeParamId(it) => {
@@ -404,6 +393,7 @@ impl AttrsWithOwner {
AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
+ AttrDefId::TraitAliasId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
AttrDefId::MacroId(id) => match id {
MacroId::Macro2Id(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
@@ -412,28 +402,14 @@ impl AttrsWithOwner {
},
AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
AttrDefId::GenericParamId(id) => match id {
- GenericParamId::ConstParamId(id) => {
- id.parent().child_source(db).map(|source| match &source[id.local_id()] {
- Either::Left(ast::TypeOrConstParam::Type(id)) => {
- ast::AnyHasAttrs::new(id.clone())
- }
- Either::Left(ast::TypeOrConstParam::Const(id)) => {
- ast::AnyHasAttrs::new(id.clone())
- }
- Either::Right(id) => ast::AnyHasAttrs::new(id.clone()),
- })
- }
- GenericParamId::TypeParamId(id) => {
- id.parent().child_source(db).map(|source| match &source[id.local_id()] {
- Either::Left(ast::TypeOrConstParam::Type(id)) => {
- ast::AnyHasAttrs::new(id.clone())
- }
- Either::Left(ast::TypeOrConstParam::Const(id)) => {
- ast::AnyHasAttrs::new(id.clone())
- }
- Either::Right(id) => ast::AnyHasAttrs::new(id.clone()),
- })
- }
+ GenericParamId::ConstParamId(id) => id
+ .parent()
+ .child_source(db)
+ .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())),
+ GenericParamId::TypeParamId(id) => id
+ .parent()
+ .child_source(db)
+ .map(|source| ast::AnyHasAttrs::new(source[id.local_id()].clone())),
GenericParamId::LifetimeParamId(id) => id
.parent
.child_source(db)
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
index 8fd9255b8..b70e658ef 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -24,7 +24,9 @@ use syntax::{ast, AstPtr, SyntaxNode, SyntaxNodePtr};
use crate::{
attr::Attrs,
db::DefDatabase,
- expr::{dummy_expr_id, Expr, ExprId, Label, LabelId, Pat, PatId},
+ expr::{
+ dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId, RecordFieldPat,
+ },
item_scope::BuiltinShadowMode,
macro_id_to_def_id,
nameres::DefMap,
@@ -270,7 +272,7 @@ pub struct Mark {
pub struct Body {
pub exprs: Arena<Expr>,
pub pats: Arena<Pat>,
- pub or_pats: FxHashMap<PatId, Arc<[PatId]>>,
+ pub bindings: Arena<Binding>,
pub labels: Arena<Label>,
/// 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
@@ -409,18 +411,6 @@ impl Body {
.map(move |&block| (block, db.block_def_map(block).expect("block ID without DefMap")))
}
- pub fn pattern_representative(&self, pat: PatId) -> PatId {
- self.or_pats.get(&pat).and_then(|pats| pats.first().copied()).unwrap_or(pat)
- }
-
- /// Retrieves all ident patterns this pattern shares the ident with.
- pub fn ident_patterns_for<'slf>(&'slf self, pat: &'slf PatId) -> &'slf [PatId] {
- match self.or_pats.get(pat) {
- Some(pats) => pats,
- None => std::slice::from_ref(pat),
- }
- }
-
pub fn pretty_print(&self, db: &dyn DefDatabase, owner: DefWithBodyId) -> String {
pretty::print_body_hir(db, self, owner)
}
@@ -435,13 +425,52 @@ impl Body {
}
fn shrink_to_fit(&mut self) {
- let Self { _c: _, body_expr: _, block_scopes, or_pats, exprs, labels, params, pats } = self;
+ let Self { _c: _, body_expr: _, block_scopes, exprs, labels, params, pats, bindings } =
+ self;
block_scopes.shrink_to_fit();
- or_pats.shrink_to_fit();
exprs.shrink_to_fit();
labels.shrink_to_fit();
params.shrink_to_fit();
pats.shrink_to_fit();
+ bindings.shrink_to_fit();
+ }
+
+ pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
+ self.walk_pats(pat_id, &mut |pat| {
+ if let Pat::Bind { id, .. } = pat {
+ f(*id);
+ }
+ });
+ }
+
+ pub fn walk_pats(&self, pat_id: PatId, f: &mut impl FnMut(&Pat)) {
+ let pat = &self[pat_id];
+ f(pat);
+ match pat {
+ Pat::Range { .. }
+ | Pat::Lit(..)
+ | Pat::Path(..)
+ | Pat::ConstBlock(..)
+ | Pat::Wild
+ | Pat::Missing => {}
+ &Pat::Bind { subpat, .. } => {
+ if let Some(subpat) = subpat {
+ self.walk_pats(subpat, f);
+ }
+ }
+ Pat::Or(args) | Pat::Tuple { args, .. } | Pat::TupleStruct { args, .. } => {
+ args.iter().copied().for_each(|p| self.walk_pats(p, f));
+ }
+ Pat::Ref { pat, .. } => self.walk_pats(*pat, f),
+ Pat::Slice { prefix, slice, suffix } => {
+ let total_iter = prefix.iter().chain(slice.iter()).chain(suffix.iter());
+ total_iter.copied().for_each(|p| self.walk_pats(p, f));
+ }
+ Pat::Record { args, .. } => {
+ args.iter().for_each(|RecordFieldPat { pat, .. }| self.walk_pats(*pat, f));
+ }
+ Pat::Box { inner } => self.walk_pats(*inner, f),
+ }
}
}
@@ -451,7 +480,7 @@ impl Default for Body {
body_expr: dummy_expr_id(),
exprs: Default::default(),
pats: Default::default(),
- or_pats: Default::default(),
+ bindings: Default::default(),
labels: Default::default(),
params: Default::default(),
block_scopes: Default::default(),
@@ -484,6 +513,14 @@ impl Index<LabelId> for Body {
}
}
+impl Index<BindingId> for Body {
+ type Output = Binding;
+
+ fn index(&self, b: BindingId) -> &Binding {
+ &self.bindings[b]
+ }
+}
+
// FIXME: Change `node_` prefix to something more reasonable.
// Perhaps `expr_syntax` and `expr_id`?
impl BodySourceMap {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index 04b1c4f01..fedaf3955 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -15,6 +15,7 @@ use la_arena::Arena;
use once_cell::unsync::OnceCell;
use profile::Count;
use rustc_hash::FxHashMap;
+use smallvec::SmallVec;
use syntax::{
ast::{
self, ArrayExprKind, AstChildren, HasArgList, HasLoopBody, HasName, LiteralKind,
@@ -30,14 +31,14 @@ use crate::{
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
db::DefDatabase,
expr::{
- dummy_expr_id, Array, BindingAnnotation, ClosureKind, Expr, ExprId, FloatTypeWrapper,
- Label, LabelId, Literal, MatchArm, Movability, Pat, PatId, RecordFieldPat, RecordLitField,
- Statement,
+ dummy_expr_id, Array, Binding, BindingAnnotation, BindingId, ClosureKind, Expr, ExprId,
+ FloatTypeWrapper, Label, LabelId, Literal, MatchArm, Movability, Pat, PatId,
+ RecordFieldPat, RecordLitField, Statement,
},
item_scope::BuiltinShadowMode,
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
- AdtId, BlockLoc, ModuleDefId, UnresolvedMacro,
+ AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
};
pub struct LowerCtx<'a> {
@@ -87,16 +88,14 @@ pub(super) fn lower(
body: Body {
exprs: Arena::default(),
pats: Arena::default(),
+ bindings: Arena::default(),
labels: Arena::default(),
params: Vec::new(),
body_expr: dummy_expr_id(),
block_scopes: Vec::new(),
_c: Count::new(),
- or_pats: Default::default(),
},
expander,
- name_to_pat_grouping: Default::default(),
- is_lowering_inside_or_pat: false,
is_lowering_assignee_expr: false,
is_lowering_generator: false,
}
@@ -109,13 +108,26 @@ struct ExprCollector<'a> {
ast_id_map: Arc<AstIdMap>,
body: Body,
source_map: BodySourceMap,
- // a poor-mans union-find?
- name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>,
- is_lowering_inside_or_pat: bool,
is_lowering_assignee_expr: bool,
is_lowering_generator: bool,
}
+#[derive(Debug, Default)]
+struct BindingList {
+ map: FxHashMap<Name, BindingId>,
+}
+
+impl BindingList {
+ fn find(
+ &mut self,
+ ec: &mut ExprCollector<'_>,
+ name: Name,
+ mode: BindingAnnotation,
+ ) -> BindingId {
+ *self.map.entry(name).or_insert_with_key(|n| ec.alloc_binding(n.clone(), mode))
+ }
+}
+
impl ExprCollector<'_> {
fn collect(
mut self,
@@ -127,17 +139,16 @@ impl ExprCollector<'_> {
param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
{
let ptr = AstPtr::new(&self_param);
- let param_pat = self.alloc_pat(
- Pat::Bind {
- name: name![self],
- mode: BindingAnnotation::new(
- self_param.mut_token().is_some() && self_param.amp_token().is_none(),
- false,
- ),
- subpat: None,
- },
- Either::Right(ptr),
+ let binding_id = self.alloc_binding(
+ name![self],
+ BindingAnnotation::new(
+ self_param.mut_token().is_some() && self_param.amp_token().is_none(),
+ false,
+ ),
);
+ let param_pat =
+ self.alloc_pat(Pat::Bind { id: binding_id, subpat: None }, Either::Right(ptr));
+ self.add_definition_to_binding(binding_id, param_pat);
self.body.params.push(param_pat);
}
@@ -179,6 +190,9 @@ impl ExprCollector<'_> {
id
}
+ fn alloc_binding(&mut self, name: Name, mode: BindingAnnotation) -> BindingId {
+ self.body.bindings.alloc(Binding { name, mode, definitions: SmallVec::new() })
+ }
fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
let src = self.expander.to_source(ptr);
let id = self.make_pat(pat, src.clone());
@@ -238,33 +252,32 @@ impl ExprCollector<'_> {
}
ast::Expr::BlockExpr(e) => match e.modifier() {
Some(ast::BlockModifier::Try(_)) => {
- let body = self.collect_block(e);
- self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
+ self.collect_block_(e, |id, statements, tail| Expr::TryBlock {
+ id,
+ statements,
+ tail,
+ })
}
Some(ast::BlockModifier::Unsafe(_)) => {
- let body = self.collect_block(e);
- self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
+ self.collect_block_(e, |id, statements, tail| Expr::Unsafe {
+ id,
+ statements,
+ tail,
+ })
}
- // FIXME: we need to record these effects somewhere...
Some(ast::BlockModifier::Label(label)) => {
let label = self.collect_label(label);
- let res = self.collect_block(e);
- match &mut self.body.exprs[res] {
- Expr::Block { label: block_label, .. } => {
- *block_label = Some(label);
- }
- _ => unreachable!(),
- }
- res
- }
- Some(ast::BlockModifier::Async(_)) => {
- let body = self.collect_block(e);
- self.alloc_expr(Expr::Async { body }, syntax_ptr)
- }
- Some(ast::BlockModifier::Const(_)) => {
- let body = self.collect_block(e);
- self.alloc_expr(Expr::Const { body }, syntax_ptr)
+ self.collect_block_(e, |id, statements, tail| Expr::Block {
+ id,
+ statements,
+ tail,
+ label: Some(label),
+ })
}
+ Some(ast::BlockModifier::Async(_)) => self
+ .collect_block_(e, |id, statements, tail| Expr::Async { id, statements, tail }),
+ Some(ast::BlockModifier::Const(_)) => self
+ .collect_block_(e, |id, statements, tail| Expr::Const { id, statements, tail }),
None => self.collect_block(e),
},
ast::Expr::LoopExpr(e) => {
@@ -486,6 +499,8 @@ impl ExprCollector<'_> {
Movability::Movable
};
ClosureKind::Generator(movability)
+ } else if e.async_token().is_some() {
+ ClosureKind::Async
} else {
ClosureKind::Closure
};
@@ -737,6 +752,19 @@ impl ExprCollector<'_> {
}
fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
+ self.collect_block_(block, |id, statements, tail| Expr::Block {
+ id,
+ statements,
+ tail,
+ label: None,
+ })
+ }
+
+ fn collect_block_(
+ &mut self,
+ block: ast::BlockExpr,
+ mk_block: impl FnOnce(BlockId, Box<[Statement]>, Option<ExprId>) -> Expr,
+ ) -> ExprId {
let file_local_id = self.ast_id_map.ast_id(&block);
let ast_id = AstId::new(self.expander.current_file_id, file_local_id);
let block_loc =
@@ -769,15 +797,8 @@ impl ExprCollector<'_> {
});
let syntax_node_ptr = AstPtr::new(&block.into());
- let expr_id = self.alloc_expr(
- Expr::Block {
- id: block_id,
- statements: statements.into_boxed_slice(),
- tail,
- label: None,
- },
- syntax_node_ptr,
- );
+ let expr_id = self
+ .alloc_expr(mk_block(block_id, statements.into_boxed_slice(), tail), syntax_node_ptr);
self.expander.def_map = prev_def_map;
self.expander.module = prev_local_module;
@@ -799,13 +820,7 @@ impl ExprCollector<'_> {
}
fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
- let pat_id = self.collect_pat_(pat);
- for (_, pats) in self.name_to_pat_grouping.drain() {
- let pats = Arc::<[_]>::from(pats);
- self.body.or_pats.extend(pats.iter().map(|&pat| (pat, pats.clone())));
- }
- self.is_lowering_inside_or_pat = false;
- pat_id
+ self.collect_pat_(pat, &mut BindingList::default())
}
fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId {
@@ -815,16 +830,18 @@ impl ExprCollector<'_> {
}
}
- fn collect_pat_(&mut self, pat: ast::Pat) -> PatId {
+ fn collect_pat_(&mut self, pat: ast::Pat, binding_list: &mut BindingList) -> PatId {
let pattern = match &pat {
ast::Pat::IdentPat(bp) => {
let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
- let key = self.is_lowering_inside_or_pat.then(|| name.clone());
let annotation =
BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
- let subpat = bp.pat().map(|subpat| self.collect_pat_(subpat));
- let pattern = if annotation == BindingAnnotation::Unannotated && subpat.is_none() {
+ let subpat = bp.pat().map(|subpat| self.collect_pat_(subpat, binding_list));
+
+ let is_simple_ident_pat =
+ annotation == BindingAnnotation::Unannotated && subpat.is_none();
+ let (binding, pattern) = if is_simple_ident_pat {
// This could also be a single-segment path pattern. To
// decide that, we need to try resolving the name.
let (resolved, _) = self.expander.def_map.resolve_path(
@@ -834,12 +851,12 @@ impl ExprCollector<'_> {
BuiltinShadowMode::Other,
);
match resolved.take_values() {
- Some(ModuleDefId::ConstId(_)) => Pat::Path(name.into()),
+ Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
Some(ModuleDefId::EnumVariantId(_)) => {
// this is only really valid for unit variants, but
// shadowing other enum variants with a pattern is
// an error anyway
- Pat::Path(name.into())
+ (None, Pat::Path(name.into()))
}
Some(ModuleDefId::AdtId(AdtId::StructId(s)))
if self.db.struct_data(s).variant_data.kind() != StructKind::Record =>
@@ -847,30 +864,34 @@ impl ExprCollector<'_> {
// Funnily enough, record structs *can* be shadowed
// by pattern bindings (but unit or tuple structs
// can't).
- Pat::Path(name.into())
+ (None, Pat::Path(name.into()))
}
// shadowing statics is an error as well, so we just ignore that case here
- _ => Pat::Bind { name, mode: annotation, subpat },
+ _ => {
+ let id = binding_list.find(self, name, annotation);
+ (Some(id), Pat::Bind { id, subpat })
+ }
}
} else {
- Pat::Bind { name, mode: annotation, subpat }
+ let id = binding_list.find(self, name, annotation);
+ (Some(id), Pat::Bind { id, subpat })
};
let ptr = AstPtr::new(&pat);
let pat = self.alloc_pat(pattern, Either::Left(ptr));
- if let Some(key) = key {
- self.name_to_pat_grouping.entry(key).or_default().push(pat);
+ if let Some(binding_id) = binding {
+ self.add_definition_to_binding(binding_id, pat);
}
return pat;
}
ast::Pat::TupleStructPat(p) => {
let path =
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
- let (args, ellipsis) = self.collect_tuple_pat(p.fields());
+ let (args, ellipsis) = self.collect_tuple_pat(p.fields(), binding_list);
Pat::TupleStruct { path, args, ellipsis }
}
ast::Pat::RefPat(p) => {
- let pat = self.collect_pat_opt(p.pat());
+ let pat = self.collect_pat_opt_(p.pat(), binding_list);
let mutability = Mutability::from_mutable(p.mut_token().is_some());
Pat::Ref { pat, mutability }
}
@@ -880,13 +901,12 @@ impl ExprCollector<'_> {
path.map(Pat::Path).unwrap_or(Pat::Missing)
}
ast::Pat::OrPat(p) => {
- self.is_lowering_inside_or_pat = true;
- let pats = p.pats().map(|p| self.collect_pat_(p)).collect();
+ let pats = p.pats().map(|p| self.collect_pat_(p, binding_list)).collect();
Pat::Or(pats)
}
- ast::Pat::ParenPat(p) => return self.collect_pat_opt_(p.pat()),
+ ast::Pat::ParenPat(p) => return self.collect_pat_opt_(p.pat(), binding_list),
ast::Pat::TuplePat(p) => {
- let (args, ellipsis) = self.collect_tuple_pat(p.fields());
+ let (args, ellipsis) = self.collect_tuple_pat(p.fields(), binding_list);
Pat::Tuple { args, ellipsis }
}
ast::Pat::WildcardPat(_) => Pat::Wild,
@@ -899,7 +919,7 @@ impl ExprCollector<'_> {
.fields()
.filter_map(|f| {
let ast_pat = f.pat()?;
- let pat = self.collect_pat_(ast_pat);
+ let pat = self.collect_pat_(ast_pat, binding_list);
let name = f.field_name()?.as_name();
Some(RecordFieldPat { name, pat })
})
@@ -918,9 +938,15 @@ impl ExprCollector<'_> {
// FIXME properly handle `RestPat`
Pat::Slice {
- prefix: prefix.into_iter().map(|p| self.collect_pat_(p)).collect(),
- slice: slice.map(|p| self.collect_pat_(p)),
- suffix: suffix.into_iter().map(|p| self.collect_pat_(p)).collect(),
+ prefix: prefix
+ .into_iter()
+ .map(|p| self.collect_pat_(p, binding_list))
+ .collect(),
+ slice: slice.map(|p| self.collect_pat_(p, binding_list)),
+ suffix: suffix
+ .into_iter()
+ .map(|p| self.collect_pat_(p, binding_list))
+ .collect(),
}
}
ast::Pat::LiteralPat(lit) => {
@@ -943,7 +969,7 @@ impl ExprCollector<'_> {
Pat::Missing
}
ast::Pat::BoxPat(boxpat) => {
- let inner = self.collect_pat_opt_(boxpat.pat());
+ let inner = self.collect_pat_opt_(boxpat.pat(), binding_list);
Pat::Box { inner }
}
ast::Pat::ConstBlockPat(const_block_pat) => {
@@ -960,7 +986,7 @@ impl ExprCollector<'_> {
let src = self.expander.to_source(Either::Left(AstPtr::new(&pat)));
let pat =
self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
- this.collect_pat_opt_(expanded_pat)
+ this.collect_pat_opt_(expanded_pat, binding_list)
});
self.source_map.pat_map.insert(src, pat);
return pat;
@@ -974,21 +1000,25 @@ impl ExprCollector<'_> {
self.alloc_pat(pattern, Either::Left(ptr))
}
- fn collect_pat_opt_(&mut self, pat: Option<ast::Pat>) -> PatId {
+ fn collect_pat_opt_(&mut self, pat: Option<ast::Pat>, binding_list: &mut BindingList) -> PatId {
match pat {
- Some(pat) => self.collect_pat_(pat),
+ Some(pat) => self.collect_pat_(pat, binding_list),
None => self.missing_pat(),
}
}
- fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Box<[PatId]>, Option<usize>) {
+ fn collect_tuple_pat(
+ &mut self,
+ args: AstChildren<ast::Pat>,
+ binding_list: &mut BindingList,
+ ) -> (Box<[PatId]>, Option<usize>) {
// Find the location of the `..`, if there is one. Note that we do not
// consider the possibility of there being multiple `..` here.
let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_)));
// We want to skip the `..` pattern here, since we account for it above.
let args = args
.filter(|p| !matches!(p, ast::Pat::RestPat(_)))
- .map(|p| self.collect_pat_(p))
+ .map(|p| self.collect_pat_(p, binding_list))
.collect();
(args, ellipsis)
@@ -1017,6 +1047,10 @@ impl ExprCollector<'_> {
None => Some(()),
}
}
+
+ fn add_definition_to_binding(&mut self, binding_id: BindingId, pat_id: PatId) {
+ self.body.bindings[binding_id].definitions.push(pat_id);
+ }
}
impl From<ast::LiteralKind> for Literal {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
index 4b4664a1c..5a9b825a2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
@@ -5,7 +5,7 @@ use std::fmt::{self, Write};
use syntax::ast::HasName;
use crate::{
- expr::{Array, BindingAnnotation, ClosureKind, Literal, Movability, Statement},
+ expr::{Array, BindingAnnotation, BindingId, ClosureKind, Literal, Movability, Statement},
pretty::{print_generic_args, print_path, print_type_ref},
type_ref::TypeRef,
};
@@ -292,18 +292,6 @@ impl<'a> Printer<'a> {
self.print_expr(*expr);
w!(self, "?");
}
- Expr::TryBlock { body } => {
- w!(self, "try ");
- self.print_expr(*body);
- }
- Expr::Async { body } => {
- w!(self, "async ");
- self.print_expr(*body);
- }
- Expr::Const { body } => {
- w!(self, "const ");
- self.print_expr(*body);
- }
Expr::Cast { expr, type_ref } => {
self.print_expr(*expr);
w!(self, " as ");
@@ -372,8 +360,14 @@ impl<'a> Printer<'a> {
w!(self, "]");
}
Expr::Closure { args, arg_types, ret_type, body, closure_kind } => {
- if let ClosureKind::Generator(Movability::Static) = closure_kind {
- w!(self, "static ");
+ match closure_kind {
+ ClosureKind::Generator(Movability::Static) => {
+ w!(self, "static ");
+ }
+ ClosureKind::Async => {
+ w!(self, "async ");
+ }
+ _ => (),
}
w!(self, "|");
for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() {
@@ -402,10 +396,6 @@ impl<'a> Printer<'a> {
}
w!(self, ")");
}
- Expr::Unsafe { body } => {
- w!(self, "unsafe ");
- self.print_expr(*body);
- }
Expr::Array(arr) => {
w!(self, "[");
if !matches!(arr, Array::ElementList { elements, .. } if elements.is_empty()) {
@@ -428,25 +418,47 @@ impl<'a> Printer<'a> {
}
Expr::Literal(lit) => self.print_literal(lit),
Expr::Block { id: _, statements, tail, label } => {
- self.whitespace();
- if let Some(lbl) = label {
- w!(self, "{}: ", self.body[*lbl].name);
+ let label = label.map(|lbl| format!("{}: ", self.body[lbl].name));
+ self.print_block(label.as_deref(), statements, tail);
+ }
+ Expr::Unsafe { id: _, statements, tail } => {
+ self.print_block(Some("unsafe "), statements, tail);
+ }
+ Expr::TryBlock { id: _, statements, tail } => {
+ self.print_block(Some("try "), statements, tail);
+ }
+ Expr::Async { id: _, statements, tail } => {
+ self.print_block(Some("async "), statements, tail);
+ }
+ Expr::Const { id: _, statements, tail } => {
+ self.print_block(Some("const "), statements, tail);
+ }
+ }
+ }
+
+ fn print_block(
+ &mut self,
+ label: Option<&str>,
+ statements: &Box<[Statement]>,
+ tail: &Option<la_arena::Idx<Expr>>,
+ ) {
+ self.whitespace();
+ if let Some(lbl) = label {
+ w!(self, "{}", lbl);
+ }
+ w!(self, "{{");
+ if !statements.is_empty() || tail.is_some() {
+ self.indented(|p| {
+ for stmt in &**statements {
+ p.print_stmt(stmt);
}
- w!(self, "{{");
- if !statements.is_empty() || tail.is_some() {
- self.indented(|p| {
- for stmt in &**statements {
- p.print_stmt(stmt);
- }
- if let Some(tail) = tail {
- p.print_expr(*tail);
- }
- p.newline();
- });
+ if let Some(tail) = tail {
+ p.print_expr(*tail);
}
- w!(self, "}}");
- }
+ p.newline();
+ });
}
+ w!(self, "}}");
}
fn print_pat(&mut self, pat: PatId) {
@@ -518,14 +530,8 @@ impl<'a> Printer<'a> {
}
Pat::Path(path) => self.print_path(path),
Pat::Lit(expr) => self.print_expr(*expr),
- Pat::Bind { mode, name, subpat } => {
- let mode = match mode {
- BindingAnnotation::Unannotated => "",
- BindingAnnotation::Mutable => "mut ",
- BindingAnnotation::Ref => "ref ",
- BindingAnnotation::RefMut => "ref mut ",
- };
- w!(self, "{}{}", mode, name);
+ Pat::Bind { id, subpat } => {
+ self.print_binding(*id);
if let Some(pat) = subpat {
self.whitespace();
self.print_pat(*pat);
@@ -629,4 +635,15 @@ impl<'a> Printer<'a> {
fn print_path(&mut self, path: &Path) {
print_path(path, self).unwrap();
}
+
+ fn print_binding(&mut self, id: BindingId) {
+ let Binding { name, mode, .. } = &self.body.bindings[id];
+ let mode = match mode {
+ BindingAnnotation::Unannotated => "",
+ BindingAnnotation::Mutable => "mut ",
+ BindingAnnotation::Ref => "ref ",
+ BindingAnnotation::RefMut => "ref mut ",
+ };
+ w!(self, "{}{}", mode, name);
+ }
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs
index 2617d4288..12fc1f116 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
use crate::{
body::Body,
db::DefDatabase,
- expr::{Expr, ExprId, LabelId, Pat, PatId, Statement},
+ expr::{Binding, BindingId, Expr, ExprId, LabelId, Pat, PatId, Statement},
BlockId, DefWithBodyId,
};
@@ -23,7 +23,7 @@ pub struct ExprScopes {
#[derive(Debug, PartialEq, Eq)]
pub struct ScopeEntry {
name: Name,
- pat: PatId,
+ binding: BindingId,
}
impl ScopeEntry {
@@ -31,8 +31,8 @@ impl ScopeEntry {
&self.name
}
- pub fn pat(&self) -> PatId {
- self.pat
+ pub fn binding(&self) -> BindingId {
+ self.binding
}
}
@@ -66,6 +66,7 @@ impl ExprScopes {
self.scopes[scope].label.clone()
}
+ /// Returns the scopes in ascending order.
pub fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ {
std::iter::successors(scope, move |&scope| self.scopes[scope].parent)
}
@@ -125,18 +126,23 @@ impl ExprScopes {
})
}
- fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
+ fn add_bindings(&mut self, body: &Body, scope: ScopeId, binding: BindingId) {
+ let Binding { name, .. } = &body.bindings[binding];
+ let entry = ScopeEntry { name: name.clone(), binding };
+ self.scopes[scope].entries.push(entry);
+ }
+
+ fn add_pat_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
let pattern = &body[pat];
- if let Pat::Bind { name, .. } = pattern {
- let entry = ScopeEntry { name: name.clone(), pat };
- self.scopes[scope].entries.push(entry);
+ if let Pat::Bind { id, .. } = pattern {
+ self.add_bindings(body, scope, *id);
}
- pattern.walk_child_pats(|pat| self.add_bindings(body, scope, pat));
+ pattern.walk_child_pats(|pat| self.add_pat_bindings(body, scope, pat));
}
fn add_params_bindings(&mut self, body: &Body, scope: ScopeId, params: &[PatId]) {
- params.iter().for_each(|pat| self.add_bindings(body, scope, *pat));
+ params.iter().for_each(|pat| self.add_pat_bindings(body, scope, *pat));
}
fn set_scope(&mut self, node: ExprId, scope: ScopeId) {
@@ -169,7 +175,7 @@ fn compute_block_scopes(
}
*scope = scopes.new_scope(*scope);
- scopes.add_bindings(body, *scope, *pat);
+ scopes.add_pat_bindings(body, *scope, *pat);
}
Statement::Expr { expr, .. } => {
compute_expr_scopes(*expr, body, scopes, scope);
@@ -194,10 +200,20 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
scopes.set_scope(expr, scope);
compute_block_scopes(statements, *tail, body, scopes, &mut scope);
}
+ Expr::Unsafe { id, statements, tail }
+ | Expr::Async { id, statements, tail }
+ | Expr::Const { id, statements, tail }
+ | Expr::TryBlock { id, statements, tail } => {
+ let mut scope = scopes.new_block_scope(*scope, *id, None);
+ // 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);
+ }
Expr::For { iterable, pat, body: body_expr, label } => {
compute_expr_scopes(*iterable, body, scopes, scope);
let mut scope = scopes.new_labeled_scope(*scope, make_label(label));
- scopes.add_bindings(body, scope, *pat);
+ scopes.add_pat_bindings(body, scope, *pat);
compute_expr_scopes(*body_expr, body, scopes, &mut scope);
}
Expr::While { condition, body: body_expr, label } => {
@@ -218,7 +234,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
compute_expr_scopes(*expr, body, scopes, scope);
for arm in arms.iter() {
let mut scope = scopes.new_scope(*scope);
- scopes.add_bindings(body, scope, arm.pat);
+ scopes.add_pat_bindings(body, scope, arm.pat);
if let Some(guard) = arm.guard {
scope = scopes.new_scope(scope);
compute_expr_scopes(guard, body, scopes, &mut scope);
@@ -237,7 +253,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
&Expr::Let { pat, expr } => {
compute_expr_scopes(expr, body, scopes, scope);
*scope = scopes.new_scope(*scope);
- scopes.add_bindings(body, *scope, pat);
+ scopes.add_pat_bindings(body, *scope, pat);
}
e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)),
};
@@ -439,7 +455,7 @@ fn foo() {
let function = find_function(&db, file_id);
let scopes = db.expr_scopes(function.into());
- let (_body, source_map) = db.body_with_source_map(function.into());
+ let (body, source_map) = db.body_with_source_map(function.into());
let expr_scope = {
let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap();
@@ -449,7 +465,9 @@ fn foo() {
};
let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap();
- let pat_src = source_map.pat_syntax(resolved.pat()).unwrap();
+ let pat_src = source_map
+ .pat_syntax(*body.bindings[resolved.binding()].definitions.first().unwrap())
+ .unwrap();
let local_name = pat_src.value.either(
|it| it.syntax_node_ptr().to_node(file.syntax()),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
index 3bba08cfc..77ac221e5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
@@ -395,3 +395,25 @@ fn foo() {
"#]],
)
}
+
+#[test]
+fn trailing_expr_macro_expands_stmts() {
+ check_at(
+ r#"
+macro_rules! foo {
+ () => { const FOO: u32 = 0;const BAR: u32 = 0; };
+}
+fn f() {$0
+ foo!{}
+};
+ "#,
+ expect![[r#"
+ block scope
+ BAR: v
+ FOO: v
+
+ crate
+ f: v
+ "#]],
+ )
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs b/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs
index 19d2fe956..68b57acca 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs
@@ -1,7 +1,7 @@
//! When *constructing* `hir`, we start at some parent syntax node and recursively
//! lower the children.
//!
-//! This modules allows one to go in the opposite direction: start with a syntax
+//! This module allows one to go in the opposite direction: start with a syntax
//! node for a *child*, and get its hir.
use either::Either;
@@ -145,6 +145,7 @@ impl ChildBySource for ItemScope {
ModuleDefId::StaticId(id) => insert!(map[keys::STATIC].insert(id)),
ModuleDefId::TypeAliasId(id) => insert!(map[keys::TYPE_ALIAS].insert(id)),
ModuleDefId::TraitId(id) => insert!(map[keys::TRAIT].insert(id)),
+ ModuleDefId::TraitAliasId(id) => insert!(map[keys::TRAIT_ALIAS].insert(id)),
ModuleDefId::AdtId(adt) => match adt {
AdtId::StructId(id) => insert!(map[keys::STRUCT].insert(id)),
AdtId::UnionId(id) => insert!(map[keys::UNION].insert(id)),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index c3c1dfd39..1633a33be 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -22,7 +22,7 @@ use crate::{
visibility::RawVisibility,
AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
Intern, ItemContainerId, ItemLoc, Lookup, Macro2Id, MacroRulesId, ModuleId, ProcMacroId,
- StaticId, TraitId, TypeAliasId, TypeAliasLoc,
+ StaticId, TraitAliasId, TraitId, TypeAliasId, TypeAliasLoc,
};
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -35,6 +35,7 @@ pub struct FunctionData {
pub visibility: RawVisibility,
pub abi: Option<Interned<str>>,
pub legacy_const_generics_indices: Box<[u32]>,
+ pub rustc_allow_incoherent_impl: bool,
flags: FnFlags,
}
@@ -84,13 +85,14 @@ impl FunctionData {
}
}
- let legacy_const_generics_indices = item_tree
- .attrs(db, krate, ModItem::from(loc.id.value).into())
+ let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
+ let legacy_const_generics_indices = attrs
.by_key("rustc_legacy_const_generics")
.tt_values()
.next()
.map(parse_rustc_legacy_const_generics)
.unwrap_or_default();
+ let rustc_allow_incoherent_impl = attrs.by_key("rustc_allow_incoherent_impl").exists();
Arc::new(FunctionData {
name: func.name.clone(),
@@ -108,6 +110,7 @@ impl FunctionData {
abi: func.abi.clone(),
legacy_const_generics_indices,
flags,
+ rustc_allow_incoherent_impl,
})
}
@@ -171,6 +174,7 @@ pub struct TypeAliasData {
pub visibility: RawVisibility,
pub is_extern: bool,
pub rustc_has_incoherent_inherent_impls: bool,
+ pub rustc_allow_incoherent_impl: bool,
/// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
pub bounds: Vec<Interned<TypeBound>>,
}
@@ -189,10 +193,14 @@ impl TypeAliasData {
item_tree[typ.visibility].clone()
};
- let rustc_has_incoherent_inherent_impls = item_tree
- .attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into())
- .by_key("rustc_has_incoherent_inherent_impls")
- .exists();
+ let attrs = item_tree.attrs(
+ db,
+ loc.container.module(db).krate(),
+ ModItem::from(loc.id.value).into(),
+ );
+ let rustc_has_incoherent_inherent_impls =
+ attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
+ let rustc_allow_incoherent_impl = attrs.by_key("rustc_allow_incoherent_impl").exists();
Arc::new(TypeAliasData {
name: typ.name.clone(),
@@ -200,6 +208,7 @@ impl TypeAliasData {
visibility,
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
rustc_has_incoherent_inherent_impls,
+ rustc_allow_incoherent_impl,
bounds: typ.bounds.to_vec(),
})
}
@@ -212,11 +221,12 @@ pub struct TraitData {
pub is_auto: bool,
pub is_unsafe: bool,
pub rustc_has_incoherent_inherent_impls: bool,
+ pub skip_array_during_method_dispatch: bool,
+ pub fundamental: bool,
pub visibility: RawVisibility,
/// Whether the trait has `#[rust_skip_array_during_method_dispatch]`. `hir_ty` will ignore
/// method calls to this trait's methods when the receiver is an array and the crate edition is
/// 2015 or 2018.
- pub skip_array_during_method_dispatch: bool,
// box it as the vec is usually empty anyways
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
}
@@ -245,19 +255,12 @@ impl TraitData {
attrs.by_key("rustc_skip_array_during_method_dispatch").exists();
let rustc_has_incoherent_inherent_impls =
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
- let (items, attribute_calls, diagnostics) = match &tr_def.items {
- Some(items) => {
- let mut collector = AssocItemCollector::new(
- db,
- module_id,
- tree_id.file_id(),
- ItemContainerId::TraitId(tr),
- );
- collector.collect(&item_tree, tree_id.tree_id(), items);
- collector.finish()
- }
- None => Default::default(),
- };
+ let fundamental = attrs.by_key("fundamental").exists();
+ let mut collector =
+ AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
+ collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
+ let (items, attribute_calls, diagnostics) = collector.finish();
+
(
Arc::new(TraitData {
name,
@@ -268,6 +271,7 @@ impl TraitData {
visibility,
skip_array_during_method_dispatch,
rustc_has_incoherent_inherent_impls,
+ fundamental,
}),
diagnostics.into(),
)
@@ -300,6 +304,23 @@ impl TraitData {
}
#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct TraitAliasData {
+ pub name: Name,
+ pub visibility: RawVisibility,
+}
+
+impl TraitAliasData {
+ pub(crate) fn trait_alias_query(db: &dyn DefDatabase, id: TraitAliasId) -> Arc<TraitAliasData> {
+ let loc = id.lookup(db);
+ let item_tree = loc.id.item_tree(db);
+ let alias = &item_tree[loc.id.value];
+ let visibility = item_tree[alias.visibility].clone();
+
+ Arc::new(TraitAliasData { name: alias.name.clone(), visibility })
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplData {
pub target_trait: Option<Interned<TraitRef>>,
pub self_ty: Interned<TypeRef>,
@@ -441,6 +462,7 @@ pub struct ConstData {
pub name: Option<Name>,
pub type_ref: Interned<TypeRef>,
pub visibility: RawVisibility,
+ pub rustc_allow_incoherent_impl: bool,
}
impl ConstData {
@@ -454,10 +476,16 @@ impl ConstData {
item_tree[konst.visibility].clone()
};
+ let rustc_allow_incoherent_impl = item_tree
+ .attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into())
+ .by_key("rustc_allow_incoherent_impl")
+ .exists();
+
Arc::new(ConstData {
name: konst.name.clone(),
type_ref: konst.type_ref.clone(),
visibility,
+ rustc_allow_incoherent_impl,
})
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index b23427a73..9371fc14d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
use base_db::{salsa, CrateId, SourceDatabase, Upcast};
use either::Either;
-use hir_expand::{db::AstDatabase, HirFileId};
+use hir_expand::{db::ExpandDatabase, HirFileId};
use intern::Interned;
use la_arena::ArenaMap;
use syntax::{ast, AstPtr};
@@ -14,7 +14,7 @@ use crate::{
body::{scope::ExprScopes, Body, BodySourceMap},
data::{
ConstData, FunctionData, ImplData, Macro2Data, MacroRulesData, ProcMacroData, StaticData,
- TraitData, TypeAliasData,
+ TraitAliasData, TraitData, TypeAliasData,
},
generics::GenericParams,
import_map::ImportMap,
@@ -25,8 +25,8 @@ use crate::{
AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId,
ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId,
LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, ProcMacroId, ProcMacroLoc,
- StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc,
- UnionId, UnionLoc, VariantId,
+ StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc,
+ TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId,
};
#[salsa::query_group(InternDatabaseStorage)]
@@ -46,6 +46,8 @@ pub trait InternDatabase: SourceDatabase {
#[salsa::interned]
fn intern_trait(&self, loc: TraitLoc) -> TraitId;
#[salsa::interned]
+ fn intern_trait_alias(&self, loc: TraitAliasLoc) -> TraitAliasId;
+ #[salsa::interned]
fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId;
#[salsa::interned]
fn intern_impl(&self, loc: ImplLoc) -> ImplId;
@@ -62,7 +64,7 @@ pub trait InternDatabase: SourceDatabase {
}
#[salsa::query_group(DefDatabaseStorage)]
-pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
+pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDatabase> {
#[salsa::input]
fn enable_proc_attr_macros(&self) -> bool;
@@ -125,6 +127,9 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
#[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, Arc<[DefDiagnostic]>);
+ #[salsa::invoke(TraitAliasData::trait_alias_query)]
+ fn trait_alias_data(&self, e: TraitAliasId) -> Arc<TraitAliasData>;
+
#[salsa::invoke(TypeAliasData::type_alias_data_query)]
fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr.rs
index 48028b7c6..19fa6b254 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr.rs
@@ -17,6 +17,7 @@ use std::fmt;
use hir_expand::name::Name;
use intern::Interned;
use la_arena::{Idx, RawIdx};
+use smallvec::SmallVec;
use crate::{
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
@@ -29,6 +30,8 @@ pub use syntax::ast::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, Unar
pub type ExprId = Idx<Expr>;
+pub type BindingId = Idx<Binding>;
+
/// FIXME: this is a hacky function which should be removed
pub(crate) fn dummy_expr_id() -> ExprId {
ExprId::from_raw(RawIdx::from(u32::MAX))
@@ -52,13 +55,21 @@ pub type LabelId = Idx<Label>;
// We convert float values into bits and that's how we don't need to deal with f32 and f64.
// For PartialEq, bits comparison should work, as ordering is not important
// https://github.com/rust-lang/rust-analyzer/issues/12380#issuecomment-1137284360
-#[derive(Default, Debug, Clone, Eq, PartialEq)]
+#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
pub struct FloatTypeWrapper(u64);
impl FloatTypeWrapper {
pub fn new(value: f64) -> Self {
Self(value.to_bits())
}
+
+ pub fn into_f64(self) -> f64 {
+ f64::from_bits(self.0)
+ }
+
+ pub fn into_f32(self) -> f32 {
+ f64::from_bits(self.0) as f32
+ }
}
impl fmt::Display for FloatTypeWrapper {
@@ -101,6 +112,26 @@ pub enum Expr {
tail: Option<ExprId>,
label: Option<LabelId>,
},
+ TryBlock {
+ id: BlockId,
+ statements: Box<[Statement]>,
+ tail: Option<ExprId>,
+ },
+ Async {
+ id: BlockId,
+ statements: Box<[Statement]>,
+ tail: Option<ExprId>,
+ },
+ Const {
+ id: BlockId,
+ statements: Box<[Statement]>,
+ tail: Option<ExprId>,
+ },
+ Unsafe {
+ id: BlockId,
+ statements: Box<[Statement]>,
+ tail: Option<ExprId>,
+ },
Loop {
body: ExprId,
label: Option<LabelId>,
@@ -164,15 +195,6 @@ pub enum Expr {
Try {
expr: ExprId,
},
- TryBlock {
- body: ExprId,
- },
- Async {
- body: ExprId,
- },
- Const {
- body: ExprId,
- },
Cast {
expr: ExprId,
type_ref: Interned<TypeRef>,
@@ -214,9 +236,6 @@ pub enum Expr {
exprs: Box<[ExprId]>,
is_assignee_expr: bool,
},
- Unsafe {
- body: ExprId,
- },
Array(Array),
Literal(Literal),
Underscore,
@@ -226,6 +245,7 @@ pub enum Expr {
pub enum ClosureKind {
Closure,
Generator(Movability),
+ Async,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -282,13 +302,20 @@ impl Expr {
Expr::Let { expr, .. } => {
f(*expr);
}
- Expr::Block { statements, tail, .. } => {
+ Expr::Block { statements, tail, .. }
+ | Expr::TryBlock { statements, tail, .. }
+ | Expr::Unsafe { statements, tail, .. }
+ | Expr::Async { statements, tail, .. }
+ | Expr::Const { statements, tail, .. } => {
for stmt in statements.iter() {
match stmt {
- Statement::Let { initializer, .. } => {
+ Statement::Let { initializer, else_branch, .. } => {
if let &Some(expr) = initializer {
f(expr);
}
+ if let &Some(expr) = else_branch {
+ f(expr);
+ }
}
Statement::Expr { expr: expression, .. } => f(*expression),
}
@@ -297,10 +324,6 @@ impl Expr {
f(expr);
}
}
- Expr::TryBlock { body }
- | Expr::Unsafe { body }
- | Expr::Async { body }
- | Expr::Const { body } => f(*body),
Expr::Loop { body, .. } => f(*body),
Expr::While { condition, body, .. } => {
f(*condition);
@@ -415,6 +438,13 @@ impl BindingAnnotation {
}
#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Binding {
+ pub name: Name,
+ pub mode: BindingAnnotation,
+ pub definitions: SmallVec<[PatId; 1]>,
+}
+
+#[derive(Debug, Clone, Eq, PartialEq)]
pub struct RecordFieldPat {
pub name: Name,
pub pat: PatId,
@@ -432,7 +462,7 @@ pub enum Pat {
Slice { prefix: Box<[PatId]>, slice: Option<PatId>, suffix: Box<[PatId]> },
Path(Box<Path>),
Lit(ExprId),
- Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
+ Bind { id: BindingId, subpat: Option<PatId> },
TupleStruct { path: Option<Box<Path>>, args: Box<[PatId]>, ellipsis: Option<usize> },
Ref { pat: PatId, mutability: Mutability },
Box { inner: PatId },
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
index b2ab0c30e..e4912fa8a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -187,6 +187,7 @@ impl GenericParams {
GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id),
GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id),
GenericDefId::TraitId(id) => id_to_generics!(id),
+ GenericDefId::TraitAliasId(id) => id_to_generics!(id),
GenericDefId::TypeAliasId(id) => id_to_generics!(id),
GenericDefId::ImplId(id) => id_to_generics!(id),
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
@@ -207,12 +208,10 @@ impl GenericParams {
pub(crate) fn fill_bounds(
&mut self,
lower_ctx: &LowerCtx<'_>,
- node: &dyn ast::HasTypeBounds,
+ type_bounds: Option<ast::TypeBoundList>,
target: Either<TypeRef, LifetimeRef>,
) {
- for bound in
- node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
- {
+ for bound in type_bounds.iter().flat_map(|type_bound_list| type_bound_list.bounds()) {
self.add_where_predicate_from_bound(lower_ctx, bound, None, target.clone());
}
}
@@ -233,7 +232,11 @@ impl GenericParams {
};
self.type_or_consts.alloc(param.into());
let type_ref = TypeRef::Path(name.into());
- self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
+ self.fill_bounds(
+ lower_ctx,
+ type_param.type_bound_list(),
+ Either::Left(type_ref),
+ );
}
ast::TypeOrConstParam::Const(const_param) => {
let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
@@ -255,7 +258,11 @@ impl GenericParams {
let param = LifetimeParamData { name: name.clone() };
self.lifetimes.alloc(param);
let lifetime_ref = LifetimeRef::new_name(name);
- self.fill_bounds(lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
+ self.fill_bounds(
+ lower_ctx,
+ lifetime_param.type_bound_list(),
+ Either::Right(lifetime_ref),
+ );
}
}
@@ -421,6 +428,10 @@ fn file_id_and_params_of(
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
}
+ GenericDefId::TraitAliasId(it) => {
+ let src = it.lookup(db).source(db);
+ (src.file_id, src.value.generic_param_list())
+ }
GenericDefId::TypeAliasId(it) => {
let src = it.lookup(db).source(db);
(src.file_id, src.value.generic_param_list())
@@ -435,7 +446,7 @@ fn file_id_and_params_of(
}
impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
- type Value = Either<ast::TypeOrConstParam, ast::Trait>;
+ type Value = Either<ast::TypeOrConstParam, ast::TraitOrAlias>;
fn child_source(
&self,
db: &dyn DefDatabase,
@@ -447,11 +458,20 @@ impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
let mut params = ArenaMap::default();
- // For traits the first type index is `Self`, we need to add it before the other params.
- if let GenericDefId::TraitId(id) = *self {
- let trait_ref = id.lookup(db).source(db).value;
- let idx = idx_iter.next().unwrap();
- params.insert(idx, Either::Right(trait_ref));
+ // For traits and trait aliases the first type index is `Self`, we need to add it before
+ // the other params.
+ match *self {
+ GenericDefId::TraitId(id) => {
+ let trait_ref = id.lookup(db).source(db).value;
+ let idx = idx_iter.next().unwrap();
+ params.insert(idx, Either::Right(ast::TraitOrAlias::Trait(trait_ref)));
+ }
+ GenericDefId::TraitAliasId(id) => {
+ let alias = id.lookup(db).source(db).value;
+ let idx = idx_iter.next().unwrap();
+ params.insert(idx, Either::Right(ast::TraitOrAlias::TraitAlias(alias)));
+ }
+ _ => {}
}
if let Some(generic_params_list) = generic_params_list {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
index 1ce191942..4f1f6000d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
@@ -264,6 +264,7 @@ pub enum ImportKind {
Const,
Static,
Trait,
+ TraitAlias,
TypeAlias,
BuiltinType,
AssociatedItem,
@@ -459,6 +460,7 @@ fn item_import_kind(item: ItemInNs) -> Option<ImportKind> {
ModuleDefId::ConstId(_) => ImportKind::Const,
ModuleDefId::StaticId(_) => ImportKind::Static,
ModuleDefId::TraitId(_) => ImportKind::Trait,
+ ModuleDefId::TraitAliasId(_) => ImportKind::TraitAlias,
ModuleDefId::TypeAliasId(_) => ImportKind::TypeAlias,
ModuleDefId::BuiltinType(_) => ImportKind::BuiltinType,
ModuleDefId::MacroId(_) => ImportKind::Macro,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index 53a4173ff..991e44703 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
@@ -431,6 +431,7 @@ impl PerNs {
ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v),
ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v),
ModuleDefId::TraitId(_) => PerNs::types(def, v),
+ ModuleDefId::TraitAliasId(_) => PerNs::types(def, v),
ModuleDefId::TypeAliasId(_) => PerNs::types(def, v),
ModuleDefId::BuiltinType(_) => PerNs::types(def, v),
ModuleDefId::MacroId(mac) => PerNs::macros(mac, v),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index 19d01630e..9da5b2d47 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -204,6 +204,7 @@ impl ItemTree {
consts,
statics,
traits,
+ trait_aliases,
impls,
type_aliases,
mods,
@@ -226,6 +227,7 @@ impl ItemTree {
consts.shrink_to_fit();
statics.shrink_to_fit();
traits.shrink_to_fit();
+ trait_aliases.shrink_to_fit();
impls.shrink_to_fit();
type_aliases.shrink_to_fit();
mods.shrink_to_fit();
@@ -276,6 +278,7 @@ struct ItemTreeData {
consts: Arena<Const>,
statics: Arena<Static>,
traits: Arena<Trait>,
+ trait_aliases: Arena<TraitAlias>,
impls: Arena<Impl>,
type_aliases: Arena<TypeAlias>,
mods: Arena<Mod>,
@@ -496,6 +499,7 @@ mod_items! {
Const in consts -> ast::Const,
Static in statics -> ast::Static,
Trait in traits -> ast::Trait,
+ TraitAlias in trait_aliases -> ast::TraitAlias,
Impl in impls -> ast::Impl,
TypeAlias in type_aliases -> ast::TypeAlias,
Mod in mods -> ast::Module,
@@ -672,12 +676,19 @@ pub struct Trait {
pub generic_params: Interned<GenericParams>,
pub is_auto: bool,
pub is_unsafe: bool,
- /// This is [`None`] if this Trait is a trait alias.
- pub items: Option<Box<[AssocItem]>>,
+ pub items: Box<[AssocItem]>,
pub ast_id: FileAstId<ast::Trait>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct TraitAlias {
+ pub name: Name,
+ pub visibility: RawVisibilityId,
+ pub generic_params: Interned<GenericParams>,
+ pub ast_id: FileAstId<ast::TraitAlias>,
+}
+
+#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Impl {
pub generic_params: Interned<GenericParams>,
pub target_trait: Option<Interned<TraitRef>>,
@@ -872,6 +883,7 @@ impl ModItem {
| ModItem::Enum(_)
| ModItem::Static(_)
| ModItem::Trait(_)
+ | ModItem::TraitAlias(_)
| ModItem::Impl(_)
| ModItem::Mod(_)
| ModItem::MacroRules(_)
@@ -899,6 +911,7 @@ impl ModItem {
ModItem::Const(it) => tree[it.index].ast_id().upcast(),
ModItem::Static(it) => tree[it.index].ast_id().upcast(),
ModItem::Trait(it) => tree[it.index].ast_id().upcast(),
+ ModItem::TraitAlias(it) => tree[it.index].ast_id().upcast(),
ModItem::Impl(it) => tree[it.index].ast_id().upcast(),
ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(),
ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index d4d3c5ef1..77b186f8e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -3,7 +3,7 @@
use std::{collections::hash_map::Entry, sync::Arc};
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId};
-use syntax::ast::{self, HasModuleItem};
+use syntax::ast::{self, HasModuleItem, HasTypeBounds};
use crate::{
generics::{GenericParams, TypeParamData, TypeParamProvenance},
@@ -90,6 +90,13 @@ impl<'a> Ctx<'a> {
_ => None,
})
.collect();
+ if let Some(ast::Expr::MacroExpr(expr)) = block.tail_expr() {
+ if let Some(call) = expr.macro_call() {
+ if let Some(mod_item) = self.lower_mod_item(&call.into()) {
+ self.tree.top_level.push(mod_item);
+ }
+ }
+ }
self.tree
}
@@ -110,6 +117,7 @@ impl<'a> Ctx<'a> {
ast::Item::Const(ast) => self.lower_const(ast).into(),
ast::Item::Module(ast) => self.lower_module(ast)?.into(),
ast::Item::Trait(ast) => self.lower_trait(ast)?.into(),
+ ast::Item::TraitAlias(ast) => self.lower_trait_alias(ast)?.into(),
ast::Item::Impl(ast) => self.lower_impl(ast)?.into(),
ast::Item::Use(ast) => self.lower_use(ast)?.into(),
ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast)?.into(),
@@ -147,7 +155,7 @@ impl<'a> Ctx<'a> {
fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> {
let visibility = self.lower_visibility(strukt);
let name = strukt.name()?.as_name();
- let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt);
+ let generic_params = self.lower_generic_params(HasImplicitSelf::No, strukt);
let fields = self.lower_fields(&strukt.kind());
let ast_id = self.source_ast_id_map.ast_id(strukt);
let res = Struct { name, visibility, generic_params, fields, ast_id };
@@ -211,7 +219,7 @@ impl<'a> Ctx<'a> {
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
let visibility = self.lower_visibility(union);
let name = union.name()?.as_name();
- let generic_params = self.lower_generic_params(GenericsOwner::Union, union);
+ let generic_params = self.lower_generic_params(HasImplicitSelf::No, union);
let fields = match union.record_field_list() {
Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
None => Fields::Record(IdxRange::new(self.next_field_idx()..self.next_field_idx())),
@@ -224,7 +232,7 @@ impl<'a> Ctx<'a> {
fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<FileItemTreeId<Enum>> {
let visibility = self.lower_visibility(enum_);
let name = enum_.name()?.as_name();
- let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_);
+ let generic_params = self.lower_generic_params(HasImplicitSelf::No, enum_);
let variants = match &enum_.variant_list() {
Some(variant_list) => self.lower_variants(variant_list),
None => IdxRange::new(self.next_variant_idx()..self.next_variant_idx()),
@@ -372,8 +380,7 @@ impl<'a> Ctx<'a> {
ast_id,
flags,
};
- res.explicit_generic_params =
- self.lower_generic_params(GenericsOwner::Function(&res), func);
+ res.explicit_generic_params = self.lower_generic_params(HasImplicitSelf::No, func);
Some(id(self.data().functions.alloc(res)))
}
@@ -386,7 +393,7 @@ impl<'a> Ctx<'a> {
let type_ref = type_alias.ty().map(|it| self.lower_type_ref(&it));
let visibility = self.lower_visibility(type_alias);
let bounds = self.lower_type_bounds(type_alias);
- let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias);
+ let generic_params = self.lower_generic_params(HasImplicitSelf::No, type_alias);
let ast_id = self.source_ast_id_map.ast_id(type_alias);
let res = TypeAlias {
name,
@@ -442,27 +449,49 @@ impl<'a> Ctx<'a> {
fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option<FileItemTreeId<Trait>> {
let name = trait_def.name()?.as_name();
let visibility = self.lower_visibility(trait_def);
- let generic_params = self.lower_generic_params(GenericsOwner::Trait(trait_def), trait_def);
+ let generic_params =
+ self.lower_generic_params(HasImplicitSelf::Yes(trait_def.type_bound_list()), trait_def);
let is_auto = trait_def.auto_token().is_some();
let is_unsafe = trait_def.unsafe_token().is_some();
- let items = trait_def.assoc_item_list().map(|list| {
- list.assoc_items()
- .filter_map(|item| {
- let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
- self.lower_assoc_item(&item).map(|item| {
- self.add_attrs(ModItem::from(item).into(), attrs);
- item
- })
- })
- .collect()
- });
let ast_id = self.source_ast_id_map.ast_id(trait_def);
- let res = Trait { name, visibility, generic_params, is_auto, is_unsafe, items, ast_id };
- Some(id(self.data().traits.alloc(res)))
+
+ let items = trait_def
+ .assoc_item_list()
+ .into_iter()
+ .flat_map(|list| list.assoc_items())
+ .filter_map(|item| {
+ let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
+ self.lower_assoc_item(&item).map(|item| {
+ self.add_attrs(ModItem::from(item).into(), attrs);
+ item
+ })
+ })
+ .collect();
+
+ let def = Trait { name, visibility, generic_params, is_auto, is_unsafe, items, ast_id };
+ Some(id(self.data().traits.alloc(def)))
+ }
+
+ fn lower_trait_alias(
+ &mut self,
+ trait_alias_def: &ast::TraitAlias,
+ ) -> Option<FileItemTreeId<TraitAlias>> {
+ let name = trait_alias_def.name()?.as_name();
+ let visibility = self.lower_visibility(trait_alias_def);
+ let generic_params = self.lower_generic_params(
+ HasImplicitSelf::Yes(trait_alias_def.type_bound_list()),
+ trait_alias_def,
+ );
+ let ast_id = self.source_ast_id_map.ast_id(trait_alias_def);
+
+ let alias = TraitAlias { name, visibility, generic_params, ast_id };
+ Some(id(self.data().trait_aliases.alloc(alias)))
}
fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
- let generic_params = self.lower_generic_params(GenericsOwner::Impl, impl_def);
+ // Note that trait impls don't get implicit `Self` unlike traits, because here they are a
+ // type alias rather than a type parameter, so this is handled by the resolver.
+ let generic_params = self.lower_generic_params(HasImplicitSelf::No, impl_def);
// FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
// as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
// equals itself.
@@ -566,42 +595,29 @@ impl<'a> Ctx<'a> {
fn lower_generic_params(
&mut self,
- owner: GenericsOwner<'_>,
+ has_implicit_self: HasImplicitSelf,
node: &dyn ast::HasGenericParams,
) -> Interned<GenericParams> {
let mut generics = GenericParams::default();
- match owner {
- GenericsOwner::Function(_)
- | GenericsOwner::Struct
- | GenericsOwner::Enum
- | GenericsOwner::Union
- | GenericsOwner::TypeAlias => {
- generics.fill(&self.body_ctx, node);
- }
- GenericsOwner::Trait(trait_def) => {
- // traits get the Self type as an implicit first type parameter
- generics.type_or_consts.alloc(
- TypeParamData {
- name: Some(name![Self]),
- default: None,
- provenance: TypeParamProvenance::TraitSelf,
- }
- .into(),
- );
- // add super traits as bounds on Self
- // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
- let self_param = TypeRef::Path(name![Self].into());
- generics.fill_bounds(&self.body_ctx, trait_def, Either::Left(self_param));
- generics.fill(&self.body_ctx, node);
- }
- GenericsOwner::Impl => {
- // Note that we don't add `Self` here: in `impl`s, `Self` is not a
- // type-parameter, but rather is a type-alias for impl's target
- // type, so this is handled by the resolver.
- generics.fill(&self.body_ctx, node);
- }
+
+ if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
+ // Traits and trait aliases get the Self type as an implicit first type parameter.
+ generics.type_or_consts.alloc(
+ TypeParamData {
+ name: Some(name![Self]),
+ default: None,
+ provenance: TypeParamProvenance::TraitSelf,
+ }
+ .into(),
+ );
+ // add super traits as bounds on Self
+ // i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar`
+ let self_param = TypeRef::Path(name![Self].into());
+ generics.fill_bounds(&self.body_ctx, bounds, Either::Left(self_param));
}
+ generics.fill(&self.body_ctx, node);
+
generics.shrink_to_fit();
Interned::new(generics)
}
@@ -673,17 +689,10 @@ fn desugar_future_path(orig: TypeRef) -> Path {
Path::from_known_path(path, generic_args)
}
-enum GenericsOwner<'a> {
- /// We need access to the partially-lowered `Function` for lowering `impl Trait` in argument
- /// position.
- Function(&'a Function),
- Struct,
- Enum,
- Union,
- /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter.
- Trait(&'a ast::Trait),
- TypeAlias,
- Impl,
+enum HasImplicitSelf {
+ /// Inner list is a type bound list for the implicit `Self`.
+ Yes(Option<ast::TypeBoundList>),
+ No,
}
fn lower_abi(abi: ast::Abi) -> Interned<str> {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index 8f230b87d..5f2999796 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -374,23 +374,24 @@ impl<'a> Printer<'a> {
}
w!(self, "trait {}", name);
self.print_generic_params(generic_params);
- match items {
- Some(items) => {
- self.print_where_clause_and_opening_brace(generic_params);
- self.indented(|this| {
- for item in &**items {
- this.print_mod_item((*item).into());
- }
- });
- }
- None => {
- w!(self, " = ");
- // FIXME: Print the aliased traits
- self.print_where_clause_and_opening_brace(generic_params);
+ self.print_where_clause_and_opening_brace(generic_params);
+ self.indented(|this| {
+ for item in &**items {
+ this.print_mod_item((*item).into());
}
- }
+ });
wln!(self, "}}");
}
+ ModItem::TraitAlias(it) => {
+ let TraitAlias { name, visibility, generic_params, ast_id: _ } = &self.tree[it];
+ self.print_visibility(*visibility);
+ w!(self, "trait {}", name);
+ self.print_generic_params(generic_params);
+ w!(self, " = ");
+ self.print_where_clause(generic_params);
+ w!(self, ";");
+ wln!(self);
+ }
ModItem::Impl(it) => {
let Impl { target_trait, self_ty, is_negative, items, generic_params, ast_id: _ } =
&self.tree[it];
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/keys.rs b/src/tools/rust-analyzer/crates/hir-def/src/keys.rs
index 72beec818..f30be6b64 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/keys.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/keys.rs
@@ -9,8 +9,8 @@ use syntax::{ast, AstNode, AstPtr};
use crate::{
dyn_map::{DynMap, Policy},
ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, Macro2Id,
- MacroRulesId, ProcMacroId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId,
- UnionId,
+ MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId,
+ TypeOrConstParamId, UnionId,
};
pub type Key<K, V> = crate::dyn_map::Key<K, V, AstPtrPolicy<K, V>>;
@@ -21,6 +21,7 @@ pub const STATIC: Key<ast::Static, StaticId> = Key::new();
pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new();
pub const IMPL: Key<ast::Impl, ImplId> = Key::new();
pub const TRAIT: Key<ast::Trait, TraitId> = Key::new();
+pub const TRAIT_ALIAS: Key<ast::TraitAlias, TraitAliasId> = Key::new();
pub const STRUCT: Key<ast::Struct, StructId> = Key::new();
pub const UNION: Key<ast::Union, UnionId> = Key::new();
pub const ENUM: Key<ast::Enum, EnumId> = Key::new();
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index ab9bc615d..4096e0a38 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -181,15 +181,15 @@ impl LangItems {
T: Into<AttrDefId> + Copy,
{
let _p = profile::span("collect_lang_item");
- if let Some(lang_item) = lang_attr(db, item).and_then(|it| LangItem::from_str(&it)) {
+ if let Some(lang_item) = lang_attr(db, item) {
self.items.entry(lang_item).or_insert_with(|| constructor(item));
}
}
}
-pub fn lang_attr(db: &dyn DefDatabase, item: impl Into<AttrDefId> + Copy) -> Option<SmolStr> {
+pub fn lang_attr(db: &dyn DefDatabase, item: impl Into<AttrDefId> + Copy) -> Option<LangItem> {
let attrs = db.attrs(item.into());
- attrs.by_key("lang").string_value().cloned()
+ attrs.by_key("lang").string_value().cloned().and_then(|it| LangItem::from_str(&it))
}
pub enum GenericRequirement {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index d07c5fb67..8c2e93f09 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -86,7 +86,7 @@ use crate::{
builtin_type::BuiltinType,
item_tree::{
Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, ModItem,
- Static, Struct, Trait, TypeAlias, Union,
+ Static, Struct, Trait, TraitAlias, TypeAlias, Union,
},
};
@@ -128,7 +128,7 @@ impl ModuleId {
}
}
-/// An ID of a module, **local** to a specific crate
+/// An ID of a module, **local** to a `DefMap`.
pub type LocalModuleId = Idx<nameres::ModuleData>;
#[derive(Debug)]
@@ -262,6 +262,11 @@ pub type TraitLoc = ItemLoc<Trait>;
impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct TraitAliasId(salsa::InternId);
+pub type TraitAliasLoc = ItemLoc<TraitAlias>;
+impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeAliasId(salsa::InternId);
type TypeAliasLoc = AssocItemLoc<TypeAlias>;
impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
@@ -453,6 +458,7 @@ pub enum ModuleDefId {
ConstId(ConstId),
StaticId(StaticId),
TraitId(TraitId),
+ TraitAliasId(TraitAliasId),
TypeAliasId(TypeAliasId),
BuiltinType(BuiltinType),
MacroId(MacroId),
@@ -466,6 +472,7 @@ impl_from!(
ConstId,
StaticId,
TraitId,
+ TraitAliasId,
TypeAliasId,
BuiltinType
for ModuleDefId
@@ -516,6 +523,7 @@ pub enum GenericDefId {
FunctionId(FunctionId),
AdtId(AdtId),
TraitId(TraitId),
+ TraitAliasId(TraitAliasId),
TypeAliasId(TypeAliasId),
ImplId(ImplId),
// enum variants cannot have generics themselves, but their parent enums
@@ -528,6 +536,7 @@ impl_from!(
FunctionId,
AdtId(StructId, EnumId, UnionId),
TraitId,
+ TraitAliasId,
TypeAliasId,
ImplId,
EnumVariantId,
@@ -555,6 +564,7 @@ pub enum AttrDefId {
StaticId(StaticId),
ConstId(ConstId),
TraitId(TraitId),
+ TraitAliasId(TraitAliasId),
TypeAliasId(TypeAliasId),
MacroId(MacroId),
ImplId(ImplId),
@@ -714,6 +724,7 @@ impl HasModule for GenericDefId {
GenericDefId::FunctionId(it) => it.lookup(db).module(db),
GenericDefId::AdtId(it) => it.module(db),
GenericDefId::TraitId(it) => it.lookup(db).container,
+ GenericDefId::TraitAliasId(it) => it.lookup(db).container,
GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
GenericDefId::ImplId(it) => it.lookup(db).container,
GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container,
@@ -747,6 +758,7 @@ impl ModuleDefId {
ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
ModuleDefId::StaticId(id) => id.lookup(db).module(db),
ModuleDefId::TraitId(id) => id.lookup(db).container,
+ ModuleDefId::TraitAliasId(id) => id.lookup(db).container,
ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db),
ModuleDefId::MacroId(id) => id.module(db),
ModuleDefId::BuiltinType(_) => return None,
@@ -765,6 +777,7 @@ impl AttrDefId {
AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
AttrDefId::TraitId(it) => it.lookup(db).container.krate,
+ AttrDefId::TraitAliasId(it) => it.lookup(db).container.krate,
AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
AttrDefId::ImplId(it) => it.lookup(db).container.krate,
AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs
index 5ab90d92d..314bf22b9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs
@@ -20,7 +20,7 @@ use ::mbe::TokenMap;
use base_db::{fixture::WithFixture, ProcMacro, SourceDatabase};
use expect_test::Expect;
use hir_expand::{
- db::{AstDatabase, TokenExpander},
+ db::{ExpandDatabase, TokenExpander},
AstId, InFile, MacroDefId, MacroDefKind, MacroFile,
};
use stdx::format_to;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index bb4526672..0b72ca1ee 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -143,7 +143,7 @@ macro_rules! assert {
fn main() {
{
- if !true {
+ if !(true ) {
$crate::panic!("{} {:?}", arg1(a, b, c), arg2);
}
};
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
index 8358a46f0..b663a2917 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
@@ -827,6 +827,7 @@ macro_rules! rgb_color {
/* parse error: expected type */
/* parse error: expected R_PAREN */
/* parse error: expected R_ANGLE */
+/* parse error: expected `::` */
/* parse error: expected COMMA */
/* parse error: expected R_ANGLE */
/* parse error: expected SEMICOLON */
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index f42b0079d..4efe8c58a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -120,6 +120,8 @@ pub struct DefMap {
registered_tools: Vec<SmolStr>,
/// Unstable features of Rust enabled with `#![feature(A, B)]`.
unstable_features: FxHashSet<SmolStr>,
+ /// #[rustc_coherence_is_core]
+ rustc_coherence_is_core: bool,
edition: Edition,
recursion_limit: Option<u32>,
@@ -215,7 +217,7 @@ pub struct ModuleData {
pub origin: ModuleOrigin,
/// Declared visibility of this module.
pub visibility: Visibility,
-
+ /// Always [`None`] for block modules
pub parent: Option<LocalModuleId>,
pub children: FxHashMap<Name, LocalModuleId>,
pub scope: ItemScope,
@@ -292,6 +294,7 @@ impl DefMap {
registered_tools: Vec::new(),
unstable_features: FxHashSet::default(),
diagnostics: Vec::new(),
+ rustc_coherence_is_core: false,
}
}
@@ -325,6 +328,10 @@ impl DefMap {
self.unstable_features.contains(feature)
}
+ pub fn is_rustc_coherence_is_core(&self) -> bool {
+ self.rustc_coherence_is_core
+ }
+
pub fn root(&self) -> LocalModuleId {
self.root
}
@@ -337,12 +344,12 @@ impl DefMap {
self.proc_macro_loading_error.as_deref()
}
- pub(crate) fn krate(&self) -> CrateId {
+ pub fn krate(&self) -> CrateId {
self.krate
}
pub(crate) fn block_id(&self) -> Option<BlockId> {
- self.block.as_ref().map(|block| block.block)
+ self.block.map(|block| block.block)
}
pub(crate) fn prelude(&self) -> Option<ModuleId> {
@@ -354,7 +361,7 @@ impl DefMap {
}
pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
- let block = self.block.as_ref().map(|b| b.block);
+ let block = self.block.map(|b| b.block);
ModuleId { krate: self.krate, local_id, block }
}
@@ -425,12 +432,12 @@ impl DefMap {
Some(self.block?.parent)
}
- /// Returns the module containing `local_mod`, either the parent `mod`, or the module containing
+ /// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing
/// the block, if `self` corresponds to a block expression.
pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
- match &self[local_mod].parent {
- Some(parent) => Some(self.module_id(*parent)),
- None => self.block.as_ref().map(|block| block.parent),
+ match self[local_mod].parent {
+ Some(parent) => Some(self.module_id(parent)),
+ None => self.block.map(|block| block.parent),
}
}
@@ -440,11 +447,11 @@ impl DefMap {
let mut buf = String::new();
let mut arc;
let mut current_map = self;
- while let Some(block) = &current_map.block {
+ while let Some(block) = current_map.block {
go(&mut buf, current_map, "block scope", current_map.root);
buf.push('\n');
arc = block.parent.def_map(db);
- current_map = &*arc;
+ current_map = &arc;
}
go(&mut buf, current_map, "crate", current_map.root);
return buf;
@@ -468,10 +475,10 @@ impl DefMap {
let mut buf = String::new();
let mut arc;
let mut current_map = self;
- while let Some(block) = &current_map.block {
+ while let Some(block) = current_map.block {
format_to!(buf, "{:?} in {:?}\n", block.block, block.parent);
arc = block.parent.def_map(db);
- current_map = &*arc;
+ current_map = &arc;
}
format_to!(buf, "crate scope\n");
@@ -498,6 +505,7 @@ impl DefMap {
krate: _,
prelude: _,
root: _,
+ rustc_coherence_is_core: _,
} = self;
extern_prelude.shrink_to_fit();
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 4b39a20d8..ddcee77ec 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -51,7 +51,8 @@ use crate::{
AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, ExternBlockLoc, FunctionId,
FunctionLoc, ImplLoc, Intern, ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc,
MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId,
- ProcMacroLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro,
+ ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc,
+ UnresolvedMacro,
};
static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
@@ -86,10 +87,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T
// FIXME: a hacky way to create a Name from string.
let name =
tt::Ident { text: it.name.clone(), span: tt::TokenId::unspecified() };
- (
- name.as_name(),
- ProcMacroExpander::new(def_map.krate, base_db::ProcMacroId(idx as u32)),
- )
+ (name.as_name(), ProcMacroExpander::new(base_db::ProcMacroId(idx as u32)))
})
.collect()
}
@@ -298,6 +296,11 @@ impl DefCollector<'_> {
continue;
}
+ if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") {
+ self.def_map.rustc_coherence_is_core = true;
+ continue;
+ }
+
if *attr_name == hir_expand::name![feature] {
let features =
attr.parse_path_comma_token_tree().into_iter().flatten().filter_map(
@@ -580,7 +583,7 @@ impl DefCollector<'_> {
let kind = def.kind.to_basedb_kind();
let (expander, kind) = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
Some(&(_, expander)) => (expander, kind),
- None => (ProcMacroExpander::dummy(self.def_map.krate), kind),
+ None => (ProcMacroExpander::dummy(), kind),
};
let proc_macro_id =
@@ -666,8 +669,10 @@ impl DefCollector<'_> {
macro_: Macro2Id,
vis: &RawVisibility,
) {
- let vis =
- self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public);
+ let vis = self
+ .def_map
+ .resolve_visibility(self.db, module_id, vis, false)
+ .unwrap_or(Visibility::Public);
self.def_map.modules[module_id].scope.declare(macro_.into());
self.update(
module_id,
@@ -831,7 +836,7 @@ impl DefCollector<'_> {
let mut def = directive.status.namespaces();
let vis = self
.def_map
- .resolve_visibility(self.db, module_id, &directive.import.visibility)
+ .resolve_visibility(self.db, module_id, &directive.import.visibility, false)
.unwrap_or(Visibility::Public);
match import.kind {
@@ -1547,7 +1552,7 @@ impl ModCollector<'_, '_> {
};
let resolve_vis = |def_map: &DefMap, visibility| {
def_map
- .resolve_visibility(db, self.module_id, visibility)
+ .resolve_visibility(db, self.module_id, visibility, false)
.unwrap_or(Visibility::Public)
};
@@ -1707,6 +1712,20 @@ impl ModCollector<'_, '_> {
false,
);
}
+ ModItem::TraitAlias(id) => {
+ let it = &self.item_tree[id];
+
+ let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ update_def(
+ self.def_collector,
+ TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
+ .intern(db)
+ .into(),
+ &it.name,
+ vis,
+ false,
+ );
+ }
ModItem::TypeAlias(id) => {
let it = &self.item_tree[id];
@@ -1823,7 +1842,7 @@ impl ModCollector<'_, '_> {
) -> LocalModuleId {
let def_map = &mut self.def_collector.def_map;
let vis = def_map
- .resolve_visibility(self.def_collector.db, self.module_id, visibility)
+ .resolve_visibility(self.def_collector.db, self.module_id, visibility, false)
.unwrap_or(Visibility::Public);
let modules = &mut def_map.modules;
let origin = match definition {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
index 1d9d5cccd..25478481d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
@@ -78,6 +78,7 @@ impl DefMap {
// pub(path)
// ^^^^ this
visibility: &RawVisibility,
+ within_impl: bool,
) -> Option<Visibility> {
let mut vis = match visibility {
RawVisibility::Module(path) => {
@@ -102,7 +103,8 @@ impl DefMap {
// `super` to its parent (etc.). However, visibilities must only refer to a module in the
// DefMap they're written in, so we restrict them when that happens.
if let Visibility::Module(m) = vis {
- if self.block_id() != m.block {
+ // ...unless we're resolving visibility for an associated item in an impl.
+ if self.block_id() != m.block && !within_impl {
cov_mark::hit!(adjust_vis_in_block_def_map);
vis = Visibility::Module(self.module_id(self.root()));
tracing::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
index f5190b76d..13e6825f8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
@@ -223,6 +223,7 @@ pub type Ty = ();
ModuleDefId::ConstId(it) => drop(db.const_data(it)),
ModuleDefId::StaticId(it) => drop(db.static_data(it)),
ModuleDefId::TraitId(it) => drop(db.trait_data(it)),
+ ModuleDefId::TraitAliasId(it) => drop(db.trait_alias_data(it)),
ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)),
ModuleDefId::EnumVariantId(_)
| ModuleDefId::ModuleId(_)
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
index 36d4c36a2..f3197d180 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
@@ -8,7 +8,7 @@ use std::{
use crate::{
body::LowerCtx,
- type_ref::{ConstScalarOrPath, LifetimeRef},
+ type_ref::{ConstRefOrPath, LifetimeRef},
};
use hir_expand::name::Name;
use intern::Interned;
@@ -85,7 +85,7 @@ pub struct AssociatedTypeBinding {
pub enum GenericArg {
Type(TypeRef),
Lifetime(LifetimeRef),
- Const(ConstScalarOrPath),
+ Const(ConstRefOrPath),
}
impl Path {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
index c85a11db6..b7542bd77 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
@@ -2,7 +2,7 @@
use std::iter;
-use crate::type_ref::ConstScalarOrPath;
+use crate::type_ref::ConstRefOrPath;
use either::Either;
use hir_expand::name::{name, AsName};
@@ -212,7 +212,7 @@ pub(super) fn lower_generic_args(
}
}
ast::GenericArg::ConstArg(arg) => {
- let arg = ConstScalarOrPath::from_expr_opt(arg.expr());
+ let arg = ConstRefOrPath::from_expr_opt(arg.expr());
args.push(GenericArg::Const(arg))
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index 86958e3da..61e64fc10 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -1,5 +1,5 @@
//! Name resolution façade.
-use std::{hash::BuildHasherDefault, sync::Arc};
+use std::{fmt, hash::BuildHasherDefault, sync::Arc};
use base_db::CrateId;
use hir_expand::name::{name, Name};
@@ -12,7 +12,7 @@ use crate::{
body::scope::{ExprScopes, ScopeId},
builtin_type::BuiltinType,
db::DefDatabase,
- expr::{ExprId, LabelId, PatId},
+ expr::{BindingId, ExprId, LabelId},
generics::{GenericParams, TypeOrConstParamData},
item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
nameres::DefMap,
@@ -22,7 +22,8 @@ use crate::{
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId,
FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
LocalModuleId, Lookup, Macro2Id, MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId,
- StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, VariantId,
+ StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
+ VariantId,
};
#[derive(Debug, Clone)]
@@ -35,19 +36,34 @@ pub struct Resolver {
module_scope: ModuleItemMap,
}
-#[derive(Debug, Clone)]
+#[derive(Clone)]
struct ModuleItemMap {
def_map: Arc<DefMap>,
module_id: LocalModuleId,
}
-#[derive(Debug, Clone)]
+impl fmt::Debug for ModuleItemMap {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("ModuleItemMap").field("module_id", &self.module_id).finish()
+ }
+}
+
+#[derive(Clone)]
struct ExprScope {
owner: DefWithBodyId,
expr_scopes: Arc<ExprScopes>,
scope_id: ScopeId,
}
+impl fmt::Debug for ExprScope {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("ExprScope")
+ .field("owner", &self.owner)
+ .field("scope_id", &self.scope_id)
+ .finish()
+ }
+}
+
#[derive(Debug, Clone)]
enum Scope {
/// All the items and imported names of a module
@@ -74,6 +90,7 @@ pub enum TypeNs {
TypeAliasId(TypeAliasId),
BuiltinType(BuiltinType),
TraitId(TraitId),
+ TraitAliasId(TraitAliasId),
// Module belong to type ns, but the resolver is used when all module paths
// are fully resolved.
// ModuleId(ModuleId)
@@ -85,10 +102,10 @@ pub enum ResolveValueResult {
Partial(TypeNs, usize),
}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ValueNs {
ImplSelf(ImplId),
- LocalBinding(PatId),
+ LocalBinding(BindingId),
FunctionId(FunctionId),
ConstId(ConstId),
StaticId(StaticId),
@@ -214,10 +231,12 @@ impl Resolver {
db: &dyn DefDatabase,
visibility: &RawVisibility,
) -> Option<Visibility> {
+ let within_impl =
+ self.scopes().find(|scope| matches!(scope, Scope::ImplDefScope(_))).is_some();
match visibility {
RawVisibility::Module(_) => {
let (item_map, module) = self.item_scope();
- item_map.resolve_visibility(db, module, visibility)
+ item_map.resolve_visibility(db, module, visibility, within_impl)
}
RawVisibility::Public => Some(Visibility::Public),
}
@@ -236,69 +255,81 @@ impl Resolver {
return self.module_scope.resolve_path_in_value_ns(db, path);
}
- for scope in self.scopes() {
- match scope {
- Scope::ExprScope(_) if n_segments > 1 => continue,
- Scope::ExprScope(scope) => {
- let entry = scope
- .expr_scopes
- .entries(scope.scope_id)
- .iter()
- .find(|entry| entry.name() == first_name);
-
- if let Some(e) = entry {
- return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(e.pat())));
+ if n_segments <= 1 {
+ for scope in self.scopes() {
+ match scope {
+ Scope::ExprScope(scope) => {
+ let entry = scope
+ .expr_scopes
+ .entries(scope.scope_id)
+ .iter()
+ .find(|entry| entry.name() == first_name);
+
+ if let Some(e) = entry {
+ return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(
+ e.binding(),
+ )));
+ }
}
- }
- Scope::GenericParams { params, def } if n_segments > 1 => {
- if let Some(id) = params.find_type_by_name(first_name, *def) {
- let ty = TypeNs::GenericParam(id);
- return Some(ResolveValueResult::Partial(ty, 1));
+ Scope::GenericParams { params, def } => {
+ if let Some(id) = params.find_const_by_name(first_name, *def) {
+ let val = ValueNs::GenericParam(id);
+ return Some(ResolveValueResult::ValueNs(val));
+ }
}
- }
- Scope::GenericParams { .. } if n_segments != 1 => continue,
- Scope::GenericParams { params, def } => {
- if let Some(id) = params.find_const_by_name(first_name, *def) {
- let val = ValueNs::GenericParam(id);
- return Some(ResolveValueResult::ValueNs(val));
+ &Scope::ImplDefScope(impl_) => {
+ if first_name == &name![Self] {
+ return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(impl_)));
+ }
}
- }
-
- &Scope::ImplDefScope(impl_) => {
- if first_name == &name![Self] {
- return Some(if n_segments > 1 {
- ResolveValueResult::Partial(TypeNs::SelfType(impl_), 1)
- } else {
- ResolveValueResult::ValueNs(ValueNs::ImplSelf(impl_))
- });
+ // bare `Self` doesn't work in the value namespace in a struct/enum definition
+ Scope::AdtScope(_) => continue,
+ Scope::BlockScope(m) => {
+ if let Some(def) = m.resolve_path_in_value_ns(db, path) {
+ return Some(def);
+ }
}
}
- // bare `Self` doesn't work in the value namespace in a struct/enum definition
- Scope::AdtScope(_) if n_segments == 1 => continue,
- Scope::AdtScope(adt) => {
- if first_name == &name![Self] {
- let ty = TypeNs::AdtSelfType(*adt);
- return Some(ResolveValueResult::Partial(ty, 1));
+ }
+ } else {
+ for scope in self.scopes() {
+ match scope {
+ Scope::ExprScope(_) => continue,
+ Scope::GenericParams { params, def } => {
+ if let Some(id) = params.find_type_by_name(first_name, *def) {
+ let ty = TypeNs::GenericParam(id);
+ return Some(ResolveValueResult::Partial(ty, 1));
+ }
}
- }
-
- Scope::BlockScope(m) => {
- if let Some(def) = m.resolve_path_in_value_ns(db, path) {
- return Some(def);
+ &Scope::ImplDefScope(impl_) => {
+ if first_name == &name![Self] {
+ return Some(ResolveValueResult::Partial(TypeNs::SelfType(impl_), 1));
+ }
+ }
+ Scope::AdtScope(adt) => {
+ if first_name == &name![Self] {
+ let ty = TypeNs::AdtSelfType(*adt);
+ return Some(ResolveValueResult::Partial(ty, 1));
+ }
+ }
+ Scope::BlockScope(m) => {
+ if let Some(def) = m.resolve_path_in_value_ns(db, path) {
+ return Some(def);
+ }
}
}
}
}
- if let res @ Some(_) = self.module_scope.resolve_path_in_value_ns(db, path) {
- return res;
+ if let Some(res) = self.module_scope.resolve_path_in_value_ns(db, path) {
+ return Some(res);
}
// If a path of the shape `u16::from_le_bytes` failed to resolve at all, then we fall back
// to resolving to the primitive type, to allow this to still work in the presence of
// `use core::u16;`.
- if path.kind == PathKind::Plain && path.segments().len() > 1 {
- if let Some(builtin) = BuiltinType::by_name(&path.segments()[0]) {
+ if path.kind == PathKind::Plain && n_segments > 1 {
+ if let Some(builtin) = BuiltinType::by_name(first_name) {
return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1));
}
}
@@ -400,6 +431,8 @@ impl Resolver {
}
pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> {
+ // FIXME(trait_alias): Trait alias brings aliased traits in scope! Note that supertraits of
+ // aliased traits are NOT brought in scope (unless also aliased).
let mut traits = FxHashSet::default();
for scope in self.scopes() {
@@ -428,6 +461,15 @@ impl Resolver {
traits
}
+ pub fn traits_in_scope_from_block_scopes(&self) -> impl Iterator<Item = TraitId> + '_ {
+ self.scopes()
+ .filter_map(|scope| match scope {
+ Scope::BlockScope(m) => Some(m.def_map[m.module_id].scope.traits()),
+ _ => None,
+ })
+ .flatten()
+ }
+
pub fn module(&self) -> ModuleId {
let (def_map, local_id) = self.item_scope();
def_map.module_id(local_id)
@@ -459,14 +501,85 @@ impl Resolver {
})
}
+ pub fn generic_params(&self) -> Option<&Interned<GenericParams>> {
+ self.scopes().find_map(|scope| match scope {
+ Scope::GenericParams { params, .. } => Some(params),
+ _ => None,
+ })
+ }
+
pub fn body_owner(&self) -> Option<DefWithBodyId> {
self.scopes().find_map(|scope| match scope {
Scope::ExprScope(it) => Some(it.owner),
_ => None,
})
}
+ /// `expr_id` is required to be an expression id that comes after the top level expression scope in the given resolver
+ #[must_use]
+ pub fn update_to_inner_scope(
+ &mut self,
+ db: &dyn DefDatabase,
+ owner: DefWithBodyId,
+ expr_id: ExprId,
+ ) -> UpdateGuard {
+ #[inline(always)]
+ fn append_expr_scope(
+ db: &dyn DefDatabase,
+ resolver: &mut Resolver,
+ owner: DefWithBodyId,
+ expr_scopes: &Arc<ExprScopes>,
+ scope_id: ScopeId,
+ ) {
+ resolver.scopes.push(Scope::ExprScope(ExprScope {
+ owner,
+ expr_scopes: expr_scopes.clone(),
+ scope_id,
+ }));
+ if let Some(block) = expr_scopes.block(scope_id) {
+ if let Some(def_map) = db.block_def_map(block) {
+ let root = def_map.root();
+ resolver
+ .scopes
+ .push(Scope::BlockScope(ModuleItemMap { def_map, module_id: root }));
+ // FIXME: This adds as many module scopes as there are blocks, but resolving in each
+ // already traverses all parents, so this is O(n²). I think we could only store the
+ // innermost module scope instead?
+ }
+ }
+ }
+
+ let start = self.scopes.len();
+ let innermost_scope = self.scopes().next();
+ match innermost_scope {
+ Some(&Scope::ExprScope(ExprScope { scope_id, ref expr_scopes, owner })) => {
+ let expr_scopes = expr_scopes.clone();
+ let scope_chain = expr_scopes
+ .scope_chain(expr_scopes.scope_for(expr_id))
+ .take_while(|&it| it != scope_id);
+ for scope_id in scope_chain {
+ append_expr_scope(db, self, owner, &expr_scopes, scope_id);
+ }
+ }
+ _ => {
+ let expr_scopes = db.expr_scopes(owner);
+ let scope_chain = expr_scopes.scope_chain(expr_scopes.scope_for(expr_id));
+
+ for scope_id in scope_chain {
+ append_expr_scope(db, self, owner, &expr_scopes, scope_id);
+ }
+ }
+ }
+ self.scopes[start..].reverse();
+ UpdateGuard(start)
+ }
+
+ pub fn reset_to_guard(&mut self, UpdateGuard(start): UpdateGuard) {
+ self.scopes.truncate(start);
+ }
}
+pub struct UpdateGuard(usize);
+
impl Resolver {
fn scopes(&self) -> impl Iterator<Item = &Scope> {
self.scopes.iter().rev()
@@ -504,7 +617,7 @@ pub enum ScopeDef {
ImplSelfType(ImplId),
AdtSelfType(AdtId),
GenericParam(GenericParamId),
- Local(PatId),
+ Local(BindingId),
Label(LabelId),
}
@@ -556,17 +669,18 @@ impl Scope {
acc.add(&name, ScopeDef::Label(label))
}
scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| {
- acc.add_local(e.name(), e.pat());
+ acc.add_local(e.name(), e.binding());
});
}
}
}
}
-// needs arbitrary_self_types to be a method... or maybe move to the def?
pub fn resolver_for_expr(db: &dyn DefDatabase, owner: DefWithBodyId, expr_id: ExprId) -> Resolver {
+ let r = owner.resolver(db);
let scopes = db.expr_scopes(owner);
- resolver_for_scope(db, owner, scopes.scope_for(expr_id))
+ let scope_id = scopes.scope_for(expr_id);
+ resolver_for_scope_(db, scopes, scope_id, r, owner)
}
pub fn resolver_for_scope(
@@ -574,8 +688,18 @@ pub fn resolver_for_scope(
owner: DefWithBodyId,
scope_id: Option<ScopeId>,
) -> Resolver {
- let mut r = owner.resolver(db);
+ let r = owner.resolver(db);
let scopes = db.expr_scopes(owner);
+ resolver_for_scope_(db, scopes, scope_id, r, owner)
+}
+
+fn resolver_for_scope_(
+ db: &dyn DefDatabase,
+ scopes: Arc<ExprScopes>,
+ scope_id: Option<ScopeId>,
+ mut r: Resolver,
+ owner: DefWithBodyId,
+) -> Resolver {
let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
r.scopes.reserve(scope_chain.len());
@@ -641,6 +765,7 @@ impl ModuleItemMap {
let ty = match module_def.take_types()? {
ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
+ ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it),
ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it),
ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
@@ -678,6 +803,7 @@ fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
ModuleDefId::AdtId(AdtId::EnumId(_) | AdtId::UnionId(_))
| ModuleDefId::TraitId(_)
+ | ModuleDefId::TraitAliasId(_)
| ModuleDefId::TypeAliasId(_)
| ModuleDefId::BuiltinType(_)
| ModuleDefId::MacroId(_)
@@ -695,6 +821,7 @@ fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it),
ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
+ ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it),
ModuleDefId::FunctionId(_)
| ModuleDefId::ConstId(_)
@@ -732,7 +859,7 @@ impl ScopeNames {
self.add(name, ScopeDef::Unknown)
}
}
- fn add_local(&mut self, name: &Name, pat: PatId) {
+ fn add_local(&mut self, name: &Name, binding: BindingId) {
let set = self.map.entry(name.clone()).or_default();
// XXX: hack, account for local (and only local) shadowing.
//
@@ -743,7 +870,7 @@ impl ScopeNames {
cov_mark::hit!(shadowing_shows_single_completion);
return;
}
- set.push(ScopeDef::Local(pat))
+ set.push(ScopeDef::Local(binding))
}
}
@@ -779,6 +906,12 @@ impl HasResolver for TraitId {
}
}
+impl HasResolver for TraitAliasId {
+ fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+ self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
+ }
+}
+
impl<T: Into<AdtId> + Copy> HasResolver for T {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
let def = self.into();
@@ -858,6 +991,7 @@ impl HasResolver for GenericDefId {
GenericDefId::FunctionId(inner) => inner.resolver(db),
GenericDefId::AdtId(adt) => adt.resolver(db),
GenericDefId::TraitId(inner) => inner.resolver(db),
+ GenericDefId::TraitAliasId(inner) => inner.resolver(db),
GenericDefId::TypeAliasId(inner) => inner.resolver(db),
GenericDefId::ImplId(inner) => inner.resolver(db),
GenericDefId::EnumVariantId(inner) => inner.parent.resolver(db),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
index b7908bdda..ee143b19a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
@@ -9,7 +9,7 @@ use base_db::{
salsa, AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, FilePosition,
SourceDatabase, Upcast,
};
-use hir_expand::{db::AstDatabase, InFile};
+use hir_expand::{db::ExpandDatabase, InFile};
use stdx::hash::NoHashHashSet;
use syntax::{algo, ast, AstNode};
@@ -23,7 +23,7 @@ use crate::{
#[salsa::database(
base_db::SourceDatabaseExtStorage,
base_db::SourceDatabaseStorage,
- hir_expand::db::AstDatabaseStorage,
+ hir_expand::db::ExpandDatabaseStorage,
crate::db::InternDatabaseStorage,
crate::db::DefDatabaseStorage
)]
@@ -40,8 +40,8 @@ impl Default for TestDB {
}
}
-impl Upcast<dyn AstDatabase> for TestDB {
- fn upcast(&self) -> &(dyn AstDatabase + 'static) {
+impl Upcast<dyn ExpandDatabase> for TestDB {
+ fn upcast(&self) -> &(dyn ExpandDatabase + 'static) {
&*self
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs
index 9652b01b9..8e30f429a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs
@@ -116,7 +116,7 @@ pub enum TypeRef {
Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability),
// FIXME: for full const generics, the latter element (length) here is going to have to be an
// expression that is further lowered later in hir_ty.
- Array(Box<TypeRef>, ConstScalarOrPath),
+ Array(Box<TypeRef>, ConstRefOrPath),
Slice(Box<TypeRef>),
/// A fn pointer. Last element of the vector is the return type.
Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/, bool /*is_unsafe*/),
@@ -188,7 +188,7 @@ impl TypeRef {
// `hir_def::body::lower` to lower this into an `Expr` and then evaluate it at the
// `hir_ty` level, which would allow knowing the type of:
// let v: [u8; 2 + 2] = [0u8; 4];
- let len = ConstScalarOrPath::from_expr_opt(inner.expr());
+ let len = ConstRefOrPath::from_expr_opt(inner.expr());
TypeRef::Array(Box::new(TypeRef::from_ast_opt(ctx, inner.ty())), len)
}
ast::Type::SliceType(inner) => {
@@ -378,25 +378,25 @@ impl TypeBound {
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum ConstScalarOrPath {
- Scalar(ConstScalar),
+pub enum ConstRefOrPath {
+ Scalar(ConstRef),
Path(Name),
}
-impl std::fmt::Display for ConstScalarOrPath {
+impl std::fmt::Display for ConstRefOrPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
- ConstScalarOrPath::Scalar(s) => s.fmt(f),
- ConstScalarOrPath::Path(n) => n.fmt(f),
+ ConstRefOrPath::Scalar(s) => s.fmt(f),
+ ConstRefOrPath::Path(n) => n.fmt(f),
}
}
}
-impl ConstScalarOrPath {
+impl ConstRefOrPath {
pub(crate) fn from_expr_opt(expr: Option<ast::Expr>) -> Self {
match expr {
Some(x) => Self::from_expr(x),
- None => Self::Scalar(ConstScalar::Unknown),
+ None => Self::Scalar(ConstRef::Unknown),
}
}
@@ -407,7 +407,7 @@ impl ConstScalarOrPath {
ast::Expr::PathExpr(p) => {
match p.path().and_then(|x| x.segment()).and_then(|x| x.name_ref()) {
Some(x) => Self::Path(x.as_name()),
- None => Self::Scalar(ConstScalar::Unknown),
+ None => Self::Scalar(ConstRef::Unknown),
}
}
ast::Expr::PrefixExpr(prefix_expr) => match prefix_expr.op_kind() {
@@ -415,8 +415,8 @@ impl ConstScalarOrPath {
let unsigned = Self::from_expr_opt(prefix_expr.expr());
// Add sign
match unsigned {
- Self::Scalar(ConstScalar::UInt(num)) => {
- Self::Scalar(ConstScalar::Int(-(num as i128)))
+ Self::Scalar(ConstRef::UInt(num)) => {
+ Self::Scalar(ConstRef::Int(-(num as i128)))
}
other => other,
}
@@ -425,22 +425,22 @@ impl ConstScalarOrPath {
},
ast::Expr::Literal(literal) => Self::Scalar(match literal.kind() {
ast::LiteralKind::IntNumber(num) => {
- num.value().map(ConstScalar::UInt).unwrap_or(ConstScalar::Unknown)
+ num.value().map(ConstRef::UInt).unwrap_or(ConstRef::Unknown)
}
ast::LiteralKind::Char(c) => {
- c.value().map(ConstScalar::Char).unwrap_or(ConstScalar::Unknown)
+ c.value().map(ConstRef::Char).unwrap_or(ConstRef::Unknown)
}
- ast::LiteralKind::Bool(f) => ConstScalar::Bool(f),
- _ => ConstScalar::Unknown,
+ ast::LiteralKind::Bool(f) => ConstRef::Bool(f),
+ _ => ConstRef::Unknown,
}),
- _ => Self::Scalar(ConstScalar::Unknown),
+ _ => Self::Scalar(ConstRef::Unknown),
}
}
}
/// A concrete constant value
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum ConstScalar {
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum ConstRef {
Int(i128),
UInt(u128),
Bool(bool),
@@ -454,18 +454,18 @@ pub enum ConstScalar {
Unknown,
}
-impl ConstScalar {
+impl ConstRef {
pub fn builtin_type(&self) -> BuiltinType {
match self {
- ConstScalar::UInt(_) | ConstScalar::Unknown => BuiltinType::Uint(BuiltinUint::U128),
- ConstScalar::Int(_) => BuiltinType::Int(BuiltinInt::I128),
- ConstScalar::Char(_) => BuiltinType::Char,
- ConstScalar::Bool(_) => BuiltinType::Bool,
+ ConstRef::UInt(_) | ConstRef::Unknown => BuiltinType::Uint(BuiltinUint::U128),
+ ConstRef::Int(_) => BuiltinType::Int(BuiltinInt::I128),
+ ConstRef::Char(_) => BuiltinType::Char,
+ ConstRef::Bool(_) => BuiltinType::Bool,
}
}
}
-impl From<Literal> for ConstScalar {
+impl From<Literal> for ConstRef {
fn from(literal: Literal) -> Self {
match literal {
Literal::Char(c) => Self::Char(c),
@@ -477,14 +477,14 @@ impl From<Literal> for ConstScalar {
}
}
-impl std::fmt::Display for ConstScalar {
+impl std::fmt::Display for ConstRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
- ConstScalar::Int(num) => num.fmt(f),
- ConstScalar::UInt(num) => num.fmt(f),
- ConstScalar::Bool(flag) => flag.fmt(f),
- ConstScalar::Char(c) => write!(f, "'{c}'"),
- ConstScalar::Unknown => f.write_char('_'),
+ ConstRef::Int(num) => num.fmt(f),
+ ConstRef::UInt(num) => num.fmt(f),
+ ConstRef::Bool(flag) => flag.fmt(f),
+ ConstRef::Char(c) => write!(f, "'{c}'"),
+ ConstRef::Unknown => f.write_char('_'),
}
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
index 087268a9e..ab76ed43d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
@@ -11,7 +11,7 @@ use crate::{
nameres::DefMap,
path::{ModPath, PathKind},
resolver::HasResolver,
- ConstId, FunctionId, HasModule, LocalFieldId, ModuleId, VariantId,
+ ConstId, FunctionId, HasModule, LocalFieldId, LocalModuleId, ModuleId, VariantId,
};
/// Visibility of an item, not yet resolved.
@@ -120,7 +120,7 @@ impl Visibility {
self,
db: &dyn DefDatabase,
def_map: &DefMap,
- mut from_module: crate::LocalModuleId,
+ mut from_module: LocalModuleId,
) -> bool {
let mut to_module = match self {
Visibility::Module(m) => m,
@@ -131,20 +131,23 @@ impl Visibility {
// visibility as the containing module (even though no items are directly nameable from
// there, getting this right is important for method resolution).
// In that case, we adjust the visibility of `to_module` to point to the containing module.
+
// Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
// currently computing, so we must not call the `def_map` query for it.
- let arc;
- let to_module_def_map =
- if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
- cov_mark::hit!(is_visible_from_same_block_def_map);
- def_map
- } else {
- arc = to_module.def_map(db);
- &arc
- };
- let is_block_root = matches!(to_module.block, Some(_) if to_module_def_map[to_module.local_id].parent.is_none());
- if is_block_root {
- to_module = to_module_def_map.containing_module(to_module.local_id).unwrap();
+ let mut arc;
+ loop {
+ let to_module_def_map =
+ if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
+ cov_mark::hit!(is_visible_from_same_block_def_map);
+ def_map
+ } else {
+ arc = to_module.def_map(db);
+ &arc
+ };
+ match to_module_def_map.parent() {
+ Some(parent) => to_module = parent,
+ None => break,
+ }
}
// from_module needs to be a descendant of to_module