Skip to content

Commit

Permalink
Added tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Regueiro committed Nov 7, 2018
1 parent d08a42b commit 0e89f57
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 42 deletions.
4 changes: 1 addition & 3 deletions src/librustc/diagnostics.rs
Expand Up @@ -2134,7 +2134,7 @@ static X: u32 = 42;


register_diagnostics! {
// E0006 // merged with E0005
// E0006, // merged with E0005
// E0101, // replaced with E0282
// E0102, // replaced with E0282
// E0134,
Expand Down Expand Up @@ -2183,9 +2183,7 @@ register_diagnostics! {
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`
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/mod.rs
Expand Up @@ -1239,11 +1239,11 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder<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`
Expand Down
42 changes: 35 additions & 7 deletions src/librustc_typeck/astconv.rs
Expand Up @@ -831,15 +831,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
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.
//
// That is, consider this case:
//
// ```
// trait SubTrait : SuperTrait<int> { }
// trait SubTrait: SuperTrait<int> { }
// trait SuperTrait<A> { type T; }
//
// ... B : SubTrait<T=foo> ...
Expand Down Expand Up @@ -879,17 +879,20 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
}
}

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.
Ok(trait_ref)
} 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)
}?;

Expand All @@ -905,6 +908,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
}
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| {
Expand All @@ -921,6 +925,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
})
.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 {
Expand Down Expand Up @@ -1017,8 +1028,25 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
}));
}

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 {
Expand Down Expand Up @@ -1132,7 +1160,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
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,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/check/wfcheck.rs
Expand Up @@ -28,9 +28,9 @@ use errors::{DiagnosticBuilder, DiagnosticId};
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,
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_typeck/collect.rs
Expand Up @@ -1978,18 +1978,18 @@ 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>,
ast_bounds: &[hir::GenericBound],
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 {
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/librustc_typeck/diagnostics.rs
Expand Up @@ -4909,4 +4909,5 @@ register_diagnostics! {
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 changes: 22 additions & 0 deletions src/test/run-pass/issues/issue-24010.rs
@@ -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);
}
Expand Up @@ -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));
}
3 changes: 1 addition & 2 deletions src/test/ui/error-codes/E0191.rs
Expand Up @@ -14,5 +14,4 @@ trait Trait {

type Foo = Trait; //~ ERROR E0191

fn main() {
}
fn main() {}
17 changes: 17 additions & 0 deletions src/test/ui/error-codes/E0719.rs
@@ -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
}
17 changes: 0 additions & 17 deletions src/test/ui/issue-51947.rs

This file was deleted.

27 changes: 27 additions & 0 deletions src/test/ui/issues/issue-51947.rs
@@ -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 changes: 17 additions & 0 deletions src/test/ui/traits/trait-alias-associated-type-rebound.rs
@@ -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() {}

0 comments on commit 0e89f57

Please sign in to comment.