@@ -7,6 +7,7 @@ use rustc::ty::{self, DefIdTree};
77use rustc_data_structures:: fx:: FxHashSet ;
88use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticBuilder } ;
99use rustc_feature:: BUILTIN_ATTRIBUTES ;
10+ use rustc_hir as hir;
1011use rustc_hir:: def:: Namespace :: { self , * } ;
1112use rustc_hir:: def:: { self , CtorKind , CtorOf , DefKind , NonMacroAttrKind } ;
1213use rustc_hir:: def_id:: { DefId , CRATE_DEF_INDEX , LOCAL_CRATE } ;
@@ -19,7 +20,7 @@ use syntax::print::pprust;
1920use syntax:: util:: lev_distance:: find_best_match_for_name;
2021
2122use crate :: imports:: { ImportDirective , ImportDirectiveSubclass , ImportResolver } ;
22- use crate :: lifetimes:: { ElisionFailureInfo , MissingLifetimeSpot } ;
23+ use crate :: lifetimes:: { ElisionFailureInfo , LifetimeContext } ;
2324use crate :: path_names_to_string;
2425use crate :: { AmbiguityError , AmbiguityErrorMisc , AmbiguityKind } ;
2526use 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"`).
@@ -1452,104 +1487,185 @@ crate fn show_candidates(
14521487 }
14531488}
14541489
1455- crate fn report_missing_lifetime_specifiers (
1456- sess : & Session ,
1457- span : Span ,
1458- count : usize ,
1459- ) -> DiagnosticBuilder < ' _ > {
1460- struct_span_err ! ( sess, span, E0106 , "missing lifetime specifier{}" , pluralize!( count) )
1461- }
1490+ impl < ' tcx > LifetimeContext < ' _ , ' tcx > {
1491+ crate fn report_missing_lifetime_specifiers (
1492+ & self ,
1493+ span : Span ,
1494+ count : usize ,
1495+ ) -> DiagnosticBuilder < ' tcx > {
1496+ struct_span_err ! (
1497+ self . tcx. sess,
1498+ span,
1499+ E0106 ,
1500+ "missing lifetime specifier{}" ,
1501+ pluralize!( count)
1502+ )
1503+ }
14621504
1463- crate fn add_missing_lifetime_specifiers_label (
1464- err : & mut DiagnosticBuilder < ' _ > ,
1465- source_map : & SourceMap ,
1466- span : Span ,
1467- count : usize ,
1468- lifetime_names : & FxHashSet < ast:: Ident > ,
1469- snippet : Option < & str > ,
1470- missing_named_lifetime_spots : & [ MissingLifetimeSpot < ' _ > ] ,
1471- params : & [ ElisionFailureInfo ] ,
1472- ) {
1473- if count > 1 {
1474- err. span_label ( span, format ! ( "expected {} lifetime parameters" , count) ) ;
1475- } else {
1476- let suggest_existing = |err : & mut DiagnosticBuilder < ' _ > , sugg| {
1477- err. span_suggestion (
1478- span,
1479- "consider using the named lifetime" ,
1480- sugg,
1481- Applicability :: MaybeIncorrect ,
1482- ) ;
1505+ crate fn emit_undeclared_lifetime_error ( & self , lifetime_ref : & hir:: Lifetime ) {
1506+ let mut err = struct_span_err ! (
1507+ self . tcx. sess,
1508+ lifetime_ref. span,
1509+ E0261 ,
1510+ "use of undeclared lifetime name `{}`" ,
1511+ lifetime_ref
1512+ ) ;
1513+ err. span_label ( lifetime_ref. span , "undeclared lifetime" ) ;
1514+ for missing in & self . missing_named_lifetime_spots {
1515+ match missing {
1516+ MissingLifetimeSpot :: Generics ( generics) => {
1517+ let ( span, sugg) = match & generics. params {
1518+ [ ] => ( generics. span , format ! ( "<{}>" , lifetime_ref) ) ,
1519+ [ param, ..] => ( param. span . shrink_to_lo ( ) , format ! ( "{}, " , lifetime_ref) ) ,
1520+ } ;
1521+ err. span_suggestion (
1522+ span,
1523+ & format ! ( "consider introducing lifetime `{}` here" , lifetime_ref) ,
1524+ sugg,
1525+ Applicability :: MaybeIncorrect ,
1526+ ) ;
1527+ }
1528+ MissingLifetimeSpot :: HigherRanked { span, span_type } => {
1529+ err. span_suggestion (
1530+ * span,
1531+ & format ! (
1532+ "consider making the {} lifetime-generic with a new `{}` lifetime" ,
1533+ span_type. descr( ) ,
1534+ lifetime_ref
1535+ ) ,
1536+ span_type. suggestion ( & lifetime_ref. to_string ( ) ) ,
1537+ Applicability :: MaybeIncorrect ,
1538+ ) ;
1539+ err. note (
1540+ "for more information on higher-ranked polymorphism, visit \
1541+ https://doc.rust-lang.org/nomicon/hrtb.html",
1542+ ) ;
1543+ }
1544+ }
1545+ }
1546+ err. emit ( ) ;
1547+ }
1548+
1549+ crate fn is_trait_ref_fn_scope ( & mut self , trait_ref : & ' tcx hir:: PolyTraitRef < ' tcx > ) -> bool {
1550+ if let def:: Res :: Def ( _, did) = trait_ref. trait_ref . path . res {
1551+ if [
1552+ self . tcx . lang_items ( ) . fn_once_trait ( ) ,
1553+ self . tcx . lang_items ( ) . fn_trait ( ) ,
1554+ self . tcx . lang_items ( ) . fn_mut_trait ( ) ,
1555+ ]
1556+ . contains ( & Some ( did) )
1557+ {
1558+ let ( span, span_type) = match & trait_ref. bound_generic_params {
1559+ [ ] => ( trait_ref. span . shrink_to_lo ( ) , ForLifetimeSpanType :: BoundEmpty ) ,
1560+ [ .., bound] => ( bound. span . shrink_to_hi ( ) , ForLifetimeSpanType :: BoundTail ) ,
1561+ } ;
1562+ self . missing_named_lifetime_spots
1563+ . push ( MissingLifetimeSpot :: HigherRanked { span, span_type } ) ;
1564+ return true ;
1565+ }
14831566 } ;
1484- let suggest_new = |err : & mut DiagnosticBuilder < ' _ > , sugg : & str | {
1485- err. span_label ( span, "expected named lifetime parameter" ) ;
1486-
1487- for missing in missing_named_lifetime_spots. iter ( ) . rev ( ) {
1488- let mut introduce_suggestion = vec ! [ ] ;
1489- let msg;
1490- let should_break;
1491- introduce_suggestion. push ( match missing {
1492- MissingLifetimeSpot :: Generics ( generics) => {
1493- msg = "consider introducing a named lifetime parameter" . to_string ( ) ;
1494- should_break = true ;
1495- match & generics. params {
1496- [ ] => ( generics. span , "<'a>" . to_string ( ) ) ,
1497- [ param, ..] => ( param. span . shrink_to_lo ( ) , "'a, " . to_string ( ) ) ,
1567+ false
1568+ }
1569+
1570+ crate fn add_missing_lifetime_specifiers_label (
1571+ & self ,
1572+ err : & mut DiagnosticBuilder < ' _ > ,
1573+ span : Span ,
1574+ count : usize ,
1575+ lifetime_names : & FxHashSet < ast:: Ident > ,
1576+ params : & [ ElisionFailureInfo ] ,
1577+ ) {
1578+ if count > 1 {
1579+ err. span_label ( span, format ! ( "expected {} lifetime parameters" , count) ) ;
1580+ } else {
1581+ let snippet = self . tcx . sess . source_map ( ) . span_to_snippet ( span) . ok ( ) ;
1582+ let suggest_existing = |err : & mut DiagnosticBuilder < ' _ > , sugg| {
1583+ err. span_suggestion (
1584+ span,
1585+ "consider using the named lifetime" ,
1586+ sugg,
1587+ Applicability :: MaybeIncorrect ,
1588+ ) ;
1589+ } ;
1590+ let suggest_new = |err : & mut DiagnosticBuilder < ' _ > , sugg : & str | {
1591+ err. span_label ( span, "expected named lifetime parameter" ) ;
1592+
1593+ for missing in self . missing_named_lifetime_spots . iter ( ) . rev ( ) {
1594+ let mut introduce_suggestion = vec ! [ ] ;
1595+ let msg;
1596+ let should_break;
1597+ introduce_suggestion. push ( match missing {
1598+ MissingLifetimeSpot :: Generics ( generics) => {
1599+ msg = "consider introducing a named lifetime parameter" . to_string ( ) ;
1600+ should_break = true ;
1601+ match & generics. params {
1602+ [ ] => ( generics. span , "<'a>" . to_string ( ) ) ,
1603+ [ param, ..] => ( param. span . shrink_to_lo ( ) , "'a, " . to_string ( ) ) ,
1604+ }
14981605 }
1499- }
1500- MissingLifetimeSpot :: HigherRanked { span, span_type } => {
1501- msg = format ! (
1502- "consider making the {} lifetime-generic with a new `'a` lifetime" ,
1503- span_type. descr( ) ,
1504- ) ;
1505- should_break = false ;
1506- err. note (
1507- "for more information on higher-ranked polymorphism, visit \
1606+ MissingLifetimeSpot :: HigherRanked { span, span_type } => {
1607+ msg = format ! (
1608+ "consider making the {} lifetime-generic with a new `'a` lifetime" ,
1609+ span_type. descr( ) ,
1610+ ) ;
1611+ should_break = false ;
1612+ err. note (
1613+ "for more information on higher-ranked polymorphism, visit \
15081614 https://doc.rust-lang.org/nomicon/hrtb.html",
1509- ) ;
1510- ( * span, span_type. suggestion ( "'a" ) )
1511- }
1512- } ) ;
1513- for param in params {
1514- if let Ok ( snippet) = source_map. span_to_snippet ( param. span ) {
1515- if snippet. starts_with ( "&" ) && !snippet. starts_with ( "&'" ) {
1516- introduce_suggestion
1517- . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 1 ..] ) ) ) ;
1518- } else if snippet. starts_with ( "&'_ " ) {
1519- introduce_suggestion
1520- . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 4 ..] ) ) ) ;
1615+ ) ;
1616+ ( * span, span_type. suggestion ( "'a" ) )
1617+ }
1618+ } ) ;
1619+ for param in params {
1620+ if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( param. span )
1621+ {
1622+ if snippet. starts_with ( "&" ) && !snippet. starts_with ( "&'" ) {
1623+ introduce_suggestion
1624+ . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 1 ..] ) ) ) ;
1625+ } else if snippet. starts_with ( "&'_ " ) {
1626+ introduce_suggestion
1627+ . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 4 ..] ) ) ) ;
1628+ }
15211629 }
15221630 }
1631+ introduce_suggestion. push ( ( span, sugg. to_string ( ) ) ) ;
1632+ err. multipart_suggestion (
1633+ & msg,
1634+ introduce_suggestion,
1635+ Applicability :: MaybeIncorrect ,
1636+ ) ;
1637+ if should_break {
1638+ break ;
1639+ }
15231640 }
1524- introduce_suggestion. push ( ( span, sugg. to_string ( ) ) ) ;
1525- err. multipart_suggestion ( & msg, introduce_suggestion, Applicability :: MaybeIncorrect ) ;
1526- if should_break {
1527- break ;
1528- }
1529- }
1530- } ;
1641+ } ;
15311642
1532- match ( lifetime_names. len ( ) , lifetime_names. iter ( ) . next ( ) , snippet) {
1533- ( 1 , Some ( name) , Some ( "&" ) ) => {
1534- suggest_existing ( err, format ! ( "&{} " , name) ) ;
1535- }
1536- ( 1 , Some ( name) , Some ( "'_" ) ) => {
1537- suggest_existing ( err, name. to_string ( ) ) ;
1538- }
1539- ( 1 , Some ( name) , Some ( snippet) ) if !snippet. ends_with ( ">" ) => {
1540- suggest_existing ( err, format ! ( "{}<{}>" , snippet, name) ) ;
1541- }
1542- ( 0 , _, Some ( "&" ) ) => {
1543- suggest_new ( err, "&'a " ) ;
1544- }
1545- ( 0 , _, Some ( "'_" ) ) => {
1546- suggest_new ( err, "'a" ) ;
1547- }
1548- ( 0 , _, Some ( snippet) ) if !snippet. ends_with ( ">" ) => {
1549- suggest_new ( err, & format ! ( "{}<'a>" , snippet) ) ;
1550- }
1551- _ => {
1552- err. span_label ( span, "expected lifetime parameter" ) ;
1643+ match (
1644+ lifetime_names. len ( ) ,
1645+ lifetime_names. iter ( ) . next ( ) ,
1646+ snippet. as_ref ( ) . map ( |s| s. as_str ( ) ) ,
1647+ ) {
1648+ ( 1 , Some ( name) , Some ( "&" ) ) => {
1649+ suggest_existing ( err, format ! ( "&{} " , name) ) ;
1650+ }
1651+ ( 1 , Some ( name) , Some ( "'_" ) ) => {
1652+ suggest_existing ( err, name. to_string ( ) ) ;
1653+ }
1654+ ( 1 , Some ( name) , Some ( snippet) ) if !snippet. ends_with ( ">" ) => {
1655+ suggest_existing ( err, format ! ( "{}<{}>" , snippet, name) ) ;
1656+ }
1657+ ( 0 , _, Some ( "&" ) ) => {
1658+ suggest_new ( err, "&'a " ) ;
1659+ }
1660+ ( 0 , _, Some ( "'_" ) ) => {
1661+ suggest_new ( err, "'a" ) ;
1662+ }
1663+ ( 0 , _, Some ( snippet) ) if !snippet. ends_with ( ">" ) => {
1664+ suggest_new ( err, & format ! ( "{}<'a>" , snippet) ) ;
1665+ }
1666+ _ => {
1667+ err. span_label ( span, "expected lifetime parameter" ) ;
1668+ }
15531669 }
15541670 }
15551671 }
0 commit comments