use rustc_hir::Item;
use rustc_hir::Node;
use rustc_infer::infer::error_reporting::same_type_modulo_infer;
-use rustc_infer::traits::{AmbiguousSelection, TraitEngine};
-use rustc_middle::thir::abstract_const::NotConstEvaluatable;
+use rustc_infer::traits::TraitEngine;
use rustc_middle::traits::select::OverflowError;
+use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::{
self.suggest_restricting_param_bound(
&mut err,
trait_predicate,
+ None,
obligation.cause.body_id,
);
} else if !suggested {
if !self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
+ obligation.cause.body_id,
&mut err,
) {
// This is *almost* equivalent to
self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
+ obligation.cause.body_id,
&mut err,
);
}
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
let found_kind = self.closure_kind(closure_substs).unwrap();
- let closure_span =
- self.tcx.sess.source_map().guess_head_span(
- self.tcx.hir().span_if_local(closure_def_id).unwrap(),
- );
+ let closure_span = self.tcx.def_span(closure_def_id);
let mut err = struct_span_err!(
self.tcx.sess,
closure_span,
}
ty::PredicateKind::WellFormed(ty) => {
- if !self.tcx.sess.opts.debugging_opts.chalk {
+ if !self.tcx.sess.opts.unstable_opts.chalk {
// WF predicates cannot themselves make
// errors. They can only block due to
// ambiguity; otherwise, they always
_ => None,
};
- let found_span = found_did
- .and_then(|did| self.tcx.hir().span_if_local(did))
- .map(|sp| self.tcx.sess.source_map().guess_head_span(sp)); // the sp could be an fn def
+ let found_span = found_did.and_then(|did| self.tcx.hir().span_if_local(did));
if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
// We check closures twice, with obligations flowing in different directions,
let hir = self.tcx.hir();
Some(match node {
Node::Expr(&hir::Expr {
- kind: hir::ExprKind::Closure { body, fn_decl_span, .. },
+ kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }),
..
}) => (
- sm.guess_head_span(fn_decl_span),
+ fn_decl_span,
hir.body(body)
.params
.iter()
&self,
impl_candidates: Vec<ImplCandidate<'tcx>>,
trait_ref: ty::PolyTraitRef<'tcx>,
+ body_id: hir::HirId,
err: &mut Diagnostic,
) -> bool;
fn annotate_source_of_ambiguity(
&self,
err: &mut Diagnostic,
- impls: &[AmbiguousSelection],
+ impls: &[DefId],
predicate: ty::Predicate<'tcx>,
);
&self,
impl_candidates: Vec<ImplCandidate<'tcx>>,
trait_ref: ty::PolyTraitRef<'tcx>,
+ body_id: hir::HirId,
err: &mut Diagnostic,
) -> bool {
let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
|| self.tcx.is_builtin_derive(def_id)
})
.filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
- // Avoid mentioning type parameters.
- .filter(|trait_ref| !matches!(trait_ref.self_ty().kind(), ty::Param(_)))
+ .filter(|trait_ref| {
+ let self_ty = trait_ref.self_ty();
+ // Avoid mentioning type parameters.
+ if let ty::Param(_) = self_ty.kind() {
+ false
+ }
+ // Avoid mentioning types that are private to another crate
+ else if let ty::Adt(def, _) = self_ty.peel_refs().kind() {
+ // FIXME(compiler-errors): This could be generalized, both to
+ // be more granular, and probably look past other `#[fundamental]`
+ // types, too.
+ self.tcx
+ .visibility(def.did())
+ .is_accessible_from(body_id.owner.to_def_id(), self.tcx)
+ } else {
+ true
+ }
+ })
.collect();
return report(normalized_impl_candidates, err);
}
);
match selcx.select_from_obligation(&obligation) {
Err(SelectionError::Ambiguous(impls)) if impls.len() > 1 => {
- if self.is_tainted_by_errors() && subst.is_none() {
- // If `subst.is_none()`, then this is probably two param-env
- // candidates or impl candidates that are equal modulo lifetimes.
- // Therefore, if we've already emitted an error, just skip this
- // one, since it's not particularly actionable.
- err.cancel();
- return;
- }
self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
}
_ => {
// |
// = note: cannot satisfy `_: Tt`
+ // Clear any more general suggestions in favor of our specific one
+ err.clear_suggestions();
+
err.span_suggestion_verbose(
span.shrink_to_hi(),
&format!(
}
ty::PredicateKind::ConstEvaluatable(data) => {
+ if predicate.references_error() || self.is_tainted_by_errors() {
+ return;
+ }
let subst = data.substs.iter().find(|g| g.has_infer_types_or_consts());
if let Some(subst) = subst {
- let mut err = self.emit_inference_failure_err(
+ let err = self.emit_inference_failure_err(
body_id,
span,
subst,
ErrorCode::E0284,
true,
);
- err.note(&format!("cannot satisfy `{}`", predicate));
err
} else {
- todo!();
+ // If we can't find a substitution, just print a generic error
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0284,
+ "type annotations needed: cannot satisfy `{}`",
+ predicate,
+ );
+ err.span_label(span, &format!("cannot satisfy `{}`", predicate));
+ err
}
}
_ => {
fn annotate_source_of_ambiguity(
&self,
err: &mut Diagnostic,
- impls: &[AmbiguousSelection],
+ impls: &[DefId],
predicate: ty::Predicate<'tcx>,
) {
let mut spans = vec![];
let mut crates = vec![];
let mut post = vec![];
- let mut or_where_clause = false;
- for ambig in impls {
- match ambig {
- AmbiguousSelection::Impl(def_id) => match self.tcx.span_of_impl(*def_id) {
- Ok(span) => spans.push(span),
- Err(name) => {
- crates.push(name);
- if let Some(header) = to_pretty_impl_header(self.tcx, *def_id) {
- post.push(header);
- }
+ for def_id in impls {
+ match self.tcx.span_of_impl(*def_id) {
+ Ok(span) => spans.push(span),
+ Err(name) => {
+ crates.push(name);
+ if let Some(header) = to_pretty_impl_header(self.tcx, *def_id) {
+ post.push(header);
}
- },
- AmbiguousSelection::ParamEnv(span) => {
- or_where_clause = true;
- spans.push(*span);
}
}
}
- let msg = format!(
- "multiple `impl`s{} satisfying `{}` found",
- if or_where_clause { " or `where` clauses" } else { "" },
- predicate
- );
+ let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect();
crate_names.sort();
crate_names.dedup();