mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
Merge commit 'baee6b338b
' into sync-from-ra
This commit is contained in:
parent
0155385b57
commit
aa55ce9567
139 changed files with 4248 additions and 1042 deletions
|
@ -485,6 +485,7 @@ impl AttrsWithOwner {
|
|||
},
|
||||
AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it),
|
||||
AttrDefId::ExternCrateId(it) => attrs_from_item_tree_loc(db, it),
|
||||
AttrDefId::UseId(it) => attrs_from_item_tree_loc(db, it),
|
||||
};
|
||||
|
||||
let attrs = raw_attrs.filter(db.upcast(), def.krate(db));
|
||||
|
@ -570,6 +571,7 @@ impl AttrsWithOwner {
|
|||
},
|
||||
AttrDefId::ExternBlockId(id) => any_has_attrs(db, id),
|
||||
AttrDefId::ExternCrateId(id) => any_has_attrs(db, id),
|
||||
AttrDefId::UseId(id) => any_has_attrs(db, id),
|
||||
};
|
||||
|
||||
AttrSourceMap::new(owner.as_ref().map(|node| node as &dyn HasAttrs))
|
||||
|
|
|
@ -313,13 +313,7 @@ impl ExprCollector<'_> {
|
|||
let body = self.collect_labelled_block_opt(label, e.loop_body());
|
||||
self.alloc_expr(Expr::Loop { body, label }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::WhileExpr(e) => {
|
||||
let label = e.label().map(|label| self.collect_label(label));
|
||||
let body = self.collect_labelled_block_opt(label, e.loop_body());
|
||||
let condition = self.collect_expr_opt(e.condition());
|
||||
|
||||
self.alloc_expr(Expr::While { condition, body, label }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::WhileExpr(e) => self.collect_while_loop(syntax_ptr, e),
|
||||
ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e),
|
||||
ast::Expr::CallExpr(e) => {
|
||||
let is_rustc_box = {
|
||||
|
@ -731,6 +725,32 @@ impl ExprCollector<'_> {
|
|||
expr_id
|
||||
}
|
||||
|
||||
/// Desugar `ast::WhileExpr` from: `[opt_ident]: while <cond> <body>` into:
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// [opt_ident]: loop {
|
||||
/// if <cond> {
|
||||
/// <body>
|
||||
/// }
|
||||
/// else {
|
||||
/// break;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
/// FIXME: Rustc wraps the condition in a construct equivalent to `{ let _t = <cond>; _t }`
|
||||
/// to preserve drop semantics. We should probably do the same in future.
|
||||
fn collect_while_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::WhileExpr) -> ExprId {
|
||||
let label = e.label().map(|label| self.collect_label(label));
|
||||
let body = self.collect_labelled_block_opt(label, e.loop_body());
|
||||
let condition = self.collect_expr_opt(e.condition());
|
||||
let break_expr =
|
||||
self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr.clone());
|
||||
let if_expr = self.alloc_expr(
|
||||
Expr::If { condition, then_branch: body, else_branch: Some(break_expr) },
|
||||
syntax_ptr.clone(),
|
||||
);
|
||||
self.alloc_expr(Expr::Loop { body: if_expr, label }, syntax_ptr)
|
||||
}
|
||||
|
||||
/// Desugar `ast::ForExpr` from: `[opt_ident]: for <pat> in <head> <body>` into:
|
||||
/// ```ignore (pseudo-rust)
|
||||
/// match IntoIterator::into_iter(<head>) {
|
||||
|
@ -893,15 +913,14 @@ impl ExprCollector<'_> {
|
|||
self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
|
||||
}
|
||||
|
||||
fn collect_macro_call<F, T, U>(
|
||||
fn collect_macro_call<T, U>(
|
||||
&mut self,
|
||||
mcall: ast::MacroCall,
|
||||
syntax_ptr: AstPtr<ast::MacroCall>,
|
||||
record_diagnostics: bool,
|
||||
collector: F,
|
||||
collector: impl FnOnce(&mut Self, Option<T>) -> U,
|
||||
) -> U
|
||||
where
|
||||
F: FnOnce(&mut Self, Option<T>) -> U,
|
||||
T: ast::AstNode,
|
||||
{
|
||||
// File containing the macro call. Expansion errors will be attached here.
|
||||
|
|
|
@ -178,14 +178,6 @@ impl Printer<'_> {
|
|||
w!(self, "loop ");
|
||||
self.print_expr(*body);
|
||||
}
|
||||
Expr::While { condition, body, label } => {
|
||||
if let Some(lbl) = label {
|
||||
w!(self, "{}: ", self.body[*lbl].name.display(self.db));
|
||||
}
|
||||
w!(self, "while ");
|
||||
self.print_expr(*condition);
|
||||
self.print_expr(*body);
|
||||
}
|
||||
Expr::Call { callee, args, is_assignee_expr: _ } => {
|
||||
self.print_expr(*callee);
|
||||
w!(self, "(");
|
||||
|
|
|
@ -228,11 +228,6 @@ 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::While { condition, body: body_expr, label } => {
|
||||
let mut scope = scopes.new_labeled_scope(*scope, make_label(label));
|
||||
compute_expr_scopes(*condition, body, scopes, &mut scope);
|
||||
compute_expr_scopes(*body_expr, body, scopes, &mut scope);
|
||||
}
|
||||
Expr::Loop { body: body_expr, label } => {
|
||||
let mut scope = scopes.new_labeled_scope(*scope, make_label(label));
|
||||
compute_expr_scopes(*body_expr, body, scopes, &mut scope);
|
||||
|
|
|
@ -14,8 +14,8 @@ use crate::{
|
|||
item_scope::ItemScope,
|
||||
nameres::DefMap,
|
||||
src::{HasChildSource, HasSource},
|
||||
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, MacroId,
|
||||
ModuleDefId, ModuleId, TraitId, VariantId,
|
||||
AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FieldId, ImplId,
|
||||
Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, VariantId,
|
||||
};
|
||||
|
||||
pub trait ChildBySource {
|
||||
|
@ -91,6 +91,8 @@ impl ChildBySource for ItemScope {
|
|||
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
|
||||
self.declarations().for_each(|item| add_module_def(db, res, file_id, item));
|
||||
self.impls().for_each(|imp| add_impl(db, res, file_id, imp));
|
||||
self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext));
|
||||
self.use_decls().for_each(|ext| add_use(db, res, file_id, ext));
|
||||
self.unnamed_consts().for_each(|konst| {
|
||||
let loc = konst.lookup(db);
|
||||
if loc.id.file_id() == file_id {
|
||||
|
@ -167,6 +169,23 @@ impl ChildBySource for ItemScope {
|
|||
map[keys::IMPL].insert(loc.source(db).value, imp)
|
||||
}
|
||||
}
|
||||
fn add_extern_crate(
|
||||
db: &dyn DefDatabase,
|
||||
map: &mut DynMap,
|
||||
file_id: HirFileId,
|
||||
ext: ExternCrateId,
|
||||
) {
|
||||
let loc = ext.lookup(db);
|
||||
if loc.id.file_id() == file_id {
|
||||
map[keys::EXTERN_CRATE].insert(loc.source(db).value, ext)
|
||||
}
|
||||
}
|
||||
fn add_use(db: &dyn DefDatabase, map: &mut DynMap, file_id: HirFileId, ext: UseId) {
|
||||
let loc = ext.lookup(db);
|
||||
if loc.id.file_id() == file_id {
|
||||
map[keys::USE].insert(loc.source(db).value, ext)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
pub mod adt;
|
||||
|
||||
use base_db::CrateId;
|
||||
use hir_expand::{
|
||||
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
|
||||
};
|
||||
|
@ -467,6 +468,7 @@ pub struct ExternCrateDeclData {
|
|||
pub name: Name,
|
||||
pub alias: Option<ImportAlias>,
|
||||
pub visibility: RawVisibility,
|
||||
pub crate_id: Option<CrateId>,
|
||||
}
|
||||
|
||||
impl ExternCrateDeclData {
|
||||
|
@ -478,10 +480,21 @@ impl ExternCrateDeclData {
|
|||
let item_tree = loc.id.item_tree(db);
|
||||
let extern_crate = &item_tree[loc.id.value];
|
||||
|
||||
let name = extern_crate.name.clone();
|
||||
let crate_id = if name == hir_expand::name![self] {
|
||||
Some(loc.container.krate())
|
||||
} else {
|
||||
db.crate_def_map(loc.container.krate())
|
||||
.extern_prelude()
|
||||
.find(|&(prelude_name, ..)| *prelude_name == name)
|
||||
.map(|(_, root)| root.krate())
|
||||
};
|
||||
|
||||
Arc::new(Self {
|
||||
name: extern_crate.name.clone(),
|
||||
visibility: item_tree[extern_crate.visibility].clone(),
|
||||
alias: extern_crate.alias.clone(),
|
||||
crate_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,17 +23,17 @@ use crate::{
|
|||
visibility::{self, Visibility},
|
||||
AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId,
|
||||
EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId,
|
||||
FunctionLoc, GenericDefId, ImplId, ImplLoc, ImportId, ImportLoc, InTypeConstId, InTypeConstLoc,
|
||||
LocalEnumVariantId, LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc,
|
||||
ProcMacroId, ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId,
|
||||
TraitAliasLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId,
|
||||
FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, InTypeConstLoc, LocalEnumVariantId,
|
||||
LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, ProcMacroId, ProcMacroLoc,
|
||||
StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc,
|
||||
TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId,
|
||||
};
|
||||
|
||||
#[salsa::query_group(InternDatabaseStorage)]
|
||||
pub trait InternDatabase: SourceDatabase {
|
||||
// region: items
|
||||
#[salsa::interned]
|
||||
fn intern_import(&self, loc: ImportLoc) -> ImportId;
|
||||
fn intern_use(&self, loc: UseLoc) -> UseId;
|
||||
#[salsa::interned]
|
||||
fn intern_extern_crate(&self, loc: ExternCrateLoc) -> ExternCrateId;
|
||||
#[salsa::interned]
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
dyn_map::{DynMap, Policy},
|
||||
ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId, LifetimeParamId,
|
||||
Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId,
|
||||
TypeOrConstParamId, UnionId,
|
||||
TypeOrConstParamId, UnionId, UseId,
|
||||
};
|
||||
|
||||
pub type Key<K, V> = crate::dyn_map::Key<K, V, AstPtrPolicy<K, V>>;
|
||||
|
@ -26,6 +26,7 @@ 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();
|
||||
pub const EXTERN_CRATE: Key<ast::ExternCrate, ExternCrateId> = Key::new();
|
||||
pub const USE: Key<ast::Use, UseId> = Key::new();
|
||||
|
||||
pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
|
||||
pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
|
||||
|
|
|
@ -164,18 +164,26 @@ impl Expander {
|
|||
return ExpandResult { value: None, err };
|
||||
};
|
||||
|
||||
Self::enter_expand_inner(db, call_id, err).map(|value| {
|
||||
value.and_then(|InFile { file_id, value }| {
|
||||
let parse = value.cast::<T>()?;
|
||||
let res = Self::enter_expand_inner(db, call_id, err);
|
||||
match res.err {
|
||||
// If proc-macro is disabled or unresolved, we want to expand to a missing expression
|
||||
// instead of an empty tree which might end up in an empty block.
|
||||
Some(ExpandError::UnresolvedProcMacro(_)) => res.map(|_| None),
|
||||
_ => res.map(|value| {
|
||||
value.and_then(|InFile { file_id, value }| {
|
||||
let parse = value.cast::<T>()?;
|
||||
|
||||
self.recursion_depth += 1;
|
||||
self.hygiene = Hygiene::new(db.upcast(), file_id);
|
||||
let old_file_id = std::mem::replace(&mut self.current_file_id, file_id);
|
||||
let mark =
|
||||
Mark { file_id: old_file_id, bomb: DropBomb::new("expansion mark dropped") };
|
||||
Some((mark, parse))
|
||||
})
|
||||
})
|
||||
self.recursion_depth += 1;
|
||||
self.hygiene = Hygiene::new(db.upcast(), file_id);
|
||||
let old_file_id = std::mem::replace(&mut self.current_file_id, file_id);
|
||||
let mark = Mark {
|
||||
file_id: old_file_id,
|
||||
bomb: DropBomb::new("expansion mark dropped"),
|
||||
};
|
||||
Some((mark, parse))
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -191,11 +191,6 @@ pub enum Expr {
|
|||
body: ExprId,
|
||||
label: Option<LabelId>,
|
||||
},
|
||||
While {
|
||||
condition: ExprId,
|
||||
body: ExprId,
|
||||
label: Option<LabelId>,
|
||||
},
|
||||
Call {
|
||||
callee: ExprId,
|
||||
args: Box<[ExprId]>,
|
||||
|
@ -379,10 +374,6 @@ impl Expr {
|
|||
}
|
||||
}
|
||||
Expr::Loop { body, .. } => f(*body),
|
||||
Expr::While { condition, body, .. } => {
|
||||
f(*condition);
|
||||
f(*body);
|
||||
}
|
||||
Expr::Call { callee, args, .. } => {
|
||||
f(*callee);
|
||||
args.iter().copied().for_each(f);
|
||||
|
|
|
@ -16,6 +16,7 @@ use syntax::ast;
|
|||
use crate::{
|
||||
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId,
|
||||
ExternCrateId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
|
||||
UseId,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -113,6 +114,17 @@ impl ItemScope {
|
|||
self.declarations.iter().copied()
|
||||
}
|
||||
|
||||
pub fn extern_crate_decls(
|
||||
&self,
|
||||
) -> impl Iterator<Item = ExternCrateId> + ExactSizeIterator + '_ {
|
||||
self.extern_crate_decls.iter().copied()
|
||||
}
|
||||
|
||||
pub fn use_decls(&self) -> impl Iterator<Item = UseId> + ExactSizeIterator + '_ {
|
||||
// FIXME: to be implemented
|
||||
std::iter::empty()
|
||||
}
|
||||
|
||||
pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
|
||||
self.impls.iter().copied()
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ impl ItemTree {
|
|||
fn shrink_to_fit(&mut self) {
|
||||
if let Some(data) = &mut self.data {
|
||||
let ItemTreeData {
|
||||
imports,
|
||||
uses,
|
||||
extern_crates,
|
||||
extern_blocks,
|
||||
functions,
|
||||
|
@ -211,7 +211,7 @@ impl ItemTree {
|
|||
vis,
|
||||
} = &mut **data;
|
||||
|
||||
imports.shrink_to_fit();
|
||||
uses.shrink_to_fit();
|
||||
extern_crates.shrink_to_fit();
|
||||
extern_blocks.shrink_to_fit();
|
||||
functions.shrink_to_fit();
|
||||
|
@ -262,7 +262,7 @@ static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(P
|
|||
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
struct ItemTreeData {
|
||||
imports: Arena<Import>,
|
||||
uses: Arena<Use>,
|
||||
extern_crates: Arena<ExternCrate>,
|
||||
extern_blocks: Arena<ExternBlock>,
|
||||
functions: Arena<Function>,
|
||||
|
@ -486,7 +486,7 @@ macro_rules! mod_items {
|
|||
}
|
||||
|
||||
mod_items! {
|
||||
Import in imports -> ast::Use,
|
||||
Use in uses -> ast::Use,
|
||||
ExternCrate in extern_crates -> ast::ExternCrate,
|
||||
ExternBlock in extern_blocks -> ast::ExternBlock,
|
||||
Function in functions -> ast::Fn,
|
||||
|
@ -541,7 +541,7 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Import {
|
||||
pub struct Use {
|
||||
pub visibility: RawVisibilityId,
|
||||
pub ast_id: FileAstId<ast::Use>,
|
||||
pub use_tree: UseTree,
|
||||
|
@ -744,7 +744,7 @@ pub struct MacroDef {
|
|||
pub ast_id: FileAstId<ast::MacroDef>,
|
||||
}
|
||||
|
||||
impl Import {
|
||||
impl Use {
|
||||
/// Maps a `UseTree` contained in this import back to its AST node.
|
||||
pub fn use_tree_to_ast(
|
||||
&self,
|
||||
|
@ -870,7 +870,7 @@ macro_rules! impl_froms {
|
|||
impl ModItem {
|
||||
pub fn as_assoc_item(&self) -> Option<AssocItem> {
|
||||
match self {
|
||||
ModItem::Import(_)
|
||||
ModItem::Use(_)
|
||||
| ModItem::ExternCrate(_)
|
||||
| ModItem::ExternBlock(_)
|
||||
| ModItem::Struct(_)
|
||||
|
@ -892,7 +892,7 @@ impl ModItem {
|
|||
|
||||
pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
|
||||
match self {
|
||||
ModItem::Import(it) => tree[it.index].ast_id().upcast(),
|
||||
ModItem::Use(it) => tree[it.index].ast_id().upcast(),
|
||||
ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(),
|
||||
ModItem::ExternBlock(it) => tree[it.index].ast_id().upcast(),
|
||||
ModItem::Function(it) => tree[it.index].ast_id().upcast(),
|
||||
|
|
|
@ -502,13 +502,13 @@ impl<'a> Ctx<'a> {
|
|||
Some(id(self.data().impls.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_use(&mut self, use_item: &ast::Use) -> Option<FileItemTreeId<Import>> {
|
||||
fn lower_use(&mut self, use_item: &ast::Use) -> Option<FileItemTreeId<Use>> {
|
||||
let visibility = self.lower_visibility(use_item);
|
||||
let ast_id = self.source_ast_id_map.ast_id(use_item);
|
||||
let (use_tree, _) = lower_use_tree(self.db, self.hygiene(), use_item.use_tree()?)?;
|
||||
|
||||
let res = Import { visibility, ast_id, use_tree };
|
||||
Some(id(self.data().imports.alloc(res)))
|
||||
let res = Use { visibility, ast_id, use_tree };
|
||||
Some(id(self.data().uses.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_extern_crate(
|
||||
|
|
|
@ -198,8 +198,8 @@ impl Printer<'_> {
|
|||
self.print_attrs_of(item);
|
||||
|
||||
match item {
|
||||
ModItem::Import(it) => {
|
||||
let Import { visibility, use_tree, ast_id: _ } = &self.tree[it];
|
||||
ModItem::Use(it) => {
|
||||
let Use { visibility, use_tree, ast_id: _ } = &self.tree[it];
|
||||
self.print_visibility(*visibility);
|
||||
w!(self, "use ");
|
||||
self.print_use_tree(use_tree);
|
||||
|
|
|
@ -88,8 +88,8 @@ use crate::{
|
|||
builtin_type::BuiltinType,
|
||||
data::adt::VariantData,
|
||||
item_tree::{
|
||||
Const, Enum, ExternCrate, Function, Impl, Import, ItemTreeId, ItemTreeNode, MacroDef,
|
||||
MacroRules, Static, Struct, Trait, TraitAlias, TypeAlias, Union,
|
||||
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules,
|
||||
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -121,6 +121,12 @@ impl From<CrateRootModuleId> for ModuleDefId {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<CrateId> for CrateRootModuleId {
|
||||
fn from(krate: CrateId) -> Self {
|
||||
CrateRootModuleId { krate }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ModuleId> for CrateRootModuleId {
|
||||
type Error = ();
|
||||
|
||||
|
@ -318,9 +324,9 @@ type ImplLoc = ItemLoc<Impl>;
|
|||
impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct ImportId(salsa::InternId);
|
||||
type ImportLoc = ItemLoc<Import>;
|
||||
impl_intern!(ImportId, ImportLoc, intern_import, lookup_intern_import);
|
||||
pub struct UseId(salsa::InternId);
|
||||
type UseLoc = ItemLoc<Use>;
|
||||
impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct ExternCrateId(salsa::InternId);
|
||||
|
@ -836,6 +842,7 @@ pub enum AttrDefId {
|
|||
GenericParamId(GenericParamId),
|
||||
ExternBlockId(ExternBlockId),
|
||||
ExternCrateId(ExternCrateId),
|
||||
UseId(UseId),
|
||||
}
|
||||
|
||||
impl_from!(
|
||||
|
@ -1073,6 +1080,7 @@ impl AttrDefId {
|
|||
}
|
||||
AttrDefId::MacroId(it) => it.module(db).krate,
|
||||
AttrDefId::ExternCrateId(it) => it.lookup(db).container.krate,
|
||||
AttrDefId::UseId(it) => it.lookup(db).container.krate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1083,7 +1091,7 @@ pub trait AsMacroCall {
|
|||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
krate: CrateId,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId> + Copy,
|
||||
) -> Option<MacroCallId> {
|
||||
self.as_call_id_with_errors(db, krate, resolver).ok()?.value
|
||||
}
|
||||
|
@ -1092,7 +1100,7 @@ pub trait AsMacroCall {
|
|||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
krate: CrateId,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId> + Copy,
|
||||
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>;
|
||||
}
|
||||
|
||||
|
@ -1101,7 +1109,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
|
|||
&self,
|
||||
db: &dyn ExpandDatabase,
|
||||
krate: CrateId,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId> + Copy,
|
||||
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
|
||||
let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
|
||||
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
|
||||
|
@ -1112,12 +1120,13 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
|
|||
return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation")));
|
||||
};
|
||||
|
||||
macro_call_as_call_id_(
|
||||
macro_call_as_call_id_with_eager(
|
||||
db,
|
||||
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
|
||||
expands_to,
|
||||
krate,
|
||||
resolver,
|
||||
resolver,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1140,33 +1149,39 @@ fn macro_call_as_call_id(
|
|||
call: &AstIdWithPath<ast::MacroCall>,
|
||||
expand_to: ExpandTo,
|
||||
krate: CrateId,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId> + Copy,
|
||||
) -> Result<Option<MacroCallId>, UnresolvedMacro> {
|
||||
macro_call_as_call_id_(db, call, expand_to, krate, resolver).map(|res| res.value)
|
||||
macro_call_as_call_id_with_eager(db, call, expand_to, krate, resolver, resolver)
|
||||
.map(|res| res.value)
|
||||
}
|
||||
|
||||
fn macro_call_as_call_id_(
|
||||
fn macro_call_as_call_id_with_eager(
|
||||
db: &dyn ExpandDatabase,
|
||||
call: &AstIdWithPath<ast::MacroCall>,
|
||||
expand_to: ExpandTo,
|
||||
krate: CrateId,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||
resolver: impl FnOnce(path::ModPath) -> Option<MacroDefId>,
|
||||
eager_resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
|
||||
let def =
|
||||
resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?;
|
||||
|
||||
let res = if let MacroDefKind::BuiltInEager(..) = def.kind {
|
||||
let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db));
|
||||
expand_eager_macro_input(db, krate, macro_call, def, &resolver)?
|
||||
} else {
|
||||
ExpandResult {
|
||||
let res = match def.kind {
|
||||
MacroDefKind::BuiltInEager(..) => {
|
||||
let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db));
|
||||
expand_eager_macro_input(db, krate, macro_call, def, &|path| {
|
||||
eager_resolver(path).filter(MacroDefId::is_fn_like)
|
||||
})
|
||||
}
|
||||
_ if def.is_fn_like() => ExpandResult {
|
||||
value: Some(def.as_lazy_macro(
|
||||
db,
|
||||
krate,
|
||||
MacroCallKind::FnLike { ast_id: call.ast_id, expand_to },
|
||||
)),
|
||||
err: None,
|
||||
}
|
||||
},
|
||||
_ => return Err(UnresolvedMacro { path: call.path.clone() }),
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -1251,6 +1266,7 @@ fn derive_macro_as_call_id(
|
|||
resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>,
|
||||
) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> {
|
||||
let (macro_id, def_id) = resolver(item_attr.path.clone())
|
||||
.filter(|(_, def_id)| def_id.is_derive())
|
||||
.ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
|
||||
let call_id = def_id.as_lazy_macro(
|
||||
db.upcast(),
|
||||
|
|
|
@ -238,7 +238,7 @@ fn main() {
|
|||
/* error: expected expression */;
|
||||
/* error: expected expression, expected COMMA */;
|
||||
/* error: expected expression */::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(), ::core::fmt::Display::fmt), ]);
|
||||
/* error: expected expression, expected R_PAREN */;
|
||||
/* error: expected expression, expected expression */;
|
||||
::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(5), ::core::fmt::Display::fmt), ]);
|
||||
}
|
||||
"##]],
|
||||
|
|
|
@ -99,6 +99,30 @@ fn#19 main#20(#21)#21 {#22
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eager_expands_with_unresolved_within() {
|
||||
check(
|
||||
r#"
|
||||
#[rustc_builtin_macro]
|
||||
#[macro_export]
|
||||
macro_rules! format_args {}
|
||||
|
||||
fn main(foo: ()) {
|
||||
format_args!("{} {} {}", format_args!("{}", 0), foo, identity!(10), "bar")
|
||||
}
|
||||
"#,
|
||||
expect![[r##"
|
||||
#[rustc_builtin_macro]
|
||||
#[macro_export]
|
||||
macro_rules! format_args {}
|
||||
|
||||
fn main(foo: ()) {
|
||||
/* error: unresolved macro identity */::core::fmt::Arguments::new_v1(&["", " ", " ", ], &[::core::fmt::ArgumentV1::new(&(::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(0), ::core::fmt::Display::fmt), ])), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(foo), ::core::fmt::Display::fmt), ::core::fmt::ArgumentV1::new(&(identity!(10)), ::core::fmt::Display::fmt), ])
|
||||
}
|
||||
"##]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn token_mapping_eager() {
|
||||
check(
|
||||
|
@ -848,6 +872,37 @@ fn foo() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_type_path_is_transcribed_as_expr_path() {
|
||||
check(
|
||||
r#"
|
||||
macro_rules! m {
|
||||
($p:path) => { let $p; }
|
||||
}
|
||||
fn test() {
|
||||
m!(S)
|
||||
m!(S<i32>)
|
||||
m!(S<S<i32>>)
|
||||
m!(S<{ module::CONST < 42 }>)
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
macro_rules! m {
|
||||
($p:path) => { let $p; }
|
||||
}
|
||||
fn test() {
|
||||
let S;
|
||||
let S:: <i32> ;
|
||||
let S:: <S:: <i32>> ;
|
||||
let S:: < {
|
||||
module::CONST<42
|
||||
}
|
||||
> ;
|
||||
}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expr() {
|
||||
check(
|
||||
|
|
|
@ -38,7 +38,7 @@ use crate::{
|
|||
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
|
||||
MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
|
||||
},
|
||||
macro_call_as_call_id, macro_id_to_def_id,
|
||||
macro_call_as_call_id, macro_call_as_call_id_with_eager, macro_id_to_def_id,
|
||||
nameres::{
|
||||
diagnostics::DefDiagnostic,
|
||||
mod_resolution::ModDir,
|
||||
|
@ -52,10 +52,10 @@ use crate::{
|
|||
tt,
|
||||
visibility::{RawVisibility, Visibility},
|
||||
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId,
|
||||
ExternBlockLoc, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, ImportLoc, Intern,
|
||||
ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId,
|
||||
MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc,
|
||||
TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro,
|
||||
ExternBlockLoc, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId,
|
||||
LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, MacroRulesLoc,
|
||||
ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc,
|
||||
TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseLoc,
|
||||
};
|
||||
|
||||
static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
|
||||
|
@ -146,7 +146,7 @@ impl PartialResolvedImport {
|
|||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
enum ImportSource {
|
||||
Import { id: ItemTreeId<item_tree::Import>, use_tree: Idx<ast::UseTree> },
|
||||
Use { id: ItemTreeId<item_tree::Use>, use_tree: Idx<ast::UseTree> },
|
||||
ExternCrate(ItemTreeId<item_tree::ExternCrate>),
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ impl Import {
|
|||
db: &dyn DefDatabase,
|
||||
krate: CrateId,
|
||||
tree: &ItemTree,
|
||||
id: ItemTreeId<item_tree::Import>,
|
||||
id: ItemTreeId<item_tree::Use>,
|
||||
mut cb: impl FnMut(Self),
|
||||
) {
|
||||
let it = &tree[id.value];
|
||||
|
@ -181,7 +181,7 @@ impl Import {
|
|||
kind,
|
||||
is_prelude,
|
||||
is_macro_use: false,
|
||||
source: ImportSource::Import { id, use_tree: idx },
|
||||
source: ImportSource::Use { id, use_tree: idx },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1474,7 +1474,7 @@ impl DefCollector<'_> {
|
|||
}
|
||||
|
||||
for directive in &self.unresolved_imports {
|
||||
if let ImportSource::Import { id: import, use_tree } = directive.import.source {
|
||||
if let ImportSource::Use { id: import, use_tree } = directive.import.source {
|
||||
if matches!(
|
||||
(directive.import.path.segments().first(), &directive.import.path.kind),
|
||||
(Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate)
|
||||
|
@ -1576,12 +1576,10 @@ impl ModCollector<'_, '_> {
|
|||
|
||||
match item {
|
||||
ModItem::Mod(m) => self.collect_module(m, &attrs),
|
||||
ModItem::Import(import_id) => {
|
||||
let _import_id = ImportLoc {
|
||||
container: module,
|
||||
id: ItemTreeId::new(self.tree_id, import_id),
|
||||
}
|
||||
.intern(db);
|
||||
ModItem::Use(import_id) => {
|
||||
let _import_id =
|
||||
UseLoc { container: module, id: ItemTreeId::new(self.tree_id, import_id) }
|
||||
.intern(db);
|
||||
Import::from_use(
|
||||
db,
|
||||
krate,
|
||||
|
@ -2187,7 +2185,7 @@ impl ModCollector<'_, '_> {
|
|||
// scopes without eager expansion.
|
||||
|
||||
// Case 1: try to resolve macro calls with single-segment name and expand macro_rules
|
||||
if let Ok(res) = macro_call_as_call_id(
|
||||
if let Ok(res) = macro_call_as_call_id_with_eager(
|
||||
db.upcast(),
|
||||
&ast_id,
|
||||
mac.expand_to,
|
||||
|
@ -2210,19 +2208,34 @@ impl ModCollector<'_, '_> {
|
|||
.map(|it| macro_id_to_def_id(self.def_collector.db, it))
|
||||
})
|
||||
},
|
||||
) {
|
||||
// Legacy macros need to be expanded immediately, so that any macros they produce
|
||||
// are in scope.
|
||||
if let Some(val) = res {
|
||||
self.def_collector.collect_macro_expansion(
|
||||
|path| {
|
||||
let resolved_res = self.def_collector.def_map.resolve_path_fp_with_macro(
|
||||
db,
|
||||
ResolveMode::Other,
|
||||
self.module_id,
|
||||
val,
|
||||
self.macro_depth + 1,
|
||||
container,
|
||||
&path,
|
||||
BuiltinShadowMode::Module,
|
||||
Some(MacroSubNs::Bang),
|
||||
);
|
||||
}
|
||||
resolved_res.resolved_def.take_macros().map(|it| macro_id_to_def_id(db, it))
|
||||
},
|
||||
) {
|
||||
// FIXME: if there were errors, this mightve been in the eager expansion from an
|
||||
// unresolved macro, so we need to push this into late macro resolution. see fixme above
|
||||
if res.err.is_none() {
|
||||
// Legacy macros need to be expanded immediately, so that any macros they produce
|
||||
// are in scope.
|
||||
if let Some(val) = res.value {
|
||||
self.def_collector.collect_macro_expansion(
|
||||
self.module_id,
|
||||
val,
|
||||
self.macro_depth + 1,
|
||||
container,
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Case 2: resolve in module scope, expand during name resolution.
|
||||
|
|
|
@ -19,7 +19,7 @@ pub enum DefDiagnosticKind {
|
|||
|
||||
UnresolvedExternCrate { ast: AstId<ast::ExternCrate> },
|
||||
|
||||
UnresolvedImport { id: ItemTreeId<item_tree::Import>, index: Idx<ast::UseTree> },
|
||||
UnresolvedImport { id: ItemTreeId<item_tree::Use>, index: Idx<ast::UseTree> },
|
||||
|
||||
UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions },
|
||||
|
||||
|
@ -70,7 +70,7 @@ impl DefDiagnostic {
|
|||
|
||||
pub(super) fn unresolved_import(
|
||||
container: LocalModuleId,
|
||||
id: ItemTreeId<item_tree::Import>,
|
||||
id: ItemTreeId<item_tree::Use>,
|
||||
index: Idx<ast::UseTree>,
|
||||
) -> Self {
|
||||
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } }
|
||||
|
|
|
@ -213,17 +213,17 @@ pub type Ty = ();
|
|||
|
||||
for (_, res) in module_data.scope.resolutions() {
|
||||
match res.values.or(res.types).unwrap().0 {
|
||||
ModuleDefId::FunctionId(f) => drop(db.function_data(f)),
|
||||
ModuleDefId::FunctionId(f) => _ = db.function_data(f),
|
||||
ModuleDefId::AdtId(adt) => match adt {
|
||||
AdtId::StructId(it) => drop(db.struct_data(it)),
|
||||
AdtId::UnionId(it) => drop(db.union_data(it)),
|
||||
AdtId::EnumId(it) => drop(db.enum_data(it)),
|
||||
AdtId::StructId(it) => _ = db.struct_data(it),
|
||||
AdtId::UnionId(it) => _ = db.union_data(it),
|
||||
AdtId::EnumId(it) => _ = db.enum_data(it),
|
||||
},
|
||||
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::ConstId(it) => _ = db.const_data(it),
|
||||
ModuleDefId::StaticId(it) => _ = db.static_data(it),
|
||||
ModuleDefId::TraitId(it) => _ = db.trait_data(it),
|
||||
ModuleDefId::TraitAliasId(it) => _ = db.trait_alias_data(it),
|
||||
ModuleDefId::TypeAliasId(it) => _ = db.type_alias_data(it),
|
||||
ModuleDefId::EnumVariantId(_)
|
||||
| ModuleDefId::ModuleId(_)
|
||||
| ModuleDefId::MacroId(_)
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::{
|
|||
EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId,
|
||||
HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId,
|
||||
MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId,
|
||||
TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, VariantId,
|
||||
TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -1024,6 +1024,12 @@ impl HasResolver for ExternCrateId {
|
|||
}
|
||||
}
|
||||
|
||||
impl HasResolver for UseId {
|
||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||
self.lookup(db).container.resolver(db)
|
||||
}
|
||||
}
|
||||
|
||||
impl HasResolver for TypeOwnerId {
|
||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||
match self {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue