16
16
use std:: ops:: Index ;
17
17
use std:: sync:: Arc ;
18
18
19
- use chalk_ir:: { cast:: Cast , ConstValue , DebruijnIndex , Mutability , Safety , Scalar , TypeFlags } ;
19
+ use chalk_ir:: { cast:: Cast , DebruijnIndex , Mutability , Safety , Scalar , TypeFlags } ;
20
20
use either:: Either ;
21
21
use hir_def:: {
22
22
body:: Body ,
@@ -37,10 +37,10 @@ use rustc_hash::{FxHashMap, FxHashSet};
37
37
use stdx:: { always, never} ;
38
38
39
39
use 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 ,
44
44
} ;
45
45
46
46
// This lint has a false positive here. See the link below for details.
@@ -744,43 +744,13 @@ impl<'a> InferenceContext<'a> {
744
744
self . result . standard_types . unknown . clone ( )
745
745
}
746
746
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
-
759
747
/// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
760
748
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)
773
750
}
774
751
775
752
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)
784
754
}
785
755
786
756
fn push_obligation ( & mut self , o : DomainGoal ) {
@@ -850,8 +820,6 @@ impl<'a> InferenceContext<'a> {
850
820
None => return ( self . err_ty ( ) , None ) ,
851
821
} ;
852
822
let ctx = crate :: lower:: TyLoweringContext :: new ( self . db , & self . resolver ) ;
853
- // FIXME: this should resolve assoc items as well, see this example:
854
- // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
855
823
let ( resolution, unresolved) = if value_ns {
856
824
match self . resolver . resolve_path_in_value_ns ( self . db . upcast ( ) , path) {
857
825
Some ( ResolveValueResult :: ValueNs ( value) ) => match value {
@@ -905,8 +873,68 @@ impl<'a> InferenceContext<'a> {
905
873
TypeNs :: SelfType ( impl_id) => {
906
874
let generics = crate :: utils:: generics ( self . db . upcast ( ) , impl_id. into ( ) ) ;
907
875
let substs = generics. placeholder_subst ( self . db ) ;
908
- let ty = self . db . impl_self_ty ( impl_id) . substitute ( Interner , & substs) ;
909
- self . resolve_variant_on_alias ( ty, unresolved, mod_path)
876
+ let mut ty = self . db . impl_self_ty ( impl_id) . substitute ( Interner , & substs) ;
877
+
878
+ let Some ( mut remaining_idx) = unresolved else {
879
+ return self . resolve_variant_on_alias ( ty, None , mod_path) ;
880
+ } ;
881
+
882
+ let mut remaining_segments = path. segments ( ) . skip ( remaining_idx) ;
883
+
884
+ // We need to try resolving unresolved segments one by one because each may resolve
885
+ // to a projection, which `TyLoweringContext` cannot handle on its own.
886
+ while !remaining_segments. is_empty ( ) {
887
+ let resolved_segment = path. segments ( ) . get ( remaining_idx - 1 ) . unwrap ( ) ;
888
+ let current_segment = remaining_segments. take ( 1 ) ;
889
+
890
+ // If we can resolve to an enum variant, it takes priority over associated type
891
+ // of the same name.
892
+ if let Some ( ( AdtId :: EnumId ( id) , _) ) = ty. as_adt ( ) {
893
+ let enum_data = self . db . enum_data ( id) ;
894
+ let name = current_segment. first ( ) . unwrap ( ) . name ;
895
+ if let Some ( local_id) = enum_data. variant ( name) {
896
+ let variant = EnumVariantId { parent : id, local_id } ;
897
+ return if remaining_segments. len ( ) == 1 {
898
+ ( ty, Some ( variant. into ( ) ) )
899
+ } else {
900
+ // We still have unresolved paths, but enum variants never have
901
+ // associated types!
902
+ ( self . err_ty ( ) , None )
903
+ } ;
904
+ }
905
+ }
906
+
907
+ // `lower_partly_resolved_path()` returns `None` as type namespace unless
908
+ // `remaining_segments` is empty, which is never the case here. We don't know
909
+ // which namespace the new `ty` is in until normalized anyway.
910
+ ( ty, _) = ctx. lower_partly_resolved_path (
911
+ resolution,
912
+ resolved_segment,
913
+ current_segment,
914
+ false ,
915
+ ) ;
916
+
917
+ ty = self . table . insert_type_vars ( ty) ;
918
+ ty = self . table . normalize_associated_types_in ( ty) ;
919
+ ty = self . table . resolve_ty_shallow ( & ty) ;
920
+ if ty. is_unknown ( ) {
921
+ return ( self . err_ty ( ) , None ) ;
922
+ }
923
+
924
+ // FIXME(inherent_associated_types): update `resolution` based on `ty` here.
925
+ remaining_idx += 1 ;
926
+ remaining_segments = remaining_segments. skip ( 1 ) ;
927
+ }
928
+
929
+ let variant = ty. as_adt ( ) . and_then ( |( id, _) | match id {
930
+ AdtId :: StructId ( s) => Some ( VariantId :: StructId ( s) ) ,
931
+ AdtId :: UnionId ( u) => Some ( VariantId :: UnionId ( u) ) ,
932
+ AdtId :: EnumId ( _) => {
933
+ // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
934
+ None
935
+ }
936
+ } ) ;
937
+ ( ty, variant)
910
938
}
911
939
TypeNs :: TypeAliasId ( it) => {
912
940
let container = it. lookup ( self . db . upcast ( ) ) . container ;
0 commit comments