]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/traits/error_reporting.rs
Auto merge of #65288 - estebank:point-at-assoc-type, r=nikomatsakis
[rust.git] / src / librustc / traits / error_reporting.rs
index 9931a2517f11213b8e0fdedb816b8e00b00eed46..be9e24cb1a291ce8ac7dca25adb5e2ed526f5c6b 100644 (file)
@@ -195,8 +195,7 @@ fn report_projection_error(
         obligation: &PredicateObligation<'tcx>,
         error: &MismatchedProjectionTypes<'tcx>,
     ) {
-        let predicate =
-            self.resolve_vars_if_possible(&obligation.predicate);
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
 
         if predicate.references_error() {
             return
@@ -228,7 +227,8 @@ fn report_projection_error(
                     &mut obligations
                 );
                 if let Err(error) = self.at(&obligation.cause, obligation.param_env)
-                                        .eq(normalized_ty, data.ty) {
+                    .eq(normalized_ty, data.ty)
+                {
                     values = Some(infer::ValuePairs::Types(ExpectedFound {
                         expected: normalized_ty,
                         found: data.ty,
@@ -239,13 +239,19 @@ fn report_projection_error(
             }
 
             let msg = format!("type mismatch resolving `{}`", predicate);
-            let error_id = (DiagnosticMessageId::ErrorId(271),
-                            Some(obligation.cause.span), msg);
+            let error_id = (
+                DiagnosticMessageId::ErrorId(271),
+                Some(obligation.cause.span),
+                msg,
+            );
             let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
             if fresh {
                 let mut diag = struct_span_err!(
-                    self.tcx.sess, obligation.cause.span, E0271,
-                    "type mismatch resolving `{}`", predicate
+                    self.tcx.sess,
+                    obligation.cause.span,
+                    E0271,
+                    "type mismatch resolving `{}`",
+                    predicate
                 );
                 self.note_type_err(&mut diag, &obligation.cause, None, values, err);
                 self.note_obligation_cause(&mut diag, obligation);
@@ -406,7 +412,7 @@ fn on_unimplemented_note(
                 },
                 GenericParamDefKind::Lifetime => continue,
             };
-            let name = param.name.as_symbol();
+            let name = param.name;
             flags.push((name, Some(value)));
         }
 
@@ -532,23 +538,33 @@ fn report_similar_impl_candidates(
     /// whose result could not be truly determined and thus we can't say
     /// if the program type checks or not -- and they are unusual
     /// occurrences in any case.
-    pub fn report_overflow_error<T>(&self,
-                                    obligation: &Obligation<'tcx, T>,
-                                    suggest_increasing_limit: bool) -> !
+    pub fn report_overflow_error<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
         where T: fmt::Display + TypeFoldable<'tcx>
     {
         let predicate =
             self.resolve_vars_if_possible(&obligation.predicate);
-        let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275,
-                                       "overflow evaluating the requirement `{}`",
-                                       predicate);
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            obligation.cause.span,
+            E0275,
+            "overflow evaluating the requirement `{}`",
+            predicate
+        );
 
         if suggest_increasing_limit {
             self.suggest_new_overflow_limit(&mut err);
         }
 
-        self.note_obligation_cause_code(&mut err, &obligation.predicate, &obligation.cause.code,
-                                        &mut vec![]);
+        self.note_obligation_cause_code(
+            &mut err,
+            &obligation.predicate,
+            &obligation.cause.code,
+            &mut vec![],
+        );
 
         err.emit();
         self.tcx.sess.abort_if_errors();
@@ -793,15 +809,11 @@ pub fn report_selection_error(
 
                     ty::Predicate::ObjectSafe(trait_def_id) => {
                         let violations = self.tcx.object_safety_violations(trait_def_id);
-                        if let Some(err) = self.tcx.report_object_safety_error(
+                        self.tcx.report_object_safety_error(
                             span,
                             trait_def_id,
                             violations,
-                        ) {
-                            err
-                        } else {
-                            return;
-                        }
+                        )
                     }
 
                     ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
@@ -937,11 +949,7 @@ pub fn report_selection_error(
 
             TraitNotObjectSafe(did) => {
                 let violations = self.tcx.object_safety_violations(did);
-                if let Some(err) = self.tcx.report_object_safety_error(span, did, violations) {
-                    err
-                } else {
-                    return;
-                }
+                self.tcx.report_object_safety_error(span, did, violations)
             }
 
             // already reported in the query
@@ -969,27 +977,31 @@ fn suggest_restricting_param_bound(
         trait_ref: &ty::PolyTraitRef<'_>,
         body_id: hir::HirId,
     ) {
-        let (param_ty, projection) = match &trait_ref.self_ty().kind {
-            ty::Param(param_ty) => (Some(param_ty), None),
-            ty::Projection(projection) => (None, Some(projection)),
+        let self_ty = trait_ref.self_ty();
+        let (param_ty, projection) = match &self_ty.kind {
+            ty::Param(_) => (true, None),
+            ty::Projection(projection) => (false, Some(projection)),
             _ => return,
         };
 
         let mut suggest_restriction = |generics: &hir::Generics, msg| {
-            err.span_suggestion(
-                generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
-                &format!("consider further restricting {}", msg),
-                format!(
-                    "{} {} ",
-                    if !generics.where_clause.predicates.is_empty() {
-                        ","
-                    } else {
-                        " where"
-                    },
-                    trait_ref.to_predicate(),
-                ),
-                Applicability::MachineApplicable,
-            );
+            let span = generics.where_clause.span_for_predicates_or_empty_place();
+            if !span.from_expansion() && span.desugaring_kind().is_none() {
+                err.span_suggestion(
+                    generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
+                    &format!("consider further restricting {}", msg),
+                    format!(
+                        "{} {} ",
+                        if !generics.where_clause.predicates.is_empty() {
+                            ","
+                        } else {
+                            " where"
+                        },
+                        trait_ref.to_predicate(),
+                    ),
+                    Applicability::MachineApplicable,
+                );
+            }
         };
 
         // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
@@ -997,17 +1009,10 @@ fn suggest_restricting_param_bound(
         let mut hir_id = body_id;
         while let Some(node) = self.tcx.hir().find(hir_id) {
             match node {
-                hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Fn(_, _, generics, _), ..
-                }) |
                 hir::Node::TraitItem(hir::TraitItem {
                     generics,
                     kind: hir::TraitItemKind::Method(..), ..
-                }) |
-                hir::Node::ImplItem(hir::ImplItem {
-                    generics,
-                    kind: hir::ImplItemKind::Method(..), ..
-                }) if param_ty.map_or(false, |p| p.name.as_str() == "Self") => {
+                }) if param_ty && self_ty == self.tcx.types.self_param => {
                     // Restricting `Self` for a single method.
                     suggest_restriction(&generics, "`Self`");
                     return;
@@ -1058,15 +1063,15 @@ fn suggest_restricting_param_bound(
                 }) |
                 hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) |
                 hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
-                if param_ty.is_some() => {
+                if param_ty => {
                     // Missing generic type parameter bound.
                     let restrict_msg = "consider further restricting this bound";
-                    let param_name = param_ty.unwrap().name.as_str();
+                    let param_name = self_ty.to_string();
                     for param in generics.params.iter().filter(|p| {
-                        param_name == p.name.ident().as_str()
+                        &param_name == std::convert::AsRef::<str>::as_ref(&p.name.ident().as_str())
                     }) {
                         if param_name.starts_with("impl ") {
-                            // `impl Trait` in argument: 
+                            // `impl Trait` in argument:
                             // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
                             err.span_suggestion(
                                 param.span,
@@ -1075,53 +1080,51 @@ fn suggest_restricting_param_bound(
                                 format!("{} + {}", param.name.ident(), trait_ref),
                                 Applicability::MachineApplicable,
                             );
-                        } else {
-                            if generics.where_clause.predicates.is_empty() &&
+                        } else if generics.where_clause.predicates.is_empty() &&
                                 param.bounds.is_empty()
-                            {
-                                // If there are no bounds whatsoever, suggest adding a constraint
-                                // to the type parameter:
-                                // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
-                                err.span_suggestion(
-                                    param.span,
-                                    "consider restricting this bound",
-                                    format!("{}", trait_ref.to_predicate()),
-                                    Applicability::MachineApplicable,
-                                );
-                            } else if !generics.where_clause.predicates.is_empty() {
-                                // There is a `where` clause, so suggest expanding it:
-                                // `fn foo<T>(t: T) where T: Debug {}` →
-                                // `fn foo<T(t: T) where T: Debug, Trait {}`
-                                err.span_suggestion(
-                                    generics.where_clause.span().unwrap().shrink_to_hi(),
-                                    &format!(
-                                        "consider further restricting type parameter `{}`",
-                                        param_name,
-                                    ),
-                                    format!(", {}", trait_ref.to_predicate()),
-                                    Applicability::MachineApplicable,
-                                );
+                        {
+                            // If there are no bounds whatsoever, suggest adding a constraint
+                            // to the type parameter:
+                            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
+                            err.span_suggestion(
+                                param.span,
+                                "consider restricting this bound",
+                                format!("{}", trait_ref.to_predicate()),
+                                Applicability::MachineApplicable,
+                            );
+                        } else if !generics.where_clause.predicates.is_empty() {
+                            // There is a `where` clause, so suggest expanding it:
+                            // `fn foo<T>(t: T) where T: Debug {}` →
+                            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
+                            err.span_suggestion(
+                                generics.where_clause.span().unwrap().shrink_to_hi(),
+                                &format!(
+                                    "consider further restricting type parameter `{}`",
+                                    param_name,
+                                ),
+                                format!(", {}", trait_ref.to_predicate()),
+                                Applicability::MachineApplicable,
+                            );
+                        } else {
+                            // If there is no `where` clause lean towards constraining to the
+                            // type parameter:
+                            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
+                            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
+                            let sp = param.span.with_hi(span.hi());
+                            let span = self.tcx.sess.source_map()
+                                .span_through_char(sp, ':');
+                            if sp != param.span && sp != span {
+                                // Only suggest if we have high certainty that the span
+                                // covers the colon in `foo<T: Trait>`.
+                                err.span_suggestion(span, restrict_msg, format!(
+                                    "{} + ",
+                                    trait_ref.to_predicate(),
+                                ), Applicability::MachineApplicable);
                             } else {
-                                // If there is no `where` clause lean towards constraining to the
-                                // type parameter:
-                                // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
-                                // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
-                                let sp = param.span.with_hi(span.hi());
-                                let span = self.tcx.sess.source_map()
-                                    .span_through_char(sp, ':');
-                                if sp != param.span && sp != span {
-                                    // Only suggest if we have high certainty that the span
-                                    // covers the colon in `foo<T: Trait>`.
-                                    err.span_suggestion(span, restrict_msg, format!(
-                                        "{} + ",
-                                        trait_ref.to_predicate(),
-                                    ), Applicability::MachineApplicable);
-                                } else {
-                                    err.span_label(param.span, &format!(
-                                        "consider adding a `where {}` bound",
-                                        trait_ref.to_predicate(),
-                                    ));
-                                }
+                                err.span_label(param.span, &format!(
+                                    "consider adding a `where {}` bound",
+                                    trait_ref.to_predicate(),
+                                ));
                             }
                         }
                         return;
@@ -1670,11 +1673,7 @@ pub fn report_object_safety_error(
         span: Span,
         trait_def_id: DefId,
         violations: Vec<ObjectSafetyViolation>,
-    ) -> Option<DiagnosticBuilder<'tcx>> {
-        if self.sess.trait_methods_not_found.borrow().contains(&span) {
-            // Avoid emitting error caused by non-existing method (#58734)
-            return None;
-        }
+    ) -> DiagnosticBuilder<'tcx> {
         let trait_str = self.def_path_str(trait_def_id);
         let span = self.sess.source_map().def_span(span);
         let mut err = struct_span_err!(
@@ -1692,7 +1691,13 @@ pub fn report_object_safety_error(
                 };
             }
         }
-        Some(err)
+
+        if self.sess.trait_methods_not_found.borrow().contains(&span) {
+            // Avoid emitting error caused by non-existing method (#58734)
+            err.cancel();
+        }
+
+        err
     }
 }
 
@@ -2103,6 +2108,10 @@ fn note_obligation_cause_code<T>(&self,
                 err.note(&format!("required for the cast to the object type `{}`",
                                   self.ty_to_string(object_ty)));
             }
+            ObligationCauseCode::Coercion { source: _, target } => {
+                err.note(&format!("required by cast to type `{}`",
+                                  self.ty_to_string(target)));
+            }
             ObligationCauseCode::RepeatVec => {
                 err.note("the `Copy` trait is required because the \
                           repeated element will be copied");
@@ -2204,6 +2213,12 @@ fn note_obligation_cause_code<T>(&self,
                     );
                 }
             }
+            ObligationCauseCode::AssocTypeBound(impl_span, orig) => {
+                err.span_label(orig, "associated type defined here");
+                if let Some(sp) = impl_span {
+                    err.span_label(sp, "in this `impl` item");
+                }
+            }
         }
     }