Skip to content

Commit 31f219f

Browse files
committed
wip
1 parent 64c13f8 commit 31f219f

File tree

1 file changed

+94
-2
lines changed

1 file changed

+94
-2
lines changed

crates/formality-prove/src/decls.rs

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use formality_types::{
33
cast::Upcast,
44
collections::Set,
55
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,
88
},
99
set,
1010
};
@@ -25,6 +25,79 @@ impl Decls {
2525
/// Max size used in unit tests that are not stress testing maximum size.
2626
pub const DEFAULT_MAX_SIZE: usize = 222;
2727

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+
28101
pub fn is_local_trait_id(&self, trait_id: &TraitId) -> bool {
29102
self.local_trait_ids.contains(trait_id)
30103
}
@@ -33,6 +106,25 @@ impl Decls {
33106
self.local_adt_ids.contains(adt_id)
34107
}
35108

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+
36128
pub fn impl_decls<'s>(&'s self, trait_id: &'s TraitId) -> impl Iterator<Item = &'s ImplDecl> {
37129
self.impl_decls
38130
.iter()

0 commit comments

Comments
 (0)