Skip to content

Commit 084d9fa

Browse files
committed
Rollup merge of rust-lang#32712 - jonas-schievink:autoderef-fields-for-fn-ty, r=nagisa
Autoderef when suggesting to call `(self.field)` Fixes rust-lang#32128
2 parents 7d63422 + 1ea98a8 commit 084d9fa

File tree

2 files changed

+58
-18
lines changed

2 files changed

+58
-18
lines changed

src/librustc_typeck/check/method/suggest.rs

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
use CrateCtxt;
1515

1616
use astconv::AstConv;
17-
use check::{self, FnCtxt};
17+
use check::{self, FnCtxt, UnresolvedTypeAction, autoderef};
1818
use front::map as hir_map;
1919
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable};
2020
use middle::cstore::{self, CrateStore};
2121
use middle::def::Def;
2222
use middle::def_id::DefId;
2323
use middle::lang_items::FnOnceTraitLangItem;
2424
use rustc::ty::subst::Substs;
25+
use rustc::ty::LvaluePreference;
2526
use rustc::traits::{Obligation, SelectionContext};
2627
use util::nodemap::{FnvHashSet};
2728

@@ -50,23 +51,37 @@ fn is_fn_ty<'a, 'tcx>(ty: &Ty<'tcx>, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> bool
5051
if let Ok(fn_once_trait_did) =
5152
cx.lang_items.require(FnOnceTraitLangItem) {
5253
let infcx = fcx.infcx();
53-
infcx.probe(|_| {
54-
let fn_once_substs =
55-
Substs::new_trait(vec![infcx.next_ty_var()],
56-
Vec::new(),
57-
ty);
58-
let trait_ref =
59-
ty::TraitRef::new(fn_once_trait_did,
60-
cx.mk_substs(fn_once_substs));
61-
let poly_trait_ref = trait_ref.to_poly_trait_ref();
62-
let obligation = Obligation::misc(span,
63-
fcx.body_id,
64-
poly_trait_ref
65-
.to_predicate());
66-
let mut selcx = SelectionContext::new(infcx);
67-
68-
return selcx.evaluate_obligation(&obligation)
69-
})
54+
let (_, _, opt_is_fn) = autoderef(fcx,
55+
span,
56+
ty,
57+
|| None,
58+
UnresolvedTypeAction::Ignore,
59+
LvaluePreference::NoPreference,
60+
|ty, _| {
61+
infcx.probe(|_| {
62+
let fn_once_substs =
63+
Substs::new_trait(vec![infcx.next_ty_var()],
64+
Vec::new(),
65+
ty);
66+
let trait_ref =
67+
ty::TraitRef::new(fn_once_trait_did,
68+
cx.mk_substs(fn_once_substs));
69+
let poly_trait_ref = trait_ref.to_poly_trait_ref();
70+
let obligation = Obligation::misc(span,
71+
fcx.body_id,
72+
poly_trait_ref
73+
.to_predicate());
74+
let mut selcx = SelectionContext::new(infcx);
75+
76+
if selcx.evaluate_obligation(&obligation) {
77+
Some(())
78+
} else {
79+
None
80+
}
81+
})
82+
});
83+
84+
opt_is_fn.is_some()
7085
} else {
7186
false
7287
}

src/test/compile-fail/issue-32128.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Example {
12+
example: Box<Fn(i32) -> i32>
13+
}
14+
15+
fn main() {
16+
let demo = Example {
17+
example: Box::new(|x| {
18+
x + 1
19+
})
20+
};
21+
22+
demo.example(1); //~ ERROR no method named `example`
23+
//~^ NOTE use `(demo.example)(...)`
24+
// (demo.example)(1);
25+
}

0 commit comments

Comments
 (0)