Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
| -rw-r--r-- | crates/hir/src/lib.rs | 114 |
1 files changed, 77 insertions, 37 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5eed7ecd5b..b922aa8e46 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -56,8 +56,8 @@ use hir_def::{ AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander, - MacroId, ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, - TypeOrConstParamId, TypeParamId, UnionId, + ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, TypeOrConstParamId, + TypeParamId, UnionId, }; use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind}; use hir_ty::{ @@ -122,7 +122,7 @@ pub use { visibility::Visibility, // FIXME: This is here since some queries take it as input that are used // outside of hir. - {AdtId, ModuleDefId}, + {AdtId, MacroId, ModuleDefId}, }, hir_expand::{ attrs::{Attr, AttrId}, @@ -754,7 +754,7 @@ impl Module { scope .declarations() .map(ModuleDef::from) - .chain(scope.unnamed_consts(db.upcast()).map(|id| ModuleDef::Const(Const::from(id)))) + .chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id)))) .collect() } @@ -1725,6 +1725,10 @@ impl DefWithBody { Ok(s) => s.map(|it| it.into()), Err(_) => continue, }, + mir::MirSpan::SelfParam => match source_map.self_param_syntax() { + Some(s) => s.map(|it| it.into()), + None => continue, + }, mir::MirSpan::Unknown => continue, }; acc.push( @@ -1776,6 +1780,11 @@ impl DefWithBody { Ok(s) => s.map(|it| it.into()), Err(_) => continue, }, + mir::MirSpan::SelfParam => match source_map.self_param_syntax() + { + Some(s) => s.map(|it| it.into()), + None => continue, + }, mir::MirSpan::Unknown => continue, }; acc.push(NeedMut { local, span }.into()); @@ -2127,8 +2136,11 @@ impl Param { pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> { let parent = DefWithBodyId::FunctionId(self.func.into()); let body = db.body(parent); - let pat_id = body.params[self.idx]; - if let Pat::Bind { id, .. } = &body[pat_id] { + if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) { + Some(Local { parent, binding_id: self_param }) + } else if let Pat::Bind { id, .. } = + &body[body.params[self.idx - body.self_param.is_some() as usize]] + { Some(Local { parent, binding_id: *id }) } else { None @@ -2143,7 +2155,7 @@ impl Param { let InFile { file_id, value } = self.func.source(db)?; let params = value.param_list()?; if params.self_param().is_some() { - params.params().nth(self.idx.checked_sub(1)?) + params.params().nth(self.idx.checked_sub(params.self_param().is_some() as usize)?) } else { params.params().nth(self.idx) } @@ -2605,6 +2617,15 @@ impl Macro { } } + pub fn is_env_or_option_env(&self, db: &dyn HirDatabase) -> bool { + match self.id { + MacroId::Macro2Id(it) => { + matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env()) + } + MacroId::MacroRulesId(_) | MacroId::ProcMacroId(_) => false, + } + } + pub fn is_attr(&self, db: &dyn HirDatabase) -> bool { matches!(self.kind(db), MacroKind::Attr) } @@ -3134,35 +3155,59 @@ impl Local { /// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = it;` pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> { let (body, source_map) = db.body_with_source_map(self.parent); - self.sources_(db, &body, &source_map).collect() + match body.self_param.zip(source_map.self_param_syntax()) { + Some((param, source)) if param == self.binding_id => { + let root = source.file_syntax(db.upcast()); + vec![LocalSource { + local: self, + source: source.map(|ast| Either::Right(ast.to_node(&root))), + }] + } + _ => body[self.binding_id] + .definitions + .iter() + .map(|&definition| { + let src = source_map.pat_syntax(definition).unwrap(); // Hmm... + let root = src.file_syntax(db.upcast()); + LocalSource { + local: self, + source: src.map(|ast| match ast.to_node(&root) { + ast::Pat::IdentPat(it) => Either::Left(it), + _ => unreachable!("local with non ident-pattern"), + }), + } + }) + .collect(), + } } /// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = it;` pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource { let (body, source_map) = db.body_with_source_map(self.parent); - let src = self.sources_(db, &body, &source_map).next().unwrap(); - src - } - - fn sources_<'a>( - self, - db: &'a dyn HirDatabase, - body: &'a hir_def::body::Body, - source_map: &'a hir_def::body::BodySourceMap, - ) -> impl Iterator<Item = LocalSource> + 'a { - body[self.binding_id] - .definitions - .iter() - .map(|&definition| { - let src = source_map.pat_syntax(definition).unwrap(); // Hmm... - let root = src.file_syntax(db.upcast()); - src.map(|ast| match ast.to_node(&root) { - Either::Left(ast::Pat::IdentPat(it)) => Either::Left(it), - Either::Left(_) => unreachable!("local with non ident-pattern"), - Either::Right(it) => Either::Right(it), + match body.self_param.zip(source_map.self_param_syntax()) { + Some((param, source)) if param == self.binding_id => { + let root = source.file_syntax(db.upcast()); + LocalSource { + local: self, + source: source.map(|ast| Either::Right(ast.to_node(&root))), + } + } + _ => body[self.binding_id] + .definitions + .first() + .map(|&definition| { + let src = source_map.pat_syntax(definition).unwrap(); // Hmm... + let root = src.file_syntax(db.upcast()); + LocalSource { + local: self, + source: src.map(|ast| match ast.to_node(&root) { + ast::Pat::IdentPat(it) => Either::Left(it), + _ => unreachable!("local with non ident-pattern"), + }), + } }) - }) - .map(move |source| LocalSource { local: self, source }) + .unwrap(), + } } } @@ -4037,7 +4082,7 @@ impl Type { let canonical_ty = Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; - method_resolution::implements_trait(&canonical_ty, db, self.env.clone(), trait_) + method_resolution::implements_trait(&canonical_ty, db, &self.env, trait_) } /// Checks that particular type `ty` implements `std::ops::FnOnce`. @@ -4052,12 +4097,7 @@ impl Type { let canonical_ty = Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; - method_resolution::implements_trait_unique( - &canonical_ty, - db, - self.env.clone(), - fnonce_trait, - ) + method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, fnonce_trait) } // FIXME: Find better API that also handles const generics |