@@ -29,8 +29,9 @@ use rustc_span::Span;
29
29
use smallvec:: { smallvec, SmallVec } ;
30
30
31
31
use log:: debug;
32
+ use rustc_span:: source_map:: { respan, Spanned } ;
32
33
use std:: collections:: BTreeSet ;
33
- use std:: mem:: replace;
34
+ use std:: mem:: { replace, take } ;
34
35
35
36
mod diagnostics;
36
37
crate mod lifetimes;
@@ -234,6 +235,13 @@ impl<'a> PathSource<'a> {
234
235
}
235
236
}
236
237
238
+ fn is_call ( self ) -> bool {
239
+ match self {
240
+ PathSource :: Expr ( Some ( & Expr { kind : ExprKind :: Call ( ..) , .. } ) ) => true ,
241
+ _ => false ,
242
+ }
243
+ }
244
+
237
245
crate fn is_expected ( self , res : Res ) -> bool {
238
246
match self {
239
247
PathSource :: Type => match res {
@@ -1620,14 +1628,83 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1620
1628
1621
1629
let report_errors = |this : & mut Self , res : Option < Res > | {
1622
1630
let ( err, candidates) = this. smart_resolve_report_errors ( path, span, source, res) ;
1631
+
1623
1632
let def_id = this. parent_scope . module . normal_ancestor_id ;
1624
- let better = res. is_some ( ) ;
1633
+ let instead = res. is_some ( ) ;
1625
1634
let suggestion =
1626
1635
if res. is_none ( ) { this. report_missing_type_error ( path) } else { None } ;
1627
- this. r . use_injections . push ( UseError { err, candidates, def_id, better, suggestion } ) ;
1636
+
1637
+ this. r . use_injections . push ( UseError { err, candidates, def_id, instead, suggestion } ) ;
1638
+
1628
1639
PartialRes :: new ( Res :: Err )
1629
1640
} ;
1630
1641
1642
+ // For paths originating from calls (like in `HashMap::new()`), tries
1643
+ // to enrich the plain `failed to resolve: ...` message with hints
1644
+ // about possible missing imports.
1645
+ //
1646
+ // Similar thing, for types, happens in `report_errors` above.
1647
+ let report_errors_for_call = |this : & mut Self , parent_err : Spanned < ResolutionError < ' a > > | {
1648
+ if !source. is_call ( ) {
1649
+ return Some ( parent_err) ;
1650
+ }
1651
+
1652
+ // Before we start looking for candidates, we have to get our hands
1653
+ // on the type user is trying to perform invocation on; basically:
1654
+ // we're transforming `HashMap::new` into just `HashMap`
1655
+ let path = if let Some ( ( _, path) ) = path. split_last ( ) {
1656
+ path
1657
+ } else {
1658
+ return Some ( parent_err) ;
1659
+ } ;
1660
+
1661
+ let ( mut err, candidates) =
1662
+ this. smart_resolve_report_errors ( path, span, PathSource :: Type , None ) ;
1663
+
1664
+ if candidates. is_empty ( ) {
1665
+ err. cancel ( ) ;
1666
+ return Some ( parent_err) ;
1667
+ }
1668
+
1669
+ // There are two different error messages user might receive at
1670
+ // this point:
1671
+ // - E0412 cannot find type `{}` in this scope
1672
+ // - E0433 failed to resolve: use of undeclared type or module `{}`
1673
+ //
1674
+ // The first one is emitted for paths in type-position, and the
1675
+ // latter one - for paths in expression-position.
1676
+ //
1677
+ // Thus (since we're in expression-position at this point), not to
1678
+ // confuse the user, we want to keep the *message* from E0432 (so
1679
+ // `parent_err`), but we want *hints* from E0412 (so `err`).
1680
+ //
1681
+ // And that's what happens below - we're just mixing both messages
1682
+ // into a single one.
1683
+ let mut parent_err = this. r . into_struct_error ( parent_err. span , parent_err. node ) ;
1684
+
1685
+ parent_err. cancel ( ) ;
1686
+
1687
+ err. message = take ( & mut parent_err. message ) ;
1688
+ err. code = take ( & mut parent_err. code ) ;
1689
+ err. children = take ( & mut parent_err. children ) ;
1690
+
1691
+ drop ( parent_err) ;
1692
+
1693
+ let def_id = this. parent_scope . module . normal_ancestor_id ;
1694
+
1695
+ this. r . use_injections . push ( UseError {
1696
+ err,
1697
+ candidates,
1698
+ def_id,
1699
+ instead : false ,
1700
+ suggestion : None ,
1701
+ } ) ;
1702
+
1703
+ // We don't return `Some(parent_err)` here, because the error will
1704
+ // be already printed as part of the `use` injections
1705
+ None
1706
+ } ;
1707
+
1631
1708
let partial_res = match self . resolve_qpath_anywhere (
1632
1709
id,
1633
1710
qself,
@@ -1637,14 +1714,15 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1637
1714
source. defer_to_typeck ( ) ,
1638
1715
crate_lint,
1639
1716
) {
1640
- Some ( partial_res) if partial_res. unresolved_segments ( ) == 0 => {
1717
+ Ok ( Some ( partial_res) ) if partial_res. unresolved_segments ( ) == 0 => {
1641
1718
if is_expected ( partial_res. base_res ( ) ) || partial_res. base_res ( ) == Res :: Err {
1642
1719
partial_res
1643
1720
} else {
1644
1721
report_errors ( self , Some ( partial_res. base_res ( ) ) )
1645
1722
}
1646
1723
}
1647
- Some ( partial_res) if source. defer_to_typeck ( ) => {
1724
+
1725
+ Ok ( Some ( partial_res) ) if source. defer_to_typeck ( ) => {
1648
1726
// Not fully resolved associated item `T::A::B` or `<T as Tr>::A::B`
1649
1727
// or `<T>::A::B`. If `B` should be resolved in value namespace then
1650
1728
// it needs to be added to the trait map.
@@ -1655,25 +1733,34 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1655
1733
}
1656
1734
1657
1735
let mut std_path = vec ! [ Segment :: from_ident( Ident :: with_dummy_span( sym:: std) ) ] ;
1736
+
1658
1737
std_path. extend ( path) ;
1738
+
1659
1739
if self . r . primitive_type_table . primitive_types . contains_key ( & path[ 0 ] . ident . name ) {
1660
- let cl = CrateLint :: No ;
1661
- let ns = Some ( ns) ;
1662
1740
if let PathResult :: Module ( _) | PathResult :: NonModule ( _) =
1663
- self . resolve_path ( & std_path, ns , false , span, cl )
1741
+ self . resolve_path ( & std_path, Some ( ns ) , false , span, CrateLint :: No )
1664
1742
{
1665
- // check if we wrote `str::from_utf8` instead of `std::str::from_utf8`
1743
+ // Check if we wrote `str::from_utf8` instead of `std::str::from_utf8`
1666
1744
let item_span =
1667
1745
path. iter ( ) . last ( ) . map ( |segment| segment. ident . span ) . unwrap_or ( span) ;
1668
- debug ! ( "accessed item from `std` submodule as a bare type {:?}" , std_path ) ;
1746
+
1669
1747
let mut hm = self . r . session . confused_type_with_std_module . borrow_mut ( ) ;
1670
1748
hm. insert ( item_span, span) ;
1671
- // In some places (E0223) we only have access to the full path
1672
1749
hm. insert ( span, span) ;
1673
1750
}
1674
1751
}
1752
+
1675
1753
partial_res
1676
1754
}
1755
+
1756
+ Err ( err) => {
1757
+ if let Some ( err) = report_errors_for_call ( self , err) {
1758
+ self . r . report_error ( err. span , err. node ) ;
1759
+ }
1760
+
1761
+ PartialRes :: new ( Res :: Err )
1762
+ }
1763
+
1677
1764
_ => report_errors ( self , None ) ,
1678
1765
} ;
1679
1766
@@ -1682,6 +1769,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1682
1769
// Avoid recording definition of `A::B` in `<T as A>::B::C`.
1683
1770
self . r . record_partial_res ( id, partial_res) ;
1684
1771
}
1772
+
1685
1773
partial_res
1686
1774
}
1687
1775
@@ -1711,17 +1799,16 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1711
1799
span : Span ,
1712
1800
defer_to_typeck : bool ,
1713
1801
crate_lint : CrateLint ,
1714
- ) -> Option < PartialRes > {
1802
+ ) -> Result < Option < PartialRes > , Spanned < ResolutionError < ' a > > > {
1715
1803
let mut fin_res = None ;
1804
+
1716
1805
for ( i, ns) in [ primary_ns, TypeNS , ValueNS ] . iter ( ) . cloned ( ) . enumerate ( ) {
1717
1806
if i == 0 || ns != primary_ns {
1718
- match self . resolve_qpath ( id, qself, path, ns, span, crate_lint) {
1719
- // If defer_to_typeck, then resolution > no resolution,
1720
- // otherwise full resolution > partial resolution > no resolution.
1807
+ match self . resolve_qpath ( id, qself, path, ns, span, crate_lint) ? {
1721
1808
Some ( partial_res)
1722
1809
if partial_res. unresolved_segments ( ) == 0 || defer_to_typeck =>
1723
1810
{
1724
- return Some ( partial_res) ;
1811
+ return Ok ( Some ( partial_res) ) ;
1725
1812
}
1726
1813
partial_res => {
1727
1814
if fin_res. is_none ( ) {
@@ -1732,19 +1819,19 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1732
1819
}
1733
1820
}
1734
1821
1735
- // `MacroNS`
1736
1822
assert ! ( primary_ns != MacroNS ) ;
1823
+
1737
1824
if qself. is_none ( ) {
1738
1825
let path_seg = |seg : & Segment | PathSegment :: from_ident ( seg. ident ) ;
1739
1826
let path = Path { segments : path. iter ( ) . map ( path_seg) . collect ( ) , span } ;
1740
1827
if let Ok ( ( _, res) ) =
1741
1828
self . r . resolve_macro_path ( & path, None , & self . parent_scope , false , false )
1742
1829
{
1743
- return Some ( PartialRes :: new ( res) ) ;
1830
+ return Ok ( Some ( PartialRes :: new ( res) ) ) ;
1744
1831
}
1745
1832
}
1746
1833
1747
- fin_res
1834
+ Ok ( fin_res)
1748
1835
}
1749
1836
1750
1837
/// Handles paths that may refer to associated items.
@@ -1756,7 +1843,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1756
1843
ns : Namespace ,
1757
1844
span : Span ,
1758
1845
crate_lint : CrateLint ,
1759
- ) -> Option < PartialRes > {
1846
+ ) -> Result < Option < PartialRes > , Spanned < ResolutionError < ' a > > > {
1760
1847
debug ! (
1761
1848
"resolve_qpath(id={:?}, qself={:?}, path={:?}, ns={:?}, span={:?})" ,
1762
1849
id, qself, path, ns, span,
@@ -1767,10 +1854,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1767
1854
// This is a case like `<T>::B`, where there is no
1768
1855
// trait to resolve. In that case, we leave the `B`
1769
1856
// segment to be resolved by type-check.
1770
- return Some ( PartialRes :: with_unresolved_segments (
1857
+ return Ok ( Some ( PartialRes :: with_unresolved_segments (
1771
1858
Res :: Def ( DefKind :: Mod , DefId :: local ( CRATE_DEF_INDEX ) ) ,
1772
1859
path. len ( ) ,
1773
- ) ) ;
1860
+ ) ) ) ;
1774
1861
}
1775
1862
1776
1863
// Make sure `A::B` in `<T as A::B>::C` is a trait item.
@@ -1800,10 +1887,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1800
1887
// The remaining segments (the `C` in our example) will
1801
1888
// have to be resolved by type-check, since that requires doing
1802
1889
// trait resolution.
1803
- return Some ( PartialRes :: with_unresolved_segments (
1890
+ return Ok ( Some ( PartialRes :: with_unresolved_segments (
1804
1891
partial_res. base_res ( ) ,
1805
1892
partial_res. unresolved_segments ( ) + path. len ( ) - qself. position - 1 ,
1806
- ) ) ;
1893
+ ) ) ) ;
1807
1894
}
1808
1895
1809
1896
let result = match self . resolve_path ( & path, Some ( ns) , true , span, crate_lint) {
@@ -1838,11 +1925,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1838
1925
PartialRes :: new ( module. res ( ) . unwrap ( ) )
1839
1926
}
1840
1927
PathResult :: Failed { is_error_from_last_segment : false , span, label, suggestion } => {
1841
- self . r . report_error ( span, ResolutionError :: FailedToResolve { label, suggestion } ) ;
1842
- PartialRes :: new ( Res :: Err )
1928
+ return Err ( respan ( span, ResolutionError :: FailedToResolve { label, suggestion } ) ) ;
1843
1929
}
1844
- PathResult :: Module ( ..) | PathResult :: Failed { .. } => return None ,
1845
- PathResult :: Indeterminate => bug ! ( "indetermined path result in resolve_qpath" ) ,
1930
+ PathResult :: Module ( ..) | PathResult :: Failed { .. } => return Ok ( None ) ,
1931
+ PathResult :: Indeterminate => bug ! ( "indeterminate path result in resolve_qpath" ) ,
1846
1932
} ;
1847
1933
1848
1934
if path. len ( ) > 1
@@ -1862,7 +1948,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1862
1948
PathResult :: Module ( ModuleOrUniformRoot :: Module ( module) ) => {
1863
1949
module. res ( ) . unwrap ( )
1864
1950
}
1865
- _ => return Some ( result) ,
1951
+ _ => return Ok ( Some ( result) ) ,
1866
1952
}
1867
1953
} ;
1868
1954
if result. base_res ( ) == unqualified_result {
@@ -1871,7 +1957,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
1871
1957
}
1872
1958
}
1873
1959
1874
- Some ( result)
1960
+ Ok ( Some ( result) )
1875
1961
}
1876
1962
1877
1963
fn with_resolved_label ( & mut self , label : Option < Label > , id : NodeId , f : impl FnOnce ( & mut Self ) ) {
0 commit comments