Repository: rust-lang/rust-analyzer (rust)

Issue:
False negative type mismatch with associated types in arguments
```Rust
trait A {
    fn m(&self) -> i32;
}

fn x<T: B>(k: &<T as B>::Ty) {
    k.m();
}

impl A for u8 {
    fn m(&self) -> i32 {
        8
    }
}

impl A for u32 {
    fn m(&self) -> i32 {
        32
    }
}

trait B {
    type Ty: A;
}

impl B for u16 {
    type Ty = u32;
}

#[test]
fn ttt() {
    x::<u16>(&2u8); // Expected u32 found u8 is missing here.
}
```


Pull request:
Normalize expected ty in call arguments
fix #15321 

I'm not sure if we should do this, or add a normalize in the beginning of `infer_expr_inner`, or somewhere else. r? @lowr

Patch:
diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs
index 5aaa2bcc7c..73c8ad3dd5 100644
--- a/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -14,12 +14,13 @@ mod case_conv;
 
 use std::fmt;
 
+use base_db::CrateId;
 use hir_def::{
     data::adt::VariantData,
     hir::{Pat, PatId},
     src::HasSource,
-    AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ItemContainerId,
-    Lookup, ModuleDefId, StaticId, StructId,
+    AdtId, AttrDefId, ConstId, EnumId, FunctionId, ItemContainerId, Lookup, ModuleDefId, StaticId,
+    StructId,
 };
 use hir_expand::{
     name::{AsName, Name},
@@ -43,9 +44,13 @@ mod allow {
     pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types";
 }
 
-pub fn incorrect_case(db: &dyn HirDatabase, owner: ModuleDefId) -> Vec<IncorrectCase> {
+pub fn incorrect_case(
+    db: &dyn HirDatabase,
+    krate: CrateId,
+    owner: ModuleDefId,
+) -> Vec<IncorrectCase> {
     let _p = profile::span("validate_module_item");
-    let mut validator = DeclValidator::new(db);
+    let mut validator = DeclValidator::new(db, krate);
     validator.validate_item(owner);
     validator.sink
 }
@@ -115,6 +120,7 @@ pub struct IncorrectCase {
 
 pub(super) struct DeclValidator<'a> {
     db: &'a dyn HirDatabase,
+    krate: CrateId,
     pub(super) sink: Vec<IncorrectCase>,
 }
 
@@ -126,8 +132,8 @@ struct Replacement {
 }
 
 impl<'a> DeclValidator<'a> {
-    pub(super) fn new(db: &'a dyn HirDatabase) -> DeclValidator<'a> {
-        DeclValidator { db, sink: Vec::new() }
+    pub(super) fn new(db: &'a dyn HirDatabase, krate: CrateId) -> DeclValidator<'a> {
+        DeclValidator { db, krate, sink: Vec::new() }
     }
 
     pub(super) fn validate_item(&mut self, item: ModuleDefId) {
@@ -189,7 +195,8 @@ impl<'a> DeclValidator<'a> {
                 AttrDefId::TypeAliasId(_) => None,
                 AttrDefId::GenericParamId(_) => None,
             }
-            .is_some_and(|mid| self.allowed(mid, allow_name, true))
+            .map(|mid| self.allowed(mid, allow_name, true))
+            .unwrap_or(false)
     }
 
     fn validate_func(&mut self, func: FunctionId) {
@@ -199,7 +206,17 @@ impl<'a> DeclValidator<'a> {
             return;
         }
 
-        self.validate_body_inner_items(func.into());
+        let body = self.db.body(func.into());
+
+        // Recursively validate inner scope items, such as static variables and constants.
+        for (_, block_def_map) in body.blocks(self.db.upcast()) {
+            for (_, module) in block_def_map.modules() {
+                for def_id in module.scope.declarations() {
+                    let mut validator = DeclValidator::new(self.db, self.krate);
+                    validator.validate_item(def_id);
+                }
+            }
+        }
 
         // Check whether non-snake case identifiers are allowed for this function.
         if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) {
@@ -214,8 +231,6 @@ impl<'a> DeclValidator<'a> {
             expected_case: CaseType::LowerSnakeCase,
         });
 
-        let body = self.db.body(func.into());
-
         // Check the patterns inside the function body.
         // This includes function parameters.
         let pats_replacements = body
@@ -481,11 +496,6 @@ impl<'a> DeclValidator<'a> {
     fn validate_enum(&mut self, enum_id: EnumId) {
         let data = self.db.enum_data(enum_id);
 
-        for (local_id, _) in data.variants.iter() {
-            let variant_id = EnumVariantId { parent: enum_id, local_id };
-            self.validate_body_inner_items(variant_id.into());
-        }
-
         // Check whether non-camel case names are allowed for this enum.
         if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) {
             return;
@@ -502,11 +512,13 @@ impl<'a> DeclValidator<'a> {
         // Check the field names.
         let enum_fields_replacements = data
             .variants
-            .values()
-            .filter_map(|variant| {
+            .iter()
+            .filter_map(|(_, variant)| {
                 Some(Replacement {
                     current_name: variant.name.clone(),
-                    suggested_text: to_camel_case(&variant.name.to_smol_str())?,
+                    suggested_text: to_camel_case(
+                        &variant.name.display(self.db.upcast()).to_string(),
+                    )?,
                     expected_case: CaseType::UpperCamelCase,
                 })
             })
@@ -610,8 +622,6 @@ impl<'a> DeclValidator<'a> {
     fn validate_const(&mut self, const_id: ConstId) {
         let data = self.db.const_data(const_id);
 
-        self.validate_body_inner_items(const_id.into());
-
         if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
             return;
         }
@@ -621,7 +631,7 @@ impl<'a> DeclValidator<'a> {
             None => return,
         };
 
-        let const_name = name.to_smol_str();
+        let const_name = name.display(self.db.upcast()).to_string();
         let replacement = if let Some(new_name) = to_upper_snake_case(&const_name) {
             Replacement {
                 current_name: name.clone(),
@@ -660,15 +670,13 @@ impl<'a> DeclValidator<'a> {
             return;
         }
 
-        self.validate_body_inner_items(static_id.into());
-
         if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
             return;
         }
 
         let name = &data.name;
 
-        let static_name = name.to_smol_str();
+        let static_name = name.display(self.db.upcast()).to_string();
         let replacement = if let Some(new_name) = to_upper_snake_case(&static_name) {
             Replacement {
                 current_name: name.clone(),
@@ -699,17 +707,4 @@ impl<'a> DeclValidator<'a> {
 
         self.sink.push(diagnostic);
     }
-
-    // FIXME: We don't currently validate names within `DefWithBodyId::InTypeConstId`.
-    /// Recursively validates inner scope items, such as static variables and constants.
-    fn validate_body_inner_items(&mut self, body_id: DefWithBodyId) {
-        let body = self.db.body(body_id);
-        for (_, block_def_map) in body.blocks(self.db.upcast()) {
-            for (_, module) in block_def_map.modules() {
-                for def_id in module.scope.declarations() {
-                    self.validate_item(def_id);
-                }
-            }
-        }
-    }
 }
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 4b14345aa3..72e6443beb 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -1665,6 +1665,7 @@ impl InferenceContext<'_> {
                 // the parameter to coerce to the expected type (for example in
                 // `coerce_unsize_expected_type_4`).
                 let param_ty = self.normalize_associated_types_in(param_ty);
+                let expected_ty = self.normalize_associated_types_in(expected_ty);
                 let expected = Expectation::rvalue_hint(self, expected_ty);
                 // infer with the expected type we have...
                 let ty = self.infer_expr_inner(arg, &expected);
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index f3a5f69b2a..95ebc70627 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -1512,7 +1512,7 @@ fn autoderef_method_receiver(
     ty: Ty,
 ) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
     let mut deref_chain: Vec<_> = Vec::new();
-    let mut autoderef = autoderef::Autoderef::new(table, ty, false);
+    let mut autoderef = autoderef::Autoderef::new(table, ty, true);
     while let Some((ty, derefs)) = autoderef.next() {
         deref_chain.push((
             autoderef.table.canonicalize(ty).value,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index b094bb7a06..2b0fdffca9 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -378,6 +378,11 @@ impl ModuleDef {
             ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
         };
 
+        let module = match self.module(db) {
+            Some(it) => it,
+            None => return Vec::new(),
+        };
+
         let mut acc = Vec::new();
 
         match self.as_def_with_body() {
@@ -385,7 +390,7 @@ impl ModuleDef {
                 def.diagnostics(db, &mut acc);
             }
             None => {
-                for diag in hir_ty::diagnostics::incorrect_case(db, id) {
+                for diag in hir_ty::diagnostics::incorrect_case(db, module.id.krate(), id) {
                     acc.push(diag.into())
                 }
             }
@@ -1826,7 +1831,7 @@ impl DefWithBody {
             // FIXME: don't ignore diagnostics for in type const
             DefWithBody::InTypeConst(_) => return,
         };
-        for diag in hir_ty::diagnostics::incorrect_case(db, def.into()) {
+        for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
             acc.push(diag.into())
         }
     }
diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
index 235062bf53..92fd4f71ca 100644
--- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs
+++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
@@ -545,100 +545,4 @@ pub static SomeStatic: u8 = 10;
     "#,
         );
     }
-
-    #[test]
-    fn fn_inner_items() {
-        check_diagnostics(
-            r#"
-fn main() {
-    const foo: bool = true;
-        //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
-    static bar: bool = true;
-         //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
-    fn BAZ() {
-     //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
-        const foo: bool = true;
-            //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
-        static bar: bool = true;
-             //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
-        fn BAZ() {
-         //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
-            let INNER_INNER = 42;
-              //^^^^^^^^^^^ 💡 warn: Variable `INNER_INNER` should have snake_case name, e.g. `inner_inner`
-        }
-
-        let INNER_LOCAL = 42;
-          //^^^^^^^^^^^ 💡 warn: Variable `INNER_LOCAL` should have snake_case name, e.g. `inner_local`
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn const_body_inner_items() {
-        check_diagnostics(
-            r#"
-const _: () = {
-    static bar: bool = true;
-         //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
-    fn BAZ() {}
-     //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
-
-    const foo: () = {
-        //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
-        const foo: bool = true;
-            //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
-        static bar: bool = true;
-             //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
-        fn BAZ() {}
-         //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
-    };
-};
-"#,
-        );
-    }
-
-    #[test]
-    fn static_body_inner_items() {
-        check_diagnostics(
-            r#"
-static FOO: () = {
-    const foo: bool = true;
-        //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
-    fn BAZ() {}
-     //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
-
-    static bar: () = {
-         //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
-        const foo: bool = true;
-            //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
-        static bar: bool = true;
-             //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
-        fn BAZ() {}
-         //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
-    };
-};
-"#,
-        );
-    }
-
-    #[test]
-    fn enum_variant_body_inner_item() {
-        check_diagnostics(
-            r#"
-enum E {
-    A = {
-        const foo: bool = true;
-            //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
-        static bar: bool = true;
-             //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
-        fn BAZ() {}
-         //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
-        42
-    },
-}
-"#,
-        );
-    }
 }
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index a868419821..1814e0e54c 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -211,54 +211,70 @@ impl BlockLike {
 const VISIBILITY_FIRST: TokenSet = TokenSet::new(&[T![pub], T![crate]]);
 
 fn opt_visibility(p: &mut Parser<'_>, in_tuple_field: bool) -> bool {
-    if !p.at(T![pub]) {
-        return false;
-    }
-
-    let m = p.start();
-    p.bump(T![pub]);
-    if p.at(T!['(']) {
-        match p.nth(1) {
-            // test crate_visibility
-            // pub(crate) struct S;
-            // pub(self) struct S;
-            // pub(super) struct S;
-
-            // test_err crate_visibility_empty_recover
-            // pub() struct S;
-
-            // test pub_parens_typepath
-            // struct B(pub (super::A));
-            // struct B(pub (crate::A,));
-            T![crate] | T![self] | T![super] | T![ident] | T![')'] if p.nth(2) != T![:] => {
-                // If we are in a tuple struct, then the parens following `pub`
-                // might be an tuple field, not part of the visibility. So in that
-                // case we don't want to consume an identifier.
-
-                // test pub_tuple_field
-                // struct MyStruct(pub (u32, u32));
-                // struct MyStruct(pub (u32));
-                // struct MyStruct(pub ());
-                if !(in_tuple_field && matches!(p.nth(1), T![ident] | T![')'])) {
-                    p.bump(T!['(']);
-                    paths::use_path(p);
-                    p.expect(T![')']);
+    match p.current() {
+        T![pub] => {
+            let m = p.start();
+            p.bump(T![pub]);
+            if p.at(T!['(']) {
+                match p.nth(1) {
+                    // test crate_visibility
+                    // pub(crate) struct S;
+                    // pub(self) struct S;
+                    // pub(super) struct S;
+
+                    // test_err crate_visibility_empty_recover
+                    // pub() struct S;
+
+                    // test pub_parens_typepath
+                    // struct B(pub (super::A));
+                    // struct B(pub (crate::A,));
+                    T![crate] | T![self] | T![super] | T![ident] | T![')'] if p.nth(2) != T![:] => {
+                        // If we are in a tuple struct, then the parens following `pub`
+                        // might be an tuple field, not part of the visibility. So in that
+                        // case we don't want to consume an identifier.
+
+                        // test pub_tuple_field
+                        // struct MyStruct(pub (u32, u32));
+                        // struct MyStruct(pub (u32));
+                        // struct MyStruct(pub ());
+                        if !(in_tuple_field && matches!(p.nth(1), T![ident] | T![')'])) {
+                            p.bump(T!['(']);
+                            paths::use_path(p);
+                            p.expect(T![')']);
+                        }
+                    }
+                    // test crate_visibility_in
+                    // pub(in super::A) struct S;
+                    // pub(in crate) struct S;
+                    T![in] => {
+                        p.bump(T!['(']);
+                        p.bump(T![in]);
+                        paths::use_path(p);
+                        p.expect(T![')']);
+                    }
+                    _ => {}
                 }
             }
-            // test crate_visibility_in
-            // pub(in super::A) struct S;
-            // pub(in crate) struct S;
-            T![in] => {
-                p.bump(T!['(']);
-                p.bump(T![in]);
-                paths::use_path(p);
-                p.expect(T![')']);
+            m.complete(p, VISIBILITY);
+            true
+        }
+        // test crate_keyword_vis
+        // crate fn main() { }
+        // struct S { crate field: u32 }
+        // struct T(crate u32);
+        T![crate] => {
+            if p.nth_at(1, T![::]) {
+                // test crate_keyword_path
+                // fn foo() { crate::foo(); }
+                return false;
             }
-            _ => {}
+            let m = p.start();
+            p.bump(T![crate]);
+            m.complete(p, VISIBILITY);
+            true
         }
+        _ => false,
     }
-    m.complete(p, VISIBILITY);
-    true
 }
 
 fn opt_rename(p: &mut Parser<'_>) {
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index e47808a2cc..e1117ac464 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -145,7 +145,7 @@ pub struct PackageDependency {
     pub kind: DepKind,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
 pub enum DepKind {
     /// Available to the library, binary, and dev targets in the package (but not the build script).
     Normal,
@@ -156,20 +156,23 @@ pub enum DepKind {
 }
 
 impl DepKind {
-    fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator<Item = Self> {
-        let mut dep_kinds = [None; 3];
+    fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator<Item = Self> + '_ {
+        let mut dep_kinds = Vec::new();
         if list.is_empty() {
-            dep_kinds[0] = Some(Self::Normal);
+            dep_kinds.push(Self::Normal);
         }
         for info in list {
-            match info.kind {
-                cargo_metadata::DependencyKind::Normal => dep_kinds[0] = Some(Self::Normal),
-                cargo_metadata::DependencyKind::Development => dep_kinds[1] = Some(Self::Dev),
-                cargo_metadata::DependencyKind::Build => dep_kinds[2] = Some(Self::Build),
+            let kind = match info.kind {
+                cargo_metadata::DependencyKind::Normal => Self::Normal,
+                cargo_metadata::DependencyKind::Development => Self::Dev,
+                cargo_metadata::DependencyKind::Build => Self::Build,
                 cargo_metadata::DependencyKind::Unknown => continue,
-            }
+            };
+            dep_kinds.push(kind);
         }
-        dep_kinds.into_iter().flatten()
+        dep_kinds.sort_unstable();
+        dep_kinds.dedup();
+        dep_kinds.into_iter()
     }
 }
 
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 2cf985adab..31035c4b72 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -449,24 +449,27 @@ You'll need to close and reopen all .rs and Cargo files, or to restart the IDE,
 Support for the language server protocol is built into Kate through the LSP plugin, which is included by default.
 It is preconfigured to use rust-analyzer for Rust sources since Kate 21.12.
 
-To change rust-analyzer config options, start from the following example and put it into Kate's "User Server Settings" tab (located under the LSP Client settings):
+Earlier versions allow you to use rust-analyzer through a simple settings change.
+In the LSP Client settings of Kate, copy the content of the third tab "default parameters" to the second tab "server configuration".
+Then in the configuration replace:
 [source,json]
 ----
-{
-    "servers": {
         "rust": {
-            "initializationOptions": {
-                "cachePriming": {
-                    "enable": false
-                },
-                "check": {
-                    "allTargets": false
-                },
-                "checkOnSave": false
-            }
-        }
-    }
-}
+            "command": ["rls"],
+            "rootIndicationFileNames": ["Cargo.lock", "Cargo.toml"],
+            "url": "https://github.com/rust-lang/rls",
+            "highlightingModeRegex": "^Rust$"
+        },
+----
+With
+[source,json]
+----
+        "rust": {
+            "command": ["rust-analyzer"],
+            "rootIndicationFileNames": ["Cargo.lock", "Cargo.toml"],
+            "url": "https://github.com/rust-lang/rust-analyzer",
+            "highlightingModeRegex": "^Rust$"
+        },
 ----
 Then click on apply, and restart the LSP server for your rust project.
 
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index e817d680ea..f3d6238d51 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -66,12 +66,6 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis
     return vscode.debug.startDebugging(undefined, debugConfig);
 }
 
-function createCommandLink(extensionId: string): string {
-    // do not remove the second quotes inside
-    // encodeURIComponent or it won't work
-    return `extension.open?${encodeURIComponent(`"${extensionId}"`)}`;
-}
-
 async function getDebugConfiguration(
     ctx: Ctx,
     runnable: ra.Runnable,
@@ -96,12 +90,9 @@ async function getDebugConfiguration(
     }
 
     if (!debugEngine) {
-        const commandCodeLLDB: string = createCommandLink("vadimcn.vscode-lldb");
-        const commandCpp: string = createCommandLink("ms-vscode.cpptools");
-
         await vscode.window.showErrorMessage(
-            `Install [CodeLLDB](command:${commandCodeLLDB} "Open CodeLLDB")` +
-                ` or [C/C++](command:${commandCpp} "Open C/C++") extension for debugging.`,
+            `Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)` +
+                ` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`,
         );
         return;
     }


Test patch:
diff --git a/crates/hir-ty/src/tests/method_resolution.rs b/crates/hir-ty/src/tests/method_resolution.rs
index c837fae3fe..a8e146b096 100644
--- a/crates/hir-ty/src/tests/method_resolution.rs
+++ b/crates/hir-ty/src/tests/method_resolution.rs
@@ -1236,27 +1236,6 @@ fn main() {
     );
 }
 
-#[test]
-fn inherent_method_ref_self_deref_raw() {
-    check_types(
-        r#"
-struct Val;
-
-impl Val {
-    pub fn method(&self) -> u32 {
-        0
-    }
-}
-
-fn main() {
-    let foo: *const Val;
-    foo.method();
- // ^^^^^^^^^^^^ {unknown}
-}
-"#,
-    );
-}
-
 #[test]
 fn trait_method_deref_raw() {
     check_types(
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 5f5cd79451..542df8b346 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -4434,3 +4434,47 @@ fn test(v: S<i32>) {
 "#,
     );
 }
+
+#[test]
+fn associated_type_in_argument() {
+    check(
+        r#"
+    trait A {
+        fn m(&self) -> i32;
+    }
+
+    fn x<T: B>(k: &<T as B>::Ty) {
+        k.m();
+    }
+
+    struct X;
+    struct Y;
+
+    impl A for X {
+        fn m(&self) -> i32 {
+            8
+        }
+    }
+
+    impl A for Y {
+        fn m(&self) -> i32 {
+            32
+        }
+    }
+
+    trait B {
+        type Ty: A;
+    }
+
+    impl B for u16 {
+        type Ty = X;
+    }
+
+    fn ttt() {
+        let inp = Y;
+        x::<u16>(&inp);
+               //^^^^ expected &X, got &Y
+    }
+    "#,
+    );
+}
diff --git a/crates/parser/src/tests/prefix_entries.rs b/crates/parser/src/tests/prefix_entries.rs
index 2f3c7febc0..11f9c34abd 100644
--- a/crates/parser/src/tests/prefix_entries.rs
+++ b/crates/parser/src/tests/prefix_entries.rs
@@ -6,6 +6,7 @@ fn vis() {
     check(PrefixEntryPoint::Vis, "fn foo() {}", "");
     check(PrefixEntryPoint::Vis, "pub(fn foo() {}", "pub");
     check(PrefixEntryPoint::Vis, "pub(crate fn foo() {}", "pub(crate");
+    check(PrefixEntryPoint::Vis, "crate fn foo() {}", "crate");
 }
 
 #[test]
diff --git a/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast b/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
new file mode 100644
index 0000000000..07b0210e44
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
@@ -0,0 +1,63 @@
+SOURCE_FILE
+  FN
+    VISIBILITY
+      CRATE_KW "crate"
+    WHITESPACE " "
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "main"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE " "
+        R_CURLY "}"
+  WHITESPACE "\n"
+  STRUCT
+    STRUCT_KW "struct"
+    WHITESPACE " "
+    NAME
+      IDENT "S"
+    WHITESPACE " "
+    RECORD_FIELD_LIST
+      L_CURLY "{"
+      WHITESPACE " "
+      RECORD_FIELD
+        VISIBILITY
+          CRATE_KW "crate"
+        WHITESPACE " "
+        NAME
+          IDENT "field"
+        COLON ":"
+        WHITESPACE " "
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "u32"
+      WHITESPACE " "
+      R_CURLY "}"
+  WHITESPACE "\n"
+  STRUCT
+    STRUCT_KW "struct"
+    WHITESPACE " "
+    NAME
+      IDENT "T"
+    TUPLE_FIELD_LIST
+      L_PAREN "("
+      TUPLE_FIELD
+        VISIBILITY
+          CRATE_KW "crate"
+        WHITESPACE " "
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "u32"
+      R_PAREN ")"
+    SEMICOLON ";"
+  WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs b/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs
new file mode 100644
index 0000000000..e2b5f2161d
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs
@@ -0,0 +1,3 @@
+crate fn main() { }
+struct S { crate field: u32 }
+struct T(crate u32);
diff --git a/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast b/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast
new file mode 100644
index 0000000000..8d9b61630a
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast
@@ -0,0 +1,33 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "foo"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE " "
+        EXPR_STMT
+          CALL_EXPR
+            PATH_EXPR
+              PATH
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      CRATE_KW "crate"
+                COLON2 "::"
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "foo"
+            ARG_LIST
+              L_PAREN "("
+              R_PAREN ")"
+          SEMICOLON ";"
+        WHITESPACE " "
+        R_CURLY "}"
+  WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs b/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs
new file mode 100644
index 0000000000..0f454d121d
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs
@@ -0,0 +1,1 @@
+fn foo() { crate::foo(); }