Auto merge of #36736 - srinivasreddy:method, r=nrc
run rustfmt on librustc_typeck/check/method folder
This commit is contained in:
commit
fd1ea1330e
4 changed files with 564 additions and 548 deletions
|
@ -55,8 +55,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
unadjusted_self_ty: Ty<'tcx>,
|
unadjusted_self_ty: Ty<'tcx>,
|
||||||
pick: probe::Pick<'tcx>,
|
pick: probe::Pick<'tcx>,
|
||||||
supplied_method_types: Vec<Ty<'tcx>>)
|
supplied_method_types: Vec<Ty<'tcx>>)
|
||||||
-> ty::MethodCallee<'tcx>
|
-> ty::MethodCallee<'tcx> {
|
||||||
{
|
|
||||||
debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})",
|
debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})",
|
||||||
unadjusted_self_ty,
|
unadjusted_self_ty,
|
||||||
pick,
|
pick,
|
||||||
|
@ -72,17 +71,20 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
self_expr: &'gcx hir::Expr,
|
self_expr: &'gcx hir::Expr,
|
||||||
call_expr: &'gcx hir::Expr)
|
call_expr: &'gcx hir::Expr)
|
||||||
-> ConfirmContext<'a, 'gcx, 'tcx>
|
-> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
{
|
ConfirmContext {
|
||||||
ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
|
fcx: fcx,
|
||||||
|
span: span,
|
||||||
|
self_expr: self_expr,
|
||||||
|
call_expr: call_expr,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self,
|
fn confirm(&mut self,
|
||||||
unadjusted_self_ty: Ty<'tcx>,
|
unadjusted_self_ty: Ty<'tcx>,
|
||||||
pick: probe::Pick<'tcx>,
|
pick: probe::Pick<'tcx>,
|
||||||
supplied_method_types: Vec<Ty<'tcx>>)
|
supplied_method_types: Vec<Ty<'tcx>>)
|
||||||
-> ty::MethodCallee<'tcx>
|
-> ty::MethodCallee<'tcx> {
|
||||||
{
|
|
||||||
// Adjust the self expression the user provided and obtain the adjusted type.
|
// Adjust the self expression the user provided and obtain the adjusted type.
|
||||||
let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
|
let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
|
||||||
|
|
||||||
|
@ -91,18 +93,13 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Create substitutions for the method's type parameters.
|
// Create substitutions for the method's type parameters.
|
||||||
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
|
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
|
||||||
let all_substs =
|
let all_substs = self.instantiate_method_substs(&pick, supplied_method_types, rcvr_substs);
|
||||||
self.instantiate_method_substs(
|
|
||||||
&pick,
|
|
||||||
supplied_method_types,
|
|
||||||
rcvr_substs);
|
|
||||||
|
|
||||||
debug!("all_substs={:?}", all_substs);
|
debug!("all_substs={:?}", all_substs);
|
||||||
|
|
||||||
// Create the final signature for the method, replacing late-bound regions.
|
// Create the final signature for the method, replacing late-bound regions.
|
||||||
let InstantiatedMethodSig {
|
let InstantiatedMethodSig { method_sig, method_predicates } =
|
||||||
method_sig, method_predicates
|
self.instantiate_method_sig(&pick, all_substs);
|
||||||
} = self.instantiate_method_sig(&pick, all_substs);
|
|
||||||
let method_self_ty = method_sig.inputs[0];
|
let method_self_ty = method_sig.inputs[0];
|
||||||
|
|
||||||
// Unify the (adjusted) self type with what the method expects.
|
// Unify the (adjusted) self type with what the method expects.
|
||||||
|
@ -111,7 +108,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
// Create the method type
|
// Create the method type
|
||||||
let def_id = pick.item.def_id();
|
let def_id = pick.item.def_id();
|
||||||
let method_ty = pick.item.as_opt_method().unwrap();
|
let method_ty = pick.item.as_opt_method().unwrap();
|
||||||
let fty = self.tcx.mk_fn_def(def_id, all_substs,
|
let fty = self.tcx.mk_fn_def(def_id,
|
||||||
|
all_substs,
|
||||||
self.tcx.mk_bare_fn(ty::BareFnTy {
|
self.tcx.mk_bare_fn(ty::BareFnTy {
|
||||||
sig: ty::Binder(method_sig),
|
sig: ty::Binder(method_sig),
|
||||||
unsafety: method_ty.fty.unsafety,
|
unsafety: method_ty.fty.unsafety,
|
||||||
|
@ -125,7 +123,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
let callee = ty::MethodCallee {
|
let callee = ty::MethodCallee {
|
||||||
def_id: def_id,
|
def_id: def_id,
|
||||||
ty: fty,
|
ty: fty,
|
||||||
substs: all_substs
|
substs: all_substs,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(hir::MutMutable) = pick.autoref {
|
if let Some(hir::MutMutable) = pick.autoref {
|
||||||
|
@ -141,14 +139,12 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
fn adjust_self_ty(&mut self,
|
fn adjust_self_ty(&mut self,
|
||||||
unadjusted_self_ty: Ty<'tcx>,
|
unadjusted_self_ty: Ty<'tcx>,
|
||||||
pick: &probe::Pick<'tcx>)
|
pick: &probe::Pick<'tcx>)
|
||||||
-> Ty<'tcx>
|
-> Ty<'tcx> {
|
||||||
{
|
|
||||||
let (autoref, unsize) = if let Some(mutbl) = pick.autoref {
|
let (autoref, unsize) = if let Some(mutbl) = pick.autoref {
|
||||||
let region = self.next_region_var(infer::Autoref(self.span));
|
let region = self.next_region_var(infer::Autoref(self.span));
|
||||||
let autoref = AutoPtr(region, mutbl);
|
let autoref = AutoPtr(region, mutbl);
|
||||||
(Some(autoref), pick.unsize.map(|target| {
|
(Some(autoref),
|
||||||
target.adjust_for_autoref(self.tcx, Some(autoref))
|
pick.unsize.map(|target| target.adjust_for_autoref(self.tcx, Some(autoref))))
|
||||||
}))
|
|
||||||
} else {
|
} else {
|
||||||
// No unsizing should be performed without autoref (at
|
// No unsizing should be performed without autoref (at
|
||||||
// least during method dispach). This is because we
|
// least during method dispach). This is because we
|
||||||
|
@ -168,10 +164,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
autoderef.finalize(LvaluePreference::NoPreference, Some(self.self_expr));
|
autoderef.finalize(LvaluePreference::NoPreference, Some(self.self_expr));
|
||||||
|
|
||||||
// Write out the final adjustment.
|
// Write out the final adjustment.
|
||||||
self.write_adjustment(self.self_expr.id, AdjustDerefRef(AutoDerefRef {
|
self.write_adjustment(self.self_expr.id,
|
||||||
|
AdjustDerefRef(AutoDerefRef {
|
||||||
autoderefs: pick.autoderefs,
|
autoderefs: pick.autoderefs,
|
||||||
autoref: autoref,
|
autoref: autoref,
|
||||||
unsize: unsize
|
unsize: unsize,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if let Some(target) = unsize {
|
if let Some(target) = unsize {
|
||||||
|
@ -193,13 +190,13 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
fn fresh_receiver_substs(&mut self,
|
fn fresh_receiver_substs(&mut self,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
pick: &probe::Pick<'tcx>)
|
pick: &probe::Pick<'tcx>)
|
||||||
-> &'tcx Substs<'tcx>
|
-> &'tcx Substs<'tcx> {
|
||||||
{
|
|
||||||
match pick.kind {
|
match pick.kind {
|
||||||
probe::InherentImplPick => {
|
probe::InherentImplPick => {
|
||||||
let impl_def_id = pick.item.container().id();
|
let impl_def_id = pick.item.container().id();
|
||||||
assert!(self.tcx.impl_trait_ref(impl_def_id).is_none(),
|
assert!(self.tcx.impl_trait_ref(impl_def_id).is_none(),
|
||||||
"impl {:?} is not an inherent impl", impl_def_id);
|
"impl {:?} is not an inherent impl",
|
||||||
|
impl_def_id);
|
||||||
self.impl_self_ty(self.span, impl_def_id).substs
|
self.impl_self_ty(self.span, impl_def_id).substs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,10 +213,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
// argument type), but those cases have already
|
// argument type), but those cases have already
|
||||||
// been ruled out when we deemed the trait to be
|
// been ruled out when we deemed the trait to be
|
||||||
// "object safe".
|
// "object safe".
|
||||||
let original_poly_trait_ref =
|
let original_poly_trait_ref = principal.with_self_ty(this.tcx, object_ty);
|
||||||
principal.with_self_ty(this.tcx, object_ty);
|
let upcast_poly_trait_ref = this.upcast(original_poly_trait_ref, trait_def_id);
|
||||||
let upcast_poly_trait_ref =
|
|
||||||
this.upcast(original_poly_trait_ref, trait_def_id);
|
|
||||||
let upcast_trait_ref =
|
let upcast_trait_ref =
|
||||||
this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
|
this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
|
||||||
debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
|
debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
|
||||||
|
@ -242,8 +237,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
// the impl ([$A,$B,$C]) not the receiver type ([$C]).
|
// the impl ([$A,$B,$C]) not the receiver type ([$C]).
|
||||||
let impl_polytype = self.impl_self_ty(self.span, impl_def_id);
|
let impl_polytype = self.impl_self_ty(self.span, impl_def_id);
|
||||||
let impl_trait_ref =
|
let impl_trait_ref =
|
||||||
self.instantiate_type_scheme(
|
self.instantiate_type_scheme(self.span,
|
||||||
self.span,
|
|
||||||
impl_polytype.substs,
|
impl_polytype.substs,
|
||||||
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
|
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
|
||||||
impl_trait_ref.substs
|
impl_trait_ref.substs
|
||||||
|
@ -268,12 +262,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_existential_trait_ref<R, F>(&mut self,
|
fn extract_existential_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R
|
||||||
self_ty: Ty<'tcx>,
|
|
||||||
mut closure: F) -> R
|
|
||||||
where F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>,
|
where F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>,
|
||||||
Ty<'tcx>,
|
Ty<'tcx>,
|
||||||
ty::PolyExistentialTraitRef<'tcx>) -> R,
|
ty::PolyExistentialTraitRef<'tcx>)
|
||||||
|
-> R
|
||||||
{
|
{
|
||||||
// If we specified that this is an object method, then the
|
// If we specified that this is an object method, then the
|
||||||
// self-type ought to be something that can be dereferenced to
|
// self-type ought to be something that can be dereferenced to
|
||||||
|
@ -281,7 +274,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
// etc).
|
// etc).
|
||||||
|
|
||||||
// FIXME: this feels, like, super dubious
|
// FIXME: this feels, like, super dubious
|
||||||
self.fcx.autoderef(self.span, self_ty)
|
self.fcx
|
||||||
|
.autoderef(self.span, self_ty)
|
||||||
.filter_map(|(ty, _)| {
|
.filter_map(|(ty, _)| {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)),
|
ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)),
|
||||||
|
@ -290,8 +284,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
span_bug!(
|
span_bug!(self.span,
|
||||||
self.span,
|
|
||||||
"self-type `{}` for ObjectPick never dereferenced to an object",
|
"self-type `{}` for ObjectPick never dereferenced to an object",
|
||||||
self_ty)
|
self_ty)
|
||||||
})
|
})
|
||||||
|
@ -301,8 +294,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
pick: &probe::Pick<'tcx>,
|
pick: &probe::Pick<'tcx>,
|
||||||
mut supplied_method_types: Vec<Ty<'tcx>>,
|
mut supplied_method_types: Vec<Ty<'tcx>>,
|
||||||
substs: &Substs<'tcx>)
|
substs: &Substs<'tcx>)
|
||||||
-> &'tcx Substs<'tcx>
|
-> &'tcx Substs<'tcx> {
|
||||||
{
|
|
||||||
// Determine the values for the generic parameters of the method.
|
// Determine the values for the generic parameters of the method.
|
||||||
// If they were not explicitly supplied, just construct fresh
|
// If they were not explicitly supplied, just construct fresh
|
||||||
// variables.
|
// variables.
|
||||||
|
@ -312,23 +304,24 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if num_supplied_types > 0 && num_supplied_types != num_method_types {
|
if num_supplied_types > 0 && num_supplied_types != num_method_types {
|
||||||
if num_method_types == 0 {
|
if num_method_types == 0 {
|
||||||
struct_span_err!(self.tcx.sess, self.span, E0035,
|
struct_span_err!(self.tcx.sess,
|
||||||
|
self.span,
|
||||||
|
E0035,
|
||||||
"does not take type parameters")
|
"does not take type parameters")
|
||||||
.span_label(self.span, &"called with unneeded type parameters")
|
.span_label(self.span, &"called with unneeded type parameters")
|
||||||
.emit();
|
.emit();
|
||||||
} else {
|
} else {
|
||||||
struct_span_err!(self.tcx.sess, self.span, E0036,
|
struct_span_err!(self.tcx.sess,
|
||||||
|
self.span,
|
||||||
|
E0036,
|
||||||
"incorrect number of type parameters given for this method: \
|
"incorrect number of type parameters given for this method: \
|
||||||
expected {}, found {}",
|
expected {}, found {}",
|
||||||
num_method_types, num_supplied_types)
|
num_method_types,
|
||||||
|
num_supplied_types)
|
||||||
.span_label(self.span,
|
.span_label(self.span,
|
||||||
&format!("Passed {} type argument{}, expected {}",
|
&format!("Passed {} type argument{}, expected {}",
|
||||||
num_supplied_types,
|
num_supplied_types,
|
||||||
if num_supplied_types != 1 {
|
if num_supplied_types != 1 { "s" } else { "" },
|
||||||
"s"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
},
|
|
||||||
num_method_types))
|
num_method_types))
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
@ -340,14 +333,17 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
//
|
//
|
||||||
// FIXME -- permit users to manually specify lifetimes
|
// FIXME -- permit users to manually specify lifetimes
|
||||||
let supplied_start = substs.params().len() + method.generics.regions.len();
|
let supplied_start = substs.params().len() + method.generics.regions.len();
|
||||||
Substs::for_item(self.tcx, method.def_id, |def, _| {
|
Substs::for_item(self.tcx,
|
||||||
|
method.def_id,
|
||||||
|
|def, _| {
|
||||||
let i = def.index as usize;
|
let i = def.index as usize;
|
||||||
if i < substs.params().len() {
|
if i < substs.params().len() {
|
||||||
substs.region_at(i)
|
substs.region_at(i)
|
||||||
} else {
|
} else {
|
||||||
self.region_var_for_def(self.span, def)
|
self.region_var_for_def(self.span, def)
|
||||||
}
|
}
|
||||||
}, |def, cur_substs| {
|
},
|
||||||
|
|def, cur_substs| {
|
||||||
let i = def.index as usize;
|
let i = def.index as usize;
|
||||||
if i < substs.params().len() {
|
if i < substs.params().len() {
|
||||||
substs.type_at(i)
|
substs.type_at(i)
|
||||||
|
@ -359,21 +355,17 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unify_receivers(&mut self,
|
fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
|
||||||
self_ty: Ty<'tcx>,
|
match self.sub_types(false, TypeOrigin::Misc(self.span), self_ty, method_self_ty) {
|
||||||
method_self_ty: Ty<'tcx>)
|
|
||||||
{
|
|
||||||
match self.sub_types(false, TypeOrigin::Misc(self.span),
|
|
||||||
self_ty, method_self_ty) {
|
|
||||||
Ok(InferOk { obligations, .. }) => {
|
Ok(InferOk { obligations, .. }) => {
|
||||||
// FIXME(#32730) propagate obligations
|
// FIXME(#32730) propagate obligations
|
||||||
assert!(obligations.is_empty());
|
assert!(obligations.is_empty());
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
span_bug!(
|
span_bug!(self.span,
|
||||||
self.span,
|
|
||||||
"{} was a subtype of {} but now is not?",
|
"{} was a subtype of {} but now is not?",
|
||||||
self_ty, method_self_ty);
|
self_ty,
|
||||||
|
method_self_ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,8 +376,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
fn instantiate_method_sig(&mut self,
|
fn instantiate_method_sig(&mut self,
|
||||||
pick: &probe::Pick<'tcx>,
|
pick: &probe::Pick<'tcx>,
|
||||||
all_substs: &'tcx Substs<'tcx>)
|
all_substs: &'tcx Substs<'tcx>)
|
||||||
-> InstantiatedMethodSig<'tcx>
|
-> InstantiatedMethodSig<'tcx> {
|
||||||
{
|
|
||||||
debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
|
debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
|
||||||
pick,
|
pick,
|
||||||
all_substs);
|
all_substs);
|
||||||
|
@ -393,13 +384,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
// Instantiate the bounds on the method with the
|
// Instantiate the bounds on the method with the
|
||||||
// type/early-bound-regions substitutions performed. There can
|
// type/early-bound-regions substitutions performed. There can
|
||||||
// be no late-bound regions appearing here.
|
// be no late-bound regions appearing here.
|
||||||
let method_predicates = pick.item.as_opt_method().unwrap()
|
let method_predicates = pick.item
|
||||||
.predicates.instantiate(self.tcx, all_substs);
|
.as_opt_method()
|
||||||
let method_predicates = self.normalize_associated_types_in(self.span,
|
.unwrap()
|
||||||
&method_predicates);
|
.predicates
|
||||||
|
.instantiate(self.tcx, all_substs);
|
||||||
|
let method_predicates = self.normalize_associated_types_in(self.span, &method_predicates);
|
||||||
|
|
||||||
debug!("method_predicates after subst = {:?}",
|
debug!("method_predicates after subst = {:?}", method_predicates);
|
||||||
method_predicates);
|
|
||||||
|
|
||||||
// Instantiate late-bound regions and substitute the trait
|
// Instantiate late-bound regions and substitute the trait
|
||||||
// parameters into the method type to get the actual method type.
|
// parameters into the method type to get the actual method type.
|
||||||
|
@ -407,14 +399,16 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
// NB: Instantiate late-bound regions first so that
|
// NB: Instantiate late-bound regions first so that
|
||||||
// `instantiate_type_scheme` can normalize associated types that
|
// `instantiate_type_scheme` can normalize associated types that
|
||||||
// may reference those regions.
|
// may reference those regions.
|
||||||
let method_sig = self.replace_late_bound_regions_with_fresh_var(
|
let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.item
|
||||||
&pick.item.as_opt_method().unwrap().fty.sig);
|
.as_opt_method()
|
||||||
|
.unwrap()
|
||||||
|
.fty
|
||||||
|
.sig);
|
||||||
debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
|
debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
|
||||||
method_sig);
|
method_sig);
|
||||||
|
|
||||||
let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig);
|
let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig);
|
||||||
debug!("type scheme substituted, method_sig={:?}",
|
debug!("type scheme substituted, method_sig={:?}", method_sig);
|
||||||
method_sig);
|
|
||||||
|
|
||||||
InstantiatedMethodSig {
|
InstantiatedMethodSig {
|
||||||
method_sig: method_sig,
|
method_sig: method_sig,
|
||||||
|
@ -431,8 +425,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
all_substs,
|
all_substs,
|
||||||
method_predicates);
|
method_predicates);
|
||||||
|
|
||||||
self.add_obligations_for_parameters(
|
self.add_obligations_for_parameters(traits::ObligationCause::misc(self.span, self.body_id),
|
||||||
traits::ObligationCause::misc(self.span, self.body_id),
|
|
||||||
method_predicates);
|
method_predicates);
|
||||||
|
|
||||||
// this is a projection from a trait reference, so we have to
|
// this is a projection from a trait reference, so we have to
|
||||||
|
@ -481,12 +474,15 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?} \
|
debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?} \
|
||||||
autoderef_count={}",
|
autoderef_count={}",
|
||||||
i, expr, autoderef_count);
|
i,
|
||||||
|
expr,
|
||||||
|
autoderef_count);
|
||||||
|
|
||||||
if autoderef_count > 0 {
|
if autoderef_count > 0 {
|
||||||
let mut autoderef = self.autoderef(expr.span, self.node_ty(expr.id));
|
let mut autoderef = self.autoderef(expr.span, self.node_ty(expr.id));
|
||||||
autoderef.nth(autoderef_count).unwrap_or_else(|| {
|
autoderef.nth(autoderef_count).unwrap_or_else(|| {
|
||||||
span_bug!(expr.span, "expr was deref-able {} times but now isn't?",
|
span_bug!(expr.span,
|
||||||
|
"expr was deref-able {} times but now isn't?",
|
||||||
autoderef_count);
|
autoderef_count);
|
||||||
});
|
});
|
||||||
autoderef.finalize(PreferMutLvalue, Some(expr));
|
autoderef.finalize(PreferMutLvalue, Some(expr));
|
||||||
|
@ -508,29 +504,30 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
// (ab)use the normal type checking paths.
|
// (ab)use the normal type checking paths.
|
||||||
let adj = self.tables.borrow().adjustments.get(&base_expr.id).cloned();
|
let adj = self.tables.borrow().adjustments.get(&base_expr.id).cloned();
|
||||||
let (autoderefs, unsize) = match adj {
|
let (autoderefs, unsize) = match adj {
|
||||||
Some(AdjustDerefRef(adr)) => match adr.autoref {
|
Some(AdjustDerefRef(adr)) => {
|
||||||
|
match adr.autoref {
|
||||||
None => {
|
None => {
|
||||||
assert!(adr.unsize.is_none());
|
assert!(adr.unsize.is_none());
|
||||||
(adr.autoderefs, None)
|
(adr.autoderefs, None)
|
||||||
}
|
}
|
||||||
Some(AutoPtr(..)) => {
|
Some(AutoPtr(..)) => {
|
||||||
(adr.autoderefs, adr.unsize.map(|target| {
|
(adr.autoderefs,
|
||||||
|
adr.unsize.map(|target| {
|
||||||
target.builtin_deref(false, NoPreference)
|
target.builtin_deref(false, NoPreference)
|
||||||
.expect("fixup: AutoPtr is not &T").ty
|
.expect("fixup: AutoPtr is not &T")
|
||||||
|
.ty
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
span_bug!(
|
span_bug!(base_expr.span,
|
||||||
base_expr.span,
|
|
||||||
"unexpected adjustment autoref {:?}",
|
"unexpected adjustment autoref {:?}",
|
||||||
adr);
|
adr);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
None => (0, None),
|
None => (0, None),
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
span_bug!(
|
span_bug!(base_expr.span, "unexpected adjustment type");
|
||||||
base_expr.span,
|
|
||||||
"unexpected adjustment type");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -541,13 +538,13 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
Some(&AdjustDerefRef(AutoDerefRef {
|
Some(&AdjustDerefRef(AutoDerefRef {
|
||||||
autoderefs: autoderefs,
|
autoderefs: autoderefs,
|
||||||
autoref: None,
|
autoref: None,
|
||||||
unsize: None
|
unsize: None,
|
||||||
}))), false)
|
}))),
|
||||||
|
false)
|
||||||
};
|
};
|
||||||
let index_expr_ty = self.node_ty(index_expr.id);
|
let index_expr_ty = self.node_ty(index_expr.id);
|
||||||
|
|
||||||
let result = self.try_index_step(
|
let result = self.try_index_step(ty::MethodCall::expr(expr.id),
|
||||||
ty::MethodCall::expr(expr.id),
|
|
||||||
expr,
|
expr,
|
||||||
&base_expr,
|
&base_expr,
|
||||||
adjusted_base_ty,
|
adjusted_base_ty,
|
||||||
|
@ -597,15 +594,13 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
fn upcast(&mut self,
|
fn upcast(&mut self,
|
||||||
source_trait_ref: ty::PolyTraitRef<'tcx>,
|
source_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
target_trait_def_id: DefId)
|
target_trait_def_id: DefId)
|
||||||
-> ty::PolyTraitRef<'tcx>
|
-> ty::PolyTraitRef<'tcx> {
|
||||||
{
|
let upcast_trait_refs = self.tcx
|
||||||
let upcast_trait_refs = self.tcx.upcast_choices(source_trait_ref.clone(),
|
.upcast_choices(source_trait_ref.clone(), target_trait_def_id);
|
||||||
target_trait_def_id);
|
|
||||||
|
|
||||||
// must be exactly one trait ref or we'd get an ambig error etc
|
// must be exactly one trait ref or we'd get an ambig error etc
|
||||||
if upcast_trait_refs.len() != 1 {
|
if upcast_trait_refs.len() != 1 {
|
||||||
span_bug!(
|
span_bug!(self.span,
|
||||||
self.span,
|
|
||||||
"cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
|
"cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
|
||||||
source_trait_ref,
|
source_trait_ref,
|
||||||
target_trait_def_id,
|
target_trait_def_id,
|
||||||
|
@ -618,7 +613,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
|
fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
|
||||||
where T: TypeFoldable<'tcx>
|
where T: TypeFoldable<'tcx>
|
||||||
{
|
{
|
||||||
self.fcx.replace_late_bound_regions_with_fresh_var(
|
self.fcx
|
||||||
self.span, infer::FnCall, value).0
|
.replace_late_bound_regions_with_fresh_var(self.span, infer::FnCall, value)
|
||||||
|
.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,8 @@ pub enum MethodError<'tcx> {
|
||||||
Ambiguity(Vec<CandidateSource>),
|
Ambiguity(Vec<CandidateSource>),
|
||||||
|
|
||||||
// Using a `Fn`/`FnMut`/etc method on a raw closure type before we have inferred its kind.
|
// Using a `Fn`/`FnMut`/etc method on a raw closure type before we have inferred its kind.
|
||||||
ClosureAmbiguity(/* DefId of fn trait */ DefId),
|
ClosureAmbiguity(// DefId of fn trait
|
||||||
|
DefId),
|
||||||
|
|
||||||
// Found an applicable method, but it is not visible.
|
// Found an applicable method, but it is not visible.
|
||||||
PrivateMatch(Def),
|
PrivateMatch(Def),
|
||||||
|
@ -53,19 +54,20 @@ pub struct NoMatchData<'tcx> {
|
||||||
pub static_candidates: Vec<CandidateSource>,
|
pub static_candidates: Vec<CandidateSource>,
|
||||||
pub unsatisfied_predicates: Vec<TraitRef<'tcx>>,
|
pub unsatisfied_predicates: Vec<TraitRef<'tcx>>,
|
||||||
pub out_of_scope_traits: Vec<DefId>,
|
pub out_of_scope_traits: Vec<DefId>,
|
||||||
pub mode: probe::Mode
|
pub mode: probe::Mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> NoMatchData<'tcx> {
|
impl<'tcx> NoMatchData<'tcx> {
|
||||||
pub fn new(static_candidates: Vec<CandidateSource>,
|
pub fn new(static_candidates: Vec<CandidateSource>,
|
||||||
unsatisfied_predicates: Vec<TraitRef<'tcx>>,
|
unsatisfied_predicates: Vec<TraitRef<'tcx>>,
|
||||||
out_of_scope_traits: Vec<DefId>,
|
out_of_scope_traits: Vec<DefId>,
|
||||||
mode: probe::Mode) -> Self {
|
mode: probe::Mode)
|
||||||
|
-> Self {
|
||||||
NoMatchData {
|
NoMatchData {
|
||||||
static_candidates: static_candidates,
|
static_candidates: static_candidates,
|
||||||
unsatisfied_predicates: unsatisfied_predicates,
|
unsatisfied_predicates: unsatisfied_predicates,
|
||||||
out_of_scope_traits: out_of_scope_traits,
|
out_of_scope_traits: out_of_scope_traits,
|
||||||
mode: mode
|
mode: mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +77,8 @@ impl<'tcx> NoMatchData<'tcx> {
|
||||||
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
pub enum CandidateSource {
|
pub enum CandidateSource {
|
||||||
ImplSource(DefId),
|
ImplSource(DefId),
|
||||||
TraitSource(/* trait id */ DefId),
|
TraitSource(// trait id
|
||||||
|
DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
@ -86,8 +89,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
self_ty: ty::Ty<'tcx>,
|
self_ty: ty::Ty<'tcx>,
|
||||||
call_expr_id: ast::NodeId,
|
call_expr_id: ast::NodeId,
|
||||||
allow_private: bool)
|
allow_private: bool)
|
||||||
-> bool
|
-> bool {
|
||||||
{
|
|
||||||
let mode = probe::Mode::MethodCall;
|
let mode = probe::Mode::MethodCall;
|
||||||
match self.probe_method(span, mode, method_name, self_ty, call_expr_id) {
|
match self.probe_method(span, mode, method_name, self_ty, call_expr_id) {
|
||||||
Ok(..) => true,
|
Ok(..) => true,
|
||||||
|
@ -119,8 +121,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
supplied_method_types: Vec<ty::Ty<'tcx>>,
|
supplied_method_types: Vec<ty::Ty<'tcx>>,
|
||||||
call_expr: &'gcx hir::Expr,
|
call_expr: &'gcx hir::Expr,
|
||||||
self_expr: &'gcx hir::Expr)
|
self_expr: &'gcx hir::Expr)
|
||||||
-> Result<ty::MethodCallee<'tcx>, MethodError<'tcx>>
|
-> Result<ty::MethodCallee<'tcx>, MethodError<'tcx>> {
|
||||||
{
|
|
||||||
debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
|
debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
|
||||||
method_name,
|
method_name,
|
||||||
self_ty,
|
self_ty,
|
||||||
|
@ -135,7 +136,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.tcx.used_trait_imports.borrow_mut().insert(import_id);
|
self.tcx.used_trait_imports.borrow_mut().insert(import_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.confirm_method(span, self_expr, call_expr, self_ty, pick, supplied_method_types))
|
Ok(self.confirm_method(span,
|
||||||
|
self_expr,
|
||||||
|
call_expr,
|
||||||
|
self_ty,
|
||||||
|
pick,
|
||||||
|
supplied_method_types))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_method_in_trait(&self,
|
pub fn lookup_method_in_trait(&self,
|
||||||
|
@ -145,10 +151,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
self_ty: ty::Ty<'tcx>,
|
self_ty: ty::Ty<'tcx>,
|
||||||
opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
|
opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
|
||||||
-> Option<ty::MethodCallee<'tcx>>
|
-> Option<ty::MethodCallee<'tcx>> {
|
||||||
{
|
self.lookup_method_in_trait_adjusted(span,
|
||||||
self.lookup_method_in_trait_adjusted(span, self_expr, m_name, trait_def_id,
|
self_expr,
|
||||||
0, false, self_ty, opt_input_types)
|
m_name,
|
||||||
|
trait_def_id,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
self_ty,
|
||||||
|
opt_input_types)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `lookup_in_trait_adjusted` is used for overloaded operators.
|
/// `lookup_in_trait_adjusted` is used for overloaded operators.
|
||||||
|
@ -171,8 +182,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
unsize: bool,
|
unsize: bool,
|
||||||
self_ty: ty::Ty<'tcx>,
|
self_ty: ty::Ty<'tcx>,
|
||||||
opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
|
opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
|
||||||
-> Option<ty::MethodCallee<'tcx>>
|
-> Option<ty::MethodCallee<'tcx>> {
|
||||||
{
|
|
||||||
debug!("lookup_in_trait_adjusted(self_ty={:?}, self_expr={:?}, \
|
debug!("lookup_in_trait_adjusted(self_ty={:?}, self_expr={:?}, \
|
||||||
m_name={}, trait_def_id={:?})",
|
m_name={}, trait_def_id={:?})",
|
||||||
self_ty,
|
self_ty,
|
||||||
|
@ -188,9 +198,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
assert!(trait_def.generics.regions.is_empty());
|
assert!(trait_def.generics.regions.is_empty());
|
||||||
|
|
||||||
// Construct a trait-reference `self_ty : Trait<input_tys>`
|
// Construct a trait-reference `self_ty : Trait<input_tys>`
|
||||||
let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
|
let substs = Substs::for_item(self.tcx,
|
||||||
self.region_var_for_def(span, def)
|
trait_def_id,
|
||||||
}, |def, substs| {
|
|def, _| self.region_var_for_def(span, def),
|
||||||
|
|def, substs| {
|
||||||
if def.index == 0 {
|
if def.index == 0 {
|
||||||
self_ty
|
self_ty
|
||||||
} else if let Some(ref input_types) = opt_input_types {
|
} else if let Some(ref input_types) = opt_input_types {
|
||||||
|
@ -204,9 +215,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Construct an obligation
|
// Construct an obligation
|
||||||
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
||||||
let obligation = traits::Obligation::misc(span,
|
let obligation =
|
||||||
self.body_id,
|
traits::Obligation::misc(span, self.body_id, poly_trait_ref.to_predicate());
|
||||||
poly_trait_ref.to_predicate());
|
|
||||||
|
|
||||||
// Now we want to know if this can be matched
|
// Now we want to know if this can be matched
|
||||||
let mut selcx = traits::SelectionContext::new(self);
|
let mut selcx = traits::SelectionContext::new(self);
|
||||||
|
@ -224,7 +234,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
assert_eq!(method_ty.generics.regions.len(), 0);
|
assert_eq!(method_ty.generics.regions.len(), 0);
|
||||||
|
|
||||||
debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}",
|
debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}",
|
||||||
method_item, method_ty);
|
method_item,
|
||||||
|
method_ty);
|
||||||
|
|
||||||
// Instantiate late-bound regions and substitute the trait
|
// Instantiate late-bound regions and substitute the trait
|
||||||
// parameters into the method type to get the actual method type.
|
// parameters into the method type to get the actual method type.
|
||||||
|
@ -232,13 +243,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// NB: Instantiate late-bound regions first so that
|
// NB: Instantiate late-bound regions first so that
|
||||||
// `instantiate_type_scheme` can normalize associated types that
|
// `instantiate_type_scheme` can normalize associated types that
|
||||||
// may reference those regions.
|
// may reference those regions.
|
||||||
let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
|
let fn_sig =
|
||||||
infer::FnCall,
|
self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &method_ty.fty.sig)
|
||||||
&method_ty.fty.sig).0;
|
.0;
|
||||||
let fn_sig = self.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
|
let fn_sig = self.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
|
||||||
let transformed_self_ty = fn_sig.inputs[0];
|
let transformed_self_ty = fn_sig.inputs[0];
|
||||||
let def_id = method_item.def_id();
|
let def_id = method_item.def_id();
|
||||||
let fty = tcx.mk_fn_def(def_id, trait_ref.substs,
|
let fty = tcx.mk_fn_def(def_id,
|
||||||
|
trait_ref.substs,
|
||||||
tcx.mk_bare_fn(ty::BareFnTy {
|
tcx.mk_bare_fn(ty::BareFnTy {
|
||||||
sig: ty::Binder(fn_sig),
|
sig: ty::Binder(fn_sig),
|
||||||
unsafety: method_ty.fty.unsafety,
|
unsafety: method_ty.fty.unsafety,
|
||||||
|
@ -259,8 +271,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// any late-bound regions appearing in its bounds.
|
// any late-bound regions appearing in its bounds.
|
||||||
let method_bounds = self.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates);
|
let method_bounds = self.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates);
|
||||||
assert!(!method_bounds.has_escaping_regions());
|
assert!(!method_bounds.has_escaping_regions());
|
||||||
self.add_obligations_for_parameters(
|
self.add_obligations_for_parameters(traits::ObligationCause::misc(span, self.body_id),
|
||||||
traits::ObligationCause::misc(span, self.body_id),
|
|
||||||
&method_bounds);
|
&method_bounds);
|
||||||
|
|
||||||
// Also register an obligation for the method type being well-formed.
|
// Also register an obligation for the method type being well-formed.
|
||||||
|
@ -278,7 +289,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
Some(self_expr) => {
|
Some(self_expr) => {
|
||||||
debug!("lookup_in_trait_adjusted: inserting adjustment if needed \
|
debug!("lookup_in_trait_adjusted: inserting adjustment if needed \
|
||||||
(self-id={}, autoderefs={}, unsize={}, explicit_self={:?})",
|
(self-id={}, autoderefs={}, unsize={}, explicit_self={:?})",
|
||||||
self_expr.id, autoderefs, unsize,
|
self_expr.id,
|
||||||
|
autoderefs,
|
||||||
|
unsize,
|
||||||
method_ty.explicit_self);
|
method_ty.explicit_self);
|
||||||
|
|
||||||
match method_ty.explicit_self {
|
match method_ty.explicit_self {
|
||||||
|
@ -301,13 +314,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
Some(transformed_self_ty)
|
Some(transformed_self_ty)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
span_bug!(
|
span_bug!(span,
|
||||||
span,
|
|
||||||
"trait method is &self but first arg is: {}",
|
"trait method is &self but first arg is: {}",
|
||||||
transformed_self_ty);
|
transformed_self_ty);
|
||||||
}
|
}
|
||||||
|
@ -315,8 +327,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
span_bug!(
|
span_bug!(span,
|
||||||
span,
|
|
||||||
"unexpected explicit self type in operator method: {:?}",
|
"unexpected explicit self type in operator method: {:?}",
|
||||||
method_ty.explicit_self);
|
method_ty.explicit_self);
|
||||||
}
|
}
|
||||||
|
@ -327,7 +338,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let callee = ty::MethodCallee {
|
let callee = ty::MethodCallee {
|
||||||
def_id: def_id,
|
def_id: def_id,
|
||||||
ty: fty,
|
ty: fty,
|
||||||
substs: trait_ref.substs
|
substs: trait_ref.substs,
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("callee = {:?}", callee);
|
debug!("callee = {:?}", callee);
|
||||||
|
@ -340,8 +351,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
method_name: ast::Name,
|
method_name: ast::Name,
|
||||||
self_ty: ty::Ty<'tcx>,
|
self_ty: ty::Ty<'tcx>,
|
||||||
expr_id: ast::NodeId)
|
expr_id: ast::NodeId)
|
||||||
-> Result<Def, MethodError<'tcx>>
|
-> Result<Def, MethodError<'tcx>> {
|
||||||
{
|
|
||||||
let mode = probe::Mode::Path;
|
let mode = probe::Mode::Path;
|
||||||
let pick = self.probe_method(span, mode, method_name, self_ty, expr_id)?;
|
let pick = self.probe_method(span, mode, method_name, self_ty, expr_id)?;
|
||||||
|
|
||||||
|
@ -364,9 +374,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn impl_or_trait_item(&self,
|
pub fn impl_or_trait_item(&self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
item_name: ast::Name)
|
item_name: ast::Name)
|
||||||
-> Option<ty::ImplOrTraitItem<'tcx>>
|
-> Option<ty::ImplOrTraitItem<'tcx>> {
|
||||||
{
|
self.tcx
|
||||||
self.tcx.impl_or_trait_items(def_id)
|
.impl_or_trait_items(def_id)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&did| self.tcx.impl_or_trait_item(did))
|
.map(|&did| self.tcx.impl_or_trait_item(did))
|
||||||
.find(|m| m.name() == item_name)
|
.find(|m| m.name() == item_name)
|
||||||
|
|
|
@ -13,7 +13,7 @@ use super::NoMatchData;
|
||||||
use super::{CandidateSource, ImplSource, TraitSource};
|
use super::{CandidateSource, ImplSource, TraitSource};
|
||||||
use super::suggest;
|
use super::suggest;
|
||||||
|
|
||||||
use check::{FnCtxt};
|
use check::FnCtxt;
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use hir::def::Def;
|
use hir::def::Def;
|
||||||
use rustc::ty::subst::{Subst, Substs};
|
use rustc::ty::subst::{Subst, Substs};
|
||||||
|
@ -52,7 +52,7 @@ struct ProbeContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
|
|
||||||
/// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
|
/// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
|
||||||
/// for error reporting
|
/// for error reporting
|
||||||
unsatisfied_predicates: Vec<TraitRef<'tcx>>
|
unsatisfied_predicates: Vec<TraitRef<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Deref for ProbeContext<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> Deref for ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
@ -66,7 +66,7 @@ impl<'a, 'gcx, 'tcx> Deref for ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
struct CandidateStep<'tcx> {
|
struct CandidateStep<'tcx> {
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
autoderefs: usize,
|
autoderefs: usize,
|
||||||
unsize: bool
|
unsize: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -80,12 +80,17 @@ struct Candidate<'tcx> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum CandidateKind<'tcx> {
|
enum CandidateKind<'tcx> {
|
||||||
InherentImplCandidate(&'tcx Substs<'tcx>,
|
InherentImplCandidate(&'tcx Substs<'tcx>,
|
||||||
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
|
// Normalize obligations
|
||||||
ExtensionImplCandidate(/* Impl */ DefId, &'tcx Substs<'tcx>,
|
Vec<traits::PredicateObligation<'tcx>>),
|
||||||
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
|
ExtensionImplCandidate(// Impl
|
||||||
|
DefId,
|
||||||
|
&'tcx Substs<'tcx>,
|
||||||
|
// Normalize obligations
|
||||||
|
Vec<traits::PredicateObligation<'tcx>>),
|
||||||
ObjectCandidate,
|
ObjectCandidate,
|
||||||
TraitCandidate,
|
TraitCandidate,
|
||||||
WhereClauseCandidate(/* Trait */ ty::PolyTraitRef<'tcx>),
|
WhereClauseCandidate(// Trait
|
||||||
|
ty::PolyTraitRef<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -115,10 +120,12 @@ pub struct Pick<'tcx> {
|
||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
pub enum PickKind<'tcx> {
|
pub enum PickKind<'tcx> {
|
||||||
InherentImplPick,
|
InherentImplPick,
|
||||||
ExtensionImplPick(/* Impl */ DefId),
|
ExtensionImplPick(// Impl
|
||||||
|
DefId),
|
||||||
ObjectPick,
|
ObjectPick,
|
||||||
TraitPick,
|
TraitPick,
|
||||||
WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>),
|
WhereClausePick(// Trait
|
||||||
|
ty::PolyTraitRef<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError<'tcx>>;
|
pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError<'tcx>>;
|
||||||
|
@ -132,7 +139,7 @@ pub enum Mode {
|
||||||
// An expression of the form `Type::item` or `<T>::item`.
|
// An expression of the form `Type::item` or `<T>::item`.
|
||||||
// No autoderefs are performed, lookup is done based on the type each
|
// No autoderefs are performed, lookup is done based on the type each
|
||||||
// implementation is for, and static methods are included.
|
// implementation is for, and static methods are included.
|
||||||
Path
|
Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
@ -142,8 +149,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
item_name: ast::Name,
|
item_name: ast::Name,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
scope_expr_id: ast::NodeId)
|
scope_expr_id: ast::NodeId)
|
||||||
-> PickResult<'tcx>
|
-> PickResult<'tcx> {
|
||||||
{
|
|
||||||
debug!("probe(self_ty={:?}, item_name={}, scope_expr_id={})",
|
debug!("probe(self_ty={:?}, item_name={}, scope_expr_id={})",
|
||||||
self_ty,
|
self_ty,
|
||||||
item_name,
|
item_name,
|
||||||
|
@ -159,14 +165,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let steps = if mode == Mode::MethodCall {
|
let steps = if mode == Mode::MethodCall {
|
||||||
match self.create_steps(span, self_ty) {
|
match self.create_steps(span, self_ty) {
|
||||||
Some(steps) => steps,
|
Some(steps) => steps,
|
||||||
None =>return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(), Vec::new(),
|
None => {
|
||||||
Vec::new(), mode))),
|
return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(),
|
||||||
|
Vec::new(),
|
||||||
|
Vec::new(),
|
||||||
|
mode)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vec![CandidateStep {
|
vec![CandidateStep {
|
||||||
self_ty: self_ty,
|
self_ty: self_ty,
|
||||||
autoderefs: 0,
|
autoderefs: 0,
|
||||||
unsize: false
|
unsize: false,
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -174,12 +184,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let mut simplified_steps = Vec::new();
|
let mut simplified_steps = Vec::new();
|
||||||
for step in &steps {
|
for step in &steps {
|
||||||
match ty::fast_reject::simplify_type(self.tcx, step.self_ty, true) {
|
match ty::fast_reject::simplify_type(self.tcx, step.self_ty, true) {
|
||||||
None => { break; }
|
None => {
|
||||||
Some(simplified_type) => { simplified_steps.push(simplified_type); }
|
break;
|
||||||
|
}
|
||||||
|
Some(simplified_type) => {
|
||||||
|
simplified_steps.push(simplified_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let opt_simplified_steps =
|
}
|
||||||
if simplified_steps.len() < steps.len() {
|
let opt_simplified_steps = if simplified_steps.len() < steps.len() {
|
||||||
None // failed to convert at least one of the steps
|
None // failed to convert at least one of the steps
|
||||||
} else {
|
} else {
|
||||||
Some(simplified_steps)
|
Some(simplified_steps)
|
||||||
|
@ -192,31 +205,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// this creates one big transaction so that all type variables etc
|
// this creates one big transaction so that all type variables etc
|
||||||
// that we create during the probe process are removed later
|
// that we create during the probe process are removed later
|
||||||
self.probe(|_| {
|
self.probe(|_| {
|
||||||
let mut probe_cx = ProbeContext::new(self,
|
let mut probe_cx =
|
||||||
span,
|
ProbeContext::new(self, span, mode, item_name, steps, opt_simplified_steps);
|
||||||
mode,
|
|
||||||
item_name,
|
|
||||||
steps,
|
|
||||||
opt_simplified_steps);
|
|
||||||
probe_cx.assemble_inherent_candidates();
|
probe_cx.assemble_inherent_candidates();
|
||||||
probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id)?;
|
probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id)?;
|
||||||
probe_cx.pick()
|
probe_cx.pick()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_steps(&self,
|
fn create_steps(&self, span: Span, self_ty: Ty<'tcx>) -> Option<Vec<CandidateStep<'tcx>>> {
|
||||||
span: Span,
|
|
||||||
self_ty: Ty<'tcx>)
|
|
||||||
-> Option<Vec<CandidateStep<'tcx>>>
|
|
||||||
{
|
|
||||||
// FIXME: we don't need to create the entire steps in one pass
|
// FIXME: we don't need to create the entire steps in one pass
|
||||||
|
|
||||||
let mut autoderef = self.autoderef(span, self_ty);
|
let mut autoderef = self.autoderef(span, self_ty);
|
||||||
let mut steps: Vec<_> = autoderef.by_ref().map(|(ty, d)| CandidateStep {
|
let mut steps: Vec<_> = autoderef.by_ref()
|
||||||
|
.map(|(ty, d)| {
|
||||||
|
CandidateStep {
|
||||||
self_ty: ty,
|
self_ty: ty,
|
||||||
autoderefs: d,
|
autoderefs: d,
|
||||||
unsize: false
|
unsize: false,
|
||||||
}).collect();
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let final_ty = autoderef.unambiguous_final_ty();
|
let final_ty = autoderef.unambiguous_final_ty();
|
||||||
match final_ty.sty {
|
match final_ty.sty {
|
||||||
|
@ -226,7 +235,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
steps.push(CandidateStep {
|
steps.push(CandidateStep {
|
||||||
self_ty: self.tcx.mk_slice(elem_ty),
|
self_ty: self.tcx.mk_slice(elem_ty),
|
||||||
autoderefs: dereferences,
|
autoderefs: dereferences,
|
||||||
unsize: true
|
unsize: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ty::TyError => return None,
|
ty::TyError => return None,
|
||||||
|
@ -246,8 +255,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
item_name: ast::Name,
|
item_name: ast::Name,
|
||||||
steps: Vec<CandidateStep<'tcx>>,
|
steps: Vec<CandidateStep<'tcx>>,
|
||||||
opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>)
|
opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>)
|
||||||
-> ProbeContext<'a, 'gcx, 'tcx>
|
-> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
{
|
|
||||||
ProbeContext {
|
ProbeContext {
|
||||||
fcx: fcx,
|
fcx: fcx,
|
||||||
span: span,
|
span: span,
|
||||||
|
@ -284,8 +292,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
|
fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
|
||||||
debug!("assemble_probe: self_ty={:?}",
|
debug!("assemble_probe: self_ty={:?}", self_ty);
|
||||||
self_ty);
|
|
||||||
|
|
||||||
match self_ty.sty {
|
match self_ty.sty {
|
||||||
ty::TyTrait(box ref data) => {
|
ty::TyTrait(box ref data) => {
|
||||||
|
@ -371,8 +378,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
let lang_def_id = self.tcx.lang_items.f64_impl();
|
let lang_def_id = self.tcx.lang_items.f64_impl();
|
||||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +411,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let item = match self.impl_or_trait_item(impl_def_id) {
|
let item = match self.impl_or_trait_item(impl_def_id) {
|
||||||
Some(m) => m,
|
Some(m) => m,
|
||||||
None => { return; } // No method with correct name on this impl
|
None => {
|
||||||
|
return;
|
||||||
|
} // No method with correct name on this impl
|
||||||
};
|
};
|
||||||
|
|
||||||
if !self.has_applicable_self(&item) {
|
if !self.has_applicable_self(&item) {
|
||||||
|
@ -415,7 +423,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if !item.vis().is_accessible_from(self.body_id, &self.tcx.map) {
|
if !item.vis().is_accessible_from(self.body_id, &self.tcx.map) {
|
||||||
self.private_candidate = Some(item.def());
|
self.private_candidate = Some(item.def());
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
|
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
|
||||||
|
@ -458,9 +466,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
self.elaborate_bounds(&[trait_ref], |this, new_trait_ref, item| {
|
self.elaborate_bounds(&[trait_ref], |this, new_trait_ref, item| {
|
||||||
let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
|
let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
|
||||||
|
|
||||||
let xform_self_ty = this.xform_self_ty(&item,
|
let xform_self_ty =
|
||||||
new_trait_ref.self_ty(),
|
this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs);
|
||||||
new_trait_ref.substs);
|
|
||||||
|
|
||||||
this.inherent_candidates.push(Candidate {
|
this.inherent_candidates.push(Candidate {
|
||||||
xform_self_ty: xform_self_ty,
|
xform_self_ty: xform_self_ty,
|
||||||
|
@ -476,8 +483,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
param_ty: ty::ParamTy) {
|
param_ty: ty::ParamTy) {
|
||||||
// FIXME -- Do we want to commit to this behavior for param bounds?
|
// FIXME -- Do we want to commit to this behavior for param bounds?
|
||||||
|
|
||||||
let bounds: Vec<_> =
|
let bounds: Vec<_> = self.parameter_environment
|
||||||
self.parameter_environment.caller_bounds
|
.caller_bounds
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|predicate| {
|
.filter_map(|predicate| {
|
||||||
match *predicate {
|
match *predicate {
|
||||||
|
@ -486,7 +493,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
ty::TyParam(ref p) if *p == param_ty => {
|
ty::TyParam(ref p) if *p == param_ty => {
|
||||||
Some(trait_predicate.to_poly_trait_ref())
|
Some(trait_predicate.to_poly_trait_ref())
|
||||||
}
|
}
|
||||||
_ => None
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Predicate::Equate(..) |
|
ty::Predicate::Equate(..) |
|
||||||
|
@ -495,21 +502,15 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
ty::Predicate::WellFormed(..) |
|
ty::Predicate::WellFormed(..) |
|
||||||
ty::Predicate::ObjectSafe(..) |
|
ty::Predicate::ObjectSafe(..) |
|
||||||
ty::Predicate::ClosureKind(..) |
|
ty::Predicate::ClosureKind(..) |
|
||||||
ty::Predicate::TypeOutlives(..) => {
|
ty::Predicate::TypeOutlives(..) => None,
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.elaborate_bounds(&bounds, |this, poly_trait_ref, item| {
|
self.elaborate_bounds(&bounds, |this, poly_trait_ref, item| {
|
||||||
let trait_ref =
|
let trait_ref = this.erase_late_bound_regions(&poly_trait_ref);
|
||||||
this.erase_late_bound_regions(&poly_trait_ref);
|
|
||||||
|
|
||||||
let xform_self_ty =
|
let xform_self_ty = this.xform_self_ty(&item, trait_ref.self_ty(), trait_ref.substs);
|
||||||
this.xform_self_ty(&item,
|
|
||||||
trait_ref.self_ty(),
|
|
||||||
trait_ref.substs);
|
|
||||||
|
|
||||||
if let Some(ref m) = item.as_opt_method() {
|
if let Some(ref m) = item.as_opt_method() {
|
||||||
debug!("found match: trait_ref={:?} substs={:?} m={:?}",
|
debug!("found match: trait_ref={:?} substs={:?} m={:?}",
|
||||||
|
@ -540,16 +541,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Do a search through a list of bounds, using a callback to actually
|
// Do a search through a list of bounds, using a callback to actually
|
||||||
// create the candidates.
|
// create the candidates.
|
||||||
fn elaborate_bounds<F>(
|
fn elaborate_bounds<F>(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F)
|
||||||
&mut self,
|
where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>,
|
||||||
bounds: &[ty::PolyTraitRef<'tcx>],
|
|
||||||
mut mk_cand: F,
|
|
||||||
) where
|
|
||||||
F: for<'b> FnMut(
|
|
||||||
&mut ProbeContext<'b, 'gcx, 'tcx>,
|
|
||||||
ty::PolyTraitRef<'tcx>,
|
ty::PolyTraitRef<'tcx>,
|
||||||
ty::ImplOrTraitItem<'tcx>,
|
ty::ImplOrTraitItem<'tcx>)
|
||||||
),
|
|
||||||
{
|
{
|
||||||
debug!("elaborate_bounds(bounds={:?})", bounds);
|
debug!("elaborate_bounds(bounds={:?})", bounds);
|
||||||
|
|
||||||
|
@ -557,7 +552,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
|
for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
|
||||||
let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) {
|
let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => { continue; }
|
None => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !self.has_applicable_self(&item) {
|
if !self.has_applicable_self(&item) {
|
||||||
|
@ -570,8 +567,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn assemble_extension_candidates_for_traits_in_scope(&mut self,
|
fn assemble_extension_candidates_for_traits_in_scope(&mut self,
|
||||||
expr_id: ast::NodeId)
|
expr_id: ast::NodeId)
|
||||||
-> Result<(), MethodError<'tcx>>
|
-> Result<(), MethodError<'tcx>> {
|
||||||
{
|
|
||||||
let mut duplicates = FnvHashSet();
|
let mut duplicates = FnvHashSet();
|
||||||
let opt_applicable_traits = self.tcx.trait_map.get(&expr_id);
|
let opt_applicable_traits = self.tcx.trait_map.get(&expr_id);
|
||||||
if let Some(applicable_traits) = opt_applicable_traits {
|
if let Some(applicable_traits) = opt_applicable_traits {
|
||||||
|
@ -600,20 +596,19 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn assemble_extension_candidates_for_trait(&mut self,
|
fn assemble_extension_candidates_for_trait(&mut self,
|
||||||
trait_def_id: DefId)
|
trait_def_id: DefId)
|
||||||
-> Result<(), MethodError<'tcx>>
|
-> Result<(), MethodError<'tcx>> {
|
||||||
{
|
|
||||||
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})",
|
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})",
|
||||||
trait_def_id);
|
trait_def_id);
|
||||||
|
|
||||||
// Check whether `trait_def_id` defines a method with suitable name:
|
// Check whether `trait_def_id` defines a method with suitable name:
|
||||||
let trait_items =
|
let trait_items = self.tcx.trait_items(trait_def_id);
|
||||||
self.tcx.trait_items(trait_def_id);
|
let maybe_item = trait_items.iter()
|
||||||
let maybe_item =
|
|
||||||
trait_items.iter()
|
|
||||||
.find(|item| item.name() == self.item_name);
|
.find(|item| item.name() == self.item_name);
|
||||||
let item = match maybe_item {
|
let item = match maybe_item {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => { return Ok(()); }
|
None => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check whether `trait_def_id` defines a method with suitable name:
|
// Check whether `trait_def_id` defines a method with suitable name:
|
||||||
|
@ -636,8 +631,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn assemble_extension_candidates_for_trait_impls(&mut self,
|
fn assemble_extension_candidates_for_trait_impls(&mut self,
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
item: ty::ImplOrTraitItem<'tcx>)
|
item: ty::ImplOrTraitItem<'tcx>) {
|
||||||
{
|
|
||||||
let trait_def = self.tcx.lookup_trait_def(trait_def_id);
|
let trait_def = self.tcx.lookup_trait_def(trait_def_id);
|
||||||
|
|
||||||
// FIXME(arielb1): can we use for_each_relevant_impl here?
|
// FIXME(arielb1): can we use for_each_relevant_impl here?
|
||||||
|
@ -655,8 +649,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
debug!("impl_substs={:?}", impl_substs);
|
debug!("impl_substs={:?}", impl_substs);
|
||||||
|
|
||||||
let impl_trait_ref =
|
let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id)
|
||||||
self.tcx.impl_trait_ref(impl_def_id)
|
|
||||||
.unwrap() // we know this is a trait impl
|
.unwrap() // we know this is a trait impl
|
||||||
.subst(self.tcx, impl_substs);
|
.subst(self.tcx, impl_substs);
|
||||||
|
|
||||||
|
@ -664,9 +657,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Determine the receiver type that the method itself expects.
|
// Determine the receiver type that the method itself expects.
|
||||||
let xform_self_ty =
|
let xform_self_ty =
|
||||||
self.xform_self_ty(&item,
|
self.xform_self_ty(&item, impl_trait_ref.self_ty(), impl_trait_ref.substs);
|
||||||
impl_trait_ref.self_ty(),
|
|
||||||
impl_trait_ref.substs);
|
|
||||||
|
|
||||||
// Normalize the receiver. We can't use normalize_associated_types_in
|
// Normalize the receiver. We can't use normalize_associated_types_in
|
||||||
// as it will pollute the fcx's fulfillment context after this probe
|
// as it will pollute the fcx's fulfillment context after this probe
|
||||||
|
@ -690,14 +681,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
fn impl_can_possibly_match(&self, impl_def_id: DefId) -> bool {
|
fn impl_can_possibly_match(&self, impl_def_id: DefId) -> bool {
|
||||||
let simplified_steps = match self.opt_simplified_steps {
|
let simplified_steps = match self.opt_simplified_steps {
|
||||||
Some(ref simplified_steps) => simplified_steps,
|
Some(ref simplified_steps) => simplified_steps,
|
||||||
None => { return true; }
|
None => {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let impl_type = self.tcx.lookup_item_type(impl_def_id);
|
let impl_type = self.tcx.lookup_item_type(impl_def_id);
|
||||||
let impl_simplified_type =
|
let impl_simplified_type =
|
||||||
match ty::fast_reject::simplify_type(self.tcx, impl_type.ty, false) {
|
match ty::fast_reject::simplify_type(self.tcx, impl_type.ty, false) {
|
||||||
Some(simplified_type) => simplified_type,
|
Some(simplified_type) => simplified_type,
|
||||||
None => { return true; }
|
None => {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
simplified_steps.contains(&impl_simplified_type)
|
simplified_steps.contains(&impl_simplified_type)
|
||||||
|
@ -706,8 +701,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
fn assemble_closure_candidates(&mut self,
|
fn assemble_closure_candidates(&mut self,
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
item: ty::ImplOrTraitItem<'tcx>)
|
item: ty::ImplOrTraitItem<'tcx>)
|
||||||
-> Result<(), MethodError<'tcx>>
|
-> Result<(), MethodError<'tcx>> {
|
||||||
{
|
|
||||||
// Check if this is one of the Fn,FnMut,FnOnce traits.
|
// Check if this is one of the Fn,FnMut,FnOnce traits.
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let kind = if Some(trait_def_id) == tcx.lang_items.fn_trait() {
|
let kind = if Some(trait_def_id) == tcx.lang_items.fn_trait() {
|
||||||
|
@ -746,9 +740,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
// for the purposes of our method lookup, we only take
|
// for the purposes of our method lookup, we only take
|
||||||
// receiver type into account, so we can just substitute
|
// receiver type into account, so we can just substitute
|
||||||
// fresh types here to use during substitution and subtyping.
|
// fresh types here to use during substitution and subtyping.
|
||||||
let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
|
let substs = Substs::for_item(self.tcx,
|
||||||
self.region_var_for_def(self.span, def)
|
trait_def_id,
|
||||||
}, |def, substs| {
|
|def, _| self.region_var_for_def(self.span, def),
|
||||||
|
|def, substs| {
|
||||||
if def.index == 0 {
|
if def.index == 0 {
|
||||||
step.self_ty
|
step.self_ty
|
||||||
} else {
|
} else {
|
||||||
|
@ -756,9 +751,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let xform_self_ty = self.xform_self_ty(&item,
|
let xform_self_ty = self.xform_self_ty(&item, step.self_ty, substs);
|
||||||
step.self_ty,
|
|
||||||
substs);
|
|
||||||
self.inherent_candidates.push(Candidate {
|
self.inherent_candidates.push(Candidate {
|
||||||
xform_self_ty: xform_self_ty,
|
xform_self_ty: xform_self_ty,
|
||||||
item: item.clone(),
|
item: item.clone(),
|
||||||
|
@ -772,8 +765,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn assemble_projection_candidates(&mut self,
|
fn assemble_projection_candidates(&mut self,
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
item: ty::ImplOrTraitItem<'tcx>)
|
item: ty::ImplOrTraitItem<'tcx>) {
|
||||||
{
|
|
||||||
debug!("assemble_projection_candidates(\
|
debug!("assemble_projection_candidates(\
|
||||||
trait_def_id={:?}, \
|
trait_def_id={:?}, \
|
||||||
item={:?})",
|
item={:?})",
|
||||||
|
@ -781,39 +773,35 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
item);
|
item);
|
||||||
|
|
||||||
for step in self.steps.iter() {
|
for step in self.steps.iter() {
|
||||||
debug!("assemble_projection_candidates: step={:?}",
|
debug!("assemble_projection_candidates: step={:?}", step);
|
||||||
step);
|
|
||||||
|
|
||||||
let (def_id, substs) = match step.self_ty.sty {
|
let (def_id, substs) = match step.self_ty.sty {
|
||||||
ty::TyProjection(ref data) => {
|
ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs),
|
||||||
(data.trait_ref.def_id, data.trait_ref.substs)
|
|
||||||
}
|
|
||||||
ty::TyAnon(def_id, substs) => (def_id, substs),
|
ty::TyAnon(def_id, substs) => (def_id, substs),
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("assemble_projection_candidates: def_id={:?} substs={:?}",
|
debug!("assemble_projection_candidates: def_id={:?} substs={:?}",
|
||||||
def_id, substs);
|
def_id,
|
||||||
|
substs);
|
||||||
|
|
||||||
let trait_predicates = self.tcx.lookup_predicates(def_id);
|
let trait_predicates = self.tcx.lookup_predicates(def_id);
|
||||||
let bounds = trait_predicates.instantiate(self.tcx, substs);
|
let bounds = trait_predicates.instantiate(self.tcx, substs);
|
||||||
let predicates = bounds.predicates;
|
let predicates = bounds.predicates;
|
||||||
debug!("assemble_projection_candidates: predicates={:?}",
|
debug!("assemble_projection_candidates: predicates={:?}",
|
||||||
predicates);
|
predicates);
|
||||||
for poly_bound in
|
for poly_bound in traits::elaborate_predicates(self.tcx, predicates)
|
||||||
traits::elaborate_predicates(self.tcx, predicates)
|
|
||||||
.filter_map(|p| p.to_opt_poly_trait_ref())
|
.filter_map(|p| p.to_opt_poly_trait_ref())
|
||||||
.filter(|b| b.def_id() == trait_def_id)
|
.filter(|b| b.def_id() == trait_def_id) {
|
||||||
{
|
|
||||||
let bound = self.erase_late_bound_regions(&poly_bound);
|
let bound = self.erase_late_bound_regions(&poly_bound);
|
||||||
|
|
||||||
debug!("assemble_projection_candidates: def_id={:?} substs={:?} bound={:?}",
|
debug!("assemble_projection_candidates: def_id={:?} substs={:?} bound={:?}",
|
||||||
def_id, substs, bound);
|
def_id,
|
||||||
|
substs,
|
||||||
|
bound);
|
||||||
|
|
||||||
if self.can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
|
if self.can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
|
||||||
let xform_self_ty = self.xform_self_ty(&item,
|
let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs);
|
||||||
bound.self_ty(),
|
|
||||||
bound.substs);
|
|
||||||
|
|
||||||
debug!("assemble_projection_candidates: bound={:?} xform_self_ty={:?}",
|
debug!("assemble_projection_candidates: bound={:?} xform_self_ty={:?}",
|
||||||
bound,
|
bound,
|
||||||
|
@ -832,20 +820,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn assemble_where_clause_candidates(&mut self,
|
fn assemble_where_clause_candidates(&mut self,
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
item: ty::ImplOrTraitItem<'tcx>)
|
item: ty::ImplOrTraitItem<'tcx>) {
|
||||||
{
|
|
||||||
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
|
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
|
||||||
trait_def_id);
|
trait_def_id);
|
||||||
|
|
||||||
let caller_predicates = self.parameter_environment.caller_bounds.clone();
|
let caller_predicates = self.parameter_environment.caller_bounds.clone();
|
||||||
for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates)
|
for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates)
|
||||||
.filter_map(|p| p.to_opt_poly_trait_ref())
|
.filter_map(|p| p.to_opt_poly_trait_ref())
|
||||||
.filter(|b| b.def_id() == trait_def_id)
|
.filter(|b| b.def_id() == trait_def_id) {
|
||||||
{
|
|
||||||
let bound = self.erase_late_bound_regions(&poly_bound);
|
let bound = self.erase_late_bound_regions(&poly_bound);
|
||||||
let xform_self_ty = self.xform_self_ty(&item,
|
let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs);
|
||||||
bound.self_ty(),
|
|
||||||
bound.substs);
|
|
||||||
|
|
||||||
debug!("assemble_where_clause_candidates: bound={:?} xform_self_ty={:?}",
|
debug!("assemble_where_clause_candidates: bound={:?} xform_self_ty={:?}",
|
||||||
bound,
|
bound,
|
||||||
|
@ -882,19 +866,24 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let out_of_scope_traits = match self.pick_core() {
|
let out_of_scope_traits = match self.pick_core() {
|
||||||
Some(Ok(p)) => vec![p.item.container().id()],
|
Some(Ok(p)) => vec![p.item.container().id()],
|
||||||
Some(Err(MethodError::Ambiguity(v))) => v.into_iter().map(|source| {
|
Some(Err(MethodError::Ambiguity(v))) => {
|
||||||
|
v.into_iter()
|
||||||
|
.map(|source| {
|
||||||
match source {
|
match source {
|
||||||
TraitSource(id) => id,
|
TraitSource(id) => id,
|
||||||
ImplSource(impl_id) => {
|
ImplSource(impl_id) => {
|
||||||
match tcx.trait_id_of_impl(impl_id) {
|
match tcx.trait_id_of_impl(impl_id) {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
None =>
|
None => {
|
||||||
span_bug!(span,
|
span_bug!(span,
|
||||||
"found inherent method when looking at traits")
|
"found inherent method when looking at traits")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).collect(),
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
Some(Err(MethodError::NoMatch(NoMatchData { out_of_scope_traits: others, .. }))) => {
|
Some(Err(MethodError::NoMatch(NoMatchData { out_of_scope_traits: others, .. }))) => {
|
||||||
assert!(others.is_empty());
|
assert!(others.is_empty());
|
||||||
vec![]
|
vec![]
|
||||||
|
@ -910,8 +899,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
return Err(MethodError::PrivateMatch(def));
|
return Err(MethodError::PrivateMatch(def));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(MethodError::NoMatch(NoMatchData::new(static_candidates, unsatisfied_predicates,
|
Err(MethodError::NoMatch(NoMatchData::new(static_candidates,
|
||||||
out_of_scope_traits, self.mode)))
|
unsatisfied_predicates,
|
||||||
|
out_of_scope_traits,
|
||||||
|
self.mode)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
|
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
|
||||||
|
@ -935,25 +926,21 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
self.pick_autorefd_method(step)
|
self.pick_autorefd_method(step)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pick_by_value_method(&mut self,
|
fn pick_by_value_method(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
|
||||||
step: &CandidateStep<'tcx>)
|
//! For each type `T` in the step list, this attempts to find a
|
||||||
-> Option<PickResult<'tcx>>
|
//! method where the (transformed) self type is exactly `T`. We
|
||||||
{
|
//! do however do one transformation on the adjustment: if we
|
||||||
/*!
|
//! are passing a region pointer in, we will potentially
|
||||||
* For each type `T` in the step list, this attempts to find a
|
//! *reborrow* it to a shorter lifetime. This allows us to
|
||||||
* method where the (transformed) self type is exactly `T`. We
|
//! transparently pass `&mut` pointers, in particular, without
|
||||||
* do however do one transformation on the adjustment: if we
|
//! consuming them for their entire lifetime.
|
||||||
* are passing a region pointer in, we will potentially
|
|
||||||
* *reborrow* it to a shorter lifetime. This allows us to
|
|
||||||
* transparently pass `&mut` pointers, in particular, without
|
|
||||||
* consuming them for their entire lifetime.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if step.unsize {
|
if step.unsize {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pick_method(step.self_ty).map(|r| r.map(|mut pick| {
|
self.pick_method(step.self_ty).map(|r| {
|
||||||
|
r.map(|mut pick| {
|
||||||
pick.autoderefs = step.autoderefs;
|
pick.autoderefs = step.autoderefs;
|
||||||
|
|
||||||
// Insert a `&*` or `&mut *` if this is a reference type:
|
// Insert a `&*` or `&mut *` if this is a reference type:
|
||||||
|
@ -963,13 +950,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pick
|
pick
|
||||||
}))
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pick_autorefd_method(&mut self,
|
fn pick_autorefd_method(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
|
||||||
step: &CandidateStep<'tcx>)
|
|
||||||
-> Option<PickResult<'tcx>>
|
|
||||||
{
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
// In general, during probing we erase regions. See
|
// In general, during probing we erase regions. See
|
||||||
|
@ -977,12 +962,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
let region = tcx.mk_region(ty::ReErased);
|
let region = tcx.mk_region(ty::ReErased);
|
||||||
|
|
||||||
// Search through mutabilities in order to find one where pick works:
|
// Search through mutabilities in order to find one where pick works:
|
||||||
[hir::MutImmutable, hir::MutMutable].iter().filter_map(|&m| {
|
[hir::MutImmutable, hir::MutMutable]
|
||||||
let autoref_ty = tcx.mk_ref(region, ty::TypeAndMut {
|
.iter()
|
||||||
|
.filter_map(|&m| {
|
||||||
|
let autoref_ty = tcx.mk_ref(region,
|
||||||
|
ty::TypeAndMut {
|
||||||
ty: step.self_ty,
|
ty: step.self_ty,
|
||||||
mutbl: m
|
mutbl: m,
|
||||||
});
|
});
|
||||||
self.pick_method(autoref_ty).map(|r| r.map(|mut pick| {
|
self.pick_method(autoref_ty).map(|r| {
|
||||||
|
r.map(|mut pick| {
|
||||||
pick.autoderefs = step.autoderefs;
|
pick.autoderefs = step.autoderefs;
|
||||||
pick.autoref = Some(m);
|
pick.autoref = Some(m);
|
||||||
pick.unsize = if step.unsize {
|
pick.unsize = if step.unsize {
|
||||||
|
@ -991,8 +980,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
pick
|
pick
|
||||||
}))
|
})
|
||||||
}).nth(0)
|
})
|
||||||
|
})
|
||||||
|
.nth(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
|
fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
|
||||||
|
@ -1008,7 +999,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("searching extension candidates");
|
debug!("searching extension candidates");
|
||||||
let res = self.consider_candidates(self_ty, &self.extension_candidates,
|
let res = self.consider_candidates(self_ty,
|
||||||
|
&self.extension_candidates,
|
||||||
&mut possibly_unsatisfied_predicates);
|
&mut possibly_unsatisfied_predicates);
|
||||||
if let None = res {
|
if let None = res {
|
||||||
self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
|
self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
|
||||||
|
@ -1021,17 +1013,17 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
probes: &[Candidate<'tcx>],
|
probes: &[Candidate<'tcx>],
|
||||||
possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>)
|
possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>)
|
||||||
-> Option<PickResult<'tcx>> {
|
-> Option<PickResult<'tcx>> {
|
||||||
let mut applicable_candidates: Vec<_> =
|
let mut applicable_candidates: Vec<_> = probes.iter()
|
||||||
probes.iter()
|
.filter(|&probe| self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
|
||||||
.filter(|&probe| self.consider_probe(self_ty,
|
|
||||||
probe,possibly_unsatisfied_predicates))
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
debug!("applicable_candidates: {:?}", applicable_candidates);
|
debug!("applicable_candidates: {:?}", applicable_candidates);
|
||||||
|
|
||||||
if applicable_candidates.len() > 1 {
|
if applicable_candidates.len() > 1 {
|
||||||
match self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) {
|
match self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) {
|
||||||
Some(pick) => { return Some(Ok(pick)); }
|
Some(pick) => {
|
||||||
|
return Some(Ok(pick));
|
||||||
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1041,21 +1033,22 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
return Some(Err(MethodError::Ambiguity(sources)));
|
return Some(Err(MethodError::Ambiguity(sources)));
|
||||||
}
|
}
|
||||||
|
|
||||||
applicable_candidates.pop().map(|probe| {
|
applicable_candidates.pop().map(|probe| Ok(probe.to_unadjusted_pick()))
|
||||||
Ok(probe.to_unadjusted_pick())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consider_probe(&self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>,
|
fn consider_probe(&self,
|
||||||
possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>) -> bool {
|
self_ty: Ty<'tcx>,
|
||||||
debug!("consider_probe: self_ty={:?} probe={:?}",
|
probe: &Candidate<'tcx>,
|
||||||
self_ty,
|
possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>)
|
||||||
probe);
|
-> bool {
|
||||||
|
debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe);
|
||||||
|
|
||||||
self.probe(|_| {
|
self.probe(|_| {
|
||||||
// First check that the self type can be related.
|
// First check that the self type can be related.
|
||||||
match self.sub_types(false, TypeOrigin::Misc(DUMMY_SP),
|
match self.sub_types(false,
|
||||||
self_ty, probe.xform_self_ty) {
|
TypeOrigin::Misc(DUMMY_SP),
|
||||||
|
self_ty,
|
||||||
|
probe.xform_self_ty) {
|
||||||
Ok(InferOk { obligations, .. }) => {
|
Ok(InferOk { obligations, .. }) => {
|
||||||
// FIXME(#32730) propagate obligations
|
// FIXME(#32730) propagate obligations
|
||||||
assert!(obligations.is_empty())
|
assert!(obligations.is_empty())
|
||||||
|
@ -1093,14 +1086,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
// Check whether the impl imposes obligations we have to worry about.
|
// Check whether the impl imposes obligations we have to worry about.
|
||||||
let impl_bounds = self.tcx.lookup_predicates(impl_def_id);
|
let impl_bounds = self.tcx.lookup_predicates(impl_def_id);
|
||||||
let impl_bounds = impl_bounds.instantiate(self.tcx, substs);
|
let impl_bounds = impl_bounds.instantiate(self.tcx, substs);
|
||||||
let traits::Normalized { value: impl_bounds,
|
let traits::Normalized { value: impl_bounds, obligations: norm_obligations } =
|
||||||
obligations: norm_obligations } =
|
|
||||||
traits::normalize(selcx, cause.clone(), &impl_bounds);
|
traits::normalize(selcx, cause.clone(), &impl_bounds);
|
||||||
|
|
||||||
// Convert the bounds into obligations.
|
// Convert the bounds into obligations.
|
||||||
let obligations =
|
let obligations = traits::predicates_for_generics(cause.clone(), &impl_bounds);
|
||||||
traits::predicates_for_generics(cause.clone(),
|
|
||||||
&impl_bounds);
|
|
||||||
debug!("impl_obligations={:?}", obligations);
|
debug!("impl_obligations={:?}", obligations);
|
||||||
|
|
||||||
// Evaluate those obligations to see if they might possibly hold.
|
// Evaluate those obligations to see if they might possibly hold.
|
||||||
|
@ -1136,14 +1126,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
///
|
///
|
||||||
/// Now imagine the receiver is `Vec<_>`. It doesn't really matter at this time which impl we
|
/// Now imagine the receiver is `Vec<_>`. It doesn't really matter at this time which impl we
|
||||||
/// use, so it's ok to just commit to "using the method from the trait Foo".
|
/// use, so it's ok to just commit to "using the method from the trait Foo".
|
||||||
fn collapse_candidates_to_trait_pick(&self,
|
fn collapse_candidates_to_trait_pick(&self, probes: &[&Candidate<'tcx>]) -> Option<Pick<'tcx>> {
|
||||||
probes: &[&Candidate<'tcx>])
|
|
||||||
-> Option<Pick<'tcx>> {
|
|
||||||
// Do all probes correspond to the same trait?
|
// Do all probes correspond to the same trait?
|
||||||
let container = probes[0].item.container();
|
let container = probes[0].item.container();
|
||||||
match container {
|
match container {
|
||||||
ty::TraitContainer(_) => {}
|
ty::TraitContainer(_) => {}
|
||||||
ty::ImplContainer(_) => return None
|
ty::ImplContainer(_) => return None,
|
||||||
}
|
}
|
||||||
if probes[1..].iter().any(|p| p.item.container() != container) {
|
if probes[1..].iter().any(|p| p.item.container() != container) {
|
||||||
return None;
|
return None;
|
||||||
|
@ -1156,7 +1144,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
import_id: probes[0].import_id,
|
import_id: probes[0].import_id,
|
||||||
autoderefs: 0,
|
autoderefs: 0,
|
||||||
autoref: None,
|
autoref: None,
|
||||||
unsize: None
|
unsize: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1165,13 +1153,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
fn has_applicable_self(&self, item: &ty::ImplOrTraitItem) -> bool {
|
fn has_applicable_self(&self, item: &ty::ImplOrTraitItem) -> bool {
|
||||||
// "fast track" -- check for usage of sugar
|
// "fast track" -- check for usage of sugar
|
||||||
match *item {
|
match *item {
|
||||||
ty::ImplOrTraitItem::MethodTraitItem(ref method) =>
|
ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
|
||||||
match method.explicit_self {
|
match method.explicit_self {
|
||||||
ty::ExplicitSelfCategory::Static => self.mode == Mode::Path,
|
ty::ExplicitSelfCategory::Static => self.mode == Mode::Path,
|
||||||
ty::ExplicitSelfCategory::ByValue |
|
ty::ExplicitSelfCategory::ByValue |
|
||||||
ty::ExplicitSelfCategory::ByReference(..) |
|
ty::ExplicitSelfCategory::ByReference(..) |
|
||||||
ty::ExplicitSelfCategory::ByBox => true,
|
ty::ExplicitSelfCategory::ByBox => true,
|
||||||
},
|
}
|
||||||
|
}
|
||||||
ty::ImplOrTraitItem::ConstTraitItem(..) => self.mode == Mode::Path,
|
ty::ImplOrTraitItem::ConstTraitItem(..) => self.mode == Mode::Path,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -1191,11 +1180,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
item: &ty::ImplOrTraitItem<'tcx>,
|
item: &ty::ImplOrTraitItem<'tcx>,
|
||||||
impl_ty: Ty<'tcx>,
|
impl_ty: Ty<'tcx>,
|
||||||
substs: &Substs<'tcx>)
|
substs: &Substs<'tcx>)
|
||||||
-> Ty<'tcx>
|
-> Ty<'tcx> {
|
||||||
{
|
|
||||||
match item.as_opt_method() {
|
match item.as_opt_method() {
|
||||||
Some(ref method) => self.xform_method_self_ty(method, impl_ty,
|
Some(ref method) => self.xform_method_self_ty(method, impl_ty, substs),
|
||||||
substs),
|
|
||||||
None => impl_ty,
|
None => impl_ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1204,8 +1191,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
method: &Rc<ty::Method<'tcx>>,
|
method: &Rc<ty::Method<'tcx>>,
|
||||||
impl_ty: Ty<'tcx>,
|
impl_ty: Ty<'tcx>,
|
||||||
substs: &Substs<'tcx>)
|
substs: &Substs<'tcx>)
|
||||||
-> Ty<'tcx>
|
-> Ty<'tcx> {
|
||||||
{
|
|
||||||
debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
|
debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
|
||||||
impl_ty,
|
impl_ty,
|
||||||
method.fty.sig.0.inputs.get(0),
|
method.fty.sig.0.inputs.get(0),
|
||||||
|
@ -1218,8 +1204,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
// are given do not include type/lifetime parameters for the
|
// are given do not include type/lifetime parameters for the
|
||||||
// method yet. So create fresh variables here for those too,
|
// method yet. So create fresh variables here for those too,
|
||||||
// if there are any.
|
// if there are any.
|
||||||
assert_eq!(substs.types().count(), method.generics.parent_types as usize);
|
assert_eq!(substs.types().count(),
|
||||||
assert_eq!(substs.regions().count(), method.generics.parent_regions as usize);
|
method.generics.parent_types as usize);
|
||||||
|
assert_eq!(substs.regions().count(),
|
||||||
|
method.generics.parent_regions as usize);
|
||||||
|
|
||||||
if self.mode == Mode::Path {
|
if self.mode == Mode::Path {
|
||||||
return impl_ty;
|
return impl_ty;
|
||||||
|
@ -1233,7 +1221,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
if method.generics.types.is_empty() && method.generics.regions.is_empty() {
|
if method.generics.types.is_empty() && method.generics.regions.is_empty() {
|
||||||
xform_self_ty.subst(self.tcx, substs)
|
xform_self_ty.subst(self.tcx, substs)
|
||||||
} else {
|
} else {
|
||||||
let substs = Substs::for_item(self.tcx, method.def_id, |def, _| {
|
let substs = Substs::for_item(self.tcx,
|
||||||
|
method.def_id,
|
||||||
|
|def, _| {
|
||||||
let i = def.index as usize;
|
let i = def.index as usize;
|
||||||
if i < substs.params().len() {
|
if i < substs.params().len() {
|
||||||
substs.region_at(i)
|
substs.region_at(i)
|
||||||
|
@ -1242,7 +1232,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
// `impl_self_ty()` for an explanation.
|
// `impl_self_ty()` for an explanation.
|
||||||
self.tcx.mk_region(ty::ReErased)
|
self.tcx.mk_region(ty::ReErased)
|
||||||
}
|
}
|
||||||
}, |def, cur_substs| {
|
},
|
||||||
|
|def, cur_substs| {
|
||||||
let i = def.index as usize;
|
let i = def.index as usize;
|
||||||
if i < substs.params().len() {
|
if i < substs.params().len() {
|
||||||
substs.type_at(i)
|
substs.type_at(i)
|
||||||
|
@ -1255,13 +1246,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the type of an impl and generate substitutions with placeholders.
|
/// Get the type of an impl and generate substitutions with placeholders.
|
||||||
fn impl_ty_and_substs(&self,
|
fn impl_ty_and_substs(&self, impl_def_id: DefId) -> (Ty<'tcx>, &'tcx Substs<'tcx>) {
|
||||||
impl_def_id: DefId)
|
|
||||||
-> (Ty<'tcx>, &'tcx Substs<'tcx>)
|
|
||||||
{
|
|
||||||
let impl_ty = self.tcx.lookup_item_type(impl_def_id).ty;
|
let impl_ty = self.tcx.lookup_item_type(impl_def_id).ty;
|
||||||
|
|
||||||
let substs = Substs::for_item(self.tcx, impl_def_id,
|
let substs = Substs::for_item(self.tcx,
|
||||||
|
impl_def_id,
|
||||||
|_, _| self.tcx.mk_region(ty::ReErased),
|
|_, _| self.tcx.mk_region(ty::ReErased),
|
||||||
|_, _| self.next_ty_var());
|
|_, _| self.next_ty_var());
|
||||||
|
|
||||||
|
@ -1294,9 +1283,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
/// Find item with name `item_name` defined in impl/trait `def_id`
|
/// Find item with name `item_name` defined in impl/trait `def_id`
|
||||||
/// and return it, or `None`, if no such item was defined there.
|
/// and return it, or `None`, if no such item was defined there.
|
||||||
fn impl_or_trait_item(&self, def_id: DefId)
|
fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::ImplOrTraitItem<'tcx>> {
|
||||||
-> Option<ty::ImplOrTraitItem<'tcx>>
|
|
||||||
{
|
|
||||||
self.fcx.impl_or_trait_item(def_id, self.item_name)
|
self.fcx.impl_or_trait_item(def_id, self.item_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1307,9 +1294,7 @@ impl<'tcx> Candidate<'tcx> {
|
||||||
item: self.item.clone(),
|
item: self.item.clone(),
|
||||||
kind: match self.kind {
|
kind: match self.kind {
|
||||||
InherentImplCandidate(..) => InherentImplPick,
|
InherentImplCandidate(..) => InherentImplPick,
|
||||||
ExtensionImplCandidate(def_id, ..) => {
|
ExtensionImplCandidate(def_id, ..) => ExtensionImplPick(def_id),
|
||||||
ExtensionImplPick(def_id)
|
|
||||||
}
|
|
||||||
ObjectCandidate => ObjectPick,
|
ObjectCandidate => ObjectPick,
|
||||||
TraitCandidate => TraitPick,
|
TraitCandidate => TraitPick,
|
||||||
WhereClauseCandidate(ref trait_ref) => {
|
WhereClauseCandidate(ref trait_ref) => {
|
||||||
|
@ -1326,15 +1311,13 @@ impl<'tcx> Candidate<'tcx> {
|
||||||
import_id: self.import_id,
|
import_id: self.import_id,
|
||||||
autoderefs: 0,
|
autoderefs: 0,
|
||||||
autoref: None,
|
autoref: None,
|
||||||
unsize: None
|
unsize: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_source(&self) -> CandidateSource {
|
fn to_source(&self) -> CandidateSource {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
InherentImplCandidate(..) => {
|
InherentImplCandidate(..) => ImplSource(self.item.container().id()),
|
||||||
ImplSource(self.item.container().id())
|
|
||||||
}
|
|
||||||
ExtensionImplCandidate(def_id, ..) => ImplSource(def_id),
|
ExtensionImplCandidate(def_id, ..) => ImplSource(def_id),
|
||||||
ObjectCandidate |
|
ObjectCandidate |
|
||||||
TraitCandidate |
|
TraitCandidate |
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
use CrateCtxt;
|
use CrateCtxt;
|
||||||
|
|
||||||
use check::{FnCtxt};
|
use check::FnCtxt;
|
||||||
use rustc::hir::map as hir_map;
|
use rustc::hir::map as hir_map;
|
||||||
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable};
|
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable};
|
||||||
use hir::def::Def;
|
use hir::def::Def;
|
||||||
|
@ -21,7 +21,7 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId};
|
||||||
use middle::lang_items::FnOnceTraitLangItem;
|
use middle::lang_items::FnOnceTraitLangItem;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::traits::{Obligation, SelectionContext};
|
use rustc::traits::{Obligation, SelectionContext};
|
||||||
use util::nodemap::{FnvHashSet};
|
use util::nodemap::FnvHashSet;
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use errors::DiagnosticBuilder;
|
use errors::DiagnosticBuilder;
|
||||||
|
@ -43,25 +43,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
// Not all of these (e.g. unsafe fns) implement FnOnce
|
// Not all of these (e.g. unsafe fns) implement FnOnce
|
||||||
// so we look for these beforehand
|
// so we look for these beforehand
|
||||||
ty::TyClosure(..) | ty::TyFnDef(..) | ty::TyFnPtr(_) => true,
|
ty::TyClosure(..) |
|
||||||
|
ty::TyFnDef(..) |
|
||||||
|
ty::TyFnPtr(_) => true,
|
||||||
// If it's not a simple function, look for things which implement FnOnce
|
// If it's not a simple function, look for things which implement FnOnce
|
||||||
_ => {
|
_ => {
|
||||||
let fn_once = match tcx.lang_items.require(FnOnceTraitLangItem) {
|
let fn_once = match tcx.lang_items.require(FnOnceTraitLangItem) {
|
||||||
Ok(fn_once) => fn_once,
|
Ok(fn_once) => fn_once,
|
||||||
Err(..) => return false
|
Err(..) => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.autoderef(span, ty).any(|(ty, _)| self.probe(|_| {
|
self.autoderef(span, ty).any(|(ty, _)| {
|
||||||
let fn_once_substs =
|
self.probe(|_| {
|
||||||
Substs::new_trait(tcx, ty, &[self.next_ty_var()]);
|
let fn_once_substs = Substs::new_trait(tcx, ty, &[self.next_ty_var()]);
|
||||||
let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
|
let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
|
||||||
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
||||||
let obligation = Obligation::misc(span,
|
let obligation =
|
||||||
self.body_id,
|
Obligation::misc(span, self.body_id, poly_trait_ref.to_predicate());
|
||||||
poly_trait_ref
|
|
||||||
.to_predicate());
|
|
||||||
SelectionContext::new(self).evaluate_obligation(&obligation)
|
SelectionContext::new(self).evaluate_obligation(&obligation)
|
||||||
}))
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,15 +72,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
rcvr_ty: Ty<'tcx>,
|
rcvr_ty: Ty<'tcx>,
|
||||||
item_name: ast::Name,
|
item_name: ast::Name,
|
||||||
rcvr_expr: Option<&hir::Expr>,
|
rcvr_expr: Option<&hir::Expr>,
|
||||||
error: MethodError<'tcx>)
|
error: MethodError<'tcx>) {
|
||||||
{
|
|
||||||
// avoid suggestions when we don't know what's going on.
|
// avoid suggestions when we don't know what's going on.
|
||||||
if rcvr_ty.references_error() {
|
if rcvr_ty.references_error() {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let report_candidates = |err: &mut DiagnosticBuilder,
|
let report_candidates = |err: &mut DiagnosticBuilder, mut sources: Vec<CandidateSource>| {
|
||||||
mut sources: Vec<CandidateSource>| {
|
|
||||||
|
|
||||||
sources.sort();
|
sources.sort();
|
||||||
sources.dedup();
|
sources.dedup();
|
||||||
|
@ -93,15 +92,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// the impl, if local to crate (item may be defaulted), else nothing.
|
// the impl, if local to crate (item may be defaulted), else nothing.
|
||||||
let item = self.impl_or_trait_item(impl_did, item_name)
|
let item = self.impl_or_trait_item(impl_did, item_name)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.impl_or_trait_item(
|
self.impl_or_trait_item(self.tcx
|
||||||
self.tcx.impl_trait_ref(impl_did).unwrap().def_id,
|
.impl_trait_ref(impl_did)
|
||||||
|
.unwrap()
|
||||||
|
.def_id,
|
||||||
|
|
||||||
item_name
|
item_name)
|
||||||
)
|
})
|
||||||
}).unwrap();
|
.unwrap();
|
||||||
let note_span = self.tcx.map.span_if_local(item.def_id()).or_else(|| {
|
let note_span = self.tcx
|
||||||
self.tcx.map.span_if_local(impl_did)
|
.map
|
||||||
});
|
.span_if_local(item.def_id())
|
||||||
|
.or_else(|| self.tcx.map.span_if_local(impl_did));
|
||||||
|
|
||||||
let impl_ty = self.impl_self_ty(span, impl_did).ty;
|
let impl_ty = self.impl_self_ty(span, impl_did).ty;
|
||||||
|
|
||||||
|
@ -128,7 +130,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
CandidateSource::TraitSource(trait_did) => {
|
CandidateSource::TraitSource(trait_did) => {
|
||||||
let item = self.impl_or_trait_item(trait_did, item_name).unwrap();
|
let item = self.impl_or_trait_item(trait_did, item_name).unwrap();
|
||||||
let item_span = self.tcx.map.def_id_span(item.def_id(), span);
|
let item_span = self.tcx.map.def_id_span(item.def_id(), span);
|
||||||
span_note!(err, item_span,
|
span_note!(err,
|
||||||
|
item_span,
|
||||||
"candidate #{} is defined in the trait `{}`",
|
"candidate #{} is defined in the trait `{}`",
|
||||||
idx + 1,
|
idx + 1,
|
||||||
self.tcx.item_path_str(trait_did));
|
self.tcx.item_path_str(trait_did));
|
||||||
|
@ -144,16 +147,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
MethodError::NoMatch(NoMatchData { static_candidates: static_sources,
|
MethodError::NoMatch(NoMatchData { static_candidates: static_sources,
|
||||||
unsatisfied_predicates,
|
unsatisfied_predicates,
|
||||||
out_of_scope_traits,
|
out_of_scope_traits,
|
||||||
mode, .. }) => {
|
mode,
|
||||||
|
.. }) => {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
let mut err = self.type_error_struct(
|
let mut err = self.type_error_struct(span,
|
||||||
span,
|
|
||||||
|actual| {
|
|actual| {
|
||||||
format!("no {} named `{}` found for type `{}` \
|
format!("no {} named `{}` found for type `{}` in the current scope",
|
||||||
in the current scope",
|
if mode == Mode::MethodCall {
|
||||||
if mode == Mode::MethodCall { "method" }
|
"method"
|
||||||
else { "associated item" },
|
} else {
|
||||||
|
"associated item"
|
||||||
|
},
|
||||||
item_name,
|
item_name,
|
||||||
actual)
|
actual)
|
||||||
},
|
},
|
||||||
|
@ -165,12 +170,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
for (ty, _) in self.autoderef(span, rcvr_ty) {
|
for (ty, _) in self.autoderef(span, rcvr_ty) {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyAdt(def, substs) if !def.is_enum() => {
|
ty::TyAdt(def, substs) if !def.is_enum() => {
|
||||||
if let Some(field) = def.struct_variant().
|
if let Some(field) = def.struct_variant()
|
||||||
find_field_named(item_name) {
|
.find_field_named(item_name) {
|
||||||
let snippet = tcx.sess.codemap().span_to_snippet(expr.span);
|
let snippet = tcx.sess.codemap().span_to_snippet(expr.span);
|
||||||
let expr_string = match snippet {
|
let expr_string = match snippet {
|
||||||
Ok(expr_string) => expr_string,
|
Ok(expr_string) => expr_string,
|
||||||
_ => "s".into() // Default to a generic placeholder for the
|
_ => "s".into(), // Default to a generic placeholder for the
|
||||||
// expression when we can't generate a
|
// expression when we can't generate a
|
||||||
// string snippet
|
// string snippet
|
||||||
};
|
};
|
||||||
|
@ -178,14 +183,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let field_ty = field.ty(tcx, substs);
|
let field_ty = field.ty(tcx, substs);
|
||||||
|
|
||||||
if self.is_fn_ty(&field_ty, span) {
|
if self.is_fn_ty(&field_ty, span) {
|
||||||
err.span_note(span, &format!(
|
err.span_note(span,
|
||||||
"use `({0}.{1})(...)` if you meant to call the \
|
&format!("use `({0}.{1})(...)` if you \
|
||||||
function stored in the `{1}` field",
|
meant to call the function \
|
||||||
expr_string, item_name));
|
stored in the `{1}` field",
|
||||||
|
expr_string,
|
||||||
|
item_name));
|
||||||
} else {
|
} else {
|
||||||
err.span_note(span, &format!(
|
err.span_note(span,
|
||||||
"did you mean to write `{0}.{1}`?",
|
&format!("did you mean to write `{0}.{1}`?",
|
||||||
expr_string, item_name));
|
expr_string,
|
||||||
|
item_name));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -206,8 +214,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
if let Some(expr) = rcvr_expr {
|
if let Some(expr) = rcvr_expr {
|
||||||
if let Ok(expr_string) = tcx.sess.codemap().span_to_snippet(expr.span) {
|
if let Ok(expr_string) = tcx.sess.codemap().span_to_snippet(expr.span) {
|
||||||
report_function!(expr.span, expr_string);
|
report_function!(expr.span, expr_string);
|
||||||
}
|
} else if let Expr_::ExprPath(_, path) = expr.node.clone() {
|
||||||
else if let Expr_::ExprPath(_, path) = expr.node.clone() {
|
|
||||||
if let Some(segment) = path.segments.last() {
|
if let Some(segment) = path.segments.last() {
|
||||||
report_function!(expr.span, segment.name);
|
report_function!(expr.span, segment.name);
|
||||||
}
|
}
|
||||||
|
@ -216,34 +223,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !static_sources.is_empty() {
|
if !static_sources.is_empty() {
|
||||||
err.note(
|
err.note("found the following associated functions; to be used as methods, \
|
||||||
"found the following associated functions; to be used as \
|
functions must have a `self` parameter");
|
||||||
methods, functions must have a `self` parameter");
|
|
||||||
|
|
||||||
report_candidates(&mut err, static_sources);
|
report_candidates(&mut err, static_sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !unsatisfied_predicates.is_empty() {
|
if !unsatisfied_predicates.is_empty() {
|
||||||
let bound_list = unsatisfied_predicates.iter()
|
let bound_list = unsatisfied_predicates.iter()
|
||||||
.map(|p| format!("`{} : {}`",
|
.map(|p| format!("`{} : {}`", p.self_ty(), p))
|
||||||
p.self_ty(),
|
|
||||||
p))
|
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
err.note(
|
err.note(&format!("the method `{}` exists but the following trait bounds \
|
||||||
&format!("the method `{}` exists but the \
|
were not satisfied: {}",
|
||||||
following trait bounds were not satisfied: {}",
|
|
||||||
item_name,
|
item_name,
|
||||||
bound_list));
|
bound_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.suggest_traits_to_import(&mut err, span, rcvr_ty, item_name,
|
self.suggest_traits_to_import(&mut err,
|
||||||
rcvr_expr, out_of_scope_traits);
|
span,
|
||||||
|
rcvr_ty,
|
||||||
|
item_name,
|
||||||
|
rcvr_expr,
|
||||||
|
out_of_scope_traits);
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodError::Ambiguity(sources) => {
|
MethodError::Ambiguity(sources) => {
|
||||||
let mut err = struct_span_err!(self.sess(), span, E0034,
|
let mut err = struct_span_err!(self.sess(),
|
||||||
|
span,
|
||||||
|
E0034,
|
||||||
"multiple applicable items in scope");
|
"multiple applicable items in scope");
|
||||||
err.span_label(span, &format!("multiple `{}` found", item_name));
|
err.span_label(span, &format!("multiple `{}` found", item_name));
|
||||||
|
|
||||||
|
@ -259,7 +268,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.tcx.item_path_str(trait_def_id));
|
self.tcx.item_path_str(trait_def_id));
|
||||||
let msg = if let Some(callee) = rcvr_expr {
|
let msg = if let Some(callee) = rcvr_expr {
|
||||||
format!("{}; use overloaded call notation instead (e.g., `{}()`)",
|
format!("{}; use overloaded call notation instead (e.g., `{}()`)",
|
||||||
msg, pprust::expr_to_string(callee))
|
msg,
|
||||||
|
pprust::expr_to_string(callee))
|
||||||
} else {
|
} else {
|
||||||
msg
|
msg
|
||||||
};
|
};
|
||||||
|
@ -279,18 +289,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
rcvr_ty: Ty<'tcx>,
|
rcvr_ty: Ty<'tcx>,
|
||||||
item_name: ast::Name,
|
item_name: ast::Name,
|
||||||
rcvr_expr: Option<&hir::Expr>,
|
rcvr_expr: Option<&hir::Expr>,
|
||||||
valid_out_of_scope_traits: Vec<DefId>)
|
valid_out_of_scope_traits: Vec<DefId>) {
|
||||||
{
|
|
||||||
if !valid_out_of_scope_traits.is_empty() {
|
if !valid_out_of_scope_traits.is_empty() {
|
||||||
let mut candidates = valid_out_of_scope_traits;
|
let mut candidates = valid_out_of_scope_traits;
|
||||||
candidates.sort();
|
candidates.sort();
|
||||||
candidates.dedup();
|
candidates.dedup();
|
||||||
let msg = format!(
|
let msg = format!("items from traits can only be used if the trait is in scope; the \
|
||||||
"items from traits can only be used if the trait is in scope; \
|
following {traits_are} implemented but not in scope, perhaps add \
|
||||||
the following {traits_are} implemented but not in scope, \
|
a `use` for {one_of_them}:",
|
||||||
perhaps add a `use` for {one_of_them}:",
|
traits_are = if candidates.len() == 1 {
|
||||||
traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
|
"trait is"
|
||||||
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"});
|
} else {
|
||||||
|
"traits are"
|
||||||
|
},
|
||||||
|
one_of_them = if candidates.len() == 1 {
|
||||||
|
"it"
|
||||||
|
} else {
|
||||||
|
"one of them"
|
||||||
|
});
|
||||||
|
|
||||||
err.help(&msg[..]);
|
err.help(&msg[..]);
|
||||||
|
|
||||||
|
@ -303,7 +319,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
if candidates.len() > limit {
|
if candidates.len() > limit {
|
||||||
err.note(&format!("and {} others", candidates.len() - limit));
|
err.note(&format!("and {} others", candidates.len() - limit));
|
||||||
}
|
}
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let type_is_local = self.type_derefs_to_local(span, rcvr_ty, rcvr_expr);
|
let type_is_local = self.type_derefs_to_local(span, rcvr_ty, rcvr_expr);
|
||||||
|
@ -319,8 +335,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// this isn't perfect (that is, there are cases when
|
// this isn't perfect (that is, there are cases when
|
||||||
// implementing a trait would be legal but is rejected
|
// implementing a trait would be legal but is rejected
|
||||||
// here).
|
// here).
|
||||||
(type_is_local || info.def_id.is_local())
|
(type_is_local || info.def_id.is_local()) &&
|
||||||
&& self.impl_or_trait_item(info.def_id, item_name).is_some()
|
self.impl_or_trait_item(info.def_id, item_name).is_some()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -332,12 +348,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// FIXME #21673 this help message could be tuned to the case
|
// FIXME #21673 this help message could be tuned to the case
|
||||||
// of a type parameter: suggest adding a trait bound rather
|
// of a type parameter: suggest adding a trait bound rather
|
||||||
// than implementing.
|
// than implementing.
|
||||||
let msg = format!(
|
let msg = format!("items from traits can only be used if the trait is implemented \
|
||||||
"items from traits can only be used if the trait is implemented and in scope; \
|
and in scope; the following {traits_define} an item `{name}`, \
|
||||||
the following {traits_define} an item `{name}`, \
|
|
||||||
perhaps you need to implement {one_of_them}:",
|
perhaps you need to implement {one_of_them}:",
|
||||||
traits_define = if candidates.len() == 1 {"trait defines"} else {"traits define"},
|
traits_define = if candidates.len() == 1 {
|
||||||
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
|
"trait defines"
|
||||||
|
} else {
|
||||||
|
"traits define"
|
||||||
|
},
|
||||||
|
one_of_them = if candidates.len() == 1 {
|
||||||
|
"it"
|
||||||
|
} else {
|
||||||
|
"one of them"
|
||||||
|
},
|
||||||
name = item_name);
|
name = item_name);
|
||||||
|
|
||||||
err.help(&msg[..]);
|
err.help(&msg[..]);
|
||||||
|
@ -355,7 +378,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
fn type_derefs_to_local(&self,
|
fn type_derefs_to_local(&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
rcvr_ty: Ty<'tcx>,
|
rcvr_ty: Ty<'tcx>,
|
||||||
rcvr_expr: Option<&hir::Expr>) -> bool {
|
rcvr_expr: Option<&hir::Expr>)
|
||||||
|
-> bool {
|
||||||
fn is_local(ty: Ty) -> bool {
|
fn is_local(ty: Ty) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyAdt(def, _) => def.did.is_local(),
|
ty::TyAdt(def, _) => def.did.is_local(),
|
||||||
|
@ -368,7 +392,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// non-local (there are "edge" cases, e.g. (LocalType,), but
|
// non-local (there are "edge" cases, e.g. (LocalType,), but
|
||||||
// the noise from these sort of types is usually just really
|
// the noise from these sort of types is usually just really
|
||||||
// annoying, rather than any sort of help).
|
// annoying, rather than any sort of help).
|
||||||
_ => false
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,9 +415,7 @@ pub struct TraitInfo {
|
||||||
|
|
||||||
impl TraitInfo {
|
impl TraitInfo {
|
||||||
fn new(def_id: DefId) -> TraitInfo {
|
fn new(def_id: DefId) -> TraitInfo {
|
||||||
TraitInfo {
|
TraitInfo { def_id: def_id }
|
||||||
def_id: def_id,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl PartialEq for TraitInfo {
|
impl PartialEq for TraitInfo {
|
||||||
|
@ -403,7 +425,9 @@ impl PartialEq for TraitInfo {
|
||||||
}
|
}
|
||||||
impl Eq for TraitInfo {}
|
impl Eq for TraitInfo {}
|
||||||
impl PartialOrd for TraitInfo {
|
impl PartialOrd for TraitInfo {
|
||||||
fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> { Some(self.cmp(other)) }
|
fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl Ord for TraitInfo {
|
impl Ord for TraitInfo {
|
||||||
fn cmp(&self, other: &TraitInfo) -> Ordering {
|
fn cmp(&self, other: &TraitInfo) -> Ordering {
|
||||||
|
@ -443,7 +467,7 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
|
||||||
}
|
}
|
||||||
ccx.tcx.map.krate().visit_all_items(&mut Visitor {
|
ccx.tcx.map.krate().visit_all_items(&mut Visitor {
|
||||||
map: &ccx.tcx.map,
|
map: &ccx.tcx.map,
|
||||||
traits: &mut traits
|
traits: &mut traits,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Cross-crate:
|
// Cross-crate:
|
||||||
|
@ -469,7 +493,10 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for cnum in ccx.tcx.sess.cstore.crates() {
|
for cnum in ccx.tcx.sess.cstore.crates() {
|
||||||
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
|
let def_id = DefId {
|
||||||
|
krate: cnum,
|
||||||
|
index: CRATE_DEF_INDEX,
|
||||||
|
};
|
||||||
handle_external_def(ccx, &mut traits, &mut external_mods, Def::Mod(def_id));
|
handle_external_def(ccx, &mut traits, &mut external_mods, Def::Mod(def_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,13 +507,13 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
|
||||||
assert!(borrow.is_some());
|
assert!(borrow.is_some());
|
||||||
AllTraits {
|
AllTraits {
|
||||||
borrow: borrow,
|
borrow: borrow,
|
||||||
idx: 0
|
idx: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AllTraits<'a> {
|
pub struct AllTraits<'a> {
|
||||||
borrow: cell::Ref<'a, Option<AllTraitsVec>>,
|
borrow: cell::Ref<'a, Option<AllTraitsVec>>,
|
||||||
idx: usize
|
idx: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for AllTraits<'a> {
|
impl<'a> Iterator for AllTraits<'a> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue