1616use std:: sync:: Arc ;
1717use std:: { convert:: identity, ops:: Index } ;
1818
19- use chalk_ir:: { cast:: Cast , ConstValue , DebruijnIndex , Mutability , Safety , Scalar , TypeFlags } ;
19+ use chalk_ir:: { cast:: Cast , DebruijnIndex , Mutability , Safety , Scalar , TypeFlags } ;
2020use either:: Either ;
2121use hir_def:: {
2222 body:: Body ,
@@ -37,10 +37,10 @@ use rustc_hash::{FxHashMap, FxHashSet};
3737use stdx:: { always, never} ;
3838
3939use crate :: {
40- db:: HirDatabase , fold_tys, fold_tys_and_consts , infer:: coerce:: CoerceMany ,
41- lower :: ImplTraitLoweringMode , static_lifetime, to_assoc_type_id, AliasEq , AliasTy , Const ,
42- DomainGoal , GenericArg , Goal , ImplTraitId , InEnvironment , Interner , ProjectionTy , RpitId ,
43- Substitution , TraitRef , Ty , TyBuilder , TyExt , TyKind ,
40+ db:: HirDatabase , fold_tys, infer:: coerce:: CoerceMany , lower :: ImplTraitLoweringMode ,
41+ static_lifetime, to_assoc_type_id, AliasEq , AliasTy , DomainGoal , GenericArg , Goal , ImplTraitId ,
42+ InEnvironment , Interner , ProjectionTy , RpitId , Substitution , TraitRef , Ty , TyBuilder , TyExt ,
43+ TyKind ,
4444} ;
4545
4646// This lint has a false positive here. See the link below for details.
@@ -744,43 +744,13 @@ impl<'a> InferenceContext<'a> {
744744 self . result . standard_types . unknown . clone ( )
745745 }
746746
747- /// Replaces ConstScalar::Unknown by a new type var, so we can maybe still infer it.
748- fn insert_const_vars_shallow ( & mut self , c : Const ) -> Const {
749- let data = c. data ( Interner ) ;
750- match & data. value {
751- ConstValue :: Concrete ( cc) => match cc. interned {
752- crate :: ConstScalar :: Unknown => self . table . new_const_var ( data. ty . clone ( ) ) ,
753- _ => c,
754- } ,
755- _ => c,
756- }
757- }
758-
759747 /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
760748 fn insert_type_vars_shallow ( & mut self , ty : Ty ) -> Ty {
761- match ty. kind ( Interner ) {
762- TyKind :: Error => self . table . new_type_var ( ) ,
763- TyKind :: InferenceVar ( ..) => {
764- let ty_resolved = self . resolve_ty_shallow ( & ty) ;
765- if ty_resolved. is_unknown ( ) {
766- self . table . new_type_var ( )
767- } else {
768- ty
769- }
770- }
771- _ => ty,
772- }
749+ self . table . insert_type_vars_shallow ( ty)
773750 }
774751
775752 fn insert_type_vars ( & mut self , ty : Ty ) -> Ty {
776- fold_tys_and_consts (
777- ty,
778- |x, _| match x {
779- Either :: Left ( ty) => Either :: Left ( self . insert_type_vars_shallow ( ty) ) ,
780- Either :: Right ( c) => Either :: Right ( self . insert_const_vars_shallow ( c) ) ,
781- } ,
782- DebruijnIndex :: INNERMOST ,
783- )
753+ self . table . insert_type_vars ( ty)
784754 }
785755
786756 fn push_obligation ( & mut self , o : DomainGoal ) {
@@ -909,8 +879,6 @@ impl<'a> InferenceContext<'a> {
909879 None => return ( self . err_ty ( ) , None ) ,
910880 } ;
911881 let ctx = crate :: lower:: TyLoweringContext :: new ( self . db , & self . resolver ) ;
912- // FIXME: this should resolve assoc items as well, see this example:
913- // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
914882 let ( resolution, unresolved) = if value_ns {
915883 match self . resolver . resolve_path_in_value_ns ( self . db . upcast ( ) , path) {
916884 Some ( ResolveValueResult :: ValueNs ( value) ) => match value {
@@ -964,8 +932,68 @@ impl<'a> InferenceContext<'a> {
964932 TypeNs :: SelfType ( impl_id) => {
965933 let generics = crate :: utils:: generics ( self . db . upcast ( ) , impl_id. into ( ) ) ;
966934 let substs = generics. placeholder_subst ( self . db ) ;
967- let ty = self . db . impl_self_ty ( impl_id) . substitute ( Interner , & substs) ;
968- self . resolve_variant_on_alias ( ty, unresolved, mod_path)
935+ let mut ty = self . db . impl_self_ty ( impl_id) . substitute ( Interner , & substs) ;
936+
937+ let Some ( mut remaining_idx) = unresolved else {
938+ return self . resolve_variant_on_alias ( ty, None , mod_path) ;
939+ } ;
940+
941+ let mut remaining_segments = path. segments ( ) . skip ( remaining_idx) ;
942+
943+ // We need to try resolving unresolved segments one by one because each may resolve
944+ // to a projection, which `TyLoweringContext` cannot handle on its own.
945+ while !remaining_segments. is_empty ( ) {
946+ let resolved_segment = path. segments ( ) . get ( remaining_idx - 1 ) . unwrap ( ) ;
947+ let current_segment = remaining_segments. take ( 1 ) ;
948+
949+ // If we can resolve to an enum variant, it takes priority over associated type
950+ // of the same name.
951+ if let Some ( ( AdtId :: EnumId ( id) , _) ) = ty. as_adt ( ) {
952+ let enum_data = self . db . enum_data ( id) ;
953+ let name = current_segment. first ( ) . unwrap ( ) . name ;
954+ if let Some ( local_id) = enum_data. variant ( name) {
955+ let variant = EnumVariantId { parent : id, local_id } ;
956+ return if remaining_segments. len ( ) == 1 {
957+ ( ty, Some ( variant. into ( ) ) )
958+ } else {
959+ // We still have unresolved paths, but enum variants never have
960+ // associated types!
961+ ( self . err_ty ( ) , None )
962+ } ;
963+ }
964+ }
965+
966+ // `lower_partly_resolved_path()` returns `None` as type namespace unless
967+ // `remaining_segments` is empty, which is never the case here. We don't know
968+ // which namespace the new `ty` is in until normalized anyway.
969+ ( ty, _) = ctx. lower_partly_resolved_path (
970+ resolution,
971+ resolved_segment,
972+ current_segment,
973+ false ,
974+ ) ;
975+
976+ ty = self . table . insert_type_vars ( ty) ;
977+ ty = self . table . normalize_associated_types_in ( ty) ;
978+ ty = self . table . resolve_ty_shallow ( & ty) ;
979+ if ty. is_unknown ( ) {
980+ return ( self . err_ty ( ) , None ) ;
981+ }
982+
983+ // FIXME(inherent_associated_types): update `resolution` based on `ty` here.
984+ remaining_idx += 1 ;
985+ remaining_segments = remaining_segments. skip ( 1 ) ;
986+ }
987+
988+ let variant = ty. as_adt ( ) . and_then ( |( id, _) | match id {
989+ AdtId :: StructId ( s) => Some ( VariantId :: StructId ( s) ) ,
990+ AdtId :: UnionId ( u) => Some ( VariantId :: UnionId ( u) ) ,
991+ AdtId :: EnumId ( _) => {
992+ // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
993+ None
994+ }
995+ } ) ;
996+ ( ty, variant)
969997 }
970998 TypeNs :: TypeAliasId ( it) => {
971999 let container = it. lookup ( self . db . upcast ( ) ) . container ;
0 commit comments