| // Copyright 2016 The Rust Project Developers. See the COPYRIGHT |
| // file at the top-level directory of this distribution and at |
| // http://rust-lang.org/COPYRIGHT. |
| // |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| // option. This file may not be copied, modified, or distributed |
| // except according to those terms. |
| |
| // Regression test for #30225, which was an ICE that would trigger as |
| // a result of a poor interaction between trait result caching and |
| // type inference. Specifically, at that time, unification could cause |
| // unrelated type variables to become instantiated, if subtyping |
| // relationships existed. These relationships are now propagated |
| // through obligations and hence everything works out fine. |
| |
| trait Foo<U,V> : Sized { |
| fn foo(self, u: Option<U>, v: Option<V>) {} |
| } |
| |
| struct A; |
| struct B; |
| |
| impl Foo<A, B> for () {} // impl A |
| impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity |
| |
| fn toxic() { |
| // cache the resolution <() as Foo<$0,$1>> = impl A |
| let u = None; |
| let v = None; |
| Foo::foo((), u, v); |
| } |
| |
| fn bomb() { |
| let mut u = None; // type is Option<$0> |
| let mut v = None; // type is Option<$1> |
| let mut x = None; // type is Option<$2> |
| |
| Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>> |
| u = v; // mark $0 and $1 in a subtype relationship |
| //~^ ERROR mismatched types |
| x = Some(()); // set $2 = (), allowing impl selection |
| // to proceed for <() as Foo<$0, $1>> = impl A. |
| // kaboom, this *used* to trigge an ICE |
| } |
| |
| fn main() {} |