parent
f0c4da4998
commit
a7b4d667fe
8 changed files with 176 additions and 218 deletions
|
@ -10,19 +10,20 @@
|
||||||
//!
|
//!
|
||||||
//! This API is completely unstable and subject to change.
|
//! This API is completely unstable and subject to change.
|
||||||
|
|
||||||
|
#![allow(rustc::potential_query_instability)]
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(drain_filter)]
|
#![feature(control_flow_enum)]
|
||||||
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(derive_default_enum)]
|
#![feature(derive_default_enum)]
|
||||||
|
#![feature(drain_filter)]
|
||||||
#![feature(hash_drain_filter)]
|
#![feature(hash_drain_filter)]
|
||||||
#![feature(label_break_value)]
|
#![feature(label_break_value)]
|
||||||
|
#![feature(let_chains)]
|
||||||
#![feature(let_else)]
|
#![feature(let_else)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(crate_visibility_modifier)]
|
|
||||||
#![feature(control_flow_enum)]
|
|
||||||
#![recursion_limit = "512"] // For rustdoc
|
#![recursion_limit = "512"] // For rustdoc
|
||||||
#![allow(rustc::potential_query_instability)]
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rustc_macros;
|
extern crate rustc_macros;
|
||||||
|
|
|
@ -1098,42 +1098,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
|
if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
|
||||||
if fields.len() == found_args.len() && is_closure {
|
&& fields.len() == found_args.len()
|
||||||
let sugg = format!(
|
&& is_closure
|
||||||
"|({}){}|",
|
{
|
||||||
found_args
|
let sugg = format!(
|
||||||
.iter()
|
"|({}){}|",
|
||||||
.map(|arg| match arg {
|
found_args
|
||||||
ArgKind::Arg(name, _) => name.to_owned(),
|
.iter()
|
||||||
_ => "_".to_owned(),
|
.map(|arg| match arg {
|
||||||
})
|
ArgKind::Arg(name, _) => name.to_owned(),
|
||||||
.collect::<Vec<String>>()
|
_ => "_".to_owned(),
|
||||||
.join(", "),
|
})
|
||||||
// add type annotations if available
|
.collect::<Vec<String>>()
|
||||||
if found_args.iter().any(|arg| match arg {
|
.join(", "),
|
||||||
ArgKind::Arg(_, ty) => ty != "_",
|
// add type annotations if available
|
||||||
_ => false,
|
if found_args.iter().any(|arg| match arg {
|
||||||
}) {
|
ArgKind::Arg(_, ty) => ty != "_",
|
||||||
format!(
|
_ => false,
|
||||||
": ({})",
|
}) {
|
||||||
fields
|
format!(
|
||||||
.iter()
|
": ({})",
|
||||||
.map(|(_, ty)| ty.to_owned())
|
fields
|
||||||
.collect::<Vec<String>>()
|
.iter()
|
||||||
.join(", ")
|
.map(|(_, ty)| ty.to_owned())
|
||||||
)
|
.collect::<Vec<String>>()
|
||||||
} else {
|
.join(", ")
|
||||||
String::new()
|
)
|
||||||
},
|
} else {
|
||||||
);
|
String::new()
|
||||||
err.span_suggestion_verbose(
|
},
|
||||||
found_span,
|
);
|
||||||
"change the closure to accept a tuple instead of individual arguments",
|
err.span_suggestion_verbose(
|
||||||
sugg,
|
found_span,
|
||||||
Applicability::MachineApplicable,
|
"change the closure to accept a tuple instead of individual arguments",
|
||||||
);
|
sugg,
|
||||||
}
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2231,16 +2232,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
if obligated_types.iter().any(|ot| ot == &self_ty) {
|
if obligated_types.iter().any(|ot| ot == &self_ty) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if let ty::Adt(def, substs) = self_ty.kind() {
|
if let ty::Adt(def, substs) = self_ty.kind()
|
||||||
if let [arg] = &substs[..] {
|
&& let [arg] = &substs[..]
|
||||||
if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() {
|
&& let ty::subst::GenericArgKind::Type(ty) = arg.unpack()
|
||||||
if let ty::Adt(inner_def, _) = ty.kind() {
|
&& let ty::Adt(inner_def, _) = ty.kind()
|
||||||
if inner_def == def {
|
&& inner_def == def
|
||||||
return true;
|
{
|
||||||
}
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
|
|
@ -891,23 +891,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
if let Some(typeck_results) =
|
if let Some(typeck_results) =
|
||||||
self.in_progress_typeck_results.map(|t| t.borrow())
|
self.in_progress_typeck_results.map(|t| t.borrow())
|
||||||
|
&& let ty = typeck_results.expr_ty_adjusted(base)
|
||||||
|
&& let ty::FnDef(def_id, _substs) = ty.kind()
|
||||||
|
&& let Some(hir::Node::Item(hir::Item { span, ident, .. })) =
|
||||||
|
hir.get_if_local(*def_id)
|
||||||
{
|
{
|
||||||
let ty = typeck_results.expr_ty_adjusted(base);
|
err.span_suggestion_verbose(
|
||||||
if let ty::FnDef(def_id, _substs) = ty.kind() {
|
span.shrink_to_lo(),
|
||||||
if let Some(hir::Node::Item(hir::Item { span, ident, .. })) =
|
&format!(
|
||||||
hir.get_if_local(*def_id)
|
"alternatively, consider making `fn {}` asynchronous",
|
||||||
{
|
ident
|
||||||
err.span_suggestion_verbose(
|
),
|
||||||
span.shrink_to_lo(),
|
"async ".to_string(),
|
||||||
&format!(
|
Applicability::MaybeIncorrect,
|
||||||
"alternatively, consider making `fn {}` asynchronous",
|
);
|
||||||
ident
|
|
||||||
),
|
|
||||||
"async ".to_string(),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1000,34 +997,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
) {
|
) {
|
||||||
let is_empty_tuple =
|
|
||||||
|ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty());
|
|
||||||
|
|
||||||
let hir = self.tcx.hir();
|
let hir = self.tcx.hir();
|
||||||
let parent_node = hir.get_parent_node(obligation.cause.body_id);
|
let parent_node = hir.get_parent_node(obligation.cause.body_id);
|
||||||
let node = hir.find(parent_node);
|
let node = hir.find(parent_node);
|
||||||
if let Some(hir::Node::Item(hir::Item {
|
if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node
|
||||||
kind: hir::ItemKind::Fn(sig, _, body_id), ..
|
&& let body = hir.body(*body_id)
|
||||||
})) = node
|
&& let hir::ExprKind::Block(blk, _) = &body.value.kind
|
||||||
|
&& sig.decl.output.span().overlaps(span)
|
||||||
|
&& blk.expr.is_none()
|
||||||
|
&& *trait_pred.self_ty().skip_binder().kind() == ty::Tuple(ty::List::empty())
|
||||||
|
// FIXME(estebank): When encountering a method with a trait
|
||||||
|
// bound not satisfied in the return type with a body that has
|
||||||
|
// no return, suggest removal of semicolon on last statement.
|
||||||
|
// Once that is added, close #54771.
|
||||||
|
&& let Some(stmt) = blk.stmts.last()
|
||||||
|
&& let hir::StmtKind::Semi(_) = stmt.kind
|
||||||
{
|
{
|
||||||
let body = hir.body(*body_id);
|
let sp = self.tcx.sess.source_map().end_point(stmt.span);
|
||||||
if let hir::ExprKind::Block(blk, _) = &body.value.kind {
|
err.span_label(sp, "consider removing this semicolon");
|
||||||
if sig.decl.output.span().overlaps(span)
|
|
||||||
&& blk.expr.is_none()
|
|
||||||
&& is_empty_tuple(trait_pred.self_ty())
|
|
||||||
{
|
|
||||||
// FIXME(estebank): When encountering a method with a trait
|
|
||||||
// bound not satisfied in the return type with a body that has
|
|
||||||
// no return, suggest removal of semicolon on last statement.
|
|
||||||
// Once that is added, close #54771.
|
|
||||||
if let Some(ref stmt) = blk.stmts.last() {
|
|
||||||
if let hir::StmtKind::Semi(_) = stmt.kind {
|
|
||||||
let sp = self.tcx.sess.source_map().end_point(stmt.span);
|
|
||||||
err.span_label(sp, "consider removing this semicolon");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2481,17 +2468,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
|
debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
|
||||||
if self.predicate_may_hold(&try_obligation)
|
if self.predicate_may_hold(&try_obligation)
|
||||||
&& impls_future.must_apply_modulo_regions()
|
&& impls_future.must_apply_modulo_regions()
|
||||||
|
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||||
|
&& snippet.ends_with('?')
|
||||||
{
|
{
|
||||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
err.span_suggestion_verbose(
|
||||||
if snippet.ends_with('?') {
|
span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
|
||||||
err.span_suggestion_verbose(
|
"consider `await`ing on the `Future`",
|
||||||
span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
|
".await".to_string(),
|
||||||
"consider `await`ing on the `Future`",
|
Applicability::MaybeIncorrect,
|
||||||
".await".to_string(),
|
);
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,10 +91,8 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
|
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
|
||||||
if let Some(symbol) = item.value_str() {
|
if let Some(symbol) = item.value_str() && parse_value(symbol).is_err() {
|
||||||
if parse_value(symbol).is_err() {
|
errored = true;
|
||||||
errored = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
@ -232,24 +230,22 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
|
options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
|
||||||
|
|
||||||
for command in self.subcommands.iter().chain(Some(self)).rev() {
|
for command in self.subcommands.iter().chain(Some(self)).rev() {
|
||||||
if let Some(ref condition) = command.condition {
|
if let Some(ref condition) = command.condition && !attr::eval_condition(
|
||||||
if !attr::eval_condition(
|
condition,
|
||||||
condition,
|
&tcx.sess.parse_sess,
|
||||||
&tcx.sess.parse_sess,
|
Some(tcx.features()),
|
||||||
Some(tcx.features()),
|
&mut |c| {
|
||||||
&mut |c| {
|
c.ident().map_or(false, |ident| {
|
||||||
c.ident().map_or(false, |ident| {
|
let value = c.value_str().map(|s| {
|
||||||
let value = c.value_str().map(|s| {
|
OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
|
||||||
OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
|
});
|
||||||
});
|
|
||||||
|
|
||||||
options.contains(&(ident.name, value))
|
options.contains(&(ident.name, value))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
debug!("evaluate: skipping {:?} due to condition", command);
|
debug!("evaluate: skipping {:?} due to condition", command);
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
debug!("evaluate: {:?} succeeded", command);
|
debug!("evaluate: {:?} succeeded", command);
|
||||||
if let Some(ref message_) = command.message {
|
if let Some(ref message_) = command.message {
|
||||||
|
|
|
@ -43,21 +43,19 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
|
||||||
let c_ty = self.infcx.canonicalize_query(self.param_env.and(ty), &mut orig_values);
|
let c_ty = self.infcx.canonicalize_query(self.param_env.and(ty), &mut orig_values);
|
||||||
let span = self.cause.span;
|
let span = self.cause.span;
|
||||||
debug!("c_ty = {:?}", c_ty);
|
debug!("c_ty = {:?}", c_ty);
|
||||||
if let Ok(result) = tcx.dropck_outlives(c_ty) {
|
if let Ok(result) = tcx.dropck_outlives(c_ty)
|
||||||
if result.is_proven() {
|
&& result.is_proven()
|
||||||
if let Ok(InferOk { value, obligations }) =
|
&& let Ok(InferOk { value, obligations }) =
|
||||||
self.infcx.instantiate_query_response_and_region_obligations(
|
self.infcx.instantiate_query_response_and_region_obligations(
|
||||||
self.cause,
|
self.cause,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
&orig_values,
|
&orig_values,
|
||||||
result,
|
result,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let ty = self.infcx.resolve_vars_if_possible(ty);
|
let ty = self.infcx.resolve_vars_if_possible(ty);
|
||||||
let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
|
let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
|
||||||
return InferOk { value: kinds, obligations };
|
return InferOk { value: kinds, obligations };
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Errors and ambiuity in dropck occur in two cases:
|
// Errors and ambiuity in dropck occur in two cases:
|
||||||
|
|
|
@ -12,50 +12,38 @@ pub(crate) fn update<'tcx, T>(
|
||||||
T: TraitEngine<'tcx>,
|
T: TraitEngine<'tcx>,
|
||||||
{
|
{
|
||||||
// (*) binder skipped
|
// (*) binder skipped
|
||||||
if let ty::PredicateKind::Trait(predicate) = obligation.predicate.kind().skip_binder() {
|
if let ty::PredicateKind::Trait(tpred) = obligation.predicate.kind().skip_binder()
|
||||||
if let Some(ty) =
|
&& let Some(ty) = infcx.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| infcx.root_var(t))
|
||||||
infcx.shallow_resolve(predicate.self_ty()).ty_vid().map(|t| infcx.root_var(t))
|
&& infcx.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id)
|
||||||
{
|
{
|
||||||
if infcx
|
let new_self_ty = infcx.tcx.types.unit;
|
||||||
.tcx
|
|
||||||
.lang_items()
|
|
||||||
.sized_trait()
|
|
||||||
.map_or(false, |st| st != predicate.trait_ref.def_id)
|
|
||||||
{
|
|
||||||
let new_self_ty = infcx.tcx.types.unit;
|
|
||||||
|
|
||||||
let trait_ref = ty::TraitRef {
|
let trait_ref = ty::TraitRef {
|
||||||
substs: infcx
|
substs: infcx.tcx.mk_substs_trait(new_self_ty, &tpred.trait_ref.substs[1..]),
|
||||||
.tcx
|
..tpred.trait_ref
|
||||||
.mk_substs_trait(new_self_ty, &predicate.trait_ref.substs[1..]),
|
};
|
||||||
..predicate.trait_ref
|
|
||||||
};
|
|
||||||
|
|
||||||
// Then contstruct a new obligation with Self = () added
|
// Then contstruct a new obligation with Self = () added
|
||||||
// to the ParamEnv, and see if it holds.
|
// to the ParamEnv, and see if it holds.
|
||||||
let o = rustc_infer::traits::Obligation::new(
|
let o = rustc_infer::traits::Obligation::new(
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
obligation
|
obligation
|
||||||
.predicate
|
.predicate
|
||||||
.kind()
|
.kind()
|
||||||
.map_bound(|_| {
|
.map_bound(|_| {
|
||||||
// (*) binder moved here
|
// (*) binder moved here
|
||||||
ty::PredicateKind::Trait(ty::TraitPredicate {
|
ty::PredicateKind::Trait(ty::TraitPredicate {
|
||||||
trait_ref,
|
trait_ref,
|
||||||
constness: predicate.constness,
|
constness: tpred.constness,
|
||||||
polarity: predicate.polarity,
|
polarity: tpred.polarity,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.to_predicate(infcx.tcx),
|
.to_predicate(infcx.tcx),
|
||||||
);
|
);
|
||||||
// Don't report overflow errors. Otherwise equivalent to may_hold.
|
// Don't report overflow errors. Otherwise equivalent to may_hold.
|
||||||
if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) {
|
if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() {
|
||||||
if result.may_apply() {
|
engine.relationships().entry(ty).or_default().self_in_trait = true;
|
||||||
engine.relationships().entry(ty).or_default().self_in_trait = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -579,24 +579,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
previous_stack,
|
previous_stack,
|
||||||
subobligations,
|
subobligations,
|
||||||
);
|
);
|
||||||
if let Ok(res) = res {
|
if let Ok(eval_rslt) = res
|
||||||
if res == EvaluatedToOk || res == EvaluatedToOkModuloRegions {
|
&& (eval_rslt == EvaluatedToOk || eval_rslt == EvaluatedToOkModuloRegions)
|
||||||
if let Some(key) =
|
&& let Some(key) =
|
||||||
ProjectionCacheKey::from_poly_projection_predicate(
|
ProjectionCacheKey::from_poly_projection_predicate(
|
||||||
self, data,
|
self, data,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// If the result is something that we can cache, then mark this
|
// If the result is something that we can cache, then mark this
|
||||||
// entry as 'complete'. This will allow us to skip evaluating the
|
// entry as 'complete'. This will allow us to skip evaluating the
|
||||||
// suboligations at all the next time we evaluate the projection
|
// suboligations at all the next time we evaluate the projection
|
||||||
// predicate.
|
// predicate.
|
||||||
self.infcx
|
self.infcx
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.projection_cache()
|
.projection_cache()
|
||||||
.complete(key, res);
|
.complete(key, eval_rslt);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,36 +224,30 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
||||||
// projection coming from another associated type. See
|
// projection coming from another associated type. See
|
||||||
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
|
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
|
||||||
// `traits-assoc-type-in-supertrait-bad.rs`.
|
// `traits-assoc-type-in-supertrait-bad.rs`.
|
||||||
if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind()) {
|
if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind())
|
||||||
if let Some(&impl_item_id) =
|
&& let Some(&impl_item_id) =
|
||||||
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
|
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
|
||||||
{
|
&& let Some(impl_item_span) = items
|
||||||
if let Some(impl_item_span) = items
|
.iter()
|
||||||
.iter()
|
.find(|item| item.id.def_id.to_def_id() == impl_item_id)
|
||||||
.find(|item| item.id.def_id.to_def_id() == impl_item_id)
|
.map(fix_span)
|
||||||
.map(fix_span)
|
{
|
||||||
{
|
cause.span = impl_item_span;
|
||||||
cause.span = impl_item_span;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Trait(pred) => {
|
ty::PredicateKind::Trait(pred) => {
|
||||||
// An associated item obligation born out of the `trait` failed to be met. An example
|
// An associated item obligation born out of the `trait` failed to be met. An example
|
||||||
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
|
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
|
||||||
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
|
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
|
||||||
if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind() {
|
if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind()
|
||||||
if let Some(&impl_item_id) =
|
&& let Some(&impl_item_id) =
|
||||||
tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
|
tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
|
||||||
{
|
&& let Some(impl_item_span) = items
|
||||||
if let Some(impl_item_span) = items
|
.iter()
|
||||||
.iter()
|
.find(|item| item.id.def_id.to_def_id() == impl_item_id)
|
||||||
.find(|item| item.id.def_id.to_def_id() == impl_item_id)
|
.map(fix_span)
|
||||||
.map(fix_span)
|
{
|
||||||
{
|
cause.span = impl_item_span;
|
||||||
cause.span = impl_item_span;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
Loading…
Add table
Reference in a new issue