mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
A few cleanups and minor improvements to rustc/traits
This commit is contained in:
parent
f1aefb48d2
commit
a8ec8e5cb7
@ -112,6 +112,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
orig_params,
|
||||
trait_pred.to_poly_trait_predicate(),
|
||||
));
|
||||
|
||||
match result {
|
||||
Ok(Some(Vtable::VtableImpl(_))) => {
|
||||
debug!(
|
||||
@ -119,10 +120,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
manual impl found, bailing out",
|
||||
did, trait_did, generics
|
||||
);
|
||||
return true;
|
||||
true
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
_ => false
|
||||
}
|
||||
});
|
||||
|
||||
// If an explicit impl exists, it always takes priority over an auto impl
|
||||
@ -426,6 +427,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
if new_trait.def_id() == old_trait.def_id() {
|
||||
let new_substs = new_trait.skip_binder().trait_ref.substs;
|
||||
let old_substs = old_trait.skip_binder().trait_ref.substs;
|
||||
|
||||
if !new_substs.types().eq(old_substs.types()) {
|
||||
// We can't compare lifetimes if the types are different,
|
||||
// so skip checking old_pred
|
||||
@ -489,12 +491,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||
|
||||
pub fn get_lifetime(&self, region: Region, names_map: &FxHashMap<String, String>) -> String {
|
||||
self.region_name(region)
|
||||
.map(|name| {
|
||||
names_map.get(&name).unwrap_or_else(|| {
|
||||
.map(|name|
|
||||
names_map.get(&name).unwrap_or_else(||
|
||||
panic!("Missing lifetime with name {:?} for {:?}", name, region)
|
||||
})
|
||||
})
|
||||
.unwrap_or(&"'static".to_string())
|
||||
)
|
||||
)
|
||||
.unwrap_or(&"'static".to_owned())
|
||||
.clone()
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let trait_ref = ty.erase_regions(&trait_ref);
|
||||
|
||||
debug!("codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
|
||||
(param_env, trait_ref), trait_ref.def_id());
|
||||
(param_env, trait_ref), trait_ref.def_id());
|
||||
|
||||
// Do the initial selection for the obligation. This yields the
|
||||
// shallow result we are looking for -- that is, what specific impl.
|
||||
@ -48,8 +48,8 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
let obligation_cause = ObligationCause::dummy();
|
||||
let obligation = Obligation::new(obligation_cause,
|
||||
param_env,
|
||||
trait_ref.to_poly_trait_predicate());
|
||||
param_env,
|
||||
trait_ref.to_poly_trait_predicate());
|
||||
|
||||
let selection = match selcx.select(&obligation) {
|
||||
Ok(Some(selection)) => selection,
|
||||
@ -61,12 +61,11 @@ pub fn codegen_fulfill_obligation<'a, 'tcx>(ty: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// overflow bug, since I believe this is the only case
|
||||
// where ambiguity can result.
|
||||
bug!("Encountered ambiguity selecting `{:?}` during codegen, \
|
||||
presuming due to overflow",
|
||||
trait_ref)
|
||||
presuming due to overflow",
|
||||
trait_ref)
|
||||
}
|
||||
Err(e) => {
|
||||
bug!("Encountered error `{:?}` selecting `{:?}` during codegen",
|
||||
e, trait_ref)
|
||||
bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
|
||||
}
|
||||
};
|
||||
|
||||
@ -163,22 +162,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// In principle, we only need to do this so long as `result`
|
||||
// contains unbound type parameters. It could be a slight
|
||||
// optimization to stop iterating early.
|
||||
match fulfill_cx.select_all_or_error(self) {
|
||||
Ok(()) => { }
|
||||
Err(errors) => {
|
||||
span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking",
|
||||
errors);
|
||||
}
|
||||
if let Err(errors) = fulfill_cx.select_all_or_error(self) {
|
||||
span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking",
|
||||
errors);
|
||||
}
|
||||
|
||||
let result = self.resolve_type_vars_if_possible(result);
|
||||
let result = self.tcx.erase_regions(&result);
|
||||
|
||||
match self.tcx.lift_to_global(&result) {
|
||||
Some(result) => result,
|
||||
None => {
|
||||
span_bug!(span, "Uninferred types/regions in `{:?}`", result);
|
||||
}
|
||||
}
|
||||
self.tcx.lift_to_global(&result).unwrap_or_else(||
|
||||
span_bug!(span, "Uninferred types/regions in `{:?}`", result)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -115,9 +115,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
|
||||
b_def_id: DefId)
|
||||
-> Option<OverlapResult<'tcx>>
|
||||
{
|
||||
debug!("overlap(a_def_id={:?}, b_def_id={:?})",
|
||||
a_def_id,
|
||||
b_def_id);
|
||||
debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id);
|
||||
|
||||
// For the purposes of this check, we don't bring any skolemized
|
||||
// types into scope; instead, we replace the generic types with
|
||||
@ -133,10 +131,9 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
|
||||
|
||||
// Do `a` and `b` unify? If not, no overlap.
|
||||
let obligations = match selcx.infcx().at(&ObligationCause::dummy(), param_env)
|
||||
.eq_impl_headers(&a_impl_header, &b_impl_header) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
obligations
|
||||
}
|
||||
.eq_impl_headers(&a_impl_header, &b_impl_header)
|
||||
{
|
||||
Ok(InferOk { obligations, value: () }) => obligations,
|
||||
Err(_) => return None
|
||||
};
|
||||
|
||||
@ -164,7 +161,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
|
||||
return None
|
||||
}
|
||||
|
||||
let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header);
|
||||
let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header);
|
||||
let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
|
||||
debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
|
||||
Some(OverlapResult { impl_header, intercrate_ambiguity_causes })
|
||||
@ -471,14 +468,12 @@ fn ty_is_local_constructor(ty: Ty, in_crate: InCrate) -> bool {
|
||||
ty::Foreign(did) => def_id_is_local(did, in_crate),
|
||||
|
||||
ty::Dynamic(ref tt, ..) => {
|
||||
tt.principal().map_or(false, |p| {
|
||||
tt.principal().map_or(false, |p|
|
||||
def_id_is_local(p.def_id(), in_crate)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
ty::Error => {
|
||||
true
|
||||
}
|
||||
ty::Error => true,
|
||||
|
||||
ty::Closure(..) |
|
||||
ty::Generator(..) |
|
||||
|
@ -34,6 +34,7 @@ use hir::def_id::DefId;
|
||||
use infer::{self, InferCtxt};
|
||||
use infer::type_variable::TypeVariableOrigin;
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use syntax::ast;
|
||||
use session::DiagnosticMessageId;
|
||||
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
@ -58,7 +59,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
index: Option<usize>, // None if this is an old error
|
||||
}
|
||||
|
||||
let mut error_map : FxHashMap<_, Vec<_>> =
|
||||
let mut error_map: FxHashMap<_, Vec<_>> =
|
||||
self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| {
|
||||
(span, predicates.iter().map(|predicate| ErrorDescriptor {
|
||||
predicate: predicate.clone(),
|
||||
@ -80,7 +81,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
// We do this in 2 passes because we want to display errors in order, tho
|
||||
// maybe it *is* better to sort errors by span or something.
|
||||
let mut is_suppressed: Vec<bool> = errors.iter().map(|_| false).collect();
|
||||
let mut is_suppressed = vec![false; errors.len()];
|
||||
for (_, error_set) in error_map.iter() {
|
||||
// We want to suppress "duplicate" errors with the same span.
|
||||
for error in error_set {
|
||||
@ -349,7 +350,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
_ => {
|
||||
// this is a "direct", user-specified, rather than derived,
|
||||
// obligation.
|
||||
flags.push(("direct".to_string(), None));
|
||||
flags.push(("direct".to_owned(), None));
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,24 +362,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// Currently I'm leaving it for what I need for `try`.
|
||||
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
|
||||
let method = self.tcx.item_name(item);
|
||||
flags.push(("from_method".to_string(), None));
|
||||
flags.push(("from_method".to_string(), Some(method.to_string())));
|
||||
flags.push(("from_method".to_owned(), None));
|
||||
flags.push(("from_method".to_owned(), Some(method.to_string())));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
|
||||
flags.push(("from_desugaring".to_string(), None));
|
||||
flags.push(("from_desugaring".to_string(), Some(k.name().to_string())));
|
||||
flags.push(("from_desugaring".to_owned(), None));
|
||||
flags.push(("from_desugaring".to_owned(), Some(k.name().to_string())));
|
||||
}
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let self_ty = trait_ref.self_ty();
|
||||
// This is also included through the generics list as `Self`,
|
||||
// but the parser won't allow you to use it
|
||||
flags.push(("_Self".to_string(), Some(self_ty.to_string())));
|
||||
flags.push(("_Self".to_owned(), Some(self_ty.to_string())));
|
||||
if let Some(def) = self_ty.ty_adt_def() {
|
||||
// We also want to be able to select self's original
|
||||
// signature with no type arguments resolved
|
||||
flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string())));
|
||||
flags.push(("_Self".to_owned(), Some(self.tcx.type_of(def.did).to_string())));
|
||||
}
|
||||
|
||||
for param in generics.params.iter() {
|
||||
@ -393,7 +394,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
|
||||
flags.push(("crate_local".to_string(), None));
|
||||
flags.push(("crate_local".to_owned(), None));
|
||||
}
|
||||
|
||||
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(
|
||||
@ -412,27 +413,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
let simp = fast_reject::simplify_type(self.tcx,
|
||||
trait_ref.skip_binder().self_ty(),
|
||||
true);
|
||||
let mut impl_candidates = Vec::new();
|
||||
let all_impls = self.tcx.all_impls(trait_ref.def_id());
|
||||
|
||||
match simp {
|
||||
Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
|
||||
Some(simp) => all_impls.iter().filter_map(|&def_id| {
|
||||
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
|
||||
let imp_simp = fast_reject::simplify_type(self.tcx,
|
||||
imp.self_ty(),
|
||||
true);
|
||||
if let Some(imp_simp) = imp_simp {
|
||||
if simp != imp_simp {
|
||||
return;
|
||||
return None
|
||||
}
|
||||
}
|
||||
impl_candidates.push(imp);
|
||||
}),
|
||||
None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
|
||||
impl_candidates.push(
|
||||
self.tcx.impl_trait_ref(def_id).unwrap());
|
||||
})
|
||||
};
|
||||
impl_candidates
|
||||
|
||||
Some(imp)
|
||||
}).collect(),
|
||||
None => all_impls.iter().map(|&def_id|
|
||||
self.tcx.impl_trait_ref(def_id).unwrap()
|
||||
).collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn report_similar_impl_candidates(&self,
|
||||
@ -603,10 +603,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
span,
|
||||
E0277,
|
||||
"{}",
|
||||
message.unwrap_or_else(|| {
|
||||
message.unwrap_or_else(||
|
||||
format!("the trait bound `{}` is not satisfied{}",
|
||||
trait_ref.to_predicate(), post_message)
|
||||
}));
|
||||
));
|
||||
|
||||
let explanation =
|
||||
if obligation.cause.code == ObligationCauseCode::MainFunctionType {
|
||||
@ -645,7 +645,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// "the type `T` can't be frobnicated"
|
||||
// which is somewhat confusing.
|
||||
err.help(&format!("consider adding a `where {}` bound",
|
||||
trait_ref.to_predicate()));
|
||||
trait_ref.to_predicate()));
|
||||
} else if !have_alt_message {
|
||||
// Can't show anything else useful, try to find similar impls.
|
||||
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
|
||||
@ -693,7 +693,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
ty::Predicate::RegionOutlives(ref predicate) => {
|
||||
let predicate = self.resolve_type_vars_if_possible(predicate);
|
||||
let err = self.region_outlives_predicate(&obligation.cause,
|
||||
&predicate).err().unwrap();
|
||||
&predicate).err().unwrap();
|
||||
struct_span_err!(self.tcx.sess, span, E0279,
|
||||
"the requirement `{}` is not satisfied (`{}`)",
|
||||
predicate, err)
|
||||
@ -722,7 +722,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess, closure_span, E0525,
|
||||
"expected a closure that implements the `{}` trait, \
|
||||
but this closure only implements `{}`",
|
||||
but this closure only implements `{}`",
|
||||
kind,
|
||||
found_kind);
|
||||
|
||||
@ -779,40 +779,34 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
|
||||
let found_trait_ref = self.resolve_type_vars_if_possible(&*found_trait_ref);
|
||||
let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
|
||||
|
||||
if expected_trait_ref.self_ty().references_error() {
|
||||
return;
|
||||
}
|
||||
|
||||
let found_trait_ty = found_trait_ref.self_ty();
|
||||
|
||||
let found_did = match found_trait_ty.sty {
|
||||
ty::Closure(did, _) |
|
||||
ty::Foreign(did) |
|
||||
ty::FnDef(did, _) => Some(did),
|
||||
ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
|
||||
ty::Adt(def, _) => Some(def.did),
|
||||
_ => None,
|
||||
};
|
||||
let found_span = found_did.and_then(|did| {
|
||||
|
||||
let found_span = found_did.and_then(|did|
|
||||
self.tcx.hir.span_if_local(did)
|
||||
}).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
|
||||
).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
|
||||
|
||||
let found = match found_trait_ref.skip_binder().substs.type_at(1).sty {
|
||||
ty::Tuple(ref tys) => tys.iter()
|
||||
.map(|_| ArgKind::empty()).collect::<Vec<_>>(),
|
||||
ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
|
||||
_ => vec![ArgKind::empty()],
|
||||
};
|
||||
|
||||
let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
|
||||
ty::Tuple(ref tys) => tys.iter()
|
||||
.map(|t| match t.sty {
|
||||
ty::Tuple(ref tys) => ArgKind::Tuple(
|
||||
Some(span),
|
||||
tys.iter()
|
||||
.map(|ty| ("_".to_owned(), ty.sty.to_string()))
|
||||
.collect::<Vec<_>>()
|
||||
),
|
||||
_ => ArgKind::Arg("_".to_owned(), t.sty.to_string()),
|
||||
}).collect(),
|
||||
.map(|t| ArgKind::from_expected_ty(t, Some(span))).collect(),
|
||||
ref sty => vec![ArgKind::Arg("_".to_owned(), sty.to_string())],
|
||||
};
|
||||
|
||||
if found.len() == expected.len() {
|
||||
self.report_closure_arg_mismatch(span,
|
||||
found_span,
|
||||
@ -836,8 +830,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
TraitNotObjectSafe(did) => {
|
||||
let violations = self.tcx.object_safety_violations(did);
|
||||
self.tcx.report_object_safety_error(span, did,
|
||||
violations)
|
||||
self.tcx.report_object_safety_error(span, did, violations)
|
||||
}
|
||||
|
||||
ConstEvalFailure(ref err) => {
|
||||
@ -981,11 +974,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
.map(|arg| match arg.clone().node {
|
||||
hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
|
||||
Some(arg.span),
|
||||
tys.iter()
|
||||
.map(|_| ("_".to_owned(), "_".to_owned()))
|
||||
.collect::<Vec<_>>(),
|
||||
vec![("_".to_owned(), "_".to_owned()); tys.len()]
|
||||
),
|
||||
_ => ArgKind::Arg("_".to_owned(), "_".to_owned())
|
||||
_ => ArgKind::empty()
|
||||
}).collect::<Vec<ArgKind>>())
|
||||
}
|
||||
Node::Variant(&hir::Variant {
|
||||
@ -997,15 +988,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
..
|
||||
}) => {
|
||||
(self.tcx.sess.source_map().def_span(span),
|
||||
fields.iter().map(|field| {
|
||||
fields.iter().map(|field|
|
||||
ArgKind::Arg(field.ident.to_string(), "_".to_string())
|
||||
}).collect::<Vec<_>>())
|
||||
).collect::<Vec<_>>())
|
||||
}
|
||||
Node::StructCtor(ref variant_data) => {
|
||||
(self.tcx.sess.source_map().def_span(self.tcx.hir.span(variant_data.id())),
|
||||
variant_data.fields()
|
||||
.iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned()))
|
||||
.collect())
|
||||
vec![ArgKind::empty(); variant_data.fields().len()])
|
||||
}
|
||||
_ => panic!("non-FnLike node found: {:?}", node),
|
||||
}
|
||||
@ -1054,7 +1043,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
found_str,
|
||||
);
|
||||
|
||||
err.span_label(span, format!( "expected {} that takes {}", kind, expected_str));
|
||||
err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
|
||||
|
||||
if let Some(found_span) = found_span {
|
||||
err.span_label(found_span, format!("takes {}", found_str));
|
||||
@ -1063,9 +1052,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// found arguments is empty (assume the user just wants to ignore args in this case).
|
||||
// For example, if `expected_args_length` is 2, suggest `|_, _|`.
|
||||
if found_args.is_empty() && is_closure {
|
||||
let underscores = "_".repeat(expected_args.len())
|
||||
.split("")
|
||||
.filter(|s| !s.is_empty())
|
||||
let underscores = iter::repeat("_")
|
||||
.take(expected_args.len())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
err.span_suggestion_with_applicability(
|
||||
@ -1087,7 +1075,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
if fields.len() == expected_args.len() {
|
||||
let sugg = fields.iter()
|
||||
.map(|(name, _)| name.to_owned())
|
||||
.collect::<Vec<String>>().join(", ");
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
err.span_suggestion_with_applicability(found_span,
|
||||
"change the closure to take multiple \
|
||||
arguments instead of a single tuple",
|
||||
@ -1146,7 +1135,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
let inputs = trait_ref.substs.type_at(1);
|
||||
let sig = if let ty::Tuple(inputs) = inputs.sty {
|
||||
tcx.mk_fn_sig(
|
||||
inputs.iter().map(|&x| x),
|
||||
inputs.iter().cloned(),
|
||||
tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
@ -1220,10 +1209,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
let mut reported_violations = FxHashSet();
|
||||
for violation in violations {
|
||||
if !reported_violations.insert(violation.clone()) {
|
||||
continue;
|
||||
if reported_violations.insert(violation.clone()) {
|
||||
err.note(&violation.error_msg());
|
||||
}
|
||||
err.note(&violation.error_msg());
|
||||
}
|
||||
err
|
||||
}
|
||||
@ -1289,10 +1277,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
self.need_type_info_err(body_id, span, self_ty).emit();
|
||||
} else {
|
||||
let mut err = struct_span_err!(self.tcx.sess,
|
||||
span, E0283,
|
||||
"type annotations required: \
|
||||
span, E0283,
|
||||
"type annotations required: \
|
||||
cannot resolve `{}`",
|
||||
predicate);
|
||||
predicate);
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit();
|
||||
}
|
||||
@ -1438,6 +1426,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
ObligationCauseCode::ItemObligation(item_def_id) => {
|
||||
let item_name = tcx.item_path_str(item_def_id);
|
||||
let msg = format!("required by `{}`", item_name);
|
||||
|
||||
if let Some(sp) = tcx.hir.span_if_local(item_def_id) {
|
||||
let sp = tcx.sess.source_map().def_span(sp);
|
||||
err.span_note(sp, &msg);
|
||||
@ -1529,9 +1518,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
parent_trait_ref.skip_binder().self_ty()));
|
||||
let parent_predicate = parent_trait_ref.to_predicate();
|
||||
self.note_obligation_cause_code(err,
|
||||
&parent_predicate,
|
||||
&data.parent_code,
|
||||
obligated_types);
|
||||
&parent_predicate,
|
||||
&data.parent_code,
|
||||
obligated_types);
|
||||
}
|
||||
ObligationCauseCode::CompareImplMethodObligation { .. } => {
|
||||
err.note(
|
||||
@ -1560,21 +1549,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn is_recursive_obligation(&self,
|
||||
obligated_types: &mut Vec<&ty::TyS<'tcx>>,
|
||||
cause_code: &ObligationCauseCode<'tcx>) -> bool {
|
||||
obligated_types: &mut Vec<&ty::TyS<'tcx>>,
|
||||
cause_code: &ObligationCauseCode<'tcx>) -> bool {
|
||||
if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
|
||||
let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
|
||||
for obligated_type in obligated_types {
|
||||
if obligated_type == &parent_trait_ref.skip_binder().self_ty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Summarizes information
|
||||
#[derive(Clone)]
|
||||
pub enum ArgKind {
|
||||
/// An argument of non-tuple type. Parameters are (name, ty)
|
||||
Arg(String, String),
|
||||
@ -1592,11 +1581,11 @@ impl ArgKind {
|
||||
}
|
||||
|
||||
/// Creates an `ArgKind` from the expected type of an
|
||||
/// argument. This has no name (`_`) and no source spans..
|
||||
pub fn from_expected_ty(t: Ty<'_>) -> ArgKind {
|
||||
/// argument. It has no name (`_`) and an optional source span.
|
||||
pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
|
||||
match t.sty {
|
||||
ty::Tuple(ref tys) => ArgKind::Tuple(
|
||||
None,
|
||||
span,
|
||||
tys.iter()
|
||||
.map(|ty| ("_".to_owned(), ty.sty.to_string()))
|
||||
.collect::<Vec<_>>()
|
||||
|
@ -526,7 +526,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
|
||||
if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
|
||||
debug!("process_child_obligations: coinductive match");
|
||||
} else {
|
||||
let cycle : Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
|
||||
let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
|
||||
self.selcx.infcx().report_overflow_error_cycle(&cycle);
|
||||
}
|
||||
}
|
||||
|
@ -661,7 +661,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
let predicates: Vec<_> =
|
||||
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec())
|
||||
.collect();
|
||||
.collect();
|
||||
|
||||
debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
|
||||
predicates);
|
||||
@ -707,7 +707,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
};
|
||||
|
||||
debug!("normalize_param_env_or_error: normalized predicates={:?}",
|
||||
predicates);
|
||||
predicates);
|
||||
|
||||
let region_scope_tree = region::ScopeTree::default();
|
||||
|
||||
@ -851,16 +851,16 @@ fn vtable_methods<'a, 'tcx>(
|
||||
|
||||
// the method may have some early-bound lifetimes, add
|
||||
// regions for those
|
||||
let substs = trait_ref.map_bound(|trait_ref| {
|
||||
Substs::for_item(tcx, def_id, |param, _| {
|
||||
let substs = trait_ref.map_bound(|trait_ref|
|
||||
Substs::for_item(tcx, def_id, |param, _|
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
|
||||
GenericParamDefKind::Type {..} => {
|
||||
trait_ref.substs[param.index as usize]
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
)
|
||||
);
|
||||
|
||||
// the trait type may have higher-ranked lifetimes in it;
|
||||
// so erase them if they appear, so that we get the type
|
||||
|
@ -124,20 +124,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
// Check methods for violations.
|
||||
let mut violations: Vec<_> = self.associated_items(trait_def_id)
|
||||
.filter(|item| item.kind == ty::AssociatedKind::Method)
|
||||
.filter_map(|item| {
|
||||
.filter_map(|item|
|
||||
self.object_safety_violation_for_method(trait_def_id, &item)
|
||||
.map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
|
||||
}).filter(|violation| {
|
||||
).filter(|violation| {
|
||||
if let ObjectSafetyViolation::Method(_,
|
||||
MethodViolationCode::WhereClauseReferencesSelf(span)) = violation {
|
||||
// Using`CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
|
||||
MethodViolationCode::WhereClauseReferencesSelf(span)) = violation
|
||||
{
|
||||
// Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
|
||||
// It's also hard to get a use site span, so we use the method definition span.
|
||||
self.lint_node_note(
|
||||
lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY,
|
||||
ast::CRATE_NODE_ID,
|
||||
*span,
|
||||
&format!("the trait `{}` cannot be made into an object",
|
||||
self.item_path_str(trait_def_id)),
|
||||
self.item_path_str(trait_def_id)),
|
||||
&violation.error_msg());
|
||||
false
|
||||
} else {
|
||||
@ -213,24 +214,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
let predicates = self.predicates_of(def_id);
|
||||
let predicates = predicates.instantiate_identity(self).predicates;
|
||||
elaborate_predicates(self, predicates)
|
||||
.any(|predicate| {
|
||||
match predicate {
|
||||
ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
|
||||
trait_pred.skip_binder().self_ty().is_self()
|
||||
}
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::TypeOutlives(..) |
|
||||
ty::Predicate::ConstEvaluatable(..) => {
|
||||
false
|
||||
}
|
||||
.any(|predicate| match predicate {
|
||||
ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
|
||||
trait_pred.skip_binder().self_ty().is_self()
|
||||
}
|
||||
})
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::TypeOutlives(..) |
|
||||
ty::Predicate::ConstEvaluatable(..) => {
|
||||
false
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns `Some(_)` if this method makes the containing trait not object safe.
|
||||
|
@ -74,17 +74,17 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
|
||||
let condition = if is_root {
|
||||
None
|
||||
} else {
|
||||
let cond = item_iter.next().ok_or_else(|| {
|
||||
let cond = item_iter.next().ok_or_else(||
|
||||
parse_error(tcx, span,
|
||||
"empty `on`-clause in `#[rustc_on_unimplemented]`",
|
||||
"empty on-clause here",
|
||||
None)
|
||||
})?.meta_item().ok_or_else(|| {
|
||||
)?.meta_item().ok_or_else(||
|
||||
parse_error(tcx, span,
|
||||
"invalid `on`-clause in `#[rustc_on_unimplemented]`",
|
||||
"invalid on-clause here",
|
||||
None)
|
||||
})?;
|
||||
)?;
|
||||
attr::eval_condition(cond, &tcx.sess.parse_sess, &mut |_| true);
|
||||
Some(cond.clone())
|
||||
};
|
||||
@ -259,9 +259,9 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
||||
// `{from_desugaring}` is allowed
|
||||
Position::ArgumentNamed(s) if s == "from_desugaring" => (),
|
||||
// So is `{A}` if A is a type parameter
|
||||
Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
|
||||
Position::ArgumentNamed(s) => match generics.params.iter().find(|param|
|
||||
param.name == s
|
||||
}) {
|
||||
) {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
span_err!(tcx.sess, span, E0230,
|
||||
@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
||||
let empty_string = String::new();
|
||||
|
||||
let parser = Parser::new(&self.0, None);
|
||||
parser.map(|p| {
|
||||
parser.map(|p|
|
||||
match p {
|
||||
Piece::String(s) => s,
|
||||
Piece::NextArgument(a) => match a.position {
|
||||
@ -326,11 +326,9 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
bug!("broken on_unimplemented {:?} - bad format arg", self.0)
|
||||
}
|
||||
_ => bug!("broken on_unimplemented {:?} - bad format arg", self.0)
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
).collect()
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
|
||||
match (current, candidate) {
|
||||
(ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
|
||||
(ParamEnv(..), _) => return false,
|
||||
(_, ParamEnv(..)) => { unreachable!(); }
|
||||
(_, ParamEnv(..)) => unreachable!(),
|
||||
(_, _) => convert_to_ambiguous = (),
|
||||
}
|
||||
}
|
||||
@ -419,9 +419,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||
normalized_ty
|
||||
}
|
||||
|
||||
_ => {
|
||||
ty
|
||||
}
|
||||
_ => ty
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,12 +435,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(evaluated) => {
|
||||
let evaluated = evaluated.subst(self.tcx(), substs);
|
||||
return self.fold_const(evaluated);
|
||||
}
|
||||
Err(_) => {}
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
let evaluated = evaluated.subst(self.tcx(), substs);
|
||||
return self.fold_const(evaluated);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -453,9 +448,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(evaluated) => return self.fold_const(evaluated),
|
||||
Err(_) => {}
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
return self.fold_const(evaluated)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -993,7 +987,7 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
|
||||
candidate_set.mark_ambiguous();
|
||||
return;
|
||||
}
|
||||
_ => { return; }
|
||||
_ => return
|
||||
};
|
||||
|
||||
// If so, extract what we know from the trait and try to come up with a good answer.
|
||||
@ -1023,33 +1017,30 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>(
|
||||
for predicate in env_predicates {
|
||||
debug!("assemble_candidates_from_predicates: predicate={:?}",
|
||||
predicate);
|
||||
match predicate {
|
||||
ty::Predicate::Projection(data) => {
|
||||
let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
|
||||
if let ty::Predicate::Projection(data) = predicate {
|
||||
let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
|
||||
|
||||
let is_match = same_def_id && infcx.probe(|_| {
|
||||
let data_poly_trait_ref =
|
||||
data.to_poly_trait_ref(infcx.tcx);
|
||||
let obligation_poly_trait_ref =
|
||||
obligation_trait_ref.to_poly_trait_ref();
|
||||
infcx.at(&obligation.cause, obligation.param_env)
|
||||
.sup(obligation_poly_trait_ref, data_poly_trait_ref)
|
||||
.map(|InferOk { obligations: _, value: () }| {
|
||||
// FIXME(#32730) -- do we need to take obligations
|
||||
// into account in any way? At the moment, no.
|
||||
})
|
||||
.is_ok()
|
||||
});
|
||||
let is_match = same_def_id && infcx.probe(|_| {
|
||||
let data_poly_trait_ref =
|
||||
data.to_poly_trait_ref(infcx.tcx);
|
||||
let obligation_poly_trait_ref =
|
||||
obligation_trait_ref.to_poly_trait_ref();
|
||||
infcx.at(&obligation.cause, obligation.param_env)
|
||||
.sup(obligation_poly_trait_ref, data_poly_trait_ref)
|
||||
.map(|InferOk { obligations: _, value: () }| {
|
||||
// FIXME(#32730) -- do we need to take obligations
|
||||
// into account in any way? At the moment, no.
|
||||
})
|
||||
.is_ok()
|
||||
});
|
||||
|
||||
debug!("assemble_candidates_from_predicates: candidate={:?} \
|
||||
is_match={} same_def_id={}",
|
||||
data, is_match, same_def_id);
|
||||
debug!("assemble_candidates_from_predicates: candidate={:?} \
|
||||
is_match={} same_def_id={}",
|
||||
data, is_match, same_def_id);
|
||||
|
||||
if is_match {
|
||||
candidate_set.push_candidate(ctor(data));
|
||||
}
|
||||
if is_match {
|
||||
candidate_set.push_candidate(ctor(data));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1072,8 +1063,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
|
||||
return Err(());
|
||||
}
|
||||
Err(e) => {
|
||||
debug!("assemble_candidates_from_impls: selection error {:?}",
|
||||
e);
|
||||
debug!("assemble_candidates_from_impls: selection error {:?}", e);
|
||||
candidate_set.mark_error(e);
|
||||
return Err(());
|
||||
}
|
||||
@ -1295,11 +1285,11 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
|
||||
let mut env_predicates = env_predicates.filter(|data| {
|
||||
let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
|
||||
let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
|
||||
selcx.infcx().probe(|_| {
|
||||
selcx.infcx().probe(|_|
|
||||
selcx.infcx().at(&obligation.cause, obligation.param_env)
|
||||
.sup(obligation_poly_trait_ref, data_poly_trait_ref)
|
||||
.is_ok()
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
// select the first matching one; there really ought to be one or
|
||||
@ -1447,7 +1437,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(
|
||||
obligation.predicate.self_ty(),
|
||||
fn_sig,
|
||||
flag)
|
||||
.map_bound(|(trait_ref, ret_type)| {
|
||||
.map_bound(|(trait_ref, ret_type)|
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: ty::ProjectionTy::from_ref_and_name(
|
||||
tcx,
|
||||
@ -1456,7 +1446,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(
|
||||
),
|
||||
ty: ret_type
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
confirm_param_env_candidate(selcx, obligation, predicate)
|
||||
}
|
||||
|
@ -57,22 +57,19 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
|
||||
debug!("c_ty = {:?}", c_ty);
|
||||
match &gcx.dropck_outlives(c_ty) {
|
||||
Ok(result) if result.is_proven() => {
|
||||
match self.infcx.instantiate_query_result_and_region_obligations(
|
||||
if let Ok(InferOk { value, obligations }) =
|
||||
self.infcx.instantiate_query_result_and_region_obligations(
|
||||
self.cause,
|
||||
self.param_env,
|
||||
&orig_values,
|
||||
result,
|
||||
) {
|
||||
Ok(InferOk { value, obligations }) => {
|
||||
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
|
||||
let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
|
||||
return InferOk {
|
||||
value: kinds,
|
||||
obligations,
|
||||
};
|
||||
}
|
||||
|
||||
Err(_) => { /* fallthrough to error-handling code below */ }
|
||||
result)
|
||||
{
|
||||
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
|
||||
let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
|
||||
return InferOk {
|
||||
value: kinds,
|
||||
obligations,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,12 +158,7 @@ impl<'tcx> FromIterator<DtorckConstraint<'tcx>> for DtorckConstraint<'tcx> {
|
||||
fn from_iter<I: IntoIterator<Item = DtorckConstraint<'tcx>>>(iter: I) -> Self {
|
||||
let mut result = Self::empty();
|
||||
|
||||
for DtorckConstraint {
|
||||
outlives,
|
||||
dtorck_types,
|
||||
overflows,
|
||||
} in iter
|
||||
{
|
||||
for DtorckConstraint { outlives, dtorck_types, overflows } in iter {
|
||||
result.outlives.extend(outlives);
|
||||
result.dtorck_types.extend(dtorck_types);
|
||||
result.overflows.extend(overflows);
|
||||
@ -254,7 +246,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
|
||||
}
|
||||
}
|
||||
|
||||
// The following *might* require a destructor: it would deeper inspection to tell.
|
||||
// The following *might* require a destructor: needs deeper inspection.
|
||||
ty::Dynamic(..)
|
||||
| ty::Projection(..)
|
||||
| ty::Param(_)
|
||||
|
@ -48,6 +48,13 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
|
||||
value,
|
||||
self.param_env,
|
||||
);
|
||||
if !value.has_projections() {
|
||||
return Ok(Normalized {
|
||||
value: value.clone(),
|
||||
obligations: vec![],
|
||||
});
|
||||
}
|
||||
|
||||
let mut normalizer = QueryNormalizer {
|
||||
infcx: self.infcx,
|
||||
cause: self.cause,
|
||||
@ -56,12 +63,6 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
|
||||
error: false,
|
||||
anon_depth: 0,
|
||||
};
|
||||
if !value.has_projections() {
|
||||
return Ok(Normalized {
|
||||
value: value.clone(),
|
||||
obligations: vec![],
|
||||
});
|
||||
}
|
||||
|
||||
let value1 = value.fold_with(&mut normalizer);
|
||||
if normalizer.error {
|
||||
@ -154,8 +155,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
||||
let gcx = self.infcx.tcx.global_tcx();
|
||||
|
||||
let mut orig_values = SmallVec::new();
|
||||
let c_data = self.infcx
|
||||
.canonicalize_query(&self.param_env.and(*data), &mut orig_values);
|
||||
let c_data = self.infcx.canonicalize_query(
|
||||
&self.param_env.and(*data), &mut orig_values);
|
||||
debug!("QueryNormalizer: c_data = {:#?}", c_data);
|
||||
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
|
||||
match gcx.normalize_projection_ty(c_data) {
|
||||
@ -170,12 +171,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
||||
self.cause,
|
||||
self.param_env,
|
||||
&orig_values,
|
||||
&result,
|
||||
) {
|
||||
Ok(InferOk {
|
||||
value: result,
|
||||
obligations,
|
||||
}) => {
|
||||
&result)
|
||||
{
|
||||
Ok(InferOk { value: result, obligations }) => {
|
||||
debug!("QueryNormalizer: result = {:#?}", result);
|
||||
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
||||
self.obligations.extend(obligations);
|
||||
@ -212,12 +210,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(evaluated) => {
|
||||
let evaluated = evaluated.subst(self.tcx(), substs);
|
||||
return self.fold_const(evaluated);
|
||||
}
|
||||
Err(_) => {}
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
let evaluated = evaluated.subst(self.tcx(), substs);
|
||||
return self.fold_const(evaluated);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -228,9 +223,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(evaluated) => return self.fold_const(evaluated),
|
||||
Err(_) => {}
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
return self.fold_const(evaluated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ use rustc_target::spec::abi::Abi;
|
||||
use hir;
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
|
||||
|
||||
pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
||||
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
||||
|
||||
@ -149,7 +148,7 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> {
|
||||
#[derive(Clone)]
|
||||
pub struct SelectionCache<'tcx> {
|
||||
hashmap: Lock<FxHashMap<ty::TraitRef<'tcx>,
|
||||
WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>>,
|
||||
WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>>,
|
||||
}
|
||||
|
||||
/// The selection process begins by considering all impls, where
|
||||
@ -623,9 +622,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
obligation: &PredicateObligation<'tcx>)
|
||||
-> Result<EvaluationResult, OverflowError>
|
||||
{
|
||||
self.probe(|this, _| {
|
||||
self.probe(|this, _|
|
||||
this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/// Evaluates the predicates in `predicates` recursively. Note that
|
||||
@ -717,13 +716,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
self.infcx.projection_cache.borrow_mut().complete(key);
|
||||
}
|
||||
result
|
||||
}
|
||||
Ok(None) => {
|
||||
Ok(EvaluatedToAmbig)
|
||||
}
|
||||
Err(_) => {
|
||||
Ok(EvaluatedToErr)
|
||||
}
|
||||
},
|
||||
Ok(None) => Ok(EvaluatedToAmbig),
|
||||
Err(_) => Ok(EvaluatedToErr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,10 +730,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
} else {
|
||||
Ok(EvaluatedToErr)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
Ok(EvaluatedToAmbig)
|
||||
}
|
||||
},
|
||||
None => Ok(EvaluatedToAmbig)
|
||||
}
|
||||
}
|
||||
|
||||
@ -901,13 +894,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
// same unbound type variable.
|
||||
if let Some(rec_index) =
|
||||
stack.iter()
|
||||
.skip(1) // skip top-most frame
|
||||
.position(|prev| stack.obligation.param_env == prev.obligation.param_env &&
|
||||
stack.fresh_trait_ref == prev.fresh_trait_ref)
|
||||
.skip(1) // skip top-most frame
|
||||
.position(|prev| stack.obligation.param_env == prev.obligation.param_env &&
|
||||
stack.fresh_trait_ref == prev.fresh_trait_ref)
|
||||
{
|
||||
debug!("evaluate_stack({:?}) --> recursive",
|
||||
stack.fresh_trait_ref);
|
||||
let cycle = stack.iter().skip(1).take(rec_index+1);
|
||||
let cycle = stack.iter().skip(1).take(rec_index + 1);
|
||||
let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate));
|
||||
if self.coinductive_match(cycle) {
|
||||
debug!("evaluate_stack({:?}) --> recursive, coinductive",
|
||||
@ -947,10 +940,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
let result = match predicate {
|
||||
ty::Predicate::Trait(ref data) => {
|
||||
self.tcx().trait_is_auto(data.def_id())
|
||||
}
|
||||
_ => {
|
||||
false
|
||||
}
|
||||
},
|
||||
_ => false
|
||||
};
|
||||
debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
|
||||
result
|
||||
@ -1088,9 +1079,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// If no match, compute result and insert into cache.
|
||||
let (candidate, dep_node) = self.in_task(|this| {
|
||||
let (candidate, dep_node) = self.in_task(|this|
|
||||
this.candidate_from_obligation_no_cache(stack)
|
||||
});
|
||||
);
|
||||
|
||||
debug!("CACHE MISS: SELECT({:?})={:?}",
|
||||
cache_fresh_trait_pred, candidate);
|
||||
@ -1104,9 +1095,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
|
||||
where OP: FnOnce(&mut Self) -> R
|
||||
{
|
||||
let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || {
|
||||
let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, ||
|
||||
op(self)
|
||||
});
|
||||
);
|
||||
self.tcx().dep_graph.read_index(dep_node);
|
||||
(result, dep_node)
|
||||
}
|
||||
@ -1138,46 +1129,53 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
match self.is_knowable(stack) {
|
||||
None => {}
|
||||
Some(conflict) => {
|
||||
debug!("coherence stage: not knowable");
|
||||
if self.intercrate_ambiguity_causes.is_some() {
|
||||
debug!("evaluate_stack: intercrate_ambiguity_causes is some");
|
||||
// Heuristics: show the diagnostics when there are no candidates in crate.
|
||||
if let Ok(candidate_set) = self.assemble_candidates(stack) {
|
||||
let no_candidates_apply =
|
||||
candidate_set
|
||||
.vec
|
||||
.iter()
|
||||
.map(|c| self.evaluate_candidate(stack, &c))
|
||||
.collect::<Result<Vec<_>, OverflowError>>()?
|
||||
.iter()
|
||||
.all(|r| !r.may_apply());
|
||||
if !candidate_set.ambiguous && no_candidates_apply {
|
||||
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let trait_desc = trait_ref.to_string();
|
||||
let self_desc = if self_ty.has_concrete_skeleton() {
|
||||
Some(self_ty.to_string())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let cause = if let Conflict::Upstream = conflict {
|
||||
IntercrateAmbiguityCause::UpstreamCrateUpdate {
|
||||
trait_desc,
|
||||
self_desc,
|
||||
}
|
||||
} else {
|
||||
IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
|
||||
};
|
||||
debug!("evaluate_stack: pushing cause = {:?}", cause);
|
||||
self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
|
||||
if let Some(conflict) = self.is_knowable(stack) {
|
||||
debug!("coherence stage: not knowable");
|
||||
if self.intercrate_ambiguity_causes.is_some() {
|
||||
debug!("evaluate_stack: intercrate_ambiguity_causes is some");
|
||||
// Heuristics: show the diagnostics when there are no candidates in crate.
|
||||
if let Ok(candidate_set) = self.assemble_candidates(stack) {
|
||||
let mut no_candidates_apply = true;
|
||||
{
|
||||
let evaluated_candidates = candidate_set.vec.iter().map(|c|
|
||||
self.evaluate_candidate(stack, &c));
|
||||
|
||||
for ec in evaluated_candidates {
|
||||
match ec {
|
||||
Ok(c) => {
|
||||
if c.may_apply() {
|
||||
no_candidates_apply = false;
|
||||
break
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(e.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !candidate_set.ambiguous && no_candidates_apply {
|
||||
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let trait_desc = trait_ref.to_string();
|
||||
let self_desc = if self_ty.has_concrete_skeleton() {
|
||||
Some(self_ty.to_string())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let cause = if let Conflict::Upstream = conflict {
|
||||
IntercrateAmbiguityCause::UpstreamCrateUpdate {
|
||||
trait_desc,
|
||||
self_desc,
|
||||
}
|
||||
} else {
|
||||
IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
|
||||
};
|
||||
debug!("evaluate_stack: pushing cause = {:?}", cause);
|
||||
self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
|
||||
}
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let candidate_set = self.assemble_candidates(stack)?;
|
||||
@ -1434,9 +1432,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
|
||||
// Other bounds. Consider both in-scope bounds from fn decl
|
||||
// and applicable impls. There is a certain set of precedence rules here.
|
||||
|
||||
let def_id = obligation.predicate.def_id();
|
||||
let lang_items = self.tcx().lang_items();
|
||||
|
||||
if lang_items.copy_trait() == Some(def_id) {
|
||||
debug!("obligation self ty is {:?}",
|
||||
obligation.predicate.skip_binder().self_ty());
|
||||
@ -1495,15 +1493,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
ty::Projection(_) | ty::Opaque(..) => {}
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
span_bug!(obligation.cause.span,
|
||||
"Self=_ should have been handled by assemble_candidates");
|
||||
"Self=_ should have been handled by assemble_candidates");
|
||||
}
|
||||
_ => return
|
||||
}
|
||||
|
||||
let result = self.probe(|this, snapshot| {
|
||||
let result = self.probe(|this, snapshot|
|
||||
this.match_projection_obligation_against_definition_bounds(obligation,
|
||||
snapshot)
|
||||
});
|
||||
);
|
||||
|
||||
if result {
|
||||
candidates.vec.push(ProjectionCandidate);
|
||||
@ -1533,7 +1531,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
span_bug!(
|
||||
obligation.cause.span,
|
||||
"match_projection_obligation_against_definition_bounds() called \
|
||||
but self-ty not a projection: {:?}",
|
||||
but self-ty is not a projection: {:?}",
|
||||
skol_trait_predicate.trait_ref.self_ty());
|
||||
}
|
||||
};
|
||||
@ -1637,14 +1635,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
|
||||
-> Result<EvaluationResult, OverflowError>
|
||||
{
|
||||
self.probe(move |this, _| {
|
||||
self.probe(move |this, _|
|
||||
match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
|
||||
Ok(obligations) => {
|
||||
this.evaluate_predicates_recursively(stack.list(), obligations.iter())
|
||||
}
|
||||
Err(()) => Ok(EvaluatedToErr)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
fn assemble_generator_candidates(&mut self,
|
||||
@ -1667,15 +1665,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
obligation);
|
||||
|
||||
candidates.vec.push(GeneratorCandidate);
|
||||
Ok(())
|
||||
}
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
debug!("assemble_generator_candidates: ambiguous self-type");
|
||||
candidates.ambiguous = true;
|
||||
return Ok(());
|
||||
}
|
||||
_ => { return Ok(()); }
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check for the artificial impl that the compiler will create for an obligation like `X :
|
||||
@ -1712,16 +1710,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
debug!("assemble_unboxed_candidates: closure_kind not yet known");
|
||||
candidates.vec.push(ClosureCandidate);
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
|
||||
candidates.ambiguous = true;
|
||||
return Ok(());
|
||||
}
|
||||
_ => { return Ok(()); }
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Implement one of the `Fn()` family for a fn pointer.
|
||||
@ -1742,7 +1740,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
debug!("assemble_fn_pointer_candidates: ambiguous self-type");
|
||||
candidates.ambiguous = true; // could wind up being a fn() type
|
||||
}
|
||||
|
||||
// provide an impl, but only for suitable `fn` pointers
|
||||
ty::FnDef(..) | ty::FnPtr(_) => {
|
||||
if let ty::FnSig {
|
||||
@ -1754,8 +1751,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
candidates.vec.push(FnPointerCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -1773,18 +1769,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
obligation.predicate.def_id(),
|
||||
obligation.predicate.skip_binder().trait_ref.self_ty(),
|
||||
|impl_def_id| {
|
||||
self.probe(|this, snapshot| { /* [1] */
|
||||
match this.match_impl(impl_def_id, obligation, snapshot) {
|
||||
Ok(skol_map) => {
|
||||
candidates.vec.push(ImplCandidate(impl_def_id));
|
||||
self.probe(|this, snapshot| /* [1] */
|
||||
if let Ok(skol_map) = this.match_impl(impl_def_id, obligation, snapshot) {
|
||||
candidates.vec.push(ImplCandidate(impl_def_id));
|
||||
|
||||
// NB: we can safely drop the skol map
|
||||
// since we are in a probe [1]
|
||||
mem::drop(skol_map);
|
||||
}
|
||||
Err(_) => { }
|
||||
// NB: we can safely drop the skol map
|
||||
// since we are in a probe [1]
|
||||
mem::drop(skol_map);
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@ -1874,7 +1867,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
ty::Dynamic(ref data, ..) => {
|
||||
if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
|
||||
debug!("assemble_candidates_from_object_ty: matched builtin bound, \
|
||||
pushing candidate");
|
||||
pushing candidate");
|
||||
candidates.vec.push(BuiltinObjectCandidate);
|
||||
return;
|
||||
}
|
||||
@ -1889,9 +1882,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
candidates.ambiguous = true; // could wind up being an object type
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
return;
|
||||
}
|
||||
_ => return
|
||||
};
|
||||
|
||||
debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}",
|
||||
@ -1904,12 +1895,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
// but `Foo` is declared as `trait Foo : Bar<u32>`.
|
||||
let upcast_trait_refs =
|
||||
util::supertraits(this.tcx(), poly_trait_ref)
|
||||
.filter(|upcast_trait_ref| {
|
||||
.filter(|upcast_trait_ref|
|
||||
this.probe(|this, _| {
|
||||
let upcast_trait_ref = upcast_trait_ref.clone();
|
||||
this.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok()
|
||||
})
|
||||
})
|
||||
)
|
||||
.count();
|
||||
|
||||
if upcast_trait_refs > 1 {
|
||||
@ -2028,6 +2019,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
other: &EvaluatedCandidate<'tcx>)
|
||||
-> bool
|
||||
{
|
||||
if victim.candidate == other.candidate {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if a bound would previously have been removed when normalizing
|
||||
// the param_env so that it can be given the lowest priority. See
|
||||
// #50825 for the motivation for this.
|
||||
@ -2035,10 +2030,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
cand.is_global() && !cand.has_late_bound_regions()
|
||||
};
|
||||
|
||||
if victim.candidate == other.candidate {
|
||||
return true;
|
||||
}
|
||||
|
||||
match other.candidate {
|
||||
// Prefer BuiltinCandidate { has_nested: false } to anything else.
|
||||
// This is a fix for #53123 and prevents winnowing from accidentally extending the
|
||||
@ -2046,9 +2037,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
BuiltinCandidate { has_nested: false } => true,
|
||||
ParamCandidate(ref cand) => match victim.candidate {
|
||||
AutoImplCandidate(..) => {
|
||||
bug!(
|
||||
"default implementations shouldn't be recorded \
|
||||
when there are other valid candidates");
|
||||
bug!("default implementations shouldn't be recorded \
|
||||
when there are other valid candidates");
|
||||
}
|
||||
// Prefer BuiltinCandidate { has_nested: false } to anything else.
|
||||
// This is a fix for #53123 and prevents winnowing from accidentally extending the
|
||||
@ -2077,9 +2067,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
ObjectCandidate |
|
||||
ProjectionCandidate => match victim.candidate {
|
||||
AutoImplCandidate(..) => {
|
||||
bug!(
|
||||
"default implementations shouldn't be recorded \
|
||||
when there are other valid candidates");
|
||||
bug!("default implementations shouldn't be recorded \
|
||||
when there are other valid candidates");
|
||||
}
|
||||
// Prefer BuiltinCandidate { has_nested: false } to anything else.
|
||||
// This is a fix for #53123 and prevents winnowing from accidentally extending the
|
||||
@ -2151,7 +2140,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
fn assemble_builtin_bound_candidates<'o>(&mut self,
|
||||
conditions: BuiltinImplConditions<'tcx>,
|
||||
candidates: &mut SelectionCandidateSet<'tcx>)
|
||||
-> Result<(),SelectionError<'tcx>>
|
||||
-> Result<(), SelectionError<'tcx>>
|
||||
{
|
||||
match conditions {
|
||||
BuiltinImplConditions::Where(nested) => {
|
||||
@ -2159,18 +2148,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
candidates.vec.push(BuiltinCandidate {
|
||||
has_nested: nested.skip_binder().len() > 0
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
BuiltinImplConditions::None => { Ok(()) }
|
||||
BuiltinImplConditions::None => {}
|
||||
BuiltinImplConditions::Ambiguous => {
|
||||
debug!("assemble_builtin_bound_candidates: ambiguous builtin");
|
||||
Ok(candidates.ambiguous = true)
|
||||
candidates.ambiguous = true;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
|
||||
-> BuiltinImplConditions<'tcx>
|
||||
fn sized_conditions(&mut self,
|
||||
obligation: &TraitObligation<'tcx>)
|
||||
-> BuiltinImplConditions<'tcx>
|
||||
{
|
||||
use self::BuiltinImplConditions::{Ambiguous, None, Where};
|
||||
|
||||
@ -2216,8 +2207,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_clone_conditions(&mut self, obligation: &TraitObligation<'tcx>)
|
||||
-> BuiltinImplConditions<'tcx>
|
||||
fn copy_clone_conditions(&mut self,
|
||||
obligation: &TraitObligation<'tcx>)
|
||||
-> BuiltinImplConditions<'tcx>
|
||||
{
|
||||
// NOTE: binder moved to (*)
|
||||
let self_ty = self.infcx.shallow_resolve(
|
||||
@ -2551,17 +2543,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
let lang_items = self.tcx().lang_items();
|
||||
let obligations = if has_nested {
|
||||
let trait_def = obligation.predicate.def_id();
|
||||
let conditions = match trait_def {
|
||||
_ if Some(trait_def) == lang_items.sized_trait() => {
|
||||
let conditions =
|
||||
if Some(trait_def) == lang_items.sized_trait() {
|
||||
self.sized_conditions(obligation)
|
||||
}
|
||||
_ if Some(trait_def) == lang_items.copy_trait() => {
|
||||
} else if Some(trait_def) == lang_items.copy_trait() {
|
||||
self.copy_clone_conditions(obligation)
|
||||
}
|
||||
_ if Some(trait_def) == lang_items.clone_trait() => {
|
||||
} else if Some(trait_def) == lang_items.clone_trait() {
|
||||
self.copy_clone_conditions(obligation)
|
||||
}
|
||||
_ => bug!("unexpected builtin trait {:?}", trait_def)
|
||||
} else {
|
||||
bug!("unexpected builtin trait {:?}", trait_def)
|
||||
};
|
||||
let nested = match conditions {
|
||||
BuiltinImplConditions::Where(nested) => nested,
|
||||
@ -2608,10 +2598,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
|
||||
/// See `confirm_auto_impl_candidate`
|
||||
fn vtable_auto_impl(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
trait_def_id: DefId,
|
||||
nested: ty::Binder<Vec<Ty<'tcx>>>)
|
||||
-> VtableAutoImplData<PredicateObligation<'tcx>>
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
trait_def_id: DefId,
|
||||
nested: ty::Binder<Vec<Ty<'tcx>>>)
|
||||
-> VtableAutoImplData<PredicateObligation<'tcx>>
|
||||
{
|
||||
debug!("vtable_auto_impl: nested={:?}", nested);
|
||||
|
||||
@ -2731,10 +2721,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
ty::Dynamic(ref data, ..) => {
|
||||
data.principal().unwrap().with_self_ty(self.tcx(), self_ty)
|
||||
}
|
||||
_ => {
|
||||
span_bug!(obligation.cause.span,
|
||||
"object candidate with non-object");
|
||||
}
|
||||
_ => span_bug!(obligation.cause.span,
|
||||
"object candidate with non-object")
|
||||
};
|
||||
|
||||
let mut upcast_trait_ref = None;
|
||||
@ -2752,10 +2740,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
// record it for later.)
|
||||
let nonmatching =
|
||||
util::supertraits(tcx, poly_trait_ref)
|
||||
.take_while(|&t| {
|
||||
match
|
||||
self.commit_if_ok(
|
||||
|this, _| this.match_poly_trait_ref(obligation, t))
|
||||
.take_while(|&t|
|
||||
match self.commit_if_ok(|this, _|
|
||||
this.match_poly_trait_ref(obligation, t))
|
||||
{
|
||||
Ok(obligations) => {
|
||||
upcast_trait_ref = Some(t);
|
||||
@ -2764,16 +2751,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
Err(_) => { true }
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
// Additionally, for each of the nonmatching predicates that
|
||||
// we pass over, we sum up the set of number of vtable
|
||||
// entries, so that we can compute the offset for the selected
|
||||
// trait.
|
||||
vtable_base =
|
||||
nonmatching.map(|t| tcx.count_own_vtable_entries(t))
|
||||
.sum();
|
||||
|
||||
vtable_base = nonmatching.map(|t| tcx.count_own_vtable_entries(t)).sum();
|
||||
}
|
||||
|
||||
VtableObjectData {
|
||||
@ -2816,7 +2800,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
fn confirm_generator_candidate(&mut self,
|
||||
obligation: &TraitObligation<'tcx>)
|
||||
-> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
|
||||
SelectionError<'tcx>>
|
||||
SelectionError<'tcx>>
|
||||
{
|
||||
// ok to skip binder because the substs on generator types never
|
||||
// touch bound regions, they just capture the in-scope
|
||||
@ -2869,10 +2853,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
{
|
||||
debug!("confirm_closure_candidate({:?})", obligation);
|
||||
|
||||
let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) {
|
||||
Some(k) => k,
|
||||
None => bug!("closure candidate for non-fn trait {:?}", obligation)
|
||||
};
|
||||
let kind = self.tcx()
|
||||
.lang_items()
|
||||
.fn_trait_kind(obligation.predicate.def_id())
|
||||
.unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}",
|
||||
obligation));
|
||||
|
||||
// ok to skip binder because the substs on closure types never
|
||||
// touch bound regions, they just capture the in-scope
|
||||
@ -2901,9 +2886,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
|
||||
obligations.extend(
|
||||
self.confirm_poly_trait_refs(obligation.cause.clone(),
|
||||
obligation.param_env,
|
||||
obligation.predicate.to_poly_trait_ref(),
|
||||
trait_ref)?);
|
||||
obligation.param_env,
|
||||
obligation.predicate.to_poly_trait_ref(),
|
||||
trait_ref)?);
|
||||
|
||||
obligations.push(Obligation::new(
|
||||
obligation.cause.clone(),
|
||||
@ -3008,20 +2993,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
(_, &ty::Dynamic(ref data, r)) => {
|
||||
let mut object_dids =
|
||||
data.auto_traits().chain(data.principal().map(|p| p.def_id()));
|
||||
if let Some(did) = object_dids.find(|did| {
|
||||
!tcx.is_object_safe(*did)
|
||||
}) {
|
||||
if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
|
||||
return Err(TraitNotObjectSafe(did))
|
||||
}
|
||||
|
||||
let cause = ObligationCause::new(obligation.cause.span,
|
||||
obligation.cause.body_id,
|
||||
ObjectCastObligation(target));
|
||||
let mut push = |predicate| {
|
||||
nested.push(Obligation::with_depth(cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
obligation.param_env,
|
||||
predicate));
|
||||
|
||||
let predicate_to_obligation = |predicate| {
|
||||
Obligation::with_depth(cause.clone(),
|
||||
obligation.recursion_depth + 1,
|
||||
obligation.param_env,
|
||||
predicate)
|
||||
};
|
||||
|
||||
// Create obligations:
|
||||
@ -3030,21 +3014,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
// words, if the object type is Foo+Send, this would create an obligation for the
|
||||
// Send check.)
|
||||
// - Projection predicates
|
||||
for predicate in data.iter() {
|
||||
push(predicate.with_self_ty(tcx, source));
|
||||
}
|
||||
nested.extend(data.iter().map(|d|
|
||||
predicate_to_obligation(d.with_self_ty(tcx, source))
|
||||
));
|
||||
|
||||
// We can only make objects from sized types.
|
||||
let tr = ty::TraitRef {
|
||||
def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem),
|
||||
substs: tcx.mk_substs_trait(source, &[]),
|
||||
};
|
||||
push(tr.to_predicate());
|
||||
nested.push(predicate_to_obligation(tr.to_predicate()));
|
||||
|
||||
// If the type is `Foo+'a`, ensures that the type
|
||||
// being cast to `Foo+'a` outlives `'a`:
|
||||
let outlives = ty::OutlivesPredicate(source, r);
|
||||
push(ty::Binder::dummy(outlives).to_predicate());
|
||||
nested.push(predicate_to_obligation(
|
||||
ty::Binder::dummy(outlives).to_predicate()));
|
||||
}
|
||||
|
||||
// [T; n] -> [T].
|
||||
@ -3105,13 +3090,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
|
||||
// Check that the source struct with the target's
|
||||
// unsized parameters is equal to the target.
|
||||
let params = substs_a.iter().enumerate().map(|(i, &k)| {
|
||||
let params = substs_a.iter().enumerate().map(|(i, &k)|
|
||||
if ty_params.contains(i) {
|
||||
substs_b.type_at(i).into()
|
||||
} else {
|
||||
k
|
||||
}
|
||||
});
|
||||
);
|
||||
let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
|
||||
let InferOk { obligations, .. } =
|
||||
self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
@ -3236,10 +3221,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
let InferOk { obligations, .. } =
|
||||
self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.eq(skol_obligation_trait_ref, impl_trait_ref)
|
||||
.map_err(|e| {
|
||||
debug!("match_impl: failed eq_trait_refs due to `{}`", e);
|
||||
()
|
||||
})?;
|
||||
.map_err(|e|
|
||||
debug!("match_impl: failed eq_trait_refs due to `{}`", e)
|
||||
)?;
|
||||
nested_obligations.extend(obligations);
|
||||
|
||||
if let Err(e) = self.infcx.leak_check(false,
|
||||
@ -3288,7 +3272,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
fn match_where_clause_trait_ref(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
|
||||
-> Result<Vec<PredicateObligation<'tcx>>,()>
|
||||
-> Result<Vec<PredicateObligation<'tcx>>, ()>
|
||||
{
|
||||
self.match_poly_trait_ref(obligation, where_clause_trait_ref)
|
||||
}
|
||||
@ -3298,7 +3282,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
fn match_poly_trait_ref(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
poly_trait_ref: ty::PolyTraitRef<'tcx>)
|
||||
-> Result<Vec<PredicateObligation<'tcx>>,()>
|
||||
-> Result<Vec<PredicateObligation<'tcx>>, ()>
|
||||
{
|
||||
debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
|
||||
obligation,
|
||||
@ -3350,20 +3334,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
// in fact unparameterized (or at least does not reference any
|
||||
// regions bound in the obligation). Still probably some
|
||||
// refactoring could make this nicer.
|
||||
|
||||
self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
|
||||
obligation.predicate
|
||||
.skip_binder().self_ty(), // (1)
|
||||
.skip_binder()
|
||||
.self_ty(), // (1)
|
||||
closure_type,
|
||||
util::TupleArgumentsFlag::No)
|
||||
.map_bound(|(trait_ref, _)| trait_ref)
|
||||
}
|
||||
|
||||
fn generator_trait_ref_unnormalized(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
substs: ty::GeneratorSubsts<'tcx>)
|
||||
-> ty::PolyTraitRef<'tcx>
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
substs: ty::GeneratorSubsts<'tcx>)
|
||||
-> ty::PolyTraitRef<'tcx>
|
||||
{
|
||||
let gen_sig = substs.poly_sig(closure_def_id, self.tcx());
|
||||
|
||||
@ -3375,7 +3359,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
|
||||
self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(),
|
||||
obligation.predicate
|
||||
.skip_binder().self_ty(), // (1)
|
||||
.skip_binder()
|
||||
.self_ty(), // (1)
|
||||
gen_sig)
|
||||
.map_bound(|(trait_ref, ..)| trait_ref)
|
||||
}
|
||||
@ -3453,8 +3438,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
impl<'tcx> TraitObligation<'tcx> {
|
||||
#[allow(unused_comparisons)]
|
||||
pub fn derived_cause(&self,
|
||||
variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
|
||||
-> ObligationCause<'tcx>
|
||||
variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
|
||||
-> ObligationCause<'tcx>
|
||||
{
|
||||
/*!
|
||||
* Creates a cause for obligations that are derived from
|
||||
|
@ -100,10 +100,10 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||
}
|
||||
|
||||
fulfill_implication(infcx, param_env, source_trait_ref, target_impl)
|
||||
.unwrap_or_else(|_| {
|
||||
.unwrap_or_else(|_|
|
||||
bug!("When translating substitutions for specialization, the expected \
|
||||
specialization failed to hold")
|
||||
})
|
||||
)
|
||||
}
|
||||
specialization_graph::Node::Trait(..) => source_trait_ref.substs,
|
||||
};
|
||||
@ -137,17 +137,15 @@ pub fn find_associated_item<'a, 'tcx>(
|
||||
let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
|
||||
substs, node_item.node);
|
||||
let substs = infcx.tcx.erase_regions(&substs);
|
||||
tcx.lift(&substs).unwrap_or_else(|| {
|
||||
tcx.lift(&substs).unwrap_or_else(||
|
||||
bug!("find_method: translate_substs \
|
||||
returned {:?} which contains inference types/regions",
|
||||
substs);
|
||||
})
|
||||
substs)
|
||||
)
|
||||
});
|
||||
(node_item.item.def_id, substs)
|
||||
}
|
||||
None => {
|
||||
bug!("{:?} not found in {:?}", item, impl_data.impl_def_id)
|
||||
}
|
||||
None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,8 +310,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
|
||||
-> Lrc<specialization_graph::Graph> {
|
||||
let mut sg = specialization_graph::Graph::new();
|
||||
|
||||
let mut trait_impls = Vec::new();
|
||||
tcx.for_each_impl(trait_id, |impl_did| trait_impls.push(impl_did));
|
||||
let mut trait_impls = tcx.all_impls(trait_id);
|
||||
|
||||
// The coherence checking implementation seems to rely on impls being
|
||||
// iterated over (roughly) in definition order, so we are sorting by
|
||||
@ -367,9 +364,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
|
||||
"first implementation here".to_string());
|
||||
err.span_label(impl_span,
|
||||
format!("conflicting implementation{}",
|
||||
overlap.self_desc
|
||||
.map_or(String::new(),
|
||||
|ty| format!(" for `{}`", ty))));
|
||||
overlap.self_desc
|
||||
.map_or(String::new(),
|
||||
|ty| format!(" for `{}`", ty))));
|
||||
}
|
||||
Err(cname) => {
|
||||
let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
|
||||
@ -428,7 +425,9 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option<String> {
|
||||
// The predicates will contain default bounds like `T: Sized`. We need to
|
||||
// remove these bounds, and add `T: ?Sized` to any untouched type parameters.
|
||||
let predicates = tcx.predicates_of(impl_def_id).predicates;
|
||||
let mut pretty_predicates = Vec::with_capacity(predicates.len());
|
||||
let mut pretty_predicates = Vec::with_capacity(
|
||||
predicates.len() + types_without_default_bounds.len());
|
||||
|
||||
for p in predicates {
|
||||
if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
|
||||
if Some(poly_trait_ref.def_id()) == sized_trait {
|
||||
@ -438,9 +437,11 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option<String> {
|
||||
}
|
||||
pretty_predicates.push(p.to_string());
|
||||
}
|
||||
|
||||
pretty_predicates.extend(
|
||||
types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty))
|
||||
);
|
||||
|
||||
if !pretty_predicates.is_empty() {
|
||||
write!(w, "\n where {}", pretty_predicates.join(", ")).unwrap();
|
||||
}
|
||||
|
@ -390,11 +390,12 @@ impl Iterator for Ancestors {
|
||||
let cur = self.current_source.take();
|
||||
if let Some(Node::Impl(cur_impl)) = cur {
|
||||
let parent = self.specialization_graph.parent(cur_impl);
|
||||
if parent == self.trait_def_id {
|
||||
self.current_source = Some(Node::Trait(parent));
|
||||
|
||||
self.current_source = if parent == self.trait_def_id {
|
||||
Some(Node::Trait(parent))
|
||||
} else {
|
||||
self.current_source = Some(Node::Impl(parent));
|
||||
}
|
||||
Some(Node::Impl(parent))
|
||||
};
|
||||
}
|
||||
cur
|
||||
}
|
||||
|
@ -166,10 +166,10 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
|
||||
match *self {
|
||||
super::Unimplemented => Some(super::Unimplemented),
|
||||
super::OutputTypeParameterMismatch(a, b, ref err) => {
|
||||
tcx.lift(&(a, b)).and_then(|(a, b)| {
|
||||
tcx.lift(&(a, b)).and_then(|(a, b)|
|
||||
tcx.lift(err)
|
||||
.map(|err| super::OutputTypeParameterMismatch(a, b, err))
|
||||
})
|
||||
)
|
||||
}
|
||||
super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
|
||||
super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure(
|
||||
@ -193,10 +193,10 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
||||
super::ReferenceOutlivesReferent(ty) => {
|
||||
tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
|
||||
}
|
||||
super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty| {
|
||||
super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty|
|
||||
tcx.lift(&r)
|
||||
.and_then(|r| Some(super::ObjectTypeBound(ty, r)))
|
||||
}),
|
||||
.and_then(|r| Some(super::ObjectTypeBound(ty, r)))
|
||||
),
|
||||
super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
|
||||
super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
|
||||
super::TupleInitializerSized => Some(super::TupleInitializerSized),
|
||||
@ -245,13 +245,13 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
||||
impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
|
||||
type Lifted = traits::DerivedObligationCause<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
|
||||
tcx.lift(&self.parent_trait_ref).and_then(|trait_ref|
|
||||
tcx.lift(&*self.parent_code)
|
||||
.map(|code| traits::DerivedObligationCause {
|
||||
parent_trait_ref: trait_ref,
|
||||
parent_code: Rc::new(code),
|
||||
})
|
||||
})
|
||||
.map(|code| traits::DerivedObligationCause {
|
||||
parent_trait_ref: trait_ref,
|
||||
parent_code: Rc::new(code),
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,40 +275,40 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
|
||||
impl_def_id,
|
||||
substs,
|
||||
nested,
|
||||
}) => tcx.lift(&substs).map(|substs| {
|
||||
}) => tcx.lift(&substs).map(|substs|
|
||||
traits::VtableImpl(traits::VtableImplData {
|
||||
impl_def_id,
|
||||
substs,
|
||||
nested,
|
||||
})
|
||||
}),
|
||||
),
|
||||
traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
|
||||
traits::VtableGenerator(traits::VtableGeneratorData {
|
||||
generator_def_id,
|
||||
substs,
|
||||
nested,
|
||||
}) => tcx.lift(&substs).map(|substs| {
|
||||
}) => tcx.lift(&substs).map(|substs|
|
||||
traits::VtableGenerator(traits::VtableGeneratorData {
|
||||
generator_def_id: generator_def_id,
|
||||
substs: substs,
|
||||
nested: nested,
|
||||
})
|
||||
}),
|
||||
),
|
||||
traits::VtableClosure(traits::VtableClosureData {
|
||||
closure_def_id,
|
||||
substs,
|
||||
nested,
|
||||
}) => tcx.lift(&substs).map(|substs| {
|
||||
}) => tcx.lift(&substs).map(|substs|
|
||||
traits::VtableClosure(traits::VtableClosureData {
|
||||
closure_def_id,
|
||||
substs,
|
||||
nested,
|
||||
})
|
||||
}),
|
||||
),
|
||||
traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
|
||||
tcx.lift(&fn_ty).map(|fn_ty| {
|
||||
tcx.lift(&fn_ty).map(|fn_ty|
|
||||
traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested })
|
||||
})
|
||||
)
|
||||
}
|
||||
traits::VtableParam(n) => Some(traits::VtableParam(n)),
|
||||
traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
|
||||
@ -316,13 +316,13 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
|
||||
upcast_trait_ref,
|
||||
vtable_base,
|
||||
nested,
|
||||
}) => tcx.lift(&upcast_trait_ref).map(|trait_ref| {
|
||||
}) => tcx.lift(&upcast_trait_ref).map(|trait_ref|
|
||||
traits::VtableObject(traits::VtableObjectData {
|
||||
upcast_trait_ref: trait_ref,
|
||||
vtable_base,
|
||||
nested,
|
||||
})
|
||||
}),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -346,8 +346,7 @@ impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
|
||||
Some(ty::Predicate::Trait(data)) => {
|
||||
return Some(data.to_poly_trait_ref());
|
||||
}
|
||||
Some(_) => {
|
||||
}
|
||||
Some(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a vector containing all impls
|
||||
pub fn all_impls(self, def_id: DefId) -> Vec<DefId> {
|
||||
let impls = self.trait_impls_of(def_id);
|
||||
|
||||
impls.blanket_impls.iter().chain(
|
||||
impls.non_blanket_impls.values().flatten()
|
||||
).cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
// Query provider for `trait_impls_of`.
|
||||
|
@ -504,7 +504,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
.sig
|
||||
.inputs()
|
||||
.iter()
|
||||
.map(|ty| ArgKind::from_expected_ty(ty))
|
||||
.map(|ty| ArgKind::from_expected_ty(ty, None))
|
||||
.collect();
|
||||
let (closure_span, found_args) = self.get_fn_like_arguments(expr_map_node);
|
||||
let expected_span = expected_sig.cause_span.unwrap_or(closure_span);
|
||||
|
Loading…
Reference in New Issue
Block a user