Rollup merge of #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 #57316.
This commit is contained in:
commit
ba55822801
@ -5,7 +5,7 @@
|
||||
use rustc::hir::def::{Def, CtorKind, Namespace::*};
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
|
||||
use rustc::session::config::nightly_options;
|
||||
use syntax::ast::{ExprKind};
|
||||
use syntax::ast::{Expr, ExprKind};
|
||||
use syntax::symbol::keywords;
|
||||
use syntax_pos::Span;
|
||||
|
||||
@ -250,6 +250,29 @@ fn smart_resolve_context_dependent_help(
|
||||
let ns = source.namespace();
|
||||
let is_expected = &|def| source.is_expected(def);
|
||||
|
||||
let path_sep = |err: &mut DiagnosticBuilder<'_>, expr: &Expr| match expr.node {
|
||||
ExprKind::Field(_, ident) => {
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
"use the path separator to refer to an item",
|
||||
format!("{}::{}", path_str, ident),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
true
|
||||
}
|
||||
ExprKind::MethodCall(ref segment, ..) => {
|
||||
let span = expr.span.with_hi(segment.ident.span.hi());
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use the path separator to refer to an item",
|
||||
format!("{}::{}", path_str, segment.ident),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
match (def, source) {
|
||||
(Def::Macro(..), _) => {
|
||||
err.span_suggestion(
|
||||
@ -259,8 +282,7 @@ fn smart_resolve_context_dependent_help(
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if path_str == "try" && span.rust_2015() {
|
||||
err.note("if you want the `try` keyword, \
|
||||
you need to be in the 2018 edition");
|
||||
err.note("if you want the `try` keyword, you need to be in the 2018 edition");
|
||||
}
|
||||
}
|
||||
(Def::TyAlias(..), PathSource::Trait(_)) => {
|
||||
@ -269,25 +291,8 @@ fn smart_resolve_context_dependent_help(
|
||||
err.note("did you mean to use a trait alias?");
|
||||
}
|
||||
}
|
||||
(Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
|
||||
ExprKind::Field(_, ident) => {
|
||||
err.span_suggestion(
|
||||
parent.span,
|
||||
"use the path separator to refer to an item",
|
||||
format!("{}::{}", path_str, ident),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
ExprKind::MethodCall(ref segment, ..) => {
|
||||
let span = parent.span.with_hi(segment.ident.span.hi());
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use the path separator to refer to an item",
|
||||
format!("{}::{}", path_str, segment.ident),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => return false,
|
||||
(Def::Mod(..), PathSource::Expr(Some(parent))) => if !path_sep(err, &parent) {
|
||||
return false;
|
||||
},
|
||||
(Def::Enum(..), PathSource::TupleStruct)
|
||||
| (Def::Enum(..), PathSource::Expr(..)) => {
|
||||
@ -315,8 +320,10 @@ fn smart_resolve_context_dependent_help(
|
||||
= self.struct_constructors.get(&def_id).cloned() {
|
||||
let accessible_ctor = self.is_accessible(ctor_vis);
|
||||
if is_expected(ctor_def) && !accessible_ctor {
|
||||
err.span_label(span, format!("constructor is not visible \
|
||||
here due to private fields"));
|
||||
err.span_label(
|
||||
span,
|
||||
format!("constructor is not visible here due to private fields"),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// HACK(estebank): find a better way to figure out that this was a
|
||||
@ -366,28 +373,12 @@ fn smart_resolve_context_dependent_help(
|
||||
}
|
||||
}
|
||||
match source {
|
||||
PathSource::Expr(Some(parent)) => {
|
||||
match parent.node {
|
||||
ExprKind::MethodCall(ref path_assignment, _) => {
|
||||
err.span_suggestion(
|
||||
sm.start_point(parent.span)
|
||||
.to(path_assignment.ident.span),
|
||||
"use `::` to access an associated function",
|
||||
format!("{}::{}",
|
||||
path_str,
|
||||
path_assignment.ident),
|
||||
Applicability::MaybeIncorrect
|
||||
);
|
||||
},
|
||||
_ => {
|
||||
err.span_label(
|
||||
span,
|
||||
format!("did you mean `{} {{ /* fields */ }}`?",
|
||||
path_str),
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
PathSource::Expr(Some(parent)) => if !path_sep(err, &parent) {
|
||||
err.span_label(
|
||||
span,
|
||||
format!("did you mean `{} {{ /* fields */ }}`?", path_str),
|
||||
);
|
||||
}
|
||||
PathSource::Expr(None) if followed_by_brace == true => {
|
||||
if let Some((sp, snippet)) = closing_brace {
|
||||
err.span_suggestion(
|
||||
@ -399,16 +390,14 @@ fn smart_resolve_context_dependent_help(
|
||||
} else {
|
||||
err.span_label(
|
||||
span,
|
||||
format!("did you mean `({} {{ /* fields */ }})`?",
|
||||
path_str),
|
||||
format!("did you mean `({} {{ /* fields */ }})`?", path_str),
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
err.span_label(
|
||||
span,
|
||||
format!("did you mean `{} {{ /* fields */ }}`?",
|
||||
path_str),
|
||||
format!("did you mean `{} {{ /* fields */ }}`?", path_str),
|
||||
);
|
||||
},
|
||||
}
|
||||
@ -417,13 +406,11 @@ fn smart_resolve_context_dependent_help(
|
||||
(Def::Union(..), _) |
|
||||
(Def::Variant(..), _) |
|
||||
(Def::Ctor(_, _, CtorKind::Fictive), _) if ns == ValueNS => {
|
||||
err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
|
||||
path_str));
|
||||
err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str));
|
||||
}
|
||||
(Def::SelfTy(..), _) if ns == ValueNS => {
|
||||
err.span_label(span, fallback_label);
|
||||
err.note("can't use `Self` as a constructor, you must use the \
|
||||
implemented struct");
|
||||
err.note("can't use `Self` as a constructor, you must use the implemented struct");
|
||||
}
|
||||
(Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => {
|
||||
err.note("can't use a type alias as a constructor");
|
||||
|
@ -4,7 +4,7 @@ error[E0423]: expected value, found struct `String`
|
||||
LL | let _ = String.new();
|
||||
| ^^^^^^----
|
||||
| |
|
||||
| help: use `::` to access an associated function: `String::new`
|
||||
| help: use the path separator to refer to an item: `String::new`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
13
src/test/ui/suggestions/assoc-const-as-field.rs
Normal file
13
src/test/ui/suggestions/assoc-const-as-field.rs
Normal file
@ -0,0 +1,13 @@
|
||||
pub mod Mod {
|
||||
pub struct Foo {}
|
||||
impl Foo {
|
||||
pub const BAR: usize = 42;
|
||||
}
|
||||
}
|
||||
|
||||
fn foo(_: usize) {}
|
||||
|
||||
fn main() {
|
||||
foo(Mod::Foo.Bar);
|
||||
//~^ ERROR expected value, found
|
||||
}
|
11
src/test/ui/suggestions/assoc-const-as-field.stderr
Normal file
11
src/test/ui/suggestions/assoc-const-as-field.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0423]: expected value, found struct `Mod::Foo`
|
||||
--> $DIR/assoc-const-as-field.rs:11:9
|
||||
|
|
||||
LL | foo(Mod::Foo.Bar);
|
||||
| ^^^^^^^^----
|
||||
| |
|
||||
| help: use the path separator to refer to an item: `Mod::Foo::Bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0423`.
|
Loading…
Reference in New Issue
Block a user