Added tests.
This commit is contained in:
parent
d08a42bf2c
commit
0e89f570d2
@ -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`
|
||||
|
@ -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`
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
22
src/test/run-pass/issues/issue-24010.rs
Normal file
22
src/test/run-pass/issues/issue-24010.rs
Normal 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);
|
||||
}
|
@ -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));
|
||||
}
|
@ -14,5 +14,4 @@ trait Trait {
|
||||
|
||||
type Foo = Trait; //~ ERROR E0191
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
|
17
src/test/ui/error-codes/E0719.rs
Normal file
17
src/test/ui/error-codes/E0719.rs
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
27
src/test/ui/issues/issue-51947.rs
Normal file
27
src/test/ui/issues/issue-51947.rs
Normal 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
|
||||
}
|
17
src/test/ui/traits/trait-alias-associated-type-rebound.rs
Normal file
17
src/test/ui/traits/trait-alias-associated-type-rebound.rs
Normal 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() {}
|
Loading…
Reference in New Issue
Block a user