Skip to content

Commit 62d8334

Browse files
authored
Rollup merge of rust-lang#59267 - estebank:assoc-const-as-field, r=davidtwco
Provide suggestion when using field access instead of path When trying to access an associated constant as if it were a field of an instance, provide a suggestion for the correct syntax. Fix rust-lang#57316.
2 parents 28dc8ba + 4beea17 commit 62d8334

File tree

4 files changed

+66
-55
lines changed

4 files changed

+66
-55
lines changed

src/librustc_resolve/error_reporting.rs

+41-54
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use log::debug;
55
use rustc::hir::def::{Def, CtorKind, Namespace::*};
66
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
77
use rustc::session::config::nightly_options;
8-
use syntax::ast::{ExprKind};
8+
use syntax::ast::{Expr, ExprKind};
99
use syntax::symbol::keywords;
1010
use syntax_pos::Span;
1111

@@ -250,6 +250,29 @@ impl<'a> Resolver<'a> {
250250
let ns = source.namespace();
251251
let is_expected = &|def| source.is_expected(def);
252252

253+
let path_sep = |err: &mut DiagnosticBuilder<'_>, expr: &Expr| match expr.node {
254+
ExprKind::Field(_, ident) => {
255+
err.span_suggestion(
256+
expr.span,
257+
"use the path separator to refer to an item",
258+
format!("{}::{}", path_str, ident),
259+
Applicability::MaybeIncorrect,
260+
);
261+
true
262+
}
263+
ExprKind::MethodCall(ref segment, ..) => {
264+
let span = expr.span.with_hi(segment.ident.span.hi());
265+
err.span_suggestion(
266+
span,
267+
"use the path separator to refer to an item",
268+
format!("{}::{}", path_str, segment.ident),
269+
Applicability::MaybeIncorrect,
270+
);
271+
true
272+
}
273+
_ => false,
274+
};
275+
253276
match (def, source) {
254277
(Def::Macro(..), _) => {
255278
err.span_suggestion(
@@ -259,8 +282,7 @@ impl<'a> Resolver<'a> {
259282
Applicability::MaybeIncorrect,
260283
);
261284
if path_str == "try" && span.rust_2015() {
262-
err.note("if you want the `try` keyword, \
263-
you need to be in the 2018 edition");
285+
err.note("if you want the `try` keyword, you need to be in the 2018 edition");
264286
}
265287
}
266288
(Def::TyAlias(..), PathSource::Trait(_)) => {
@@ -269,25 +291,8 @@ impl<'a> Resolver<'a> {
269291
err.note("did you mean to use a trait alias?");
270292
}
271293
}
272-
(Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
273-
ExprKind::Field(_, ident) => {
274-
err.span_suggestion(
275-
parent.span,
276-
"use the path separator to refer to an item",
277-
format!("{}::{}", path_str, ident),
278-
Applicability::MaybeIncorrect,
279-
);
280-
}
281-
ExprKind::MethodCall(ref segment, ..) => {
282-
let span = parent.span.with_hi(segment.ident.span.hi());
283-
err.span_suggestion(
284-
span,
285-
"use the path separator to refer to an item",
286-
format!("{}::{}", path_str, segment.ident),
287-
Applicability::MaybeIncorrect,
288-
);
289-
}
290-
_ => return false,
294+
(Def::Mod(..), PathSource::Expr(Some(parent))) => if !path_sep(err, &parent) {
295+
return false;
291296
},
292297
(Def::Enum(..), PathSource::TupleStruct)
293298
| (Def::Enum(..), PathSource::Expr(..)) => {
@@ -315,8 +320,10 @@ impl<'a> Resolver<'a> {
315320
= self.struct_constructors.get(&def_id).cloned() {
316321
let accessible_ctor = self.is_accessible(ctor_vis);
317322
if is_expected(ctor_def) && !accessible_ctor {
318-
err.span_label(span, format!("constructor is not visible \
319-
here due to private fields"));
323+
err.span_label(
324+
span,
325+
format!("constructor is not visible here due to private fields"),
326+
);
320327
}
321328
} else {
322329
// HACK(estebank): find a better way to figure out that this was a
@@ -366,28 +373,12 @@ impl<'a> Resolver<'a> {
366373
}
367374
}
368375
match source {
369-
PathSource::Expr(Some(parent)) => {
370-
match parent.node {
371-
ExprKind::MethodCall(ref path_assignment, _) => {
372-
err.span_suggestion(
373-
sm.start_point(parent.span)
374-
.to(path_assignment.ident.span),
375-
"use `::` to access an associated function",
376-
format!("{}::{}",
377-
path_str,
378-
path_assignment.ident),
379-
Applicability::MaybeIncorrect
380-
);
381-
},
382-
_ => {
383-
err.span_label(
384-
span,
385-
format!("did you mean `{} {{ /* fields */ }}`?",
386-
path_str),
387-
);
388-
},
389-
}
390-
},
376+
PathSource::Expr(Some(parent)) => if !path_sep(err, &parent) {
377+
err.span_label(
378+
span,
379+
format!("did you mean `{} {{ /* fields */ }}`?", path_str),
380+
);
381+
}
391382
PathSource::Expr(None) if followed_by_brace == true => {
392383
if let Some((sp, snippet)) = closing_brace {
393384
err.span_suggestion(
@@ -399,16 +390,14 @@ impl<'a> Resolver<'a> {
399390
} else {
400391
err.span_label(
401392
span,
402-
format!("did you mean `({} {{ /* fields */ }})`?",
403-
path_str),
393+
format!("did you mean `({} {{ /* fields */ }})`?", path_str),
404394
);
405395
}
406396
},
407397
_ => {
408398
err.span_label(
409399
span,
410-
format!("did you mean `{} {{ /* fields */ }}`?",
411-
path_str),
400+
format!("did you mean `{} {{ /* fields */ }}`?", path_str),
412401
);
413402
},
414403
}
@@ -417,13 +406,11 @@ impl<'a> Resolver<'a> {
417406
(Def::Union(..), _) |
418407
(Def::Variant(..), _) |
419408
(Def::Ctor(_, _, CtorKind::Fictive), _) if ns == ValueNS => {
420-
err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
421-
path_str));
409+
err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str));
422410
}
423411
(Def::SelfTy(..), _) if ns == ValueNS => {
424412
err.span_label(span, fallback_label);
425-
err.note("can't use `Self` as a constructor, you must use the \
426-
implemented struct");
413+
err.note("can't use `Self` as a constructor, you must use the implemented struct");
427414
}
428415
(Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => {
429416
err.note("can't use a type alias as a constructor");

src/test/ui/resolve/issue-22692.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0423]: expected value, found struct `String`
44
LL | let _ = String.new();
55
| ^^^^^^----
66
| |
7-
| help: use `::` to access an associated function: `String::new`
7+
| help: use the path separator to refer to an item: `String::new`
88

99
error: aborting due to previous error
1010

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
pub mod Mod {
2+
pub struct Foo {}
3+
impl Foo {
4+
pub const BAR: usize = 42;
5+
}
6+
}
7+
8+
fn foo(_: usize) {}
9+
10+
fn main() {
11+
foo(Mod::Foo.Bar);
12+
//~^ ERROR expected value, found
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0423]: expected value, found struct `Mod::Foo`
2+
--> $DIR/assoc-const-as-field.rs:11:9
3+
|
4+
LL | foo(Mod::Foo.Bar);
5+
| ^^^^^^^^----
6+
| |
7+
| help: use the path separator to refer to an item: `Mod::Foo::Bar`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0423`.

0 commit comments

Comments
 (0)