@@ -28,7 +28,8 @@ use hir_def::{
2828 path:: { path, Path } ,
2929 resolver:: { HasResolver , Resolver , TypeNs } ,
3030 type_ref:: { Mutability , TypeRef } ,
31- AdtId , AssocItemId , DefWithBodyId , FieldId , FunctionId , TraitId , TypeAliasId , VariantId ,
31+ AdtId , AssocItemId , DefWithBodyId , EnumVariantId , FieldId , FunctionId , TraitId , TypeAliasId ,
32+ VariantId ,
3233} ;
3334use hir_expand:: { diagnostics:: DiagnosticSink , name:: name} ;
3435use ra_arena:: map:: ArenaMap ;
@@ -438,43 +439,95 @@ impl<'a> InferenceContext<'a> {
438439 let ctx = crate :: lower:: TyLoweringContext :: new ( self . db , & self . resolver ) ;
439440 // FIXME: this should resolve assoc items as well, see this example:
440441 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
441- return match resolver. resolve_path_in_type_ns_fully ( self . db . upcast ( ) , path. mod_path ( ) ) {
442- Some ( TypeNs :: AdtId ( AdtId :: StructId ( strukt) ) ) => {
442+ let ( resolution, unresolved) =
443+ match resolver. resolve_path_in_type_ns ( self . db . upcast ( ) , path. mod_path ( ) ) {
444+ Some ( it) => it,
445+ None => return ( Ty :: Unknown , None ) ,
446+ } ;
447+ return match resolution {
448+ TypeNs :: AdtId ( AdtId :: StructId ( strukt) ) => {
443449 let substs = Ty :: substs_from_path ( & ctx, path, strukt. into ( ) ) ;
444450 let ty = self . db . ty ( strukt. into ( ) ) ;
445451 let ty = self . insert_type_vars ( ty. subst ( & substs) ) ;
446- ( ty, Some ( strukt. into ( ) ) )
452+ forbid_unresolved_segments ( ( ty, Some ( strukt. into ( ) ) ) , unresolved )
447453 }
448- Some ( TypeNs :: EnumVariantId ( var) ) => {
454+ TypeNs :: EnumVariantId ( var) => {
449455 let substs = Ty :: substs_from_path ( & ctx, path, var. into ( ) ) ;
450456 let ty = self . db . ty ( var. parent . into ( ) ) ;
451457 let ty = self . insert_type_vars ( ty. subst ( & substs) ) ;
452- ( ty, Some ( var. into ( ) ) )
458+ forbid_unresolved_segments ( ( ty, Some ( var. into ( ) ) ) , unresolved )
453459 }
454- Some ( TypeNs :: SelfType ( impl_id) ) => {
460+ TypeNs :: SelfType ( impl_id) => {
455461 let generics = crate :: utils:: generics ( self . db . upcast ( ) , impl_id. into ( ) ) ;
456462 let substs = Substs :: type_params_for_generics ( & generics) ;
457463 let ty = self . db . impl_self_ty ( impl_id) . subst ( & substs) ;
458- let variant = ty_variant ( & ty) ;
459- ( ty, variant)
464+ match unresolved {
465+ None => {
466+ let variant = ty_variant ( & ty) ;
467+ ( ty, variant)
468+ }
469+ Some ( 1 ) => {
470+ let segment = path. mod_path ( ) . segments . last ( ) . unwrap ( ) ;
471+ // this could be an enum variant or associated type
472+ if let Some ( ( AdtId :: EnumId ( enum_id) , _) ) = ty. as_adt ( ) {
473+ let enum_data = self . db . enum_data ( enum_id) ;
474+ if let Some ( local_id) = enum_data. variant ( segment) {
475+ let variant = EnumVariantId { parent : enum_id, local_id } ;
476+ return ( ty, Some ( variant. into ( ) ) ) ;
477+ }
478+ }
479+ // FIXME potentially resolve assoc type
480+ ( Ty :: Unknown , None )
481+ }
482+ Some ( _) => {
483+ // FIXME diagnostic
484+ ( Ty :: Unknown , None )
485+ }
486+ }
460487 }
461- Some ( TypeNs :: TypeAliasId ( it) ) => {
488+ TypeNs :: TypeAliasId ( it) => {
462489 let substs = Substs :: build_for_def ( self . db , it)
463490 . fill ( std:: iter:: repeat_with ( || self . table . new_type_var ( ) ) )
464491 . build ( ) ;
465492 let ty = self . db . ty ( it. into ( ) ) . subst ( & substs) ;
466493 let variant = ty_variant ( & ty) ;
467- ( ty, variant)
494+ forbid_unresolved_segments ( ( ty, variant) , unresolved)
495+ }
496+ TypeNs :: AdtSelfType ( _) => {
497+ // FIXME this could happen in array size expressions, once we're checking them
498+ ( Ty :: Unknown , None )
499+ }
500+ TypeNs :: GenericParam ( _) => {
501+ // FIXME potentially resolve assoc type
502+ ( Ty :: Unknown , None )
503+ }
504+ TypeNs :: AdtId ( AdtId :: EnumId ( _) )
505+ | TypeNs :: AdtId ( AdtId :: UnionId ( _) )
506+ | TypeNs :: BuiltinType ( _)
507+ | TypeNs :: TraitId ( _) => {
508+ // FIXME diagnostic
509+ ( Ty :: Unknown , None )
468510 }
469- Some ( _) | None => ( Ty :: Unknown , None ) ,
470511 } ;
471512
513+ fn forbid_unresolved_segments (
514+ result : ( Ty , Option < VariantId > ) ,
515+ unresolved : Option < usize > ,
516+ ) -> ( Ty , Option < VariantId > ) {
517+ if unresolved. is_none ( ) {
518+ result
519+ } else {
520+ // FIXME diagnostic
521+ ( Ty :: Unknown , None )
522+ }
523+ }
524+
472525 fn ty_variant ( ty : & Ty ) -> Option < VariantId > {
473526 ty. as_adt ( ) . and_then ( |( adt_id, _) | match adt_id {
474527 AdtId :: StructId ( s) => Some ( VariantId :: StructId ( s) ) ,
475528 AdtId :: UnionId ( u) => Some ( VariantId :: UnionId ( u) ) ,
476529 AdtId :: EnumId ( _) => {
477- // Error E0071, expected struct, variant or union type, found enum `Foo`
530+ // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
478531 None
479532 }
480533 } )
0 commit comments