@@ -8,6 +8,7 @@ use rustc_ast_pretty::pprust;
88use rustc_data_structures:: fx:: FxHashSet ;
99use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticBuilder } ;
1010use rustc_feature:: BUILTIN_ATTRIBUTES ;
11+ use rustc_hir as hir;
1112use rustc_hir:: def:: Namespace :: { self , * } ;
1213use rustc_hir:: def:: { self , CtorKind , CtorOf , DefKind , NonMacroAttrKind } ;
1314use rustc_hir:: def_id:: { DefId , CRATE_DEF_INDEX , LOCAL_CRATE } ;
@@ -19,7 +20,7 @@ use syntax::ast::{self, Ident, Path};
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"`).
@@ -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