From 08e95a5dc1035c57f2cfe6f61f0d64280b940b10 Mon Sep 17 00:00:00 2001 From: GrayJack Date: Mon, 26 Oct 2020 15:20:33 -0300 Subject: [PATCH 1/3] Fix case where non FnOnce variables is marked callable --- crates/hir/src/code_model.rs | 2 +- crates/hir_ty/src/method_resolution.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 63c1a8ebf0..563145f921 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs @@ -1398,7 +1398,7 @@ impl Type { }; let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) }; - method_resolution::implements_trait( + method_resolution::implements_trait_unique( &canonical_ty, db, self.ty.environment.clone(), diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 8961df4049..5a6f0c67fb 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -740,6 +740,19 @@ pub fn implements_trait( solution.is_some() } +pub fn implements_trait_unique( + ty: &Canonical, + db: &dyn HirDatabase, + env: Arc, + krate: CrateId, + trait_: TraitId, +) -> bool { + let goal = generic_implements_goal(db, env, trait_, ty.clone()); + let solution = db.trait_solve(krate, goal); + + matches!(solution, Some(crate::traits::Solution::Unique(_))) +} + /// This creates Substs for a trait with the given Self type and type variables /// for all other parameters, to query Chalk with it. fn generic_implements_goal( From 40a875ab7a65f21adae81414de48706b2b794687 Mon Sep 17 00:00:00 2001 From: GrayJack Date: Mon, 26 Oct 2020 15:28:56 -0300 Subject: [PATCH 2/3] Add test to avoid regression --- .../test_data/highlighting.html | 368 +++++++++--------- crates/ide/src/syntax_highlighting/tests.rs | 6 + 2 files changed, 193 insertions(+), 181 deletions(-) diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index c6b4f5a002..212f04c807 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html @@ -1,197 +1,203 @@ -
use inner::{self as inner_mod};
-mod inner {}
+    .unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+    
+    
use inner::{self as inner_mod};
+    mod inner {}
 
-// Needed for function consuming vs normal
-pub mod marker {
-    #[lang = "copy"]
-    pub trait Copy {}
-}
-
-pub mod ops {
-    #[lang = "fn_once"]
-    pub trait FnOnce<Args> {}
-
-    #[lang = "fn_mut"]
-    pub trait FnMut<Args>: FnOnce<Args> {}
-
-    #[lang = "fn"]
-    pub trait Fn<Args>: FnMut<Args> {}
-}
-
-
-struct Foo {
-    pub x: i32,
-    pub y: i32,
-}
-
-trait Bar {
-    fn bar(&self) -> i32;
-}
-
-impl Bar for Foo {
-    fn bar(&self) -> i32 {
-        self.x
-    }
-}
-
-impl Foo {
-    fn baz(mut self, f: Foo) -> i32 {
-        f.baz(self)
+    // Needed for function consuming vs normal
+    pub mod marker {
+        #[lang = "copy"]
+        pub trait Copy {}
     }
 
-    fn qux(&mut self) {
-        self.x = 0;
+    pub mod ops {
+        #[lang = "fn_once"]
+        pub trait FnOnce<Args> {}
+
+        #[lang = "fn_mut"]
+        pub trait FnMut<Args>: FnOnce<Args> {}
+
+        #[lang = "fn"]
+        pub trait Fn<Args>: FnMut<Args> {}
     }
 
-    fn quop(&self) -> i32 {
-        self.x
-    }
-}
 
-#[derive(Copy)]
-struct FooCopy {
-    x: u32,
-}
-
-impl FooCopy {
-    fn baz(self, f: FooCopy) -> u32 {
-        f.baz(self)
+    struct Foo {
+        pub x: i32,
+        pub y: i32,
     }
 
-    fn qux(&mut self) {
-        self.x = 0;
+    trait Bar {
+        fn bar(&self) -> i32;
     }
 
-    fn quop(&self) -> u32 {
-        self.x
-    }
-}
-
-static mut STATIC_MUT: i32 = 0;
-
-fn foo<'a, T>() -> T {
-    foo::<'a, i32>()
-}
-
-use ops::Fn;
-fn baz<F: Fn() -> ()>(f: F) {
-    f()
-}
-
-macro_rules! def_fn {
-    ($($tt:tt)*) => {$($tt)*}
-}
-
-def_fn! {
-    fn bar() -> u32 {
-        100
-    }
-}
-
-macro_rules! noop {
-    ($expr:expr) => {
-        $expr
-    }
-}
-
-macro_rules! keyword_frag {
-    ($type:ty) => ($type)
-}
-
-// comment
-fn main() {
-    println!("Hello, {}!", 92);
-
-    let mut vec = Vec::new();
-    if true {
-        let x = 92;
-        vec.push(Foo { x, y: 1 });
-    }
-    unsafe {
-        vec.set_len(0);
-        STATIC_MUT = 1;
-    }
-
-    for e in vec {
-        // Do nothing
-    }
-
-    noop!(noop!(1));
-
-    let mut x = 42;
-    let y = &mut x;
-    let z = &y;
-
-    let Foo { x: z, y } = Foo { x: z, y };
-
-    y;
-
-    let mut foo = Foo { x, y: x };
-    let foo2 = Foo { x, y: x };
-    foo.quop();
-    foo.qux();
-    foo.baz(foo2);
-
-    let mut copy = FooCopy { x };
-    copy.quop();
-    copy.qux();
-    copy.baz(copy);
-
-    let a = |x| x;
-    let bar = Foo::baz;
-
-    let baz = -42;
-    let baz = -baz;
-}
-
-enum Option<T> {
-    Some(T),
-    None,
-}
-use Option::*;
-
-impl<T> Option<T> {
-    fn and<U>(self, other: Option<U>) -> Option<(T, U)> {
-        match other {
-            None => unimplemented!(),
-            Nope => Nope,
+    impl Bar for Foo {
+        fn bar(&self) -> i32 {
+            self.x
         }
     }
-}
\ No newline at end of file + + impl Foo { + fn baz(mut self, f: Foo) -> i32 { + f.baz(self) + } + + fn qux(&mut self) { + self.x = 0; + } + + fn quop(&self) -> i32 { + self.x + } + } + + #[derive(Copy)] + struct FooCopy { + x: u32, + } + + impl FooCopy { + fn baz(self, f: FooCopy) -> u32 { + f.baz(self) + } + + fn qux(&mut self) { + self.x = 0; + } + + fn quop(&self) -> u32 { + self.x + } + } + + static mut STATIC_MUT: i32 = 0; + + fn foo<'a, T>() -> T { + foo::<'a, i32>() + } + + use ops::Fn; + fn baz<F: Fn() -> ()>(f: F) { + f() + } + + fn foobar() -> impl Copy {} + + fn foo() { + let bar = foobar(); + } + + macro_rules! def_fn { + ($($tt:tt)*) => {$($tt)*} + } + + def_fn! { + fn bar() -> u32 { + 100 + } + } + + macro_rules! noop { + ($expr:expr) => { + $expr + } + } + + macro_rules! keyword_frag { + ($type:ty) => ($type) + } + + // comment + fn main() { + println!("Hello, {}!", 92); + + let mut vec = Vec::new(); + if true { + let x = 92; + vec.push(Foo { x, y: 1 }); + } + unsafe { + vec.set_len(0); + STATIC_MUT = 1; + } + + for e in vec { + // Do nothing + } + + noop!(noop!(1)); + + let mut x = 42; + let y = &mut x; + let z = &y; + + let Foo { x: z, y } = Foo { x: z, y }; + + y; + + let mut foo = Foo { x, y: x }; + let foo2 = Foo { x, y: x }; + foo.quop(); + foo.qux(); + foo.baz(foo2); + + let mut copy = FooCopy { x }; + copy.quop(); + copy.qux(); + copy.baz(copy); + + let a = |x| x; + let bar = Foo::baz; + + let baz = -42; + let baz = -baz; + } + + enum Option<T> { + Some(T), + None, + } + use Option::*; + + impl<T> Option<T> { + fn and<U>(self, other: Option<U>) -> Option<(T, U)> { + match other { + None => unimplemented!(), + Nope => Nope, + } + } + }
\ 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 dd43f9dd95..5ea712cf5f 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -89,6 +89,12 @@ fn baz ()>(f: F) { f() } +fn foobar() -> impl Copy {} + +fn foo() { + let bar = foobar(); +} + macro_rules! def_fn { ($($tt:tt)*) => {$($tt)*} } From ae6376d74cf354a71a83d8c1dcc93589acbce6ea Mon Sep 17 00:00:00 2001 From: GrayJack Date: Mon, 26 Oct 2020 17:23:29 -0300 Subject: [PATCH 3/3] Fix test --- .../test_data/highlighting.html | 374 +++++++++--------- 1 file changed, 187 insertions(+), 187 deletions(-) diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 212f04c807..ee115972b0 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html @@ -1,203 +1,203 @@ -
use inner::{self as inner_mod};
-    mod inner {}
+.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+
+
use inner::{self as inner_mod};
+mod inner {}
 
-    // Needed for function consuming vs normal
-    pub mod marker {
-        #[lang = "copy"]
-        pub trait Copy {}
+// Needed for function consuming vs normal
+pub mod marker {
+    #[lang = "copy"]
+    pub trait Copy {}
+}
+
+pub mod ops {
+    #[lang = "fn_once"]
+    pub trait FnOnce<Args> {}
+
+    #[lang = "fn_mut"]
+    pub trait FnMut<Args>: FnOnce<Args> {}
+
+    #[lang = "fn"]
+    pub trait Fn<Args>: FnMut<Args> {}
+}
+
+
+struct Foo {
+    pub x: i32,
+    pub y: i32,
+}
+
+trait Bar {
+    fn bar(&self) -> i32;
+}
+
+impl Bar for Foo {
+    fn bar(&self) -> i32 {
+        self.x
+    }
+}
+
+impl Foo {
+    fn baz(mut self, f: Foo) -> i32 {
+        f.baz(self)
     }
 
-    pub mod ops {
-        #[lang = "fn_once"]
-        pub trait FnOnce<Args> {}
-
-        #[lang = "fn_mut"]
-        pub trait FnMut<Args>: FnOnce<Args> {}
-
-        #[lang = "fn"]
-        pub trait Fn<Args>: FnMut<Args> {}
+    fn qux(&mut self) {
+        self.x = 0;
     }
 
+    fn quop(&self) -> i32 {
+        self.x
+    }
+}
 
-    struct Foo {
-        pub x: i32,
-        pub y: i32,
+#[derive(Copy)]
+struct FooCopy {
+    x: u32,
+}
+
+impl FooCopy {
+    fn baz(self, f: FooCopy) -> u32 {
+        f.baz(self)
     }
 
-    trait Bar {
-        fn bar(&self) -> i32;
+    fn qux(&mut self) {
+        self.x = 0;
     }
 
-    impl Bar for Foo {
-        fn bar(&self) -> i32 {
-            self.x
+    fn quop(&self) -> u32 {
+        self.x
+    }
+}
+
+static mut STATIC_MUT: i32 = 0;
+
+fn foo<'a, T>() -> T {
+    foo::<'a, i32>()
+}
+
+use ops::Fn;
+fn baz<F: Fn() -> ()>(f: F) {
+    f()
+}
+
+fn foobar() -> impl Copy {}
+
+fn foo() {
+    let bar = foobar();
+}
+
+macro_rules! def_fn {
+    ($($tt:tt)*) => {$($tt)*}
+}
+
+def_fn! {
+    fn bar() -> u32 {
+        100
+    }
+}
+
+macro_rules! noop {
+    ($expr:expr) => {
+        $expr
+    }
+}
+
+macro_rules! keyword_frag {
+    ($type:ty) => ($type)
+}
+
+// comment
+fn main() {
+    println!("Hello, {}!", 92);
+
+    let mut vec = Vec::new();
+    if true {
+        let x = 92;
+        vec.push(Foo { x, y: 1 });
+    }
+    unsafe {
+        vec.set_len(0);
+        STATIC_MUT = 1;
+    }
+
+    for e in vec {
+        // Do nothing
+    }
+
+    noop!(noop!(1));
+
+    let mut x = 42;
+    let y = &mut x;
+    let z = &y;
+
+    let Foo { x: z, y } = Foo { x: z, y };
+
+    y;
+
+    let mut foo = Foo { x, y: x };
+    let foo2 = Foo { x, y: x };
+    foo.quop();
+    foo.qux();
+    foo.baz(foo2);
+
+    let mut copy = FooCopy { x };
+    copy.quop();
+    copy.qux();
+    copy.baz(copy);
+
+    let a = |x| x;
+    let bar = Foo::baz;
+
+    let baz = -42;
+    let baz = -baz;
+}
+
+enum Option<T> {
+    Some(T),
+    None,
+}
+use Option::*;
+
+impl<T> Option<T> {
+    fn and<U>(self, other: Option<U>) -> Option<(T, U)> {
+        match other {
+            None => unimplemented!(),
+            Nope => Nope,
         }
     }
-
-    impl Foo {
-        fn baz(mut self, f: Foo) -> i32 {
-            f.baz(self)
-        }
-
-        fn qux(&mut self) {
-            self.x = 0;
-        }
-
-        fn quop(&self) -> i32 {
-            self.x
-        }
-    }
-
-    #[derive(Copy)]
-    struct FooCopy {
-        x: u32,
-    }
-
-    impl FooCopy {
-        fn baz(self, f: FooCopy) -> u32 {
-            f.baz(self)
-        }
-
-        fn qux(&mut self) {
-            self.x = 0;
-        }
-
-        fn quop(&self) -> u32 {
-            self.x
-        }
-    }
-
-    static mut STATIC_MUT: i32 = 0;
-
-    fn foo<'a, T>() -> T {
-        foo::<'a, i32>()
-    }
-
-    use ops::Fn;
-    fn baz<F: Fn() -> ()>(f: F) {
-        f()
-    }
-
-    fn foobar() -> impl Copy {}
-
-    fn foo() {
-        let bar = foobar();
-    }
-
-    macro_rules! def_fn {
-        ($($tt:tt)*) => {$($tt)*}
-    }
-
-    def_fn! {
-        fn bar() -> u32 {
-            100
-        }
-    }
-
-    macro_rules! noop {
-        ($expr:expr) => {
-            $expr
-        }
-    }
-
-    macro_rules! keyword_frag {
-        ($type:ty) => ($type)
-    }
-
-    // comment
-    fn main() {
-        println!("Hello, {}!", 92);
-
-        let mut vec = Vec::new();
-        if true {
-            let x = 92;
-            vec.push(Foo { x, y: 1 });
-        }
-        unsafe {
-            vec.set_len(0);
-            STATIC_MUT = 1;
-        }
-
-        for e in vec {
-            // Do nothing
-        }
-
-        noop!(noop!(1));
-
-        let mut x = 42;
-        let y = &mut x;
-        let z = &y;
-
-        let Foo { x: z, y } = Foo { x: z, y };
-
-        y;
-
-        let mut foo = Foo { x, y: x };
-        let foo2 = Foo { x, y: x };
-        foo.quop();
-        foo.qux();
-        foo.baz(foo2);
-
-        let mut copy = FooCopy { x };
-        copy.quop();
-        copy.qux();
-        copy.baz(copy);
-
-        let a = |x| x;
-        let bar = Foo::baz;
-
-        let baz = -42;
-        let baz = -baz;
-    }
-
-    enum Option<T> {
-        Some(T),
-        None,
-    }
-    use Option::*;
-
-    impl<T> Option<T> {
-        fn and<U>(self, other: Option<U>) -> Option<(T, U)> {
-            match other {
-                None => unimplemented!(),
-                Nope => Nope,
-            }
-        }
-    }
\ No newline at end of file +}
\ No newline at end of file