internal: Enforce Resolver to always have a module scope

This commit is contained in:
Lukas Wirth 2022-03-31 11:12:08 +02:00
parent ef92453dfe
commit 75689f2ad8
71 changed files with 360 additions and 398 deletions

View file

@ -159,7 +159,7 @@ impl Crate {
.map(|dep| { .map(|dep| {
let krate = Crate { id: dep.crate_id }; let krate = Crate { id: dep.crate_id };
let name = dep.as_name(); let name = dep.as_name();
CrateDependency { krate, name, } CrateDependency { krate, name }
}) })
.collect() .collect()
} }
@ -2224,7 +2224,7 @@ impl BuiltinAttr {
Some(BuiltinAttr { krate: Some(krate.id), idx }) Some(BuiltinAttr { krate: Some(krate.id), idx })
} }
pub(crate) fn builtin(name: &str) -> Option<Self> { fn builtin(name: &str) -> Option<Self> {
hir_def::builtin_attr::INERT_ATTRIBUTES hir_def::builtin_attr::INERT_ATTRIBUTES
.iter() .iter()
.position(|tool| tool.name == name) .position(|tool| tool.name == name)
@ -2263,7 +2263,7 @@ impl ToolModule {
Some(ToolModule { krate: Some(krate.id), idx }) Some(ToolModule { krate: Some(krate.id), idx })
} }
pub(crate) fn builtin(name: &str) -> Option<Self> { fn builtin(name: &str) -> Option<Self> {
hir_def::builtin_attr::TOOL_MODULES hir_def::builtin_attr::TOOL_MODULES
.iter() .iter()
.position(|&tool| tool == name) .position(|&tool| tool == name)
@ -2613,13 +2613,9 @@ pub struct Type {
} }
impl Type { impl Type {
pub(crate) fn new_with_resolver( pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver, ty: Ty) -> Type {
db: &dyn HirDatabase, let krate = resolver.krate();
resolver: &Resolver, Type::new_with_resolver_inner(db, krate, resolver, ty)
ty: Ty,
) -> Option<Type> {
let krate = resolver.krate()?;
Some(Type::new_with_resolver_inner(db, krate, resolver, ty))
} }
pub(crate) fn new_with_resolver_inner( pub(crate) fn new_with_resolver_inner(
@ -3038,10 +3034,7 @@ impl Type {
// There should be no inference vars in types passed here // There should be no inference vars in types passed here
let canonical = hir_ty::replace_errors_with_variables(&self.ty); let canonical = hir_ty::replace_errors_with_variables(&self.ty);
let krate = match scope.krate() { let krate = scope.krate();
Some(k) => k,
None => return,
};
let environment = scope.resolver().generic_def().map_or_else( let environment = scope.resolver().generic_def().map_or_else(
|| Arc::new(TraitEnvironment::empty(krate.id)), || Arc::new(TraitEnvironment::empty(krate.id)),
|d| db.trait_environment(d), |d| db.trait_environment(d),
@ -3098,10 +3091,7 @@ impl Type {
) { ) {
let canonical = hir_ty::replace_errors_with_variables(&self.ty); let canonical = hir_ty::replace_errors_with_variables(&self.ty);
let krate = match scope.krate() { let krate = scope.krate();
Some(k) => k,
None => return,
};
let environment = scope.resolver().generic_def().map_or_else( let environment = scope.resolver().generic_def().map_or_else(
|| Arc::new(TraitEnvironment::empty(krate.id)), || Arc::new(TraitEnvironment::empty(krate.id)),
|d| db.trait_environment(d), |d| db.trait_environment(d),

View file

@ -403,11 +403,15 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.to_module_def(file) self.imp.to_module_def(file)
} }
pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { pub fn scope(&self, node: &SyntaxNode) -> Option<SemanticsScope<'db>> {
self.imp.scope(node) self.imp.scope(node)
} }
pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { pub fn scope_at_offset(
&self,
node: &SyntaxNode,
offset: TextSize,
) -> Option<SemanticsScope<'db>> {
self.imp.scope_at_offset(node, offset) self.imp.scope_at_offset(node, offset)
} }
@ -456,7 +460,7 @@ impl<'db> SemanticsImpl<'db> {
} }
fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
let sa = self.analyze_no_infer(macro_call.syntax()); let sa = self.analyze_no_infer(macro_call.syntax())?;
let file_id = sa.expand(self.db, InFile::new(sa.file_id, macro_call))?; let file_id = sa.expand(self.db, InFile::new(sa.file_id, macro_call))?;
let node = self.parse_or_expand(file_id)?; let node = self.parse_or_expand(file_id)?;
Some(node) Some(node)
@ -535,9 +539,9 @@ impl<'db> SemanticsImpl<'db> {
token_to_map: SyntaxToken, token_to_map: SyntaxToken,
) -> Option<(SyntaxNode, SyntaxToken)> { ) -> Option<(SyntaxNode, SyntaxToken)> {
let SourceAnalyzer { file_id, resolver, .. } = let SourceAnalyzer { file_id, resolver, .. } =
self.analyze_no_infer(actual_macro_call.syntax()); self.analyze_no_infer(actual_macro_call.syntax())?;
let macro_call = InFile::new(file_id, actual_macro_call); let macro_call = InFile::new(file_id, actual_macro_call);
let krate = resolver.krate()?; let krate = resolver.krate();
let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
resolver resolver
.resolve_path_as_macro(self.db.upcast(), &path) .resolve_path_as_macro(self.db.upcast(), &path)
@ -669,7 +673,10 @@ impl<'db> SemanticsImpl<'db> {
Some(it) => it, Some(it) => it,
None => return, None => return,
}; };
let sa = self.analyze_no_infer(&parent); let sa = match self.analyze_no_infer(&parent) {
Some(it) => it,
None => return,
};
let mut stack: SmallVec<[_; 4]> = smallvec![InFile::new(sa.file_id, token)]; let mut stack: SmallVec<[_; 4]> = smallvec![InFile::new(sa.file_id, token)];
let mut cache = self.expansion_info_cache.borrow_mut(); let mut cache = self.expansion_info_cache.borrow_mut();
let mut mcache = self.macro_call_cache.borrow_mut(); let mut mcache = self.macro_call_cache.borrow_mut();
@ -903,70 +910,74 @@ impl<'db> SemanticsImpl<'db> {
} }
fn resolve_type(&self, ty: &ast::Type) -> Option<Type> { fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
let scope = self.scope(ty.syntax()); let analyze = self.analyze(ty.syntax())?;
let ctx = body::LowerCtx::new(self.db.upcast(), scope.file_id); let ctx = body::LowerCtx::new(self.db.upcast(), analyze.file_id);
let ty = hir_ty::TyLoweringContext::new(self.db, &scope.resolver) let ty = hir_ty::TyLoweringContext::new(self.db, &analyze.resolver)
.lower_ty(&crate::TypeRef::from_ast(&ctx, ty.clone())); .lower_ty(&crate::TypeRef::from_ast(&ctx, ty.clone()));
Type::new_with_resolver(self.db, &scope.resolver, ty) Some(Type::new_with_resolver(self.db, &analyze.resolver, ty))
} }
fn is_implicit_reborrow(&self, expr: &ast::Expr) -> Option<Mutability> { fn is_implicit_reborrow(&self, expr: &ast::Expr) -> Option<Mutability> {
self.analyze(expr.syntax()).is_implicit_reborrow(self.db, expr) self.analyze(expr.syntax())?.is_implicit_reborrow(self.db, expr)
} }
fn type_of_expr(&self, expr: &ast::Expr) -> Option<TypeInfo> { fn type_of_expr(&self, expr: &ast::Expr) -> Option<TypeInfo> {
self.analyze(expr.syntax()) self.analyze(expr.syntax())?
.type_of_expr(self.db, expr) .type_of_expr(self.db, expr)
.map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced }) .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
} }
fn type_of_pat(&self, pat: &ast::Pat) -> Option<TypeInfo> { fn type_of_pat(&self, pat: &ast::Pat) -> Option<TypeInfo> {
self.analyze(pat.syntax()) self.analyze(pat.syntax())?
.type_of_pat(self.db, pat) .type_of_pat(self.db, pat)
.map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced }) .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
} }
fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
self.analyze(param.syntax()).type_of_self(self.db, param) self.analyze(param.syntax())?.type_of_self(self.db, param)
} }
fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
self.analyze(call.syntax()).resolve_method_call(self.db, call).map(|(id, _)| id) self.analyze(call.syntax())?.resolve_method_call(self.db, call).map(|(id, _)| id)
} }
fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
let (func, subst) = self.analyze(call.syntax()).resolve_method_call(self.db, call)?; let source_analyzer = self.analyze(call.syntax())?;
let (func, subst) = source_analyzer.resolve_method_call(self.db, call)?;
let ty = self.db.value_ty(func.into()).substitute(Interner, &subst); let ty = self.db.value_ty(func.into()).substitute(Interner, &subst);
let resolver = self.analyze(call.syntax()).resolver; let resolver = source_analyzer.resolver;
let ty = Type::new_with_resolver(self.db, &resolver, ty)?; let ty = Type::new_with_resolver(self.db, &resolver, ty);
let mut res = ty.as_callable(self.db)?; let mut res = ty.as_callable(self.db)?;
res.is_bound_method = true; res.is_bound_method = true;
Some(res) Some(res)
} }
fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> { fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
self.analyze(field.syntax()).resolve_field(self.db, field) self.analyze(field.syntax())?.resolve_field(self.db, field)
} }
fn resolve_record_field( fn resolve_record_field(
&self, &self,
field: &ast::RecordExprField, field: &ast::RecordExprField,
) -> Option<(Field, Option<Local>, Type)> { ) -> Option<(Field, Option<Local>, Type)> {
self.analyze(field.syntax()).resolve_record_field(self.db, field) self.analyze(field.syntax())?.resolve_record_field(self.db, field)
} }
fn resolve_record_pat_field(&self, field: &ast::RecordPatField) -> Option<Field> { fn resolve_record_pat_field(&self, field: &ast::RecordPatField) -> Option<Field> {
self.analyze(field.syntax()).resolve_record_pat_field(self.db, field) self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field)
} }
fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> { fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> {
let sa = self.analyze(macro_call.syntax()); let sa = self.analyze(macro_call.syntax())?;
let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call); let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
sa.resolve_macro_call(self.db, macro_call) sa.resolve_macro_call(self.db, macro_call)
} }
fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool { fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
let sa = self.analyze(macro_call.syntax()); let sa = match self.analyze(macro_call.syntax()) {
Some(it) => it,
None => return false,
};
let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call); let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
sa.is_unsafe_macro_call(self.db, macro_call) sa.is_unsafe_macro_call(self.db, macro_call)
} }
@ -981,11 +992,11 @@ impl<'db> SemanticsImpl<'db> {
} }
fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> { fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
self.analyze(path.syntax()).resolve_path(self.db, path) self.analyze(path.syntax())?.resolve_path(self.db, path)
} }
fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> { fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> {
let krate = self.scope(extern_crate.syntax()).krate()?; let krate = self.scope(extern_crate.syntax())?.krate();
let name = extern_crate.name_ref()?.as_name(); let name = extern_crate.name_ref()?.as_name();
if name == known::SELF_PARAM { if name == known::SELF_PARAM {
return Some(krate); return Some(krate);
@ -997,22 +1008,22 @@ impl<'db> SemanticsImpl<'db> {
} }
fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> { fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) self.analyze(record_lit.syntax())?.resolve_variant(self.db, record_lit)
} }
fn resolve_bind_pat_to_const(&self, pat: &ast::IdentPat) -> Option<ModuleDef> { fn resolve_bind_pat_to_const(&self, pat: &ast::IdentPat) -> Option<ModuleDef> {
self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) self.analyze(pat.syntax())?.resolve_bind_pat_to_const(self.db, pat)
} }
fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> { fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> {
self.analyze(literal.syntax()) self.analyze(literal.syntax())
.record_literal_missing_fields(self.db, literal) .and_then(|it| it.record_literal_missing_fields(self.db, literal))
.unwrap_or_default() .unwrap_or_default()
} }
fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> { fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> {
self.analyze(pattern.syntax()) self.analyze(pattern.syntax())
.record_pattern_missing_fields(self.db, pattern) .and_then(|it| it.record_pattern_missing_fields(self.db, pattern))
.unwrap_or_default() .unwrap_or_default()
} }
@ -1026,15 +1037,22 @@ impl<'db> SemanticsImpl<'db> {
self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from) self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from)
} }
fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { fn scope(&self, node: &SyntaxNode) -> Option<SemanticsScope<'db>> {
let SourceAnalyzer { file_id, resolver, .. } = self.analyze_no_infer(node); self.analyze_no_infer(node).map(|SourceAnalyzer { file_id, resolver, .. }| SemanticsScope {
SemanticsScope { db: self.db, file_id, resolver } db: self.db,
file_id,
resolver,
})
} }
fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> Option<SemanticsScope<'db>> {
let SourceAnalyzer { file_id, resolver, .. } = self.analyze_with_offset_no_infer(node, offset).map(
self.analyze_with_offset_no_infer(node, offset); |SourceAnalyzer { file_id, resolver, .. }| SemanticsScope {
SemanticsScope { db: self.db, file_id, resolver } db: self.db,
file_id,
resolver,
},
)
} }
fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
@ -1052,15 +1070,21 @@ impl<'db> SemanticsImpl<'db> {
Some(res) Some(res)
} }
fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer { /// Returns none if the file of the node is not part of a crate.
fn analyze(&self, node: &SyntaxNode) -> Option<SourceAnalyzer> {
self.analyze_impl(node, None, true) self.analyze_impl(node, None, true)
} }
fn analyze_no_infer(&self, node: &SyntaxNode) -> SourceAnalyzer { /// Returns none if the file of the node is not part of a crate.
fn analyze_no_infer(&self, node: &SyntaxNode) -> Option<SourceAnalyzer> {
self.analyze_impl(node, None, false) self.analyze_impl(node, None, false)
} }
fn analyze_with_offset_no_infer(&self, node: &SyntaxNode, offset: TextSize) -> SourceAnalyzer { fn analyze_with_offset_no_infer(
&self,
node: &SyntaxNode,
offset: TextSize,
) -> Option<SourceAnalyzer> {
self.analyze_impl(node, Some(offset), false) self.analyze_impl(node, Some(offset), false)
} }
@ -1069,22 +1093,22 @@ impl<'db> SemanticsImpl<'db> {
node: &SyntaxNode, node: &SyntaxNode,
offset: Option<TextSize>, offset: Option<TextSize>,
infer_body: bool, infer_body: bool,
) -> SourceAnalyzer { ) -> Option<SourceAnalyzer> {
let _p = profile::span("Semantics::analyze_impl"); let _p = profile::span("Semantics::analyze_impl");
let node = self.find_file(node); let node = self.find_file(node);
let container = match self.with_ctx(|ctx| ctx.find_container(node)) { let container = match self.with_ctx(|ctx| ctx.find_container(node)) {
Some(it) => it, Some(it) => it,
None => return SourceAnalyzer::new_for_resolver(Resolver::default(), node), None => return None,
}; };
let resolver = match container { let resolver = match container {
ChildContainer::DefWithBodyId(def) => { ChildContainer::DefWithBodyId(def) => {
return if infer_body { return Some(if infer_body {
SourceAnalyzer::new_for_body(self.db, def, node, offset) SourceAnalyzer::new_for_body(self.db, def, node, offset)
} else { } else {
SourceAnalyzer::new_for_body_no_infer(self.db, def, node, offset) SourceAnalyzer::new_for_body_no_infer(self.db, def, node, offset)
} })
} }
ChildContainer::TraitId(it) => it.resolver(self.db.upcast()), ChildContainer::TraitId(it) => it.resolver(self.db.upcast()),
ChildContainer::ImplId(it) => it.resolver(self.db.upcast()), ChildContainer::ImplId(it) => it.resolver(self.db.upcast()),
@ -1094,7 +1118,7 @@ impl<'db> SemanticsImpl<'db> {
ChildContainer::TypeAliasId(it) => it.resolver(self.db.upcast()), ChildContainer::TypeAliasId(it) => it.resolver(self.db.upcast()),
ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()), ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()),
}; };
SourceAnalyzer::new_for_resolver(resolver, node) Some(SourceAnalyzer::new_for_resolver(resolver, node))
} }
fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) { fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
@ -1118,6 +1142,7 @@ impl<'db> SemanticsImpl<'db> {
InFile::new(file_id, node) InFile::new(file_id, node)
} }
/// Wraps the node in a [`InFile`] with the file id it belongs to.
fn find_file<'node>(&self, node: &'node SyntaxNode) -> InFile<&'node SyntaxNode> { fn find_file<'node>(&self, node: &'node SyntaxNode) -> InFile<&'node SyntaxNode> {
let root_node = find_root(node); let root_node = find_root(node);
let file_id = self.lookup(&root_node).unwrap_or_else(|| { let file_id = self.lookup(&root_node).unwrap_or_else(|| {
@ -1319,12 +1344,12 @@ pub struct SemanticsScope<'a> {
} }
impl<'a> SemanticsScope<'a> { impl<'a> SemanticsScope<'a> {
pub fn module(&self) -> Option<Module> { pub fn module(&self) -> Module {
Some(Module { id: self.resolver.module()? }) Module { id: self.resolver.module() }
} }
pub fn krate(&self) -> Option<Crate> { pub fn krate(&self) -> Crate {
Some(Crate { id: self.resolver.krate()? }) Crate { id: self.resolver.krate() }
} }
pub(crate) fn resolver(&self) -> &Resolver { pub(crate) fn resolver(&self) -> &Resolver {

View file

@ -169,7 +169,7 @@ impl SourceAnalyzer {
.and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone())); .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
let ty = infer[expr_id].clone(); let ty = infer[expr_id].clone();
let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
mk_ty(ty).zip(Some(coerced.and_then(mk_ty))) Some((mk_ty(ty), coerced.map(mk_ty)))
} }
pub(crate) fn type_of_pat( pub(crate) fn type_of_pat(
@ -185,7 +185,7 @@ impl SourceAnalyzer {
.and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone())); .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
let ty = infer[pat_id].clone(); let ty = infer[pat_id].clone();
let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
mk_ty(ty).zip(Some(coerced.and_then(mk_ty))) Some((mk_ty(ty), coerced.map(mk_ty)))
} }
pub(crate) fn type_of_self( pub(crate) fn type_of_self(
@ -196,7 +196,7 @@ impl SourceAnalyzer {
let src = InFile { file_id: self.file_id, value: param }; let src = InFile { file_id: self.file_id, value: param };
let pat_id = self.body_source_map()?.node_self_param(src)?; let pat_id = self.body_source_map()?.node_self_param(src)?;
let ty = self.infer.as_ref()?[pat_id].clone(); let ty = self.infer.as_ref()?[pat_id].clone();
Type::new_with_resolver(db, &self.resolver, ty) Some(Type::new_with_resolver(db, &self.resolver, ty))
} }
pub(crate) fn resolve_method_call( pub(crate) fn resolve_method_call(
@ -244,7 +244,7 @@ impl SourceAnalyzer {
let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
let field_ty = let field_ty =
db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
Some((field.into(), local, Type::new_with_resolver(db, &self.resolver, field_ty)?)) Some((field.into(), local, Type::new_with_resolver(db, &self.resolver, field_ty)))
} }
pub(crate) fn resolve_record_pat_field( pub(crate) fn resolve_record_pat_field(
@ -366,10 +366,7 @@ impl SourceAnalyzer {
return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path) { return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path) {
None if is_path_of_attr => { None if is_path_of_attr => {
path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| { path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| {
match self.resolver.krate() { ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
Some(krate) => ToolModule::by_name(db, krate.into(), &name_ref.text()),
None => ToolModule::builtin(&name_ref.text()),
}
.map(PathResolution::ToolModule) .map(PathResolution::ToolModule)
}) })
} }
@ -380,9 +377,8 @@ impl SourceAnalyzer {
// in this case we have to check for inert/builtin attributes and tools and prioritize // in this case we have to check for inert/builtin attributes and tools and prioritize
// resolution of attributes over other namespaces // resolution of attributes over other namespaces
let name_ref = path.as_single_name_ref(); let name_ref = path.as_single_name_ref();
let builtin = name_ref.as_ref().and_then(|name_ref| match self.resolver.krate() { let builtin = name_ref.as_ref().and_then(|name_ref| {
Some(krate) => BuiltinAttr::by_name(db, krate.into(), &name_ref.text()), BuiltinAttr::by_name(db, self.resolver.krate().into(), &name_ref.text())
None => BuiltinAttr::builtin(&name_ref.text()),
}); });
if let builtin @ Some(_) = builtin { if let builtin @ Some(_) = builtin {
return builtin.map(PathResolution::BuiltinAttr); return builtin.map(PathResolution::BuiltinAttr);
@ -392,10 +388,7 @@ impl SourceAnalyzer {
// this labels any path that starts with a tool module as the tool itself, this is technically wrong // this labels any path that starts with a tool module as the tool itself, this is technically wrong
// but there is no benefit in differentiating these two cases for the time being // but there is no benefit in differentiating these two cases for the time being
None => path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| { None => path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| {
match self.resolver.krate() { ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
Some(krate) => ToolModule::by_name(db, krate.into(), &name_ref.text()),
None => ToolModule::builtin(&name_ref.text()),
}
.map(PathResolution::ToolModule) .map(PathResolution::ToolModule)
}), }),
}; };
@ -412,7 +405,7 @@ impl SourceAnalyzer {
db: &dyn HirDatabase, db: &dyn HirDatabase,
literal: &ast::RecordExpr, literal: &ast::RecordExpr,
) -> Option<Vec<(Field, Type)>> { ) -> Option<Vec<(Field, Type)>> {
let krate = self.resolver.krate()?; let krate = self.resolver.krate();
let body = self.body()?; let body = self.body()?;
let infer = self.infer.as_ref()?; let infer = self.infer.as_ref()?;
@ -430,7 +423,7 @@ impl SourceAnalyzer {
db: &dyn HirDatabase, db: &dyn HirDatabase,
pattern: &ast::RecordPat, pattern: &ast::RecordPat,
) -> Option<Vec<(Field, Type)>> { ) -> Option<Vec<(Field, Type)>> {
let krate = self.resolver.krate()?; let krate = self.resolver.krate();
let body = self.body()?; let body = self.body()?;
let infer = self.infer.as_ref()?; let infer = self.infer.as_ref()?;
@ -468,7 +461,7 @@ impl SourceAnalyzer {
db: &dyn HirDatabase, db: &dyn HirDatabase,
macro_call: InFile<&ast::MacroCall>, macro_call: InFile<&ast::MacroCall>,
) -> Option<HirFileId> { ) -> Option<HirFileId> {
let krate = self.resolver.krate()?; let krate = self.resolver.krate();
let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
self.resolver self.resolver
.resolve_path_as_macro(db.upcast(), &path) .resolve_path_as_macro(db.upcast(), &path)

View file

@ -25,12 +25,14 @@ use crate::{
StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, VariantId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, VariantId,
}; };
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone)]
pub struct Resolver { pub struct Resolver {
/// The stack of scopes, where the inner-most scope is the last item. /// The stack of scopes, where the inner-most scope is the last item.
/// ///
/// When using, you generally want to process the scopes in reverse order, /// When using, you generally want to process the scopes in reverse order,
/// there's `scopes` *method* for that. /// there's `scopes` *method* for that.
///
/// Invariant: There exists at least one Scope::ModuleScope at the start of the vec.
scopes: Vec<Scope>, scopes: Vec<Scope>,
} }
@ -135,10 +137,7 @@ impl Resolver {
path: &ModPath, path: &ModPath,
shadow: BuiltinShadowMode, shadow: BuiltinShadowMode,
) -> PerNs { ) -> PerNs {
let (item_map, module) = match self.module_scope() { let (item_map, module) = self.module_scope();
Some(it) => it,
None => return PerNs::none(),
};
let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow); let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow);
if segment_index.is_some() { if segment_index.is_some() {
return PerNs::none(); return PerNs::none();
@ -155,7 +154,7 @@ impl Resolver {
db: &dyn DefDatabase, db: &dyn DefDatabase,
path: &ModPath, path: &ModPath,
) -> Option<PerNs> { ) -> Option<PerNs> {
let (item_map, module) = self.module_scope()?; let (item_map, module) = self.module_scope();
let (module_res, idx) = item_map.resolve_path(db, module, path, BuiltinShadowMode::Module); let (module_res, idx) = item_map.resolve_path(db, module, path, BuiltinShadowMode::Module);
match module_res.take_types()? { match module_res.take_types()? {
ModuleDefId::TraitId(it) => { ModuleDefId::TraitId(it) => {
@ -235,10 +234,7 @@ impl Resolver {
) -> Option<Visibility> { ) -> Option<Visibility> {
match visibility { match visibility {
RawVisibility::Module(_) => { RawVisibility::Module(_) => {
let (item_map, module) = match self.module_scope() { let (item_map, module) = self.module_scope();
Some(it) => it,
None => return None,
};
item_map.resolve_visibility(db, module, visibility) item_map.resolve_visibility(db, module, visibility)
} }
RawVisibility::Public => Some(Visibility::Public), RawVisibility::Public => Some(Visibility::Public),
@ -336,7 +332,7 @@ impl Resolver {
} }
pub fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroId> { pub fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroId> {
let (item_map, module) = self.module_scope()?; let (item_map, module) = self.module_scope();
item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros() item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros()
} }
@ -425,22 +421,22 @@ impl Resolver {
traits traits
} }
fn module_scope(&self) -> Option<(&DefMap, LocalModuleId)> { fn module_scope(&self) -> (&DefMap, LocalModuleId) {
self.scopes().find_map(|scope| match scope { self.scopes()
.find_map(|scope| match scope {
Scope::ModuleScope(m) => Some((&*m.def_map, m.module_id)), Scope::ModuleScope(m) => Some((&*m.def_map, m.module_id)),
_ => None, _ => None,
}) })
.expect("module scope invariant violated")
} }
pub fn module(&self) -> Option<ModuleId> { pub fn module(&self) -> ModuleId {
let (def_map, local_id) = self.module_scope()?; let (def_map, local_id) = self.module_scope();
Some(def_map.module_id(local_id)) def_map.module_id(local_id)
} }
pub fn krate(&self) -> Option<CrateId> { pub fn krate(&self) -> CrateId {
// FIXME: can this ever be `None`? self.module_scope().0.krate()
self.module_scope().map(|t| t.0.krate())
} }
pub fn where_predicates_in_scope( pub fn where_predicates_in_scope(
@ -749,8 +745,7 @@ impl HasResolver for ModuleId {
def_map = parent.def_map(db); def_map = parent.def_map(db);
modules.push((def_map.clone(), parent.local_id)); modules.push((def_map.clone(), parent.local_id));
} }
let mut resolver = Resolver::default(); let mut resolver = Resolver { scopes: Vec::with_capacity(modules.len()) };
resolver.scopes.reserve(modules.len());
for (def_map, module) in modules.into_iter().rev() { for (def_map, module) in modules.into_iter().rev() {
resolver = resolver.push_module_scope(def_map, module); resolver = resolver.push_module_scope(def_map, module);
} }

View file

@ -420,9 +420,8 @@ pub(crate) fn associated_ty_data_query(
.collect(); .collect();
if !ctx.unsized_types.borrow().contains(&self_ty) { if !ctx.unsized_types.borrow().contains(&self_ty) {
let sized_trait = resolver let sized_trait = db
.krate() .lang_item(resolver.krate(), SmolStr::new_inline("sized"))
.and_then(|krate| db.lang_item(krate, SmolStr::new_inline("sized")))
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id)); .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
let sized_bound = sized_trait.into_iter().map(|sized_trait| { let sized_bound = sized_trait.into_iter().map(|sized_trait| {
let trait_bound = let trait_bound =

View file

@ -762,7 +762,7 @@ impl<'a> InferenceContext<'a> {
} }
fn resolve_lang_item(&self, name: Name) -> Option<LangItemTarget> { fn resolve_lang_item(&self, name: Name) -> Option<LangItemTarget> {
let krate = self.resolver.krate()?; let krate = self.resolver.krate();
self.db.lang_item(krate, name.to_smol_str()) self.db.lang_item(krate, name.to_smol_str())
} }

View file

@ -29,7 +29,7 @@ use crate::{
const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode, const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode,
}, },
mapping::{from_chalk, ToChalk}, mapping::{from_chalk, ToChalk},
method_resolution, method_resolution::{self, VisibleFromModule},
primitive::{self, UintTy}, primitive::{self, UintTy},
static_lifetime, to_chalk_trait_id, static_lifetime, to_chalk_trait_id,
utils::{generics, Generics}, utils::{generics, Generics},
@ -487,13 +487,8 @@ impl<'a> InferenceContext<'a> {
} }
_ => return None, _ => return None,
}; };
let module = self.resolver.module(); let is_visible = self.db.field_visibilities(field_id.parent)[field_id.local_id]
let is_visible = module .is_visible_from(self.db.upcast(), self.resolver.module());
.map(|mod_id| {
self.db.field_visibilities(field_id.parent)[field_id.local_id]
.is_visible_from(self.db.upcast(), mod_id)
})
.unwrap_or(true);
if !is_visible { if !is_visible {
// Write down the first field resolution even if it is not visible // Write down the first field resolution even if it is not visible
// This aids IDE features for private fields like goto def and in // This aids IDE features for private fields like goto def and in
@ -946,7 +941,7 @@ impl<'a> InferenceContext<'a> {
self.db, self.db,
self.trait_env.clone(), self.trait_env.clone(),
&traits_in_scope, &traits_in_scope,
self.resolver.module().into(), VisibleFromModule::Filter(self.resolver.module()),
method_name, method_name,
); );
let (receiver_ty, method_ty, substs) = match resolved { let (receiver_ty, method_ty, substs) = match resolved {

View file

@ -9,8 +9,11 @@ use hir_def::{
use hir_expand::name::Name; use hir_expand::name::Name;
use crate::{ use crate::{
builder::ParamKind, consteval, method_resolution, GenericArgData, Interner, Substitution, builder::ParamKind,
TraitRefExt, Ty, TyBuilder, TyExt, TyKind, ValueTyDefId, consteval,
method_resolution::{self, VisibleFromModule},
GenericArgData, Interner, Substitution, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
ValueTyDefId,
}; };
use super::{ExprOrPatId, InferenceContext, TraitRef}; use super::{ExprOrPatId, InferenceContext, TraitRef};
@ -231,7 +234,7 @@ impl<'a> InferenceContext<'a> {
self.db, self.db,
self.table.trait_env.clone(), self.table.trait_env.clone(),
&traits_in_scope, &traits_in_scope,
self.resolver.module().into(), VisibleFromModule::Filter(self.resolver.module()),
Some(name), Some(name),
method_resolution::LookupMode::Path, method_resolution::LookupMode::Path,
move |_ty, item| { move |_ty, item| {

View file

@ -335,12 +335,13 @@ impl<'a> TyLoweringContext<'a> {
let mut expander = self.expander.borrow_mut(); let mut expander = self.expander.borrow_mut();
if expander.is_some() { if expander.is_some() {
(Some(expander), false) (Some(expander), false)
} else if let Some(module_id) = self.resolver.module() {
*expander =
Some(Expander::new(self.db.upcast(), macro_call.file_id, module_id));
(Some(expander), true)
} else { } else {
(None, false) *expander = Some(Expander::new(
self.db.upcast(),
macro_call.file_id,
self.resolver.module(),
));
(Some(expander), true)
} }
}; };
let ty = if let Some(mut expander) = expander { let ty = if let Some(mut expander) = expander {
@ -860,9 +861,8 @@ impl<'a> TyLoweringContext<'a> {
} }
TypeBound::Path(path, TraitBoundModifier::Maybe) => { TypeBound::Path(path, TraitBoundModifier::Maybe) => {
let sized_trait = self let sized_trait = self
.resolver .db
.krate() .lang_item(self.resolver.krate(), SmolStr::new_inline("sized"))
.and_then(|krate| self.db.lang_item(krate, SmolStr::new_inline("sized")))
.and_then(|lang_item| lang_item.as_trait()); .and_then(|lang_item| lang_item.as_trait());
// Don't lower associated type bindings as the only possible relaxed trait bound // Don't lower associated type bindings as the only possible relaxed trait bound
// `?Sized` has no of them. // `?Sized` has no of them.
@ -1268,9 +1268,8 @@ fn implicitly_sized_clauses<'a>(
) -> impl Iterator<Item = WhereClause> + 'a { ) -> impl Iterator<Item = WhereClause> + 'a {
let is_trait_def = matches!(def, GenericDefId::TraitId(..)); let is_trait_def = matches!(def, GenericDefId::TraitId(..));
let generic_args = &substitution.as_slice(Interner)[is_trait_def as usize..]; let generic_args = &substitution.as_slice(Interner)[is_trait_def as usize..];
let sized_trait = resolver let sized_trait = db
.krate() .lang_item(resolver.krate(), SmolStr::new_inline("sized"))
.and_then(|krate| db.lang_item(krate, SmolStr::new_inline("sized")))
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id)); .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
sized_trait.into_iter().flat_map(move |sized_trait| { sized_trait.into_iter().flat_map(move |sized_trait| {

View file

@ -170,7 +170,7 @@ pub(crate) fn hover_for_definition(
config: &HoverConfig, config: &HoverConfig,
) -> Option<HoverResult> { ) -> Option<HoverResult> {
let famous_defs = match &definition { let famous_defs = match &definition {
Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(node).krate())), Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(node)?.krate())),
_ => None, _ => None,
}; };
if let Some(markup) = render::definition(sema.db, definition, famous_defs.as_ref(), config) { if let Some(markup) = render::definition(sema.db, definition, famous_defs.as_ref(), config) {

View file

@ -103,7 +103,7 @@ pub(super) fn try_expr(
let adts = inner_ty.as_adt().zip(body_ty.as_adt()); let adts = inner_ty.as_adt().zip(body_ty.as_adt());
if let Some((hir::Adt::Enum(inner), hir::Adt::Enum(body))) = adts { if let Some((hir::Adt::Enum(inner), hir::Adt::Enum(body))) = adts {
let famous_defs = FamousDefs(sema, sema.scope(try_expr.syntax()).krate()); let famous_defs = FamousDefs(sema, sema.scope(try_expr.syntax())?.krate());
// special case for two options, there is no value in showing them // special case for two options, there is no value in showing them
if let Some(option_enum) = famous_defs.core_option_Option() { if let Some(option_enum) = famous_defs.core_option_Option() {
if inner == option_enum && body == option_enum { if inner == option_enum && body == option_enum {
@ -234,7 +234,7 @@ pub(super) fn keyword(
return None; return None;
} }
let parent = token.parent()?; let parent = token.parent()?;
let famous_defs = FamousDefs(sema, sema.scope(&parent).krate()); let famous_defs = FamousDefs(sema, sema.scope(&parent)?.krate());
let KeywordHint { description, keyword_mod, actions } = keyword_hints(sema, token, parent); let KeywordHint { description, keyword_mod, actions } = keyword_hints(sema, token, parent);

View file

@ -110,7 +110,10 @@ fn hints(
config: &InlayHintsConfig, config: &InlayHintsConfig,
node: SyntaxNode, node: SyntaxNode,
) { ) {
let krate = sema.scope(&node).module().map(|it| it.krate()); let krate = match sema.scope(&node) {
Some(it) => it.krate(),
None => return,
};
let famous_defs = FamousDefs(sema, krate); let famous_defs = FamousDefs(sema, krate);
if let Some(expr) = ast::Expr::cast(node.clone()) { if let Some(expr) = ast::Expr::cast(node.clone()) {
chaining_hints(hints, sema, &famous_defs, config, &expr); chaining_hints(hints, sema, &famous_defs, config, &expr);
@ -503,7 +506,7 @@ fn bind_pat_hints(
return None; return None;
} }
let krate = sema.scope(desc_pat.syntax()).module().map(|it| it.krate()); let krate = sema.scope(desc_pat.syntax())?.krate();
let famous_defs = FamousDefs(sema, krate); let famous_defs = FamousDefs(sema, krate);
let label = hint_iterator(sema, &famous_defs, config, &ty); let label = hint_iterator(sema, &famous_defs, config, &ty);

View file

@ -635,7 +635,7 @@ impl Analysis {
self.with_db(|db| { self.with_db(|db| {
let rule: ide_ssr::SsrRule = query.parse()?; let rule: ide_ssr::SsrRule = query.parse()?;
let mut match_finder = let mut match_finder =
ide_ssr::MatchFinder::in_context(db, resolve_context, selections); ide_ssr::MatchFinder::in_context(db, resolve_context, selections)?;
match_finder.add_rule(rule)?; match_finder.add_rule(rule)?;
let edits = if parse_only { Default::default() } else { match_finder.edits() }; let edits = if parse_only { Default::default() } else { match_finder.edits() };
Ok(SourceChange::from(edits)) Ok(SourceChange::from(edits))

View file

@ -179,12 +179,16 @@ pub(crate) fn highlight(
}; };
let mut hl = highlights::Highlights::new(root.text_range()); let mut hl = highlights::Highlights::new(root.text_range());
let krate = match sema.scope(&root) {
Some(it) => it.krate(),
None => return hl.to_vec(),
};
traverse( traverse(
&mut hl, &mut hl,
&sema, &sema,
file_id, file_id,
&root, &root,
sema.scope(&root).krate(), krate,
range_to_highlight, range_to_highlight,
syntactic_name_ref_highlighting, syntactic_name_ref_highlighting,
); );
@ -196,7 +200,7 @@ fn traverse(
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
file_id: FileId, file_id: FileId,
root: &SyntaxNode, root: &SyntaxNode,
krate: Option<hir::Crate>, krate: hir::Crate,
range_to_highlight: TextRange, range_to_highlight: TextRange,
syntactic_name_ref_highlighting: bool, syntactic_name_ref_highlighting: bool,
) { ) {

View file

@ -48,7 +48,7 @@ pub(super) fn token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Optio
pub(super) fn name_like( pub(super) fn name_like(
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
krate: Option<hir::Crate>, krate: hir::Crate,
bindings_shadow_count: &mut FxHashMap<hir::Name, u32>, bindings_shadow_count: &mut FxHashMap<hir::Name, u32>,
syntactic_name_ref_highlighting: bool, syntactic_name_ref_highlighting: bool,
name_like: ast::NameLike, name_like: ast::NameLike,
@ -192,7 +192,7 @@ fn keyword(
fn highlight_name_ref( fn highlight_name_ref(
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
krate: Option<hir::Crate>, krate: hir::Crate,
bindings_shadow_count: &mut FxHashMap<hir::Name, u32>, bindings_shadow_count: &mut FxHashMap<hir::Name, u32>,
binding_hash: &mut Option<u64>, binding_hash: &mut Option<u64>,
syntactic_name_ref_highlighting: bool, syntactic_name_ref_highlighting: bool,
@ -278,7 +278,7 @@ fn highlight_name(
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
bindings_shadow_count: &mut FxHashMap<hir::Name, u32>, bindings_shadow_count: &mut FxHashMap<hir::Name, u32>,
binding_hash: &mut Option<u64>, binding_hash: &mut Option<u64>,
krate: Option<hir::Crate>, krate: hir::Crate,
name: ast::Name, name: ast::Name,
) -> Highlight { ) -> Highlight {
let name_kind = NameClass::classify(sema, &name); let name_kind = NameClass::classify(sema, &name);
@ -322,11 +322,7 @@ fn calc_binding_hash(name: &hir::Name, shadow_count: u32) -> u64 {
hash((name, shadow_count)) hash((name, shadow_count))
} }
fn highlight_def( fn highlight_def(sema: &Semantics<RootDatabase>, krate: hir::Crate, def: Definition) -> Highlight {
sema: &Semantics<RootDatabase>,
krate: Option<hir::Crate>,
def: Definition,
) -> Highlight {
let db = sema.db; let db = sema.db;
let mut h = match def { let mut h = match def {
Definition::Macro(m) => Highlight::new(HlTag::Symbol(m.kind(sema.db).into())), Definition::Macro(m) => Highlight::new(HlTag::Symbol(m.kind(sema.db).into())),
@ -475,7 +471,7 @@ fn highlight_def(
Definition::Module(module) => Some(module.krate()), Definition::Module(module) => Some(module.krate()),
_ => None, _ => None,
}); });
let is_from_other_crate = def_crate != krate; let is_from_other_crate = def_crate != Some(krate);
let is_from_builtin_crate = def_crate.map_or(false, |def_crate| def_crate.is_builtin(db)); let is_from_builtin_crate = def_crate.map_or(false, |def_crate| def_crate.is_builtin(db));
let is_builtin_type = matches!(def, Definition::BuiltinType(_)); let is_builtin_type = matches!(def, Definition::BuiltinType(_));
let is_public = def.visibility(db) == Some(hir::Visibility::Public); let is_public = def.visibility(db) == Some(hir::Visibility::Public);
@ -495,7 +491,7 @@ fn highlight_def(
fn highlight_method_call_by_name_ref( fn highlight_method_call_by_name_ref(
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
krate: Option<hir::Crate>, krate: hir::Crate,
name_ref: &ast::NameRef, name_ref: &ast::NameRef,
) -> Option<Highlight> { ) -> Option<Highlight> {
let mc = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?; let mc = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?;
@ -504,7 +500,7 @@ fn highlight_method_call_by_name_ref(
fn highlight_method_call( fn highlight_method_call(
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
krate: Option<hir::Crate>, krate: hir::Crate,
method_call: &ast::MethodCallExpr, method_call: &ast::MethodCallExpr,
) -> Option<Highlight> { ) -> Option<Highlight> {
let func = sema.resolve_method_call(method_call)?; let func = sema.resolve_method_call(method_call)?;
@ -523,7 +519,7 @@ fn highlight_method_call(
} }
let def_crate = func.module(sema.db).krate(); let def_crate = func.module(sema.db).krate();
let is_from_other_crate = Some(def_crate) != krate; let is_from_other_crate = def_crate != krate;
let is_from_builtin_crate = def_crate.is_builtin(sema.db); let is_from_builtin_crate = def_crate.is_builtin(sema.db);
let is_public = func.visibility(sema.db) == hir::Visibility::Public; let is_public = func.visibility(sema.db) == hir::Visibility::Public;
@ -589,7 +585,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
fn highlight_name_ref_by_syntax( fn highlight_name_ref_by_syntax(
name: ast::NameRef, name: ast::NameRef,
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
krate: Option<hir::Crate>, krate: hir::Crate,
) -> Highlight { ) -> Highlight {
let default = HlTag::UnresolvedReference; let default = HlTag::UnresolvedReference;

View file

@ -41,7 +41,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio
return None; return None;
}; };
let module = ctx.sema.scope(pat.syntax()).module()?; let module = ctx.sema.scope(pat.syntax())?.module();
let pat_range = pat.syntax().text_range(); let pat_range = pat.syntax().text_range();
// Don't enable the assist if there is a type ascription without any placeholders // Don't enable the assist if there is a type ascription without any placeholders

View file

@ -104,6 +104,7 @@ fn add_missing_impl_members_inner(
) -> Option<()> { ) -> Option<()> {
let _p = profile::span("add_missing_impl_members_inner"); let _p = profile::span("add_missing_impl_members_inner");
let impl_def = ctx.find_node_at_offset::<ast::Impl>()?; let impl_def = ctx.find_node_at_offset::<ast::Impl>()?;
let target_scope = ctx.sema.scope(impl_def.syntax())?;
let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?; let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?;
let missing_items = filter_assoc_items( let missing_items = filter_assoc_items(
@ -118,7 +119,6 @@ fn add_missing_impl_members_inner(
let target = impl_def.syntax().text_range(); let target = impl_def.syntax().text_range();
acc.add(AssistId(assist_id, AssistKind::QuickFix), label, target, |builder| { acc.add(AssistId(assist_id, AssistKind::QuickFix), label, target, |builder| {
let target_scope = ctx.sema.scope(impl_def.syntax());
let missing_items = missing_items let missing_items = missing_items
.into_iter() .into_iter()
.map(|it| { .map(|it| {

View file

@ -73,7 +73,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext) ->
.filter(|pat| !matches!(pat, Pat::WildcardPat(_))) .filter(|pat| !matches!(pat, Pat::WildcardPat(_)))
.collect(); .collect();
let module = ctx.sema.scope(expr.syntax()).module()?; let module = ctx.sema.scope(expr.syntax())?.module();
let (mut missing_pats, is_non_exhaustive): ( let (mut missing_pats, is_non_exhaustive): (
Peekable<Box<dyn Iterator<Item = (ast::Pat, bool)>>>, Peekable<Box<dyn Iterator<Item = (ast::Pat, bool)>>>,
bool, bool,
@ -92,8 +92,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext) ->
}) })
.filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat)); .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
let option_enum = let option_enum = FamousDefs(&ctx.sema, module.krate()).core_option_Option().map(lift_enum);
FamousDefs(&ctx.sema, Some(module.krate())).core_option_Option().map(lift_enum);
let missing_pats: Box<dyn Iterator<Item = _>> = if Some(enum_def) == option_enum { let missing_pats: Box<dyn Iterator<Item = _>> = if Some(enum_def) == option_enum {
// Match `Some` variant first. // Match `Some` variant first.
cov_mark::hit!(option_order); cov_mark::hit!(option_order);

View file

@ -17,7 +17,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
// ``` // ```
pub(crate) fn add_return_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { pub(crate) fn add_return_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let (fn_type, tail_expr, builder_edit_pos) = extract_tail(ctx)?; let (fn_type, tail_expr, builder_edit_pos) = extract_tail(ctx)?;
let module = ctx.sema.scope(tail_expr.syntax()).module()?; let module = ctx.sema.scope(tail_expr.syntax())?.module();
let ty = ctx.sema.type_of_expr(&peel_blocks(tail_expr.clone()))?.original(); let ty = ctx.sema.type_of_expr(&peel_blocks(tail_expr.clone()))?.original();
if ty.is_unit() { if ty.is_unit() {
return None; return None;

View file

@ -222,7 +222,7 @@ fn option_variants(
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
expr: &SyntaxNode, expr: &SyntaxNode,
) -> Option<(hir::Variant, hir::Variant)> { ) -> Option<(hir::Variant, hir::Variant)> {
let fam = FamousDefs(sema, sema.scope(expr).krate()); let fam = FamousDefs(sema, sema.scope(expr)?.krate());
let option_variants = fam.core_option_Option()?.variants(sema.db); let option_variants = fam.core_option_Option()?.variants(sema.db);
match &*option_variants { match &*option_variants {
&[variant0, variant1] => Some(if variant0.name(sema.db) == known::None { &[variant0, variant1] => Some(if variant0.name(sema.db) == known::None {

View file

@ -36,10 +36,10 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext) -> Op
let src_type = impl_.self_ty()?; let src_type = impl_.self_ty()?;
let ast_trait = impl_.trait_()?; let ast_trait = impl_.trait_()?;
let module = ctx.sema.scope(impl_.syntax()).module()?; let module = ctx.sema.scope(impl_.syntax())?.module();
let trait_ = resolve_target_trait(&ctx.sema, &impl_)?; let trait_ = resolve_target_trait(&ctx.sema, &impl_)?;
if trait_ != FamousDefs(&ctx.sema, Some(module.krate())).core_convert_Into()? { if trait_ != FamousDefs(&ctx.sema, module.krate()).core_convert_Into()? {
return None; return None;
} }

View file

@ -146,10 +146,10 @@ fn is_ref_and_impls_iter_method(
let wanted_method = if ref_expr.mut_token().is_some() { known::iter_mut } else { known::iter }; let wanted_method = if ref_expr.mut_token().is_some() { known::iter_mut } else { known::iter };
let expr_behind_ref = ref_expr.expr()?; let expr_behind_ref = ref_expr.expr()?;
let ty = sema.type_of_expr(&expr_behind_ref)?.adjusted(); let ty = sema.type_of_expr(&expr_behind_ref)?.adjusted();
let scope = sema.scope(iterable.syntax()); let scope = sema.scope(iterable.syntax())?;
let krate = scope.module()?.krate(); let krate = scope.krate();
let traits_in_scope = scope.visible_traits(); let traits_in_scope = scope.visible_traits();
let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?; let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
let has_wanted_method = ty let has_wanted_method = ty
.iterate_method_candidates( .iterate_method_candidates(
@ -175,24 +175,17 @@ fn is_ref_and_impls_iter_method(
/// Whether iterable implements core::Iterator /// Whether iterable implements core::Iterator
fn impls_core_iter(sema: &hir::Semantics<ide_db::RootDatabase>, iterable: &ast::Expr) -> bool { fn impls_core_iter(sema: &hir::Semantics<ide_db::RootDatabase>, iterable: &ast::Expr) -> bool {
let it_typ = match sema.type_of_expr(iterable) { (|| {
Some(it) => it.adjusted(), let it_typ = sema.type_of_expr(iterable)?.adjusted();
None => return false,
};
let module = match sema.scope(iterable.syntax()).module() { let module = sema.scope(iterable.syntax())?.module();
Some(it) => it,
None => return false,
};
let krate = module.krate(); let krate = module.krate();
match FamousDefs(sema, Some(krate)).core_iter_Iterator() { let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
Some(iter_trait) => {
cov_mark::hit!(test_already_impls_iterator); cov_mark::hit!(test_already_impls_iterator);
it_typ.impls_trait(sema.db, iter_trait, &[]) Some(it_typ.impls_trait(sema.db, iter_trait, &[]))
} })()
None => false, .unwrap_or(false)
}
} }
fn validate_method_call_expr( fn validate_method_call_expr(
@ -214,10 +207,10 @@ fn validate_method_call_expr(
let expr = ast::Expr::MethodCallExpr(expr); let expr = ast::Expr::MethodCallExpr(expr);
let it_type = sema.type_of_expr(&receiver)?.adjusted(); let it_type = sema.type_of_expr(&receiver)?.adjusted();
let module = sema.scope(receiver.syntax()).module()?; let module = sema.scope(receiver.syntax())?.module();
let krate = module.krate(); let krate = module.krate();
let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?; let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
it_type.impls_trait(sema.db, iter_trait, &[]).then(|| (expr, receiver)) it_type.impls_trait(sema.db, iter_trait, &[]).then(|| (expr, receiver))
} }

View file

@ -49,8 +49,8 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
_ => return None, _ => return None,
}; };
let current_scope = ctx.sema.scope(&star.parent()?); let current_scope = ctx.sema.scope(&star.parent()?)?;
let current_module = current_scope.module()?; let current_module = current_scope.module();
let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?; let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?;
let imported_defs = find_imported_defs(ctx, star)?; let imported_defs = find_imported_defs(ctx, star)?;

View file

@ -81,7 +81,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option
let anchor = if self_param.is_some() { Anchor::Method } else { Anchor::Freestanding }; let anchor = if self_param.is_some() { Anchor::Method } else { Anchor::Freestanding };
let insert_after = node_to_insert_after(&body, anchor)?; let insert_after = node_to_insert_after(&body, anchor)?;
let module = ctx.sema.scope(&insert_after).module()?; let module = ctx.sema.scope(&insert_after)?.module();
let ret_ty = body.return_ty(ctx)?; let ret_ty = body.return_ty(ctx)?;
let control_flow = body.external_control_flow(ctx, &container_info)?; let control_flow = body.external_control_flow(ctx, &container_info)?;
@ -132,7 +132,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option
}; };
let control_flow_enum = let control_flow_enum =
FamousDefs(&ctx.sema, Some(module.krate())).core_ops_ControlFlow(); FamousDefs(&ctx.sema, module.krate()).core_ops_ControlFlow();
if let Some(control_flow_enum) = control_flow_enum { if let Some(control_flow_enum) = control_flow_enum {
let mod_path = module.find_use_path_prefixed( let mod_path = module.find_use_path_prefixed(

View file

@ -423,7 +423,7 @@ fn reference_to_node(
_ => return None, _ => return None,
} }
}; };
let module = sema.scope(&expr_or_pat).module()?; let module = sema.scope(&expr_or_pat)?.module();
Some((segment, expr_or_pat, module)) Some((segment, expr_or_pat, module))
} }

View file

@ -43,7 +43,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O
_ => return None, _ => return None,
}; };
let current_module = ctx.sema.scope(path.syntax()).module()?; let current_module = ctx.sema.scope(path.syntax())?.module();
let target_module = def.module(ctx.db())?; let target_module = def.module(ctx.db())?;
if def.visibility(ctx.db()).is_visible_from(ctx.db(), current_module.into()) { if def.visibility(ctx.db()).is_visible_from(ctx.db(), current_module.into()) {
@ -86,7 +86,7 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) ->
let record_field: ast::RecordExprField = ctx.find_node_at_offset()?; let record_field: ast::RecordExprField = ctx.find_node_at_offset()?;
let (record_field_def, _, _) = ctx.sema.resolve_record_field(&record_field)?; let (record_field_def, _, _) = ctx.sema.resolve_record_field(&record_field)?;
let current_module = ctx.sema.scope(record_field.syntax()).module()?; let current_module = ctx.sema.scope(record_field.syntax())?.module();
let visibility = record_field_def.visibility(ctx.db()); let visibility = record_field_def.visibility(ctx.db());
if visibility.is_visible_from(ctx.db(), current_module.into()) { if visibility.is_visible_from(ctx.db(), current_module.into()) {
return None; return None;

View file

@ -35,8 +35,8 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext) -> Optio
let expr = constant_token.syntax().ancestors().find_map(ast::Expr::cast)?; let expr = constant_token.syntax().ancestors().find_map(ast::Expr::cast)?;
let statement = expr.syntax().ancestors().find_map(ast::Stmt::cast)?; let statement = expr.syntax().ancestors().find_map(ast::Stmt::cast)?;
let ty = ctx.sema.type_of_expr(&expr)?; let ty = ctx.sema.type_of_expr(&expr)?;
let scope = ctx.sema.scope(statement.syntax()); let scope = ctx.sema.scope(statement.syntax())?;
let module = scope.module()?; let module = scope.module();
let type_name = ty.original().display_source_code(ctx.db(), module.into()).ok()?; let type_name = ty.original().display_source_code(ctx.db(), module.into()).ok()?;
let indent = IndentLevel::from_node(statement.syntax()); let indent = IndentLevel::from_node(statement.syntax());
if constant_token.to_string().chars().any(|it| !(it.is_uppercase() || it == '_')) { if constant_token.to_string().chars().any(|it| !(it.is_uppercase() || it == '_')) {

View file

@ -75,7 +75,7 @@ fn existing_default_impl(
let enum_ = variant.parent_enum(sema.db); let enum_ = variant.parent_enum(sema.db);
let krate = enum_.module(sema.db).krate(); let krate = enum_.module(sema.db).krate();
let default_trait = FamousDefs(sema, Some(krate)).core_default_Default()?; let default_trait = FamousDefs(sema, krate).core_default_Default()?;
let enum_type = enum_.ty(sema.db); let enum_type = enum_.ty(sema.db);
if enum_type.impls_trait(sema.db, default_trait, &[]) { if enum_type.impls_trait(sema.db, default_trait, &[]) {

View file

@ -132,7 +132,7 @@ fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> bool {
let ty = impl_def.self_ty(db); let ty = impl_def.self_ty(db);
let krate = impl_def.module(db).krate(); let krate = impl_def.module(db).krate();
let default = FamousDefs(&ctx.sema, Some(krate)).core_default_Default(); let default = FamousDefs(&ctx.sema, krate).core_default_Default();
let default_trait = match default { let default_trait = match default {
Some(value) => value, Some(value) => value,
None => return false, None => return false,

View file

@ -45,7 +45,7 @@ use syntax::ast::edit::AstNodeEdit;
pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let strukt = ctx.find_node_at_offset::<ast::Struct>()?; let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
let strukt_name = strukt.name()?; let strukt_name = strukt.name()?;
let current_module = ctx.sema.scope(strukt.syntax()).module()?; let current_module = ctx.sema.scope(strukt.syntax())?.module();
let (field_name, field_ty, target) = match ctx.find_node_at_offset::<ast::RecordField>() { let (field_name, field_ty, target) = match ctx.find_node_at_offset::<ast::RecordField>() {
Some(field) => { Some(field) => {

View file

@ -110,7 +110,7 @@ fn existing_deref_impl(
let strukt = sema.to_def(strukt)?; let strukt = sema.to_def(strukt)?;
let krate = strukt.module(sema.db).krate(); let krate = strukt.module(sema.db).krate();
let deref_trait = FamousDefs(sema, Some(krate)).core_ops_Deref()?; let deref_trait = FamousDefs(sema, krate).core_ops_Deref()?;
let strukt_type = strukt.ty(sema.db); let strukt_type = strukt.ty(sema.db);
if strukt_type.impls_trait(sema.db, deref_trait, &[]) { if strukt_type.impls_trait(sema.db, deref_trait, &[]) {

View file

@ -202,7 +202,7 @@ fn all_parent_mods_public(hir_func: &hir::Function, ctx: &AssistContext) -> bool
/// Returns the name of the current crate /// Returns the name of the current crate
fn crate_name(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<String> { fn crate_name(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<String> {
let krate = ctx.sema.scope(ast_func.syntax()).module()?.krate(); let krate = ctx.sema.scope(ast_func.syntax())?.krate();
Some(krate.display_name(ctx.db())?.to_string()) Some(krate.display_name(ctx.db())?.to_string())
} }

View file

@ -86,7 +86,7 @@ fn existing_from_impl(
let enum_ = variant.parent_enum(sema.db); let enum_ = variant.parent_enum(sema.db);
let krate = enum_.module(sema.db).krate(); let krate = enum_.module(sema.db).krate();
let from_trait = FamousDefs(sema, Some(krate)).core_convert_From()?; let from_trait = FamousDefs(sema, krate).core_convert_From()?;
let enum_type = enum_.ty(sema.db); let enum_type = enum_.ty(sema.db);

View file

@ -73,7 +73,7 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
get_fn_target(ctx, &target_module, call.clone())? get_fn_target(ctx, &target_module, call.clone())?
} }
Some(hir::PathResolution::Def(hir::ModuleDef::Adt(adt))) => { Some(hir::PathResolution::Def(hir::ModuleDef::Adt(adt))) => {
let current_module = current_module(call.syntax(), ctx)?; let current_module = ctx.sema.scope(call.syntax())?.module();
let module = adt.module(ctx.sema.db); let module = adt.module(ctx.sema.db);
target_module = if current_module == module { None } else { Some(module) }; target_module = if current_module == module { None } else { Some(module) };
if current_module.krate() != module.krate() { if current_module.krate() != module.krate() {
@ -117,7 +117,7 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let fn_name = call.name_ref()?; let fn_name = call.name_ref()?;
let adt = ctx.sema.type_of_expr(&call.receiver()?)?.original().strip_references().as_adt()?; let adt = ctx.sema.type_of_expr(&call.receiver()?)?.original().strip_references().as_adt()?;
let current_module = current_module(call.syntax(), ctx)?; let current_module = ctx.sema.scope(call.syntax())?.module();
let target_module = adt.module(ctx.sema.db); let target_module = adt.module(ctx.sema.db);
if current_module.krate() != target_module.krate() { if current_module.krate() != target_module.krate() {
@ -166,10 +166,6 @@ fn add_func_to_accumulator(
}) })
} }
fn current_module(current_node: &SyntaxNode, ctx: &AssistContext) -> Option<Module> {
ctx.sema.scope(current_node).module()
}
fn get_adt_source( fn get_adt_source(
ctx: &AssistContext, ctx: &AssistContext,
adt: &hir::Adt, adt: &hir::Adt,
@ -235,7 +231,8 @@ impl FunctionBuilder {
target: GeneratedFunctionTarget, target: GeneratedFunctionTarget,
) -> Option<Self> { ) -> Option<Self> {
let needs_pub = target_module.is_some(); let needs_pub = target_module.is_some();
let target_module = target_module.or_else(|| current_module(target.syntax(), ctx))?; let target_module =
target_module.or_else(|| ctx.sema.scope(target.syntax()).map(|it| it.module()))?;
let fn_name = make::name(fn_name); let fn_name = make::name(fn_name);
let (type_params, params) = let (type_params, params) =
fn_args(ctx, target_module, ast::CallableExpr::Call(call.clone()))?; fn_args(ctx, target_module, ast::CallableExpr::Call(call.clone()))?;
@ -266,7 +263,7 @@ impl FunctionBuilder {
target: GeneratedFunctionTarget, target: GeneratedFunctionTarget,
) -> Option<Self> { ) -> Option<Self> {
let needs_pub = let needs_pub =
!module_is_descendant(&current_module(call.syntax(), ctx)?, &target_module, ctx); !module_is_descendant(&ctx.sema.scope(call.syntax())?.module(), &target_module, ctx);
let fn_name = make::name(&name.text()); let fn_name = make::name(&name.text());
let (type_params, params) = let (type_params, params) =
fn_args(ctx, target_module, ast::CallableExpr::MethodCall(call.clone()))?; fn_args(ctx, target_module, ast::CallableExpr::MethodCall(call.clone()))?;
@ -520,7 +517,7 @@ fn fn_arg_type(ctx: &AssistContext, target_module: hir::Module, fn_arg: &ast::Ex
} }
if ty.is_reference() || ty.is_mutable_reference() { if ty.is_reference() || ty.is_mutable_reference() {
let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax()).krate()); let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax())?.krate());
convert_reference_type(ty.strip_references(), ctx.db(), famous_defs) convert_reference_type(ty.strip_references(), ctx.db(), famous_defs)
.map(|conversion| conversion.convert_type(ctx.db())) .map(|conversion| conversion.convert_type(ctx.db()))
.or_else(|| ty.display_source_code(ctx.db(), target_module.into()).ok()) .or_else(|| ty.display_source_code(ctx.db(), target_module.into()).ok())

View file

@ -121,7 +121,9 @@ pub(crate) fn generate_getter_impl(
"a mutable reference to ", "a mutable reference to ",
) )
} else { } else {
let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(field_ty.syntax()).krate()); (|| {
let krate = ctx.sema.scope(field_ty.syntax())?.krate();
let famous_defs = &FamousDefs(&ctx.sema, krate);
ctx.sema ctx.sema
.resolve_type(&field_ty) .resolve_type(&field_ty)
.and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs)) .and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs))
@ -133,12 +135,9 @@ pub(crate) fn generate_getter_impl(
if conversion.is_copy() { "" } else { "a reference to " }, if conversion.is_copy() { "" } else { "a reference to " },
) )
}) })
})()
.unwrap_or_else(|| { .unwrap_or_else(|| {
( (format!("&{}", field_ty), format!("&self.{}", field_name), "a reference to ")
format!("&{}", field_ty),
format!("&self.{}", field_name),
"a reference to ",
)
}) })
}; };

View file

@ -93,7 +93,7 @@ fn get_impl_method(
let db = ctx.sema.db; let db = ctx.sema.db;
let impl_def: hir::Impl = ctx.sema.to_def(impl_)?; let impl_def: hir::Impl = ctx.sema.to_def(impl_)?;
let scope = ctx.sema.scope(impl_.syntax()); let scope = ctx.sema.scope(impl_.syntax())?;
let ty = impl_def.self_ty(db); let ty = impl_def.self_ty(db);
let traits_in_scope = scope.visible_traits(); let traits_in_scope = scope.visible_traits();
ty.iterate_method_candidates(db, &scope, &traits_in_scope, None, Some(fn_name), |func| { ty.iterate_method_candidates(db, &scope, &traits_in_scope, None, Some(fn_name), |func| {

View file

@ -391,14 +391,12 @@ fn inline(
} }
} }
if let Some(generic_arg_list) = generic_arg_list.clone() { if let Some(generic_arg_list) = generic_arg_list.clone() {
PathTransform::function_call( if let Some((target, source)) = &sema.scope(node.syntax()).zip(sema.scope(fn_body.syntax()))
&sema.scope(node.syntax()), {
&sema.scope(fn_body.syntax()), PathTransform::function_call(target, source, function, generic_arg_list)
function,
generic_arg_list,
)
.apply(body.syntax()); .apply(body.syntax());
} }
}
let original_indentation = match node { let original_indentation = match node {
ast::CallableExpr::Call(it) => it.indent_level(), ast::CallableExpr::Call(it) => it.indent_level(),

View file

@ -53,7 +53,7 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext) ->
} }
let let_stmt = pat.syntax().parent().and_then(ast::LetStmt::cast)?; let let_stmt = pat.syntax().parent().and_then(ast::LetStmt::cast)?;
let module = ctx.sema.scope(pat.syntax()).module()?; let module = ctx.sema.scope(pat.syntax())?.module();
let local = ctx.sema.to_def(&pat)?; let local = ctx.sema.to_def(&pat)?;
let ty = ctx.sema.type_of_pat(&pat.into())?.original; let ty = ctx.sema.type_of_pat(&pat.into())?.original;

View file

@ -44,7 +44,7 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext) -> Opt
let range = call.syntax().text_range(); let range = call.syntax().text_range();
let resolved_call = ctx.sema.resolve_method_call(&call)?; let resolved_call = ctx.sema.resolve_method_call(&call)?;
let current_module = ctx.sema.scope(call.syntax()).module()?; let current_module = ctx.sema.scope(call.syntax())?.module();
let target_module_def = ModuleDef::from(resolved_call); let target_module_def = ModuleDef::from(resolved_call);
let item_in_ns = ItemInNs::from(target_module_def); let item_in_ns = ItemInNs::from(target_module_def);
let receiver_path = current_module let receiver_path = current_module

View file

@ -69,7 +69,7 @@ pub(crate) fn replace_derive_with_manual_impl(
let attr = ast::Attr::cast(value)?; let attr = ast::Attr::cast(value)?;
let args = attr.token_tree()?; let args = attr.token_tree()?;
let current_module = ctx.sema.scope(adt.syntax()).module()?; let current_module = ctx.sema.scope(adt.syntax())?.module();
let current_crate = current_module.krate(); let current_crate = current_module.krate();
let found_traits = items_locator::items_with_name( let found_traits = items_locator::items_with_name(
@ -177,7 +177,7 @@ fn impl_def_from_trait(
trait_path: &ast::Path, trait_path: &ast::Path,
) -> Option<(ast::Impl, ast::AssocItem)> { ) -> Option<(ast::Impl, ast::AssocItem)> {
let trait_ = trait_?; let trait_ = trait_?;
let target_scope = sema.scope(annotated_name.syntax()); let target_scope = sema.scope(annotated_name.syntax())?;
let trait_items = filter_assoc_items(sema, &trait_.items(sema.db), DefaultMethods::No); let trait_items = filter_assoc_items(sema, &trait_.items(sema.db), DefaultMethods::No);
if trait_items.is_empty() { if trait_items.is_empty() {
return None; return None;

View file

@ -63,9 +63,11 @@ pub(crate) fn replace_qualified_name_with_use(
); );
let path_to_qualifier = starts_with_name_ref let path_to_qualifier = starts_with_name_ref
.then(|| { .then(|| {
ctx.sema.scope(path.syntax()).module().and_then(|m| { ctx.sema.scope(path.syntax())?.module().find_use_path_prefixed(
m.find_use_path_prefixed(ctx.sema.db, module, ctx.config.insert_use.prefix_kind) ctx.sema.db,
}) module,
ctx.config.insert_use.prefix_kind,
)
}) })
.flatten(); .flatten();

View file

@ -38,9 +38,9 @@ pub(crate) fn unwrap_result_return_type(acc: &mut Assists, ctx: &AssistContext)
}; };
let type_ref = &ret_type.ty()?; let type_ref = &ret_type.ty()?;
let ty = ctx.sema.resolve_type(type_ref).and_then(|ty| ty.as_adt()); let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
let result_enum = let result_enum =
FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax()).krate()).core_result_Result()?; FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate()).core_result_Result()?;
if !matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == result_enum) { if !matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == result_enum) {
return None; return None;

View file

@ -39,9 +39,9 @@ pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext)
}; };
let type_ref = &ret_type.ty()?; let type_ref = &ret_type.ty()?;
let ty = ctx.sema.resolve_type(type_ref).and_then(|ty| ty.as_adt()); let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
let result_enum = let result_enum =
FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax()).krate()).core_result_Result()?; FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate()).core_result_Result()?;
if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == result_enum) { if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == result_enum) {
cov_mark::hit!(wrap_return_type_in_result_simple_return_type_already_result); cov_mark::hit!(wrap_return_type_in_result_simple_return_type_already_result);

View file

@ -352,14 +352,6 @@ fn enum_variants_with_paths(
) { ) {
let variants = enum_.variants(ctx.db); let variants = enum_.variants(ctx.db);
let module = if let Some(module) = ctx.module {
// Compute path from the completion site if available.
module
} else {
// Otherwise fall back to the enum's definition site.
enum_.module(ctx.db)
};
if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
if impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_)) { if impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_)) {
for &variant in &variants { for &variant in &variants {
@ -373,7 +365,7 @@ fn enum_variants_with_paths(
} }
for variant in variants { for variant in variants {
if let Some(path) = module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) { if let Some(path) = ctx.module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) {
// Variants with trivial paths are already added by the existing completion logic, // Variants with trivial paths are already added by the existing completion logic,
// so we should avoid adding these twice // so we should avoid adding these twice
if path.segments().len() > 1 { if path.segments().len() > 1 {

View file

@ -91,7 +91,7 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
_ => return, _ => return,
}; };
for (name, def) in module.scope(ctx.db, ctx.module) { for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
if let Some(def) = module_or_attr(ctx.db, def) { if let Some(def) = module_or_attr(ctx.db, def) {
acc.add_resolution(ctx, name, def); acc.add_resolution(ctx, name, def);
} }

View file

@ -27,26 +27,17 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
Some("target_os") => KNOWN_OS.iter().copied().for_each(add_completion), Some("target_os") => KNOWN_OS.iter().copied().for_each(add_completion),
Some("target_vendor") => KNOWN_VENDOR.iter().copied().for_each(add_completion), Some("target_vendor") => KNOWN_VENDOR.iter().copied().for_each(add_completion),
Some("target_endian") => ["little", "big"].into_iter().for_each(add_completion), Some("target_endian") => ["little", "big"].into_iter().for_each(add_completion),
Some(name) => { Some(name) => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| {
if let Some(krate) = ctx.krate {
krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| {
let insert_text = format!(r#""{}""#, s); let insert_text = format!(r#""{}""#, s);
let mut item = let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
item.insert_text(insert_text); item.insert_text(insert_text);
acc.add(item.build()); acc.add(item.build());
}) }),
}; None => ctx.krate.potential_cfg(ctx.db).get_cfg_keys().cloned().for_each(|s| {
}
None => {
if let Some(krate) = ctx.krate {
krate.potential_cfg(ctx.db).get_cfg_keys().cloned().for_each(|s| {
let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s); let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
acc.add(item.build()); acc.add(item.build());
}) }),
}
}
}; };
} }

View file

@ -34,7 +34,7 @@ pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) {
_ => return, _ => return,
}; };
for (name, def) in module.scope(ctx.db, ctx.module) { for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
let add_def = match def { let add_def = match def {
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => { ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
!ctx.existing_derives.contains(&mac) && mac.is_derive(ctx.db) !ctx.existing_derives.contains(&mac) && mac.is_derive(ctx.db)

View file

@ -87,7 +87,7 @@ fn complete_methods(
ctx.db, ctx.db,
&ctx.scope, &ctx.scope,
&traits_in_scope, &traits_in_scope,
ctx.module, Some(ctx.module),
None, None,
|func| { |func| {
if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) { if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {

View file

@ -225,7 +225,7 @@ pub(crate) fn position_for_import(
} }
fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> { fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> {
let current_module = ctx.module?; let current_module = ctx.module;
if let Some(dot_receiver) = ctx.dot_receiver() { if let Some(dot_receiver) = ctx.dot_receiver() {
ImportAssets::for_fuzzy_method_call( ImportAssets::for_fuzzy_method_call(
current_module, current_module,

View file

@ -120,19 +120,19 @@ fn params_from_stmt_list_scope(
Some(it) => it, Some(it) => it,
None => return, None => return,
}; };
let scope = ctx.sema.scope_at_offset(stmt_list.syntax(), syntax_node.text_range().end()); if let Some(scope) =
let module = match scope.module() { ctx.sema.scope_at_offset(stmt_list.syntax(), syntax_node.text_range().end())
Some(it) => it, {
None => return, let module = scope.module().into();
};
scope.process_all_names(&mut |name, def| { scope.process_all_names(&mut |name, def| {
if let hir::ScopeDef::Local(local) = def { if let hir::ScopeDef::Local(local) = def {
if let Ok(ty) = local.ty(ctx.db).display_source_code(ctx.db, module.into()) { if let Ok(ty) = local.ty(ctx.db).display_source_code(ctx.db, module) {
cb(name, ty); cb(name, ty);
} }
} }
}); });
} }
}
fn remove_duplicated( fn remove_duplicated(
file_params: &mut FxHashMap<String, String>, file_params: &mut FxHashMap<String, String>,

View file

@ -22,7 +22,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
let _p = profile::span("completion::complete_mod"); let _p = profile::span("completion::complete_mod");
let current_module = ctx.module?; let current_module = ctx.module;
let module_definition_file = let module_definition_file =
current_module.definition_source(ctx.db).file_id.original_file(ctx.db); current_module.definition_source(ctx.db).file_id.original_file(ctx.db);

View file

@ -122,7 +122,7 @@ fn pattern_path_completion(
match resolution { match resolution {
hir::PathResolution::Def(hir::ModuleDef::Module(module)) => { hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
let module_scope = module.scope(ctx.db, ctx.module); let module_scope = module.scope(ctx.db, Some(ctx.module));
for (name, def) in module_scope { for (name, def) in module_scope {
let add_resolution = match def { let add_resolution = match def {
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => { ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
@ -169,7 +169,7 @@ fn pattern_path_completion(
ctx.db, ctx.db,
&ctx.scope, &ctx.scope,
&traits_in_scope, &traits_in_scope,
ctx.module, Some(ctx.module),
None, None,
|item| { |item| {
match item { match item {

View file

@ -57,7 +57,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
match ctx.completion_location { match ctx.completion_location {
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => { Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution { if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
for (name, def) in module.scope(ctx.db, ctx.module) { for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
if let Some(def) = module_or_fn_macro(ctx.db, def) { if let Some(def) = module_or_fn_macro(ctx.db, def) {
acc.add_resolution(ctx, name, def); acc.add_resolution(ctx, name, def);
} }
@ -89,7 +89,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
match resolution { match resolution {
hir::PathResolution::Def(hir::ModuleDef::Module(module)) => { hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
let module_scope = module.scope(ctx.db, ctx.module); let module_scope = module.scope(ctx.db, Some(ctx.module));
for (name, def) in module_scope { for (name, def) in module_scope {
let add_resolution = match def { let add_resolution = match def {
// Don't suggest attribute macros and derives. // Don't suggest attribute macros and derives.
@ -141,14 +141,12 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
// XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType. // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
// (where AssocType is defined on a trait, not an inherent impl) // (where AssocType is defined on a trait, not an inherent impl)
let krate = ctx.krate;
if let Some(krate) = krate {
let traits_in_scope = traits_in_scope(ctx); let traits_in_scope = traits_in_scope(ctx);
ty.iterate_path_candidates( ty.iterate_path_candidates(
ctx.db, ctx.db,
&ctx.scope, &ctx.scope,
&traits_in_scope, &traits_in_scope,
ctx.module, Some(ctx.module),
None, None,
|item| { |item| {
add_assoc_item(acc, ctx, item); add_assoc_item(acc, ctx, item);
@ -157,14 +155,13 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
); );
// Iterate assoc types separately // Iterate assoc types separately
ty.iterate_assoc_items(ctx.db, krate, |item| { ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
if let hir::AssocItem::TypeAlias(ty) = item { if let hir::AssocItem::TypeAlias(ty) = item {
acc.add_type_alias(ctx, ty) acc.add_type_alias(ctx, ty)
} }
None::<()> None::<()>
}); });
} }
}
hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => { hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
// Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`. // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
for item in t.items(ctx.db) { for item in t.items(ctx.db) {
@ -187,7 +184,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
ctx.db, ctx.db,
&ctx.scope, &ctx.scope,
&traits_in_scope, &traits_in_scope,
ctx.module, Some(ctx.module),
None, None,
|item| { |item| {
// We might iterate candidates of a trait multiple times here, so deduplicate // We might iterate candidates of a trait multiple times here, so deduplicate

View file

@ -83,17 +83,18 @@ pub(crate) fn complete_record_literal(
match ctx.expected_type.as_ref()?.as_adt()? { match ctx.expected_type.as_ref()?.as_adt()? {
hir::Adt::Struct(strukt) if ctx.path_qual().is_none() => { hir::Adt::Struct(strukt) if ctx.path_qual().is_none() => {
let module = if let Some(module) = ctx.module { module } else { strukt.module(ctx.db) }; let path = ctx
let path = module .module
.find_use_path(ctx.db, hir::ModuleDef::from(strukt)) .find_use_path(ctx.db, hir::ModuleDef::from(strukt))
.filter(|it| it.len() > 1); .filter(|it| it.len() > 1);
acc.add_struct_literal(ctx, strukt, path, None); acc.add_struct_literal(ctx, strukt, path, None);
} }
hir::Adt::Union(un) if ctx.path_qual().is_none() => { hir::Adt::Union(un) if ctx.path_qual().is_none() => {
let module = if let Some(module) = ctx.module { module } else { un.module(ctx.db) }; let path = ctx
let path = .module
module.find_use_path(ctx.db, hir::ModuleDef::from(un)).filter(|it| it.len() > 1); .find_use_path(ctx.db, hir::ModuleDef::from(un))
.filter(|it| it.len() > 1);
acc.add_union_literal(ctx, un, path, None); acc.add_union_literal(ctx, un, path, None);
} }

View file

@ -183,7 +183,7 @@ fn get_transformed_assoc_item(
let assoc_item = assoc_item.clone_for_update(); let assoc_item = assoc_item.clone_for_update();
let trait_ = impl_def.trait_(ctx.db)?; let trait_ = impl_def.trait_(ctx.db)?;
let source_scope = &ctx.sema.scope_for_def(trait_); let source_scope = &ctx.sema.scope_for_def(trait_);
let target_scope = &ctx.sema.scope(ctx.sema.source(impl_def)?.syntax().value); let target_scope = &ctx.sema.scope(ctx.sema.source(impl_def)?.syntax().value)?;
let transform = PathTransform::trait_impl( let transform = PathTransform::trait_impl(
target_scope, target_scope,
source_scope, source_scope,

View file

@ -41,7 +41,7 @@ pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext)
match resolution { match resolution {
hir::PathResolution::Def(hir::ModuleDef::Module(module)) => { hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
let module_scope = module.scope(ctx.db, ctx.module); let module_scope = module.scope(ctx.db, Some(ctx.module));
let unknown_is_current = |name: &hir::Name| { let unknown_is_current = |name: &hir::Name| {
matches!( matches!(
ctx.name_syntax.as_ref(), ctx.name_syntax.as_ref(),

View file

@ -22,8 +22,8 @@ pub(crate) fn complete_vis(acc: &mut Completions, ctx: &CompletionContext) {
Some(PathQualifierCtx { resolution, is_super_chain, .. }) => { Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
// Try completing next child module of the path that is still a parent of the current module // Try completing next child module of the path that is still a parent of the current module
if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = resolution { if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = resolution {
if let Some(current_module) = ctx.module { let next_towards_current = ctx
let next_towards_current = current_module .module
.path_to_root(ctx.db) .path_to_root(ctx.db)
.into_iter() .into_iter()
.take_while(|it| it != module) .take_while(|it| it != module)
@ -35,7 +35,6 @@ pub(crate) fn complete_vis(acc: &mut Completions, ctx: &CompletionContext) {
} }
} }
} }
}
if *is_super_chain { if *is_super_chain {
acc.add_keyword(ctx, "super::"); acc.add_keyword(ctx, "super::");

View file

@ -121,9 +121,9 @@ pub(crate) struct CompletionContext<'a> {
/// The token before the cursor, in the macro-expanded file. /// The token before the cursor, in the macro-expanded file.
pub(super) token: SyntaxToken, pub(super) token: SyntaxToken,
/// The crate of the current file. /// The crate of the current file.
pub(super) krate: Option<hir::Crate>, pub(super) krate: hir::Crate,
/// The module of the `scope`. /// The module of the `scope`.
pub(super) module: Option<hir::Module>, pub(super) module: hir::Module,
pub(super) expected_name: Option<NameOrNameRef>, pub(super) expected_name: Option<NameOrNameRef>,
pub(super) expected_type: Option<Type>, pub(super) expected_type: Option<Type>,
@ -353,11 +353,7 @@ impl<'a> CompletionContext<'a> {
attrs: &hir::Attrs, attrs: &hir::Attrs,
defining_crate: hir::Crate, defining_crate: hir::Crate,
) -> Visible { ) -> Visible {
let module = match self.module { if !vis.is_visible_from(self.db, self.module.into()) {
Some(it) => it,
None => return Visible::No,
};
if !vis.is_visible_from(self.db, module.into()) {
if !self.config.enable_private_editable { if !self.config.enable_private_editable {
return Visible::No; return Visible::No;
} }
@ -376,11 +372,8 @@ impl<'a> CompletionContext<'a> {
} }
fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool { fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
match self.krate {
// `doc(hidden)` items are only completed within the defining crate. // `doc(hidden)` items are only completed within the defining crate.
Some(krate) => krate != defining_crate && attrs.has_doc_hidden(), self.krate != defining_crate && attrs.has_doc_hidden()
None => true,
}
} }
} }
@ -409,7 +402,7 @@ impl<'a> CompletionContext<'a> {
let original_token = original_file.syntax().token_at_offset(offset).left_biased()?; let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
let token = sema.descend_into_macros_single(original_token.clone()); let token = sema.descend_into_macros_single(original_token.clone());
let scope = sema.scope_at_offset(&token.parent()?, offset); let scope = sema.scope_at_offset(&token.parent()?, offset)?;
let krate = scope.krate(); let krate = scope.krate();
let module = scope.module(); let module = scope.module();
let mut locals = FxHashMap::default(); let mut locals = FxHashMap::default();

View file

@ -185,7 +185,7 @@ pub fn resolve_completion_edits(
let position_for_import = &position_for_import(&ctx, None)?; let position_for_import = &position_for_import(&ctx, None)?;
let scope = ImportScope::find_insert_use_container(position_for_import, &ctx.sema)?; let scope = ImportScope::find_insert_use_container(position_for_import, &ctx.sema)?;
let current_module = ctx.sema.scope(position_for_import).module()?; let current_module = ctx.sema.scope(position_for_import)?.module();
let current_crate = current_module.krate(); let current_crate = current_module.krate();
let new_ast = scope.clone_for_update(); let new_ast = scope.clone_for_update();
let mut import_insert = TextEdit::builder(); let mut import_insert = TextEdit::builder();

View file

@ -72,7 +72,7 @@ pub(crate) fn visible_fields(
fields: &[hir::Field], fields: &[hir::Field],
item: impl HasAttrs, item: impl HasAttrs,
) -> Option<(Vec<hir::Field>, bool)> { ) -> Option<(Vec<hir::Field>, bool)> {
let module = ctx.module?; let module = ctx.module;
let n_fields = fields.len(); let n_fields = fields.len();
let fields = fields let fields = fields
.iter() .iter()

View file

@ -185,7 +185,7 @@ fn import_edits(
_ => return None, _ => return None,
}; };
let path = let path =
ctx.module?.find_use_path_prefixed(ctx.db, item, ctx.config.insert_use.prefix_kind)?; ctx.module.find_use_path_prefixed(ctx.db, item, ctx.config.insert_use.prefix_kind)?;
Some((path.len() > 1).then(|| ImportEdit { Some((path.len() > 1).then(|| ImportEdit {
import: LocatedImport::new(path.clone(), item, item, None), import: LocatedImport::new(path.clone(), item, item, None),
scope: import_scope.clone(), scope: import_scope.clone(),

View file

@ -18,7 +18,7 @@ use crate::RootDatabase;
/// ``` /// ```
/// //- minicore: iterator, ord, derive /// //- minicore: iterator, ord, derive
/// ``` /// ```
pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>); pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Crate);
#[allow(non_snake_case)] #[allow(non_snake_case)]
impl FamousDefs<'_, '_> { impl FamousDefs<'_, '_> {
@ -142,7 +142,7 @@ impl FamousDefs<'_, '_> {
} }
fn find_lang_crate(&self, origin: LangCrateOrigin) -> Option<Crate> { fn find_lang_crate(&self, origin: LangCrateOrigin) -> Option<Crate> {
let krate = self.1?; let krate = self.1;
let db = self.0.db; let db = self.0.db;
let crate_graph = self.0.db.crate_graph(); let crate_graph = self.0.db.crate_graph();
let res = krate let res = krate

View file

@ -104,7 +104,7 @@ impl ImportAssets {
let candidate_node = method_call.syntax().clone(); let candidate_node = method_call.syntax().clone();
Some(Self { Some(Self {
import_candidate: ImportCandidate::for_method_call(sema, method_call)?, import_candidate: ImportCandidate::for_method_call(sema, method_call)?,
module_with_candidate: sema.scope(&candidate_node).module()?, module_with_candidate: sema.scope(&candidate_node)?.module(),
candidate_node, candidate_node,
}) })
} }
@ -119,7 +119,7 @@ impl ImportAssets {
} }
Some(Self { Some(Self {
import_candidate: ImportCandidate::for_regular_path(sema, fully_qualified_path)?, import_candidate: ImportCandidate::for_regular_path(sema, fully_qualified_path)?,
module_with_candidate: sema.scope(&candidate_node).module()?, module_with_candidate: sema.scope(&candidate_node)?.module(),
candidate_node, candidate_node,
}) })
} }
@ -132,7 +132,7 @@ impl ImportAssets {
let candidate_node = pat.syntax().clone(); let candidate_node = pat.syntax().clone();
Some(Self { Some(Self {
import_candidate: ImportCandidate::for_name(sema, &name)?, import_candidate: ImportCandidate::for_name(sema, &name)?,
module_with_candidate: sema.scope(&candidate_node).module()?, module_with_candidate: sema.scope(&candidate_node)?.module(),
candidate_node, candidate_node,
}) })
} }
@ -248,7 +248,10 @@ impl ImportAssets {
}; };
let krate = self.module_with_candidate.krate(); let krate = self.module_with_candidate.krate();
let scope = sema.scope(&self.candidate_node); let scope = match sema.scope(&self.candidate_node) {
Some(it) => it,
None => return Vec::new(),
};
match &self.import_candidate { match &self.import_candidate {
ImportCandidate::Path(path_candidate) => { ImportCandidate::Path(path_candidate) => {
@ -271,9 +274,11 @@ impl ImportAssets {
fn scope_definitions(&self, sema: &Semantics<RootDatabase>) -> FxHashSet<ScopeDef> { fn scope_definitions(&self, sema: &Semantics<RootDatabase>) -> FxHashSet<ScopeDef> {
let _p = profile::span("import_assets::scope_definitions"); let _p = profile::span("import_assets::scope_definitions");
let mut scope_definitions = FxHashSet::default(); let mut scope_definitions = FxHashSet::default();
sema.scope(&self.candidate_node).process_all_names(&mut |_, scope_def| { if let Some(scope) = sema.scope(&self.candidate_node) {
scope.process_all_names(&mut |_, scope_def| {
scope_definitions.insert(scope_def); scope_definitions.insert(scope_def);
}); });
}
scope_definitions scope_definitions
} }
} }
@ -588,7 +593,7 @@ impl ImportCandidate {
fn for_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Self> { fn for_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Self> {
if sema if sema
.scope(name.syntax()) .scope(name.syntax())?
.speculative_resolve(&ast::make::ext::ident_path(&name.text())) .speculative_resolve(&ast::make::ext::ident_path(&name.text()))
.is_some() .is_some()
{ {

View file

@ -69,15 +69,13 @@ impl<'a> PathTransform<'a> {
} }
pub fn apply(&self, syntax: &SyntaxNode) { pub fn apply(&self, syntax: &SyntaxNode) {
if let Some(ctx) = self.build_ctx() { self.build_ctx().apply(syntax)
ctx.apply(syntax)
}
} }
fn build_ctx(&self) -> Option<Ctx<'a>> { fn build_ctx(&self) -> Ctx<'a> {
let db = self.source_scope.db; let db = self.source_scope.db;
let target_module = self.target_scope.module()?; let target_module = self.target_scope.module();
let source_module = self.source_scope.module()?; let source_module = self.source_scope.module();
let skip = match self.generic_def { let skip = match self.generic_def {
// this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
hir::GenericDef::Trait(_) => 1, hir::GenericDef::Trait(_) => 1,
@ -111,8 +109,7 @@ impl<'a> PathTransform<'a> {
}, },
}) })
.collect(); .collect();
let res = Ctx { substs: substs_by_param, target_module, source_scope: self.source_scope }; Ctx { substs: substs_by_param, target_module, source_scope: self.source_scope }
Some(res)
} }
} }

View file

@ -64,7 +64,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
let new_field_list = old_field_list.clone_for_update(); let new_field_list = old_field_list.clone_for_update();
let mut locals = FxHashMap::default(); let mut locals = FxHashMap::default();
ctx.sema.scope(field_list_parent.syntax()).process_all_names(&mut |name, def| { ctx.sema.scope(field_list_parent.syntax())?.process_all_names(&mut |name, def| {
if let hir::ScopeDef::Local(local) = def { if let hir::ScopeDef::Local(local) = def {
locals.insert(name, local); locals.insert(name, local);
} }
@ -171,11 +171,7 @@ fn get_default_constructor(
if has_new_func { if has_new_func {
Some(make::ext::expr_ty_new(&make_ty(ty, ctx.sema.db, module))) Some(make::ext::expr_ty_new(&make_ty(ty, ctx.sema.db, module)))
} else if !ty.is_array() } else if !ty.is_array()
&& ty.impls_trait( && ty.impls_trait(ctx.sema.db, FamousDefs(&ctx.sema, krate).core_default_Default()?, &[])
ctx.sema.db,
FamousDefs(&ctx.sema, Some(krate)).core_default_Default()?,
&[],
)
{ {
Some(make::ext::expr_ty_default(&make_ty(ty, ctx.sema.db, module))) Some(make::ext::expr_ty_default(&make_ty(ty, ctx.sema.db, module)))
} else { } else {

View file

@ -76,7 +76,7 @@ fn add_missing_ok_or_some(
let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?; let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?;
let expr = d.expr.value.to_node(&root); let expr = d.expr.value.to_node(&root);
let expr_range = expr.syntax().text_range(); let expr_range = expr.syntax().text_range();
let scope = ctx.sema.scope(expr.syntax()); let scope = ctx.sema.scope(expr.syntax())?;
let expected_adt = d.expected.as_adt()?; let expected_adt = d.expected.as_adt()?;
let expected_enum = expected_adt.as_enum()?; let expected_enum = expected_adt.as_enum()?;

View file

@ -25,7 +25,7 @@ pub fn ssr_from_comment(db: &RootDatabase, frange: FileRange) -> Option<(MatchFi
let lookup_context = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; let lookup_context = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
let mut match_finder = MatchFinder::in_context(db, lookup_context, vec![]); let mut match_finder = MatchFinder::in_context(db, lookup_context, vec![]).ok()?;
match_finder.add_rule(ssr_rule).ok()?; match_finder.add_rule(ssr_rule).ok()?;
Some((match_finder, comment.syntax().text_range())) Some((match_finder, comment.syntax().text_range()))

View file

@ -128,11 +128,12 @@ impl<'db> MatchFinder<'db> {
db: &'db ide_db::RootDatabase, db: &'db ide_db::RootDatabase,
lookup_context: FilePosition, lookup_context: FilePosition,
mut restrict_ranges: Vec<FileRange>, mut restrict_ranges: Vec<FileRange>,
) -> MatchFinder<'db> { ) -> Result<MatchFinder<'db>, SsrError> {
restrict_ranges.retain(|range| !range.range.is_empty()); restrict_ranges.retain(|range| !range.range.is_empty());
let sema = Semantics::new(db); let sema = Semantics::new(db);
let resolution_scope = resolving::ResolutionScope::new(&sema, lookup_context); let resolution_scope = resolving::ResolutionScope::new(&sema, lookup_context)
MatchFinder { sema, rules: Vec::new(), resolution_scope, restrict_ranges } .ok_or_else(|| SsrError("no resolution scope for file".into()))?;
Ok(MatchFinder { sema, rules: Vec::new(), resolution_scope, restrict_ranges })
} }
/// Constructs an instance using the start of the first file in `db` as the lookup context. /// Constructs an instance using the start of the first file in `db` as the lookup context.
@ -142,11 +143,11 @@ impl<'db> MatchFinder<'db> {
if let Some(first_file_id) = if let Some(first_file_id) =
db.local_roots().iter().next().and_then(|root| db.source_root(*root).iter().next()) db.local_roots().iter().next().and_then(|root| db.source_root(*root).iter().next())
{ {
Ok(MatchFinder::in_context( MatchFinder::in_context(
db, db,
FilePosition { file_id: first_file_id, offset: 0.into() }, FilePosition { file_id: first_file_id, offset: 0.into() },
vec![], vec![],
)) )
} else { } else {
bail!("No files to search"); bail!("No files to search");
} }

View file

@ -646,8 +646,8 @@ impl Match {
) -> Result<(), MatchFailed> { ) -> Result<(), MatchFailed> {
let module = sema let module = sema
.scope(&self.matched_node) .scope(&self.matched_node)
.module() .ok_or_else(|| match_error!("Matched node isn't in a module"))?
.ok_or_else(|| match_error!("Matched node isn't in a module"))?; .module();
for (path, resolved_path) in &template.resolved_paths { for (path, resolved_path) in &template.resolved_paths {
if let hir::PathResolution::Def(module_def) = resolved_path.resolution { if let hir::PathResolution::Def(module_def) = resolved_path.resolution {
let mod_path = module.find_use_path(sema.db, module_def).ok_or_else(|| { let mod_path = module.find_use_path(sema.db, module_def).ok_or_else(|| {
@ -788,7 +788,7 @@ mod tests {
let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }"; let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }";
let (db, position, selections) = crate::tests::single_file(input); let (db, position, selections) = crate::tests::single_file(input);
let mut match_finder = MatchFinder::in_context(&db, position, selections); let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
match_finder.add_rule(rule).unwrap(); match_finder.add_rule(rule).unwrap();
let matches = match_finder.matches(); let matches = match_finder.matches();
assert_eq!(matches.matches.len(), 1); assert_eq!(matches.matches.len(), 1);

View file

@ -186,7 +186,7 @@ impl<'db> ResolutionScope<'db> {
pub(crate) fn new( pub(crate) fn new(
sema: &hir::Semantics<'db, ide_db::RootDatabase>, sema: &hir::Semantics<'db, ide_db::RootDatabase>,
resolve_context: FilePosition, resolve_context: FilePosition,
) -> ResolutionScope<'db> { ) -> Option<ResolutionScope<'db>> {
use syntax::ast::AstNode; use syntax::ast::AstNode;
let file = sema.parse(resolve_context.file_id); let file = sema.parse(resolve_context.file_id);
// Find a node at the requested position, falling back to the whole file. // Find a node at the requested position, falling back to the whole file.
@ -197,8 +197,8 @@ impl<'db> ResolutionScope<'db> {
.and_then(|token| token.parent()) .and_then(|token| token.parent())
.unwrap_or_else(|| file.syntax().clone()); .unwrap_or_else(|| file.syntax().clone());
let node = pick_node_for_resolution(node); let node = pick_node_for_resolution(node);
let scope = sema.scope(&node); let scope = sema.scope(&node)?;
ResolutionScope { scope, node } Some(ResolutionScope { scope, node })
} }
/// Returns the function in which SSR was invoked, if any. /// Returns the function in which SSR was invoked, if any.
@ -219,7 +219,7 @@ impl<'db> ResolutionScope<'db> {
let resolved_qualifier = self.scope.speculative_resolve(&path.qualifier()?)?; let resolved_qualifier = self.scope.speculative_resolve(&path.qualifier()?)?;
if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier { if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier {
let name = path.segment()?.name_ref()?; let name = path.segment()?.name_ref()?;
let module = self.scope.module()?; let module = self.scope.module();
adt.ty(self.scope.db).iterate_path_candidates( adt.ty(self.scope.db).iterate_path_candidates(
self.scope.db, self.scope.db,
&self.scope, &self.scope,

View file

@ -94,7 +94,7 @@ fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) {
fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) { fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
let (db, position, selections) = single_file(input); let (db, position, selections) = single_file(input);
let mut match_finder = MatchFinder::in_context(&db, position, selections); let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
for rule in rules { for rule in rules {
let rule: SsrRule = rule.parse().unwrap(); let rule: SsrRule = rule.parse().unwrap();
match_finder.add_rule(rule).unwrap(); match_finder.add_rule(rule).unwrap();
@ -124,7 +124,7 @@ fn print_match_debug_info(match_finder: &MatchFinder, file_id: FileId, snippet:
fn assert_matches(pattern: &str, code: &str, expected: &[&str]) { fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
let (db, position, selections) = single_file(code); let (db, position, selections) = single_file(code);
let mut match_finder = MatchFinder::in_context(&db, position, selections); let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
let matched_strings: Vec<String> = let matched_strings: Vec<String> =
match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect(); match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect();
@ -136,7 +136,7 @@ fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
fn assert_no_match(pattern: &str, code: &str) { fn assert_no_match(pattern: &str, code: &str) {
let (db, position, selections) = single_file(code); let (db, position, selections) = single_file(code);
let mut match_finder = MatchFinder::in_context(&db, position, selections); let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
let matches = match_finder.matches().flattened().matches; let matches = match_finder.matches().flattened().matches;
if !matches.is_empty() { if !matches.is_empty() {
@ -147,7 +147,7 @@ fn assert_no_match(pattern: &str, code: &str) {
fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) { fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expected_reason: &str) {
let (db, position, selections) = single_file(code); let (db, position, selections) = single_file(code);
let mut match_finder = MatchFinder::in_context(&db, position, selections); let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
let mut reasons = Vec::new(); let mut reasons = Vec::new();
for d in match_finder.debug_where_text_equal(position.file_id, snippet) { for d in match_finder.debug_where_text_equal(position.file_id, snippet) {