Skip to content

Commit 973da22

Browse files
committed
Wrapped inferred context changes in a probe, handle fnOnce trait require error with a fallback, renamed variable to something clearer
1 parent c8a0b0e commit 973da22

File tree

1 file changed

+36
-27
lines changed

1 file changed

+36
-27
lines changed

src/librustc_typeck/check/method/suggest.rs

+36-27
Original file line numberDiff line numberDiff line change
@@ -73,40 +73,49 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
7373
// snippet
7474
};
7575

76-
fn span_stored_function() {
77-
cx.sess.span_note(span, &format!("use `({0}.{1})(...)` if you meant to call \
78-
the function stored in the `{1}` field",
79-
expr_string, item_name));
80-
}
76+
macro_rules! span_stored_function {
77+
() => {
78+
cx.sess.span_note(span,
79+
&format!("use `({0}.{1})(...)` if you meant to call \
80+
the function stored in the `{1}` field",
81+
expr_string, item_name));
82+
}
83+
};
8184

82-
fn span_did_you_mean() {
83-
cx.sess.span_note(span, &format!("did you mean to write `{0}.{1}`?",
84-
expr_string, item_name));
85-
}
85+
macro_rules! span_did_you_mean {
86+
() => {
87+
cx.sess.span_note(span, &format!("did you mean to write `{0}.{1}`?",
88+
expr_string, item_name));
89+
}
90+
};
8691

8792
// Determine if the field can be used as a function in some way
8893
let field_ty = ty::lookup_field_type(cx, did, field.id, substs);
8994
if let Ok(fn_once_trait_did) = cx.lang_items.require(FnOnceTraitLangItem) {
90-
let fn_once_substs = Substs::new_trait(vec![fcx.inh.infcx.next_ty_var()],
91-
Vec::new(),
92-
field_ty);
93-
let trait_ref = ty::TraitRef::new(fn_once_trait_did,
94-
cx.mk_substs(fn_once_substs));
95-
let poly_trait_ref = trait_ref.to_poly_trait_ref();
96-
let obligation = Obligation::misc(span,
97-
fcx.body_id,
98-
poly_trait_ref.as_predicate());
99-
let mut selcx = SelectionContext::new(fcx.infcx(), fcx);
100-
101-
if selcx.evaluate_obligation(&obligation) {
102-
span_stored_function();
103-
} else {
104-
span_did_you_mean();
105-
}
95+
let infcx = fcx.infcx();
96+
infcx.probe(|_| {
97+
let fn_once_substs = Substs::new_trait(vec![infcx.next_ty_var()],
98+
Vec::new(),
99+
field_ty);
100+
let trait_ref = ty::TraitRef::new(fn_once_trait_did,
101+
cx.mk_substs(fn_once_substs));
102+
let poly_trait_ref = trait_ref.to_poly_trait_ref();
103+
let obligation = Obligation::misc(span,
104+
fcx.body_id,
105+
poly_trait_ref.as_predicate());
106+
let mut selcx = SelectionContext::new(infcx, fcx);
107+
108+
if selcx.evaluate_obligation(&obligation) {
109+
span_stored_function!();
110+
} else {
111+
span_did_you_mean!();
112+
}
113+
});
106114
} else {
107115
match field_ty.sty {
108-
ty::TyClosure(_,_) | ty::TyFnPtr(_,_) => span_stored_function(),
109-
_ => span_did_you_mean(),
116+
// fallback to matching a closure or function pointer
117+
ty::TyClosure(_,_) | ty::TyBareFn(None,_) => span_stored_function!(),
118+
_ => span_did_you_mean!(),
110119
}
111120
}
112121
}

0 commit comments

Comments
 (0)