Rollup merge of #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.
This commit is contained in:
commit
ea2347843c
@ -2310,13 +2310,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let guar = if field.name == kw::Empty {
|
||||
self.tcx.sess.delay_span_bug(field.span, "field name with no name")
|
||||
} else if self.method_exists(
|
||||
field,
|
||||
base_ty,
|
||||
expr.hir_id,
|
||||
true,
|
||||
expected.only_has_type(self),
|
||||
) {
|
||||
} else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) {
|
||||
self.ban_take_value_of_method(expr, base_ty, field)
|
||||
} else if !base_ty.is_primitive_ty() {
|
||||
self.ban_nonexisting_field(field, base, expr, base_ty)
|
||||
@ -2501,7 +2495,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let mut err = self.private_field_err(field, base_did);
|
||||
|
||||
// Also check if an accessible method exists, which is often what is meant.
|
||||
if self.method_exists(field, expr_t, expr.hir_id, false, return_ty)
|
||||
if self.method_exists(field, expr_t, expr.hir_id, return_ty)
|
||||
&& !self.expr_in_place(expr.hir_id)
|
||||
{
|
||||
self.suggest_method_call(
|
||||
|
@ -89,14 +89,13 @@ pub enum CandidateSource {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// Determines whether the type `self_ty` supports a method name `method_name` or not.
|
||||
/// Determines whether the type `self_ty` supports a visible method named `method_name` or not.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub fn method_exists(
|
||||
&self,
|
||||
method_name: Ident,
|
||||
self_ty: Ty<'tcx>,
|
||||
call_expr_id: hir::HirId,
|
||||
allow_private: bool,
|
||||
return_type: Option<Ty<'tcx>>,
|
||||
) -> bool {
|
||||
match self.probe_for_name(
|
||||
@ -118,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
Err(NoMatch(..)) => false,
|
||||
Err(Ambiguity(..)) => true,
|
||||
Err(PrivateMatch(..)) => allow_private,
|
||||
Err(PrivateMatch(..)) => false,
|
||||
Err(IllegalSizedBound { .. }) => true,
|
||||
Err(BadReturnType) => false,
|
||||
}
|
||||
|
@ -2361,8 +2361,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Some(output_ty) => self.resolve_vars_if_possible(output_ty),
|
||||
_ => return,
|
||||
};
|
||||
let method_exists =
|
||||
self.method_exists(item_name, output_ty, call.hir_id, true, return_type);
|
||||
let method_exists = self.method_exists(item_name, output_ty, call.hir_id, return_type);
|
||||
debug!("suggest_await_before_method: is_method_exist={}", method_exists);
|
||||
if method_exists {
|
||||
err.span_suggestion_verbose(
|
||||
|
16
tests/ui/error-codes/E0609-private-method.rs
Normal file
16
tests/ui/error-codes/E0609-private-method.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// This error is an E0609 and *not* an E0615 because the fact that the method exists is not
|
||||
// relevant.
|
||||
mod foo {
|
||||
pub struct Foo {
|
||||
x: u32,
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
fn method(&self) {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let f = foo::Foo { x: 0 };
|
||||
f.method; //~ ERROR E0609
|
||||
}
|
9
tests/ui/error-codes/E0609-private-method.stderr
Normal file
9
tests/ui/error-codes/E0609-private-method.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0609]: no field `method` on type `Foo`
|
||||
--> $DIR/E0609-private-method.rs:15:7
|
||||
|
|
||||
LL | f.method;
|
||||
| ^^^^^^ unknown field
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0609`.
|
Loading…
x
Reference in New Issue
Block a user