Skip to content

Commit 487de42

Browse files
committed
Auto merge of #33615 - GuillaumeGomez:field_static_method, r=pnkfelix
Don't suggest using fields in a static method Fixes #33613. cc @LeoTestard
2 parents 8393d99 + 145747e commit 487de42

File tree

3 files changed

+93
-24
lines changed

3 files changed

+93
-24
lines changed

src/librustc_resolve/lib.rs

+64-22
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
6767
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
6868
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
6969
use syntax::ast::{Local, Pat, PatKind, Path};
70-
use syntax::ast::{PathSegment, PathParameters, TraitItemKind, TraitRef, Ty, TyKind};
70+
use syntax::ast::{PathSegment, PathParameters, SelfKind, TraitItemKind, TraitRef, Ty, TyKind};
7171

7272
use std::collections::{HashMap, HashSet};
7373
use std::cell::{Cell, RefCell};
@@ -148,7 +148,13 @@ enum ResolutionError<'a> {
148148
/// error E0424: `self` is not available in a static method
149149
SelfNotAvailableInStaticMethod,
150150
/// error E0425: unresolved name
151-
UnresolvedName(&'a str, &'a str, UnresolvedNameContext<'a>),
151+
UnresolvedName {
152+
path: &'a str,
153+
message: &'a str,
154+
context: UnresolvedNameContext<'a>,
155+
is_static_method: bool,
156+
is_field: bool
157+
},
152158
/// error E0426: use of undeclared label
153159
UndeclaredLabel(&'a str),
154160
/// error E0427: cannot use `ref` binding mode with ...
@@ -406,16 +412,21 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
406412
"`self` is not available in a static method. Maybe a `self` \
407413
argument is missing?")
408414
}
409-
ResolutionError::UnresolvedName(path, msg, context) => {
415+
ResolutionError::UnresolvedName { path, message: msg, context, is_static_method,
416+
is_field } => {
410417
let mut err = struct_span_err!(resolver.session,
411418
span,
412419
E0425,
413420
"unresolved name `{}`{}",
414421
path,
415422
msg);
416-
417423
match context {
418-
UnresolvedNameContext::Other => { } // no help available
424+
UnresolvedNameContext::Other => {
425+
if msg.is_empty() && is_static_method && is_field {
426+
err.help("this is an associated function, you don't have access to \
427+
this type's fields or methods");
428+
}
429+
}
419430
UnresolvedNameContext::PathIsMod(parent) => {
420431
err.help(&match parent.map(|parent| &parent.node) {
421432
Some(&ExprKind::Field(_, ident)) => {
@@ -596,7 +607,7 @@ impl<'a, 'v> Visitor<'v> for Resolver<'a> {
596607
}
597608
FnKind::Method(_, sig, _) => {
598609
self.visit_generics(&sig.generics);
599-
MethodRibKind
610+
MethodRibKind(sig.explicit_self.node == SelfKind::Static)
600611
}
601612
FnKind::Closure => ClosureRibKind(node_id),
602613
};
@@ -666,7 +677,9 @@ enum RibKind<'a> {
666677
// methods. Allow references to ty params that impl or trait
667678
// binds. Disallow any other upvars (including other ty params that are
668679
// upvars).
669-
MethodRibKind,
680+
//
681+
// The boolean value represents the fact that this method is static or not.
682+
MethodRibKind(bool),
670683

671684
// We passed through an item scope. Disallow upvars.
672685
ItemRibKind,
@@ -1095,7 +1108,13 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
10951108
Err(false) => {
10961109
let path_name = &format!("{}", path);
10971110
let error =
1098-
ResolutionError::UnresolvedName(path_name, "", UnresolvedNameContext::Other);
1111+
ResolutionError::UnresolvedName {
1112+
path: path_name,
1113+
message: "",
1114+
context: UnresolvedNameContext::Other,
1115+
is_static_method: false,
1116+
is_field: false
1117+
};
10991118
resolve_error(self, path.span, error);
11001119
Def::Err
11011120
}
@@ -1657,7 +1676,9 @@ impl<'a> Resolver<'a> {
16571676
let type_parameters =
16581677
HasTypeParameters(&sig.generics,
16591678
FnSpace,
1660-
MethodRibKind);
1679+
MethodRibKind(
1680+
sig.explicit_self.node ==
1681+
SelfKind::Static));
16611682
this.with_type_parameter_rib(type_parameters, |this| {
16621683
visit::walk_trait_item(this, trait_item)
16631684
});
@@ -1776,7 +1797,10 @@ impl<'a> Resolver<'a> {
17761797
self.value_ribs.pop();
17771798
}
17781799

1779-
fn resolve_function(&mut self, rib_kind: RibKind<'a>, declaration: &FnDecl, block: &Block) {
1800+
fn resolve_function(&mut self,
1801+
rib_kind: RibKind<'a>,
1802+
declaration: &FnDecl,
1803+
block: &Block) {
17801804
// Create a value rib for the function.
17811805
self.value_ribs.push(Rib::new(rib_kind));
17821806

@@ -1983,7 +2007,9 @@ impl<'a> Resolver<'a> {
19832007
let type_parameters =
19842008
HasTypeParameters(&sig.generics,
19852009
FnSpace,
1986-
MethodRibKind);
2010+
MethodRibKind(
2011+
sig.explicit_self.node ==
2012+
SelfKind::Static));
19872013
this.with_type_parameter_rib(type_parameters, |this| {
19882014
visit::walk_impl_item(this, impl_item);
19892015
});
@@ -2677,7 +2703,7 @@ impl<'a> Resolver<'a> {
26772703
def = Def::Upvar(node_def_id, node_id, depth, function_id);
26782704
seen.insert(node_id, depth);
26792705
}
2680-
ItemRibKind | MethodRibKind => {
2706+
ItemRibKind | MethodRibKind(_) => {
26812707
// This was an attempt to access an upvar inside a
26822708
// named function item. This is not allowed, so we
26832709
// report an error.
@@ -2699,7 +2725,7 @@ impl<'a> Resolver<'a> {
26992725
Def::TyParam(..) | Def::SelfTy(..) => {
27002726
for rib in ribs {
27012727
match rib.kind {
2702-
NormalRibKind | MethodRibKind | ClosureRibKind(..) |
2728+
NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
27032729
ModuleRibKind(..) => {
27042730
// Nothing to do. Continue.
27052731
}
@@ -2992,9 +3018,13 @@ impl<'a> Resolver<'a> {
29923018
// `resolve_path` already reported the error
29933019
} else {
29943020
let mut method_scope = false;
3021+
let mut is_static = false;
29953022
self.value_ribs.iter().rev().all(|rib| {
29963023
method_scope = match rib.kind {
2997-
MethodRibKind => true,
3024+
MethodRibKind(is_static_) => {
3025+
is_static = is_static_;
3026+
true
3027+
}
29983028
ItemRibKind | ConstantItemRibKind => false,
29993029
_ => return true, // Keep advancing
30003030
};
@@ -3008,22 +3038,29 @@ impl<'a> Resolver<'a> {
30083038
ResolutionError::SelfNotAvailableInStaticMethod);
30093039
} else {
30103040
let last_name = path.segments.last().unwrap().identifier.name;
3011-
let mut msg = match self.find_fallback_in_self_type(last_name) {
3041+
let (mut msg, is_field) =
3042+
match self.find_fallback_in_self_type(last_name) {
30123043
NoSuggestion => {
30133044
// limit search to 5 to reduce the number
30143045
// of stupid suggestions
3015-
match self.find_best_match(&path_name) {
3046+
(match self.find_best_match(&path_name) {
30163047
SuggestionType::Macro(s) => {
30173048
format!("the macro `{}`", s)
30183049
}
30193050
SuggestionType::Function(s) => format!("`{}`", s),
30203051
SuggestionType::NotFound => "".to_string(),
3021-
}
3052+
}, false)
3053+
}
3054+
Field => {
3055+
(if is_static && method_scope {
3056+
"".to_string()
3057+
} else {
3058+
format!("`self.{}`", path_name)
3059+
}, true)
30223060
}
3023-
Field => format!("`self.{}`", path_name),
3024-
TraitItem => format!("to call `self.{}`", path_name),
3061+
TraitItem => (format!("to call `self.{}`", path_name), false),
30253062
TraitMethod(path_str) =>
3026-
format!("to call `{}::{}`", path_str, path_name),
3063+
(format!("to call `{}::{}`", path_str, path_name), false),
30273064
};
30283065

30293066
let mut context = UnresolvedNameContext::Other;
@@ -3048,8 +3085,13 @@ impl<'a> Resolver<'a> {
30483085

30493086
resolve_error(self,
30503087
expr.span,
3051-
ResolutionError::UnresolvedName(
3052-
&path_name, &msg, context));
3088+
ResolutionError::UnresolvedName {
3089+
path: &path_name,
3090+
message: &msg,
3091+
context: context,
3092+
is_static_method: method_scope && is_static,
3093+
is_field: is_field,
3094+
});
30533095
}
30543096
}
30553097
}

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ impl MaybeDog {
3232
impl Groom for cat {
3333
fn shave(other: usize) {
3434
whiskers -= other;
35-
//~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`?
35+
//~^ ERROR: unresolved name `whiskers`
36+
//~| HELP this is an associated function
3637
shave(4);
3738
//~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`?
3839
purr();
@@ -77,7 +78,8 @@ impl cat {
7778

7879
pub fn grow_older(other:usize) {
7980
whiskers = 4;
80-
//~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`?
81+
//~^ ERROR: unresolved name `whiskers`
82+
//~| HELP this is an associated function
8183
purr_louder();
8284
//~^ ERROR: unresolved name `purr_louder`
8385
}
@@ -86,5 +88,6 @@ impl cat {
8688
fn main() {
8789
self += 1;
8890
//~^ ERROR: unresolved name `self`
91+
//~| HELP: Module
8992
// it's a bug if this suggests a missing `self` as we're not in a method
9093
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
fn f(_: bool) {}
12+
13+
struct Foo {
14+
cx: bool,
15+
}
16+
17+
impl Foo {
18+
fn bar() {
19+
f(cx); //~ ERROR E0425
20+
//~| HELP this is an associated function
21+
}
22+
}
23+
24+
fn main() {}

0 commit comments

Comments
 (0)