]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Rollup merge of #99351 - compiler-errors:arg-mismatch-blame, r=davidtwco
[rust.git] / compiler / rustc_trait_selection / src / traits / error_reporting / mod.rs
index 8396df4a243c9bf7ccb4c0b154941a9cd4d58581..8a679ca005f3d567740c89fdfbf98fc2e4a403ff 100644 (file)
@@ -23,9 +23,9 @@
 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::{
@@ -665,6 +665,7 @@ fn report_selection_error(
                             self.suggest_restricting_param_bound(
                                 &mut err,
                                 trait_predicate,
+                                None,
                                 obligation.cause.body_id,
                             );
                         } else if !suggested {
@@ -673,6 +674,7 @@ fn report_selection_error(
                             if !self.report_similar_impl_candidates(
                                 impl_candidates,
                                 trait_ref,
+                                obligation.cause.body_id,
                                 &mut err,
                             ) {
                                 // This is *almost* equivalent to
@@ -707,6 +709,7 @@ fn report_selection_error(
                                     self.report_similar_impl_candidates(
                                         impl_candidates,
                                         trait_ref,
+                                        obligation.cause.body_id,
                                         &mut err,
                                     );
                                 }
@@ -821,10 +824,7 @@ fn report_selection_error(
 
                     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,
@@ -882,7 +882,7 @@ fn report_selection_error(
                     }
 
                     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
@@ -949,9 +949,7 @@ fn report_selection_error(
                     _ => 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,
@@ -1084,10 +1082,10 @@ fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)>
         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()
@@ -1353,6 +1351,7 @@ fn report_similar_impl_candidates(
         &self,
         impl_candidates: Vec<ImplCandidate<'tcx>>,
         trait_ref: ty::PolyTraitRef<'tcx>,
+        body_id: hir::HirId,
         err: &mut Diagnostic,
     ) -> bool;
 
@@ -1404,7 +1403,7 @@ fn suggest_unsized_bound_if_applicable(
     fn annotate_source_of_ambiguity(
         &self,
         err: &mut Diagnostic,
-        impls: &[AmbiguousSelection],
+        impls: &[DefId],
         predicate: ty::Predicate<'tcx>,
     );
 
@@ -1735,6 +1734,7 @@ fn report_similar_impl_candidates(
         &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| {
@@ -1805,8 +1805,24 @@ fn report_similar_impl_candidates(
                         || 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);
         }
@@ -2020,14 +2036,6 @@ fn maybe_report_ambiguity(
                 );
                 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);
                     }
                     _ => {
@@ -2074,6 +2082,9 @@ fn maybe_report_ambiguity(
                         //    |
                         //    = 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!(
@@ -2157,19 +2168,30 @@ fn maybe_report_ambiguity(
             }
 
             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
                 }
             }
             _ => {
@@ -2194,35 +2216,24 @@ fn maybe_report_ambiguity(
     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();