提交 084d9fa9 编写于 作者: M Manish Goregaokar

Rollup merge of #32712 - jonas-schievink:autoderef-fields-for-fn-ty, r=nagisa

Autoderef when suggesting to call `(self.field)`

Fixes #32128
......@@ -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_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
}
......
// 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);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册