@@ -10,6 +10,7 @@ use hir::HirVec;
1010use  lint; 
1111use  middle:: resolve_lifetime as  rl; 
1212use  namespace:: Namespace ; 
13+ use  rustc:: lint:: builtin:: AMBIGUOUS_ASSOCIATED_ITEMS ; 
1314use  rustc:: traits; 
1415use  rustc:: ty:: { self ,  Ty ,  TyCtxt ,  ToPredicate ,  TypeFoldable } ; 
1516use  rustc:: ty:: { GenericParamDef ,  GenericParamDefKind } ; 
@@ -1278,29 +1279,50 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
12781279    } 
12791280
12801281    // Create a type from a path to an associated type. 
1281-     // For a path `A::B::C::D`, `ty ` and `ty_path_def ` are the type and def for `A::B::C` 
1282+     // For a path `A::B::C::D`, `qself_ty ` and `qself_def ` are the type and def for `A::B::C` 
12821283    // and item_segment is the path segment for `D`. We return a type and a def for 
12831284    // the whole path. 
1284-     // Will fail except for `T::A` and `Self::A`; i.e., if `ty `/`ty_path_def ` are not a type 
1285+     // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty `/`qself_def ` are not a type 
12851286    // parameter or `Self`. 
1286-     pub  fn  associated_path_def_to_ty ( & self , 
1287-                                      ref_id :  ast:: NodeId , 
1288-                                      span :  Span , 
1289-                                      ty :  Ty < ' tcx > , 
1290-                                      ty_path_def :  Def , 
1291-                                      item_segment :  & hir:: PathSegment ) 
1292-                                      -> ( Ty < ' tcx > ,  Def ) 
1293-     { 
1287+     pub  fn  associated_path_to_ty ( 
1288+         & self , 
1289+         ref_id :  ast:: NodeId , 
1290+         span :  Span , 
1291+         qself_ty :  Ty < ' tcx > , 
1292+         qself_def :  Def , 
1293+         assoc_segment :  & hir:: PathSegment , 
1294+         permit_variants :  bool , 
1295+     )  -> ( Ty < ' tcx > ,  Def )  { 
12941296        let  tcx = self . tcx ( ) ; 
1295-         let  assoc_name  = item_segment . ident ; 
1297+         let  assoc_ident  = assoc_segment . ident ; 
12961298
1297-         debug ! ( "associated_path_def_to_ty : {:?}::{}" ,  ty ,  assoc_name ) ; 
1299+         debug ! ( "associated_path_to_ty : {:?}::{}" ,  qself_ty ,  assoc_ident ) ; 
12981300
1299-         self . prohibit_generics ( slice:: from_ref ( item_segment) ) ; 
1301+         self . prohibit_generics ( slice:: from_ref ( assoc_segment) ) ; 
1302+ 
1303+         // Check if we have an enum variant. 
1304+         let  mut  variant_resolution = None ; 
1305+         if  let  ty:: Adt ( adt_def,  _)  = qself_ty. sty  { 
1306+             if  adt_def. is_enum ( )  { 
1307+                 let  variant_def = adt_def. variants . iter ( ) . find ( |vd| { 
1308+                     tcx. hygienic_eq ( assoc_ident,  vd. ident ,  adt_def. did ) 
1309+                 } ) ; 
1310+                 if  let  Some ( variant_def)  = variant_def { 
1311+                     let  def = Def :: Variant ( variant_def. did ) ; 
1312+                     if  permit_variants { 
1313+                         check_type_alias_enum_variants_enabled ( tcx,  span) ; 
1314+                         tcx. check_stability ( variant_def. did ,  Some ( ref_id) ,  span) ; 
1315+                         return  ( qself_ty,  def) ; 
1316+                     }  else  { 
1317+                         variant_resolution = Some ( def) ; 
1318+                     } 
1319+                 } 
1320+             } 
1321+         } 
13001322
13011323        // Find the type of the associated item, and the trait where the associated 
13021324        // item is declared. 
1303-         let  bound = match  ( & ty . sty ,  ty_path_def )  { 
1325+         let  bound = match  ( & qself_ty . sty ,  qself_def )  { 
13041326            ( _,  Def :: SelfTy ( Some ( _) ,  Some ( impl_def_id) ) )  => { 
13051327                // `Self` in an impl of a trait -- we have a concrete self type and a 
13061328                // trait reference. 
@@ -1313,77 +1335,61 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
13131335                } ; 
13141336
13151337                let  candidates = traits:: supertraits ( tcx,  ty:: Binder :: bind ( trait_ref) ) 
1316-                     . filter ( |r| self . trait_defines_associated_type_named ( r. def_id ( ) ,  assoc_name ) ) ; 
1338+                     . filter ( |r| self . trait_defines_associated_type_named ( r. def_id ( ) ,  assoc_ident ) ) ; 
13171339
1318-                 match  self . one_bound_for_assoc_type ( candidates,  "Self" ,  assoc_name ,  span)  { 
1340+                 match  self . one_bound_for_assoc_type ( candidates,  "Self" ,  assoc_ident ,  span)  { 
13191341                    Ok ( bound)  => bound, 
13201342                    Err ( ErrorReported )  => return  ( tcx. types . err ,  Def :: Err ) , 
13211343                } 
13221344            } 
13231345            ( & ty:: Param ( _) ,  Def :: SelfTy ( Some ( param_did) ,  None ) )  |
13241346            ( & ty:: Param ( _) ,  Def :: TyParam ( param_did) )  => { 
1325-                 match  self . find_bound_for_assoc_item ( param_did,  assoc_name ,  span)  { 
1347+                 match  self . find_bound_for_assoc_item ( param_did,  assoc_ident ,  span)  { 
13261348                    Ok ( bound)  => bound, 
13271349                    Err ( ErrorReported )  => return  ( tcx. types . err ,  Def :: Err ) , 
13281350                } 
13291351            } 
1330-             ( & ty:: Adt ( adt_def,  _substs) ,  Def :: Enum ( _did) )  => { 
1331-                 let  ty_str = ty. to_string ( ) ; 
1332-                 // Incorrect enum variant. 
1333-                 let  mut  err = tcx. sess . struct_span_err ( 
1334-                     span, 
1335-                     & format ! ( "no variant `{}` on enum `{}`" ,  & assoc_name. as_str( ) ,  ty_str) , 
1336-                 ) ; 
1337-                 // Check if it was a typo. 
1338-                 let  input = adt_def. variants . iter ( ) . map ( |variant| & variant. ident . name ) ; 
1339-                 if  let  Some ( suggested_name)  = find_best_match_for_name ( 
1340-                     input, 
1341-                     & assoc_name. as_str ( ) , 
1342-                     None , 
1343-                 )  { 
1344-                     err. span_suggestion_with_applicability ( 
1352+             _ => { 
1353+                 if  variant_resolution. is_some ( )  { 
1354+                     // Variant in type position 
1355+                     let  msg = format ! ( "expected type, found variant `{}`" ,  assoc_ident) ; 
1356+                     tcx. sess . span_err ( span,  & msg) ; 
1357+                 }  else  if  qself_ty. is_enum ( )  { 
1358+                     // Report as incorrect enum variant rather than ambiguous type. 
1359+                     let  mut  err = tcx. sess . struct_span_err ( 
13451360                        span, 
1346-                         "did you mean" , 
1347-                         format ! ( "{}::{}" ,  ty_str,  suggested_name. to_string( ) ) , 
1348-                         Applicability :: MaybeIncorrect , 
1361+                         & format ! ( "no variant `{}` on enum `{}`" ,  & assoc_ident. as_str( ) ,  qself_ty) , 
13491362                    ) ; 
1350-                 }  else  { 
1351-                     err. span_label ( span,  "unknown variant" ) ; 
1352-                 } 
1353-                 err. emit ( ) ; 
1354-                 return  ( tcx. types . err ,  Def :: Err ) ; 
1355-             } 
1356-             _ => { 
1357-                 // Check if we have an enum variant. 
1358-                 match  ty. sty  { 
1359-                     ty:: Adt ( adt_def,  _)  if  adt_def. is_enum ( )  => { 
1360-                         let  variant_def = adt_def. variants . iter ( ) . find ( |vd| { 
1361-                             tcx. hygienic_eq ( assoc_name,  vd. ident ,  adt_def. did ) 
1362-                         } ) ; 
1363-                         if  let  Some ( variant_def)  = variant_def { 
1364-                             check_type_alias_enum_variants_enabled ( tcx,  span) ; 
1365- 
1366-                             let  def = Def :: Variant ( variant_def. did ) ; 
1367-                             tcx. check_stability ( def. def_id ( ) ,  Some ( ref_id) ,  span) ; 
1368-                             return  ( ty,  def) ; 
1369-                         } 
1370-                     } , 
1371-                     _ => ( ) , 
1372-                 } 
1373- 
1374-                 // Don't print `TyErr` to the user. 
1375-                 if  !ty. references_error ( )  { 
1363+                     // Check if it was a typo. 
1364+                     let  adt_def = qself_ty. ty_adt_def ( ) . expect ( "enum is not an ADT" ) ; 
1365+                     if  let  Some ( suggested_name)  = find_best_match_for_name ( 
1366+                         adt_def. variants . iter ( ) . map ( |variant| & variant. ident . name ) , 
1367+                         & assoc_ident. as_str ( ) , 
1368+                         None , 
1369+                     )  { 
1370+                         err. span_suggestion_with_applicability ( 
1371+                             span, 
1372+                             "did you mean" , 
1373+                             format ! ( "{}::{}" ,  qself_ty,  suggested_name) , 
1374+                             Applicability :: MaybeIncorrect , 
1375+                         ) ; 
1376+                     }  else  { 
1377+                         err. span_label ( span,  "unknown variant" ) ; 
1378+                     } 
1379+                     err. emit ( ) ; 
1380+                 }  else  if  !qself_ty. references_error ( )  { 
1381+                     // Don't print `TyErr` to the user. 
13761382                    self . report_ambiguous_associated_type ( span, 
1377-                                                           & ty . to_string ( ) , 
1383+                                                           & qself_ty . to_string ( ) , 
13781384                                                          "Trait" , 
1379-                                                           & assoc_name . as_str ( ) ) ; 
1385+                                                           & assoc_ident . as_str ( ) ) ; 
13801386                } 
13811387                return  ( tcx. types . err ,  Def :: Err ) ; 
13821388            } 
13831389        } ; 
13841390
13851391        let  trait_did = bound. def_id ( ) ; 
1386-         let  ( assoc_ident,  def_scope)  = tcx. adjust_ident ( assoc_name ,  trait_did,  ref_id) ; 
1392+         let  ( assoc_ident,  def_scope)  = tcx. adjust_ident ( assoc_ident ,  trait_did,  ref_id) ; 
13871393        let  item = tcx. associated_items ( trait_did) . find ( |i| { 
13881394            Namespace :: from ( i. kind )  == Namespace :: Type  &&
13891395                i. ident . modern ( )  == assoc_ident
@@ -1394,11 +1400,35 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
13941400
13951401        let  def = Def :: AssociatedTy ( item. def_id ) ; 
13961402        if  !item. vis . is_accessible_from ( def_scope,  tcx)  { 
1397-             let  msg = format ! ( "{} `{}` is private" ,  def. kind_name( ) ,  assoc_name ) ; 
1403+             let  msg = format ! ( "{} `{}` is private" ,  def. kind_name( ) ,  assoc_ident ) ; 
13981404            tcx. sess . span_err ( span,  & msg) ; 
13991405        } 
14001406        tcx. check_stability ( item. def_id ,  Some ( ref_id) ,  span) ; 
14011407
1408+         if  let  Some ( variant_def)  = variant_resolution { 
1409+             let  mut  err = tcx. struct_span_lint_node ( 
1410+                 AMBIGUOUS_ASSOCIATED_ITEMS , 
1411+                 ref_id, 
1412+                 span, 
1413+                 "ambiguous associated item" , 
1414+             ) ; 
1415+ 
1416+             let  mut  could_refer_to = |def :  Def ,  also| { 
1417+                 let  note_msg = format ! ( "`{}` could{} refer to {} defined here" , 
1418+                                        assoc_ident,  also,  def. kind_name( ) ) ; 
1419+                 err. span_note ( tcx. def_span ( def. def_id ( ) ) ,  & note_msg) ; 
1420+             } ; 
1421+             could_refer_to ( variant_def,  "" ) ; 
1422+             could_refer_to ( def,  " also" ) ; 
1423+ 
1424+             err. span_suggestion_with_applicability ( 
1425+                 span, 
1426+                 "use fully-qualified syntax" , 
1427+                 format ! ( "<{} as {}>::{}" ,  qself_ty,  "Trait" ,  assoc_ident) , 
1428+                 Applicability :: HasPlaceholders , 
1429+             ) . emit ( ) ; 
1430+         } 
1431+ 
14021432        ( ty,  def) 
14031433    } 
14041434
@@ -1773,7 +1803,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
17731803                }  else  { 
17741804                    Def :: Err 
17751805                } ; 
1776-                 self . associated_path_def_to_ty ( ast_ty. id ,  ast_ty. span ,  ty,  def,  segment) . 0 
1806+                 self . associated_path_to_ty ( ast_ty. id ,  ast_ty. span ,  ty,  def,  segment,   false ) . 0 
17771807            } 
17781808            hir:: TyKind :: Array ( ref  ty,  ref  length)  => { 
17791809                let  length_def_id = tcx. hir ( ) . local_def_id ( length. id ) ; 
0 commit comments