@@ -30,75 +30,26 @@ where
30
30
) -> QueryResult < I > {
31
31
self . set_is_normalizes_to_goal ( ) ;
32
32
debug_assert ! ( self . term_is_fully_unconstrained( goal) ) ;
33
- let normalize_result = self
34
- . probe ( |& result| ProbeKind :: TryNormalizeNonRigid { result } )
35
- . enter ( |this| this. normalize_at_least_one_step ( goal) ) ;
36
-
37
- match normalize_result {
38
- Ok ( res) => Ok ( res) ,
39
- Err ( NoSolution ) => {
40
- self . probe ( |& result| ProbeKind :: RigidAlias { result } ) . enter ( |this| {
41
- let Goal { param_env, predicate : NormalizesTo { alias, term } } = goal;
42
- this. add_rigid_constraints ( param_env, alias) ?;
43
- this. relate_rigid_alias_non_alias ( param_env, alias, ty:: Invariant , term) ?;
44
- this. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
45
- } )
46
- }
47
- }
48
- }
49
-
50
- /// Register any obligations that are used to validate that an alias should be
51
- /// treated as rigid.
52
- ///
53
- /// An alias may be considered rigid if it fails normalization, but we also don't
54
- /// want to consider aliases that are not well-formed to be rigid simply because
55
- /// they fail normalization.
56
- ///
57
- /// For example, some `<T as Trait>::Assoc` where `T: Trait` does not hold, or an
58
- /// opaque type whose hidden type doesn't actually satisfy the opaque item bounds.
59
- fn add_rigid_constraints (
60
- & mut self ,
61
- param_env : I :: ParamEnv ,
62
- rigid_alias : ty:: AliasTerm < I > ,
63
- ) -> Result < ( ) , NoSolution > {
64
- let cx = self . cx ( ) ;
65
- match rigid_alias. kind ( cx) {
66
- // Projections are rigid only if their trait ref holds,
67
- // and the GAT where-clauses hold.
68
- ty:: AliasTermKind :: ProjectionTy | ty:: AliasTermKind :: ProjectionConst => {
69
- let trait_ref = rigid_alias. trait_ref ( cx) ;
70
- self . add_goal ( GoalSource :: AliasWellFormed , Goal :: new ( cx, param_env, trait_ref) ) ;
71
- Ok ( ( ) )
72
- }
73
- ty:: AliasTermKind :: OpaqueTy => {
74
- if self . opaque_type_is_rigid ( rigid_alias. def_id ) {
75
- Ok ( ( ) )
76
- } else {
77
- Err ( NoSolution )
78
- }
79
- }
80
- // FIXME(generic_const_exprs): we would need to support generic consts here
81
- ty:: AliasTermKind :: UnevaluatedConst => Err ( NoSolution ) ,
82
- // Inherent and weak types are never rigid. This type must not be well-formed.
83
- ty:: AliasTermKind :: WeakTy | ty:: AliasTermKind :: InherentTy => Err ( NoSolution ) ,
84
- }
85
- }
86
-
87
- /// Normalize the given alias by at least one step. If the alias is rigid, this
88
- /// returns `NoSolution`.
89
- #[ instrument( level = "trace" , skip( self ) , ret) ]
90
- fn normalize_at_least_one_step ( & mut self , goal : Goal < I , NormalizesTo < I > > ) -> QueryResult < I > {
91
33
let cx = self . cx ( ) ;
92
34
match goal. predicate . alias . kind ( cx) {
93
35
ty:: AliasTermKind :: ProjectionTy | ty:: AliasTermKind :: ProjectionConst => {
94
36
let candidates = self . assemble_and_evaluate_candidates ( goal) ;
37
+ let trait_ref = goal. predicate . alias . trait_ref ( cx) ;
95
38
let ( _, proven_via) =
96
39
self . probe ( |_| ProbeKind :: ShadowedEnvProbing ) . enter ( |ecx| {
97
- let trait_goal: Goal < I , ty:: TraitPredicate < I > > =
98
- goal. with ( cx, goal. predicate . alias . trait_ref ( cx) ) ;
40
+ let trait_goal: Goal < I , ty:: TraitPredicate < I > > = goal. with ( cx, trait_ref) ;
99
41
ecx. compute_trait_goal ( trait_goal)
100
42
} ) ?;
101
- self . merge_candidates ( proven_via, candidates)
43
+ self . merge_candidates ( proven_via, candidates, |ecx| {
44
+ ecx. probe ( |& result| ProbeKind :: RigidAlias { result } ) . enter ( |this| {
45
+ this. structurally_instantiate_normalizes_to_term (
46
+ goal,
47
+ goal. predicate . alias ,
48
+ ) ;
49
+ this. add_goal ( GoalSource :: AliasWellFormed , goal. with ( cx, trait_ref) ) ;
50
+ this. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
51
+ } )
52
+ } )
102
53
}
103
54
ty:: AliasTermKind :: InherentTy => self . normalize_inherent_associated_type ( goal) ,
104
55
ty:: AliasTermKind :: OpaqueTy => self . normalize_opaque_type ( goal) ,
@@ -120,6 +71,17 @@ where
120
71
self . eq ( goal. param_env , goal. predicate . term , term)
121
72
. expect ( "expected goal term to be fully unconstrained" ) ;
122
73
}
74
+
75
+ /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term
76
+ /// with a rigid alias. Using this is pretty much always wrong.
77
+ pub fn structurally_instantiate_normalizes_to_term (
78
+ & mut self ,
79
+ goal : Goal < I , NormalizesTo < I > > ,
80
+ term : ty:: AliasTerm < I > ,
81
+ ) {
82
+ self . relate_rigid_alias_non_alias ( goal. param_env , term, ty:: Invariant , goal. predicate . term )
83
+ . expect ( "expected goal term to be fully unconstrained" ) ;
84
+ }
123
85
}
124
86
125
87
impl < D , I > assembly:: GoalKind < D > for NormalizesTo < I >
@@ -576,80 +538,92 @@ where
576
538
let cx = ecx. cx ( ) ;
577
539
let metadata_def_id = cx. require_lang_item ( TraitSolverLangItem :: Metadata ) ;
578
540
assert_eq ! ( metadata_def_id, goal. predicate. def_id( ) ) ;
579
- ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
580
- let metadata_ty = match goal. predicate . self_ty ( ) . kind ( ) {
581
- ty:: Bool
582
- | ty:: Char
583
- | ty:: Int ( ..)
584
- | ty:: Uint ( ..)
585
- | ty:: Float ( ..)
586
- | ty:: Array ( ..)
587
- | ty:: Pat ( ..)
588
- | ty:: RawPtr ( ..)
589
- | ty:: Ref ( ..)
590
- | ty:: FnDef ( ..)
591
- | ty:: FnPtr ( ..)
592
- | ty:: Closure ( ..)
593
- | ty:: CoroutineClosure ( ..)
594
- | ty:: Infer ( ty:: IntVar ( ..) | ty:: FloatVar ( ..) )
595
- | ty:: Coroutine ( ..)
596
- | ty:: CoroutineWitness ( ..)
597
- | ty:: Never
598
- | ty:: Foreign ( ..)
599
- | ty:: Dynamic ( _, _, ty:: DynStar ) => Ty :: new_unit ( cx) ,
600
-
601
- ty:: Error ( e) => Ty :: new_error ( cx, e) ,
602
-
603
- ty:: Str | ty:: Slice ( _) => Ty :: new_usize ( cx) ,
604
-
605
- ty:: Dynamic ( _, _, ty:: Dyn ) => {
606
- let dyn_metadata = cx. require_lang_item ( TraitSolverLangItem :: DynMetadata ) ;
607
- cx. type_of ( dyn_metadata)
608
- . instantiate ( cx, & [ I :: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] )
609
- }
541
+ let metadata_ty = match goal. predicate . self_ty ( ) . kind ( ) {
542
+ ty:: Bool
543
+ | ty:: Char
544
+ | ty:: Int ( ..)
545
+ | ty:: Uint ( ..)
546
+ | ty:: Float ( ..)
547
+ | ty:: Array ( ..)
548
+ | ty:: Pat ( ..)
549
+ | ty:: RawPtr ( ..)
550
+ | ty:: Ref ( ..)
551
+ | ty:: FnDef ( ..)
552
+ | ty:: FnPtr ( ..)
553
+ | ty:: Closure ( ..)
554
+ | ty:: CoroutineClosure ( ..)
555
+ | ty:: Infer ( ty:: IntVar ( ..) | ty:: FloatVar ( ..) )
556
+ | ty:: Coroutine ( ..)
557
+ | ty:: CoroutineWitness ( ..)
558
+ | ty:: Never
559
+ | ty:: Foreign ( ..)
560
+ | ty:: Dynamic ( _, _, ty:: DynStar ) => Ty :: new_unit ( cx) ,
610
561
611
- ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
612
- // This is the "fallback impl" for type parameters, unnormalizable projections
613
- // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
614
- // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
615
- // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
616
- let sized_predicate = ty:: TraitRef :: new (
617
- cx,
618
- cx. require_lang_item ( TraitSolverLangItem :: Sized ) ,
619
- [ I :: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] ,
620
- ) ;
621
- // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
622
- ecx. add_goal ( GoalSource :: Misc , goal. with ( cx, sized_predicate) ) ;
623
- Ty :: new_unit ( cx)
624
- }
562
+ ty:: Error ( e) => Ty :: new_error ( cx, e) ,
625
563
626
- ty:: Adt ( def, args) if def. is_struct ( ) => match def. struct_tail_ty ( cx) {
627
- None => Ty :: new_unit ( cx) ,
628
- Some ( tail_ty) => {
629
- Ty :: new_projection ( cx, metadata_def_id, [ tail_ty. instantiate ( cx, args) ] )
630
- }
631
- } ,
632
- ty:: Adt ( _, _) => Ty :: new_unit ( cx) ,
564
+ ty:: Str | ty:: Slice ( _) => Ty :: new_usize ( cx) ,
633
565
634
- ty:: Tuple ( elements) => match elements. last ( ) {
635
- None => Ty :: new_unit ( cx) ,
636
- Some ( tail_ty) => Ty :: new_projection ( cx, metadata_def_id, [ tail_ty] ) ,
637
- } ,
566
+ ty:: Dynamic ( _, _, ty:: Dyn ) => {
567
+ let dyn_metadata = cx. require_lang_item ( TraitSolverLangItem :: DynMetadata ) ;
568
+ cx. type_of ( dyn_metadata)
569
+ . instantiate ( cx, & [ I :: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] )
570
+ }
571
+
572
+ ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
573
+ // This is the "fallback impl" for type parameters, unnormalizable projections
574
+ // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
575
+ // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
576
+ // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
577
+ let alias_bound_result =
578
+ ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
579
+ let sized_predicate = ty:: TraitRef :: new (
580
+ cx,
581
+ cx. require_lang_item ( TraitSolverLangItem :: Sized ) ,
582
+ [ I :: GenericArg :: from ( goal. predicate . self_ty ( ) ) ] ,
583
+ ) ;
584
+ ecx. add_goal ( GoalSource :: Misc , goal. with ( cx, sized_predicate) ) ;
585
+ ecx. instantiate_normalizes_to_term ( goal, Ty :: new_unit ( cx) . into ( ) ) ;
586
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
587
+ } ) ;
588
+ // In case the dummy alias-bound candidate does not apply, we instead treat this projection
589
+ // as rigid.
590
+ return alias_bound_result. or_else ( |NoSolution | {
591
+ ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |this| {
592
+ this. structurally_instantiate_normalizes_to_term (
593
+ goal,
594
+ goal. predicate . alias ,
595
+ ) ;
596
+ this. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
597
+ } )
598
+ } ) ;
599
+ }
638
600
639
- ty:: UnsafeBinder ( _) => {
640
- // FIXME(unsafe_binder): Figure out how to handle pointee for unsafe binders.
641
- todo ! ( )
601
+ ty:: Adt ( def, args) if def. is_struct ( ) => match def. struct_tail_ty ( cx) {
602
+ None => Ty :: new_unit ( cx) ,
603
+ Some ( tail_ty) => {
604
+ Ty :: new_projection ( cx, metadata_def_id, [ tail_ty. instantiate ( cx, args) ] )
642
605
}
606
+ } ,
607
+ ty:: Adt ( _, _) => Ty :: new_unit ( cx) ,
643
608
644
- ty:: Infer (
645
- ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ,
646
- )
647
- | ty:: Bound ( ..) => panic ! (
648
- "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`" ,
649
- goal. predicate. self_ty( )
650
- ) ,
651
- } ;
609
+ ty:: Tuple ( elements) => match elements. last ( ) {
610
+ None => Ty :: new_unit ( cx) ,
611
+ Some ( tail_ty) => Ty :: new_projection ( cx, metadata_def_id, [ tail_ty] ) ,
612
+ } ,
652
613
614
+ ty:: UnsafeBinder ( _) => {
615
+ // FIXME(unsafe_binder): Figure out how to handle pointee for unsafe binders.
616
+ todo ! ( )
617
+ }
618
+
619
+ ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
620
+ | ty:: Bound ( ..) => panic ! (
621
+ "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`" ,
622
+ goal. predicate. self_ty( )
623
+ ) ,
624
+ } ;
625
+
626
+ ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
653
627
ecx. instantiate_normalizes_to_term ( goal, metadata_ty. into ( ) ) ;
654
628
ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
655
629
} )
@@ -850,12 +824,14 @@ where
850
824
todo ! ( "discr subgoal..." )
851
825
}
852
826
853
- // We do not call `Ty::discriminant_ty` on alias, param, or placeholder
854
- // types, which return `<self_ty as DiscriminantKind>::Discriminant`
855
- // (or ICE in the case of placeholders). Projecting a type to itself
856
- // is never really productive.
827
+ // Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid
828
+ // alias. In case there's a where-bound further constraining this alias it is preferred over
829
+ // this impl candidate anyways. It's still a bit scuffed.
857
830
ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
858
- return Err ( NoSolution ) ;
831
+ return ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
832
+ ecx. structurally_instantiate_normalizes_to_term ( goal, goal. predicate . alias ) ;
833
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
834
+ } ) ;
859
835
}
860
836
861
837
ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
@@ -902,12 +878,14 @@ where
902
878
todo ! ( )
903
879
}
904
880
905
- // We do not call `Ty::async_destructor_ty` on alias, param, or placeholder
906
- // types, which return `<self_ty as AsyncDestruct>::AsyncDestructor`
907
- // (or ICE in the case of placeholders). Projecting a type to itself
908
- // is never really productive.
881
+ // Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid
882
+ // alias. In case there's a where-bound further constraining this alias it is preferred over
883
+ // this impl candidate anyways. It's still a bit scuffed.
909
884
ty:: Alias ( _, _) | ty:: Param ( _) | ty:: Placeholder ( ..) => {
910
- return Err ( NoSolution ) ;
885
+ return ecx. probe_builtin_trait_candidate ( BuiltinImplSource :: Misc ) . enter ( |ecx| {
886
+ ecx. structurally_instantiate_normalizes_to_term ( goal, goal. predicate . alias ) ;
887
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
888
+ } ) ;
911
889
}
912
890
913
891
ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) )
0 commit comments