Added tests.

This commit is contained in:
Alexander Regueiro 2018-11-04 04:47:10 +00:00
parent d08a42bf2c
commit 0e89f570d2
13 changed files with 133 additions and 42 deletions

View File

@ -2134,7 +2134,7 @@ trait Foo { }
register_diagnostics! {
// E0006 // merged with E0005
// E0006, // merged with E0005
// E0101, // replaced with E0282
// E0102, // replaced with E0282
// E0134,
@ -2183,9 +2183,7 @@ trait Foo { }
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
E0697, // closures cannot be static
E0707, // multiple elided lifetimes used in arguments of `async fn`
E0708, // `async` non-`move` closures with arguments are not currently supported
E0709, // multiple different lifetimes used in arguments of `async fn`

View File

@ -1239,11 +1239,11 @@ pub struct SubtypePredicate<'tcx> {
/// This kind of predicate has no *direct* correspondent in the
/// syntax, but it roughly corresponds to the syntactic forms:
///
/// 1. `T : TraitRef<..., Item=Type>`
/// 1. `T: TraitRef<..., Item=Type>`
/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
///
/// In particular, form #1 is "desugared" to the combination of a
/// normal trait predicate (`T : TraitRef<...>`) and one of these
/// normal trait predicate (`T: TraitRef<...>`) and one of these
/// predicates. Form #2 is a broader form in that it also permits
/// equality between arbitrary types. Processing an instance of
/// Form #2 eventually yields one of these `ProjectionPredicate`

View File

@ -831,7 +831,7 @@ fn ast_type_binding_to_poly_projection_predicate(
let tcx = self.tcx();
if !speculative {
// Given something like `U : SomeTrait<T=X>`, we want to produce a
// Given something like `U: SomeTrait<T = X>`, we want to produce a
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
// subtle in the event that `T` is defined in a supertrait of
// `SomeTrait`, because in that case we need to upcast.
@ -839,7 +839,7 @@ fn ast_type_binding_to_poly_projection_predicate(
// That is, consider this case:
//
// ```
// trait SubTrait : SuperTrait<int> { }
// trait SubTrait: SuperTrait<int> { }
// trait SuperTrait<A> { type T; }
//
// ... B : SubTrait<T=foo> ...
@ -879,6 +879,7 @@ fn ast_type_binding_to_poly_projection_predicate(
}
}
let supertraits = traits::supertraits(tcx, trait_ref);
let candidate = if self.trait_defines_associated_type_named(trait_ref.def_id(),
binding.item_name) {
// Simple case: X is defined in the current trait.
@ -886,10 +887,12 @@ fn ast_type_binding_to_poly_projection_predicate(
} else {
// Otherwise, we have to walk through the supertraits to find
// those that do.
let candidates = traits::supertraits(tcx, trait_ref).filter(|r| {
let candidates = supertraits.filter(|r| {
self.trait_defines_associated_type_named(r.def_id(), binding.item_name)
});
self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(),
let candidates = candidates.collect::<Vec<_>>();
debug!("foo: candidates: {:?}", candidates);
self.one_bound_for_assoc_type(candidates.into_iter(), &trait_ref.to_string(),
binding.item_name, binding.span)
}?;
@ -905,6 +908,7 @@ fn ast_type_binding_to_poly_projection_predicate(
}
tcx.check_stability(assoc_ty.def_id, Some(ref_id), binding.span);
debug!("foo: info: {:?} {:?} {:?} {:?} {:?}", trait_ref, binding.item_name, speculative, assoc_ty.def_id, dup_bindings);
if !speculative {
dup_bindings.entry(assoc_ty.def_id)
.and_modify(|prev_span| {
@ -921,6 +925,13 @@ fn ast_type_binding_to_poly_projection_predicate(
})
.or_insert(binding.span);
}
static mut ABC: u32 = 0;
unsafe {
ABC += 1;
if ABC == 3 {
assert!(false);
}
};
Ok(candidate.map_bound(|trait_ref| {
ty::ProjectionPredicate {
@ -1017,8 +1028,25 @@ fn conv_object_ty_poly_trait_ref(&self,
}));
}
for (projection_bound, _) in &projection_bounds {
associated_types.remove(&projection_bound.projection_def_id());
let mut seen_projection_bounds = FxHashMap::default();
for (projection_bound, span) in projection_bounds.iter().rev() {
let bound_def_id = projection_bound.projection_def_id();
seen_projection_bounds.entry(bound_def_id)
.and_modify(|prev_span| {
let assoc_item = tcx.associated_item(bound_def_id);
let trait_def_id = assoc_item.container.id();
struct_span_err!(tcx.sess, *span, E0719,
"the value of the associated type `{}` (from the trait `{}`) \
is already specified",
assoc_item.ident,
tcx.item_path_str(trait_def_id))
.span_label(*span, "re-bound here")
.span_label(*prev_span, format!("binding for `{}`", assoc_item.ident))
.emit();
})
.or_insert(*span);
associated_types.remove(&bound_def_id);
}
for item_def_id in associated_types {
@ -1132,7 +1160,7 @@ fn find_bound_for_assoc_item(&self,
span)
}
// Checks that bounds contains exactly one element and reports appropriate
// Checks that `bounds` contains exactly one element and reports appropriate
// errors otherwise.
fn one_bound_for_assoc_type<I>(&self,
mut bounds: I,

View File

@ -28,9 +28,9 @@
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir;
/// Helper type of a temporary returned by .for_item(...).
/// Helper type of a temporary returned by `.for_item(...)`.
/// Necessary because we can't write the following bound:
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>).
/// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>)`.
struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
id: ast::NodeId,

View File

@ -1978,9 +1978,9 @@ pub enum SizedByDefault {
No,
}
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
/// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
/// built-in trait (formerly known as kind): Send.
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped `Ty`
/// or a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
/// built-in trait `Send`.
pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
astconv: &dyn AstConv<'gcx, 'tcx>,
param_ty: Ty<'tcx>,
@ -1988,8 +1988,8 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
sized_by_default: SizedByDefault,
span: Span,
) -> Bounds<'tcx> {
let mut region_bounds = vec![];
let mut trait_bounds = vec![];
let mut region_bounds = Vec::new();
let mut trait_bounds = Vec::new();
for ast_bound in ast_bounds {
match *ast_bound {
@ -1999,7 +1999,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
}
}
let mut projection_bounds = vec![];
let mut projection_bounds = Vec::new();
let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
(astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds), bound.span)

View File

@ -4909,4 +4909,5 @@ fn is_null(self: *const Self) -> bool {
E0641, // cannot cast to/from a pointer with an unknown kind
E0645, // trait aliases not finished
E0698, // type inside generator must be known in this context
E0719, // duplicate values for associated type binding
}

View File

@ -0,0 +1,22 @@
// Copyright 2018 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.
trait Foo: Fn(i32) -> i32 + Send {}
impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
fn wants_foo(f: Box<Foo>) -> i32 {
f(42)
}
fn main() {
let f = Box::new(|x| x);
assert_eq!(wants_foo(f), 42);
}

View File

@ -21,7 +21,6 @@ pub fn main() {
let b = Box::new(456) as Box<dyn Foo>;
assert!(*b == 456);
// FIXME(alexreg): associated type should be gotten from trait alias definition
// let c: &dyn I32Iterator = &vec![123].into_iter();
// assert_eq!(c.next(), Some(123));
let c: &mut dyn I32Iterator<Item = u32> = &mut vec![123].into_iter();
assert_eq!(c.next(), Some(123));
}

View File

@ -14,5 +14,4 @@ trait Trait {
type Foo = Trait; //~ ERROR E0191
fn main() {
}
fn main() {}

View File

@ -0,0 +1,17 @@
// Copyright 2018 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.
#![feature(trait_alias)]
trait I32Iterator = Iterator<Item = i32>;
pub fn main() {
let _: &I32Iterator<Item = f32>; //~ ERROR E0719
}

View File

@ -1,17 +0,0 @@
// compile-pass
#![crate_type = "lib"]
#![feature(linkage)]
// MergeFunctions will merge these via an anonymous internal
// backing function, which must be named if ThinLTO buffers are used
#[linkage = "weak"]
pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
a + b + c
}
#[linkage = "weak"]
pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
a + b + c
}

View File

@ -0,0 +1,27 @@
// Copyright 2018 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.
// compile-pass
#![crate_type = "lib"]
#![feature(linkage)]
// MergeFunctions will merge these via an anonymous internal
// backing function, which must be named if ThinLTO buffers are used
#[linkage = "weak"]
pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
a + b + c
}
#[linkage = "weak"]
pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
a + b + c
}

View File

@ -0,0 +1,17 @@
// Copyright 2018 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.
#![feature(trait_alias)]
trait I32Iterator = Iterator<Item = i32>;
trait I32Iterator2 = I32Iterator<Item = i32>;
trait U32Iterator = I32Iterator2<Item = i32>;
pub fn main() {}