Skip to content

Node-ify lifetimes #6896

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/assists/src/handlers/generate_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()
if let Some(type_params) = type_params {
let lifetime_params = type_params
.lifetime_params()
.filter_map(|it| it.lifetime_token())
.filter_map(|it| it.lifetime())
.map(|it| it.text().clone());
let type_params = type_params
.type_params()
Expand Down
2 changes: 1 addition & 1 deletion crates/assists/src/handlers/generate_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ fn generate_impl_text(strukt: &ast::Struct, code: &str) -> String {
if let Some(type_params) = type_params {
let lifetime_params = type_params
.lifetime_params()
.filter_map(|it| it.lifetime_token())
.filter_map(|it| it.lifetime())
.map(|it| it.text().clone());
let type_params =
type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
Expand Down
21 changes: 9 additions & 12 deletions crates/assists/src/handlers/introduce_named_lifetime.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_hash::FxHashSet;
use syntax::{
ast::{self, GenericParamsOwner, NameOwner},
AstNode, SyntaxKind, TextRange, TextSize,
AstNode, TextRange, TextSize,
};

use crate::{assist_context::AssistBuilder, AssistContext, AssistId, AssistKind, Assists};
Expand Down Expand Up @@ -35,13 +35,12 @@ static ASSIST_LABEL: &str = "Introduce named lifetime";
// FIXME: How can we handle renaming any one of multiple anonymous lifetimes?
// FIXME: should also add support for the case fun(f: &Foo) -> &<|>Foo
pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let lifetime_token = ctx
.find_token_syntax_at_offset(SyntaxKind::LIFETIME)
.filter(|lifetime| lifetime.text() == "'_")?;
if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::Fn::cast) {
generate_fn_def_assist(acc, &fn_def, lifetime_token.text_range())
} else if let Some(impl_def) = lifetime_token.ancestors().find_map(ast::Impl::cast) {
generate_impl_def_assist(acc, &impl_def, lifetime_token.text_range())
let lifetime =
ctx.find_node_at_offset::<ast::Lifetime>().filter(|lifetime| lifetime.text() == "'_")?;
if let Some(fn_def) = lifetime.syntax().ancestors().find_map(ast::Fn::cast) {
generate_fn_def_assist(acc, &fn_def, lifetime.lifetime_ident_token()?.text_range())
} else if let Some(impl_def) = lifetime.syntax().ancestors().find_map(ast::Impl::cast) {
generate_impl_def_assist(acc, &impl_def, lifetime.lifetime_ident_token()?.text_range())
} else {
None
}
Expand All @@ -58,7 +57,7 @@ fn generate_fn_def_assist(
let end_of_fn_ident = fn_def.name()?.ident_token()?.text_range().end();
let self_param =
// use the self if it's a reference and has no explicit lifetime
param_list.self_param().filter(|p| p.lifetime_token().is_none() && p.amp_token().is_some());
param_list.self_param().filter(|p| p.lifetime().is_none() && p.amp_token().is_some());
// compute the location which implicitly has the same lifetime as the anonymous lifetime
let loc_needing_lifetime = if let Some(self_param) = self_param {
// if we have a self reference, use that
Expand All @@ -68,9 +67,7 @@ fn generate_fn_def_assist(
let fn_params_without_lifetime: Vec<_> = param_list
.params()
.filter_map(|param| match param.ty() {
Some(ast::Type::RefType(ascribed_type))
if ascribed_type.lifetime_token() == None =>
{
Some(ast::Type::RefType(ascribed_type)) if ascribed_type.lifetime().is_none() => {
Some(ascribed_type.amp_token()?.text_range().end())
}
_ => None,
Expand Down
2 changes: 1 addition & 1 deletion crates/hir/src/code_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ impl MacroDef {
/// defines this macro. The reasons for this is that macros are expanded
/// early, in `hir_expand`, where modules simply do not exist yet.
pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
let krate = self.id.krate?;
let krate = self.id.krate;
let module_id = db.crate_def_map(krate).root;
Some(Module::new(Crate { id: krate }, module_id))
}
Expand Down
4 changes: 2 additions & 2 deletions crates/hir/src/has_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ impl HasSource for TypeAlias {
}
}
impl HasSource for MacroDef {
type Ast = ast::MacroRules;
fn source(self, db: &dyn HirDatabase) -> InFile<ast::MacroRules> {
type Ast = ast::Macro;
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Macro> {
InFile {
file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id,
value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()),
Expand Down
17 changes: 6 additions & 11 deletions crates/hir/src/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.descend_node_at_offset(node, offset).find_map(N::cast)
}

// FIXME: Replace the SyntaxToken with a typed ast Node/Token
pub fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> {
self.imp.resolve_lifetime_param(lifetime_token)
pub fn resolve_lifetime_param(&self, lifetime: &ast::Lifetime) -> Option<LifetimeParam> {
self.imp.resolve_lifetime_param(lifetime)
}

pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
Expand Down Expand Up @@ -402,13 +401,9 @@ impl<'db> SemanticsImpl<'db> {
.kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
}

// FIXME: Replace the SyntaxToken with a typed ast Node/Token
fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> {
if lifetime_token.kind() != syntax::SyntaxKind::LIFETIME {
return None;
}
let lifetime_text = lifetime_token.text();
let lifetime_param = lifetime_token.parent().ancestors().find_map(|syn| {
fn resolve_lifetime_param(&self, lifetime: &ast::Lifetime) -> Option<LifetimeParam> {
let text = lifetime.text();
let lifetime_param = lifetime.syntax().ancestors().find_map(|syn| {
let gpl = match_ast! {
match syn {
ast::Fn(it) => it.generic_param_list()?,
Expand All @@ -424,7 +419,7 @@ impl<'db> SemanticsImpl<'db> {
}
};
gpl.lifetime_params()
.find(|tp| tp.lifetime_token().as_ref().map(|lt| lt.text()) == Some(lifetime_text))
.find(|tp| tp.lifetime().as_ref().map(|lt| lt.text()) == Some(text))
})?;
let src = self.find_file(lifetime_param.syntax().clone()).with_value(lifetime_param);
ToDef::to_def(self, src)
Expand Down
4 changes: 2 additions & 2 deletions crates/hir/src/semantics/source_to_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ impl SourceToDefCtx<'_, '_> {
let file_id = src.file_id.original_file(self.db.upcast());
let krate = self.file_to_def(file_id)?.krate;
let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value);
let ast_id = Some(AstId::new(src.file_id, file_ast_id));
Some(MacroDefId { krate: Some(krate), ast_id, kind, local_inner: false })
let ast_id = Some(AstId::new(src.file_id, file_ast_id.upcast()));
Some(MacroDefId { krate, ast_id, kind, local_inner: false })
}

pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
Expand Down
31 changes: 12 additions & 19 deletions crates/hir_def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,7 @@ impl ExprCollector<'_> {
let res = self.collect_block(block);
match &mut self.body.exprs[res] {
Expr::Block { label: block_label, .. } => {
*block_label =
label.lifetime_token().map(|t| Name::new_lifetime(&t))
*block_label = label.lifetime().map(|t| Name::new_lifetime(&t))
}
_ => unreachable!(),
}
Expand All @@ -254,10 +253,7 @@ impl ExprCollector<'_> {
self.alloc_expr(
Expr::Loop {
body,
label: e
.label()
.and_then(|l| l.lifetime_token())
.map(|l| Name::new_lifetime(&l)),
label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
},
syntax_ptr,
)
Expand Down Expand Up @@ -288,7 +284,7 @@ impl ExprCollector<'_> {
body: match_expr,
label: e
.label()
.and_then(|l| l.lifetime_token())
.and_then(|l| l.lifetime())
.map(|l| Name::new_lifetime(&l)),
},
syntax_ptr,
Expand All @@ -301,10 +297,7 @@ impl ExprCollector<'_> {
Expr::While {
condition,
body,
label: e
.label()
.and_then(|l| l.lifetime_token())
.map(|l| Name::new_lifetime(&l)),
label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
},
syntax_ptr,
)
Expand All @@ -318,10 +311,7 @@ impl ExprCollector<'_> {
iterable,
pat,
body,
label: e
.label()
.and_then(|l| l.lifetime_token())
.map(|l| Name::new_lifetime(&l)),
label: e.label().and_then(|l| l.lifetime()).map(|l| Name::new_lifetime(&l)),
},
syntax_ptr,
)
Expand Down Expand Up @@ -380,13 +370,13 @@ impl ExprCollector<'_> {
self.alloc_expr(path, syntax_ptr)
}
ast::Expr::ContinueExpr(e) => self.alloc_expr(
Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
Expr::Continue { label: e.lifetime().map(|l| Name::new_lifetime(&l)) },
syntax_ptr,
),
ast::Expr::BreakExpr(e) => {
let expr = e.expr().map(|e| self.collect_expr(e));
self.alloc_expr(
Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
Expr::Break { expr, label: e.lifetime().map(|l| Name::new_lifetime(&l)) },
syntax_ptr,
)
}
Expand Down Expand Up @@ -772,7 +762,10 @@ impl ExprCollector<'_> {
| ast::Item::Module(_)
| ast::Item::MacroCall(_) => return None,
ast::Item::MacroRules(def) => {
return Some(Either::Right(def));
return Some(Either::Right(ast::Macro::from(def)));
}
ast::Item::MacroDef(def) => {
return Some(Either::Right(ast::Macro::from(def)));
}
};

Expand Down Expand Up @@ -800,7 +793,7 @@ impl ExprCollector<'_> {
}
Either::Right(e) => {
let mac = MacroDefId {
krate: Some(self.expander.module.krate),
krate: self.expander.module.krate,
ast_id: Some(self.expander.ast_id(&e)),
kind: MacroDefKind::Declarative,
local_inner: false,
Expand Down
9 changes: 4 additions & 5 deletions crates/hir_def/src/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,8 @@ impl GenericParams {
self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref));
}
for lifetime_param in params.lifetime_params() {
let name = lifetime_param
.lifetime_token()
.map_or_else(Name::missing, |tok| Name::new_lifetime(&tok));
let name =
lifetime_param.lifetime().map_or_else(Name::missing, |lt| Name::new_lifetime(&lt));
let param = LifetimeParamData { name: name.clone() };
let param_id = self.lifetimes.alloc(param);
sm.lifetime_params.insert(param_id, lifetime_param.clone());
Expand All @@ -275,8 +274,8 @@ impl GenericParams {
for pred in where_clause.predicates() {
let target = if let Some(type_ref) = pred.ty() {
Either::Left(TypeRef::from_ast(lower_ctx, type_ref))
} else if let Some(lifetime_tok) = pred.lifetime_token() {
Either::Right(LifetimeRef::from_token(lifetime_tok))
} else if let Some(lifetime) = pred.lifetime() {
Either::Right(LifetimeRef::new(&lifetime))
} else {
continue;
};
Expand Down
2 changes: 1 addition & 1 deletion crates/hir_def/src/item_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ impl ItemInNs {
ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate,
ModuleDefId::BuiltinType(_) => return None,
},
ItemInNs::Macros(id) => return id.krate,
ItemInNs::Macros(id) => return Some(id.krate),
})
}
}
20 changes: 18 additions & 2 deletions crates/hir_def/src/item_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ impl ItemTree {
mods,
macro_calls,
macro_rules,
macro_defs,
exprs,
vis,
generics,
Expand All @@ -164,6 +165,7 @@ impl ItemTree {
mods.shrink_to_fit();
macro_calls.shrink_to_fit();
macro_rules.shrink_to_fit();
macro_defs.shrink_to_fit();
exprs.shrink_to_fit();

vis.arena.shrink_to_fit();
Expand Down Expand Up @@ -283,6 +285,7 @@ struct ItemTreeData {
mods: Arena<Mod>,
macro_calls: Arena<MacroCall>,
macro_rules: Arena<MacroRules>,
macro_defs: Arena<MacroDef>,
exprs: Arena<Expr>,

vis: ItemVisibilities,
Expand Down Expand Up @@ -431,6 +434,7 @@ mod_items! {
Mod in mods -> ast::Module,
MacroCall in macro_calls -> ast::MacroCall,
MacroRules in macro_rules -> ast::MacroRules,
MacroDef in macro_defs -> ast::MacroDef,
}

macro_rules! impl_index {
Expand Down Expand Up @@ -640,7 +644,7 @@ pub struct MacroCall {

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct MacroRules {
/// For `macro_rules!` declarations, this is the name of the declared macro.
/// The name of the declared macro.
pub name: Name,
/// Has `#[macro_export]`.
pub is_export: bool,
Expand All @@ -651,6 +655,16 @@ pub struct MacroRules {
pub ast_id: FileAstId<ast::MacroRules>,
}

/// "Macros 2.0" macro definition.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct MacroDef {
pub name: Name,
pub visibility: RawVisibilityId,
/// Has `#[rustc_builtin_macro]`.
pub is_builtin: bool,
pub ast_id: FileAstId<ast::MacroDef>,
}

// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
// lengths, but we don't do much with them yet.
#[derive(Debug, Clone, Eq, PartialEq)]
Expand Down Expand Up @@ -680,7 +694,8 @@ impl ModItem {
| ModItem::Trait(_)
| ModItem::Impl(_)
| ModItem::Mod(_)
| ModItem::MacroRules(_) => None,
| ModItem::MacroRules(_)
| ModItem::MacroDef(_) => None,
ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
Expand Down Expand Up @@ -708,6 +723,7 @@ impl ModItem {
ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(),
}
}
}
Expand Down
20 changes: 17 additions & 3 deletions crates/hir_def/src/item_tree/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ impl Ctx {
| ast::Item::ExternCrate(_)
| ast::Item::Use(_)
| ast::Item::MacroCall(_)
| ast::Item::MacroRules(_) => {}
| ast::Item::MacroRules(_)
| ast::Item::MacroDef(_) => {}
};

let attrs = Attrs::new(item, &self.hygiene);
Expand All @@ -122,6 +123,7 @@ impl Ctx {
ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into),
ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into),
ast::Item::ExternBlock(ast) => {
Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
}
Expand Down Expand Up @@ -298,12 +300,12 @@ impl Ctx {
ast::SelfParamKind::Owned => self_type,
ast::SelfParamKind::Ref => TypeRef::Reference(
Box::new(self_type),
self_param.lifetime_token().map(LifetimeRef::from_token),
self_param.lifetime().as_ref().map(LifetimeRef::new),
Mutability::Shared,
),
ast::SelfParamKind::MutRef => TypeRef::Reference(
Box::new(self_type),
self_param.lifetime_token().map(LifetimeRef::from_token),
self_param.lifetime().as_ref().map(LifetimeRef::new),
Mutability::Mut,
),
}
Expand Down Expand Up @@ -561,6 +563,18 @@ impl Ctx {
Some(id(self.data().macro_rules.alloc(res)))
}

fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> {
let name = m.name().map(|it| it.as_name())?;
let attrs = Attrs::new(m, &self.hygiene);

let ast_id = self.source_ast_id_map.ast_id(m);
let visibility = self.lower_visibility(m);

let is_builtin = attrs.by_key("rustc_builtin_macro").exists();
let res = MacroDef { name, is_builtin, ast_id, visibility };
Some(id(self.data().macro_defs.alloc(res)))
}

fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
block.extern_item_list().map_or(Vec::new(), |list| {
list.extern_items()
Expand Down
Loading