Rework normalization so that it works recursively, since the types extracted from an impl are potentially in need of normalization. This also lays groundwork for further cleanup in other areas by disconnecting normalization from the fulfillment context.

This commit is contained in:
Niko Matsakis 2014-12-30 17:42:02 -05:00
parent 0aa7ba9f5e
commit 6cb425d964
13 changed files with 578 additions and 378 deletions

View file

@ -25,11 +25,30 @@ pub fn f2<T: Foo>(a: T) -> T::A {
panic!();
}
pub fn main() {
f1(2i, 4i); //~ ERROR expected uint, found int
f1(2i, 4u);
f1(2u, 4u); //~ ERROR the trait `Foo` is not implemented
f1(2u, 4i); //~ ERROR the trait `Foo` is not implemented
let _: int = f2(2i); //~ERROR expected `int`, found `uint`
pub fn f1_int_int() {
f1(2i, 4i);
//~^ ERROR expected uint, found int
}
pub fn f1_int_uint() {
f1(2i, 4u);
}
pub fn f1_uint_uint() {
f1(2u, 4u);
//~^ ERROR the trait `Foo` is not implemented
//~| ERROR the trait `Foo` is not implemented
}
pub fn f1_uint_int() {
f1(2u, 4i);
//~^ ERROR the trait `Foo` is not implemented
//~| ERROR the trait `Foo` is not implemented
}
pub fn f2_int() {
let _: int = f2(2i);
//~^ ERROR expected `int`, found `uint`
}
pub fn main() { }

View file

@ -29,9 +29,10 @@ fn bar<'a, 'b, I : for<'x> Foo<&'x int>>(
x: <I as Foo<&'a int>>::A,
y: <I as Foo<&'b int>>::A,
cond: bool)
{ //~ ERROR cannot infer
{
// x and y here have two distinct lifetimes:
let z: I::A = if cond { x } else { y };
//~^ ERROR cannot infer
}
pub fn main() {}

View file

@ -0,0 +1,28 @@
// Copyright 2014 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.
// Check that an associated type cannot be bound in an expression path.
#![feature(associated_types)]
trait Foo {
type A;
fn bar() -> int;
}
impl Foo for int {
type A = uint;
fn bar() -> int { 42 }
}
pub fn main() {
let x: int = Foo::bar();
//~^ ERROR type annotations required
}

View file

@ -33,7 +33,7 @@ where T : Convert<U>
}
fn a() {
test(22_i32, 44); //~ ERROR unable to infer
test(22_i32, 44); //~ ERROR type annotations required
}
fn main() {}

View file

@ -0,0 +1,58 @@
// Copyright 2014 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.
// Test how resolving a projection interacts with inference. In this
// case, we were eagerly unifying the type variable for the iterator
// type with `I` from the where clause, ignoring the in-scope `impl`
// for `ByRef`. The right answer was to consider the result ambiguous
// until more type information was available.
// ignore-pretty -- FIXME(#17362)
#![feature(associated_types, lang_items, unboxed_closures)]
#![no_implicit_prelude]
use std::option::Option::{None, Some, mod};
trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
trait IteratorExt: Iterator {
fn by_ref(&mut self) -> ByRef<Self> {
ByRef(self)
}
}
impl<I> IteratorExt for I where I: Iterator {}
struct ByRef<'a, I: 'a + Iterator>(&'a mut I);
impl<'a, I: Iterator> Iterator for ByRef<'a, I> {
type Item = I::Item;
fn next(&mut self) -> Option< <I as Iterator>::Item > {
self.0.next()
}
}
fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
fn test<A, I: Iterator<Item=A>>(mut it: I) {
is_iterator_of::<A, _>(&it.by_ref());
}
fn test2<A, I1: Iterator<Item=A>, I2: Iterator<Item=I1::Item>>(mut it: I2) {
is_iterator_of::<A, _>(&it)
}
fn main() { }