use rustc::bug;
use rustc::session::Session;
use rustc::ty::{self, DefIdTree};
+use rustc_ast::ast::{self, Ident, Path};
+use rustc_ast::util::lev_distance::find_best_match_for_name;
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_errors::{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};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{BytePos, MultiSpan, Span};
-use syntax::ast::{self, Ident, Path};
-use syntax::util::lev_distance::find_best_match_for_name;
use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
-use crate::lifetimes::{ElisionFailureInfo, LifetimeContext};
use crate::path_names_to_string;
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
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"`).
E0401,
"can't use generic parameters from outer function",
);
- err.span_label(span, format!("use of generic parameter from outer function"));
+ err.span_label(span, "use of generic parameter from outer function".to_string());
let sm = self.session.source_map();
match outer_res {
if has_generic_params == HasGenericParams::Yes {
// Try to retrieve the span of the function signature and generate a new
// message with a local type or const parameter.
- let sugg_msg = &format!("try using a local generic parameter instead");
+ let sugg_msg = "try using a local generic parameter instead";
if let Some((sugg_span, snippet)) = sm.generate_local_type_param_snippet(span) {
// Suggest the modification to the user
err.span_suggestion(
} else if let Some(sp) = sm.generate_fn_name_span(span) {
err.span_label(
sp,
- format!("try adding a local generic parameter in this method instead"),
+ "try adding a local generic parameter in this method instead"
+ .to_string(),
);
} else {
- err.help(&format!("try using a local generic parameter instead"));
+ err.help("try using a local generic parameter instead");
}
}
self.session,
span,
E0409,
- "variable `{}` is bound in inconsistent \
- ways within the same match arm",
+ "variable `{}` is bound inconsistently across alternatives separated by `|`",
variable_name
);
err.span_label(span, "bound in different ways");
// we want consistent results across executions, but candidates are produced
// by iterating through a hash map, so make sure they are ordered:
let mut path_strings: Vec<_> =
- candidates.into_iter().map(|c| path_names_to_string(&c.path)).collect();
+ candidates.iter().map(|c| path_names_to_string(&c.path)).collect();
path_strings.sort();
path_strings.dedup();
err.note(&msg);
}
}
-
-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 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) = if let Some(param) = generics
- .params
- .iter()
- .filter(|p| match p.kind {
- hir::GenericParamKind::Type {
- synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
- ..
- } => false,
- _ => true,
- })
- .next()
- {
- (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
- } else {
- (generics.span, 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;
- }
- };
- 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;
- if let Some(param) = generics.params.iter().filter(|p| match p.kind {
- hir::GenericParamKind::Type {
- synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
- ..
- } => false,
- _ => true,
- }).next() {
- (param.span.shrink_to_lo(), "'a, ".to_string())
- } else {
- (generics.span, "<'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 \
- https://doc.rust-lang.org/nomicon/hrtb.html",
- );
- (*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;
- }
- }
- };
-
- 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");
- }
- }
- }
- }
-}