Skip to content

Commit 7b0ff5c

Browse files
committed
Suggest stable candidates rather than unstable ones
1 parent 7e552b4 commit 7b0ff5c

File tree

6 files changed

+91
-6
lines changed

6 files changed

+91
-6
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4330,6 +4330,7 @@ dependencies = [
43304330
"rustc_arena",
43314331
"rustc_ast",
43324332
"rustc_ast_pretty",
4333+
"rustc_attr_data_structures",
43334334
"rustc_attr_parsing",
43344335
"rustc_data_structures",
43354336
"rustc_errors",

compiler/rustc_resolve/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pulldown-cmark = { version = "0.11", features = ["html"], default-features = fal
1111
rustc_arena = { path = "../rustc_arena" }
1212
rustc_ast = { path = "../rustc_ast" }
1313
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
14+
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
1415
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
1516
rustc_data_structures = { path = "../rustc_data_structures" }
1617
rustc_errors = { path = "../rustc_errors" }

compiler/rustc_resolve/src/diagnostics.rs

+65-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_ast::{
55
self as ast, CRATE_NODE_ID, Crate, ItemKind, MetaItemInner, MetaItemKind, ModKind, NodeId, Path,
66
};
77
use rustc_ast_pretty::pprust;
8+
use rustc_attr_data_structures::{self as attr, Stability};
89
use rustc_data_structures::fx::FxHashSet;
910
use rustc_data_structures::unord::UnordSet;
1011
use rustc_errors::codes::*;
@@ -110,6 +111,7 @@ pub(crate) struct ImportSuggestion {
110111
pub via_import: bool,
111112
/// An extra note that should be issued if this item is suggested
112113
pub note: Option<String>,
114+
pub is_stable: bool,
113115
}
114116

115117
/// Adjust the impl span so that just the `impl` keyword is taken by removing
@@ -1172,13 +1174,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11721174
ThinVec::<ast::PathSegment>::new(),
11731175
true,
11741176
start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
1177+
true,
11751178
)];
11761179
let mut worklist_via_import = vec![];
11771180

1178-
while let Some((in_module, path_segments, accessible, doc_visible)) = match worklist.pop() {
1179-
None => worklist_via_import.pop(),
1180-
Some(x) => Some(x),
1181-
} {
1181+
while let Some((in_module, path_segments, accessible, doc_visible, is_stable)) =
1182+
match worklist.pop() {
1183+
None => worklist_via_import.pop(),
1184+
Some(x) => Some(x),
1185+
}
1186+
{
11821187
let in_module_is_extern = !in_module.def_id().is_local();
11831188
in_module.for_each_child(self, |this, ident, ns, name_binding| {
11841189
// Avoid non-importable candidates.
@@ -1258,6 +1263,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12581263
candidates.remove(idx);
12591264
}
12601265

1266+
let is_stable = if is_stable
1267+
&& let Some(did) = did
1268+
&& this.is_stable(did, path.span)
1269+
{
1270+
true
1271+
} else {
1272+
false
1273+
};
1274+
1275+
if is_stable
1276+
// Remove unstable match if exists
1277+
&& let Some(idx) = candidates
1278+
.iter()
1279+
.position(|v: &ImportSuggestion| v.did == did && !v.is_stable)
1280+
{
1281+
candidates.remove(idx);
1282+
}
1283+
12611284
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
12621285
// See if we're recommending TryFrom, TryInto, or FromIterator and add
12631286
// a note about editions
@@ -1289,6 +1312,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12891312
doc_visible: child_doc_visible,
12901313
note,
12911314
via_import,
1315+
is_stable,
12921316
});
12931317
}
12941318
}
@@ -1315,8 +1339,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13151339
if !is_extern_crate_that_also_appears_in_prelude || alias_import {
13161340
// add the module to the lookup
13171341
if seen_modules.insert(module.def_id()) {
1318-
if via_import { &mut worklist_via_import } else { &mut worklist }
1319-
.push((module, path_segments, child_accessible, child_doc_visible));
1342+
if via_import { &mut worklist_via_import } else { &mut worklist }.push(
1343+
(
1344+
module,
1345+
path_segments,
1346+
child_accessible,
1347+
child_doc_visible,
1348+
is_stable && this.is_stable(module.def_id(), name_binding.span),
1349+
),
1350+
);
13201351
}
13211352
}
13221353
}
@@ -1326,6 +1357,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13261357
candidates
13271358
}
13281359

1360+
fn is_stable(&self, did: DefId, span: Span) -> bool {
1361+
if did.is_local() {
1362+
return true;
1363+
}
1364+
1365+
match self.tcx.lookup_stability(did) {
1366+
Some(Stability {
1367+
level: attr::StabilityLevel::Unstable { implied_by, .. },
1368+
feature,
1369+
..
1370+
}) => {
1371+
if span.allows_unstable(feature) {
1372+
true
1373+
} else if self.tcx.features().enabled(feature) {
1374+
true
1375+
} else if let Some(implied_by) = implied_by
1376+
&& self.tcx.features().enabled(implied_by)
1377+
{
1378+
true
1379+
} else {
1380+
false
1381+
}
1382+
}
1383+
Some(_) => true,
1384+
None => false,
1385+
}
1386+
}
1387+
13291388
/// When name resolution fails, this method can be used to look up candidate
13301389
/// entities with the expected name. It allows filtering them using the
13311390
/// supplied predicate (which should be used to only accept the types of

compiler/rustc_resolve/src/late/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2501,6 +2501,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
25012501
doc_visible,
25022502
note: None,
25032503
via_import: false,
2504+
is_stable: true,
25042505
},
25052506
));
25062507
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
const _: Range = 0..1; //~ ERROR cannot find type `Range` in this scope
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0412]: cannot find type `Range` in this scope
2+
--> $DIR/sugg-stable-import-first-issue-140240.rs:2:14
3+
|
4+
LL | const _: Range = 0..1;
5+
| ^^^^^ not found in this scope
6+
|
7+
help: consider importing one of these structs
8+
|
9+
LL + use std::collections::btree_map::Range;
10+
|
11+
LL + use std::collections::btree_set::Range;
12+
|
13+
LL + use std::ops::Range;
14+
|
15+
LL + use std::range::Range;
16+
|
17+
18+
error: aborting due to 1 previous error
19+
20+
For more information about this error, try `rustc --explain E0412`.

0 commit comments

Comments
 (0)