Skip to content

Commit 1beac2b

Browse files
committed
Move code to diagnostics.rs
1 parent 49f9bf8 commit 1beac2b

File tree

2 files changed

+214
-200
lines changed

2 files changed

+214
-200
lines changed

src/librustc_resolve/diagnostics.rs

+207-91
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_ast_pretty::pprust;
88
use rustc_data_structures::fx::FxHashSet;
99
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
1010
use rustc_feature::BUILTIN_ATTRIBUTES;
11+
use rustc_hir as hir;
1112
use rustc_hir::def::Namespace::{self, *};
1213
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind};
1314
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -19,7 +20,7 @@ use syntax::ast::{self, Ident, Path};
1920
use syntax::util::lev_distance::find_best_match_for_name;
2021

2122
use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
22-
use crate::lifetimes::{ElisionFailureInfo, MissingLifetimeSpot};
23+
use crate::lifetimes::{ElisionFailureInfo, LifetimeContext};
2324
use crate::path_names_to_string;
2425
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
2526
use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
@@ -48,6 +49,40 @@ crate struct ImportSuggestion {
4849
pub path: Path,
4950
}
5051

52+
crate enum MissingLifetimeSpot<'tcx> {
53+
Generics(&'tcx hir::Generics<'tcx>),
54+
HigherRanked { span: Span, span_type: ForLifetimeSpanType },
55+
}
56+
57+
crate enum ForLifetimeSpanType {
58+
BoundEmpty,
59+
BoundTail,
60+
TypeEmpty,
61+
TypeTail,
62+
}
63+
64+
impl ForLifetimeSpanType {
65+
crate fn descr(&self) -> &'static str {
66+
match self {
67+
Self::BoundEmpty | Self::BoundTail => "bound",
68+
Self::TypeEmpty | Self::TypeTail => "type",
69+
}
70+
}
71+
72+
crate fn suggestion(&self, sugg: &str) -> String {
73+
match self {
74+
Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg),
75+
Self::BoundTail | Self::TypeTail => format!(", {}", sugg),
76+
}
77+
}
78+
}
79+
80+
impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &'tcx hir::Generics<'tcx> {
81+
fn into(self) -> MissingLifetimeSpot<'tcx> {
82+
MissingLifetimeSpot::Generics(self)
83+
}
84+
}
85+
5186
/// Adjust the impl span so that just the `impl` keyword is taken by removing
5287
/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
5388
/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
@@ -1457,104 +1492,185 @@ crate fn show_candidates(
14571492
}
14581493
}
14591494

1460-
crate fn report_missing_lifetime_specifiers(
1461-
sess: &Session,
1462-
span: Span,
1463-
count: usize,
1464-
) -> DiagnosticBuilder<'_> {
1465-
struct_span_err!(sess, span, E0106, "missing lifetime specifier{}", pluralize!(count))
1466-
}
1495+
impl<'tcx> LifetimeContext<'_, 'tcx> {
1496+
crate fn report_missing_lifetime_specifiers(
1497+
&self,
1498+
span: Span,
1499+
count: usize,
1500+
) -> DiagnosticBuilder<'tcx> {
1501+
struct_span_err!(
1502+
self.tcx.sess,
1503+
span,
1504+
E0106,
1505+
"missing lifetime specifier{}",
1506+
pluralize!(count)
1507+
)
1508+
}
14671509

1468-
crate fn add_missing_lifetime_specifiers_label(
1469-
err: &mut DiagnosticBuilder<'_>,
1470-
source_map: &SourceMap,
1471-
span: Span,
1472-
count: usize,
1473-
lifetime_names: &FxHashSet<ast::Ident>,
1474-
snippet: Option<&str>,
1475-
missing_named_lifetime_spots: &[MissingLifetimeSpot<'_>],
1476-
params: &[ElisionFailureInfo],
1477-
) {
1478-
if count > 1 {
1479-
err.span_label(span, format!("expected {} lifetime parameters", count));
1480-
} else {
1481-
let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
1482-
err.span_suggestion(
1483-
span,
1484-
"consider using the named lifetime",
1485-
sugg,
1486-
Applicability::MaybeIncorrect,
1487-
);
1510+
crate fn emit_undeclared_lifetime_error(&self, lifetime_ref: &hir::Lifetime) {
1511+
let mut err = struct_span_err!(
1512+
self.tcx.sess,
1513+
lifetime_ref.span,
1514+
E0261,
1515+
"use of undeclared lifetime name `{}`",
1516+
lifetime_ref
1517+
);
1518+
err.span_label(lifetime_ref.span, "undeclared lifetime");
1519+
for missing in &self.missing_named_lifetime_spots {
1520+
match missing {
1521+
MissingLifetimeSpot::Generics(generics) => {
1522+
let (span, sugg) = match &generics.params {
1523+
[] => (generics.span, format!("<{}>", lifetime_ref)),
1524+
[param, ..] => (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref)),
1525+
};
1526+
err.span_suggestion(
1527+
span,
1528+
&format!("consider introducing lifetime `{}` here", lifetime_ref),
1529+
sugg,
1530+
Applicability::MaybeIncorrect,
1531+
);
1532+
}
1533+
MissingLifetimeSpot::HigherRanked { span, span_type } => {
1534+
err.span_suggestion(
1535+
*span,
1536+
&format!(
1537+
"consider making the {} lifetime-generic with a new `{}` lifetime",
1538+
span_type.descr(),
1539+
lifetime_ref
1540+
),
1541+
span_type.suggestion(&lifetime_ref.to_string()),
1542+
Applicability::MaybeIncorrect,
1543+
);
1544+
err.note(
1545+
"for more information on higher-ranked polymorphism, visit \
1546+
https://doc.rust-lang.org/nomicon/hrtb.html",
1547+
);
1548+
}
1549+
}
1550+
}
1551+
err.emit();
1552+
}
1553+
1554+
crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool {
1555+
if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res {
1556+
if [
1557+
self.tcx.lang_items().fn_once_trait(),
1558+
self.tcx.lang_items().fn_trait(),
1559+
self.tcx.lang_items().fn_mut_trait(),
1560+
]
1561+
.contains(&Some(did))
1562+
{
1563+
let (span, span_type) = match &trait_ref.bound_generic_params {
1564+
[] => (trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty),
1565+
[.., bound] => (bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail),
1566+
};
1567+
self.missing_named_lifetime_spots
1568+
.push(MissingLifetimeSpot::HigherRanked { span, span_type });
1569+
return true;
1570+
}
14881571
};
1489-
let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg: &str| {
1490-
err.span_label(span, "expected named lifetime parameter");
1491-
1492-
for missing in missing_named_lifetime_spots.iter().rev() {
1493-
let mut introduce_suggestion = vec![];
1494-
let msg;
1495-
let should_break;
1496-
introduce_suggestion.push(match missing {
1497-
MissingLifetimeSpot::Generics(generics) => {
1498-
msg = "consider introducing a named lifetime parameter".to_string();
1499-
should_break = true;
1500-
match &generics.params {
1501-
[] => (generics.span, "<'a>".to_string()),
1502-
[param, ..] => (param.span.shrink_to_lo(), "'a, ".to_string()),
1572+
false
1573+
}
1574+
1575+
crate fn add_missing_lifetime_specifiers_label(
1576+
&self,
1577+
err: &mut DiagnosticBuilder<'_>,
1578+
span: Span,
1579+
count: usize,
1580+
lifetime_names: &FxHashSet<ast::Ident>,
1581+
params: &[ElisionFailureInfo],
1582+
) {
1583+
if count > 1 {
1584+
err.span_label(span, format!("expected {} lifetime parameters", count));
1585+
} else {
1586+
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok();
1587+
let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
1588+
err.span_suggestion(
1589+
span,
1590+
"consider using the named lifetime",
1591+
sugg,
1592+
Applicability::MaybeIncorrect,
1593+
);
1594+
};
1595+
let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg: &str| {
1596+
err.span_label(span, "expected named lifetime parameter");
1597+
1598+
for missing in self.missing_named_lifetime_spots.iter().rev() {
1599+
let mut introduce_suggestion = vec![];
1600+
let msg;
1601+
let should_break;
1602+
introduce_suggestion.push(match missing {
1603+
MissingLifetimeSpot::Generics(generics) => {
1604+
msg = "consider introducing a named lifetime parameter".to_string();
1605+
should_break = true;
1606+
match &generics.params {
1607+
[] => (generics.span, "<'a>".to_string()),
1608+
[param, ..] => (param.span.shrink_to_lo(), "'a, ".to_string()),
1609+
}
15031610
}
1504-
}
1505-
MissingLifetimeSpot::HigherRanked { span, span_type } => {
1506-
msg = format!(
1507-
"consider making the {} lifetime-generic with a new `'a` lifetime",
1508-
span_type.descr(),
1509-
);
1510-
should_break = false;
1511-
err.note(
1512-
"for more information on higher-ranked polymorphism, visit \
1611+
MissingLifetimeSpot::HigherRanked { span, span_type } => {
1612+
msg = format!(
1613+
"consider making the {} lifetime-generic with a new `'a` lifetime",
1614+
span_type.descr(),
1615+
);
1616+
should_break = false;
1617+
err.note(
1618+
"for more information on higher-ranked polymorphism, visit \
15131619
https://doc.rust-lang.org/nomicon/hrtb.html",
1514-
);
1515-
(*span, span_type.suggestion("'a"))
1516-
}
1517-
});
1518-
for param in params {
1519-
if let Ok(snippet) = source_map.span_to_snippet(param.span) {
1520-
if snippet.starts_with("&") && !snippet.starts_with("&'") {
1521-
introduce_suggestion
1522-
.push((param.span, format!("&'a {}", &snippet[1..])));
1523-
} else if snippet.starts_with("&'_ ") {
1524-
introduce_suggestion
1525-
.push((param.span, format!("&'a {}", &snippet[4..])));
1620+
);
1621+
(*span, span_type.suggestion("'a"))
1622+
}
1623+
});
1624+
for param in params {
1625+
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span)
1626+
{
1627+
if snippet.starts_with("&") && !snippet.starts_with("&'") {
1628+
introduce_suggestion
1629+
.push((param.span, format!("&'a {}", &snippet[1..])));
1630+
} else if snippet.starts_with("&'_ ") {
1631+
introduce_suggestion
1632+
.push((param.span, format!("&'a {}", &snippet[4..])));
1633+
}
15261634
}
15271635
}
1636+
introduce_suggestion.push((span, sugg.to_string()));
1637+
err.multipart_suggestion(
1638+
&msg,
1639+
introduce_suggestion,
1640+
Applicability::MaybeIncorrect,
1641+
);
1642+
if should_break {
1643+
break;
1644+
}
15281645
}
1529-
introduce_suggestion.push((span, sugg.to_string()));
1530-
err.multipart_suggestion(&msg, introduce_suggestion, Applicability::MaybeIncorrect);
1531-
if should_break {
1532-
break;
1533-
}
1534-
}
1535-
};
1646+
};
15361647

1537-
match (lifetime_names.len(), lifetime_names.iter().next(), snippet) {
1538-
(1, Some(name), Some("&")) => {
1539-
suggest_existing(err, format!("&{} ", name));
1540-
}
1541-
(1, Some(name), Some("'_")) => {
1542-
suggest_existing(err, name.to_string());
1543-
}
1544-
(1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
1545-
suggest_existing(err, format!("{}<{}>", snippet, name));
1546-
}
1547-
(0, _, Some("&")) => {
1548-
suggest_new(err, "&'a ");
1549-
}
1550-
(0, _, Some("'_")) => {
1551-
suggest_new(err, "'a");
1552-
}
1553-
(0, _, Some(snippet)) if !snippet.ends_with(">") => {
1554-
suggest_new(err, &format!("{}<'a>", snippet));
1555-
}
1556-
_ => {
1557-
err.span_label(span, "expected lifetime parameter");
1648+
match (
1649+
lifetime_names.len(),
1650+
lifetime_names.iter().next(),
1651+
snippet.as_ref().map(|s| s.as_str()),
1652+
) {
1653+
(1, Some(name), Some("&")) => {
1654+
suggest_existing(err, format!("&{} ", name));
1655+
}
1656+
(1, Some(name), Some("'_")) => {
1657+
suggest_existing(err, name.to_string());
1658+
}
1659+
(1, Some(name), Some(snippet)) if !snippet.ends_with(">") => {
1660+
suggest_existing(err, format!("{}<{}>", snippet, name));
1661+
}
1662+
(0, _, Some("&")) => {
1663+
suggest_new(err, "&'a ");
1664+
}
1665+
(0, _, Some("'_")) => {
1666+
suggest_new(err, "'a");
1667+
}
1668+
(0, _, Some(snippet)) if !snippet.ends_with(">") => {
1669+
suggest_new(err, &format!("{}<'a>", snippet));
1670+
}
1671+
_ => {
1672+
err.span_label(span, "expected lifetime parameter");
1673+
}
15581674
}
15591675
}
15601676
}

0 commit comments

Comments
 (0)