Skip to content

suggesting for traits do not search the "prelude crates" #55613

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ use crate::ich::{Fingerprint, StableHashingContext};
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
use std::fmt;
use std::hash::Hash;
use syntax_pos::symbol::InternedString;
use syntax_pos::symbol::{InternedString, Symbol};
use crate::traits;
use crate::traits::query::{
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
@@ -593,6 +593,7 @@ define_dep_nodes!( <'tcx>
[input] CrateDisambiguator(CrateNum),
[input] CrateHash(CrateNum),
[input] OriginalCrateName(CrateNum),
[input] MaybeLoadExternCrate(Symbol),
[input] ExtraFileName(CrateNum),

[] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId },
@@ -637,8 +638,7 @@ define_dep_nodes!( <'tcx>
[input] MaybeUnusedExternCrates,
[input] NamesImportedByGlobUse(DefId),
[eval_always] StabilityIndex,
[eval_always] AllTraits,
[input] AllCrateNums,
[eval_always] AllSuggestibleTraits,
[] ExportedSymbols(CrateNum),
[eval_always] CollectAndPartitionMonoItems,
[] IsCodegenedItem(DefId),
3 changes: 3 additions & 0 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
@@ -201,6 +201,9 @@ pub trait CrateStore {
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
fn maybe_load_extern_crate_untracked(
&self, sess: &Session, name: Symbol
) -> Option<CrateNum>;

// This is basically a 1-based range of ints, which is a little
// silly - I may fix that.
11 changes: 5 additions & 6 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
@@ -1334,8 +1334,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.stability_index(LOCAL_CRATE)
}

pub fn crates(self) -> Lrc<Vec<CrateNum>> {
self.all_crate_nums(LOCAL_CRATE)
pub fn crates(self) -> Vec<CrateNum> {
self.cstore.crates_untracked()
}

pub fn features(self) -> Lrc<feature_gate::Features> {
@@ -2989,6 +2989,9 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
assert_eq!(id, LOCAL_CRATE);
tcx.crate_name
};
providers.maybe_load_extern_crate = |tcx, name| {
tcx.cstore.maybe_load_extern_crate_untracked(tcx.sess, name)
};
providers.get_lib_features = |tcx, id| {
assert_eq!(id, LOCAL_CRATE);
Lrc::new(middle::lib_features::collect(tcx))
@@ -3028,10 +3031,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
let id = tcx.hir().as_local_node_id(id).unwrap();
tcx.cstore.extern_mod_stmt_cnum_untracked(id)
};
providers.all_crate_nums = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
Lrc::new(tcx.cstore.crates_untracked())
};
providers.postorder_cnums = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
Lrc::new(tcx.cstore.postorder_cnums_untracked())
16 changes: 8 additions & 8 deletions src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ use crate::util::profiling::ProfileCategory;
use std::borrow::Cow;
use std::hash::Hash;
use std::fmt::Debug;
use syntax_pos::symbol::InternedString;
use syntax_pos::symbol::{Symbol, InternedString};
use rustc_data_structures::sync::Lock;
use rustc_data_structures::fingerprint::Fingerprint;
use crate::ich::StableHashingContext;
@@ -706,6 +706,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::original_crate_name<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::maybe_load_extern_crate<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, name: Symbol) -> Cow<'static, str> {
format!("loading crate with name {}", name).into()
}
}

impl<'tcx> QueryDescription<'tcx> for queries::extra_filename<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"looking up the extra filename for a crate".into()
@@ -832,18 +838,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::stability_index<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::all_traits<'tcx> {
impl<'tcx> QueryDescription<'tcx> for queries::all_suggestible_traits<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"fetching all foreign and local traits".into()
}
}

impl<'tcx> QueryDescription<'tcx> for queries::all_crate_nums<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"fetching all foreign CrateNum instances".into()
}
}

impl<'tcx> QueryDescription<'tcx> for queries::exported_symbols<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"exported_symbols".into()
11 changes: 10 additions & 1 deletion src/librustc/ty/query/keys.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ use crate::mir;
use std::fmt::Debug;
use std::hash::Hash;
use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::symbol::InternedString;
use syntax_pos::symbol::{Symbol, InternedString};

/// The `Key` trait controls what types can legally be used as the key
/// for a query.
@@ -190,6 +190,15 @@ impl Key for InternedString {
}
}

impl Key for Symbol {
fn query_crate(&self) -> CrateNum {
LOCAL_CRATE
}
fn default_span(&self, _tcx: TyCtxt<'_, '_, '_>) -> Span {
DUMMY_SP
}
}

/// Canonical query goals correspond to abstract trait operations that
/// are not tied to any crate in particular.
impl<'tcx, T> Key for Canonical<'tcx, T>
12 changes: 4 additions & 8 deletions src/librustc/ty/query/mod.rs
Original file line number Diff line number Diff line change
@@ -493,6 +493,7 @@ define_queries! { <'tcx>
[] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator,
[] fn crate_hash: CrateHash(CrateNum) -> Svh,
[] fn original_crate_name: OriginalCrateName(CrateNum) -> Symbol,
[] fn maybe_load_extern_crate: MaybeLoadExternCrate(Symbol) -> Option<CrateNum>,
[] fn extra_filename: ExtraFileName(CrateNum) -> String,
},

@@ -557,12 +558,11 @@ define_queries! { <'tcx>
-> Lrc<FxHashSet<ast::Name>>,

[] fn stability_index: stability_index_node(CrateNum) -> Lrc<stability::Index<'tcx>>,
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,

/// A vector of every trait accessible in the whole crate
/// (i.e., including those from subcrates). This is used only for
/// error reporting.
[] fn all_traits: all_traits_node(CrateNum) -> Lrc<Vec<DefId>>,
[] fn all_suggestible_traits: all_suggestible_traits_node(CrateNum) -> Lrc<Vec<DefId>>,
},

Linking {
@@ -894,12 +894,8 @@ fn stability_index_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::StabilityIndex
}

fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::AllCrateNums
}

fn all_traits_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::AllTraits
fn all_suggestible_traits_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::AllSuggestibleTraits
}

fn collect_and_partition_mono_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
2 changes: 1 addition & 1 deletion src/librustc/ty/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
@@ -429,7 +429,7 @@ impl<'sess> OnDiskCache<'sess> {
-> IndexVec<CrateNum, Option<CrateNum>>
{
tcx.dep_graph.with_ignore(|| {
let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
let current_cnums = tcx.crates().iter().map(|&cnum| {
let crate_name = tcx.original_crate_name(cnum)
.to_string();
let crate_disambiguator = tcx.crate_disambiguator(cnum);
4 changes: 2 additions & 2 deletions src/librustc/ty/query/plumbing.rs
Original file line number Diff line number Diff line change
@@ -1242,6 +1242,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::MethodAutoderefSteps |
DepKind::InstanceDefSizeEstimate |
DepKind::ProgramClausesForEnv |
DepKind::MaybeLoadExternCrate |

// This one should never occur in this context
DepKind::Null => {
@@ -1415,8 +1416,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::NamesImportedByGlobUse => { force!(names_imported_by_glob_use, def_id!()); }
DepKind::MaybeUnusedExternCrates => { force!(maybe_unused_extern_crates, LOCAL_CRATE); }
DepKind::StabilityIndex => { force!(stability_index, LOCAL_CRATE); }
DepKind::AllTraits => { force!(all_traits, LOCAL_CRATE); }
DepKind::AllCrateNums => { force!(all_crate_nums, LOCAL_CRATE); }
DepKind::AllSuggestibleTraits => { force!(all_suggestible_traits, LOCAL_CRATE); }
DepKind::ExportedSymbols => { force!(exported_symbols, krate!()); }
DepKind::CollectAndPartitionMonoItems => {
force!(collect_and_partition_mono_items, LOCAL_CRATE);
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/back/symbol_export.rs
Original file line number Diff line number Diff line change
@@ -286,7 +286,7 @@ fn upstream_monomorphizations_provider<'a, 'tcx>(
{
debug_assert!(cnum == LOCAL_CRATE);

let cnums = tcx.all_crate_nums(LOCAL_CRATE);
let cnums = tcx.crates();

let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default();

14 changes: 12 additions & 2 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::cstore::{self, LoadedMacro};
use crate::creader::CrateLoader;
use crate::encoder;
use crate::link_args;
use crate::native_libs;
@@ -31,7 +32,7 @@ use syntax::edition::Edition;
use syntax::parse::source_file_to_stream;
use syntax::parse::parser::emit_unclosed_delims;
use syntax::symbol::Symbol;
use syntax_pos::{Span, NO_EXPANSION, FileName};
use syntax_pos::{Span, DUMMY_SP, NO_EXPANSION, FileName};
use rustc_data_structures::bit_set::BitSet;

macro_rules! provide {
@@ -328,7 +329,7 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
// which is to say, its not deterministic in general. But
// we believe that libstd is consistently assigned crate
// num 1, so it should be enough to resolve #46112.
let mut crates: Vec<CrateNum> = (*tcx.crates()).clone();
let mut crates = tcx.crates();
crates.sort();

for &cnum in crates.iter() {
@@ -541,6 +542,15 @@ impl CrateStore for cstore::CStore {
self.do_postorder_cnums_untracked()
}

fn maybe_load_extern_crate_untracked(
&self,
sess: &Session,
name: Symbol
) -> Option<CrateNum> {
let mut crate_loader = CrateLoader::new(sess, self, "");
crate_loader.maybe_process_path_extern(name, DUMMY_SP)
}

fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> EncodedMetadata
23 changes: 21 additions & 2 deletions src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
@@ -491,6 +491,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
}

fn reset(&mut self) {
debug!("reset");
self.inherent_candidates.clear();
self.extension_candidates.clear();
self.impl_dups.clear();
@@ -505,13 +506,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
candidate: Candidate<'tcx>,
is_inherent: bool)
{
debug!("push_candidate: candidate={:?} is_inherent={:?}", candidate, is_inherent);
let is_accessible = if let Some(name) = self.method_name {
let item = candidate.item;
let def_scope = self.tcx.adjust_ident(name, item.container.id(), self.body_id).1;
item.vis.is_accessible_from(def_scope, self.tcx)
} else {
true
};

debug!("push_candidate: is_accessible={:?}", is_accessible);
if is_accessible {
if is_inherent {
self.inherent_candidates.push(candidate);
@@ -847,8 +851,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
}

fn assemble_extension_candidates_for_all_traits(&mut self) -> Result<(), MethodError<'tcx>> {
debug!("assemble_extension_candidates_for_all_traits");
let mut duplicates = FxHashSet::default();
for trait_info in suggest::all_traits(self.tcx) {
for trait_info in suggest::all_suggestible_traits(self.tcx) {
if duplicates.insert(trait_info.def_id) {
self.assemble_extension_candidates_for_trait(None, trait_info.def_id)?;
}
@@ -939,6 +944,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
// THE ACTUAL SEARCH

fn pick(mut self) -> PickResult<'tcx> {
debug!("pick: method_name={:?}", self.method_name);
assert!(self.method_name.is_some());

if let Some(r) = self.pick_core() {
@@ -958,9 +964,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
self.assemble_extension_candidates_for_all_traits()?;

let out_of_scope_traits = match self.pick_core() {
Some(Ok(p)) => vec![p.item.container.id()],
Some(Ok(p)) => {
debug!("pick: (ok) p={:?}", p);
vec![p.item.container.id()]
},
//Some(Ok(p)) => p.iter().map(|p| p.item.container().id()).collect(),
Some(Err(MethodError::Ambiguity(v))) => {
debug!("pick: (ambiguity) v={:?}", v);
v.into_iter()
.map(|source| {
match source {
@@ -979,6 +989,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
.collect()
}
Some(Err(MethodError::NoMatch(NoMatchData { out_of_scope_traits: others, .. }))) => {
debug!("pick: (no match) others={:?}", others);
assert!(others.is_empty());
vec![]
}
@@ -990,6 +1001,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
}
let lev_candidate = self.probe_for_lev_candidate()?;

debug!("pick: out_of_scope_traits={:?}", out_of_scope_traits);
Err(MethodError::NoMatch(NoMatchData::new(static_candidates,
unsatisfied_predicates,
out_of_scope_traits,
@@ -1302,13 +1314,20 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let predicate = trait_ref.to_predicate();
let obligation =
traits::Obligation::new(cause, self.param_env, predicate);
debug!(
"consider_probe: predicate={:?} obligation={:?} trait_ref={:?}",
predicate, obligation, trait_ref
);
if !self.predicate_may_hold(&obligation) {
debug!("consider_probe: predicate did not hold");
if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) {
debug!("consider_probe: select_trait_candidate.is_err=true");
// This candidate's primary obligation doesn't even
// select - don't bother registering anything in
// `potentially_unsatisfied_predicates`.
return ProbeResult::NoMatch;
} else {
debug!("consider_probe: nested subobligation");
// Some nested subobligation of this predicate
// failed.
//
67 changes: 42 additions & 25 deletions src/librustc_typeck/check/method/suggest.rs
Original file line number Diff line number Diff line change
@@ -207,7 +207,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Suggest clamping down the type if the method that is being attempted to
// be used exists at all, and the type is an ambiuous numeric type
// ({integer}/{float}).
let mut candidates = all_traits(self.tcx)
let mut candidates = all_suggestible_traits(self.tcx)
.into_iter()
.filter_map(|info|
self.associated_item(info.def_id, item_name, Namespace::Value)
@@ -430,15 +430,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
bound_list));
}

if actual.is_numeric() && actual.is_fresh() {

} else {
self.suggest_traits_to_import(&mut err,
span,
rcvr_ty,
item_name,
source,
out_of_scope_traits);
if !actual.is_numeric() || !actual.is_fresh() {
self.suggest_traits_to_import(
&mut err, span, rcvr_ty, item_name, source, out_of_scope_traits
);
}

if let Some(lev_candidate) = lev_candidate {
@@ -575,13 +570,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
}

fn suggest_traits_to_import<'b>(&self,
err: &mut DiagnosticBuilder,
span: Span,
rcvr_ty: Ty<'tcx>,
item_name: ast::Ident,
source: SelfSource<'b>,
valid_out_of_scope_traits: Vec<DefId>) {
fn suggest_traits_to_import(
&self,
err: &mut DiagnosticBuilder,
span: Span,
rcvr_ty: Ty<'tcx>,
item_name: ast::Ident,
source: SelfSource<'a>,
valid_out_of_scope_traits: Vec<DefId>
) {
debug!(
"suggest_traits_to_import: rcvr_ty={:?} item_name={:?} source={:?} \
valid_out_of_scope_traits={:?}",
rcvr_ty, item_name, source, valid_out_of_scope_traits,
);
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
return;
}
@@ -591,7 +593,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// There are no traits implemented, so lets suggest some traits to
// implement, by finding ones that have the item name, and are
// legal to implement.
let mut candidates = all_traits(self.tcx)
let mut candidates = all_suggestible_traits(self.tcx)
.into_iter()
.filter(|info| {
// We approximate the coherence rules to only suggest
@@ -610,6 +612,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
})
.collect::<Vec<_>>();

debug!("suggest_traits_to_import: candidates={:?}", candidates);
if !candidates.is_empty() {
// Sort from most relevant to least relevant.
candidates.sort_by(|a, b| a.cmp(b).reverse());
@@ -676,13 +679,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
}

#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub enum SelfSource<'a> {
QPath(&'a hir::Ty),
MethodCall(&'a hir::Expr /* rcvr */),
}

#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub struct TraitInfo {
pub def_id: DefId,
}
@@ -692,12 +695,15 @@ impl PartialEq for TraitInfo {
self.cmp(other) == Ordering::Equal
}
}

impl Eq for TraitInfo {}

impl PartialOrd for TraitInfo {
fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for TraitInfo {
fn cmp(&self, other: &TraitInfo) -> Ordering {
// Local crates are more important than remote ones (local:
@@ -710,8 +716,8 @@ impl Ord for TraitInfo {
}

/// Retrieves all traits in this crate and any dependent crates.
pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<TraitInfo> {
tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
pub fn all_suggestible_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<TraitInfo> {
tcx.all_suggestible_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
}

/// Computes all traits in this crate and any dependent crates.
@@ -768,9 +774,20 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<DefId>
_ => {}
}
}
for &cnum in tcx.crates().iter() {

// Attempt to load all crates that we have `--extern` flags for, this means
// we will be able to make suggestions for traits they define. Particularly useful
// in Rust 2018 as there aren't `extern crate` lines that import a crate even if it isn't
// otherwise used.
for name in tcx.extern_prelude.keys() {
let cnum = tcx.maybe_load_extern_crate(*name);
debug!("compute_all_traits: (attempt load) name={:?} cnum={:?}", name, cnum);
}

for cnum in tcx.crates().iter() {
debug!("compute_all_traits: cnum={:?} name={:?}", cnum, tcx.crate_name(*cnum));
let def_id = DefId {
krate: cnum,
krate: *cnum,
index: CRATE_DEF_INDEX,
};
handle_external_def(tcx, &mut traits, &mut external_mods, Def::Mod(def_id));
@@ -780,7 +797,7 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec<DefId>
}

pub fn provide(providers: &mut ty::query::Providers) {
providers.all_traits = |tcx, cnum| {
providers.all_suggestible_traits = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
Lrc::new(compute_all_traits(tcx))
}
2 changes: 1 addition & 1 deletion src/librustdoc/core.rs
Original file line number Diff line number Diff line change
@@ -532,7 +532,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
fake_def_ids: Default::default(),
all_fake_def_ids: Default::default(),
generated_synthetics: Default::default(),
all_traits: tcx.all_traits(LOCAL_CRATE).to_vec(),
all_traits: tcx.all_suggestible_traits(LOCAL_CRATE).to_vec(),
};
debug!("crate: {:?}", tcx.hir().krate());

9 changes: 8 additions & 1 deletion src/test/ui/rust-2018/auxiliary/baz.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
// This file is used as part of the local-path-suggestions.rs test.
// This file is used as part of the local-path-suggestions.rs and
// the trait-import-suggestions.rs test.

pub mod foobar {
pub struct Baz;
}

pub trait BazTrait {
fn extern_baz(&self) { }
}

impl BazTrait for u32 { }
5 changes: 0 additions & 5 deletions src/test/ui/rust-2018/auxiliary/trait-import-suggestions.rs

This file was deleted.

13 changes: 13 additions & 0 deletions src/test/ui/rust-2018/extern-trait-impl-suggestions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// edition:2018
// aux-build:baz.rs
// compile-flags:--extern baz

// Don't use anything from baz - making suggestions from it when the only reference to it
// is an `--extern` flag is what is tested by this test.

struct Local;

fn main() {
let local = Local;
local.extern_baz(); //~ ERROR no method named `extern_baz`
}
16 changes: 16 additions & 0 deletions src/test/ui/rust-2018/extern-trait-impl-suggestions.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0599]: no method named `extern_baz` found for type `Local` in the current scope
--> $DIR/extern-trait-impl-suggestions.rs:12:11
|
LL | struct Local;
| ------------- method `extern_baz` not found for this
...
LL | local.extern_baz(); //~ ERROR no method named `extern_baz`
| ^^^^^^^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `extern_baz`, perhaps you need to implement it:
candidate #1: `baz::BazTrait`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
9 changes: 6 additions & 3 deletions src/test/ui/rust-2018/trait-import-suggestions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// edition:2018
// aux-build:trait-import-suggestions.rs
// compile-flags:--extern trait-import-suggestions
// aux-build:baz.rs
// compile-flags:--extern baz

// Don't use anything from baz - making suggestions from it when the only reference to it
// is an `--extern` flag is one of the things tested by this test.

mod foo {
mod foobar {
@@ -26,6 +29,6 @@ mod foo {
fn main() {
let x: u32 = 22;
x.bar(); //~ ERROR no method named `bar`
x.baz(); //~ ERROR no method named `baz`
x.extern_baz(); //~ ERROR no method named `extern_baz`
let y = u32::from_str("33"); //~ ERROR no function or associated item named `from_str`
}
20 changes: 13 additions & 7 deletions src/test/ui/rust-2018/trait-import-suggestions.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0599]: no method named `foobar` found for type `u32` in the current scope
--> $DIR/trait-import-suggestions.rs:22:11
--> $DIR/trait-import-suggestions.rs:25:11
|
LL | x.foobar(); //~ ERROR no method named `foobar`
| ^^^^^^
@@ -9,7 +9,7 @@ LL | x.foobar(); //~ ERROR no method named `foobar`
`use crate::foo::foobar::Foobar;`

error[E0599]: no method named `bar` found for type `u32` in the current scope
--> $DIR/trait-import-suggestions.rs:28:7
--> $DIR/trait-import-suggestions.rs:31:7
|
LL | x.bar(); //~ ERROR no method named `bar`
| ^^^
@@ -20,14 +20,20 @@ help: the following trait is implemented but not in scope, perhaps add a `use` f
LL | use crate::foo::Bar;
|

error[E0599]: no method named `baz` found for type `u32` in the current scope
--> $DIR/trait-import-suggestions.rs:29:7
error[E0599]: no method named `extern_baz` found for type `u32` in the current scope
--> $DIR/trait-import-suggestions.rs:32:7
|
LL | x.extern_baz(); //~ ERROR no method named `extern_baz`
| ^^^^^^^^^^
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
|
LL | use baz::BazTrait;
|
LL | x.baz(); //~ ERROR no method named `baz`
| ^^^

error[E0599]: no function or associated item named `from_str` found for type `u32` in the current scope
--> $DIR/trait-import-suggestions.rs:30:18
--> $DIR/trait-import-suggestions.rs:33:18
|
LL | let y = u32::from_str("33"); //~ ERROR no function or associated item named `from_str`
| -----^^^^^^^^