Skip to content

Commit 468b625

Browse files
committed
Fix an implied bound related to assoc types according to #12
1 parent 0435fc2 commit 468b625

File tree

2 files changed

+85
-12
lines changed

2 files changed

+85
-12
lines changed

src/rules.rs

+23-12
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl ImplDatum {
107107
/// Given `impl<T: Clone> Clone for Vec<T>`, generate:
108108
///
109109
/// ```notrust
110-
/// forall<T> { (Vec<T>: Clone) :- (T: Clone) }
110+
/// forall<T> { Implemented(Vec<T>: Clone) :- Implemented(T: Clone) }
111111
/// ```
112112
fn to_program_clause(&self) -> ProgramClause {
113113
self.binders
@@ -137,9 +137,9 @@ impl DefaultImplDatum {
137137
///
138138
/// ```notrust
139139
/// forall<T> {
140-
/// (MyList<T>: Send) :-
141-
/// (T: Send),
142-
/// (Box<Option<MyList<T>>>: Send)
140+
/// Implemented(MyList<T>: Send) :-
141+
/// Implemented(T: Send),
142+
/// Implemented(Box<Option<MyList<T>>>: Send)
143143
/// }
144144
/// ```
145145
fn to_program_clause(&self) -> ProgramClause {
@@ -179,8 +179,8 @@ impl AssociatedTyValue {
179179
/// ```notrust
180180
/// forall<'a, T> {
181181
/// Normalize(<Vec<T> as Iterable>::IntoIter<'a> -> Iter<'a, T>>) :-
182-
/// (Vec<T>: Iterable), // (1)
183-
/// (Iter<'a, T>: 'a) // (2)
182+
/// Implemented(Vec<T>: Iterable), // (1)
183+
/// Implemented(Iter<'a, T>: 'a) // (2)
184184
/// }
185185
/// ```
186186
///
@@ -304,7 +304,7 @@ impl StructDatum {
304304
//
305305
// we generate the following clauses:
306306
//
307-
// forall<T> { WF(Foo<T>) :- (T: Eq). }
307+
// forall<T> { WF(Foo<T>) :- Implemented(T: Eq). }
308308
// forall<T> { FromEnv(T: Eq) :- FromEnv(Foo<T>). }
309309
// forall<T> { IsFullyVisible(Foo<T>) :- IsFullyVisible(T) }
310310
//
@@ -456,7 +456,7 @@ impl TraitDatum {
456456
// we generate the following clause:
457457
//
458458
// forall<Self, T> {
459-
// WF(Self: Ord<T>) :- (Self: Ord<T>), WF(Self: Eq<T>)
459+
// WF(Self: Ord<T>) :- Implemented(Self: Ord<T>), WF(Self: Eq<T>)
460460
// }
461461
//
462462
// and the reverse rules:
@@ -786,7 +786,7 @@ impl AssociatedTyDatum {
786786
// Well-formedness of projection type.
787787
//
788788
// forall<Self> {
789-
// WellFormed((Foo::Assoc)<Self>) :- Self: Foo, WC.
789+
// WellFormed((Foo::Assoc)<Self>) :- Implemented(Self: Foo), WC.
790790
// }
791791
clauses.push(
792792
Binders {
@@ -837,12 +837,23 @@ impl AssociatedTyDatum {
837837

838838
// Reverse rule for implied bounds.
839839
//
840-
// forall<T> {
841-
// FromEnv(<T as Foo>::Assoc: Bounds) :- FromEnv(Self: Foo)
840+
// forall<Self> {
841+
// FromEnv(<Self as Foo>::Assoc: Bounds) :- FromEnv(Self: Foo), FromEnv(WC)
842842
// }
843843
clauses.extend(self.bounds_on_self().into_iter().map(|bound| {
844844
// Same as above in case of higher-ranked inline bounds.
845845
let shift = bound.binders.len();
846+
let from_env_trait = iter::once(
847+
FromEnv::Trait(trait_ref.clone()).shifted_in(shift).cast()
848+
);
849+
850+
let where_clauses = self.where_clauses
851+
.iter()
852+
.cloned()
853+
// `wc` may be a higher-ranked where clause
854+
.map(|wc| wc.map(|value| value.into_from_env_goal()))
855+
.casted();
856+
846857
Binders {
847858
binders: bound
848859
.binders
@@ -852,7 +863,7 @@ impl AssociatedTyDatum {
852863
.collect(),
853864
value: ProgramClauseImplication {
854865
consequence: bound.value.clone().into_from_env_goal(),
855-
conditions: vec![FromEnv::Trait(trait_ref.clone()).shifted_in(shift).cast()],
866+
conditions: from_env_trait.chain(where_clauses).collect(),
856867
},
857868
}.cast()
858869
}));

src/rules/wf/test.rs

+62
Original file line numberDiff line numberDiff line change
@@ -563,3 +563,65 @@ fn higher_ranked_inline_bound_on_gat() {
563563
}
564564
}
565565
}
566+
567+
#[test]
568+
fn assoc_type_recursive_bound() {
569+
lowering_error! {
570+
program {
571+
trait Sized { }
572+
trait Print {
573+
// fn print();
574+
}
575+
576+
trait Foo {
577+
type Item: Sized where <Self as Foo>::Item: Sized;
578+
}
579+
580+
struct i32 { }
581+
struct str { } // not sized
582+
583+
impl Foo for i32 {
584+
type Item = str;
585+
}
586+
587+
struct OnlySized<T> where T: Sized { }
588+
impl<T> Print for OnlySized<T> {
589+
// fn print() {
590+
// println!("{}", std::mem::size_of::<T>());
591+
// }
592+
}
593+
594+
trait Bar {
595+
type Assoc: Print;
596+
}
597+
598+
impl<T> Bar for T where T: Foo {
599+
type Assoc = OnlySized<<T as Foo>::Item>;
600+
}
601+
602+
// Above, we used to incorrectly assume that `OnlySized<<T as Foo>::Item>`
603+
// is well-formed because of the `T: Foo` bound, hence making the `T: Bar`
604+
// impl pass the well-formedness check. But the following query will
605+
// (and should) always succeed:
606+
// ```
607+
// forall<T> { if (T: Bar) { WellFormed(<T as Bar>::Assoc) } }
608+
// ```
609+
//
610+
// This may lead to the following code to compile:
611+
612+
// fn foo<T: Print>() {
613+
// T::print() // oops, `T = str`
614+
// }
615+
616+
// fn bar<T: Bar> {
617+
// foo<<T as Bar>::Assoc>()
618+
// }
619+
620+
// fn main() {
621+
// bar::<i32>()
622+
// }
623+
} error_msg {
624+
"trait impl for \"Bar\" does not meet well-formedness requirements"
625+
}
626+
}
627+
}

0 commit comments

Comments
 (0)