Skip to content

Commit ea23478

Browse files
authored
Rollup merge of rust-lang#115363 - kpreid:suggest-private, r=compiler-errors
Don't suggest adding parentheses to call an inaccessible method. Previously, code of this form would emit E0615 (attempt to use a method as a field), thus emphasizing the existence of private methods that the programmer probably does not care about. Now it ignores their existence instead, producing error E0609 (no field). The motivating example is: ```rust let x = std::rc::Rc::new(()); x.inner; ``` which would previously mention the private method `Rc::inner()`, even though `Rc<T>` intentionally has no public methods so that it can be a transparent smart pointer for any `T`. ```rust error[E0615]: attempted to take value of method `inner` on type `Rc<()>` --> src/main.rs:3:3 | 3 | x.inner; | ^^^^^ method, not a field | help: use parentheses to call the method | 3 | x.inner(); | ++ ``` With this change, it emits E0609 and no suggestion.
2 parents 36182f1 + 4e9a2a6 commit ea23478

File tree

5 files changed

+30
-13
lines changed

5 files changed

+30
-13
lines changed

compiler/rustc_hir_typeck/src/expr.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -2310,13 +2310,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23102310

23112311
let guar = if field.name == kw::Empty {
23122312
self.tcx.sess.delay_span_bug(field.span, "field name with no name")
2313-
} else if self.method_exists(
2314-
field,
2315-
base_ty,
2316-
expr.hir_id,
2317-
true,
2318-
expected.only_has_type(self),
2319-
) {
2313+
} else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) {
23202314
self.ban_take_value_of_method(expr, base_ty, field)
23212315
} else if !base_ty.is_primitive_ty() {
23222316
self.ban_nonexisting_field(field, base, expr, base_ty)
@@ -2501,7 +2495,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25012495
let mut err = self.private_field_err(field, base_did);
25022496

25032497
// Also check if an accessible method exists, which is often what is meant.
2504-
if self.method_exists(field, expr_t, expr.hir_id, false, return_ty)
2498+
if self.method_exists(field, expr_t, expr.hir_id, return_ty)
25052499
&& !self.expr_in_place(expr.hir_id)
25062500
{
25072501
self.suggest_method_call(

compiler/rustc_hir_typeck/src/method/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,13 @@ pub enum CandidateSource {
8989
}
9090

9191
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
92-
/// Determines whether the type `self_ty` supports a method name `method_name` or not.
92+
/// Determines whether the type `self_ty` supports a visible method named `method_name` or not.
9393
#[instrument(level = "debug", skip(self))]
9494
pub fn method_exists(
9595
&self,
9696
method_name: Ident,
9797
self_ty: Ty<'tcx>,
9898
call_expr_id: hir::HirId,
99-
allow_private: bool,
10099
return_type: Option<Ty<'tcx>>,
101100
) -> bool {
102101
match self.probe_for_name(
@@ -118,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
118117
}
119118
Err(NoMatch(..)) => false,
120119
Err(Ambiguity(..)) => true,
121-
Err(PrivateMatch(..)) => allow_private,
120+
Err(PrivateMatch(..)) => false,
122121
Err(IllegalSizedBound { .. }) => true,
123122
Err(BadReturnType) => false,
124123
}

compiler/rustc_hir_typeck/src/method/suggest.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2361,8 +2361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23612361
Some(output_ty) => self.resolve_vars_if_possible(output_ty),
23622362
_ => return,
23632363
};
2364-
let method_exists =
2365-
self.method_exists(item_name, output_ty, call.hir_id, true, return_type);
2364+
let method_exists = self.method_exists(item_name, output_ty, call.hir_id, return_type);
23662365
debug!("suggest_await_before_method: is_method_exist={}", method_exists);
23672366
if method_exists {
23682367
err.span_suggestion_verbose(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// This error is an E0609 and *not* an E0615 because the fact that the method exists is not
2+
// relevant.
3+
mod foo {
4+
pub struct Foo {
5+
x: u32,
6+
}
7+
8+
impl Foo {
9+
fn method(&self) {}
10+
}
11+
}
12+
13+
fn main() {
14+
let f = foo::Foo { x: 0 };
15+
f.method; //~ ERROR E0609
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0609]: no field `method` on type `Foo`
2+
--> $DIR/E0609-private-method.rs:15:7
3+
|
4+
LL | f.method;
5+
| ^^^^^^ unknown field
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0609`.

0 commit comments

Comments
 (0)