diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-06-20 16:10:35 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-06-20 16:10:35 +0100 |
commit | c8557b91a3ccfea5c83260bc35a59e6839784281 (patch) | |
tree | 995472970b95ec9da7980588fb85372764afca04 /crates/ra_hir_ty/src/tests/traits.rs | |
parent | 0f7961d5570f17d6c2098ab11d2a3bcbbfb84ff6 (diff) | |
parent | 1629fb770e21c7e7fd4c478f5074590d5c9e6829 (diff) |
Merge #4958
4958: Infer FnSig via Fn traits r=flodiebold a=adamrk
Addresses https://github.com/rust-analyzer/rust-analyzer/issues/4481.
When inferring types check if the callee implements one of the builtin `Fn` traits. Also autoderef the callee before trying to figure out it's `FnSig`.
Co-authored-by: adamrk <[email protected]>
Diffstat (limited to 'crates/ra_hir_ty/src/tests/traits.rs')
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index e81193a3c..961be4abd 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -2888,3 +2888,226 @@ impl<A: Step> iter::Iterator for ops::Range<A> { | |||
2888 | ); | 2888 | ); |
2889 | assert_eq!(t, "i32"); | 2889 | assert_eq!(t, "i32"); |
2890 | } | 2890 | } |
2891 | |||
2892 | #[test] | ||
2893 | fn infer_closure_arg() { | ||
2894 | assert_snapshot!( | ||
2895 | infer( | ||
2896 | r#" | ||
2897 | //- /lib.rs | ||
2898 | |||
2899 | enum Option<T> { | ||
2900 | None, | ||
2901 | Some(T) | ||
2902 | } | ||
2903 | |||
2904 | fn foo() { | ||
2905 | let s = Option::None; | ||
2906 | let f = |x: Option<i32>| {}; | ||
2907 | (&f)(s) | ||
2908 | } | ||
2909 | "# | ||
2910 | ), | ||
2911 | @r###" | ||
2912 | 137..259 '{ ... }': () | ||
2913 | 159..160 's': Option<i32> | ||
2914 | 163..175 'Option::None': Option<i32> | ||
2915 | 197..198 'f': |Option<i32>| -> () | ||
2916 | 201..220 '|x: Op...2>| {}': |Option<i32>| -> () | ||
2917 | 202..203 'x': Option<i32> | ||
2918 | 218..220 '{}': () | ||
2919 | 238..245 '(&f)(s)': () | ||
2920 | 239..241 '&f': &|Option<i32>| -> () | ||
2921 | 240..241 'f': |Option<i32>| -> () | ||
2922 | 243..244 's': Option<i32> | ||
2923 | "### | ||
2924 | ); | ||
2925 | } | ||
2926 | |||
2927 | #[test] | ||
2928 | fn infer_fn_trait_arg() { | ||
2929 | assert_snapshot!( | ||
2930 | infer( | ||
2931 | r#" | ||
2932 | //- /lib.rs deps:std | ||
2933 | |||
2934 | #[lang = "fn_once"] | ||
2935 | pub trait FnOnce<Args> { | ||
2936 | type Output; | ||
2937 | |||
2938 | extern "rust-call" fn call_once(&self, args: Args) -> Self::Output; | ||
2939 | } | ||
2940 | |||
2941 | #[lang = "fn"] | ||
2942 | pub trait Fn<Args>:FnOnce<Args> { | ||
2943 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; | ||
2944 | } | ||
2945 | |||
2946 | enum Option<T> { | ||
2947 | None, | ||
2948 | Some(T) | ||
2949 | } | ||
2950 | |||
2951 | fn foo<F, T>(f: F) -> T | ||
2952 | where | ||
2953 | F: Fn(Option<i32>) -> T, | ||
2954 | { | ||
2955 | let s = None; | ||
2956 | f(s) | ||
2957 | } | ||
2958 | "# | ||
2959 | ), | ||
2960 | @r###" | ||
2961 | 183..187 'self': &Self | ||
2962 | 189..193 'args': Args | ||
2963 | 350..354 'self': &Self | ||
2964 | 356..360 'args': Args | ||
2965 | 515..516 'f': F | ||
2966 | 597..663 '{ ... }': T | ||
2967 | 619..620 's': Option<i32> | ||
2968 | 623..627 'None': Option<i32> | ||
2969 | 645..646 'f': F | ||
2970 | 645..649 'f(s)': T | ||
2971 | 647..648 's': Option<i32> | ||
2972 | "### | ||
2973 | ); | ||
2974 | } | ||
2975 | |||
2976 | #[test] | ||
2977 | fn infer_box_fn_arg() { | ||
2978 | assert_snapshot!( | ||
2979 | infer( | ||
2980 | r#" | ||
2981 | //- /lib.rs deps:std | ||
2982 | |||
2983 | #[lang = "fn_once"] | ||
2984 | pub trait FnOnce<Args> { | ||
2985 | type Output; | ||
2986 | |||
2987 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ||
2988 | } | ||
2989 | |||
2990 | #[lang = "deref"] | ||
2991 | pub trait Deref { | ||
2992 | type Target: ?Sized; | ||
2993 | |||
2994 | fn deref(&self) -> &Self::Target; | ||
2995 | } | ||
2996 | |||
2997 | #[lang = "owned_box"] | ||
2998 | pub struct Box<T: ?Sized> { | ||
2999 | inner: *mut T, | ||
3000 | } | ||
3001 | |||
3002 | impl<T: ?Sized> Deref for Box<T> { | ||
3003 | type Target = T; | ||
3004 | |||
3005 | fn deref(&self) -> &T { | ||
3006 | &self.inner | ||
3007 | } | ||
3008 | } | ||
3009 | |||
3010 | enum Option<T> { | ||
3011 | None, | ||
3012 | Some(T) | ||
3013 | } | ||
3014 | |||
3015 | fn foo() { | ||
3016 | let s = Option::None; | ||
3017 | let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {}); | ||
3018 | f(&s) | ||
3019 | } | ||
3020 | "# | ||
3021 | ), | ||
3022 | @r###" | ||
3023 | 182..186 'self': Self | ||
3024 | 188..192 'args': Args | ||
3025 | 356..360 'self': &Self | ||
3026 | 622..626 'self': &Box<T> | ||
3027 | 634..685 '{ ... }': &T | ||
3028 | 656..667 '&self.inner': &*mut T | ||
3029 | 657..661 'self': &Box<T> | ||
3030 | 657..667 'self.inner': *mut T | ||
3031 | 812..957 '{ ... }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)> | ||
3032 | 834..835 's': Option<i32> | ||
3033 | 838..850 'Option::None': Option<i32> | ||
3034 | 872..873 'f': Box<dyn FnOnce<(&Option<i32>,)>> | ||
3035 | 907..920 'box (|ps| {})': Box<|{unknown}| -> ()> | ||
3036 | 912..919 '|ps| {}': |{unknown}| -> () | ||
3037 | 913..915 'ps': {unknown} | ||
3038 | 917..919 '{}': () | ||
3039 | 938..939 'f': Box<dyn FnOnce<(&Option<i32>,)>> | ||
3040 | 938..943 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)> | ||
3041 | 940..942 '&s': &Option<i32> | ||
3042 | 941..942 's': Option<i32> | ||
3043 | "### | ||
3044 | ); | ||
3045 | } | ||
3046 | |||
3047 | #[test] | ||
3048 | fn infer_dyn_fn_output() { | ||
3049 | assert_snapshot!( | ||
3050 | infer( | ||
3051 | r#" | ||
3052 | //- /lib.rs deps:std | ||
3053 | |||
3054 | #[lang = "fn_once"] | ||
3055 | pub trait FnOnce<Args> { | ||
3056 | type Output; | ||
3057 | |||
3058 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ||
3059 | } | ||
3060 | |||
3061 | #[lang = "fn"] | ||
3062 | pub trait Fn<Args>:FnOnce<Args> { | ||
3063 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; | ||
3064 | } | ||
3065 | |||
3066 | #[lang = "deref"] | ||
3067 | pub trait Deref { | ||
3068 | type Target: ?Sized; | ||
3069 | |||
3070 | fn deref(&self) -> &Self::Target; | ||
3071 | } | ||
3072 | |||
3073 | #[lang = "owned_box"] | ||
3074 | pub struct Box<T: ?Sized> { | ||
3075 | inner: *mut T, | ||
3076 | } | ||
3077 | |||
3078 | impl<T: ?Sized> Deref for Box<T> { | ||
3079 | type Target = T; | ||
3080 | |||
3081 | fn deref(&self) -> &T { | ||
3082 | &self.inner | ||
3083 | } | ||
3084 | } | ||
3085 | |||
3086 | fn foo() { | ||
3087 | let f: Box<dyn Fn() -> i32> = box(|| 5); | ||
3088 | let x = f(); | ||
3089 | } | ||
3090 | "# | ||
3091 | ), | ||
3092 | @r###" | ||
3093 | 182..186 'self': Self | ||
3094 | 188..192 'args': Args | ||
3095 | 349..353 'self': &Self | ||
3096 | 355..359 'args': Args | ||
3097 | 523..527 'self': &Self | ||
3098 | 789..793 'self': &Box<T> | ||
3099 | 801..852 '{ ... }': &T | ||
3100 | 823..834 '&self.inner': &*mut T | ||
3101 | 824..828 'self': &Box<T> | ||
3102 | 824..834 'self.inner': *mut T | ||
3103 | 889..990 '{ ... }': () | ||
3104 | 911..912 'f': Box<dyn Fn<(), Output = i32>> | ||
3105 | 937..946 'box(|| 5)': Box<|| -> i32> | ||
3106 | 941..945 '|| 5': || -> i32 | ||
3107 | 944..945 '5': i32 | ||
3108 | 968..969 'x': FnOnce::Output<dyn Fn<(), Output = i32>, ()> | ||
3109 | 972..973 'f': Box<dyn Fn<(), Output = i32>> | ||
3110 | 972..975 'f()': FnOnce::Output<dyn Fn<(), Output = i32>, ()> | ||
3111 | "### | ||
3112 | ); | ||
3113 | } | ||