-
Notifications
You must be signed in to change notification settings - Fork 182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implied bounds, second take #82
Changes from all commits
a4ddd09
9d4f4cb
a640bea
902d344
acd499f
4bac247
432c2ec
4506e42
91eda35
249bd61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
use cast::Cast; | ||
use chalk_parse::ast; | ||
use fallible::*; | ||
use fold::{DefaultTypeFolder, ExistentialFolder, Fold, IdentityUniversalFolder}; | ||
|
@@ -297,6 +296,13 @@ impl Ty { | |
_ => panic!("{:?} is not a projection", self), | ||
} | ||
} | ||
|
||
pub fn is_projection(&self) -> bool { | ||
match *self { | ||
Ty::Projection(..) | Ty::UnselectedProjection(..) => true, | ||
_ => false, | ||
} | ||
} | ||
} | ||
|
||
/// for<'a...'z> X -- all binders are instantiated at once, | ||
|
@@ -444,6 +450,7 @@ pub enum DomainGoal { | |
Normalize(Normalize), | ||
UnselectedNormalize(UnselectedNormalize), | ||
WellFormed(WellFormed), | ||
FromEnv(FromEnv), | ||
InScope(ItemId), | ||
} | ||
|
||
|
@@ -462,27 +469,25 @@ impl DomainGoal { | |
} | ||
} | ||
|
||
/// A clause of the form (T: Foo) expands to (T: Foo), WF(T: Foo). | ||
/// A clause of the form (T: Foo<Item = U>) expands to (T: Foo<Item = U>), T: Foo, WF(T: Foo). | ||
crate fn expanded(self, program: &Program) -> impl Iterator<Item = DomainGoal> { | ||
let mut expanded = vec![]; | ||
/// Turn a where clause into the WF version of it i.e.: | ||
/// * `T: Trait` maps to `WellFormed(T: Trait)` | ||
/// * `T: Trait<Item = Foo>` maps to `WellFormed(T: Trait<Item = Foo>)` | ||
/// * any other clause maps to itself | ||
crate fn into_well_formed_clause(self) -> DomainGoal { | ||
match self { | ||
DomainGoal::Implemented(ref trait_ref) => { | ||
expanded.push(WellFormed::TraitRef(trait_ref.clone()).cast()) | ||
} | ||
DomainGoal::ProjectionEq(ProjectionEq { ref projection, .. }) => { | ||
let (associated_ty_data, trait_params, _) = program.split_projection(&projection); | ||
let trait_ref = TraitRef { | ||
trait_id: associated_ty_data.trait_id, | ||
parameters: trait_params.to_owned(), | ||
}; | ||
expanded.push(WellFormed::TraitRef(trait_ref.clone()).cast()); | ||
expanded.push(trait_ref.cast()); | ||
} | ||
_ => (), | ||
}; | ||
expanded.push(self.cast()); | ||
expanded.into_iter() | ||
DomainGoal::Implemented(tr) => DomainGoal::WellFormed(WellFormed::TraitRef(tr)), | ||
DomainGoal::ProjectionEq(n) => DomainGoal::WellFormed(WellFormed::ProjectionEq(n)), | ||
goal => goal, | ||
} | ||
} | ||
|
||
/// Same as `into_well_formed_clause` but with the `FromEnv` predicate instead of `WellFormed`. | ||
crate fn into_from_env_clause(self) -> DomainGoal { | ||
match self { | ||
DomainGoal::Implemented(tr) => DomainGoal::FromEnv(FromEnv::TraitRef(tr)), | ||
DomainGoal::ProjectionEq(n) => DomainGoal::FromEnv(FromEnv::ProjectionEq(n)), | ||
goal => goal, | ||
} | ||
} | ||
} | ||
|
||
|
@@ -502,9 +507,47 @@ pub struct EqGoal { | |
} | ||
|
||
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] | ||
/// A predicate which is true is some object is well-formed, e.g. a type or a trait ref. | ||
/// For example, given the following type definition: | ||
/// | ||
/// ```notrust | ||
/// struct Set<K> where K: Hash { | ||
/// ... | ||
/// } | ||
/// ``` | ||
/// | ||
/// then we have the following rule: `WellFormed(Set<K>) :- (K: Hash)`. | ||
/// See the complete rules in `lower.rs`. | ||
pub enum WellFormed { | ||
Ty(Ty), | ||
TraitRef(TraitRef), | ||
ProjectionEq(ProjectionEq), | ||
} | ||
|
||
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] | ||
/// A predicate which enables deriving everything which should be true if we *know* that some object | ||
/// is well-formed. For example, given the following trait definitions: | ||
/// | ||
/// ```notrust | ||
/// trait Clone { ... } | ||
/// trait Copy where Self: Clone { ... } | ||
/// ``` | ||
/// | ||
/// then we can use `FromEnv(T: Copy)` to derive that `T: Clone`, like in: | ||
/// | ||
/// ```notrust | ||
/// forall<T> { | ||
/// if (FromEnv(T: Copy)) { | ||
/// T: Clone | ||
/// } | ||
/// } | ||
/// ``` | ||
/// | ||
/// See the complete rules in `lower.rs`. | ||
pub enum FromEnv { | ||
Ty(Ty), | ||
TraitRef(TraitRef), | ||
ProjectionEq(ProjectionEq), | ||
} | ||
|
||
/// Proves that the given projection **normalizes** to the given | ||
|
@@ -710,13 +753,19 @@ impl<T> UCanonical<T> { | |
} | ||
|
||
impl UCanonical<InEnvironment<Goal>> { | ||
/// A goal has coinductive semantics if it is of the form `T: AutoTrait`. | ||
/// A goal has coinductive semantics if it is of the form `T: AutoTrait`, or if it is of the | ||
/// form `WellFormed(T: Trait)` where `Trait` is any trait. The latter is needed for dealing | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am mildly surprised that we don't want to just make all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well types only have where clauses of the form |
||
/// with WF requirements and cyclic traits, which generates cycles in the proof tree which must | ||
/// not be rejected but instead must be treated as a success. | ||
crate fn is_coinductive(&self, program: &ProgramEnvironment) -> bool { | ||
match &self.canonical.value.goal { | ||
Goal::Leaf(LeafGoal::DomainGoal(DomainGoal::Implemented(tr))) => { | ||
let trait_datum = &program.trait_data[&tr.trait_id]; | ||
trait_datum.binders.value.flags.auto | ||
} | ||
Goal::Leaf(LeafGoal::DomainGoal(DomainGoal::WellFormed(WellFormed::TraitRef(_)))) => { | ||
true | ||
} | ||
_ => false, | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am happy to see
if_raw
gone, I have to say. That always felt "yucky".