@@ -3,8 +3,8 @@ use formality_types::{
3
3
cast:: Upcast ,
4
4
collections:: Set ,
5
5
grammar:: {
6
- AdtId , AliasName , AliasTy , Binder , Parameter , Predicate , Relation , TraitId , TraitRef , Ty ,
7
- Wc , Wcs , PR ,
6
+ AdtId , AliasName , AliasTy , Binder , Parameter , ParameterData , Predicate , Relation ,
7
+ RigidName , TraitId , TraitRef , Ty , TyData , Variable , Wc , Wcs , PR ,
8
8
} ,
9
9
set,
10
10
} ;
@@ -25,6 +25,79 @@ impl Decls {
25
25
/// Max size used in unit tests that are not stress testing maximum size.
26
26
pub const DEFAULT_MAX_SIZE : usize = 222 ;
27
27
28
+ pub fn is_local_trait_ref ( & self , trait_ref : & TraitRef ) -> bool {
29
+ // From https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html:
30
+ //
31
+ // Given `impl<P1..=Pn> Trait<T1..=Tn> for T0`, an impl is valid only if at least one of the following is true:
32
+ //
33
+ // - `Trait` is a local trait
34
+ // - All of
35
+ // - At least one of the types `T0..=Tn` must be a local type. Let `Ti` be the
36
+ // first such type.
37
+ // - No uncovered type parameters `P1..=Pn` may appear in `T0..Ti` (excluding
38
+ // `Ti`)
39
+ //
40
+ // Given the following definitions:
41
+ //
42
+ // Covered Type: A type which appears as a parameter to another type. For example,
43
+ // `T` is uncovered, but the `T` in `Vec<T>` is covered. This is only relevant for
44
+ // type parameters.
45
+ //
46
+ // Fundamental Type: A type for which you cannot add a blanket impl backwards
47
+ // compatibly. This includes `&`, `&mut`, and `Box`. Any time a type `T` is
48
+ // considered local, `&T`, `&mut T`, and `Box<T>` are also considered local.
49
+ // Fundamental types cannot cover other types. Any time the term "covered type" is
50
+ // used, `&T`, `&mut T`, and `Box<T>` are not considered covered.
51
+ //
52
+ // Local Type: A struct, enum, or union which was defined in the current crate.
53
+ // This is not affected by type parameters. `struct Foo` is considered local, but
54
+ // `Vec<Foo>` is not. `LocalType<ForeignType>` is local. Type aliases and trait
55
+ // aliases do not affect locality.
56
+ self . is_local_trait_id ( & trait_ref. trait_id ) || {
57
+ if let Some ( first_local) = trait_ref
58
+ . parameters
59
+ . iter ( )
60
+ . position ( |p| self . is_local_parameter ( p) )
61
+ {
62
+ let parameters_before = & trait_ref. parameters [ ..first_local] ;
63
+ !parameters_before
64
+ . iter ( )
65
+ . any ( |p| self . may_have_downstream_type ( p) )
66
+ } else {
67
+ false
68
+ }
69
+ }
70
+ }
71
+
72
+ pub fn is_local_parameter ( & self , parameter : impl Upcast < Parameter > ) -> bool {
73
+ let parameter: Parameter = parameter. upcast ( ) ;
74
+ match parameter. data ( ) {
75
+ ParameterData :: Ty ( t) => match t {
76
+ TyData :: RigidTy ( r) => {
77
+ if self . is_fundamental ( & r. name ) {
78
+ r. parameters . iter ( ) . all ( |p| self . is_local_parameter ( p) )
79
+ } else {
80
+ match & r. name {
81
+ RigidName :: AdtId ( a) => self . is_local_adt_id ( a) ,
82
+ RigidName :: ScalarId ( _) => false ,
83
+ RigidName :: Ref ( _) => unreachable ! ( "refs are fundamental" ) ,
84
+ RigidName :: Tuple ( _) => todo ! ( ) ,
85
+ RigidName :: FnPtr ( _) => false ,
86
+ RigidName :: FnDef ( _) => todo ! ( ) ,
87
+ }
88
+ }
89
+ }
90
+ TyData :: AliasTy ( _) => todo ! ( ) ,
91
+ TyData :: PredicateTy ( _) => todo ! ( ) ,
92
+ TyData :: Variable ( v) => match v {
93
+ Variable :: PlaceholderVar ( _) | Variable :: InferenceVar ( _) => false ,
94
+ Variable :: BoundVar ( _) => todo ! ( ) ,
95
+ } ,
96
+ } ,
97
+ ParameterData :: Lt ( _) => false ,
98
+ }
99
+ }
100
+
28
101
pub fn is_local_trait_id ( & self , trait_id : & TraitId ) -> bool {
29
102
self . local_trait_ids . contains ( trait_id)
30
103
}
@@ -33,6 +106,25 @@ impl Decls {
33
106
self . local_adt_ids . contains ( adt_id)
34
107
}
35
108
109
+ pub fn is_fundamental ( & self , name : & RigidName ) -> bool {
110
+ // Fundamental Type: A type for which you cannot add a blanket impl backwards
111
+ // compatibly. This includes `&`, `&mut`, and `Box`. Any time a type `T` is
112
+ // considered local, `&T`, `&mut T`, and `Box<T>` are also considered local.
113
+ // Fundamental types cannot cover other types. Any time the term "covered type" is
114
+ // used, `&T`, `&mut T`, and `Box<T>` are not considered covered.
115
+
116
+ match name {
117
+ RigidName :: AdtId ( _) => false , // FIXME
118
+
119
+ RigidName :: Ref ( _) => true ,
120
+
121
+ RigidName :: ScalarId ( _)
122
+ | RigidName :: Tuple ( _)
123
+ | RigidName :: FnPtr ( _)
124
+ | RigidName :: FnDef ( _) => false ,
125
+ }
126
+ }
127
+
36
128
pub fn impl_decls < ' s > ( & ' s self , trait_id : & ' s TraitId ) -> impl Iterator < Item = & ' s ImplDecl > {
37
129
self . impl_decls
38
130
. iter ( )
0 commit comments