Skip to content

Commit d2baf92

Browse files
committed
Add note linking to Rust 2018 path semantics docs.
This commit extends existing path suggestions to link to documentation on the changed semantics of `use` in Rust 2018.
1 parent 74ff7dc commit d2baf92

File tree

3 files changed

+63
-29
lines changed

3 files changed

+63
-29
lines changed

src/librustc_resolve/error_reporting.rs

+16-9
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
2424
&mut self,
2525
span: Span,
2626
path: Vec<Ident>
27-
) -> Option<Vec<Ident>> {
27+
) -> Option<(Vec<Ident>, Option<String>)> {
2828
debug!("make_path_suggestion: span={:?} path={:?}", span, path);
2929
// If we don't have a path to suggest changes to, then return.
3030
if path.is_empty() {
@@ -60,13 +60,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
6060
&mut self,
6161
span: Span,
6262
mut path: Vec<Ident>
63-
) -> Option<Vec<Ident>> {
63+
) -> Option<(Vec<Ident>, Option<String>)> {
6464
// Replace first ident with `self` and check if that is valid.
6565
path[0].name = keywords::SelfValue.name();
6666
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
6767
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
6868
if let PathResult::Module(..) = result {
69-
Some(path)
69+
Some((path, None))
7070
} else {
7171
None
7272
}
@@ -83,13 +83,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
8383
&mut self,
8484
span: Span,
8585
mut path: Vec<Ident>
86-
) -> Option<Vec<Ident>> {
86+
) -> Option<(Vec<Ident>, Option<String>)> {
8787
// Replace first ident with `crate` and check if that is valid.
8888
path[0].name = keywords::Crate.name();
8989
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
9090
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
9191
if let PathResult::Module(..) = result {
92-
Some(path)
92+
Some((
93+
path,
94+
Some(
95+
"`use` statements changed in Rust 2018; read more at \
96+
<https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
97+
clarity.html>".to_string()
98+
),
99+
))
93100
} else {
94101
None
95102
}
@@ -106,13 +113,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
106113
&mut self,
107114
span: Span,
108115
mut path: Vec<Ident>
109-
) -> Option<Vec<Ident>> {
116+
) -> Option<(Vec<Ident>, Option<String>)> {
110117
// Replace first ident with `crate` and check if that is valid.
111118
path[0].name = keywords::Super.name();
112119
let result = self.resolve_path(None, &path, None, false, span, CrateLint::No);
113120
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
114121
if let PathResult::Module(..) = result {
115-
Some(path)
122+
Some((path, None))
116123
} else {
117124
None
118125
}
@@ -132,7 +139,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
132139
&mut self,
133140
span: Span,
134141
mut path: Vec<Ident>
135-
) -> Option<Vec<Ident>> {
142+
) -> Option<(Vec<Ident>, Option<String>)> {
136143
// Need to clone else we can't call `resolve_path` without a borrow error. We also store
137144
// into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic)
138145
// each time.
@@ -157,7 +164,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
157164
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
158165
name, path, result);
159166
if let PathResult::Module(..) = result {
160-
return Some(path)
167+
return Some((path, None))
161168
}
162169
}
163170
}

src/librustc_resolve/resolve_imports.rs

+45-20
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
697697
}
698698
}
699699
});
700-
} else if let Some((span, err)) = error {
700+
} else if let Some((span, err, note)) = error {
701701
errors = true;
702702

703703
if let SingleImport { source, ref result, .. } = import.subclass {
@@ -725,7 +725,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
725725
let path = import_path_to_string(&import.module_path[..],
726726
&import.subclass,
727727
span);
728-
error_vec.push((span, path, err));
728+
error_vec.push((span, path, err, note));
729729
seen_spans.insert(span);
730730
prev_root_id = import.root_id;
731731
}
@@ -818,27 +818,45 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
818818
}
819819
}
820820

821-
fn throw_unresolved_import_error(&self, error_vec: Vec<(Span, String, String)>,
822-
span: Option<MultiSpan>) {
821+
fn throw_unresolved_import_error(
822+
&self,
823+
error_vec: Vec<(Span, String, String, Option<String>)>,
824+
span: Option<MultiSpan>,
825+
) {
823826
let max_span_label_msg_count = 10; // upper limit on number of span_label message.
824-
let (span, msg) = if error_vec.is_empty() {
825-
(span.unwrap(), "unresolved import".to_string())
827+
let (span, msg, note) = if error_vec.is_empty() {
828+
(span.unwrap(), "unresolved import".to_string(), None)
826829
} else {
827-
let span = MultiSpan::from_spans(error_vec.clone().into_iter()
828-
.map(|elem: (Span, String, String)| { elem.0 })
829-
.collect());
830+
let span = MultiSpan::from_spans(
831+
error_vec.clone().into_iter()
832+
.map(|elem: (Span, String, String, Option<String>)| elem.0)
833+
.collect()
834+
);
835+
836+
let note: Option<String> = error_vec.clone().into_iter()
837+
.filter_map(|elem: (Span, String, String, Option<String>)| elem.3)
838+
.last();
839+
830840
let path_vec: Vec<String> = error_vec.clone().into_iter()
831-
.map(|elem: (Span, String, String)| { format!("`{}`", elem.1) })
841+
.map(|elem: (Span, String, String, Option<String>)| format!("`{}`", elem.1))
832842
.collect();
833843
let path = path_vec.join(", ");
834-
let msg = format!("unresolved import{} {}",
835-
if path_vec.len() > 1 { "s" } else { "" }, path);
836-
(span, msg)
844+
let msg = format!(
845+
"unresolved import{} {}",
846+
if path_vec.len() > 1 { "s" } else { "" },
847+
path
848+
);
849+
850+
(span, msg, note)
837851
};
852+
838853
let mut err = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg);
839854
for span_error in error_vec.into_iter().take(max_span_label_msg_count) {
840855
err.span_label(span_error.0, span_error.2);
841856
}
857+
if let Some(note) = note {
858+
err.note(&note);
859+
}
842860
err.emit();
843861
}
844862

@@ -933,7 +951,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
933951
}
934952

935953
// If appropriate, returns an error to report.
936-
fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> {
954+
fn finalize_import(
955+
&mut self,
956+
directive: &'b ImportDirective<'b>
957+
) -> Option<(Span, String, Option<String>)> {
937958
self.current_module = directive.parent;
938959
let ImportDirective { ref module_path, span, .. } = *directive;
939960

@@ -956,15 +977,16 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
956977
return None;
957978
}
958979
PathResult::Failed(span, msg, true) => {
959-
return if let Some(suggested_path) = self.make_path_suggestion(
980+
return if let Some((suggested_path, note)) = self.make_path_suggestion(
960981
span, module_path.clone()
961982
) {
962983
Some((
963984
span,
964-
format!("Did you mean `{}`?", names_to_string(&suggested_path[..]))
985+
format!("Did you mean `{}`?", names_to_string(&suggested_path[..])),
986+
note,
965987
))
966988
} else {
967-
Some((span, msg))
989+
Some((span, msg, None))
968990
};
969991
},
970992
_ => return None,
@@ -989,8 +1011,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
9891011
if let ModuleOrUniformRoot::Module(module) = module {
9901012
if module.def_id() == directive.parent.def_id() {
9911013
// Importing a module into itself is not allowed.
992-
return Some((directive.span,
993-
"Cannot glob-import a module into itself.".to_string()));
1014+
return Some((
1015+
directive.span,
1016+
"Cannot glob-import a module into itself.".to_string(),
1017+
None,
1018+
));
9941019
}
9951020
}
9961021
if !is_prelude &&
@@ -1081,7 +1106,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
10811106
}
10821107
}
10831108
};
1084-
Some((span, msg))
1109+
Some((span, msg, None))
10851110
} else {
10861111
// `resolve_ident_in_module` reported a privacy error.
10871112
self.import_dummy_binding(directive);

src/test/ui/rust-2018/local-path-suggestions-2018.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error[E0432]: unresolved import `foo`
33
|
44
LL | use foo::Bar;
55
| ^^^ Did you mean `crate::foo`?
6+
|
7+
= note: `use` statements changed in Rust 2018; read more at <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html>
68

79
error[E0432]: unresolved import `foo`
810
--> $DIR/local-path-suggestions-2018.rs:27:5

0 commit comments

Comments
 (0)