Skip to content

Commit 4f5edf9

Browse files
committed
Auto merge of #29827 - Manishearth:diag-fn-field, r=eddyb
Fixes #29043
2 parents 968e8bf + 2b3117c commit 4f5edf9

File tree

2 files changed

+54
-23
lines changed

2 files changed

+54
-23
lines changed

src/librustc_typeck/check/method/suggest.rs

+31-23
Original file line numberDiff line numberDiff line change
@@ -92,31 +92,39 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
9292

9393
// Determine if the field can be used as a function in some way
9494
let field_ty = field.ty(cx, substs);
95-
if let Ok(fn_once_trait_did) = cx.lang_items.require(FnOnceTraitLangItem) {
96-
let infcx = fcx.infcx();
97-
infcx.probe(|_| {
98-
let fn_once_substs = Substs::new_trait(vec![infcx.next_ty_var()],
99-
Vec::new(),
100-
field_ty);
101-
let trait_ref = ty::TraitRef::new(fn_once_trait_did,
102-
cx.mk_substs(fn_once_substs));
103-
let poly_trait_ref = trait_ref.to_poly_trait_ref();
104-
let obligation = Obligation::misc(span,
105-
fcx.body_id,
106-
poly_trait_ref.to_predicate());
107-
let mut selcx = SelectionContext::new(infcx);
108-
109-
if selcx.evaluate_obligation(&obligation) {
110-
span_stored_function();
95+
96+
match field_ty.sty {
97+
// Not all of these (e.g. unsafe fns) implement FnOnce
98+
// so we look for these beforehand
99+
ty::TyClosure(..) | ty::TyBareFn(..) => span_stored_function(),
100+
// If it's not a simple function, look for things which implement FnOnce
101+
_ => {
102+
if let Ok(fn_once_trait_did) =
103+
cx.lang_items.require(FnOnceTraitLangItem) {
104+
let infcx = fcx.infcx();
105+
infcx.probe(|_| {
106+
let fn_once_substs = Substs::new_trait(vec![
107+
infcx.next_ty_var()],
108+
Vec::new(),
109+
field_ty);
110+
let trait_ref = ty::TraitRef::new(fn_once_trait_did,
111+
cx.mk_substs(fn_once_substs));
112+
let poly_trait_ref = trait_ref.to_poly_trait_ref();
113+
let obligation = Obligation::misc(span,
114+
fcx.body_id,
115+
poly_trait_ref
116+
.to_predicate());
117+
let mut selcx = SelectionContext::new(infcx);
118+
119+
if selcx.evaluate_obligation(&obligation) {
120+
span_stored_function();
121+
} else {
122+
span_did_you_mean();
123+
}
124+
});
111125
} else {
112-
span_did_you_mean();
126+
span_did_you_mean()
113127
}
114-
});
115-
} else {
116-
match field_ty.sty {
117-
// fallback to matching a closure or function pointer
118-
ty::TyClosure(..) | ty::TyBareFn(..) => span_stored_function(),
119-
_ => span_did_you_mean(),
120128
}
121129
}
122130
}

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

+23
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@
1111
#![feature(core)]
1212
use std::boxed::FnBox;
1313

14+
struct FuncContainer {
15+
f1: fn(data: u8),
16+
f2: extern "C" fn(data: u8),
17+
f3: unsafe fn(data: u8),
18+
}
19+
20+
struct FuncContainerOuter {
21+
container: Box<FuncContainer>
22+
}
23+
1424
struct Obj<F> where F: FnOnce() -> u32 {
1525
closure: F,
1626
not_closure: usize,
@@ -66,3 +76,16 @@ fn main() {
6676
check_expression().closure();//~ ERROR no method named `closure` found
6777
//~^ NOTE use `(check_expression().closure)(...)` if you meant to call the function stored
6878
}
79+
80+
impl FuncContainerOuter {
81+
fn run(&self) {
82+
unsafe {
83+
(*self.container).f1(1); //~ ERROR no method named `f1` found
84+
//~^ NOTE use `(*self.container.f1)(...)`
85+
(*self.container).f2(1); //~ ERROR no method named `f2` found
86+
//~^ NOTE use `(*self.container.f2)(...)`
87+
(*self.container).f3(1); //~ ERROR no method named `f3` found
88+
//~^ NOTE use `(*self.container.f3)(...)`
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)