Merge branch 'master' into mb/36812_ICHFunctionInterfaces

This commit is contained in:
Mathieu Borderé 2016-10-05 23:30:55 +02:00
commit 6f6429609a
15 changed files with 649 additions and 555 deletions

View File

@ -96,6 +96,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::LogicalOp { .. } |
ExprKind::Box { .. } |
ExprKind::Cast { .. } |
ExprKind::Use { .. } |
ExprKind::NeverToAny { .. } |
ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } |

View File

@ -115,6 +115,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let source = unpack!(block = this.as_operand(block, source));
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
}
ExprKind::Use { source } => {
let source = unpack!(block = this.as_operand(block, source));
block.and(Rvalue::Use(source))
}
ExprKind::ReifyFnPointer { source } => {
let source = unpack!(block = this.as_operand(block, source));
block.and(Rvalue::Cast(CastKind::ReifyFnPointer, source, expr.ty))

View File

@ -68,6 +68,7 @@ impl Category {
ExprKind::Binary { .. } |
ExprKind::Box { .. } |
ExprKind::Cast { .. } |
ExprKind::Use { .. } |
ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } |
ExprKind::Unsize { .. } |

View File

@ -249,6 +249,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Binary { .. } |
ExprKind::Box { .. } |
ExprKind::Cast { .. } |
ExprKind::Use { .. } |
ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } |
ExprKind::Unsize { .. } |

View File

@ -600,8 +600,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// Check to see if this cast is a "coercion cast", where the cast is actually done
// using a coercion (or is a no-op).
if let Some(&TyCastKind::CoercionCast) = cx.tcx.cast_kinds.borrow().get(&source.id) {
// Skip the actual cast itexpr, as it's now a no-op.
return source.make_mirror(cx);
// Convert the lexpr to a vexpr.
ExprKind::Use { source: source.to_ref() }
} else {
ExprKind::Cast { source: source.to_ref() }
}

View File

@ -139,6 +139,9 @@ pub enum ExprKind<'tcx> {
Cast {
source: ExprRef<'tcx>,
},
Use {
source: ExprRef<'tcx>,
}, // Use a lexpr to get a vexpr.
NeverToAny {
source: ExprRef<'tcx>,
},

View File

@ -308,7 +308,16 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
_ => bug!("compare_scalar_types: must be a comparison operator"),
}
}
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyBool | ty::TyUint(_) | ty::TyChar => {
ty::TyBool => {
// FIXME(#36856) -- using `from_immediate` forces these booleans into `i8`,
// which works around some LLVM bugs
ICmp(bcx,
bin_op_to_icmp_predicate(op, false),
from_immediate(bcx, lhs),
from_immediate(bcx, rhs),
debug_loc)
}
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyUint(_) | ty::TyChar => {
ICmp(bcx,
bin_op_to_icmp_predicate(op, false),
lhs,

View File

@ -23,7 +23,7 @@ use rustc::hir;
use std::ops::Deref;
struct ConfirmContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a>{
struct ConfirmContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
span: Span,
self_expr: &'gcx hir::Expr,
@ -55,8 +55,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
unadjusted_self_ty: Ty<'tcx>,
pick: probe::Pick<'tcx>,
supplied_method_types: Vec<Ty<'tcx>>)
-> ty::MethodCallee<'tcx>
{
-> ty::MethodCallee<'tcx> {
debug!("confirm(unadjusted_self_ty={:?}, pick={:?}, supplied_method_types={:?})",
unadjusted_self_ty,
pick,
@ -72,17 +71,20 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
span: Span,
self_expr: &'gcx hir::Expr,
call_expr: &'gcx hir::Expr)
-> ConfirmContext<'a, 'gcx, 'tcx>
{
ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
-> ConfirmContext<'a, 'gcx, 'tcx> {
ConfirmContext {
fcx: fcx,
span: span,
self_expr: self_expr,
call_expr: call_expr,
}
}
fn confirm(&mut self,
unadjusted_self_ty: Ty<'tcx>,
pick: probe::Pick<'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.
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.
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
let all_substs =
self.instantiate_method_substs(
&pick,
supplied_method_types,
rcvr_substs);
let all_substs = self.instantiate_method_substs(&pick, supplied_method_types, rcvr_substs);
debug!("all_substs={:?}", all_substs);
// Create the final signature for the method, replacing late-bound regions.
let InstantiatedMethodSig {
method_sig, method_predicates
} = self.instantiate_method_sig(&pick, all_substs);
let InstantiatedMethodSig { method_sig, method_predicates } =
self.instantiate_method_sig(&pick, all_substs);
let method_self_ty = method_sig.inputs[0];
// Unify the (adjusted) self type with what the method expects.
@ -111,12 +108,13 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// Create the method type
let def_id = pick.item.def_id();
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 {
sig: ty::Binder(method_sig),
unsafety: method_ty.fty.unsafety,
abi: method_ty.fty.abi.clone(),
}));
sig: ty::Binder(method_sig),
unsafety: method_ty.fty.unsafety,
abi: method_ty.fty.abi.clone(),
}));
// Add any trait/regions obligations specified on the method's type parameters.
self.add_obligations(fty, all_substs, &method_predicates);
@ -125,7 +123,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
let callee = ty::MethodCallee {
def_id: def_id,
ty: fty,
substs: all_substs
substs: all_substs,
};
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,
unadjusted_self_ty: Ty<'tcx>,
pick: &probe::Pick<'tcx>)
-> Ty<'tcx>
{
-> Ty<'tcx> {
let (autoref, unsize) = if let Some(mutbl) = pick.autoref {
let region = self.next_region_var(infer::Autoref(self.span));
let autoref = AutoPtr(region, mutbl);
(Some(autoref), pick.unsize.map(|target| {
target.adjust_for_autoref(self.tcx, Some(autoref))
}))
(Some(autoref),
pick.unsize.map(|target| target.adjust_for_autoref(self.tcx, Some(autoref))))
} else {
// No unsizing should be performed without autoref (at
// least during method dispach). This is because we
@ -168,11 +164,12 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
autoderef.finalize(LvaluePreference::NoPreference, Some(self.self_expr));
// Write out the final adjustment.
self.write_adjustment(self.self_expr.id, AdjustDerefRef(AutoDerefRef {
autoderefs: pick.autoderefs,
autoref: autoref,
unsize: unsize
}));
self.write_adjustment(self.self_expr.id,
AdjustDerefRef(AutoDerefRef {
autoderefs: pick.autoderefs,
autoref: autoref,
unsize: unsize,
}));
if let Some(target) = unsize {
target
@ -193,13 +190,13 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
fn fresh_receiver_substs(&mut self,
self_ty: Ty<'tcx>,
pick: &probe::Pick<'tcx>)
-> &'tcx Substs<'tcx>
{
-> &'tcx Substs<'tcx> {
match pick.kind {
probe::InherentImplPick => {
let impl_def_id = pick.item.container().id();
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
}
@ -216,10 +213,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// argument type), but those cases have already
// been ruled out when we deemed the trait to be
// "object safe".
let original_poly_trait_ref =
principal.with_self_ty(this.tcx, object_ty);
let upcast_poly_trait_ref =
this.upcast(original_poly_trait_ref, trait_def_id);
let original_poly_trait_ref = principal.with_self_ty(this.tcx, object_ty);
let upcast_poly_trait_ref = this.upcast(original_poly_trait_ref, trait_def_id);
let upcast_trait_ref =
this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
@ -242,10 +237,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// the impl ([$A,$B,$C]) not the receiver type ([$C]).
let impl_polytype = self.impl_self_ty(self.span, impl_def_id);
let impl_trait_ref =
self.instantiate_type_scheme(
self.span,
impl_polytype.substs,
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
self.instantiate_type_scheme(self.span,
impl_polytype.substs,
&self.tcx.impl_trait_ref(impl_def_id).unwrap());
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,
self_ty: Ty<'tcx>,
mut closure: F) -> R
fn extract_existential_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R
where F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>,
Ty<'tcx>,
ty::PolyExistentialTraitRef<'tcx>) -> R,
ty::PolyExistentialTraitRef<'tcx>)
-> R
{
// If we specified that this is an object method, then the
// self-type ought to be something that can be dereferenced to
@ -281,7 +274,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// etc).
// FIXME: this feels, like, super dubious
self.fcx.autoderef(self.span, self_ty)
self.fcx
.autoderef(self.span, self_ty)
.filter_map(|(ty, _)| {
match ty.sty {
ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)),
@ -290,10 +284,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
})
.next()
.unwrap_or_else(|| {
span_bug!(
self.span,
"self-type `{}` for ObjectPick never dereferenced to an object",
self_ty)
span_bug!(self.span,
"self-type `{}` for ObjectPick never dereferenced to an object",
self_ty)
})
}
@ -301,8 +294,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
pick: &probe::Pick<'tcx>,
mut supplied_method_types: Vec<Ty<'tcx>>,
substs: &Substs<'tcx>)
-> &'tcx Substs<'tcx>
{
-> &'tcx Substs<'tcx> {
// Determine the values for the generic parameters of the method.
// If they were not explicitly supplied, just construct fresh
// 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_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")
.span_label(self.span, &"called with unneeded type parameters")
.emit();
} else {
struct_span_err!(self.tcx.sess, self.span, E0036,
"incorrect number of type parameters given for this method: \
expected {}, found {}",
num_method_types, num_supplied_types)
struct_span_err!(self.tcx.sess,
self.span,
E0036,
"incorrect number of type parameters given for this method: \
expected {}, found {}",
num_method_types,
num_supplied_types)
.span_label(self.span,
&format!("Passed {} type argument{}, expected {}",
num_supplied_types,
if num_supplied_types != 1 {
"s"
} else {
""
},
if num_supplied_types != 1 { "s" } else { "" },
num_method_types))
.emit();
}
@ -340,14 +333,17 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
//
// FIXME -- permit users to manually specify lifetimes
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;
if i < substs.params().len() {
substs.region_at(i)
} else {
self.region_var_for_def(self.span, def)
}
}, |def, cur_substs| {
},
|def, cur_substs| {
let i = def.index as usize;
if i < substs.params().len() {
substs.type_at(i)
@ -359,21 +355,17 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
})
}
fn unify_receivers(&mut self,
self_ty: Ty<'tcx>,
method_self_ty: Ty<'tcx>)
{
match self.sub_types(false, TypeOrigin::Misc(self.span),
self_ty, method_self_ty) {
fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
match self.sub_types(false, TypeOrigin::Misc(self.span), self_ty, method_self_ty) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
}
Err(_) => {
span_bug!(
self.span,
"{} was a subtype of {} but now is not?",
self_ty, method_self_ty);
span_bug!(self.span,
"{} was a subtype of {} but now is not?",
self_ty,
method_self_ty);
}
}
}
@ -384,8 +376,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
fn instantiate_method_sig(&mut self,
pick: &probe::Pick<'tcx>,
all_substs: &'tcx Substs<'tcx>)
-> InstantiatedMethodSig<'tcx>
{
-> InstantiatedMethodSig<'tcx> {
debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
pick,
all_substs);
@ -393,13 +384,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// Instantiate the bounds on the method with the
// type/early-bound-regions substitutions performed. There can
// be no late-bound regions appearing here.
let method_predicates = pick.item.as_opt_method().unwrap()
.predicates.instantiate(self.tcx, all_substs);
let method_predicates = self.normalize_associated_types_in(self.span,
&method_predicates);
let method_predicates = pick.item
.as_opt_method()
.unwrap()
.predicates
.instantiate(self.tcx, all_substs);
let method_predicates = self.normalize_associated_types_in(self.span, &method_predicates);
debug!("method_predicates after subst = {:?}",
method_predicates);
debug!("method_predicates after subst = {:?}", method_predicates);
// Instantiate late-bound regions and substitute the trait
// 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
// `instantiate_type_scheme` can normalize associated types that
// may reference those regions.
let method_sig = self.replace_late_bound_regions_with_fresh_var(
&pick.item.as_opt_method().unwrap().fty.sig);
let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.item
.as_opt_method()
.unwrap()
.fty
.sig);
debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
method_sig);
let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig);
debug!("type scheme substituted, method_sig={:?}",
method_sig);
debug!("type scheme substituted, method_sig={:?}", method_sig);
InstantiatedMethodSig {
method_sig: method_sig,
@ -431,9 +425,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
all_substs,
method_predicates);
self.add_obligations_for_parameters(
traits::ObligationCause::misc(self.span, self.body_id),
method_predicates);
self.add_obligations_for_parameters(traits::ObligationCause::misc(self.span, self.body_id),
method_predicates);
// this is a projection from a trait reference, so we have to
// make sure that the trait reference inputs are well-formed.
@ -472,21 +465,24 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
for (i, &expr) in exprs.iter().rev().enumerate() {
// Count autoderefs.
let autoderef_count = match self.tables
.borrow()
.adjustments
.get(&expr.id) {
.borrow()
.adjustments
.get(&expr.id) {
Some(&AdjustDerefRef(ref adj)) => adj.autoderefs,
Some(_) | None => 0,
};
debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?} \
autoderef_count={}",
i, expr, autoderef_count);
i,
expr,
autoderef_count);
if autoderef_count > 0 {
let mut autoderef = self.autoderef(expr.span, self.node_ty(expr.id));
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.finalize(PreferMutLvalue, Some(expr));
@ -508,29 +504,30 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// (ab)use the normal type checking paths.
let adj = self.tables.borrow().adjustments.get(&base_expr.id).cloned();
let (autoderefs, unsize) = match adj {
Some(AdjustDerefRef(adr)) => match adr.autoref {
None => {
assert!(adr.unsize.is_none());
(adr.autoderefs, None)
Some(AdjustDerefRef(adr)) => {
match adr.autoref {
None => {
assert!(adr.unsize.is_none());
(adr.autoderefs, None)
}
Some(AutoPtr(..)) => {
(adr.autoderefs,
adr.unsize.map(|target| {
target.builtin_deref(false, NoPreference)
.expect("fixup: AutoPtr is not &T")
.ty
}))
}
Some(_) => {
span_bug!(base_expr.span,
"unexpected adjustment autoref {:?}",
adr);
}
}
Some(AutoPtr(..)) => {
(adr.autoderefs, adr.unsize.map(|target| {
target.builtin_deref(false, NoPreference)
.expect("fixup: AutoPtr is not &T").ty
}))
}
Some(_) => {
span_bug!(
base_expr.span,
"unexpected adjustment autoref {:?}",
adr);
}
},
}
None => (0, None),
Some(_) => {
span_bug!(
base_expr.span,
"unexpected adjustment type");
span_bug!(base_expr.span, "unexpected adjustment type");
}
};
@ -538,23 +535,23 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
(target, true)
} else {
(self.adjust_expr_ty(base_expr,
Some(&AdjustDerefRef(AutoDerefRef {
autoderefs: autoderefs,
autoref: None,
unsize: None
}))), false)
Some(&AdjustDerefRef(AutoDerefRef {
autoderefs: autoderefs,
autoref: None,
unsize: None,
}))),
false)
};
let index_expr_ty = self.node_ty(index_expr.id);
let result = self.try_index_step(
ty::MethodCall::expr(expr.id),
expr,
&base_expr,
adjusted_base_ty,
autoderefs,
unsize,
PreferMutLvalue,
index_expr_ty);
let result = self.try_index_step(ty::MethodCall::expr(expr.id),
expr,
&base_expr,
adjusted_base_ty,
autoderefs,
unsize,
PreferMutLvalue,
index_expr_ty);
if let Some((input_ty, return_ty)) = result {
self.demand_suptype(index_expr.span, input_ty, index_expr_ty);
@ -569,9 +566,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
let method_call = ty::MethodCall::expr(expr.id);
if self.tables.borrow().method_map.contains_key(&method_call) {
let method = self.try_overloaded_deref(expr.span,
Some(&base_expr),
self.node_ty(base_expr.id),
PreferMutLvalue);
Some(&base_expr),
self.node_ty(base_expr.id),
PreferMutLvalue);
let method = method.expect("re-trying deref failed");
self.tables.borrow_mut().method_map.insert(method_call, method);
}
@ -597,28 +594,27 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
fn upcast(&mut self,
source_trait_ref: ty::PolyTraitRef<'tcx>,
target_trait_def_id: DefId)
-> ty::PolyTraitRef<'tcx>
{
let upcast_trait_refs = self.tcx.upcast_choices(source_trait_ref.clone(),
target_trait_def_id);
-> ty::PolyTraitRef<'tcx> {
let upcast_trait_refs = self.tcx
.upcast_choices(source_trait_ref.clone(), target_trait_def_id);
// must be exactly one trait ref or we'd get an ambig error etc
if upcast_trait_refs.len() != 1 {
span_bug!(
self.span,
"cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
source_trait_ref,
target_trait_def_id,
upcast_trait_refs);
span_bug!(self.span,
"cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
source_trait_ref,
target_trait_def_id,
upcast_trait_refs);
}
upcast_trait_refs.into_iter().next().unwrap()
}
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.span, infer::FnCall, value).0
self.fcx
.replace_late_bound_regions_with_fresh_var(self.span, infer::FnCall, value)
.0
}
}

View File

@ -41,7 +41,8 @@ pub enum MethodError<'tcx> {
Ambiguity(Vec<CandidateSource>),
// 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.
PrivateMatch(Def),
@ -53,19 +54,20 @@ pub struct NoMatchData<'tcx> {
pub static_candidates: Vec<CandidateSource>,
pub unsatisfied_predicates: Vec<TraitRef<'tcx>>,
pub out_of_scope_traits: Vec<DefId>,
pub mode: probe::Mode
pub mode: probe::Mode,
}
impl<'tcx> NoMatchData<'tcx> {
pub fn new(static_candidates: Vec<CandidateSource>,
unsatisfied_predicates: Vec<TraitRef<'tcx>>,
out_of_scope_traits: Vec<DefId>,
mode: probe::Mode) -> Self {
mode: probe::Mode)
-> Self {
NoMatchData {
static_candidates: static_candidates,
unsatisfied_predicates: unsatisfied_predicates,
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)]
pub enum CandidateSource {
ImplSource(DefId),
TraitSource(/* trait id */ DefId),
TraitSource(// trait id
DefId),
}
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>,
call_expr_id: ast::NodeId,
allow_private: bool)
-> bool
{
-> bool {
let mode = probe::Mode::MethodCall;
match self.probe_method(span, mode, method_name, self_ty, call_expr_id) {
Ok(..) => true,
@ -119,8 +121,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
supplied_method_types: Vec<ty::Ty<'tcx>>,
call_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={:?})",
method_name,
self_ty,
@ -135,7 +136,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
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,
@ -145,10 +151,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
trait_def_id: DefId,
self_ty: ty::Ty<'tcx>,
opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
-> Option<ty::MethodCallee<'tcx>>
{
self.lookup_method_in_trait_adjusted(span, self_expr, m_name, trait_def_id,
0, false, self_ty, opt_input_types)
-> Option<ty::MethodCallee<'tcx>> {
self.lookup_method_in_trait_adjusted(span,
self_expr,
m_name,
trait_def_id,
0,
false,
self_ty,
opt_input_types)
}
/// `lookup_in_trait_adjusted` is used for overloaded operators.
@ -171,8 +182,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
unsize: bool,
self_ty: 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={:?}, \
m_name={}, trait_def_id={:?})",
self_ty,
@ -188,9 +198,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
assert!(trait_def.generics.regions.is_empty());
// Construct a trait-reference `self_ty : Trait<input_tys>`
let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
self.region_var_for_def(span, def)
}, |def, substs| {
let substs = Substs::for_item(self.tcx,
trait_def_id,
|def, _| self.region_var_for_def(span, def),
|def, substs| {
if def.index == 0 {
self_ty
} 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
let poly_trait_ref = trait_ref.to_poly_trait_ref();
let obligation = traits::Obligation::misc(span,
self.body_id,
poly_trait_ref.to_predicate());
let obligation =
traits::Obligation::misc(span, self.body_id, poly_trait_ref.to_predicate());
// Now we want to know if this can be matched
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);
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
// parameters into the method type to get the actual method type.
@ -232,18 +243,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// NB: Instantiate late-bound regions first so that
// `instantiate_type_scheme` can normalize associated types that
// may reference those regions.
let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
infer::FnCall,
&method_ty.fty.sig).0;
let fn_sig =
self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &method_ty.fty.sig)
.0;
let fn_sig = self.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
let transformed_self_ty = fn_sig.inputs[0];
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 {
sig: ty::Binder(fn_sig),
unsafety: method_ty.fty.unsafety,
abi: method_ty.fty.abi.clone(),
}));
sig: ty::Binder(fn_sig),
unsafety: method_ty.fty.unsafety,
abi: method_ty.fty.abi.clone(),
}));
debug!("lookup_in_trait_adjusted: matched method fty={:?} obligation={:?}",
fty,
@ -259,9 +271,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// any late-bound regions appearing in its bounds.
let method_bounds = self.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates);
assert!(!method_bounds.has_escaping_regions());
self.add_obligations_for_parameters(
traits::ObligationCause::misc(span, self.body_id),
&method_bounds);
self.add_obligations_for_parameters(traits::ObligationCause::misc(span, self.body_id),
&method_bounds);
// Also register an obligation for the method type being well-formed.
self.register_wf_obligation(fty, span, traits::MiscObligation);
@ -273,12 +284,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Insert any adjustments needed (always an autoref of some mutability).
match self_expr {
None => { }
None => {}
Some(self_expr) => {
debug!("lookup_in_trait_adjusted: inserting adjustment if needed \
(self-id={}, autoderefs={}, unsize={}, explicit_self={:?})",
self_expr.id, autoderefs, unsize,
self_expr.id,
autoderefs,
unsize,
method_ty.explicit_self);
match method_ty.explicit_self {
@ -294,31 +307,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match transformed_self_ty.sty {
ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => {
self.write_adjustment(self_expr.id,
AdjustDerefRef(AutoDerefRef {
autoderefs: autoderefs,
autoref: Some(AutoPtr(region, mutbl)),
unsize: if unsize {
Some(transformed_self_ty)
} else {
None
}
}));
AdjustDerefRef(AutoDerefRef {
autoderefs: autoderefs,
autoref: Some(AutoPtr(region, mutbl)),
unsize: if unsize {
Some(transformed_self_ty)
} else {
None
},
}));
}
_ => {
span_bug!(
span,
"trait method is &self but first arg is: {}",
transformed_self_ty);
span_bug!(span,
"trait method is &self but first arg is: {}",
transformed_self_ty);
}
}
}
_ => {
span_bug!(
span,
"unexpected explicit self type in operator method: {:?}",
method_ty.explicit_self);
span_bug!(span,
"unexpected explicit self type in operator method: {:?}",
method_ty.explicit_self);
}
}
}
@ -327,7 +338,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let callee = ty::MethodCallee {
def_id: def_id,
ty: fty,
substs: trait_ref.substs
substs: trait_ref.substs,
};
debug!("callee = {:?}", callee);
@ -340,8 +351,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
method_name: ast::Name,
self_ty: ty::Ty<'tcx>,
expr_id: ast::NodeId)
-> Result<Def, MethodError<'tcx>>
{
-> Result<Def, MethodError<'tcx>> {
let mode = probe::Mode::Path;
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,
def_id: DefId,
item_name: ast::Name)
-> Option<ty::ImplOrTraitItem<'tcx>>
{
self.tcx.impl_or_trait_items(def_id)
-> Option<ty::ImplOrTraitItem<'tcx>> {
self.tcx
.impl_or_trait_items(def_id)
.iter()
.map(|&did| self.tcx.impl_or_trait_item(did))
.find(|m| m.name() == item_name)

View File

@ -13,7 +13,7 @@ use super::NoMatchData;
use super::{CandidateSource, ImplSource, TraitSource};
use super::suggest;
use check::{FnCtxt};
use check::FnCtxt;
use hir::def_id::DefId;
use hir::def::Def;
use rustc::ty::subst::{Subst, Substs};
@ -31,7 +31,7 @@ use std::rc::Rc;
use self::CandidateKind::*;
pub use self::PickKind::*;
struct ProbeContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
span: Span,
mode: Mode,
@ -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
/// for error reporting
unsatisfied_predicates: Vec<TraitRef<'tcx>>
unsatisfied_predicates: Vec<TraitRef<'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> {
self_ty: Ty<'tcx>,
autoderefs: usize,
unsize: bool
unsize: bool,
}
#[derive(Debug)]
@ -80,12 +80,17 @@ struct Candidate<'tcx> {
#[derive(Debug)]
enum CandidateKind<'tcx> {
InherentImplCandidate(&'tcx Substs<'tcx>,
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
ExtensionImplCandidate(/* Impl */ DefId, &'tcx Substs<'tcx>,
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
// Normalize obligations
Vec<traits::PredicateObligation<'tcx>>),
ExtensionImplCandidate(// Impl
DefId,
&'tcx Substs<'tcx>,
// Normalize obligations
Vec<traits::PredicateObligation<'tcx>>),
ObjectCandidate,
TraitCandidate,
WhereClauseCandidate(/* Trait */ ty::PolyTraitRef<'tcx>),
WhereClauseCandidate(// Trait
ty::PolyTraitRef<'tcx>),
}
#[derive(Debug)]
@ -115,10 +120,12 @@ pub struct Pick<'tcx> {
#[derive(Clone,Debug)]
pub enum PickKind<'tcx> {
InherentImplPick,
ExtensionImplPick(/* Impl */ DefId),
ExtensionImplPick(// Impl
DefId),
ObjectPick,
TraitPick,
WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>),
WhereClausePick(// Trait
ty::PolyTraitRef<'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`.
// No autoderefs are performed, lookup is done based on the type each
// implementation is for, and static methods are included.
Path
Path,
}
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
@ -142,8 +149,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
item_name: ast::Name,
self_ty: Ty<'tcx>,
scope_expr_id: ast::NodeId)
-> PickResult<'tcx>
{
-> PickResult<'tcx> {
debug!("probe(self_ty={:?}, item_name={}, scope_expr_id={})",
self_ty,
item_name,
@ -159,31 +165,38 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let steps = if mode == Mode::MethodCall {
match self.create_steps(span, self_ty) {
Some(steps) => steps,
None =>return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(), Vec::new(),
Vec::new(), mode))),
None => {
return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(),
Vec::new(),
Vec::new(),
mode)))
}
}
} else {
vec![CandidateStep {
self_ty: self_ty,
autoderefs: 0,
unsize: false
}]
self_ty: self_ty,
autoderefs: 0,
unsize: false,
}]
};
// Create a list of simplified self types, if we can.
let mut simplified_steps = Vec::new();
for step in &steps {
match ty::fast_reject::simplify_type(self.tcx, step.self_ty, true) {
None => { break; }
Some(simplified_type) => { simplified_steps.push(simplified_type); }
None => {
break;
}
Some(simplified_type) => {
simplified_steps.push(simplified_type);
}
}
}
let opt_simplified_steps =
if simplified_steps.len() < steps.len() {
None // failed to convert at least one of the steps
} else {
Some(simplified_steps)
};
let opt_simplified_steps = if simplified_steps.len() < steps.len() {
None // failed to convert at least one of the steps
} else {
Some(simplified_steps)
};
debug!("ProbeContext: steps for self_ty={:?} are {:?}",
self_ty,
@ -192,31 +205,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// this creates one big transaction so that all type variables etc
// that we create during the probe process are removed later
self.probe(|_| {
let mut probe_cx = ProbeContext::new(self,
span,
mode,
item_name,
steps,
opt_simplified_steps);
let mut probe_cx =
ProbeContext::new(self, span, mode, item_name, steps, opt_simplified_steps);
probe_cx.assemble_inherent_candidates();
probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id)?;
probe_cx.pick()
})
}
fn create_steps(&self,
span: Span,
self_ty: Ty<'tcx>)
-> Option<Vec<CandidateStep<'tcx>>>
{
fn create_steps(&self, span: Span, self_ty: Ty<'tcx>) -> Option<Vec<CandidateStep<'tcx>>> {
// FIXME: we don't need to create the entire steps in one pass
let mut autoderef = self.autoderef(span, self_ty);
let mut steps: Vec<_> = autoderef.by_ref().map(|(ty, d)| CandidateStep {
self_ty: ty,
autoderefs: d,
unsize: false
}).collect();
let mut steps: Vec<_> = autoderef.by_ref()
.map(|(ty, d)| {
CandidateStep {
self_ty: ty,
autoderefs: d,
unsize: false,
}
})
.collect();
let final_ty = autoderef.unambiguous_final_ty();
match final_ty.sty {
@ -226,7 +235,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
steps.push(CandidateStep {
self_ty: self.tcx.mk_slice(elem_ty),
autoderefs: dereferences,
unsize: true
unsize: true,
});
}
ty::TyError => return None,
@ -246,8 +255,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
item_name: ast::Name,
steps: Vec<CandidateStep<'tcx>>,
opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>)
-> ProbeContext<'a, 'gcx, 'tcx>
{
-> ProbeContext<'a, 'gcx, 'tcx> {
ProbeContext {
fcx: fcx,
span: span,
@ -284,8 +292,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
}
fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
debug!("assemble_probe: self_ty={:?}",
self_ty);
debug!("assemble_probe: self_ty={:?}", self_ty);
match self_ty.sty {
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();
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) {
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) {
@ -415,7 +423,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
if !item.vis().is_accessible_from(self.body_id, &self.tcx.map) {
self.private_candidate = Some(item.def());
return
return;
}
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| {
let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
let xform_self_ty = this.xform_self_ty(&item,
new_trait_ref.self_ty(),
new_trait_ref.substs);
let xform_self_ty =
this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs);
this.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
@ -476,8 +483,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
param_ty: ty::ParamTy) {
// FIXME -- Do we want to commit to this behavior for param bounds?
let bounds: Vec<_> =
self.parameter_environment.caller_bounds
let bounds: Vec<_> = self.parameter_environment
.caller_bounds
.iter()
.filter_map(|predicate| {
match *predicate {
@ -486,7 +493,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
ty::TyParam(ref p) if *p == param_ty => {
Some(trait_predicate.to_poly_trait_ref())
}
_ => None
_ => None,
}
}
ty::Predicate::Equate(..) |
@ -495,21 +502,15 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
ty::Predicate::WellFormed(..) |
ty::Predicate::ObjectSafe(..) |
ty::Predicate::ClosureKind(..) |
ty::Predicate::TypeOutlives(..) => {
None
}
ty::Predicate::TypeOutlives(..) => None,
}
})
.collect();
self.elaborate_bounds(&bounds, |this, poly_trait_ref, item| {
let trait_ref =
this.erase_late_bound_regions(&poly_trait_ref);
let trait_ref = this.erase_late_bound_regions(&poly_trait_ref);
let xform_self_ty =
this.xform_self_ty(&item,
trait_ref.self_ty(),
trait_ref.substs);
let xform_self_ty = this.xform_self_ty(&item, trait_ref.self_ty(), trait_ref.substs);
if let Some(ref m) = item.as_opt_method() {
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
// create the candidates.
fn elaborate_bounds<F>(
&mut self,
bounds: &[ty::PolyTraitRef<'tcx>],
mut mk_cand: F,
) where
F: for<'b> FnMut(
&mut ProbeContext<'b, 'gcx, 'tcx>,
ty::PolyTraitRef<'tcx>,
ty::ImplOrTraitItem<'tcx>,
),
fn elaborate_bounds<F>(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F)
where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>,
ty::PolyTraitRef<'tcx>,
ty::ImplOrTraitItem<'tcx>)
{
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) {
let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) {
Some(v) => v,
None => { continue; }
None => {
continue;
}
};
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,
expr_id: ast::NodeId)
-> Result<(), MethodError<'tcx>>
{
-> Result<(), MethodError<'tcx>> {
let mut duplicates = FnvHashSet();
let opt_applicable_traits = self.tcx.trait_map.get(&expr_id);
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,
trait_def_id: DefId)
-> Result<(), MethodError<'tcx>>
{
-> Result<(), MethodError<'tcx>> {
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})",
trait_def_id);
// Check whether `trait_def_id` defines a method with suitable name:
let trait_items =
self.tcx.trait_items(trait_def_id);
let maybe_item =
trait_items.iter()
.find(|item| item.name() == self.item_name);
let trait_items = self.tcx.trait_items(trait_def_id);
let maybe_item = trait_items.iter()
.find(|item| item.name() == self.item_name);
let item = match maybe_item {
Some(i) => i,
None => { return Ok(()); }
None => {
return Ok(());
}
};
// 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,
trait_def_id: DefId,
item: ty::ImplOrTraitItem<'tcx>)
{
item: ty::ImplOrTraitItem<'tcx>) {
let trait_def = self.tcx.lookup_trait_def(trait_def_id);
// 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);
let impl_trait_ref =
self.tcx.impl_trait_ref(impl_def_id)
let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id)
.unwrap() // we know this is a trait impl
.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.
let xform_self_ty =
self.xform_self_ty(&item,
impl_trait_ref.self_ty(),
impl_trait_ref.substs);
self.xform_self_ty(&item, impl_trait_ref.self_ty(), impl_trait_ref.substs);
// Normalize the receiver. We can't use normalize_associated_types_in
// 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 {
let simplified_steps = match self.opt_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_simplified_type =
match ty::fast_reject::simplify_type(self.tcx, impl_type.ty, false) {
Some(simplified_type) => simplified_type,
None => { return true; }
None => {
return true;
}
};
simplified_steps.contains(&impl_simplified_type)
@ -706,8 +701,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
fn assemble_closure_candidates(&mut self,
trait_def_id: DefId,
item: ty::ImplOrTraitItem<'tcx>)
-> Result<(), MethodError<'tcx>>
{
-> Result<(), MethodError<'tcx>> {
// Check if this is one of the Fn,FnMut,FnOnce traits.
let tcx = self.tcx;
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
// receiver type into account, so we can just substitute
// fresh types here to use during substitution and subtyping.
let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
self.region_var_for_def(self.span, def)
}, |def, substs| {
let substs = Substs::for_item(self.tcx,
trait_def_id,
|def, _| self.region_var_for_def(self.span, def),
|def, substs| {
if def.index == 0 {
step.self_ty
} else {
@ -756,9 +751,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
}
});
let xform_self_ty = self.xform_self_ty(&item,
step.self_ty,
substs);
let xform_self_ty = self.xform_self_ty(&item, step.self_ty, substs);
self.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
@ -772,8 +765,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
fn assemble_projection_candidates(&mut self,
trait_def_id: DefId,
item: ty::ImplOrTraitItem<'tcx>)
{
item: ty::ImplOrTraitItem<'tcx>) {
debug!("assemble_projection_candidates(\
trait_def_id={:?}, \
item={:?})",
@ -781,39 +773,35 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
item);
for step in self.steps.iter() {
debug!("assemble_projection_candidates: step={:?}",
step);
debug!("assemble_projection_candidates: step={:?}", step);
let (def_id, substs) = match step.self_ty.sty {
ty::TyProjection(ref data) => {
(data.trait_ref.def_id, data.trait_ref.substs)
}
ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs),
ty::TyAnon(def_id, substs) => (def_id, substs),
_ => continue,
};
debug!("assemble_projection_candidates: def_id={:?} substs={:?}",
def_id, substs);
def_id,
substs);
let trait_predicates = self.tcx.lookup_predicates(def_id);
let bounds = trait_predicates.instantiate(self.tcx, substs);
let predicates = bounds.predicates;
debug!("assemble_projection_candidates: predicates={:?}",
predicates);
for poly_bound in
traits::elaborate_predicates(self.tcx, predicates)
for poly_bound in traits::elaborate_predicates(self.tcx, predicates)
.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);
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() {
let xform_self_ty = self.xform_self_ty(&item,
bound.self_ty(),
bound.substs);
let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs);
debug!("assemble_projection_candidates: bound={:?} xform_self_ty={:?}",
bound,
@ -832,20 +820,16 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
fn assemble_where_clause_candidates(&mut self,
trait_def_id: DefId,
item: ty::ImplOrTraitItem<'tcx>)
{
item: ty::ImplOrTraitItem<'tcx>) {
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
trait_def_id);
let caller_predicates = self.parameter_environment.caller_bounds.clone();
for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates)
.filter_map(|p| p.to_opt_poly_trait_ref())
.filter(|b| b.def_id() == trait_def_id)
{
.filter_map(|p| p.to_opt_poly_trait_ref())
.filter(|b| b.def_id() == trait_def_id) {
let bound = self.erase_late_bound_regions(&poly_bound);
let xform_self_ty = self.xform_self_ty(&item,
bound.self_ty(),
bound.substs);
let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs);
debug!("assemble_where_clause_candidates: bound={:?} xform_self_ty={:?}",
bound,
@ -882,19 +866,24 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let out_of_scope_traits = match self.pick_core() {
Some(Ok(p)) => vec![p.item.container().id()],
Some(Err(MethodError::Ambiguity(v))) => v.into_iter().map(|source| {
match source {
TraitSource(id) => id,
ImplSource(impl_id) => {
match tcx.trait_id_of_impl(impl_id) {
Some(id) => id,
None =>
span_bug!(span,
"found inherent method when looking at traits")
Some(Err(MethodError::Ambiguity(v))) => {
v.into_iter()
.map(|source| {
match source {
TraitSource(id) => id,
ImplSource(impl_id) => {
match tcx.trait_id_of_impl(impl_id) {
Some(id) => id,
None => {
span_bug!(span,
"found inherent method when looking at traits")
}
}
}
}
}
}
}).collect(),
})
.collect()
}
Some(Err(MethodError::NoMatch(NoMatchData { out_of_scope_traits: others, .. }))) => {
assert!(others.is_empty());
vec![]
@ -910,8 +899,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
return Err(MethodError::PrivateMatch(def));
}
Err(MethodError::NoMatch(NoMatchData::new(static_candidates, unsatisfied_predicates,
out_of_scope_traits, self.mode)))
Err(MethodError::NoMatch(NoMatchData::new(static_candidates,
unsatisfied_predicates,
out_of_scope_traits,
self.mode)))
}
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
@ -935,41 +926,35 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
self.pick_autorefd_method(step)
}
fn pick_by_value_method(&mut self,
step: &CandidateStep<'tcx>)
-> Option<PickResult<'tcx>>
{
/*!
* For each type `T` in the step list, this attempts to find a
* 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
* *reborrow* it to a shorter lifetime. This allows us to
* transparently pass `&mut` pointers, in particular, without
* consuming them for their entire lifetime.
*/
fn pick_by_value_method(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
//! For each type `T` in the step list, this attempts to find a
//! 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
//! *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 {
return None;
}
self.pick_method(step.self_ty).map(|r| r.map(|mut pick| {
pick.autoderefs = step.autoderefs;
self.pick_method(step.self_ty).map(|r| {
r.map(|mut pick| {
pick.autoderefs = step.autoderefs;
// Insert a `&*` or `&mut *` if this is a reference type:
if let ty::TyRef(_, mt) = step.self_ty.sty {
pick.autoderefs += 1;
pick.autoref = Some(mt.mutbl);
}
// Insert a `&*` or `&mut *` if this is a reference type:
if let ty::TyRef(_, mt) = step.self_ty.sty {
pick.autoderefs += 1;
pick.autoref = Some(mt.mutbl);
}
pick
}))
pick
})
})
}
fn pick_autorefd_method(&mut self,
step: &CandidateStep<'tcx>)
-> Option<PickResult<'tcx>>
{
fn pick_autorefd_method(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
let tcx = self.tcx;
// In general, during probing we erase regions. See
@ -977,22 +962,28 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let region = tcx.mk_region(ty::ReErased);
// Search through mutabilities in order to find one where pick works:
[hir::MutImmutable, hir::MutMutable].iter().filter_map(|&m| {
let autoref_ty = tcx.mk_ref(region, ty::TypeAndMut {
ty: step.self_ty,
mutbl: m
});
self.pick_method(autoref_ty).map(|r| r.map(|mut pick| {
pick.autoderefs = step.autoderefs;
pick.autoref = Some(m);
pick.unsize = if step.unsize {
Some(step.self_ty)
} else {
None
};
pick
}))
}).nth(0)
[hir::MutImmutable, hir::MutMutable]
.iter()
.filter_map(|&m| {
let autoref_ty = tcx.mk_ref(region,
ty::TypeAndMut {
ty: step.self_ty,
mutbl: m,
});
self.pick_method(autoref_ty).map(|r| {
r.map(|mut pick| {
pick.autoderefs = step.autoderefs;
pick.autoref = Some(m);
pick.unsize = if step.unsize {
Some(step.self_ty)
} else {
None
};
pick
})
})
})
.nth(0)
}
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");
let res = self.consider_candidates(self_ty, &self.extension_candidates,
let res = self.consider_candidates(self_ty,
&self.extension_candidates,
&mut possibly_unsatisfied_predicates);
if let None = res {
self.unsatisfied_predicates.extend(possibly_unsatisfied_predicates);
@ -1021,18 +1013,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
probes: &[Candidate<'tcx>],
possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>)
-> Option<PickResult<'tcx>> {
let mut applicable_candidates: Vec<_> =
probes.iter()
.filter(|&probe| self.consider_probe(self_ty,
probe,possibly_unsatisfied_predicates))
.collect();
let mut applicable_candidates: Vec<_> = probes.iter()
.filter(|&probe| self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
.collect();
debug!("applicable_candidates: {:?}", applicable_candidates);
if applicable_candidates.len() > 1 {
match self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) {
Some(pick) => { return Some(Ok(pick)); }
None => { }
Some(pick) => {
return Some(Ok(pick));
}
None => {}
}
}
@ -1041,21 +1033,22 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
return Some(Err(MethodError::Ambiguity(sources)));
}
applicable_candidates.pop().map(|probe| {
Ok(probe.to_unadjusted_pick())
})
applicable_candidates.pop().map(|probe| Ok(probe.to_unadjusted_pick()))
}
fn consider_probe(&self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>,
possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>) -> bool {
debug!("consider_probe: self_ty={:?} probe={:?}",
self_ty,
probe);
fn consider_probe(&self,
self_ty: Ty<'tcx>,
probe: &Candidate<'tcx>,
possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>)
-> bool {
debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe);
self.probe(|_| {
// First check that the self type can be related.
match self.sub_types(false, TypeOrigin::Misc(DUMMY_SP),
self_ty, probe.xform_self_ty) {
match self.sub_types(false,
TypeOrigin::Misc(DUMMY_SP),
self_ty,
probe.xform_self_ty) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
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.
let impl_bounds = self.tcx.lookup_predicates(impl_def_id);
let impl_bounds = impl_bounds.instantiate(self.tcx, substs);
let traits::Normalized { value: impl_bounds,
obligations: norm_obligations } =
let traits::Normalized { value: impl_bounds, obligations: norm_obligations } =
traits::normalize(selcx, cause.clone(), &impl_bounds);
// Convert the bounds into obligations.
let obligations =
traits::predicates_for_generics(cause.clone(),
&impl_bounds);
let obligations = traits::predicates_for_generics(cause.clone(), &impl_bounds);
debug!("impl_obligations={:?}", obligations);
// 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
/// use, so it's ok to just commit to "using the method from the trait Foo".
fn collapse_candidates_to_trait_pick(&self,
probes: &[&Candidate<'tcx>])
-> Option<Pick<'tcx>> {
fn collapse_candidates_to_trait_pick(&self, probes: &[&Candidate<'tcx>]) -> Option<Pick<'tcx>> {
// Do all probes correspond to the same trait?
let container = probes[0].item.container();
match container {
ty::TraitContainer(_) => {}
ty::ImplContainer(_) => return None
ty::ImplContainer(_) => return None,
}
if probes[1..].iter().any(|p| p.item.container() != container) {
return None;
@ -1156,7 +1144,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
import_id: probes[0].import_id,
autoderefs: 0,
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 {
// "fast track" -- check for usage of sugar
match *item {
ty::ImplOrTraitItem::MethodTraitItem(ref method) =>
ty::ImplOrTraitItem::MethodTraitItem(ref method) => {
match method.explicit_self {
ty::ExplicitSelfCategory::Static => self.mode == Mode::Path,
ty::ExplicitSelfCategory::ByValue |
ty::ExplicitSelfCategory::ByReference(..) |
ty::ExplicitSelfCategory::ByBox => true,
},
}
}
ty::ImplOrTraitItem::ConstTraitItem(..) => self.mode == Mode::Path,
_ => false,
}
@ -1191,11 +1180,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
item: &ty::ImplOrTraitItem<'tcx>,
impl_ty: Ty<'tcx>,
substs: &Substs<'tcx>)
-> Ty<'tcx>
{
-> Ty<'tcx> {
match item.as_opt_method() {
Some(ref method) => self.xform_method_self_ty(method, impl_ty,
substs),
Some(ref method) => self.xform_method_self_ty(method, impl_ty, substs),
None => impl_ty,
}
}
@ -1204,8 +1191,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
method: &Rc<ty::Method<'tcx>>,
impl_ty: Ty<'tcx>,
substs: &Substs<'tcx>)
-> Ty<'tcx>
{
-> Ty<'tcx> {
debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
impl_ty,
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
// method yet. So create fresh variables here for those too,
// if there are any.
assert_eq!(substs.types().count(), method.generics.parent_types as usize);
assert_eq!(substs.regions().count(), method.generics.parent_regions as usize);
assert_eq!(substs.types().count(),
method.generics.parent_types as usize);
assert_eq!(substs.regions().count(),
method.generics.parent_regions as usize);
if self.mode == Mode::Path {
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() {
xform_self_ty.subst(self.tcx, substs)
} 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;
if i < substs.params().len() {
substs.region_at(i)
@ -1242,7 +1232,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
// `impl_self_ty()` for an explanation.
self.tcx.mk_region(ty::ReErased)
}
}, |def, cur_substs| {
},
|def, cur_substs| {
let i = def.index as usize;
if i < substs.params().len() {
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.
fn impl_ty_and_substs(&self,
impl_def_id: DefId)
-> (Ty<'tcx>, &'tcx Substs<'tcx>)
{
fn impl_ty_and_substs(&self, impl_def_id: DefId) -> (Ty<'tcx>, &'tcx Substs<'tcx>) {
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.next_ty_var());
@ -1287,16 +1276,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
/// and/or tracking the substitution and
/// so forth.
fn erase_late_bound_regions<T>(&self, value: &ty::Binder<T>) -> T
where T : TypeFoldable<'tcx>
where T: TypeFoldable<'tcx>
{
self.tcx.erase_late_bound_regions(value)
}
/// Find item with name `item_name` defined in impl/trait `def_id`
/// and return it, or `None`, if no such item was defined there.
fn impl_or_trait_item(&self, def_id: DefId)
-> Option<ty::ImplOrTraitItem<'tcx>>
{
fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::ImplOrTraitItem<'tcx>> {
self.fcx.impl_or_trait_item(def_id, self.item_name)
}
}
@ -1307,9 +1294,7 @@ impl<'tcx> Candidate<'tcx> {
item: self.item.clone(),
kind: match self.kind {
InherentImplCandidate(..) => InherentImplPick,
ExtensionImplCandidate(def_id, ..) => {
ExtensionImplPick(def_id)
}
ExtensionImplCandidate(def_id, ..) => ExtensionImplPick(def_id),
ObjectCandidate => ObjectPick,
TraitCandidate => TraitPick,
WhereClauseCandidate(ref trait_ref) => {
@ -1326,15 +1311,13 @@ impl<'tcx> Candidate<'tcx> {
import_id: self.import_id,
autoderefs: 0,
autoref: None,
unsize: None
unsize: None,
}
}
fn to_source(&self) -> CandidateSource {
match self.kind {
InherentImplCandidate(..) => {
ImplSource(self.item.container().id())
}
InherentImplCandidate(..) => ImplSource(self.item.container().id()),
ExtensionImplCandidate(def_id, ..) => ImplSource(def_id),
ObjectCandidate |
TraitCandidate |

View File

@ -13,7 +13,7 @@
use CrateCtxt;
use check::{FnCtxt};
use check::FnCtxt;
use rustc::hir::map as hir_map;
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable};
use hir::def::Def;
@ -21,7 +21,7 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId};
use middle::lang_items::FnOnceTraitLangItem;
use rustc::ty::subst::Substs;
use rustc::traits::{Obligation, SelectionContext};
use util::nodemap::{FnvHashSet};
use util::nodemap::FnvHashSet;
use syntax::ast;
use errors::DiagnosticBuilder;
@ -43,25 +43,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match ty.sty {
// Not all of these (e.g. unsafe fns) implement FnOnce
// 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
_ => {
let fn_once = match tcx.lang_items.require(FnOnceTraitLangItem) {
Ok(fn_once) => fn_once,
Err(..) => return false
Err(..) => return false,
};
self.autoderef(span, ty).any(|(ty, _)| self.probe(|_| {
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 poly_trait_ref = trait_ref.to_poly_trait_ref();
let obligation = Obligation::misc(span,
self.body_id,
poly_trait_ref
.to_predicate());
SelectionContext::new(self).evaluate_obligation(&obligation)
}))
self.autoderef(span, ty).any(|(ty, _)| {
self.probe(|_| {
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 poly_trait_ref = trait_ref.to_poly_trait_ref();
let obligation =
Obligation::misc(span, self.body_id, poly_trait_ref.to_predicate());
SelectionContext::new(self).evaluate_obligation(&obligation)
})
})
}
}
}
@ -71,15 +72,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
rcvr_ty: Ty<'tcx>,
item_name: ast::Name,
rcvr_expr: Option<&hir::Expr>,
error: MethodError<'tcx>)
{
error: MethodError<'tcx>) {
// avoid suggestions when we don't know what's going on.
if rcvr_ty.references_error() {
return
return;
}
let report_candidates = |err: &mut DiagnosticBuilder,
mut sources: Vec<CandidateSource>| {
let report_candidates = |err: &mut DiagnosticBuilder, mut sources: Vec<CandidateSource>| {
sources.sort();
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.
let item = self.impl_or_trait_item(impl_did, item_name)
.or_else(|| {
self.impl_or_trait_item(
self.tcx.impl_trait_ref(impl_did).unwrap().def_id,
self.impl_or_trait_item(self.tcx
.impl_trait_ref(impl_did)
.unwrap()
.def_id,
item_name
)
}).unwrap();
let note_span = self.tcx.map.span_if_local(item.def_id()).or_else(|| {
self.tcx.map.span_if_local(impl_did)
});
item_name)
})
.unwrap();
let note_span = self.tcx
.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;
@ -128,7 +130,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
CandidateSource::TraitSource(trait_did) => {
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);
span_note!(err, item_span,
span_note!(err,
item_span,
"candidate #{} is defined in the trait `{}`",
idx + 1,
self.tcx.item_path_str(trait_did));
@ -144,20 +147,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
MethodError::NoMatch(NoMatchData { static_candidates: static_sources,
unsatisfied_predicates,
out_of_scope_traits,
mode, .. }) => {
mode,
.. }) => {
let tcx = self.tcx;
let mut err = self.type_error_struct(
span,
|actual| {
format!("no {} named `{}` found for type `{}` \
in the current scope",
if mode == Mode::MethodCall { "method" }
else { "associated item" },
item_name,
actual)
},
rcvr_ty);
let mut err = self.type_error_struct(span,
|actual| {
format!("no {} named `{}` found for type `{}` in the current scope",
if mode == Mode::MethodCall {
"method"
} else {
"associated item"
},
item_name,
actual)
},
rcvr_ty);
// If the method name is the name of a field with a function or closure type,
// give a helping note that it has to be called as (x.f)(...).
@ -165,27 +170,30 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
for (ty, _) in self.autoderef(span, rcvr_ty) {
match ty.sty {
ty::TyAdt(def, substs) if !def.is_enum() => {
if let Some(field) = def.struct_variant().
find_field_named(item_name) {
if let Some(field) = def.struct_variant()
.find_field_named(item_name) {
let snippet = tcx.sess.codemap().span_to_snippet(expr.span);
let expr_string = match snippet {
Ok(expr_string) => expr_string,
_ => "s".into() // Default to a generic placeholder for the
// expression when we can't generate a
// string snippet
_ => "s".into(), // Default to a generic placeholder for the
// expression when we can't generate a
// string snippet
};
let field_ty = field.ty(tcx, substs);
if self.is_fn_ty(&field_ty, span) {
err.span_note(span, &format!(
"use `({0}.{1})(...)` if you meant to call the \
function stored in the `{1}` field",
expr_string, item_name));
err.span_note(span,
&format!("use `({0}.{1})(...)` if you \
meant to call the function \
stored in the `{1}` field",
expr_string,
item_name));
} else {
err.span_note(span, &format!(
"did you mean to write `{0}.{1}`?",
expr_string, item_name));
err.span_note(span,
&format!("did you mean to write `{0}.{1}`?",
expr_string,
item_name));
}
break;
}
@ -204,10 +212,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
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);
}
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() {
report_function!(expr.span, segment.name);
}
@ -216,34 +223,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
if !static_sources.is_empty() {
err.note(
"found the following associated functions; to be used as \
methods, functions must have a `self` parameter");
err.note("found the following associated functions; to be used as methods, \
functions must have a `self` parameter");
report_candidates(&mut err, static_sources);
}
if !unsatisfied_predicates.is_empty() {
let bound_list = unsatisfied_predicates.iter()
.map(|p| format!("`{} : {}`",
p.self_ty(),
p))
.map(|p| format!("`{} : {}`", p.self_ty(), p))
.collect::<Vec<_>>()
.join(", ");
err.note(
&format!("the method `{}` exists but the \
following trait bounds were not satisfied: {}",
item_name,
bound_list));
err.note(&format!("the method `{}` exists but the following trait bounds \
were not satisfied: {}",
item_name,
bound_list));
}
self.suggest_traits_to_import(&mut err, span, rcvr_ty, item_name,
rcvr_expr, out_of_scope_traits);
self.suggest_traits_to_import(&mut err,
span,
rcvr_ty,
item_name,
rcvr_expr,
out_of_scope_traits);
err.emit();
}
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");
err.span_label(span, &format!("multiple `{}` found", item_name));
@ -255,11 +264,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
invoked on this closure as we have not yet inferred what \
kind of closure it is",
item_name,
self.tcx.item_path_str(trait_def_id));
item_name,
self.tcx.item_path_str(trait_def_id));
let msg = if let Some(callee) = rcvr_expr {
format!("{}; use overloaded call notation instead (e.g., `{}()`)",
msg, pprust::expr_to_string(callee))
msg,
pprust::expr_to_string(callee))
} else {
msg
};
@ -279,18 +289,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
rcvr_ty: Ty<'tcx>,
item_name: ast::Name,
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() {
let mut candidates = valid_out_of_scope_traits;
candidates.sort();
candidates.dedup();
let msg = format!(
"items from traits can only be used if the trait is in scope; \
the following {traits_are} implemented but not in scope, \
perhaps add a `use` for {one_of_them}:",
traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"});
let msg = format!("items from traits can only be used if the trait is in scope; the \
following {traits_are} implemented but not in scope, perhaps add \
a `use` for {one_of_them}:",
traits_are = if candidates.len() == 1 {
"trait is"
} else {
"traits are"
},
one_of_them = if candidates.len() == 1 {
"it"
} else {
"one of them"
});
err.help(&msg[..]);
@ -303,7 +319,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if 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);
@ -319,8 +335,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// this isn't perfect (that is, there are cases when
// implementing a trait would be legal but is rejected
// here).
(type_is_local || info.def_id.is_local())
&& self.impl_or_trait_item(info.def_id, item_name).is_some()
(type_is_local || info.def_id.is_local()) &&
self.impl_or_trait_item(info.def_id, item_name).is_some()
})
.collect::<Vec<_>>();
@ -332,13 +348,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// FIXME #21673 this help message could be tuned to the case
// of a type parameter: suggest adding a trait bound rather
// than implementing.
let msg = format!(
"items from traits can only be used if the trait is implemented and in scope; \
the following {traits_define} an item `{name}`, \
perhaps you need to implement {one_of_them}:",
traits_define = if candidates.len() == 1 {"trait defines"} else {"traits define"},
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
name = item_name);
let msg = format!("items from traits can only be used if the trait is implemented \
and in scope; the following {traits_define} an item `{name}`, \
perhaps you need to implement {one_of_them}:",
traits_define = if candidates.len() == 1 {
"trait defines"
} else {
"traits define"
},
one_of_them = if candidates.len() == 1 {
"it"
} else {
"one of them"
},
name = item_name);
err.help(&msg[..]);
@ -355,7 +378,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn type_derefs_to_local(&self,
span: Span,
rcvr_ty: Ty<'tcx>,
rcvr_expr: Option<&hir::Expr>) -> bool {
rcvr_expr: Option<&hir::Expr>)
-> bool {
fn is_local(ty: Ty) -> bool {
match ty.sty {
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
// the noise from these sort of types is usually just really
// annoying, rather than any sort of help).
_ => false
_ => false,
}
}
@ -391,9 +415,7 @@ pub struct TraitInfo {
impl TraitInfo {
fn new(def_id: DefId) -> TraitInfo {
TraitInfo {
def_id: def_id,
}
TraitInfo { def_id: def_id }
}
}
impl PartialEq for TraitInfo {
@ -403,7 +425,9 @@ impl PartialEq for TraitInfo {
}
impl Eq 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 {
fn cmp(&self, other: &TraitInfo) -> Ordering {
@ -426,7 +450,7 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
// Crate-local:
//
// meh.
struct Visitor<'a, 'tcx:'a> {
struct Visitor<'a, 'tcx: 'a> {
map: &'a hir_map::Map<'tcx>,
traits: &'a mut AllTraitsVec,
}
@ -443,7 +467,7 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
}
ccx.tcx.map.krate().visit_all_items(&mut Visitor {
map: &ccx.tcx.map,
traits: &mut traits
traits: &mut traits,
});
// Cross-crate:
@ -469,7 +493,10 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
}
}
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));
}
@ -480,13 +507,13 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
assert!(borrow.is_some());
AllTraits {
borrow: borrow,
idx: 0
idx: 0,
}
}
pub struct AllTraits<'a> {
borrow: cell::Ref<'a, Option<AllTraitsVec>>,
idx: usize
idx: usize,
}
impl<'a> Iterator for AllTraits<'a> {

View File

@ -140,7 +140,7 @@ pub mod os {
}
#[cfg(target_os = "haiku")]
mod os {
pub mod os {
pub const FAMILY: &'static str = "unix";
pub const OS: &'static str = "haiku";
pub const DLL_PREFIX: &'static str = "lib";
@ -151,7 +151,7 @@ mod os {
}
#[cfg(all(target_os = "emscripten", target_arch = "asmjs"))]
mod os {
pub mod os {
pub const FAMILY: &'static str = "unix";
pub const OS: &'static str = "emscripten";
pub const DLL_PREFIX: &'static str = "lib";
@ -162,7 +162,7 @@ mod os {
}
#[cfg(all(target_os = "emscripten", target_arch = "wasm32"))]
mod os {
pub mod os {
pub const FAMILY: &'static str = "unix";
pub const OS: &'static str = "emscripten";
pub const DLL_PREFIX: &'static str = "lib";

@ -1 +1 @@
Subproject commit 755bc3db4ff795865ea31b5b4f38ac920d8acacb
Subproject commit 4f994850808a572e2cc8d43f968893c8e942e9bf

View File

@ -0,0 +1,24 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Regression test for #36856.
// compile-flags:-g
fn g() -> bool {
false
}
pub fn main() {
let a = !g();
if a != !g() {
panic!();
}
}

View File

@ -0,0 +1,35 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// check that casts are not being treated as lexprs.
fn main() {
let mut a = 0i32;
let b = &(a as i32);
a = 1;
assert_ne!(&a as *const i32, b as *const i32);
assert_eq!(*b, 0);
assert_eq!(issue_36936(), 1);
}
struct A(u32);
impl Drop for A {
fn drop(&mut self) {
self.0 = 0;
}
}
fn issue_36936() -> u32 {
let a = &(A(1) as A);
a.0
}