@@ -5,10 +5,14 @@ use crate::{
5
5
navigation_target:: { self , ToNav } ,
6
6
FilePosition , NavigationTarget , RangeInfo , TryToNav , UpmappingResult ,
7
7
} ;
8
- use hir:: { AsAssocItem , AssocItem , FileRange , InFile , MacroFileIdExt , ModuleDef , Semantics } ;
8
+ use hir:: {
9
+ sym, AsAssocItem , AssocItem , CallableKind , FileRange , HasCrate , InFile , MacroFileIdExt ,
10
+ ModuleDef , Semantics ,
11
+ } ;
9
12
use ide_db:: {
10
13
base_db:: { AnchoredPath , FileLoader , SourceDatabase } ,
11
14
defs:: { Definition , IdentClass } ,
15
+ famous_defs:: FamousDefs ,
12
16
helpers:: pick_best_token,
13
17
RootDatabase , SymbolKind ,
14
18
} ;
@@ -129,15 +133,45 @@ pub(crate) fn goto_definition(
129
133
Some ( RangeInfo :: new ( original_token. text_range ( ) , navs) )
130
134
}
131
135
132
- // If the token is into(), try_into(), parse(), search the definition of From, TryFrom, FromStr .
136
+ // If the token is into(), try_into(), search the definition of From, TryFrom.
133
137
fn find_definition_for_known_blanket_dual_impls (
134
138
sema : & Semantics < ' _ , RootDatabase > ,
135
139
original_token : & SyntaxToken ,
136
140
) -> Option < Vec < NavigationTarget > > {
137
141
let method_call = ast:: MethodCallExpr :: cast ( original_token. parent ( ) ?. parent ( ) ?) ?;
138
- let target_method = sema. resolve_known_blanket_dual_impls ( & method_call) ?;
139
-
140
- let def = Definition :: from ( target_method) ;
142
+ let callable = sema. resolve_method_call_as_callable ( & method_call) ?;
143
+ let CallableKind :: Function ( f) = callable. kind ( ) else { return None } ;
144
+ let t = f. as_assoc_item ( sema. db ) ?. container_trait ( sema. db ) ?;
145
+
146
+ let return_type = callable. return_type ( ) ;
147
+ let fd = FamousDefs ( sema, return_type. krate ( sema. db ) ) ;
148
+ let fn_name = f. name ( sema. db ) ;
149
+ let f = if fn_name == sym:: into && fd. core_convert_Into ( ) == Some ( t) {
150
+ let dual = fd. core_convert_From ( ) ?;
151
+ let dual_f = dual. function ( sema. db , & sym:: from) ?;
152
+ sema. resolve_impl_method (
153
+ return_type. clone ( ) ,
154
+ dual,
155
+ dual_f,
156
+ [ return_type, callable. receiver_param ( sema. db ) ?. 1 ] ,
157
+ ) ?
158
+ } else if fn_name == sym:: try_into && fd. core_convert_TryInto ( ) == Some ( t) {
159
+ let dual = fd. core_convert_TryFrom ( ) ?;
160
+ let dual_f = dual. function ( sema. db , & sym:: try_from) ?;
161
+ sema. resolve_impl_method (
162
+ return_type. clone ( ) ,
163
+ dual,
164
+ dual_f,
165
+ // Extract the `T` from `Result<T, ..>`
166
+ [ return_type. type_arguments ( ) . next ( ) ?, callable. receiver_param ( sema. db ) ?. 1 ] ,
167
+ ) ?
168
+ } else {
169
+ return None ;
170
+ } ;
171
+ // Assert that we got a trait impl function, if we are back in a trait definition we didn't
172
+ // succeed
173
+ let _t = f. as_assoc_item ( sema. db ) ?. implemented_trait ( sema. db ) ?;
174
+ let def = Definition :: from ( f) ;
141
175
Some ( def_to_nav ( sema. db , def) )
142
176
}
143
177
@@ -3157,29 +3191,6 @@ impl TryInto<B> for A {
3157
3191
fn f() {
3158
3192
let a = A;
3159
3193
let b: Result<B, _> = a.try_into$0();
3160
- }
3161
- "# ,
3162
- ) ;
3163
- }
3164
-
3165
- #[ test]
3166
- fn parse_call_to_from_str_definition ( ) {
3167
- check (
3168
- r#"
3169
- //- minicore: from, str
3170
- struct A;
3171
-
3172
- impl FromStr for A {
3173
- type Error = String;
3174
-
3175
- fn from_str(value: &str) -> Result<Self, Self::Error> {
3176
- //^^^^^^^^
3177
- Ok(A)
3178
- }
3179
- }
3180
-
3181
- fn f() {
3182
- let a: Result<A, _> = "aaaaaa".parse$0();
3183
3194
}
3184
3195
"# ,
3185
3196
) ;
0 commit comments