diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 1d21a5cf79d10..96590c1fc72d4 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -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, @@ -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` diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c18c55bcb5db7..71d59750d6c87 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1239,11 +1239,11 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder>; /// 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. `>::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` diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index daf04aa0db223..3aaa5810eab38 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -831,7 +831,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let tcx = self.tcx(); if !speculative { - // Given something like `U : SomeTrait`, we want to produce a + // Given something like `U: SomeTrait`, we want to produce a // predicate like `::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 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { // That is, consider this case: // // ``` - // trait SubTrait : SuperTrait { } + // trait SubTrait: SuperTrait { } // trait SuperTrait { type T; } // // ... B : SubTrait ... @@ -879,6 +879,7 @@ 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. @@ -886,10 +887,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { } 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::>(); + 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 @@ 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| { @@ -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 { @@ -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 { @@ -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(&self, mut bounds: I, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 53f536578632c..8574443190d7c 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index be09cfce8cae6..d5f5cbb562e78 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index c81aea2465b7b..a985c3e9fdf44 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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 } diff --git a/src/test/run-pass/issues/issue-24010.rs b/src/test/run-pass/issues/issue-24010.rs new file mode 100644 index 0000000000000..cce8bb84837f3 --- /dev/null +++ b/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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo: Fn(i32) -> i32 + Send {} + +impl i32 + Send> Foo for T {} + +fn wants_foo(f: Box) -> i32 { + f(42) +} + +fn main() { + let f = Box::new(|x| x); + assert_eq!(wants_foo(f), 42); +} diff --git a/src/test/run-pass/traits/trait-alias-object-type.rs b/src/test/run-pass/traits/trait-alias-objects.rs similarity index 80% rename from src/test/run-pass/traits/trait-alias-object-type.rs rename to src/test/run-pass/traits/trait-alias-objects.rs index 17e30922b2cb8..a5bb0cac251b2 100644 --- a/src/test/run-pass/traits/trait-alias-object-type.rs +++ b/src/test/run-pass/traits/trait-alias-objects.rs @@ -21,7 +21,6 @@ pub fn main() { let b = Box::new(456) as Box; 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 = &mut vec![123].into_iter(); + assert_eq!(c.next(), Some(123)); } diff --git a/src/test/ui/error-codes/E0191.rs b/src/test/ui/error-codes/E0191.rs index 489ebb033f84e..c35c7e10f5a38 100644 --- a/src/test/ui/error-codes/E0191.rs +++ b/src/test/ui/error-codes/E0191.rs @@ -14,5 +14,4 @@ trait Trait { type Foo = Trait; //~ ERROR E0191 -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0719.rs b/src/test/ui/error-codes/E0719.rs new file mode 100644 index 0000000000000..951041124bb1d --- /dev/null +++ b/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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(trait_alias)] + +trait I32Iterator = Iterator; + +pub fn main() { + let _: &I32Iterator; //~ ERROR E0719 +} diff --git a/src/test/ui/issue-51947.rs b/src/test/ui/issue-51947.rs deleted file mode 100644 index 7b79807e4d7ff..0000000000000 --- a/src/test/ui/issue-51947.rs +++ /dev/null @@ -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 -} diff --git a/src/test/ui/issues/issue-51947.rs b/src/test/ui/issues/issue-51947.rs new file mode 100644 index 0000000000000..3e0c3c002f649 --- /dev/null +++ b/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 or the MIT license +// , 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 +} diff --git a/src/test/ui/traits/trait-alias-associated-type-rebound.rs b/src/test/ui/traits/trait-alias-associated-type-rebound.rs new file mode 100644 index 0000000000000..32f707e192dec --- /dev/null +++ b/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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(trait_alias)] + +trait I32Iterator = Iterator; +trait I32Iterator2 = I32Iterator; +trait U32Iterator = I32Iterator2; + +pub fn main() {}