@@ -8,6 +8,7 @@ use rustc_ast_pretty::pprust;
8
8
use rustc_data_structures:: fx:: FxHashSet ;
9
9
use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticBuilder } ;
10
10
use rustc_feature:: BUILTIN_ATTRIBUTES ;
11
+ use rustc_hir as hir;
11
12
use rustc_hir:: def:: Namespace :: { self , * } ;
12
13
use rustc_hir:: def:: { self , CtorKind , CtorOf , DefKind , NonMacroAttrKind } ;
13
14
use rustc_hir:: def_id:: { DefId , CRATE_DEF_INDEX , LOCAL_CRATE } ;
@@ -19,7 +20,7 @@ use syntax::ast::{self, Ident, Path};
19
20
use syntax:: util:: lev_distance:: find_best_match_for_name;
20
21
21
22
use crate :: imports:: { ImportDirective , ImportDirectiveSubclass , ImportResolver } ;
22
- use crate :: lifetimes:: { ElisionFailureInfo , MissingLifetimeSpot } ;
23
+ use crate :: lifetimes:: { ElisionFailureInfo , LifetimeContext } ;
23
24
use crate :: path_names_to_string;
24
25
use crate :: { AmbiguityError , AmbiguityErrorMisc , AmbiguityKind } ;
25
26
use crate :: { BindingError , CrateLint , HasGenericParams , LegacyScope , Module , ModuleOrUniformRoot } ;
@@ -48,6 +49,40 @@ crate struct ImportSuggestion {
48
49
pub path : Path ,
49
50
}
50
51
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
+
51
86
/// Adjust the impl span so that just the `impl` keyword is taken by removing
52
87
/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
53
88
/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
@@ -1457,104 +1492,185 @@ crate fn show_candidates(
1457
1492
}
1458
1493
}
1459
1494
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
+ }
1467
1509
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
+ }
1488
1571
} ;
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
+ }
1503
1610
}
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 \
1513
1619
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
+ }
1526
1634
}
1527
1635
}
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
+ }
1528
1645
}
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
+ } ;
1536
1647
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
+ }
1558
1674
}
1559
1675
}
1560
1676
}
0 commit comments