@@ -33,25 +33,17 @@ use self::CandidateKind::*;
33
33
pub use self :: PickKind :: * ;
34
34
35
35
pub enum LookingFor < ' tcx > {
36
+ /// looking for methods with the given name; this is the normal case
36
37
MethodName ( ast:: Name ) ,
38
+
39
+ /// looking for methods that return a given type; this is used to
40
+ /// assemble suggestions
37
41
ReturnType ( Ty < ' tcx > ) ,
38
42
}
39
43
40
- impl < ' tcx > LookingFor < ' tcx > {
41
- pub fn is_method_name ( & self ) -> bool {
42
- match * self {
43
- LookingFor :: MethodName ( _) => true ,
44
- _ => false ,
45
- }
46
- }
47
-
48
- pub fn is_return_type ( & self ) -> bool {
49
- match * self {
50
- LookingFor :: ReturnType ( _) => true ,
51
- _ => false ,
52
- }
53
- }
54
- }
44
+ /// Boolean flag used to indicate if this search is for a suggestion
45
+ /// or not. If true, we can allow ambiguity and so forth.
46
+ pub struct IsSuggestion ( pub bool ) ;
55
47
56
48
struct ProbeContext < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
57
49
fcx : & ' a FnCtxt < ' a , ' gcx , ' tcx > ,
@@ -183,13 +175,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
183
175
return_type,
184
176
scope_expr_id) ;
185
177
let method_names =
186
- self . probe_op ( span, mode, LookingFor :: ReturnType ( return_type) , self_ty, scope_expr_id,
178
+ self . probe_op ( span, mode, LookingFor :: ReturnType ( return_type) , IsSuggestion ( true ) ,
179
+ self_ty, scope_expr_id,
187
180
|probe_cx| Ok ( probe_cx. candidate_method_names ( ) ) )
188
181
. unwrap_or ( vec ! [ ] ) ;
189
182
method_names
190
183
. iter ( )
191
184
. flat_map ( |& method_name| {
192
- match self . probe_for_name ( span, mode, method_name, self_ty, scope_expr_id) {
185
+ match self . probe_for_name ( span, mode, method_name, IsSuggestion ( true ) , self_ty, scope_expr_id) {
193
186
Ok ( pick) => Some ( pick. item ) ,
194
187
Err ( _) => None ,
195
188
}
@@ -201,6 +194,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
201
194
span : Span ,
202
195
mode : Mode ,
203
196
item_name : ast:: Name ,
197
+ is_suggestion : IsSuggestion ,
204
198
self_ty : Ty < ' tcx > ,
205
199
scope_expr_id : ast:: NodeId )
206
200
-> PickResult < ' tcx > {
@@ -211,6 +205,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
211
205
self . probe_op ( span,
212
206
mode,
213
207
LookingFor :: MethodName ( item_name) ,
208
+ is_suggestion,
214
209
self_ty,
215
210
scope_expr_id,
216
211
|probe_cx| probe_cx. pick ( ) )
@@ -220,6 +215,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
220
215
span : Span ,
221
216
mode : Mode ,
222
217
looking_for : LookingFor < ' tcx > ,
218
+ is_suggestion : IsSuggestion ,
223
219
self_ty : Ty < ' tcx > ,
224
220
scope_expr_id : ast:: NodeId ,
225
221
op : OP )
@@ -234,7 +230,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
234
230
// think cause spurious errors. Really though this part should
235
231
// take place in the `self.probe` below.
236
232
let steps = if mode == Mode :: MethodCall {
237
- match self . create_steps ( span, self_ty) {
233
+ match self . create_steps ( span, self_ty, is_suggestion ) {
238
234
Some ( steps) => steps,
239
235
None => {
240
236
return Err ( MethodError :: NoMatch ( NoMatchData :: new ( Vec :: new ( ) ,
@@ -287,7 +283,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
287
283
288
284
fn create_steps ( & self ,
289
285
span : Span ,
290
- self_ty : Ty < ' tcx > )
286
+ self_ty : Ty < ' tcx > ,
287
+ is_suggestion : IsSuggestion )
291
288
-> Option < Vec < CandidateStep < ' tcx > > > {
292
289
// FIXME: we don't need to create the entire steps in one pass
293
290
@@ -302,8 +299,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
302
299
} )
303
300
. collect ( ) ;
304
301
305
- let final_ty = autoderef. unambiguous_final_ty ( ) ;
302
+ let final_ty = autoderef. maybe_ambiguous_final_ty ( ) ;
306
303
match final_ty. sty {
304
+ ty:: TyInfer ( ty:: TyVar ( _) ) => {
305
+ // Ended in an inference variable. If we are doing
306
+ // a real method lookup, this is a hard error (it's an
307
+ // ambiguity and we can't make progress).
308
+ if !is_suggestion. 0 {
309
+ let t = self . structurally_resolved_type ( span, final_ty) ;
310
+ assert_eq ! ( t, self . tcx. types. err) ;
311
+ return None
312
+ } else {
313
+ // If we're just looking for suggestions,
314
+ // though, ambiguity is no big thing, we can
315
+ // just ignore it.
316
+ }
317
+ }
307
318
ty:: TyArray ( elem_ty, _) => {
308
319
let dereferences = steps. len ( ) - 1 ;
309
320
0 commit comments