Repository: rust-analyzer/rust-analyzer
Pull request #11869 (2022-04-01 06:34:38)

fix: code blocks with tilde also works like code block
The `rustdoc` uses the `pulldown_cmark` package to parse *doc_comment* and the package also treat triple `~` characters also as code block fences. So when we run `cargo doc`, they will be placed also.

<img width="965" alt="image" src="https://user-images.githubusercontent.com/26626194/161208072-5a09a209-57fc-4a52-b190-b0a9be9ffcd6.png">

But `rust-analyzer` doesn't support it so it doesn't have any injected code highlights and any `Run doctest` hint. This pull request tries to allow also them. 🙇🏻‍♂️ 

Before:

<img width="224" alt="image" src="https://user-images.githubusercontent.com/26626194/161207405-b1d6cfda-82b1-4f60-8e42-c51d0ed98f38.png">

After:

<img width="161" alt="image" src="https://user-images.githubusercontent.com/26626194/161207693-8e39997c-9ca6-4e69-8c65-e9b70899f7db.png">



Patch:
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs
index daa0e3f699..d1e2d74a98 100644
--- a/crates/base_db/src/fixture.rs
+++ b/crates/base_db/src/fixture.rs
@@ -10,7 +10,7 @@ use tt::Subtree;
 use vfs::{file_set::FileSet, VfsPath};
 
 use crate::{
-    input::{CrateName, CrateOrigin, LangCrateOrigin},
+    input::{CrateName, CrateOrigin},
     Change, CrateDisplayName, CrateGraph, CrateId, Dependency, Edition, Env, FileId, FilePosition,
     FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, SourceDatabaseExt,
     SourceRoot, SourceRootId,
@@ -196,7 +196,7 @@ impl ChangeFixture {
                 Env::default(),
                 Default::default(),
                 false,
-                CrateOrigin::CratesIo { repo: None },
+                Default::default(),
             );
         } else {
             for (from, to, prelude) in crate_deps {
@@ -233,7 +233,7 @@ impl ChangeFixture {
                 Env::default(),
                 Vec::new(),
                 false,
-                CrateOrigin::Lang(LangCrateOrigin::Core),
+                CrateOrigin::Lang,
             );
 
             for krate in all_crates {
@@ -270,7 +270,7 @@ impl ChangeFixture {
                 Env::default(),
                 proc_macro,
                 true,
-                CrateOrigin::CratesIo { repo: None },
+                CrateOrigin::Lang,
             );
 
             for krate in all_crates {
@@ -406,11 +406,7 @@ fn parse_crate(crate_str: String) -> (String, CrateOrigin, Option<String>) {
         };
         (a.to_owned(), origin, Some(version.to_string()))
     } else {
-        let crate_origin = match &*crate_str {
-            "std" => CrateOrigin::Lang(LangCrateOrigin::Std),
-            _ => CrateOrigin::CratesIo { repo: None },
-        };
-        (crate_str, crate_origin, None)
+        (crate_str, CrateOrigin::Unknown, None)
     }
 }
 
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs
index 43d7ccad49..db3f85604b 100644
--- a/crates/base_db/src/input.rs
+++ b/crates/base_db/src/input.rs
@@ -117,22 +117,21 @@ impl ops::Deref for CrateName {
 }
 
 /// Origin of the crates. It is used in emitting monikers.
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone)]
 pub enum CrateOrigin {
     /// Crates that are from crates.io official registry,
     CratesIo { repo: Option<String> },
     /// Crates that are provided by the language, like std, core, proc-macro, ...
-    Lang(LangCrateOrigin),
+    Lang,
+    /// Crates that we don't know their origin.
+    // Ideally this enum should cover all cases, and then we remove this variant.
+    Unknown,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum LangCrateOrigin {
-    Alloc,
-    Core,
-    ProcMacro,
-    Std,
-    Test,
-    Other,
+impl Default for CrateOrigin {
+    fn default() -> Self {
+        Self::Unknown
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -586,8 +585,6 @@ impl fmt::Display for CyclicDependenciesError {
 
 #[cfg(test)]
 mod tests {
-    use crate::CrateOrigin;
-
     use super::{CfgOptions, CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId};
 
     #[test]
@@ -603,7 +600,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         let crate2 = graph.add_crate_root(
             FileId(2u32),
@@ -615,7 +612,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         let crate3 = graph.add_crate_root(
             FileId(3u32),
@@ -627,7 +624,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         assert!(graph
             .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@@ -653,7 +650,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         let crate2 = graph.add_crate_root(
             FileId(2u32),
@@ -665,7 +662,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         assert!(graph
             .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@@ -688,7 +685,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         let crate2 = graph.add_crate_root(
             FileId(2u32),
@@ -700,7 +697,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         let crate3 = graph.add_crate_root(
             FileId(3u32),
@@ -712,7 +709,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         assert!(graph
             .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@@ -735,7 +732,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         let crate2 = graph.add_crate_root(
             FileId(2u32),
@@ -747,7 +744,7 @@ mod tests {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         assert!(graph
             .add_dep(
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs
index 2454698bb6..d80660f7c9 100644
--- a/crates/base_db/src/lib.rs
+++ b/crates/base_db/src/lib.rs
@@ -12,8 +12,8 @@ pub use crate::{
     change::Change,
     input::{
         CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency,
-        Edition, Env, LangCrateOrigin, ProcMacro, ProcMacroExpander, ProcMacroExpansionError,
-        ProcMacroId, ProcMacroKind, SourceRoot, SourceRootId,
+        Edition, Env, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroId,
+        ProcMacroKind, SourceRoot, SourceRootId,
     },
 };
 pub use salsa::{self, Cancelled};
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8b99662685..c07c017c3d 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -148,10 +148,6 @@ impl Crate {
         db.crate_graph()[self.id].origin.clone()
     }
 
-    pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
-        matches!(self.origin(db), CrateOrigin::Lang(_))
-    }
-
     pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
         db.crate_graph()[self.id]
             .dependencies
@@ -1745,8 +1741,10 @@ impl BuiltinType {
         BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
     }
 
-    pub fn ty(self, db: &dyn HirDatabase) -> Type {
-        Type::new_for_crate(db.crate_graph().iter().next().unwrap(), TyBuilder::builtin(self.inner))
+    pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type {
+        let resolver = module.id.resolver(db.upcast());
+        Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner))
+            .expect("crate not present in resolver")
     }
 
     pub fn name(self) -> Name {
@@ -2224,7 +2222,7 @@ impl BuiltinAttr {
         Some(BuiltinAttr { krate: Some(krate.id), idx })
     }
 
-    fn builtin(name: &str) -> Option<Self> {
+    pub(crate) fn builtin(name: &str) -> Option<Self> {
         hir_def::builtin_attr::INERT_ATTRIBUTES
             .iter()
             .position(|tool| tool.name == name)
@@ -2263,7 +2261,7 @@ impl ToolModule {
         Some(ToolModule { krate: Some(krate.id), idx })
     }
 
-    fn builtin(name: &str) -> Option<Self> {
+    pub(crate) fn builtin(name: &str) -> Option<Self> {
         hir_def::builtin_attr::TOOL_MODULES
             .iter()
             .position(|&tool| tool == name)
@@ -2613,11 +2611,14 @@ pub struct Type {
 }
 
 impl Type {
-    pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver, ty: Ty) -> Type {
-        let krate = resolver.krate();
-        Type::new_with_resolver_inner(db, krate, resolver, ty)
+    pub(crate) fn new_with_resolver(
+        db: &dyn HirDatabase,
+        resolver: &Resolver,
+        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(
         db: &dyn HirDatabase,
         krate: CrateId,
@@ -2630,10 +2631,6 @@ impl Type {
         Type { krate, env: environment, ty }
     }
 
-    pub(crate) fn new_for_crate(krate: CrateId, ty: Ty) -> Type {
-        Type { krate, env: Arc::new(TraitEnvironment::empty(krate)), ty }
-    }
-
     pub fn reference(inner: &Type, m: Mutability) -> Type {
         inner.derived(
             TyKind::Ref(
@@ -3034,7 +3031,10 @@ impl Type {
         // There should be no inference vars in types passed here
         let canonical = hir_ty::replace_errors_with_variables(&self.ty);
 
-        let krate = scope.krate();
+        let krate = match scope.krate() {
+            Some(k) => k,
+            None => return,
+        };
         let environment = scope.resolver().generic_def().map_or_else(
             || Arc::new(TraitEnvironment::empty(krate.id)),
             |d| db.trait_environment(d),
@@ -3091,7 +3091,10 @@ impl Type {
     ) {
         let canonical = hir_ty::replace_errors_with_variables(&self.ty);
 
-        let krate = scope.krate();
+        let krate = match scope.krate() {
+            Some(k) => k,
+            None => return,
+        };
         let environment = scope.resolver().generic_def().map_or_else(
             || Arc::new(TraitEnvironment::empty(krate.id)),
             |d| db.trait_environment(d),
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 8a700027a3..4afdde6494 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -403,15 +403,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.to_module_def(file)
     }
 
-    pub fn scope(&self, node: &SyntaxNode) -> Option<SemanticsScope<'db>> {
+    pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
         self.imp.scope(node)
     }
 
-    pub fn scope_at_offset(
-        &self,
-        node: &SyntaxNode,
-        offset: TextSize,
-    ) -> Option<SemanticsScope<'db>> {
+    pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> {
         self.imp.scope_at_offset(node, offset)
     }
 
@@ -460,7 +456,7 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     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 node = self.parse_or_expand(file_id)?;
         Some(node)
@@ -539,9 +535,9 @@ impl<'db> SemanticsImpl<'db> {
         token_to_map: SyntaxToken,
     ) -> Option<(SyntaxNode, SyntaxToken)> {
         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 krate = resolver.krate();
+        let krate = resolver.krate()?;
         let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
             resolver
                 .resolve_path_as_macro(self.db.upcast(), &path)
@@ -673,10 +669,7 @@ impl<'db> SemanticsImpl<'db> {
             Some(it) => it,
             None => return,
         };
-        let sa = match self.analyze_no_infer(&parent) {
-            Some(it) => it,
-            None => return,
-        };
+        let sa = self.analyze_no_infer(&parent);
         let mut stack: SmallVec<[_; 4]> = smallvec![InFile::new(sa.file_id, token)];
         let mut cache = self.expansion_info_cache.borrow_mut();
         let mut mcache = self.macro_call_cache.borrow_mut();
@@ -910,74 +903,70 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
-        let analyze = self.analyze(ty.syntax())?;
-        let ctx = body::LowerCtx::new(self.db.upcast(), analyze.file_id);
-        let ty = hir_ty::TyLoweringContext::new(self.db, &analyze.resolver)
+        let scope = self.scope(ty.syntax());
+        let ctx = body::LowerCtx::new(self.db.upcast(), scope.file_id);
+        let ty = hir_ty::TyLoweringContext::new(self.db, &scope.resolver)
             .lower_ty(&crate::TypeRef::from_ast(&ctx, ty.clone()));
-        Some(Type::new_with_resolver(self.db, &analyze.resolver, ty))
+        Type::new_with_resolver(self.db, &scope.resolver, ty)
     }
 
     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> {
-        self.analyze(expr.syntax())?
+        self.analyze(expr.syntax())
             .type_of_expr(self.db, expr)
             .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
     }
 
     fn type_of_pat(&self, pat: &ast::Pat) -> Option<TypeInfo> {
-        self.analyze(pat.syntax())?
+        self.analyze(pat.syntax())
             .type_of_pat(self.db, pat)
             .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
     }
 
     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> {
-        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> {
-        let source_analyzer = self.analyze(call.syntax())?;
-        let (func, subst) = source_analyzer.resolve_method_call(self.db, call)?;
+        let (func, subst) = self.analyze(call.syntax()).resolve_method_call(self.db, call)?;
         let ty = self.db.value_ty(func.into()).substitute(Interner, &subst);
-        let resolver = source_analyzer.resolver;
-        let ty = Type::new_with_resolver(self.db, &resolver, ty);
+        let resolver = self.analyze(call.syntax()).resolver;
+        let ty = Type::new_with_resolver(self.db, &resolver, ty)?;
         let mut res = ty.as_callable(self.db)?;
         res.is_bound_method = true;
         Some(res)
     }
 
     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(
         &self,
         field: &ast::RecordExprField,
     ) -> 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> {
-        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> {
-        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);
         sa.resolve_macro_call(self.db, macro_call)
     }
 
     fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
-        let sa = match self.analyze(macro_call.syntax()) {
-            Some(it) => it,
-            None => return false,
-        };
+        let sa = self.analyze(macro_call.syntax());
         let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
         sa.is_unsafe_macro_call(self.db, macro_call)
     }
@@ -992,11 +981,11 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     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> {
-        let krate = self.scope(extern_crate.syntax())?.krate();
+        let krate = self.scope(extern_crate.syntax()).krate()?;
         let name = extern_crate.name_ref()?.as_name();
         if name == known::SELF_PARAM {
             return Some(krate);
@@ -1008,22 +997,22 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     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> {
-        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)> {
         self.analyze(literal.syntax())
-            .and_then(|it| it.record_literal_missing_fields(self.db, literal))
+            .record_literal_missing_fields(self.db, literal)
             .unwrap_or_default()
     }
 
     fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> {
         self.analyze(pattern.syntax())
-            .and_then(|it| it.record_pattern_missing_fields(self.db, pattern))
+            .record_pattern_missing_fields(self.db, pattern)
             .unwrap_or_default()
     }
 
@@ -1037,22 +1026,15 @@ impl<'db> SemanticsImpl<'db> {
         self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from)
     }
 
-    fn scope(&self, node: &SyntaxNode) -> Option<SemanticsScope<'db>> {
-        self.analyze_no_infer(node).map(|SourceAnalyzer { file_id, resolver, .. }| SemanticsScope {
-            db: self.db,
-            file_id,
-            resolver,
-        })
+    fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
+        let SourceAnalyzer { file_id, resolver, .. } = self.analyze_no_infer(node);
+        SemanticsScope { db: self.db, file_id, resolver }
     }
 
-    fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> Option<SemanticsScope<'db>> {
-        self.analyze_with_offset_no_infer(node, offset).map(
-            |SourceAnalyzer { file_id, resolver, .. }| SemanticsScope {
-                db: self.db,
-                file_id,
-                resolver,
-            },
-        )
+    fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> {
+        let SourceAnalyzer { file_id, resolver, .. } =
+            self.analyze_with_offset_no_infer(node, offset);
+        SemanticsScope { db: self.db, file_id, resolver }
     }
 
     fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
@@ -1070,21 +1052,15 @@ impl<'db> SemanticsImpl<'db> {
         Some(res)
     }
 
-    /// Returns none if the file of the node is not part of a crate.
-    fn analyze(&self, node: &SyntaxNode) -> Option<SourceAnalyzer> {
+    fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer {
         self.analyze_impl(node, None, true)
     }
 
-    /// Returns none if the file of the node is not part of a crate.
-    fn analyze_no_infer(&self, node: &SyntaxNode) -> Option<SourceAnalyzer> {
+    fn analyze_no_infer(&self, node: &SyntaxNode) -> SourceAnalyzer {
         self.analyze_impl(node, None, false)
     }
 
-    fn analyze_with_offset_no_infer(
-        &self,
-        node: &SyntaxNode,
-        offset: TextSize,
-    ) -> Option<SourceAnalyzer> {
+    fn analyze_with_offset_no_infer(&self, node: &SyntaxNode, offset: TextSize) -> SourceAnalyzer {
         self.analyze_impl(node, Some(offset), false)
     }
 
@@ -1093,22 +1069,22 @@ impl<'db> SemanticsImpl<'db> {
         node: &SyntaxNode,
         offset: Option<TextSize>,
         infer_body: bool,
-    ) -> Option<SourceAnalyzer> {
+    ) -> SourceAnalyzer {
         let _p = profile::span("Semantics::analyze_impl");
         let node = self.find_file(node);
 
         let container = match self.with_ctx(|ctx| ctx.find_container(node)) {
             Some(it) => it,
-            None => return None,
+            None => return SourceAnalyzer::new_for_resolver(Resolver::default(), node),
         };
 
         let resolver = match container {
             ChildContainer::DefWithBodyId(def) => {
-                return Some(if infer_body {
+                return if infer_body {
                     SourceAnalyzer::new_for_body(self.db, def, node, offset)
                 } else {
                     SourceAnalyzer::new_for_body_no_infer(self.db, def, node, offset)
-                })
+                }
             }
             ChildContainer::TraitId(it) => it.resolver(self.db.upcast()),
             ChildContainer::ImplId(it) => it.resolver(self.db.upcast()),
@@ -1118,7 +1094,7 @@ impl<'db> SemanticsImpl<'db> {
             ChildContainer::TypeAliasId(it) => it.resolver(self.db.upcast()),
             ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()),
         };
-        Some(SourceAnalyzer::new_for_resolver(resolver, node))
+        SourceAnalyzer::new_for_resolver(resolver, node)
     }
 
     fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
@@ -1142,7 +1118,6 @@ impl<'db> SemanticsImpl<'db> {
         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> {
         let root_node = find_root(node);
         let file_id = self.lookup(&root_node).unwrap_or_else(|| {
@@ -1344,12 +1319,12 @@ pub struct SemanticsScope<'a> {
 }
 
 impl<'a> SemanticsScope<'a> {
-    pub fn module(&self) -> Module {
-        Module { id: self.resolver.module() }
+    pub fn module(&self) -> Option<Module> {
+        Some(Module { id: self.resolver.module()? })
     }
 
-    pub fn krate(&self) -> Crate {
-        Crate { id: self.resolver.krate() }
+    pub fn krate(&self) -> Option<Crate> {
+        Some(Crate { id: self.resolver.krate()? })
     }
 
     pub(crate) fn resolver(&self) -> &Resolver {
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index f918443427..2b818b8eba 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -169,7 +169,7 @@ impl SourceAnalyzer {
             .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
         let ty = infer[expr_id].clone();
         let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
-        Some((mk_ty(ty), coerced.map(mk_ty)))
+        mk_ty(ty).zip(Some(coerced.and_then(mk_ty)))
     }
 
     pub(crate) fn type_of_pat(
@@ -185,7 +185,7 @@ impl SourceAnalyzer {
             .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
         let ty = infer[pat_id].clone();
         let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
-        Some((mk_ty(ty), coerced.map(mk_ty)))
+        mk_ty(ty).zip(Some(coerced.and_then(mk_ty)))
     }
 
     pub(crate) fn type_of_self(
@@ -196,7 +196,7 @@ impl SourceAnalyzer {
         let src = InFile { file_id: self.file_id, value: param };
         let pat_id = self.body_source_map()?.node_self_param(src)?;
         let ty = self.infer.as_ref()?[pat_id].clone();
-        Some(Type::new_with_resolver(db, &self.resolver, ty))
+        Type::new_with_resolver(db, &self.resolver, ty)
     }
 
     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_ty =
             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(
@@ -366,8 +366,11 @@ impl SourceAnalyzer {
             return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path) {
                 None if is_path_of_attr => {
                     path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| {
-                        ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
-                            .map(PathResolution::ToolModule)
+                        match self.resolver.krate() {
+                            Some(krate) => ToolModule::by_name(db, krate.into(), &name_ref.text()),
+                            None => ToolModule::builtin(&name_ref.text()),
+                        }
+                        .map(PathResolution::ToolModule)
                     })
                 }
                 res => res,
@@ -377,8 +380,9 @@ impl SourceAnalyzer {
             // in this case we have to check for inert/builtin attributes and tools and prioritize
             // resolution of attributes over other namespaces
             let name_ref = path.as_single_name_ref();
-            let builtin = name_ref.as_ref().and_then(|name_ref| {
-                BuiltinAttr::by_name(db, self.resolver.krate().into(), &name_ref.text())
+            let builtin = name_ref.as_ref().and_then(|name_ref| match self.resolver.krate() {
+                Some(krate) => BuiltinAttr::by_name(db, krate.into(), &name_ref.text()),
+                None => BuiltinAttr::builtin(&name_ref.text()),
             });
             if let builtin @ Some(_) = builtin {
                 return builtin.map(PathResolution::BuiltinAttr);
@@ -388,8 +392,11 @@ impl SourceAnalyzer {
                 // 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
                 None => path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| {
-                    ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
-                        .map(PathResolution::ToolModule)
+                    match self.resolver.krate() {
+                        Some(krate) => ToolModule::by_name(db, krate.into(), &name_ref.text()),
+                        None => ToolModule::builtin(&name_ref.text()),
+                    }
+                    .map(PathResolution::ToolModule)
                 }),
             };
         }
@@ -405,7 +412,7 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         literal: &ast::RecordExpr,
     ) -> Option<Vec<(Field, Type)>> {
-        let krate = self.resolver.krate();
+        let krate = self.resolver.krate()?;
         let body = self.body()?;
         let infer = self.infer.as_ref()?;
 
@@ -423,7 +430,7 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         pattern: &ast::RecordPat,
     ) -> Option<Vec<(Field, Type)>> {
-        let krate = self.resolver.krate();
+        let krate = self.resolver.krate()?;
         let body = self.body()?;
         let infer = self.infer.as_ref()?;
 
@@ -461,7 +468,7 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         macro_call: InFile<&ast::MacroCall>,
     ) -> 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| {
             self.resolver
                 .resolve_path_as_macro(db.upcast(), &path)
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index fe0100fb8c..ab99627d18 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -25,14 +25,12 @@ use crate::{
     StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, VariantId,
 };
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Default)]
 pub struct Resolver {
     /// 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,
     /// there's `scopes` *method* for that.
-    ///
-    /// Invariant: There exists at least one Scope::ModuleScope at the start of the vec.
     scopes: Vec<Scope>,
 }
 
@@ -137,7 +135,10 @@ impl Resolver {
         path: &ModPath,
         shadow: BuiltinShadowMode,
     ) -> PerNs {
-        let (item_map, module) = self.module_scope();
+        let (item_map, module) = match self.module_scope() {
+            Some(it) => it,
+            None => return PerNs::none(),
+        };
         let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow);
         if segment_index.is_some() {
             return PerNs::none();
@@ -154,7 +155,7 @@ impl Resolver {
         db: &dyn DefDatabase,
         path: &ModPath,
     ) -> 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);
         match module_res.take_types()? {
             ModuleDefId::TraitId(it) => {
@@ -234,7 +235,10 @@ impl Resolver {
     ) -> Option<Visibility> {
         match visibility {
             RawVisibility::Module(_) => {
-                let (item_map, module) = self.module_scope();
+                let (item_map, module) = match self.module_scope() {
+                    Some(it) => it,
+                    None => return None,
+                };
                 item_map.resolve_visibility(db, module, visibility)
             }
             RawVisibility::Public => Some(Visibility::Public),
@@ -332,7 +336,7 @@ impl Resolver {
     }
 
     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()
     }
 
@@ -421,22 +425,22 @@ impl Resolver {
         traits
     }
 
-    fn module_scope(&self) -> (&DefMap, LocalModuleId) {
-        self.scopes()
-            .find_map(|scope| match scope {
-                Scope::ModuleScope(m) => Some((&*m.def_map, m.module_id)),
-                _ => None,
-            })
-            .expect("module scope invariant violated")
+    fn module_scope(&self) -> Option<(&DefMap, LocalModuleId)> {
+        self.scopes().find_map(|scope| match scope {
+            Scope::ModuleScope(m) => Some((&*m.def_map, m.module_id)),
+
+            _ => None,
+        })
     }
 
-    pub fn module(&self) -> ModuleId {
-        let (def_map, local_id) = self.module_scope();
-        def_map.module_id(local_id)
+    pub fn module(&self) -> Option<ModuleId> {
+        let (def_map, local_id) = self.module_scope()?;
+        Some(def_map.module_id(local_id))
     }
 
-    pub fn krate(&self) -> CrateId {
-        self.module_scope().0.krate()
+    pub fn krate(&self) -> Option<CrateId> {
+        // FIXME: can this ever be `None`?
+        self.module_scope().map(|t| t.0.krate())
     }
 
     pub fn where_predicates_in_scope(
@@ -745,7 +749,8 @@ impl HasResolver for ModuleId {
             def_map = parent.def_map(db);
             modules.push((def_map.clone(), parent.local_id));
         }
-        let mut resolver = Resolver { scopes: Vec::with_capacity(modules.len()) };
+        let mut resolver = Resolver::default();
+        resolver.scopes.reserve(modules.len());
         for (def_map, module) in modules.into_iter().rev() {
             resolver = resolver.push_module_scope(def_map, module);
         }
diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs
index 6972db8495..451245b5d2 100644
--- a/crates/hir_ty/src/chalk_db.rs
+++ b/crates/hir_ty/src/chalk_db.rs
@@ -420,8 +420,9 @@ pub(crate) fn associated_ty_data_query(
         .collect();
 
     if !ctx.unsized_types.borrow().contains(&self_ty) {
-        let sized_trait = db
-            .lang_item(resolver.krate(), SmolStr::new_inline("sized"))
+        let sized_trait = resolver
+            .krate()
+            .and_then(|krate| db.lang_item(krate, SmolStr::new_inline("sized")))
             .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
         let sized_bound = sized_trait.into_iter().map(|sized_trait| {
             let trait_bound =
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 70bb56e02f..71e81b4348 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -762,7 +762,7 @@ impl<'a> InferenceContext<'a> {
     }
 
     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())
     }
 
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index fc88e97d6a..01022f20bd 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -29,7 +29,7 @@ use crate::{
         const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode,
     },
     mapping::{from_chalk, ToChalk},
-    method_resolution::{self, VisibleFromModule},
+    method_resolution,
     primitive::{self, UintTy},
     static_lifetime, to_chalk_trait_id,
     utils::{generics, Generics},
@@ -487,8 +487,13 @@ impl<'a> InferenceContext<'a> {
                         }
                         _ => return None,
                     };
-                    let is_visible = self.db.field_visibilities(field_id.parent)[field_id.local_id]
-                        .is_visible_from(self.db.upcast(), self.resolver.module());
+                    let module = self.resolver.module();
+                    let is_visible = 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 {
                         // Write down the first field resolution even if it is not visible
                         // This aids IDE features for private fields like goto def and in
@@ -941,7 +946,7 @@ impl<'a> InferenceContext<'a> {
             self.db,
             self.trait_env.clone(),
             &traits_in_scope,
-            VisibleFromModule::Filter(self.resolver.module()),
+            self.resolver.module().into(),
             method_name,
         );
         let (receiver_ty, method_ty, substs) = match resolved {
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index f580e09e91..53fe2131a3 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -9,11 +9,8 @@ use hir_def::{
 use hir_expand::name::Name;
 
 use crate::{
-    builder::ParamKind,
-    consteval,
-    method_resolution::{self, VisibleFromModule},
-    GenericArgData, Interner, Substitution, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
-    ValueTyDefId,
+    builder::ParamKind, consteval, method_resolution, GenericArgData, Interner, Substitution,
+    TraitRefExt, Ty, TyBuilder, TyExt, TyKind, ValueTyDefId,
 };
 
 use super::{ExprOrPatId, InferenceContext, TraitRef};
@@ -234,7 +231,7 @@ impl<'a> InferenceContext<'a> {
             self.db,
             self.table.trait_env.clone(),
             &traits_in_scope,
-            VisibleFromModule::Filter(self.resolver.module()),
+            self.resolver.module().into(),
             Some(name),
             method_resolution::LookupMode::Path,
             move |_ty, item| {
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 81134f666b..de56414d30 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -335,13 +335,12 @@ impl<'a> TyLoweringContext<'a> {
                     let mut expander = self.expander.borrow_mut();
                     if expander.is_some() {
                         (Some(expander), false)
-                    } else {
-                        *expander = Some(Expander::new(
-                            self.db.upcast(),
-                            macro_call.file_id,
-                            self.resolver.module(),
-                        ));
+                    } 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 {
+                        (None, false)
                     }
                 };
                 let ty = if let Some(mut expander) = expander {
@@ -861,8 +860,9 @@ impl<'a> TyLoweringContext<'a> {
             }
             TypeBound::Path(path, TraitBoundModifier::Maybe) => {
                 let sized_trait = self
-                    .db
-                    .lang_item(self.resolver.krate(), SmolStr::new_inline("sized"))
+                    .resolver
+                    .krate()
+                    .and_then(|krate| self.db.lang_item(krate, SmolStr::new_inline("sized")))
                     .and_then(|lang_item| lang_item.as_trait());
                 // Don't lower associated type bindings as the only possible relaxed trait bound
                 // `?Sized` has no of them.
@@ -1268,8 +1268,9 @@ fn implicitly_sized_clauses<'a>(
 ) -> impl Iterator<Item = WhereClause> + 'a {
     let is_trait_def = matches!(def, GenericDefId::TraitId(..));
     let generic_args = &substitution.as_slice(Interner)[is_trait_def as usize..];
-    let sized_trait = db
-        .lang_item(resolver.krate(), SmolStr::new_inline("sized"))
+    let sized_trait = resolver
+        .krate()
+        .and_then(|krate| db.lang_item(krate, SmolStr::new_inline("sized")))
         .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
 
     sized_trait.into_iter().flat_map(move |sized_trait| {
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index a7d6bc2401..775af2b66c 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -63,7 +63,10 @@ pub(crate) fn goto_implementation(
                 Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
                 Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
                 Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
-                Definition::BuiltinType(builtin) => impls_for_ty(&sema, builtin.ty(sema.db)),
+                Definition::BuiltinType(builtin) => {
+                    let module = sema.to_module_def(position.file_id)?;
+                    impls_for_ty(&sema, builtin.ty(sema.db, module))
+                }
                 Definition::Function(f) => {
                     let assoc = f.as_assoc_item(sema.db)?;
                     let name = assoc.name(sema.db)?;
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 23b995dbb8..ec0435aad0 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -170,7 +170,7 @@ pub(crate) fn hover_for_definition(
     config: &HoverConfig,
 ) -> Option<HoverResult> {
     let famous_defs = match &definition {
-        Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(node)?.krate())),
+        Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(node).krate())),
         _ => None,
     };
     if let Some(markup) = render::definition(sema.db, definition, famous_defs.as_ref(), config) {
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 0676220272..b2b74ccce3 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -103,7 +103,7 @@ pub(super) fn try_expr(
 
     let adts = inner_ty.as_adt().zip(body_ty.as_adt());
     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
         if let Some(option_enum) = famous_defs.core_option_Option() {
             if inner == option_enum && body == option_enum {
@@ -234,7 +234,7 @@ pub(super) fn keyword(
         return None;
     }
     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);
 
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index ba2b397f2a..4fdb7d0bc3 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -110,10 +110,7 @@ fn hints(
     config: &InlayHintsConfig,
     node: SyntaxNode,
 ) {
-    let krate = match sema.scope(&node) {
-        Some(it) => it.krate(),
-        None => return,
-    };
+    let krate = sema.scope(&node).module().map(|it| it.krate());
     let famous_defs = FamousDefs(sema, krate);
     if let Some(expr) = ast::Expr::cast(node.clone()) {
         chaining_hints(hints, sema, &famous_defs, config, &expr);
@@ -506,7 +503,7 @@ fn bind_pat_hints(
         return None;
     }
 
-    let krate = sema.scope(desc_pat.syntax())?.krate();
+    let krate = sema.scope(desc_pat.syntax()).module().map(|it| it.krate());
     let famous_defs = FamousDefs(sema, krate);
     let label = hint_iterator(sema, &famous_defs, config, &ty);
 
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index c9b53b1c48..7fcb09b5e2 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -64,7 +64,7 @@ use cfg::CfgOptions;
 use ide_db::{
     base_db::{
         salsa::{self, ParallelDatabase},
-        CrateOrigin, Env, FileLoader, FileSet, SourceDatabase, VfsPath,
+        Env, FileLoader, FileSet, SourceDatabase, VfsPath,
     },
     symbol_index, LineIndexDatabase,
 };
@@ -232,7 +232,7 @@ impl Analysis {
             Env::default(),
             Default::default(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            Default::default(),
         );
         change.change_file(file_id, Some(Arc::new(text)));
         change.set_crate_graph(crate_graph);
@@ -635,7 +635,7 @@ impl Analysis {
         self.with_db(|db| {
             let rule: ide_ssr::SsrRule = query.parse()?;
             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)?;
             let edits = if parse_only { Default::default() } else { match_finder.edits() };
             Ok(SourceChange::from(edits))
diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs
index 0f75abe55c..2e93d895f0 100644
--- a/crates/ide/src/moniker.rs
+++ b/crates/ide/src/moniker.rs
@@ -3,7 +3,7 @@
 
 use hir::{db::DefDatabase, AsAssocItem, AssocItemContainer, Crate, Name, Semantics};
 use ide_db::{
-    base_db::{CrateOrigin, FileId, FileLoader, FilePosition, LangCrateOrigin},
+    base_db::{CrateOrigin, FileId, FileLoader, FilePosition},
     defs::{Definition, IdentClass},
     helpers::pick_best_token,
     RootDatabase,
@@ -151,20 +151,11 @@ pub(crate) fn def_to_moniker(
             let name = krate.display_name(db)?.to_string();
             let (repo, version) = match krate.origin(db) {
                 CrateOrigin::CratesIo { repo } => (repo?, krate.version(db)?),
-                CrateOrigin::Lang(lang) => (
+                CrateOrigin::Lang => (
                     "https://github.com/rust-lang/rust/".to_string(),
-                    format!(
-                        "https://github.com/rust-lang/rust/library/{}",
-                        match lang {
-                            LangCrateOrigin::Alloc => "alloc",
-                            LangCrateOrigin::Core => "core",
-                            LangCrateOrigin::ProcMacro => "proc_macro",
-                            LangCrateOrigin::Std => "std",
-                            LangCrateOrigin::Test => "test",
-                            LangCrateOrigin::Other => "",
-                        }
-                    ),
+                    "compiler_version".to_string(),
                 ),
+                CrateOrigin::Unknown => return None,
             };
             PackageInformation { name, repo, version }
         },
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index bcb2c8797d..1c455c5f30 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -474,7 +474,7 @@ impl TestAttr {
     }
 }
 
-const RUSTDOC_FENCE: &str = "```";
+const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
 const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
     &["", "rust", "should_panic", "edition2015", "edition2018", "edition2021"];
 
@@ -483,7 +483,9 @@ fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool {
         let mut in_code_block = false;
 
         for line in String::from(doc).lines() {
-            if let Some(header) = line.strip_prefix(RUSTDOC_FENCE) {
+            if let Some(header) =
+                RUSTDOC_FENCES.into_iter().find_map(|fence| line.strip_prefix(fence))
+            {
                 in_code_block = !in_code_block;
 
                 if in_code_block
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 908bbfde24..e5d4ed8b92 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -179,16 +179,12 @@ pub(crate) fn highlight(
     };
 
     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(
         &mut hl,
         &sema,
         file_id,
         &root,
-        krate,
+        sema.scope(&root).krate(),
         range_to_highlight,
         syntactic_name_ref_highlighting,
     );
@@ -200,7 +196,7 @@ fn traverse(
     sema: &Semantics<RootDatabase>,
     file_id: FileId,
     root: &SyntaxNode,
-    krate: hir::Crate,
+    krate: Option<hir::Crate>,
     range_to_highlight: TextRange,
     syntactic_name_ref_highlighting: bool,
 ) {
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 5fb87598f4..7ac6775685 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -3,6 +3,7 @@
 use hir::{AsAssocItem, HasVisibility, Semantics};
 use ide_db::{
     defs::{Definition, IdentClass, NameClass, NameRefClass},
+    famous_defs::FamousDefs,
     RootDatabase, SymbolKind,
 };
 use rustc_hash::FxHashMap;
@@ -48,7 +49,7 @@ pub(super) fn token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Optio
 
 pub(super) fn name_like(
     sema: &Semantics<RootDatabase>,
-    krate: hir::Crate,
+    krate: Option<hir::Crate>,
     bindings_shadow_count: &mut FxHashMap<hir::Name, u32>,
     syntactic_name_ref_highlighting: bool,
     name_like: ast::NameLike,
@@ -192,7 +193,7 @@ fn keyword(
 
 fn highlight_name_ref(
     sema: &Semantics<RootDatabase>,
-    krate: hir::Crate,
+    krate: Option<hir::Crate>,
     bindings_shadow_count: &mut FxHashMap<hir::Name, u32>,
     binding_hash: &mut Option<u64>,
     syntactic_name_ref_highlighting: bool,
@@ -278,7 +279,7 @@ fn highlight_name(
     sema: &Semantics<RootDatabase>,
     bindings_shadow_count: &mut FxHashMap<hir::Name, u32>,
     binding_hash: &mut Option<u64>,
-    krate: hir::Crate,
+    krate: Option<hir::Crate>,
     name: ast::Name,
 ) -> Highlight {
     let name_kind = NameClass::classify(sema, &name);
@@ -322,7 +323,11 @@ fn calc_binding_hash(name: &hir::Name, shadow_count: u32) -> u64 {
     hash((name, shadow_count))
 }
 
-fn highlight_def(sema: &Semantics<RootDatabase>, krate: hir::Crate, def: Definition) -> Highlight {
+fn highlight_def(
+    sema: &Semantics<RootDatabase>,
+    krate: Option<hir::Crate>,
+    def: Definition,
+) -> Highlight {
     let db = sema.db;
     let mut h = match def {
         Definition::Macro(m) => Highlight::new(HlTag::Symbol(m.kind(sema.db).into())),
@@ -467,12 +472,14 @@ fn highlight_def(sema: &Semantics<RootDatabase>, krate: hir::Crate, def: Definit
         Definition::ToolModule(_) => Highlight::new(HlTag::Symbol(SymbolKind::ToolModule)),
     };
 
+    let famous_defs = FamousDefs(sema, krate);
     let def_crate = def.module(db).map(hir::Module::krate).or_else(|| match def {
         Definition::Module(module) => Some(module.krate()),
         _ => None,
     });
-    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_other_crate = def_crate != krate;
+    let is_from_builtin_crate =
+        def_crate.map_or(false, |def_crate| famous_defs.builtin_crates().any(|it| def_crate == it));
     let is_builtin_type = matches!(def, Definition::BuiltinType(_));
     let is_public = def.visibility(db) == Some(hir::Visibility::Public);
 
@@ -491,7 +498,7 @@ fn highlight_def(sema: &Semantics<RootDatabase>, krate: hir::Crate, def: Definit
 
 fn highlight_method_call_by_name_ref(
     sema: &Semantics<RootDatabase>,
-    krate: hir::Crate,
+    krate: Option<hir::Crate>,
     name_ref: &ast::NameRef,
 ) -> Option<Highlight> {
     let mc = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?;
@@ -500,7 +507,7 @@ fn highlight_method_call_by_name_ref(
 
 fn highlight_method_call(
     sema: &Semantics<RootDatabase>,
-    krate: hir::Crate,
+    krate: Option<hir::Crate>,
     method_call: &ast::MethodCallExpr,
 ) -> Option<Highlight> {
     let func = sema.resolve_method_call(method_call)?;
@@ -518,9 +525,10 @@ fn highlight_method_call(
         h |= HlMod::Trait;
     }
 
+    let famous_defs = FamousDefs(sema, krate);
     let def_crate = func.module(sema.db).krate();
-    let is_from_other_crate = def_crate != krate;
-    let is_from_builtin_crate = def_crate.is_builtin(sema.db);
+    let is_from_other_crate = Some(def_crate) != krate;
+    let is_from_builtin_crate = famous_defs.builtin_crates().any(|it| def_crate == it);
     let is_public = func.visibility(sema.db) == hir::Visibility::Public;
 
     if is_from_other_crate {
@@ -585,7 +593,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
 fn highlight_name_ref_by_syntax(
     name: ast::NameRef,
     sema: &Semantics<RootDatabase>,
-    krate: hir::Crate,
+    krate: Option<hir::Crate>,
 ) -> Highlight {
     let default = HlTag::UnresolvedReference;
 
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs
index 8af0d8007d..8ac3c2da50 100644
--- a/crates/ide/src/syntax_highlighting/inject.rs
+++ b/crates/ide/src/syntax_highlighting/inject.rs
@@ -78,7 +78,8 @@ pub(super) fn ra_fixture(
     Some(())
 }
 
-const RUSTDOC_FENCE: &str = "```";
+const RUSTDOC_FENCE_LENGTH: usize = 3;
+const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
 
 /// Injection of syntax highlighting of doctests.
 pub(super) fn doc_comment(
@@ -166,11 +167,11 @@ pub(super) fn doc_comment(
             };
             let mut pos = TextSize::from(0);
 
-            match line.find(RUSTDOC_FENCE) {
+            match RUSTDOC_FENCES.into_iter().find_map(|fence| line.find(fence)) {
                 Some(idx) => {
                     is_codeblock = !is_codeblock;
                     // Check whether code is rust by inspecting fence guards
-                    let guards = &line[idx + RUSTDOC_FENCE.len()..];
+                    let guards = &line[idx + RUSTDOC_FENCE_LENGTH..];
                     let is_rust = is_rust_fence(guards);
                     is_doctest = is_codeblock && is_rust;
                     continue;
diff --git a/crates/ide_assists/src/handlers/add_explicit_type.rs b/crates/ide_assists/src/handlers/add_explicit_type.rs
index 6b7db739c8..11f12773e8 100644
--- a/crates/ide_assists/src/handlers/add_explicit_type.rs
+++ b/crates/ide_assists/src/handlers/add_explicit_type.rs
@@ -41,7 +41,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio
         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();
 
     // Don't enable the assist if there is a type ascription without any placeholders
diff --git a/crates/ide_assists/src/handlers/add_missing_impl_members.rs b/crates/ide_assists/src/handlers/add_missing_impl_members.rs
index 6e700695fb..c82caa3704 100644
--- a/crates/ide_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ide_assists/src/handlers/add_missing_impl_members.rs
@@ -104,7 +104,6 @@ fn add_missing_impl_members_inner(
 ) -> Option<()> {
     let _p = profile::span("add_missing_impl_members_inner");
     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 missing_items = filter_assoc_items(
@@ -119,6 +118,7 @@ fn add_missing_impl_members_inner(
 
     let target = impl_def.syntax().text_range();
     acc.add(AssistId(assist_id, AssistKind::QuickFix), label, target, |builder| {
+        let target_scope = ctx.sema.scope(impl_def.syntax());
         let missing_items = missing_items
             .into_iter()
             .map(|it| {
diff --git a/crates/ide_assists/src/handlers/add_missing_match_arms.rs b/crates/ide_assists/src/handlers/add_missing_match_arms.rs
index 171b3f4432..0dc67ede36 100644
--- a/crates/ide_assists/src/handlers/add_missing_match_arms.rs
+++ b/crates/ide_assists/src/handlers/add_missing_match_arms.rs
@@ -73,7 +73,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext) ->
         .filter(|pat| !matches!(pat, Pat::WildcardPat(_)))
         .collect();
 
-    let module = ctx.sema.scope(expr.syntax())?.module();
+    let module = ctx.sema.scope(expr.syntax()).module()?;
     let (mut missing_pats, is_non_exhaustive): (
         Peekable<Box<dyn Iterator<Item = (ast::Pat, bool)>>>,
         bool,
@@ -92,7 +92,8 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext) ->
             })
             .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
 
-        let option_enum = FamousDefs(&ctx.sema, module.krate()).core_option_Option().map(lift_enum);
+        let option_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 {
             // Match `Some` variant first.
             cov_mark::hit!(option_order);
diff --git a/crates/ide_assists/src/handlers/add_return_type.rs b/crates/ide_assists/src/handlers/add_return_type.rs
index 42a5b8b672..c7172741e4 100644
--- a/crates/ide_assists/src/handlers/add_return_type.rs
+++ b/crates/ide_assists/src/handlers/add_return_type.rs
@@ -17,7 +17,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
 // ```
 pub(crate) fn add_return_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     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();
     if ty.is_unit() {
         return None;
diff --git a/crates/ide_assists/src/handlers/convert_bool_then.rs b/crates/ide_assists/src/handlers/convert_bool_then.rs
index f07fde07c0..daec28999e 100644
--- a/crates/ide_assists/src/handlers/convert_bool_then.rs
+++ b/crates/ide_assists/src/handlers/convert_bool_then.rs
@@ -222,7 +222,7 @@ fn option_variants(
     sema: &Semantics<RootDatabase>,
     expr: &SyntaxNode,
 ) -> 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);
     match &*option_variants {
         &[variant0, variant1] => Some(if variant0.name(sema.db) == known::None {
diff --git a/crates/ide_assists/src/handlers/convert_into_to_from.rs b/crates/ide_assists/src/handlers/convert_into_to_from.rs
index 869f76951d..9185501a62 100644
--- a/crates/ide_assists/src/handlers/convert_into_to_from.rs
+++ b/crates/ide_assists/src/handlers/convert_into_to_from.rs
@@ -36,10 +36,10 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext) -> Op
     let src_type = impl_.self_ty()?;
     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_)?;
-    if trait_ != FamousDefs(&ctx.sema, module.krate()).core_convert_Into()? {
+    if trait_ != FamousDefs(&ctx.sema, Some(module.krate())).core_convert_Into()? {
         return None;
     }
 
diff --git a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs
index 711b914561..bb75cb5c95 100644
--- a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs
+++ b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs
@@ -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 expr_behind_ref = ref_expr.expr()?;
     let ty = sema.type_of_expr(&expr_behind_ref)?.adjusted();
-    let scope = sema.scope(iterable.syntax())?;
-    let krate = scope.krate();
+    let scope = sema.scope(iterable.syntax());
+    let krate = scope.module()?.krate();
     let traits_in_scope = scope.visible_traits();
-    let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
+    let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?;
 
     let has_wanted_method = ty
         .iterate_method_candidates(
@@ -175,17 +175,24 @@ fn is_ref_and_impls_iter_method(
 
 /// Whether iterable implements core::Iterator
 fn impls_core_iter(sema: &hir::Semantics<ide_db::RootDatabase>, iterable: &ast::Expr) -> bool {
-    (|| {
-        let it_typ = sema.type_of_expr(iterable)?.adjusted();
+    let it_typ = match sema.type_of_expr(iterable) {
+        Some(it) => it.adjusted(),
+        None => return false,
+    };
 
-        let module = sema.scope(iterable.syntax())?.module();
+    let module = match sema.scope(iterable.syntax()).module() {
+        Some(it) => it,
+        None => return false,
+    };
 
-        let krate = module.krate();
-        let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
-        cov_mark::hit!(test_already_impls_iterator);
-        Some(it_typ.impls_trait(sema.db, iter_trait, &[]))
-    })()
-    .unwrap_or(false)
+    let krate = module.krate();
+    match FamousDefs(sema, Some(krate)).core_iter_Iterator() {
+        Some(iter_trait) => {
+            cov_mark::hit!(test_already_impls_iterator);
+            it_typ.impls_trait(sema.db, iter_trait, &[])
+        }
+        None => false,
+    }
 }
 
 fn validate_method_call_expr(
@@ -207,10 +214,10 @@ fn validate_method_call_expr(
     let expr = ast::Expr::MethodCallExpr(expr);
 
     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 iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
+    let iter_trait = FamousDefs(sema, Some(krate)).core_iter_Iterator()?;
     it_type.impls_trait(sema.db, iter_trait, &[]).then(|| (expr, receiver))
 }
 
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs
index 3566b1be89..135f2a70b7 100644
--- a/crates/ide_assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide_assists/src/handlers/expand_glob_import.rs
@@ -49,8 +49,8 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
         _ => return None,
     };
 
-    let current_scope = ctx.sema.scope(&star.parent()?)?;
-    let current_module = current_scope.module();
+    let current_scope = ctx.sema.scope(&star.parent()?);
+    let current_module = current_scope.module()?;
 
     let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?;
     let imported_defs = find_imported_defs(ctx, star)?;
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index c26e4b1c75..fcb4aaf065 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -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 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 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 =
-                    FamousDefs(&ctx.sema, module.krate()).core_ops_ControlFlow();
+                    FamousDefs(&ctx.sema, Some(module.krate())).core_ops_ControlFlow();
 
                 if let Some(control_flow_enum) = control_flow_enum {
                     let mod_path = module.find_use_path_prefixed(
diff --git a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
index 45f98e690f..4b597837aa 100644
--- a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -423,7 +423,7 @@ fn reference_to_node(
             _ => return None,
         }
     };
-    let module = sema.scope(&expr_or_pat)?.module();
+    let module = sema.scope(&expr_or_pat).module()?;
     Some((segment, expr_or_pat, module))
 }
 
diff --git a/crates/ide_assists/src/handlers/fix_visibility.rs b/crates/ide_assists/src/handlers/fix_visibility.rs
index b895208f41..bbb5cf9187 100644
--- a/crates/ide_assists/src/handlers/fix_visibility.rs
+++ b/crates/ide_assists/src/handlers/fix_visibility.rs
@@ -43,7 +43,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O
         _ => 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())?;
 
     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_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());
     if visibility.is_visible_from(ctx.db(), current_module.into()) {
         return None;
diff --git a/crates/ide_assists/src/handlers/generate_constant.rs b/crates/ide_assists/src/handlers/generate_constant.rs
index c4b759d5f3..52ae60e2ed 100644
--- a/crates/ide_assists/src/handlers/generate_constant.rs
+++ b/crates/ide_assists/src/handlers/generate_constant.rs
@@ -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 statement = expr.syntax().ancestors().find_map(ast::Stmt::cast)?;
     let ty = ctx.sema.type_of_expr(&expr)?;
-    let scope = ctx.sema.scope(statement.syntax())?;
-    let module = scope.module();
+    let scope = ctx.sema.scope(statement.syntax());
+    let module = scope.module()?;
     let type_name = ty.original().display_source_code(ctx.db(), module.into()).ok()?;
     let indent = IndentLevel::from_node(statement.syntax());
     if constant_token.to_string().chars().any(|it| !(it.is_uppercase() || it == '_')) {
diff --git a/crates/ide_assists/src/handlers/generate_default_from_enum_variant.rs b/crates/ide_assists/src/handlers/generate_default_from_enum_variant.rs
index 4d47437f7c..4745ac24e9 100644
--- a/crates/ide_assists/src/handlers/generate_default_from_enum_variant.rs
+++ b/crates/ide_assists/src/handlers/generate_default_from_enum_variant.rs
@@ -75,7 +75,7 @@ fn existing_default_impl(
     let enum_ = variant.parent_enum(sema.db);
     let krate = enum_.module(sema.db).krate();
 
-    let default_trait = FamousDefs(sema, krate).core_default_Default()?;
+    let default_trait = FamousDefs(sema, Some(krate)).core_default_Default()?;
     let enum_type = enum_.ty(sema.db);
 
     if enum_type.impls_trait(sema.db, default_trait, &[]) {
diff --git a/crates/ide_assists/src/handlers/generate_default_from_new.rs b/crates/ide_assists/src/handlers/generate_default_from_new.rs
index 119bb6e07b..669fb28d10 100644
--- a/crates/ide_assists/src/handlers/generate_default_from_new.rs
+++ b/crates/ide_assists/src/handlers/generate_default_from_new.rs
@@ -132,7 +132,7 @@ fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> bool {
 
     let ty = impl_def.self_ty(db);
     let krate = impl_def.module(db).krate();
-    let default = FamousDefs(&ctx.sema, krate).core_default_Default();
+    let default = FamousDefs(&ctx.sema, Some(krate)).core_default_Default();
     let default_trait = match default {
         Some(value) => value,
         None => return false,
diff --git a/crates/ide_assists/src/handlers/generate_delegate_methods.rs b/crates/ide_assists/src/handlers/generate_delegate_methods.rs
index 120acde8e5..f6e0d619de 100644
--- a/crates/ide_assists/src/handlers/generate_delegate_methods.rs
+++ b/crates/ide_assists/src/handlers/generate_delegate_methods.rs
@@ -45,7 +45,7 @@ use syntax::ast::edit::AstNodeEdit;
 pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
     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>() {
         Some(field) => {
diff --git a/crates/ide_assists/src/handlers/generate_deref.rs b/crates/ide_assists/src/handlers/generate_deref.rs
index 3cb8a68687..4328c54c09 100644
--- a/crates/ide_assists/src/handlers/generate_deref.rs
+++ b/crates/ide_assists/src/handlers/generate_deref.rs
@@ -110,7 +110,7 @@ fn existing_deref_impl(
     let strukt = sema.to_def(strukt)?;
     let krate = strukt.module(sema.db).krate();
 
-    let deref_trait = FamousDefs(sema, krate).core_ops_Deref()?;
+    let deref_trait = FamousDefs(sema, Some(krate)).core_ops_Deref()?;
     let strukt_type = strukt.ty(sema.db);
 
     if strukt_type.impls_trait(sema.db, deref_trait, &[]) {
diff --git a/crates/ide_assists/src/handlers/generate_documentation_template.rs b/crates/ide_assists/src/handlers/generate_documentation_template.rs
index 3eaa445d32..15a07492ec 100644
--- a/crates/ide_assists/src/handlers/generate_documentation_template.rs
+++ b/crates/ide_assists/src/handlers/generate_documentation_template.rs
@@ -202,7 +202,7 @@ fn all_parent_mods_public(hir_func: &hir::Function, ctx: &AssistContext) -> bool
 
 /// Returns the name of the current crate
 fn crate_name(ast_func: &ast::Fn, ctx: &AssistContext) -> Option<String> {
-    let krate = ctx.sema.scope(ast_func.syntax())?.krate();
+    let krate = ctx.sema.scope(ast_func.syntax()).module()?.krate();
     Some(krate.display_name(ctx.db())?.to_string())
 }
 
diff --git a/crates/ide_assists/src/handlers/generate_enum_is_method.rs b/crates/ide_assists/src/handlers/generate_enum_is_method.rs
index 7dc1e4df28..863ada79ba 100644
--- a/crates/ide_assists/src/handlers/generate_enum_is_method.rs
+++ b/crates/ide_assists/src/handlers/generate_enum_is_method.rs
@@ -1,4 +1,3 @@
-use ide_db::assists::GroupLabel;
 use stdx::to_lower_snake_case;
 use syntax::ast::HasVisibility;
 use syntax::ast::{self, AstNode, HasName};
@@ -55,8 +54,7 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext) ->
     let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?;
 
     let target = variant.syntax().text_range();
-    acc.add_group(
-        &GroupLabel("Generate `is_`,`as_`,`try_into_`".to_owned()),
+    acc.add(
         AssistId("generate_enum_is_method", AssistKind::Generate),
         "Generate an `is_` method for an enum variant",
         target,
diff --git a/crates/ide_assists/src/handlers/generate_enum_projection_method.rs b/crates/ide_assists/src/handlers/generate_enum_projection_method.rs
index fdaa791340..a9116be67c 100644
--- a/crates/ide_assists/src/handlers/generate_enum_projection_method.rs
+++ b/crates/ide_assists/src/handlers/generate_enum_projection_method.rs
@@ -1,4 +1,3 @@
-use ide_db::assists::GroupLabel;
 use itertools::Itertools;
 use stdx::to_lower_snake_case;
 use syntax::ast::HasVisibility;
@@ -140,37 +139,31 @@ fn generate_enum_projection_method(
     let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?;
 
     let target = variant.syntax().text_range();
-    acc.add_group(
-        &GroupLabel("Generate `is_`,`as_`,`try_into_`".to_owned()),
-        AssistId(assist_id, AssistKind::Generate),
-        assist_description,
-        target,
-        |builder| {
-            let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
-            let method = format!(
-                "    {0}fn {1}({2}) -> {3}{4}{5} {{
+    acc.add(AssistId(assist_id, AssistKind::Generate), assist_description, target, |builder| {
+        let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
+        let method = format!(
+            "    {0}fn {1}({2}) -> {3}{4}{5} {{
         if let Self::{6}{7} = self {{
             {8}({9})
         }} else {{
             {10}
         }}
     }}",
-                vis,
-                fn_name,
-                props.self_param,
-                props.return_prefix,
-                field_type.syntax(),
-                props.return_suffix,
-                variant_name,
-                pattern_suffix,
-                props.happy_case,
-                bound_name,
-                props.sad_case,
-            );
+            vis,
+            fn_name,
+            props.self_param,
+            props.return_prefix,
+            field_type.syntax(),
+            props.return_suffix,
+            variant_name,
+            pattern_suffix,
+            props.happy_case,
+            bound_name,
+            props.sad_case,
+        );
 
-            add_method_to_adt(builder, &parent_enum, impl_def, &method);
-        },
-    )
+        add_method_to_adt(builder, &parent_enum, impl_def, &method);
+    })
 }
 
 #[cfg(test)]
diff --git a/crates/ide_assists/src/handlers/generate_from_impl_for_enum.rs b/crates/ide_assists/src/handlers/generate_from_impl_for_enum.rs
index 5bb7edb0a7..ee8de5a20e 100644
--- a/crates/ide_assists/src/handlers/generate_from_impl_for_enum.rs
+++ b/crates/ide_assists/src/handlers/generate_from_impl_for_enum.rs
@@ -86,7 +86,7 @@ fn existing_from_impl(
     let enum_ = variant.parent_enum(sema.db);
     let krate = enum_.module(sema.db).krate();
 
-    let from_trait = FamousDefs(sema, krate).core_convert_From()?;
+    let from_trait = FamousDefs(sema, Some(krate)).core_convert_From()?;
 
     let enum_type = enum_.ty(sema.db);
 
diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index ae4436ce88..c06498a4c9 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -73,7 +73,7 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
                 get_fn_target(ctx, &target_module, call.clone())?
             }
             Some(hir::PathResolution::Def(hir::ModuleDef::Adt(adt))) => {
-                let current_module = ctx.sema.scope(call.syntax())?.module();
+                let current_module = current_module(call.syntax(), ctx)?;
                 let module = adt.module(ctx.sema.db);
                 target_module = if current_module == module { None } else { Some(module) };
                 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 adt = ctx.sema.type_of_expr(&call.receiver()?)?.original().strip_references().as_adt()?;
 
-    let current_module = ctx.sema.scope(call.syntax())?.module();
+    let current_module = current_module(call.syntax(), ctx)?;
     let target_module = adt.module(ctx.sema.db);
 
     if current_module.krate() != target_module.krate() {
@@ -166,6 +166,10 @@ 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(
     ctx: &AssistContext,
     adt: &hir::Adt,
@@ -231,8 +235,7 @@ impl FunctionBuilder {
         target: GeneratedFunctionTarget,
     ) -> Option<Self> {
         let needs_pub = target_module.is_some();
-        let target_module =
-            target_module.or_else(|| ctx.sema.scope(target.syntax()).map(|it| it.module()))?;
+        let target_module = target_module.or_else(|| current_module(target.syntax(), ctx))?;
         let fn_name = make::name(fn_name);
         let (type_params, params) =
             fn_args(ctx, target_module, ast::CallableExpr::Call(call.clone()))?;
@@ -263,7 +266,7 @@ impl FunctionBuilder {
         target: GeneratedFunctionTarget,
     ) -> Option<Self> {
         let needs_pub =
-            !module_is_descendant(&ctx.sema.scope(call.syntax())?.module(), &target_module, ctx);
+            !module_is_descendant(&current_module(call.syntax(), ctx)?, &target_module, ctx);
         let fn_name = make::name(&name.text());
         let (type_params, params) =
             fn_args(ctx, target_module, ast::CallableExpr::MethodCall(call.clone()))?;
@@ -517,7 +520,7 @@ fn fn_arg_type(ctx: &AssistContext, target_module: hir::Module, fn_arg: &ast::Ex
         }
 
         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)
                 .map(|conversion| conversion.convert_type(ctx.db()))
                 .or_else(|| ty.display_source_code(ctx.db(), target_module.into()).ok())
diff --git a/crates/ide_assists/src/handlers/generate_getter.rs b/crates/ide_assists/src/handlers/generate_getter.rs
index 9513c112f3..2e81dd13f4 100644
--- a/crates/ide_assists/src/handlers/generate_getter.rs
+++ b/crates/ide_assists/src/handlers/generate_getter.rs
@@ -121,24 +121,25 @@ pub(crate) fn generate_getter_impl(
                     "a mutable reference to ",
                 )
             } else {
-                (|| {
-                    let krate = ctx.sema.scope(field_ty.syntax())?.krate();
-                    let famous_defs = &FamousDefs(&ctx.sema, krate);
-                    ctx.sema
-                        .resolve_type(&field_ty)
-                        .and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs))
-                        .map(|conversion| {
-                            cov_mark::hit!(convert_reference_type);
-                            (
-                                conversion.convert_type(ctx.db()),
-                                conversion.getter(field_name.to_string()),
-                                if conversion.is_copy() { "" } else { "a reference to " },
-                            )
-                        })
-                })()
-                .unwrap_or_else(|| {
-                    (format!("&{}", field_ty), format!("&self.{}", field_name), "a reference to ")
-                })
+                let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(field_ty.syntax()).krate());
+                ctx.sema
+                    .resolve_type(&field_ty)
+                    .and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs))
+                    .map(|conversion| {
+                        cov_mark::hit!(convert_reference_type);
+                        (
+                            conversion.convert_type(ctx.db()),
+                            conversion.getter(field_name.to_string()),
+                            if conversion.is_copy() { "" } else { "a reference to " },
+                        )
+                    })
+                    .unwrap_or_else(|| {
+                        (
+                            format!("&{}", field_ty),
+                            format!("&self.{}", field_name),
+                            "a reference to ",
+                        )
+                    })
             };
 
             format_to!(
diff --git a/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs
index 1ad1cea43f..bd7c85c443 100644
--- a/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs
+++ b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs
@@ -93,7 +93,7 @@ fn get_impl_method(
     let db = ctx.sema.db;
     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 traits_in_scope = scope.visible_traits();
     ty.iterate_method_candidates(db, &scope, &traits_in_scope, None, Some(fn_name), |func| {
diff --git a/crates/ide_assists/src/handlers/inline_call.rs b/crates/ide_assists/src/handlers/inline_call.rs
index 5a28cbcc23..994d78303f 100644
--- a/crates/ide_assists/src/handlers/inline_call.rs
+++ b/crates/ide_assists/src/handlers/inline_call.rs
@@ -391,11 +391,13 @@ fn inline(
         }
     }
     if let Some(generic_arg_list) = generic_arg_list.clone() {
-        if let Some((target, source)) = &sema.scope(node.syntax()).zip(sema.scope(fn_body.syntax()))
-        {
-            PathTransform::function_call(target, source, function, generic_arg_list)
-                .apply(body.syntax());
-        }
+        PathTransform::function_call(
+            &sema.scope(node.syntax()),
+            &sema.scope(fn_body.syntax()),
+            function,
+            generic_arg_list,
+        )
+        .apply(body.syntax());
     }
 
     let original_indentation = match node {
diff --git a/crates/ide_assists/src/handlers/promote_local_to_const.rs b/crates/ide_assists/src/handlers/promote_local_to_const.rs
index 65c14406f9..58cee8eafb 100644
--- a/crates/ide_assists/src/handlers/promote_local_to_const.rs
+++ b/crates/ide_assists/src/handlers/promote_local_to_const.rs
@@ -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 module = ctx.sema.scope(pat.syntax())?.module();
+    let module = ctx.sema.scope(pat.syntax()).module()?;
     let local = ctx.sema.to_def(&pat)?;
     let ty = ctx.sema.type_of_pat(&pat.into())?.original;
 
diff --git a/crates/ide_assists/src/handlers/qualify_method_call.rs b/crates/ide_assists/src/handlers/qualify_method_call.rs
index ba0a142718..0f232caab6 100644
--- a/crates/ide_assists/src/handlers/qualify_method_call.rs
+++ b/crates/ide_assists/src/handlers/qualify_method_call.rs
@@ -44,7 +44,7 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext) -> Opt
     let range = call.syntax().text_range();
     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 item_in_ns = ItemInNs::from(target_module_def);
     let receiver_path = current_module
diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
index 03e41b4340..0d0bd7071f 100644
--- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -69,7 +69,7 @@ pub(crate) fn replace_derive_with_manual_impl(
     let attr = ast::Attr::cast(value)?;
     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 found_traits = items_locator::items_with_name(
@@ -177,7 +177,7 @@ fn impl_def_from_trait(
     trait_path: &ast::Path,
 ) -> Option<(ast::Impl, ast::AssocItem)> {
     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);
     if trait_items.is_empty() {
         return None;
diff --git a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
index 4800d54956..b23b5bf87c 100644
--- a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
@@ -63,11 +63,9 @@ pub(crate) fn replace_qualified_name_with_use(
     );
     let path_to_qualifier = starts_with_name_ref
         .then(|| {
-            ctx.sema.scope(path.syntax())?.module().find_use_path_prefixed(
-                ctx.sema.db,
-                module,
-                ctx.config.insert_use.prefix_kind,
-            )
+            ctx.sema.scope(path.syntax()).module().and_then(|m| {
+                m.find_use_path_prefixed(ctx.sema.db, module, ctx.config.insert_use.prefix_kind)
+            })
         })
         .flatten();
 
diff --git a/crates/ide_assists/src/handlers/unwrap_result_return_type.rs b/crates/ide_assists/src/handlers/unwrap_result_return_type.rs
index ff79c5b82a..b890462389 100644
--- a/crates/ide_assists/src/handlers/unwrap_result_return_type.rs
+++ b/crates/ide_assists/src/handlers/unwrap_result_return_type.rs
@@ -38,9 +38,9 @@ pub(crate) fn unwrap_result_return_type(acc: &mut Assists, ctx: &AssistContext)
     };
 
     let type_ref = &ret_type.ty()?;
-    let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
+    let ty = ctx.sema.resolve_type(type_ref).and_then(|ty| ty.as_adt());
     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) {
         return None;
diff --git a/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs b/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
index 251b41c84a..972d4765bb 100644
--- a/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
+++ b/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
@@ -39,9 +39,9 @@ pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext)
     };
 
     let type_ref = &ret_type.ty()?;
-    let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
+    let ty = ctx.sema.resolve_type(type_ref).and_then(|ty| ty.as_adt());
     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) {
         cov_mark::hit!(wrap_return_type_in_result_simple_return_type_already_result);
diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs
index 0add950718..42317ea4da 100644
--- a/crates/ide_assists/src/utils.rs
+++ b/crates/ide_assists/src/utils.rs
@@ -600,7 +600,8 @@ fn handle_as_ref_str(
     db: &dyn HirDatabase,
     famous_defs: &FamousDefs,
 ) -> Option<ReferenceConversionType> {
-    let str_type = hir::BuiltinType::str().ty(db);
+    let module = famous_defs.1?.root_module(db);
+    let str_type = hir::BuiltinType::str().ty(db, module);
 
     ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[str_type])
         .then(|| ReferenceConversionType::AsRefStr)
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs
index ab442fa64b..867e6bcf48 100644
--- a/crates/ide_completion/src/completions.rs
+++ b/crates/ide_completion/src/completions.rs
@@ -352,6 +352,14 @@ fn enum_variants_with_paths(
 ) {
     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 impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_)) {
             for &variant in &variants {
@@ -365,7 +373,7 @@ fn enum_variants_with_paths(
     }
 
     for variant in variants {
-        if let Some(path) = ctx.module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) {
+        if let Some(path) = module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) {
             // Variants with trivial paths are already added by the existing completion logic,
             // so we should avoid adding these twice
             if path.segments().len() > 1 {
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index c79a9816f4..6b51e19bbb 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -91,7 +91,7 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
                 _ => return,
             };
 
-            for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
+            for (name, def) in module.scope(ctx.db, ctx.module) {
                 if let Some(def) = module_or_attr(ctx.db, def) {
                     acc.add_resolution(ctx, name, def);
                 }
diff --git a/crates/ide_completion/src/completions/attribute/cfg.rs b/crates/ide_completion/src/completions/attribute/cfg.rs
index b7e69d7b43..58d0a39949 100644
--- a/crates/ide_completion/src/completions/attribute/cfg.rs
+++ b/crates/ide_completion/src/completions/attribute/cfg.rs
@@ -27,17 +27,26 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
         Some("target_os") => KNOWN_OS.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(name) => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| {
-            let insert_text = format!(r#""{}""#, s);
-            let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
-            item.insert_text(insert_text);
+        Some(name) => {
+            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 mut item =
+                        CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
+                    item.insert_text(insert_text);
 
-            acc.add(item.build());
-        }),
-        None => ctx.krate.potential_cfg(ctx.db).get_cfg_keys().cloned().for_each(|s| {
-            let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s);
-            acc.add(item.build());
-        }),
+                    acc.add(item.build());
+                })
+            };
+        }
+        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);
+                    acc.add(item.build());
+                })
+            }
+        }
     };
 }
 
diff --git a/crates/ide_completion/src/completions/attribute/derive.rs b/crates/ide_completion/src/completions/attribute/derive.rs
index 4611811539..3c0e43ceac 100644
--- a/crates/ide_completion/src/completions/attribute/derive.rs
+++ b/crates/ide_completion/src/completions/attribute/derive.rs
@@ -34,7 +34,7 @@ pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) {
                 _ => return,
             };
 
-            for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
+            for (name, def) in module.scope(ctx.db, ctx.module) {
                 let add_def = match def {
                     ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
                         !ctx.existing_derives.contains(&mac) && mac.is_derive(ctx.db)
diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs
index c237a65bfe..981e25b55c 100644
--- a/crates/ide_completion/src/completions/dot.rs
+++ b/crates/ide_completion/src/completions/dot.rs
@@ -87,7 +87,7 @@ fn complete_methods(
         ctx.db,
         &ctx.scope,
         &traits_in_scope,
-        Some(ctx.module),
+        ctx.module,
         None,
         |func| {
             if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs
index 7d5709ec90..ee751f9f77 100644
--- a/crates/ide_completion/src/completions/flyimport.rs
+++ b/crates/ide_completion/src/completions/flyimport.rs
@@ -225,7 +225,7 @@ pub(crate) fn position_for_import(
 }
 
 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() {
         ImportAssets::for_fuzzy_method_call(
             current_module,
diff --git a/crates/ide_completion/src/completions/fn_param.rs b/crates/ide_completion/src/completions/fn_param.rs
index 7e9c1f49de..c5bc91d73d 100644
--- a/crates/ide_completion/src/completions/fn_param.rs
+++ b/crates/ide_completion/src/completions/fn_param.rs
@@ -120,18 +120,18 @@ fn params_from_stmt_list_scope(
         Some(it) => it,
         None => return,
     };
-    if let Some(scope) =
-        ctx.sema.scope_at_offset(stmt_list.syntax(), syntax_node.text_range().end())
-    {
-        let module = scope.module().into();
-        scope.process_all_names(&mut |name, def| {
-            if let hir::ScopeDef::Local(local) = def {
-                if let Ok(ty) = local.ty(ctx.db).display_source_code(ctx.db, module) {
-                    cb(name, ty);
-                }
+    let scope = ctx.sema.scope_at_offset(stmt_list.syntax(), syntax_node.text_range().end());
+    let module = match scope.module() {
+        Some(it) => it,
+        None => return,
+    };
+    scope.process_all_names(&mut |name, def| {
+        if let hir::ScopeDef::Local(local) = def {
+            if let Ok(ty) = local.ty(ctx.db).display_source_code(ctx.db, module.into()) {
+                cb(name, ty);
             }
-        });
-    }
+        }
+    });
 }
 
 fn remove_duplicated(
diff --git a/crates/ide_completion/src/completions/mod_.rs b/crates/ide_completion/src/completions/mod_.rs
index fb42e4e72f..7699c530c6 100644
--- a/crates/ide_completion/src/completions/mod_.rs
+++ b/crates/ide_completion/src/completions/mod_.rs
@@ -22,7 +22,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
 
     let _p = profile::span("completion::complete_mod");
 
-    let current_module = ctx.module;
+    let current_module = ctx.module?;
 
     let module_definition_file =
         current_module.definition_source(ctx.db).file_id.original_file(ctx.db);
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs
index 00f9bdfb51..0d3a49c668 100644
--- a/crates/ide_completion/src/completions/pattern.rs
+++ b/crates/ide_completion/src/completions/pattern.rs
@@ -122,7 +122,7 @@ fn pattern_path_completion(
 
             match resolution {
                 hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
-                    let module_scope = module.scope(ctx.db, Some(ctx.module));
+                    let module_scope = module.scope(ctx.db, ctx.module);
                     for (name, def) in module_scope {
                         let add_resolution = match def {
                             ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
@@ -159,7 +159,13 @@ fn pattern_path_completion(
                         hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Union(u))) => {
                             u.ty(ctx.db)
                         }
-                        hir::PathResolution::Def(hir::ModuleDef::BuiltinType(ty)) => ty.ty(ctx.db),
+                        hir::PathResolution::Def(hir::ModuleDef::BuiltinType(ty)) => {
+                            let module = match ctx.module {
+                                Some(m) => m,
+                                None => return,
+                            };
+                            ty.ty(ctx.db, module)
+                        }
                         _ => return,
                     };
 
@@ -169,7 +175,7 @@ fn pattern_path_completion(
                         ctx.db,
                         &ctx.scope,
                         &traits_in_scope,
-                        Some(ctx.module),
+                        ctx.module,
                         None,
                         |item| {
                             match item {
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index 534d27d983..c1f23ceeca 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -1,6 +1,7 @@
 //! Completion of paths, i.e. `some::prefix::$0`.
 
 use hir::{ScopeDef, Trait};
+use ide_db::famous_defs::FamousDefs;
 use rustc_hash::FxHashSet;
 use syntax::ast;
 
@@ -25,7 +26,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
     };
     let traits_in_scope = |ctx: &CompletionContext| {
         let mut traits_in_scope = ctx.scope.visible_traits();
-        if let Some(drop) = ctx.famous_defs().core_ops_Drop() {
+        if let Some(drop) = FamousDefs(&ctx.sema, ctx.krate).core_ops_Drop() {
             traits_in_scope.remove(&drop.into());
         }
         traits_in_scope
@@ -57,7 +58,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
     match ctx.completion_location {
         Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
             if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
-                for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
+                for (name, def) in module.scope(ctx.db, ctx.module) {
                     if let Some(def) = module_or_fn_macro(ctx.db, def) {
                         acc.add_resolution(ctx, name, def);
                     }
@@ -89,7 +90,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
 
     match resolution {
         hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
-            let module_scope = module.scope(ctx.db, Some(ctx.module));
+            let module_scope = module.scope(ctx.db, ctx.module);
             for (name, def) in module_scope {
                 let add_resolution = match def {
                     // Don't suggest attribute macros and derives.
@@ -132,8 +133,12 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
                     ty
                 }
                 hir::ModuleDef::BuiltinType(builtin) => {
+                    let module = match ctx.module {
+                        Some(it) => it,
+                        None => return,
+                    };
                     cov_mark::hit!(completes_primitive_assoc_const);
-                    builtin.ty(ctx.db)
+                    builtin.ty(ctx.db, module)
                 }
                 _ => unreachable!(),
             };
@@ -141,26 +146,29 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
             // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
             // (where AssocType is defined on a trait, not an inherent impl)
 
-            let traits_in_scope = traits_in_scope(ctx);
-            ty.iterate_path_candidates(
-                ctx.db,
-                &ctx.scope,
-                &traits_in_scope,
-                Some(ctx.module),
-                None,
-                |item| {
-                    add_assoc_item(acc, ctx, item);
+            let krate = ctx.krate;
+            if let Some(krate) = krate {
+                let traits_in_scope = traits_in_scope(ctx);
+                ty.iterate_path_candidates(
+                    ctx.db,
+                    &ctx.scope,
+                    &traits_in_scope,
+                    ctx.module,
+                    None,
+                    |item| {
+                        add_assoc_item(acc, ctx, item);
+                        None::<()>
+                    },
+                );
+
+                // Iterate assoc types separately
+                ty.iterate_assoc_items(ctx.db, krate, |item| {
+                    if let hir::AssocItem::TypeAlias(ty) = item {
+                        acc.add_type_alias(ctx, ty)
+                    }
                     None::<()>
-                },
-            );
-
-            // Iterate assoc types separately
-            ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
-                if let hir::AssocItem::TypeAlias(ty) = item {
-                    acc.add_type_alias(ctx, ty)
-                }
-                None::<()>
-            });
+                });
+            }
         }
         hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
             // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
@@ -184,7 +192,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
                 ctx.db,
                 &ctx.scope,
                 &traits_in_scope,
-                Some(ctx.module),
+                ctx.module,
                 None,
                 |item| {
                     // We might iterate candidates of a trait multiple times here, so deduplicate
diff --git a/crates/ide_completion/src/completions/record.rs b/crates/ide_completion/src/completions/record.rs
index b65cf60a01..5509ec922f 100644
--- a/crates/ide_completion/src/completions/record.rs
+++ b/crates/ide_completion/src/completions/record.rs
@@ -83,18 +83,17 @@ pub(crate) fn complete_record_literal(
 
     match ctx.expected_type.as_ref()?.as_adt()? {
         hir::Adt::Struct(strukt) if ctx.path_qual().is_none() => {
-            let path = ctx
-                .module
+            let module = if let Some(module) = ctx.module { module } else { strukt.module(ctx.db) };
+            let path = module
                 .find_use_path(ctx.db, hir::ModuleDef::from(strukt))
                 .filter(|it| it.len() > 1);
 
             acc.add_struct_literal(ctx, strukt, path, None);
         }
         hir::Adt::Union(un) if ctx.path_qual().is_none() => {
-            let path = ctx
-                .module
-                .find_use_path(ctx.db, hir::ModuleDef::from(un))
-                .filter(|it| it.len() > 1);
+            let module = if let Some(module) = ctx.module { module } else { un.module(ctx.db) };
+            let path =
+                module.find_use_path(ctx.db, hir::ModuleDef::from(un)).filter(|it| it.len() > 1);
 
             acc.add_union_literal(ctx, un, path, None);
         }
diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs
index 9c557aa524..0d59f77a55 100644
--- a/crates/ide_completion/src/completions/trait_impl.rs
+++ b/crates/ide_completion/src/completions/trait_impl.rs
@@ -183,7 +183,7 @@ fn get_transformed_assoc_item(
     let assoc_item = assoc_item.clone_for_update();
     let trait_ = impl_def.trait_(ctx.db)?;
     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(
         target_scope,
         source_scope,
diff --git a/crates/ide_completion/src/completions/use_.rs b/crates/ide_completion/src/completions/use_.rs
index d7c279f9d9..16b356963d 100644
--- a/crates/ide_completion/src/completions/use_.rs
+++ b/crates/ide_completion/src/completions/use_.rs
@@ -41,7 +41,7 @@ pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext)
 
             match resolution {
                 hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
-                    let module_scope = module.scope(ctx.db, Some(ctx.module));
+                    let module_scope = module.scope(ctx.db, ctx.module);
                     let unknown_is_current = |name: &hir::Name| {
                         matches!(
                             ctx.name_syntax.as_ref(),
diff --git a/crates/ide_completion/src/completions/vis.rs b/crates/ide_completion/src/completions/vis.rs
index ca6f6dff1e..c610dcd705 100644
--- a/crates/ide_completion/src/completions/vis.rs
+++ b/crates/ide_completion/src/completions/vis.rs
@@ -22,16 +22,17 @@ pub(crate) fn complete_vis(acc: &mut Completions, ctx: &CompletionContext) {
         Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
             // 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 {
-                let next_towards_current = ctx
-                    .module
-                    .path_to_root(ctx.db)
-                    .into_iter()
-                    .take_while(|it| it != module)
-                    .last();
-                if let Some(next) = next_towards_current {
-                    if let Some(name) = next.name(ctx.db) {
-                        cov_mark::hit!(visibility_qualified);
-                        acc.add_resolution(ctx, name, ScopeDef::ModuleDef(next.into()));
+                if let Some(current_module) = ctx.module {
+                    let next_towards_current = current_module
+                        .path_to_root(ctx.db)
+                        .into_iter()
+                        .take_while(|it| it != module)
+                        .last();
+                    if let Some(next) = next_towards_current {
+                        if let Some(name) = next.name(ctx.db) {
+                            cov_mark::hit!(visibility_qualified);
+                            acc.add_resolution(ctx, name, ScopeDef::ModuleDef(next.into()));
+                        }
                     }
                 }
             }
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 12747b3ce4..ed59eb6bd3 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -121,9 +121,9 @@ pub(crate) struct CompletionContext<'a> {
     /// The token before the cursor, in the macro-expanded file.
     pub(super) token: SyntaxToken,
     /// The crate of the current file.
-    pub(super) krate: hir::Crate,
+    pub(super) krate: Option<hir::Crate>,
     /// The module of the `scope`.
-    pub(super) module: hir::Module,
+    pub(super) module: Option<hir::Module>,
     pub(super) expected_name: Option<NameOrNameRef>,
     pub(super) expected_type: Option<Type>,
 
@@ -353,7 +353,11 @@ impl<'a> CompletionContext<'a> {
         attrs: &hir::Attrs,
         defining_crate: hir::Crate,
     ) -> Visible {
-        if !vis.is_visible_from(self.db, self.module.into()) {
+        let module = match self.module {
+            Some(it) => it,
+            None => return Visible::No,
+        };
+        if !vis.is_visible_from(self.db, module.into()) {
             if !self.config.enable_private_editable {
                 return Visible::No;
             }
@@ -372,8 +376,11 @@ impl<'a> CompletionContext<'a> {
     }
 
     fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
-        // `doc(hidden)` items are only completed within the defining crate.
-        self.krate != defining_crate && attrs.has_doc_hidden()
+        match self.krate {
+            // `doc(hidden)` items are only completed within the defining crate.
+            Some(krate) => krate != defining_crate && attrs.has_doc_hidden(),
+            None => true,
+        }
     }
 }
 
@@ -402,7 +409,7 @@ impl<'a> CompletionContext<'a> {
 
         let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
         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 module = scope.module();
         let mut locals = FxHashMap::default();
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index 56c41a88e4..422bda6460 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -185,7 +185,7 @@ pub fn resolve_completion_edits(
     let position_for_import = &position_for_import(&ctx, None)?;
     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 new_ast = scope.clone_for_update();
     let mut import_insert = TextEdit::builder();
diff --git a/crates/ide_completion/src/render/variant.rs b/crates/ide_completion/src/render/variant.rs
index 39a37dc9f8..a37b4237c4 100644
--- a/crates/ide_completion/src/render/variant.rs
+++ b/crates/ide_completion/src/render/variant.rs
@@ -72,7 +72,7 @@ pub(crate) fn visible_fields(
     fields: &[hir::Field],
     item: impl HasAttrs,
 ) -> Option<(Vec<hir::Field>, bool)> {
-    let module = ctx.module;
+    let module = ctx.module?;
     let n_fields = fields.len();
     let fields = fields
         .iter()
diff --git a/crates/ide_completion/src/snippet.rs b/crates/ide_completion/src/snippet.rs
index 1340080fdf..0a154f14e5 100644
--- a/crates/ide_completion/src/snippet.rs
+++ b/crates/ide_completion/src/snippet.rs
@@ -185,7 +185,7 @@ fn import_edits(
             _ => return None,
         };
         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 {
             import: LocatedImport::new(path.clone(), item, item, None),
             scope: import_scope.clone(),
diff --git a/crates/ide_db/src/famous_defs.rs b/crates/ide_db/src/famous_defs.rs
index 58d99ff9df..cc9f2f9151 100644
--- a/crates/ide_db/src/famous_defs.rs
+++ b/crates/ide_db/src/famous_defs.rs
@@ -1,6 +1,4 @@
 //! See [`FamousDefs`].
-
-use base_db::{CrateOrigin, LangCrateOrigin, SourceDatabase};
 use hir::{Crate, Enum, Macro, Module, ScopeDef, Semantics, Trait};
 
 use crate::RootDatabase;
@@ -18,28 +16,16 @@ use crate::RootDatabase;
 /// ```
 /// //- minicore: iterator, ord, derive
 /// ```
-pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Crate);
+pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>);
 
 #[allow(non_snake_case)]
 impl FamousDefs<'_, '_> {
     pub fn std(&self) -> Option<Crate> {
-        self.find_lang_crate(LangCrateOrigin::Std)
+        self.find_crate("std")
     }
 
     pub fn core(&self) -> Option<Crate> {
-        self.find_lang_crate(LangCrateOrigin::Core)
-    }
-
-    pub fn alloc(&self) -> Option<Crate> {
-        self.find_lang_crate(LangCrateOrigin::Alloc)
-    }
-
-    pub fn test(&self) -> Option<Crate> {
-        self.find_lang_crate(LangCrateOrigin::Test)
-    }
-
-    pub fn proc_macro(&self) -> Option<Crate> {
-        self.find_lang_crate(LangCrateOrigin::ProcMacro)
+        self.find_crate("core")
     }
 
     pub fn core_cmp_Ord(&self) -> Option<Trait> {
@@ -102,6 +88,18 @@ impl FamousDefs<'_, '_> {
         self.find_macro("core:macros:builtin:derive")
     }
 
+    pub fn alloc(&self) -> Option<Crate> {
+        self.find_crate("alloc")
+    }
+
+    pub fn test(&self) -> Option<Crate> {
+        self.find_crate("test")
+    }
+
+    pub fn proc_macro(&self) -> Option<Crate> {
+        self.find_crate("proc_macro")
+    }
+
     pub fn builtin_crates(&self) -> impl Iterator<Item = Crate> {
         IntoIterator::into_iter([
             self.std(),
@@ -141,15 +139,11 @@ impl FamousDefs<'_, '_> {
         }
     }
 
-    fn find_lang_crate(&self, origin: LangCrateOrigin) -> Option<Crate> {
-        let krate = self.1;
+    fn find_crate(&self, name: &str) -> Option<Crate> {
+        let krate = self.1?;
         let db = self.0.db;
-        let crate_graph = self.0.db.crate_graph();
-        let res = krate
-            .dependencies(db)
-            .into_iter()
-            .find(|dep| crate_graph[dep.krate.into()].origin == CrateOrigin::Lang(origin))?
-            .krate;
+        let res =
+            krate.dependencies(db).into_iter().find(|dep| dep.name.to_smol_str() == name)?.krate;
         Some(res)
     }
 
@@ -157,16 +151,8 @@ impl FamousDefs<'_, '_> {
         let db = self.0.db;
         let mut path = path.split(':');
         let trait_ = path.next_back()?;
-        let lang_crate = path.next()?;
-        let lang_crate = match lang_crate {
-            "core" => LangCrateOrigin::Core,
-            "alloc" => LangCrateOrigin::Alloc,
-            "test" => LangCrateOrigin::Test,
-            "proc_macro" => LangCrateOrigin::ProcMacro,
-            "std" => LangCrateOrigin::Std,
-            _ => return None,
-        };
-        let std_crate = self.find_lang_crate(lang_crate)?;
+        let std_crate = path.next()?;
+        let std_crate = self.find_crate(std_crate)?;
         let mut module = std_crate.root_module(db);
         for segment in path {
             module = module.children(db).find_map(|child| {
diff --git a/crates/ide_db/src/imports/import_assets.rs b/crates/ide_db/src/imports/import_assets.rs
index f8cfe15c89..d6246c7ad6 100644
--- a/crates/ide_db/src/imports/import_assets.rs
+++ b/crates/ide_db/src/imports/import_assets.rs
@@ -104,7 +104,7 @@ impl ImportAssets {
         let candidate_node = method_call.syntax().clone();
         Some(Self {
             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,
         })
     }
@@ -119,7 +119,7 @@ impl ImportAssets {
         }
         Some(Self {
             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,
         })
     }
@@ -132,7 +132,7 @@ impl ImportAssets {
         let candidate_node = pat.syntax().clone();
         Some(Self {
             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,
         })
     }
@@ -248,10 +248,7 @@ impl ImportAssets {
         };
 
         let krate = self.module_with_candidate.krate();
-        let scope = match sema.scope(&self.candidate_node) {
-            Some(it) => it,
-            None => return Vec::new(),
-        };
+        let scope = sema.scope(&self.candidate_node);
 
         match &self.import_candidate {
             ImportCandidate::Path(path_candidate) => {
@@ -274,11 +271,9 @@ impl ImportAssets {
     fn scope_definitions(&self, sema: &Semantics<RootDatabase>) -> FxHashSet<ScopeDef> {
         let _p = profile::span("import_assets::scope_definitions");
         let mut scope_definitions = FxHashSet::default();
-        if let Some(scope) = sema.scope(&self.candidate_node) {
-            scope.process_all_names(&mut |_, scope_def| {
-                scope_definitions.insert(scope_def);
-            });
-        }
+        sema.scope(&self.candidate_node).process_all_names(&mut |_, scope_def| {
+            scope_definitions.insert(scope_def);
+        });
         scope_definitions
     }
 }
@@ -593,7 +588,7 @@ impl ImportCandidate {
 
     fn for_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Self> {
         if sema
-            .scope(name.syntax())?
+            .scope(name.syntax())
             .speculative_resolve(&ast::make::ext::ident_path(&name.text()))
             .is_some()
         {
diff --git a/crates/ide_db/src/path_transform.rs b/crates/ide_db/src/path_transform.rs
index 15bd9a8c9c..558f4f1b63 100644
--- a/crates/ide_db/src/path_transform.rs
+++ b/crates/ide_db/src/path_transform.rs
@@ -69,13 +69,15 @@ impl<'a> PathTransform<'a> {
     }
 
     pub fn apply(&self, syntax: &SyntaxNode) {
-        self.build_ctx().apply(syntax)
+        if let Some(ctx) = self.build_ctx() {
+            ctx.apply(syntax)
+        }
     }
 
-    fn build_ctx(&self) -> Ctx<'a> {
+    fn build_ctx(&self) -> Option<Ctx<'a>> {
         let db = self.source_scope.db;
-        let target_module = self.target_scope.module();
-        let source_module = self.source_scope.module();
+        let target_module = self.target_scope.module()?;
+        let source_module = self.source_scope.module()?;
         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
             hir::GenericDef::Trait(_) => 1,
@@ -109,7 +111,8 @@ impl<'a> PathTransform<'a> {
                 },
             })
             .collect();
-        Ctx { substs: substs_by_param, target_module, source_scope: self.source_scope }
+        let res = Ctx { substs: substs_by_param, target_module, source_scope: self.source_scope };
+        Some(res)
     }
 }
 
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index fe99c2e2ce..805eac30b8 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -734,7 +734,13 @@ fn def_to_ty(sema: &Semantics<RootDatabase>, def: &Definition) -> Option<hir::Ty
     match def {
         Definition::Adt(adt) => Some(adt.ty(sema.db)),
         Definition::TypeAlias(it) => Some(it.ty(sema.db)),
-        Definition::BuiltinType(it) => Some(it.ty(sema.db)),
+        Definition::BuiltinType(it) => {
+            let graph = sema.db.crate_graph();
+            let krate = graph.iter().next()?;
+            let root_file = graph[krate].root_file_id;
+            let module = sema.to_module_def(root_file)?;
+            Some(it.ty(sema.db, module))
+        }
         Definition::SelfType(it) => Some(it.self_ty(sema.db)),
         _ => None,
     }
diff --git a/crates/ide_diagnostics/src/handlers/missing_fields.rs b/crates/ide_diagnostics/src/handlers/missing_fields.rs
index 414878b230..8b3c22fffc 100644
--- a/crates/ide_diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide_diagnostics/src/handlers/missing_fields.rs
@@ -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 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 {
             locals.insert(name, local);
         }
@@ -171,7 +171,11 @@ fn get_default_constructor(
     if has_new_func {
         Some(make::ext::expr_ty_new(&make_ty(ty, ctx.sema.db, module)))
     } else if !ty.is_array()
-        && ty.impls_trait(ctx.sema.db, FamousDefs(&ctx.sema, krate).core_default_Default()?, &[])
+        && ty.impls_trait(
+            ctx.sema.db,
+            FamousDefs(&ctx.sema, Some(krate)).core_default_Default()?,
+            &[],
+        )
     {
         Some(make::ext::expr_ty_default(&make_ty(ty, ctx.sema.db, module)))
     } else {
diff --git a/crates/ide_diagnostics/src/handlers/type_mismatch.rs b/crates/ide_diagnostics/src/handlers/type_mismatch.rs
index 1b275f7e6c..8ae9a0be53 100644
--- a/crates/ide_diagnostics/src/handlers/type_mismatch.rs
+++ b/crates/ide_diagnostics/src/handlers/type_mismatch.rs
@@ -76,7 +76,7 @@ fn add_missing_ok_or_some(
     let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?;
     let expr = d.expr.value.to_node(&root);
     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_enum = expected_adt.as_enum()?;
diff --git a/crates/ide_ssr/src/from_comment.rs b/crates/ide_ssr/src/from_comment.rs
index c50e74d93a..f1b312284d 100644
--- a/crates/ide_ssr/src/from_comment.rs
+++ b/crates/ide_ssr/src/from_comment.rs
@@ -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 mut match_finder = MatchFinder::in_context(db, lookup_context, vec![]).ok()?;
+    let mut match_finder = MatchFinder::in_context(db, lookup_context, vec![]);
     match_finder.add_rule(ssr_rule).ok()?;
 
     Some((match_finder, comment.syntax().text_range()))
diff --git a/crates/ide_ssr/src/lib.rs b/crates/ide_ssr/src/lib.rs
index 4db8034212..d56bc12b68 100644
--- a/crates/ide_ssr/src/lib.rs
+++ b/crates/ide_ssr/src/lib.rs
@@ -128,12 +128,11 @@ impl<'db> MatchFinder<'db> {
         db: &'db ide_db::RootDatabase,
         lookup_context: FilePosition,
         mut restrict_ranges: Vec<FileRange>,
-    ) -> Result<MatchFinder<'db>, SsrError> {
+    ) -> MatchFinder<'db> {
         restrict_ranges.retain(|range| !range.range.is_empty());
         let sema = Semantics::new(db);
-        let resolution_scope = resolving::ResolutionScope::new(&sema, lookup_context)
-            .ok_or_else(|| SsrError("no resolution scope for file".into()))?;
-        Ok(MatchFinder { sema, rules: Vec::new(), resolution_scope, restrict_ranges })
+        let resolution_scope = resolving::ResolutionScope::new(&sema, lookup_context);
+        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.
@@ -143,11 +142,11 @@ impl<'db> MatchFinder<'db> {
         if let Some(first_file_id) =
             db.local_roots().iter().next().and_then(|root| db.source_root(*root).iter().next())
         {
-            MatchFinder::in_context(
+            Ok(MatchFinder::in_context(
                 db,
                 FilePosition { file_id: first_file_id, offset: 0.into() },
                 vec![],
-            )
+            ))
         } else {
             bail!("No files to search");
         }
diff --git a/crates/ide_ssr/src/matching.rs b/crates/ide_ssr/src/matching.rs
index ba5aa0cc94..88c1d80608 100644
--- a/crates/ide_ssr/src/matching.rs
+++ b/crates/ide_ssr/src/matching.rs
@@ -646,8 +646,8 @@ impl Match {
     ) -> Result<(), MatchFailed> {
         let module = sema
             .scope(&self.matched_node)
-            .ok_or_else(|| match_error!("Matched node isn't in a module"))?
-            .module();
+            .module()
+            .ok_or_else(|| match_error!("Matched node isn't in a module"))?;
         for (path, resolved_path) in &template.resolved_paths {
             if let hir::PathResolution::Def(module_def) = resolved_path.resolution {
                 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 (db, position, selections) = crate::tests::single_file(input);
-        let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
+        let mut match_finder = MatchFinder::in_context(&db, position, selections);
         match_finder.add_rule(rule).unwrap();
         let matches = match_finder.matches();
         assert_eq!(matches.matches.len(), 1);
diff --git a/crates/ide_ssr/src/resolving.rs b/crates/ide_ssr/src/resolving.rs
index d9b40608b8..e15cb874ef 100644
--- a/crates/ide_ssr/src/resolving.rs
+++ b/crates/ide_ssr/src/resolving.rs
@@ -186,7 +186,7 @@ impl<'db> ResolutionScope<'db> {
     pub(crate) fn new(
         sema: &hir::Semantics<'db, ide_db::RootDatabase>,
         resolve_context: FilePosition,
-    ) -> Option<ResolutionScope<'db>> {
+    ) -> ResolutionScope<'db> {
         use syntax::ast::AstNode;
         let file = sema.parse(resolve_context.file_id);
         // 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())
             .unwrap_or_else(|| file.syntax().clone());
         let node = pick_node_for_resolution(node);
-        let scope = sema.scope(&node)?;
-        Some(ResolutionScope { scope, node })
+        let scope = sema.scope(&node);
+        ResolutionScope { scope, node }
     }
 
     /// 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()?)?;
         if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier {
             let name = path.segment()?.name_ref()?;
-            let module = self.scope.module();
+            let module = self.scope.module()?;
             adt.ty(self.scope.db).iterate_path_candidates(
                 self.scope.db,
                 &self.scope,
diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs
index c2e633fdb0..a000f515cc 100644
--- a/crates/parser/src/grammar/params.rs
+++ b/crates/parser/src/grammar/params.rs
@@ -71,10 +71,13 @@ fn list_(p: &mut Parser, flavor: Flavor) {
             m.abandon(p);
             break;
         }
-        param(p, m, flavor);
+        let param = param(p, m, flavor);
         if !p.at(ket) {
             p.expect(T![,]);
         }
+        if let Variadic(true) = param {
+            break;
+        }
     }
 
     if let Some(m) = param_marker {
@@ -87,24 +90,27 @@ fn list_(p: &mut Parser, flavor: Flavor) {
 
 const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
 
-fn param(p: &mut Parser, m: Marker, flavor: Flavor) {
+struct Variadic(bool);
+
+fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
+    let mut res = Variadic(false);
     match flavor {
         // test param_list_vararg
-        // extern "C" { fn printf(format: *const i8, ..., _: u8) -> i32; }
-        Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => {}
+        // extern "C" { fn printf(format: *const i8, ...) -> i32; }
+        Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => res = Variadic(true),
 
         // test fn_def_param
-        // fn foo(..., (x, y): (i32, i32)) {}
+        // fn foo((x, y): (i32, i32)) {}
         Flavor::FnDef => {
             patterns::pattern(p);
-            if !variadic_param(p) {
-                if p.at(T![:]) {
-                    types::ascription(p);
-                } else {
-                    // test_err missing_fn_param_type
-                    // fn f(x y: i32, z, t: i32) {}
-                    p.error("missing type for function parameter");
-                }
+            if variadic_param(p) {
+                res = Variadic(true);
+            } else if p.at(T![:]) {
+                types::ascription(p);
+            } else {
+                // test_err missing_fn_param_type
+                // fn f(x y: i32, z, t: i32) {}
+                p.error("missing type for function parameter");
             }
         }
         // test value_parameters_no_patterns
@@ -121,12 +127,12 @@ fn param(p: &mut Parser, m: Marker, flavor: Flavor) {
         Flavor::FnPointer => {
             if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
                 patterns::pattern_single(p);
-                if !variadic_param(p) {
-                    if p.at(T![:]) {
-                        types::ascription(p);
-                    } else {
-                        p.error("missing type for function parameter");
-                    }
+                if variadic_param(p) {
+                    res = Variadic(true);
+                } else if p.at(T![:]) {
+                    types::ascription(p);
+                } else {
+                    p.error("missing type for function parameter");
                 }
             } else {
                 types::type_(p);
@@ -144,6 +150,7 @@ fn param(p: &mut Parser, m: Marker, flavor: Flavor) {
         }
     }
     m.complete(p, PARAM);
+    res
 }
 
 fn variadic_param(p: &mut Parser) -> bool {
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs
index 509219f0b6..1a86d232eb 100644
--- a/crates/project_model/src/workspace.rs
+++ b/crates/project_model/src/workspace.rs
@@ -7,7 +7,7 @@ use std::{collections::VecDeque, fmt, fs, process::Command};
 use anyhow::{format_err, Context, Result};
 use base_db::{
     CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
-    FileId, LangCrateOrigin, ProcMacro,
+    FileId, ProcMacro,
 };
 use cfg::{CfgDiff, CfgOptions};
 use paths::{AbsPath, AbsPathBuf};
@@ -487,7 +487,7 @@ fn project_json_to_crate_graph(
                     if krate.display_name.is_some() {
                         CrateOrigin::CratesIo { repo: krate.repository.clone() }
                     } else {
-                        CrateOrigin::CratesIo { repo: None }
+                        CrateOrigin::Unknown
                     },
                 ),
             )
@@ -710,7 +710,7 @@ fn detached_files_to_crate_graph(
             Env::default(),
             Vec::new(),
             false,
-            CrateOrigin::CratesIo { repo: None },
+            CrateOrigin::Unknown,
         );
 
         public_deps.add(detached_file_crate, &mut crate_graph);
@@ -908,14 +908,7 @@ fn sysroot_to_crate_graph(
                 env,
                 proc_macro,
                 false,
-                CrateOrigin::Lang(match &*sysroot[krate].name {
-                    "alloc" => LangCrateOrigin::Alloc,
-                    "core" => LangCrateOrigin::Core,
-                    "proc_macro" => LangCrateOrigin::ProcMacro,
-                    "std" => LangCrateOrigin::Std,
-                    "test" => LangCrateOrigin::Test,
-                    _ => LangCrateOrigin::Other,
-                }),
+                CrateOrigin::Lang,
             );
             Some((krate, crate_id))
         })
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 15f4978367..8f91f64a69 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -123,14 +123,6 @@ pub(crate) fn handle_view_hir(
     Ok(res)
 }
 
-pub(crate) fn handle_view_file_text(
-    snap: GlobalStateSnapshot,
-    params: lsp_types::TextDocumentIdentifier,
-) -> Result<String> {
-    let file_id = from_proto::file_id(&snap, &params.uri)?;
-    Ok(snap.analysis.file_text(file_id)?.to_string())
-}
-
 pub(crate) fn handle_view_item_tree(
     snap: GlobalStateSnapshot,
     params: lsp_ext::ViewItemTreeParams,
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index b638a57111..2e131eeac9 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -70,14 +70,6 @@ impl Request for ViewHir {
     const METHOD: &'static str = "rust-analyzer/viewHir";
 }
 
-pub enum ViewFileText {}
-
-impl Request for ViewFileText {
-    type Params = lsp_types::TextDocumentIdentifier;
-    type Result = String;
-    const METHOD: &'static str = "rust-analyzer/viewFileText";
-}
-
 #[derive(Deserialize, Serialize, Debug)]
 #[serde(rename_all = "camelCase")]
 pub struct ViewCrateGraphParams {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 2d898d76a6..b62a830803 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -590,7 +590,6 @@ impl GlobalState {
             .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status)
             .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)
             .on::<lsp_ext::ViewHir>(handlers::handle_view_hir)
-            .on::<lsp_ext::ViewFileText>(handlers::handle_view_file_text)
             .on::<lsp_ext::ViewCrateGraph>(handlers::handle_view_crate_graph)
             .on::<lsp_ext::ViewItemTree>(handlers::handle_view_item_tree)
             .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro)
diff --git a/crates/rust-analyzer/src/markdown.rs b/crates/rust-analyzer/src/markdown.rs
index e1ff0f0178..912ed1e764 100644
--- a/crates/rust-analyzer/src/markdown.rs
+++ b/crates/rust-analyzer/src/markdown.rs
@@ -1,7 +1,7 @@
 //! Transforms markdown
 use ide_db::rust_doc::is_rust_fence;
 
-const RUSTDOC_FENCE: &str = "```";
+const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
 
 pub(crate) fn format_docs(src: &str) -> String {
     let mut processed_lines = Vec::new();
@@ -13,7 +13,8 @@ pub(crate) fn format_docs(src: &str) -> String {
             continue;
         }
 
-        if let Some(header) = line.strip_prefix(RUSTDOC_FENCE) {
+        if let Some(header) = RUSTDOC_FENCES.into_iter().find_map(|fence| line.strip_prefix(fence))
+        {
             in_code_block ^= true;
 
             if in_code_block {
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 516d1caccc..3091bdcbf0 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: a61de7db4504a4d1
+lsp_ext.rs hash: 854109e98d02a780
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
@@ -494,17 +494,6 @@ Primarily for debugging, but very useful for all people working on rust-analyzer
 Returns a textual representation of the HIR of the function containing the cursor.
 For debugging or when working on rust-analyzer itself.
 
-## View File Text
-
-**Method:** `rust-analyzer/viewFileText`
-
-**Request:** `TextDocumentIdentifier`
-
-**Response:** `string`
-
-Returns the text of a file as seen by the server.
-This is for debugging file sync problems.
-
 ## View ItemTree
 
 **Method:** `rust-analyzer/viewItemTree`
diff --git a/editors/code/package.json b/editors/code/package.json
index 7df00d2ef2..c55ef6f0f7 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -104,11 +104,6 @@
                 "title": "View Hir",
                 "category": "Rust Analyzer"
             },
-            {
-                "command": "rust-analyzer.viewFileText",
-                "title": "View File Text (as seen by the server)",
-                "category": "Rust Analyzer"
-            },
             {
                 "command": "rust-analyzer.viewItemTree",
                 "title": "Debug ItemTree",
@@ -1413,10 +1408,6 @@
                     "command": "rust-analyzer.viewHir",
                     "when": "inRustProject"
                 },
-                {
-                    "command": "rust-analyzer.viewFileText",
-                    "when": "inRustProject"
-                },
                 {
                     "command": "rust-analyzer.expandMacro",
                     "when": "inRustProject"
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 2802668be3..fe006a63e2 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -432,54 +432,6 @@ export function viewHir(ctx: Ctx): Cmd {
     };
 }
 
-export function viewFileText(ctx: Ctx): Cmd {
-    const tdcp = new class implements vscode.TextDocumentContentProvider {
-        readonly uri = vscode.Uri.parse('rust-analyzer://viewFileText/file.rs');
-        readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
-        constructor() {
-            vscode.workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, ctx.subscriptions);
-            vscode.window.onDidChangeActiveTextEditor(this.onDidChangeActiveTextEditor, this, ctx.subscriptions);
-        }
-
-        private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) {
-            if (isRustDocument(event.document)) {
-                // We need to order this after language server updates, but there's no API for that.
-                // Hence, good old sleep().
-                void sleep(10).then(() => this.eventEmitter.fire(this.uri));
-            }
-        }
-        private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
-            if (editor && isRustEditor(editor)) {
-                this.eventEmitter.fire(this.uri);
-            }
-        }
-
-        provideTextDocumentContent(_uri: vscode.Uri, ct: vscode.CancellationToken): vscode.ProviderResult<string> {
-            const rustEditor = ctx.activeRustEditor;
-            const client = ctx.client;
-            if (!rustEditor || !client) return '';
-
-            const params = client.code2ProtocolConverter.asTextDocumentIdentifier(rustEditor.document);
-            return client.sendRequest(ra.viewFileText, params, ct);
-        }
-
-        get onDidChange(): vscode.Event<vscode.Uri> {
-            return this.eventEmitter.event;
-        }
-    };
-
-    ctx.pushCleanup(vscode.workspace.registerTextDocumentContentProvider('rust-analyzer', tdcp));
-
-    return async () => {
-        const document = await vscode.workspace.openTextDocument(tdcp.uri);
-        tdcp.eventEmitter.fire(tdcp.uri);
-        void await vscode.window.showTextDocument(document, {
-            viewColumn: vscode.ViewColumn.Two,
-            preserveFocus: true
-        });
-    };
-}
-
 export function viewItemTree(ctx: Ctx): Cmd {
     const tdcp = new class implements vscode.TextDocumentContentProvider {
         readonly uri = vscode.Uri.parse('rust-analyzer://viewItemTree/itemtree.rs');
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 0ae5e93a73..9493a03481 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -36,8 +36,6 @@ export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>("ru
 
 export const viewHir = new lc.RequestType<lc.TextDocumentPositionParams, string, void>("rust-analyzer/viewHir");
 
-export const viewFileText = new lc.RequestType<lc.TextDocumentIdentifier, string, void>("rust-analyzer/viewFileText");
-
 export interface ViewItemTreeParams {
     textDocument: lc.TextDocumentIdentifier;
 }
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 36a095bdd3..06e5c1185d 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -114,7 +114,6 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) {
     ctx.registerCommand('parentModule', commands.parentModule);
     ctx.registerCommand('syntaxTree', commands.syntaxTree);
     ctx.registerCommand('viewHir', commands.viewHir);
-    ctx.registerCommand('viewFileText', commands.viewFileText);
     ctx.registerCommand('viewItemTree', commands.viewItemTree);
     ctx.registerCommand('viewCrateGraph', commands.viewCrateGraph);
     ctx.registerCommand('viewFullCrateGraph', commands.viewFullCrateGraph);


Test patch:
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index d9126421cd..36e9ec6333 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -110,6 +110,11 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foobar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
     <span class="comment documentation">/// ```</span>
     <span class="comment documentation">///</span>
+    <span class="comment documentation">/// ~~~rust,no_run</span>
+    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="comment injected">// code block with tilde.</span>
+    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foobar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
+    <span class="comment documentation">/// ~~~</span>
+    <span class="comment documentation">///</span>
     <span class="comment documentation">/// ```</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="comment injected">// functions</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function declaration injected">foo</span><span class="angle injected">&lt;</span><span class="type_param declaration injected">T</span><span class="comma injected">,</span><span class="none injected"> </span><span class="keyword injected">const</span><span class="none injected"> </span><span class="const_param declaration injected">X</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">usize</span><span class="angle injected">&gt;</span><span class="parenthesis injected">(</span><span class="value_param declaration injected">arg</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">i32</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
index af41796e21..87b9da46e2 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
@@ -43,5 +43,5 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span>
-<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root library">alloc</span> <span class="keyword">as</span> <span class="module crate_root declaration library">abc</span><span class="semicolon">;</span>
+<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">alloc</span> <span class="keyword">as</span> <span class="module crate_root default_library declaration library">abc</span><span class="semicolon">;</span>
 </code></pre>
\ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 2cd4fa809a..fdfe347a32 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -644,6 +644,11 @@ impl Foo {
     /// let foobar = Foo::new().bar();
     /// ```
     ///
+    /// ~~~rust,no_run
+    /// // code block with tilde.
+    /// let foobar = Foo::new().bar();
+    /// ~~~
+    ///
     /// ```
     /// // functions
     /// fn foo<T, const X: usize>(arg: i32) {
diff --git a/crates/ide_ssr/src/tests.rs b/crates/ide_ssr/src/tests.rs
index 26a043dc98..1862c3bcc2 100644
--- a/crates/ide_ssr/src/tests.rs
+++ b/crates/ide_ssr/src/tests.rs
@@ -94,7 +94,7 @@ fn assert_ssr_transform(rule: &str, input: &str, expected: Expect) {
 
 fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
     let (db, position, selections) = single_file(input);
-    let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
+    let mut match_finder = MatchFinder::in_context(&db, position, selections);
     for rule in rules {
         let rule: SsrRule = rule.parse().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]) {
     let (db, position, selections) = single_file(code);
-    let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
+    let mut match_finder = MatchFinder::in_context(&db, position, selections);
     match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
     let matched_strings: Vec<String> =
         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) {
     let (db, position, selections) = single_file(code);
-    let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
+    let mut match_finder = MatchFinder::in_context(&db, position, selections);
     match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
     let matches = match_finder.matches().flattened().matches;
     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) {
     let (db, position, selections) = single_file(code);
-    let mut match_finder = MatchFinder::in_context(&db, position, selections).unwrap();
+    let mut match_finder = MatchFinder::in_context(&db, position, selections);
     match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
     let mut reasons = Vec::new();
     for d in match_finder.debug_where_text_equal(position.file_id, snippet) {
diff --git a/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rast b/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rast
index 338d53995a..c86cf18bbe 100644
--- a/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rast
+++ b/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rast
@@ -34,18 +34,6 @@ SOURCE_FILE
           WHITESPACE " "
           PARAM
             DOT3 "..."
-          COMMA ","
-          WHITESPACE " "
-          PARAM
-            WILDCARD_PAT
-              UNDERSCORE "_"
-            COLON ":"
-            WHITESPACE " "
-            PATH_TYPE
-              PATH
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "u8"
           R_PAREN ")"
         WHITESPACE " "
         RET_TYPE
diff --git a/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rs b/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rs
index 533096cd5b..c59addaf42 100644
--- a/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rs
+++ b/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rs
@@ -1,1 +1,1 @@
-extern "C" { fn printf(format: *const i8, ..., _: u8) -> i32; }
+extern "C" { fn printf(format: *const i8, ...) -> i32; }
diff --git a/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rast b/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rast
index ce425a1afd..7511877aa8 100644
--- a/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rast
+++ b/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rast
@@ -6,10 +6,6 @@ SOURCE_FILE
       IDENT "foo"
     PARAM_LIST
       L_PAREN "("
-      PARAM
-        DOT3 "..."
-      COMMA ","
-      WHITESPACE " "
       PARAM
         TUPLE_PAT
           L_PAREN "("
diff --git a/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rs b/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rs
index 7b4c626582..7b277c16b1 100644
--- a/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rs
+++ b/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rs
@@ -1,1 +1,1 @@
-fn foo(..., (x, y): (i32, i32)) {}
+fn foo((x, y): (i32, i32)) {}
diff --git a/crates/project_model/src/tests.rs b/crates/project_model/src/tests.rs
index 351e820ada..ca347d71a2 100644
--- a/crates/project_model/src/tests.rs
+++ b/crates/project_model/src/tests.rs
@@ -1261,9 +1261,7 @@ fn rust_project_hello_world_project_model() {
                             },
                         ],
                         proc_macro: [],
-                        origin: Lang(
-                            Alloc,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1293,9 +1291,7 @@ fn rust_project_hello_world_project_model() {
                         },
                         dependencies: [],
                         proc_macro: [],
-                        origin: Lang(
-                            Other,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1325,9 +1321,7 @@ fn rust_project_hello_world_project_model() {
                         },
                         dependencies: [],
                         proc_macro: [],
-                        origin: Lang(
-                            Other,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1367,9 +1361,7 @@ fn rust_project_hello_world_project_model() {
                             },
                         ],
                         proc_macro: [],
-                        origin: Lang(
-                            ProcMacro,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1399,9 +1391,7 @@ fn rust_project_hello_world_project_model() {
                         },
                         dependencies: [],
                         proc_macro: [],
-                        origin: Lang(
-                            Core,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1500,9 +1490,7 @@ fn rust_project_hello_world_project_model() {
                         },
                         dependencies: [],
                         proc_macro: [],
-                        origin: Lang(
-                            Other,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1532,9 +1520,7 @@ fn rust_project_hello_world_project_model() {
                         },
                         dependencies: [],
                         proc_macro: [],
-                        origin: Lang(
-                            Other,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1564,9 +1550,7 @@ fn rust_project_hello_world_project_model() {
                         },
                         dependencies: [],
                         proc_macro: [],
-                        origin: Lang(
-                            Other,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1596,9 +1580,7 @@ fn rust_project_hello_world_project_model() {
                         },
                         dependencies: [],
                         proc_macro: [],
-                        origin: Lang(
-                            Test,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1710,9 +1692,7 @@ fn rust_project_hello_world_project_model() {
                             },
                         ],
                         proc_macro: [],
-                        origin: Lang(
-                            Std,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                     CrateId(
@@ -1742,9 +1722,7 @@ fn rust_project_hello_world_project_model() {
                         },
                         dependencies: [],
                         proc_macro: [],
-                        origin: Lang(
-                            Other,
-                        ),
+                        origin: Lang,
                         is_proc_macro: false,
                     },
                 },