about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-04-05 16:43:22 +0530
committerManish Goregaokar <manishsmail@gmail.com>2016-04-05 16:43:22 +0530
commit084d9fa94345c72e450184a0a6e4b46ba95285cd (patch)
tree131dbb9cf443c34a38ff490ba02204868a8fb9c2
parent7d63422bb279f2fc430f38fb1d6c90987c86e0bf (diff)
parent1ea98a8b7060579e69c6269cdfb1cc527093d561 (diff)
downloadrust-084d9fa94345c72e450184a0a6e4b46ba95285cd.tar.gz
rust-084d9fa94345c72e450184a0a6e4b46ba95285cd.zip
Rollup merge of #32712 - jonas-schievink:autoderef-fields-for-fn-ty, r=nagisa
Autoderef when suggesting to call `(self.field)`

Fixes #32128
-rw-r--r--src/librustc_typeck/check/method/suggest.rs51
-rw-r--r--src/test/compile-fail/issue-32128.rs25
2 files changed, 58 insertions, 18 deletions
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 4d806bda484..32b5a63817e 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -14,7 +14,7 @@
 use CrateCtxt;
 
 use astconv::AstConv;
-use check::{self, FnCtxt};
+use check::{self, FnCtxt, UnresolvedTypeAction, autoderef};
 use front::map as hir_map;
 use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable};
 use middle::cstore::{self, CrateStore};
@@ -22,6 +22,7 @@ use middle::def::Def;
 use middle::def_id::DefId;
 use middle::lang_items::FnOnceTraitLangItem;
 use rustc::ty::subst::Substs;
+use rustc::ty::LvaluePreference;
 use rustc::traits::{Obligation, SelectionContext};
 use util::nodemap::{FnvHashSet};
 
@@ -50,23 +51,37 @@ fn is_fn_ty<'a, 'tcx>(ty: &Ty<'tcx>, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> bool
             if let Ok(fn_once_trait_did) =
                     cx.lang_items.require(FnOnceTraitLangItem) {
                 let infcx = fcx.infcx();
-                infcx.probe(|_| {
-                    let fn_once_substs =
-                        Substs::new_trait(vec![infcx.next_ty_var()],
-                                          Vec::new(),
-                                          ty);
-                    let trait_ref =
-                      ty::TraitRef::new(fn_once_trait_did,
-                                        cx.mk_substs(fn_once_substs));
-                    let poly_trait_ref = trait_ref.to_poly_trait_ref();
-                    let obligation = Obligation::misc(span,
-                                                      fcx.body_id,
-                                                      poly_trait_ref
-                                                         .to_predicate());
-                    let mut selcx = SelectionContext::new(infcx);
-
-                    return selcx.evaluate_obligation(&obligation)
-                })
+                let (_, _, opt_is_fn) = autoderef(fcx,
+                                                  span,
+                                                  ty,
+                                                  || None,
+                                                  UnresolvedTypeAction::Ignore,
+                                                  LvaluePreference::NoPreference,
+                                                  |ty, _| {
+                    infcx.probe(|_| {
+                        let fn_once_substs =
+                            Substs::new_trait(vec![infcx.next_ty_var()],
+                                              Vec::new(),
+                                              ty);
+                        let trait_ref =
+                          ty::TraitRef::new(fn_once_trait_did,
+                                            cx.mk_substs(fn_once_substs));
+                        let poly_trait_ref = trait_ref.to_poly_trait_ref();
+                        let obligation = Obligation::misc(span,
+                                                          fcx.body_id,
+                                                          poly_trait_ref
+                                                             .to_predicate());
+                        let mut selcx = SelectionContext::new(infcx);
+
+                        if selcx.evaluate_obligation(&obligation) {
+                            Some(())
+                        } else {
+                            None
+                        }
+                    })
+                });
+
+                opt_is_fn.is_some()
             } else {
                 false
             }
diff --git a/src/test/compile-fail/issue-32128.rs b/src/test/compile-fail/issue-32128.rs
new file mode 100644
index 00000000000..fe7e66a2116
--- /dev/null
+++ b/src/test/compile-fail/issue-32128.rs
@@ -0,0 +1,25 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Example {
+    example: Box<Fn(i32) -> i32>
+}
+
+fn main() {
+    let demo = Example {
+        example: Box::new(|x| {
+            x + 1
+        })
+    };
+
+    demo.example(1);    //~ ERROR no method named `example`
+                        //~^ NOTE use `(demo.example)(...)`
+    // (demo.example)(1);
+}