| //@ check-pass |
| |
| // Test when deferring repeat expr checks to end of typechecking whether they're |
| // checked before integer fallback occurs. We accomplish this by having the repeat |
| // expr check allow inference progress on an ambiguous goal, where the ambiguous goal |
| // would fail if the inference variable was fallen back to `i32`. This test will |
| // pass if we check repeat exprs before integer fallback. |
| |
| use std::marker::PhantomData; |
| struct Foo<T>(PhantomData<T>); |
| |
| impl Clone for Foo<u32> { |
| fn clone(&self) -> Self { |
| Foo(PhantomData) |
| } |
| } |
| impl Copy for Foo<u32> {} |
| |
| trait Trait {} |
| |
| // Two impls just to ensure that `?int: Trait` wont itself succeed by unifying with |
| // a self type on an impl here. It also ensures that integer fallback would actually |
| // be valid for all of the stalled goals incase that's ever something we take into account. |
| impl Trait for i32 {} |
| impl Trait for u32 {} |
| |
| fn make_goal<T: Trait>(_: &T) {} |
| fn tie<T>(_: &T, _: &[Foo<T>; 2]) {} |
| |
| fn main() { |
| let a = 1; |
| // `?int: Trait` |
| make_goal(&a); |
| |
| // Deferred `Foo<?int>: Copy` requirement |
| let b: [Foo<_>; 2] = [Foo(PhantomData); _]; |
| tie(&a, &b); |
| |
| // If fallback doesn't occur: |
| // - `Foo<?int>; 2`is > 1, needs copy |
| // - `Foo<?int>: Copy` infers `?int=u32` |
| // - stalled goal `?int: Trait` can now make progress and succeed |
| |
| // If fallback occurs: |
| // - `Foo<i32>; 2` is > 1, needs copy |
| // - `Foo<i32>: Copy` doesn't hold -> error |
| } |