use crate::check::autoderef::{self, Autoderef};
use crate::check::FnCtxt;
use crate::hir::def_id::DefId;
-use crate::hir::def::Def;
+use crate::hir::def::DefKind;
use crate::namespace::Namespace;
use rustc_data_structures::sync::Lrc;
use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable};
use rustc::ty::GenericParamDefKind;
use rustc::infer::type_variable::TypeVariableOrigin;
+use rustc::infer::unify_key::ConstVariableOrigin;
use rustc::util::nodemap::FxHashSet;
use rustc::infer::{self, InferOk};
use rustc::infer::canonical::{Canonical, QueryResponse};
allow_similar_names: bool,
/// Some(candidate) if there is a private candidate
- private_candidate: Option<Def>,
+ private_candidate: Option<(DefKind, DefId)>,
/// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
/// for error reporting
self.extension_candidates.push(candidate);
}
} else if self.private_candidate.is_none() {
- self.private_candidate = Some(candidate.item.def());
+ self.private_candidate =
+ Some((candidate.item.def_kind(), candidate.item.def_id));
}
}
method: &ty::AssociatedItem,
self_ty: Option<Ty<'tcx>>,
expected: Ty<'tcx>) -> bool {
- match method.def() {
- Def::Method(def_id) => {
- let fty = self.tcx.fn_sig(def_id);
+ match method.kind {
+ ty::AssociatedKind::Method => {
+ let fty = self.tcx.fn_sig(method.def_id);
self.probe(|_| {
let substs = self.fresh_substs_for_item(self.span, method.def_id);
let fty = fty.subst(self.tcx, substs);
let trait_substs = self.fresh_item_substs(trait_def_id);
let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
- for item in self.impl_or_trait_item(trait_def_id) {
- // Check whether `trait_def_id` defines a method with suitable name:
- if !self.has_applicable_self(&item) {
- debug!("method has inapplicable self");
- self.record_static_candidate(TraitSource(trait_def_id));
- continue;
- }
+ if self.tcx.is_trait_alias(trait_def_id) {
+ // For trait aliases, assume all super-traits are relevant.
+ let bounds = iter::once(trait_ref.to_poly_trait_ref());
+ self.elaborate_bounds(bounds, |this, new_trait_ref, item| {
+ let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
+
+ let (xform_self_ty, xform_ret_ty) =
+ this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs);
+ this.push_candidate(Candidate {
+ xform_self_ty, xform_ret_ty, item, import_id,
+ kind: TraitCandidate(new_trait_ref),
+ }, true);
+ });
+ } else {
+ debug_assert!(self.tcx.is_trait(trait_def_id));
+ for item in self.impl_or_trait_item(trait_def_id) {
+ // Check whether `trait_def_id` defines a method with suitable name.
+ if !self.has_applicable_self(&item) {
+ debug!("method has inapplicable self");
+ self.record_static_candidate(TraitSource(trait_def_id));
+ continue;
+ }
- let (xform_self_ty, xform_ret_ty) =
- self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs);
- self.push_candidate(Candidate {
- xform_self_ty, xform_ret_ty, item, import_id,
- kind: TraitCandidate(trait_ref),
- }, false);
+ let (xform_self_ty, xform_ret_ty) =
+ self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs);
+ self.push_candidate(Candidate {
+ xform_self_ty, xform_ret_ty, item, import_id,
+ kind: TraitCandidate(trait_ref),
+ }, false);
+ }
}
Ok(())
}
.filter(|&name| set.insert(name))
.collect();
- // sort them by the name so we have a stable result
+ // Sort them by the name so we have a stable result.
names.sort_by_cached_key(|n| n.as_str());
names
}
return r;
}
+ debug!("pick: actual search failed, assemble diagnotics");
+
let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
let private_candidate = self.private_candidate.take();
let unsatisfied_predicates = mem::replace(&mut self.unsatisfied_predicates, vec![]);
_ => vec![],
};
- if let Some(def) = private_candidate {
- return Err(MethodError::PrivateMatch(def, out_of_scope_traits));
+ if let Some((kind, def_id)) = private_candidate {
+ return Err(MethodError::PrivateMatch(kind, def_id, out_of_scope_traits));
}
let lev_candidate = self.probe_for_lev_candidate()?;
// In general, during probing we erase regions. See
// `impl_self_ty()` for an explanation.
- let region = tcx.types.re_erased;
+ let region = tcx.lifetimes.re_erased;
let autoref_ty = tcx.mk_ref(region,
ty::TypeAndMut {
GenericParamDefKind::Lifetime => {
// In general, during probe we erase regions. See
// `impl_self_ty()` for an explanation.
- self.tcx.types.re_erased.into()
+ self.tcx.lifetimes.re_erased.into()
}
GenericParamDefKind::Type { .. }
| GenericParamDefKind::Const => {
fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx> {
InternalSubsts::for_item(self.tcx, def_id, |param, _| {
match param.kind {
- GenericParamDefKind::Lifetime => self.tcx.types.re_erased.into(),
+ GenericParamDefKind::Lifetime => self.tcx.lifetimes.re_erased.into(),
GenericParamDefKind::Type { .. } => {
self.next_ty_var(TypeVariableOrigin::SubstitutionPlaceholder(
self.tcx.def_span(def_id))).into()
}
GenericParamDefKind::Const { .. } => {
- unimplemented!() // FIXME(const_generics)
+ let span = self.tcx.def_span(def_id);
+ let origin = ConstVariableOrigin::SubstitutionPlaceholder(span);
+ self.next_const_var(self.tcx.type_of(param.def_id), origin).into()
}
}
})