]> git.lizzy.rs Git - rust.git/commitdiff
Move code to `diagnostics.rs`
authorEsteban Küber <esteban@kuber.com.ar>
Tue, 28 Jan 2020 23:04:18 +0000 (15:04 -0800)
committerEsteban Küber <esteban@kuber.com.ar>
Wed, 5 Feb 2020 18:32:01 +0000 (10:32 -0800)
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lifetimes.rs

index be7a9de4317c594d77eaab1d41beb0bacd5f8d55..2732197f3612567f8b707faa848ae94425bc6a55 100644 (file)
@@ -8,6 +8,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_feature::BUILTIN_ATTRIBUTES;
+use rustc_hir as hir;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -19,7 +20,7 @@
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
-use crate::lifetimes::{ElisionFailureInfo, MissingLifetimeSpot};
+use crate::lifetimes::{ElisionFailureInfo, LifetimeContext};
 use crate::path_names_to_string;
 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
 use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
@@ -48,6 +49,40 @@ impl TypoSuggestion {
     pub path: Path,
 }
 
+crate enum MissingLifetimeSpot<'tcx> {
+    Generics(&'tcx hir::Generics<'tcx>),
+    HigherRanked { span: Span, span_type: ForLifetimeSpanType },
+}
+
+crate enum ForLifetimeSpanType {
+    BoundEmpty,
+    BoundTail,
+    TypeEmpty,
+    TypeTail,
+}
+
+impl ForLifetimeSpanType {
+    crate fn descr(&self) -> &'static str {
+        match self {
+            Self::BoundEmpty | Self::BoundTail => "bound",
+            Self::TypeEmpty | Self::TypeTail => "type",
+        }
+    }
+
+    crate fn suggestion(&self, sugg: &str) -> String {
+        match self {
+            Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg),
+            Self::BoundTail | Self::TypeTail => format!(", {}", sugg),
+        }
+    }
+}
+
+impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &'tcx hir::Generics<'tcx> {
+    fn into(self) -> MissingLifetimeSpot<'tcx> {
+        MissingLifetimeSpot::Generics(self)
+    }
+}
+
 /// Adjust the impl span so that just the `impl` keyword is taken by removing
 /// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
 /// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
@@ -1457,104 +1492,185 @@ fn find_span_immediately_after_crate_name(
     }
 }
 
-crate fn report_missing_lifetime_specifiers(
-    sess: &Session,
-    span: Span,
-    count: usize,
-) -> DiagnosticBuilder<'_> {
-    struct_span_err!(sess, span, E0106, "missing lifetime specifier{}", pluralize!(count))
-}
+impl<'tcx> LifetimeContext<'_, 'tcx> {
+    crate fn report_missing_lifetime_specifiers(
+        &self,
+        span: Span,
+        count: usize,
+    ) -> DiagnosticBuilder<'tcx> {
+        struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0106,
+            "missing lifetime specifier{}",
+            pluralize!(count)
+        )
+    }
 
-crate fn add_missing_lifetime_specifiers_label(
-    err: &mut DiagnosticBuilder<'_>,
-    source_map: &SourceMap,
-    span: Span,
-    count: usize,
-    lifetime_names: &FxHashSet<ast::Ident>,
-    snippet: Option<&str>,
-    missing_named_lifetime_spots: &[MissingLifetimeSpot<'_>],
-    params: &[ElisionFailureInfo],
-) {
-    if count > 1 {
-        err.span_label(span, format!("expected {} lifetime parameters", count));
-    } else {
-        let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
-            err.span_suggestion(
-                span,
-                "consider using the named lifetime",
-                sugg,
-                Applicability::MaybeIncorrect,
-            );
+    crate fn emit_undeclared_lifetime_error(&self, lifetime_ref: &hir::Lifetime) {
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            lifetime_ref.span,
+            E0261,
+            "use of undeclared lifetime name `{}`",
+            lifetime_ref
+        );
+        err.span_label(lifetime_ref.span, "undeclared lifetime");
+        for missing in &self.missing_named_lifetime_spots {
+            match missing {
+                MissingLifetimeSpot::Generics(generics) => {
+                    let (span, sugg) = match &generics.params {
+                        [] => (generics.span, format!("<{}>", lifetime_ref)),
+                        [param, ..] => (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref)),
+                    };
+                    err.span_suggestion(
+                        span,
+                        &format!("consider introducing lifetime `{}` here", lifetime_ref),
+                        sugg,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                MissingLifetimeSpot::HigherRanked { span, span_type } => {
+                    err.span_suggestion(
+                        *span,
+                        &format!(
+                            "consider making the {} lifetime-generic with a new `{}` lifetime",
+                            span_type.descr(),
+                            lifetime_ref
+                        ),
+                        span_type.suggestion(&lifetime_ref.to_string()),
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.note(
+                        "for more information on higher-ranked polymorphism, visit \
+                            https://doc.rust-lang.org/nomicon/hrtb.html",
+                    );
+                }
+            }
+        }
+        err.emit();
+    }
+
+    crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool {
+        if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res {
+            if [
+                self.tcx.lang_items().fn_once_trait(),
+                self.tcx.lang_items().fn_trait(),
+                self.tcx.lang_items().fn_mut_trait(),
+            ]
+            .contains(&Some(did))
+            {
+                let (span, span_type) = match &trait_ref.bound_generic_params {
+                    [] => (trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty),
+                    [.., bound] => (bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail),
+                };
+                self.missing_named_lifetime_spots
+                    .push(MissingLifetimeSpot::HigherRanked { span, span_type });
+                return true;
+            }
         };
-        let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg: &str| {
-            err.span_label(span, "expected named lifetime parameter");
-
-            for missing in missing_named_lifetime_spots.iter().rev() {
-                let mut introduce_suggestion = vec![];
-                let msg;
-                let should_break;
-                introduce_suggestion.push(match missing {
-                    MissingLifetimeSpot::Generics(generics) => {
-                        msg = "consider introducing a named lifetime parameter".to_string();
-                        should_break = true;
-                        match &generics.params {
-                            [] => (generics.span, "<'a>".to_string()),
-                            [param, ..] => (param.span.shrink_to_lo(), "'a, ".to_string()),
+        false
+    }
+
+    crate fn add_missing_lifetime_specifiers_label(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        span: Span,
+        count: usize,
+        lifetime_names: &FxHashSet<ast::Ident>,
+        params: &[ElisionFailureInfo],
+    ) {
+        if count > 1 {
+            err.span_label(span, format!("expected {} lifetime parameters", count));
+        } else {
+            let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok();
+            let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
+                err.span_suggestion(
+                    span,
+                    "consider using the named lifetime",
+                    sugg,
+                    Applicability::MaybeIncorrect,
+                );
+            };
+            let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg: &str| {
+                err.span_label(span, "expected named lifetime parameter");
+
+                for missing in self.missing_named_lifetime_spots.iter().rev() {
+                    let mut introduce_suggestion = vec![];
+                    let msg;
+                    let should_break;
+                    introduce_suggestion.push(match missing {
+                        MissingLifetimeSpot::Generics(generics) => {
+                            msg = "consider introducing a named lifetime parameter".to_string();
+                            should_break = true;
+                            match &generics.params {
+                                [] => (generics.span, "<'a>".to_string()),
+                                [param, ..] => (param.span.shrink_to_lo(), "'a, ".to_string()),
+                            }
                         }
-                    }
-                    MissingLifetimeSpot::HigherRanked { span, span_type } => {
-                        msg = format!(
-                            "consider making the {} lifetime-generic with a new `'a` lifetime",
-                            span_type.descr(),
-                        );
-                        should_break = false;
-                        err.note(
-                            "for more information on higher-ranked polymorphism, visit \
+                        MissingLifetimeSpot::HigherRanked { span, span_type } => {
+                            msg = format!(
+                                "consider making the {} lifetime-generic with a new `'a` lifetime",
+                                span_type.descr(),
+                            );
+                            should_break = false;
+                            err.note(
+                                "for more information on higher-ranked polymorphism, visit \
                              https://doc.rust-lang.org/nomicon/hrtb.html",
-                        );
-                        (*span, span_type.suggestion("'a"))
-                    }
-                });
-                for param in params {
-                    if let Ok(snippet) = source_map.span_to_snippet(param.span) {
-                        if snippet.starts_with("&") && !snippet.starts_with("&'") {
-                            introduce_suggestion
-                                .push((param.span, format!("&'a {}", &snippet[1..])));
-                        } else if snippet.starts_with("&'_ ") {
-                            introduce_suggestion
-                                .push((param.span, format!("&'a {}", &snippet[4..])));
+                            );
+                            (*span, span_type.suggestion("'a"))
+                        }
+                    });
+                    for param in params {
+                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span)
+                        {
+                            if snippet.starts_with("&") && !snippet.starts_with("&'") {
+                                introduce_suggestion
+                                    .push((param.span, format!("&'a {}", &snippet[1..])));
+                            } else if snippet.starts_with("&'_ ") {
+                                introduce_suggestion
+                                    .push((param.span, format!("&'a {}", &snippet[4..])));
+                            }
                         }
                     }
+                    introduce_suggestion.push((span, sugg.to_string()));
+                    err.multipart_suggestion(
+                        &msg,
+                        introduce_suggestion,
+                        Applicability::MaybeIncorrect,
+                    );
+                    if should_break {
+                        break;
+                    }
                 }
-                introduce_suggestion.push((span, sugg.to_string()));
-                err.multipart_suggestion(&msg, introduce_suggestion, Applicability::MaybeIncorrect);
-                if should_break {
-                    break;
-                }
-            }
-        };
+            };
 
-        match (lifetime_names.len(), lifetime_names.iter().next(), snippet) {
-            (1, Some(name), Some("&")) => {
-                suggest_existing(err, format!("&{} ", name));
-            }
-            (1, Some(name), Some("'_")) => {
-                suggest_existing(err, name.to_string());
-            }
-            (1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
-                suggest_existing(err, format!("{}<{}>", snippet, name));
-            }
-            (0, _, Some("&")) => {
-                suggest_new(err, "&'a ");
-            }
-            (0, _, Some("'_")) => {
-                suggest_new(err, "'a");
-            }
-            (0, _, Some(snippet)) if !snippet.ends_with(">") => {
-                suggest_new(err, &format!("{}<'a>", snippet));
-            }
-            _ => {
-                err.span_label(span, "expected lifetime parameter");
+            match (
+                lifetime_names.len(),
+                lifetime_names.iter().next(),
+                snippet.as_ref().map(|s| s.as_str()),
+            ) {
+                (1, Some(name), Some("&")) => {
+                    suggest_existing(err, format!("&{} ", name));
+                }
+                (1, Some(name), Some("'_")) => {
+                    suggest_existing(err, name.to_string());
+                }
+                (1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
+                    suggest_existing(err, format!("{}<{}>", snippet, name));
+                }
+                (0, _, Some("&")) => {
+                    suggest_new(err, "&'a ");
+                }
+                (0, _, Some("'_")) => {
+                    suggest_new(err, "'a");
+                }
+                (0, _, Some(snippet)) if !snippet.ends_with(">") => {
+                    suggest_new(err, &format!("{}<'a>", snippet));
+                }
+                _ => {
+                    err.span_label(span, "expected lifetime parameter");
+                }
             }
         }
     }
index 811b36022a5b9b83ad5bf6b844e638d769a4b695..0ba9b4f17068e0fbcc5a047a179133acbc74afcb 100644 (file)
@@ -5,9 +5,7 @@
 //! used between functions, and they operate in a purely top-down
 //! way. Therefore, we break lifetime name resolution into a separate pass.
 
-use crate::diagnostics::{
-    add_missing_lifetime_specifiers_label, report_missing_lifetime_specifiers,
-};
+use crate::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
 use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::middle::resolve_lifetime::*;
@@ -153,42 +151,8 @@ struct NamedRegionMap {
     object_lifetime_defaults: HirIdMap<Vec<ObjectLifetimeDefault>>,
 }
 
-crate enum MissingLifetimeSpot<'tcx> {
-    Generics(&'tcx hir::Generics<'tcx>),
-    HigherRanked { span: Span, span_type: ForLifetimeSpanType },
-}
-
-crate enum ForLifetimeSpanType {
-    BoundEmpty,
-    BoundTail,
-    TypeEmpty,
-    TypeTail,
-}
-
-impl ForLifetimeSpanType {
-    crate fn descr(&self) -> &'static str {
-        match self {
-            Self::BoundEmpty | Self::BoundTail => "bound",
-            Self::TypeEmpty | Self::TypeTail => "type",
-        }
-    }
-
-    crate fn suggestion(&self, sugg: &str) -> String {
-        match self {
-            Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg),
-            Self::BoundTail | Self::TypeTail => format!(", {}", sugg),
-        }
-    }
-}
-
-impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &'tcx hir::Generics<'tcx> {
-    fn into(self) -> MissingLifetimeSpot<'tcx> {
-        MissingLifetimeSpot::Generics(self)
-    }
-}
-
-struct LifetimeContext<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
+crate struct LifetimeContext<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
     map: &'a mut NamedRegionMap,
     scope: ScopeRef<'a>,
 
@@ -220,7 +184,7 @@ struct LifetimeContext<'a, 'tcx> {
 
     /// When encountering an undefined named lifetime, we will suggest introducing it in these
     /// places.
-    missing_named_lifetime_spots: Vec<MissingLifetimeSpot<'tcx>>,
+    crate missing_named_lifetime_spots: Vec<MissingLifetimeSpot<'tcx>>,
 }
 
 #[derive(Debug)]
@@ -1879,49 +1843,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
 
             self.insert_lifetime(lifetime_ref, def);
         } else {
-            let mut err = struct_span_err!(
-                self.tcx.sess,
-                lifetime_ref.span,
-                E0261,
-                "use of undeclared lifetime name `{}`",
-                lifetime_ref
-            );
-            err.span_label(lifetime_ref.span, "undeclared lifetime");
-            for missing in &self.missing_named_lifetime_spots {
-                match missing {
-                    MissingLifetimeSpot::Generics(generics) => {
-                        let (span, sugg) = match &generics.params {
-                            [] => (generics.span, format!("<{}>", lifetime_ref)),
-                            [param, ..] => {
-                                (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
-                            }
-                        };
-                        err.span_suggestion(
-                            span,
-                            &format!("consider introducing lifetime `{}` here", lifetime_ref),
-                            sugg,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                    MissingLifetimeSpot::HigherRanked { span, span_type } => {
-                        err.span_suggestion(
-                            *span,
-                            &format!(
-                                "consider making the {} lifetime-generic with a new `{}` lifetime",
-                                span_type.descr(),
-                                lifetime_ref
-                            ),
-                            span_type.suggestion(&lifetime_ref.to_string()),
-                            Applicability::MaybeIncorrect,
-                        );
-                        err.note(
-                            "for more information on higher-ranked polymorphism, visit \
-                             https://doc.rust-lang.org/nomicon/hrtb.html",
-                        );
-                    }
-                }
-            }
-            err.emit();
+            self.emit_undeclared_lifetime_error(lifetime_ref);
         }
     }
 
@@ -2461,7 +2383,7 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>)
             }
         };
 
-        let mut err = report_missing_lifetime_specifiers(self.tcx.sess, span, lifetime_refs.len());
+        let mut err = self.report_missing_lifetime_specifiers(span, lifetime_refs.len());
         let mut add_label = true;
 
         if let Some(params) = error {
@@ -2470,14 +2392,11 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>)
             }
         }
         if add_label {
-            add_missing_lifetime_specifiers_label(
+            self.add_missing_lifetime_specifiers_label(
                 &mut err,
-                self.tcx.sess.source_map(),
                 span,
                 lifetime_refs.len(),
                 &lifetime_names,
-                self.tcx.sess.source_map().span_to_snippet(span).ok().as_ref().map(|s| s.as_str()),
-                &self.missing_named_lifetime_spots,
                 error.map(|p| &p[..]).unwrap_or(&[]),
             );
         }
@@ -2827,27 +2746,6 @@ fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_
         let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
         assert_eq!(old_value, Some(bad_def));
     }
-
-    fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool {
-        if let Res::Def(_, did) = trait_ref.trait_ref.path.res {
-            if [
-                self.tcx.lang_items().fn_once_trait(),
-                self.tcx.lang_items().fn_trait(),
-                self.tcx.lang_items().fn_mut_trait(),
-            ]
-            .contains(&Some(did))
-            {
-                let (span, span_type) = match &trait_ref.bound_generic_params {
-                    [] => (trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty),
-                    [.., bound] => (bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail),
-                };
-                self.missing_named_lifetime_spots
-                    .push(MissingLifetimeSpot::HigherRanked { span, span_type });
-                return true;
-            }
-        };
-        false
-    }
 }
 
 /// Detects late-bound lifetimes and inserts them into