]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_middle/ty/diagnostics.rs
Account for multiple impl/dyn Trait in return type when suggesting `'_`
[rust.git] / src / librustc_middle / ty / diagnostics.rs
index 1403efb745b156bec69771e54a047d2beb50ee5b..b22727bdd7587b71848ce692971577f2cf1cdc3c 100644 (file)
@@ -7,7 +7,6 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
-use rustc_span::{BytePos, Span};
 
 impl<'tcx> TyS<'tcx> {
     /// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive.
@@ -221,24 +220,11 @@ pub fn suggest_constraining_type_param(
             }
         }
 
-        let where_clause_span = generics.where_clause.span_for_predicates_or_empty_place();
-        // Account for `fn foo<T>(t: T) where T: Foo,` so we don't suggest two trailing commas.
-        let mut trailing_comma = false;
-        if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(where_clause_span) {
-            trailing_comma = snippet.ends_with(',');
-        }
-        let where_clause_span = if trailing_comma {
-            let hi = where_clause_span.hi();
-            Span::new(hi - BytePos(1), hi, where_clause_span.ctxt())
-        } else {
-            where_clause_span.shrink_to_hi()
-        };
-
         match &param_spans[..] {
             &[&param_span] => suggest_restrict(param_span.shrink_to_hi()),
             _ => {
                 err.span_suggestion_verbose(
-                    where_clause_span,
+                    generics.where_clause.tail_span_for_suggestion(),
                     &msg_restrict_type_further,
                     format!(", {}: {}", param_name, constraint),
                     Applicability::MachineApplicable,
@@ -250,21 +236,35 @@ pub fn suggest_constraining_type_param(
     }
 }
 
-pub struct TraitObjectVisitor(pub Vec<rustc_span::Span>);
-impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor {
+/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
+pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>);
+
+impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
     type Map = rustc_hir::intravisit::ErasedMap<'v>;
 
     fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
         hir::intravisit::NestedVisitorMap::None
     }
 
-    fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
-        if let hir::TyKind::TraitObject(
-            _,
-            hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. },
-        ) = ty.kind
-        {
-            self.0.push(ty.span);
+    fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
+        match ty.kind {
+            hir::TyKind::TraitObject(
+                _,
+                hir::Lifetime {
+                    name:
+                        hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
+                    ..
+                },
+            ) => {
+                self.0.push(ty);
+            }
+            hir::TyKind::OpaqueDef(item_id, _) => {
+                self.0.push(ty);
+                let item = self.1.expect_item(item_id.id);
+                hir::intravisit::walk_item(self, item);
+            }
+            _ => {}
         }
+        hir::intravisit::walk_ty(self, ty);
     }
 }