Skip to content

Commit 76e7050

Browse files
authored
Suggest stable candidates rather than unstable ones
1 parent 7e552b4 commit 76e7050

File tree

6 files changed

+85
-6
lines changed

6 files changed

+85
-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

+59-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,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12581263
candidates.remove(idx);
12591264
}
12601265

1266+
let is_stable =
1267+
is_stable && did.is_some() && this.is_stable(did.unwrap(), path.span);
1268+
if is_stable
1269+
&& let Some(idx) = candidates
1270+
.iter()
1271+
.position(|v: &ImportSuggestion| v.did == did && !v.is_stable)
1272+
{
1273+
candidates.remove(idx);
1274+
}
1275+
12611276
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
12621277
// See if we're recommending TryFrom, TryInto, or FromIterator and add
12631278
// a note about editions
@@ -1289,6 +1304,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12891304
doc_visible: child_doc_visible,
12901305
note,
12911306
via_import,
1307+
is_stable,
12921308
});
12931309
}
12941310
}
@@ -1299,6 +1315,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12991315
let mut path_segments = path_segments.clone();
13001316
path_segments.push(ast::PathSegment::from_ident(ident));
13011317

1318+
let is_stable = is_stable && this.is_stable(module.def_id(), name_binding.span);
1319+
13021320
let alias_import = if let NameBindingKind::Import { import, .. } =
13031321
name_binding.kind
13041322
&& let ImportKind::ExternCrate { source: Some(_), .. } = import.kind
@@ -1315,8 +1333,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13151333
if !is_extern_crate_that_also_appears_in_prelude || alias_import {
13161334
// add the module to the lookup
13171335
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));
1336+
if via_import { &mut worklist_via_import } else { &mut worklist }.push(
1337+
(
1338+
module,
1339+
path_segments,
1340+
child_accessible,
1341+
child_doc_visible,
1342+
is_stable,
1343+
),
1344+
);
13201345
}
13211346
}
13221347
}
@@ -1326,6 +1351,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13261351
candidates
13271352
}
13281353

1354+
fn is_stable(&self, did: DefId, span: Span) -> bool {
1355+
if did.is_local() {
1356+
return true;
1357+
}
1358+
1359+
match self.tcx.lookup_stability(did) {
1360+
Some(Stability {
1361+
level: attr::StabilityLevel::Unstable { implied_by, .. },
1362+
feature,
1363+
..
1364+
}) => {
1365+
if span.allows_unstable(feature) {
1366+
true
1367+
} else if self.tcx.features().enabled(feature) {
1368+
true
1369+
} else if let Some(implied_by) = implied_by
1370+
&& self.tcx.features().enabled(implied_by)
1371+
{
1372+
true
1373+
} else {
1374+
false
1375+
}
1376+
}
1377+
Some(_) => true,
1378+
None => false,
1379+
}
1380+
}
1381+
13291382
/// When name resolution fails, this method can be used to look up candidate
13301383
/// entities with the expected name. It allows filtering them using the
13311384
/// 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)