]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #58578 - kennytm:rollup, r=kennytm
authorbors <bors@rust-lang.org>
Wed, 20 Feb 2019 10:14:28 +0000 (10:14 +0000)
committerbors <bors@rust-lang.org>
Wed, 20 Feb 2019 10:14:28 +0000 (10:14 +0000)
Rollup of 24 pull requests

Successful merges:

 - #56470 (Modify doctest's auto-`fn main()` to allow `Result`s)
 - #58044 (Make overflowing and wrapping negation const)
 - #58303 (Improve stability tags display)
 - #58336 (Fix search results interactions)
 - #58384 (Fix tables display)
 - #58392 (Use less explicit shifting in std::net::ip)
 - #58409 (rustdoc: respect alternate flag when formatting impl trait)
 - #58456 (Remove no longer accurate diagnostic code about NLL)
 - #58528 (Don't use an allocation for ItemId in StmtKind)
 - #58530 (Monomorphize less code in fs::{read|write})
 - #58534 (Mention capping forbid lints)
 - #58536 (Remove UB in pointer tests)
 - #58538 (Add missing fmt structs examples)
 - #58539 (Add alias methods to PathBuf for underlying OsString (#58234))
 - #58544 (Fix doc for rustc "-g" flag)
 - #58545 (Add regression test for a specialization-related ICE (#39448))
 - #58546 (librustc_codegen_llvm => 2018)
 - #58551 (Explain a panic in test case net::tcp::tests::double_bind)
 - #58553 (Use more impl header lifetime elision)
 - #58562 (Fix style nits)
 - #58565 (Fix typo in std::future::Future docs)
 - #58568 (Fix a transposition in driver.rs.)
 - #58569 (Reduce Some Code Repetitions like `(n << amt) >> amt`)
 - #58576 (Stabilize iter::successors and iter::from_fn)

39 files changed:
src/librustc/ich/impls_ty.rs
src/librustc/infer/opaque_types/mod.rs
src/librustc/ty/context.rs
src/librustc/ty/mod.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/collect.rs
src/test/ui/existential_types/bound_reduction2.rs
src/test/ui/existential_types/bound_reduction2.stderr
src/test/ui/existential_types/different_defining_uses.rs
src/test/ui/existential_types/different_defining_uses.stderr
src/test/ui/existential_types/different_defining_uses_never_type.rs
src/test/ui/existential_types/different_defining_uses_never_type.stderr
src/test/ui/existential_types/generic_different_defining_uses.rs
src/test/ui/existential_types/generic_different_defining_uses.stderr
src/test/ui/existential_types/generic_duplicate_param_use.rs
src/test/ui/existential_types/generic_duplicate_param_use.stderr
src/test/ui/existential_types/generic_duplicate_param_use10.rs [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use2.rs [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use2.stderr [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use3.rs [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use3.stderr [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use4.rs [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use4.stderr [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use5.rs [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use5.stderr [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use6.rs [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use6.stderr [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use7.rs [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use8.rs [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use8.stderr [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use9.rs [new file with mode: 0644]
src/test/ui/existential_types/generic_duplicate_param_use9.stderr [new file with mode: 0644]
src/test/ui/existential_types/generic_nondefining_use.rs
src/test/ui/existential_types/generic_nondefining_use.stderr
src/test/ui/existential_types/not_a_defining_use.rs [new file with mode: 0644]
src/test/ui/existential_types/not_a_defining_use.stderr [new file with mode: 0644]
src/test/ui/existential_types/unused_generic_param.rs
src/test/ui/existential_types/unused_generic_param.stderr [deleted file]

index 6f04a68a6ed614e5283152b7f59437e7699b042f..53ed0bfb12ee98095baa674868dc3c65e3f3d446 100644 (file)
@@ -237,6 +237,11 @@ fn hash_stable<W: StableHasherResult>(&self,
     abi
 });
 
+impl_stable_hash_for!(struct ty::ResolvedOpaqueTy<'tcx> {
+    concrete_type,
+    substs
+});
+
 impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for ty::Binder<T>
     where T: HashStable<StableHashingContext<'a>>
 {
index 1f81321d22d6ed1099dd7082ef905130050c1b3c..e75446b01c11e5c90155800caa6583fad01de07b 100644 (file)
@@ -26,7 +26,7 @@ pub struct OpaqueTypeDecl<'tcx> {
     ///
     /// winds up desugared to:
     ///
-    ///     abstract type Foo<'x, T>: Trait<'x>
+    ///     abstract type Foo<'x, X>: Trait<'x>
     ///     fn foo<'a, 'b, T>() -> Foo<'a, T>
     ///
     /// then `substs` would be `['a, T]`.
index 18b0afe1fd91ec08b01ded39a9b8432bc848b9c4..6bb322251256554030bc2b7ac601b159f4172891 100644 (file)
@@ -317,6 +317,17 @@ pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
     }
 }
 
+/// All information necessary to validate and reveal an `impl Trait` or `existential Type`
+#[derive(RustcEncodable, RustcDecodable, Debug)]
+pub struct ResolvedOpaqueTy<'tcx> {
+    /// The revealed type as seen by this function.
+    pub concrete_type: Ty<'tcx>,
+    /// Generic parameters on the opaque type as passed by this function.
+    /// For `existential type Foo<A, B>; fn foo<T, U>() -> Foo<T, U> { .. }` this is `[T, U]`, not
+    /// `[A, B]`
+    pub substs: &'tcx Substs<'tcx>,
+}
+
 #[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct TypeckTables<'tcx> {
     /// The HirId::owner all ItemLocalIds in this table are relative to.
@@ -419,7 +430,7 @@ pub struct TypeckTables<'tcx> {
 
     /// All the existential types that are restricted to concrete types
     /// by this function
-    pub concrete_existential_types: FxHashMap<DefId, Ty<'tcx>>,
+    pub concrete_existential_types: FxHashMap<DefId, ResolvedOpaqueTy<'tcx>>,
 
     /// Given the closure ID this map provides the list of UpvarIDs used by it.
     /// The upvarID contains the HIR node ID and it also contains the full path
index 18dba3092ad5a5063e824b12c4ba125a8b45e7cf..02e4fb12af5c9b21ab202e36c0bd9767a285198d 100644 (file)
@@ -74,7 +74,7 @@
 pub use self::context::{Lift, TypeckTables, CtxtInterners};
 pub use self::context::{
     UserTypeAnnotationIndex, UserType, CanonicalUserType,
-    CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+    CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy,
 };
 
 pub use self::instance::{Instance, InstanceDef};
index 91e44a15882684f3e463b5e1feef378f8110ee60..10f234fd3ca6a5f6c18af71191d8d5a32e024112 100644 (file)
@@ -1386,10 +1386,7 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite
         }
         hir::ItemKind::Existential(..) => {
             let def_id = tcx.hir().local_def_id(it.id);
-            let pty_ty = tcx.type_of(def_id);
-            let generics = tcx.generics_of(def_id);
 
-            check_bounds_are_used(tcx, &generics, pty_ty);
             let substs = Substs::identity_for_item(tcx, def_id);
             check_opaque(tcx, def_id, substs, it.span);
         }
index e68c50d752bd5d78c07f71605f6f1191d050587f..e4c0e3bd54d5dd861db6f2bca04f71d2b32bc0ec 100644 (file)
@@ -560,21 +560,29 @@ fn visit_opaque_types(&mut self, span: Span) {
                 if def_id == defin_ty_def_id {
                     // Concrete type resolved to the existential type itself
                     // Force a cycle error
+                    // FIXME(oli-obk): we could just not insert it into `concrete_existential_types`
+                    // which simply would make this use not a defining use.
                     self.tcx().at(span).type_of(defin_ty_def_id);
                 }
             }
 
+            let new = ty::ResolvedOpaqueTy {
+                concrete_type: definition_ty,
+                substs: self.tcx().lift_to_global(&opaque_defn.substs).unwrap(),
+            };
+
             let old = self.tables
                 .concrete_existential_types
-                .insert(def_id, definition_ty);
+                .insert(def_id, new);
             if let Some(old) = old {
-                if old != definition_ty {
+                if old.concrete_type != definition_ty || old.substs != opaque_defn.substs {
                     span_bug!(
                         span,
                         "visit_opaque_types tried to write \
-                        different types for the same existential type: {:?}, {:?}, {:?}",
+                        different types for the same existential type: {:?}, {:?}, {:?}, {:?}",
                         def_id,
                         definition_ty,
+                        opaque_defn,
                         old,
                     );
                 }
index 84de38beafad9dde00490d6eb1d0b20c87a8c8b4..ec1d9d24730edd59b82c7825739381a0455b1fec 100644 (file)
 use crate::middle::weak_lang_items;
 use rustc::mir::mono::Linkage;
 use rustc::ty::query::Providers;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::util::Discr;
 use rustc::ty::util::IntTypeExt;
+use rustc::ty::subst::UnpackedKind;
 use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::{ReprOptions, ToPredicate};
 use rustc::util::captures::Captures;
@@ -1211,7 +1212,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
                     tcx.typeck_tables_of(owner)
                         .concrete_existential_types
                         .get(&def_id)
-                        .cloned()
+                        .map(|opaque| opaque.concrete_type)
                         .unwrap_or_else(|| {
                             // This can occur if some error in the
                             // owner fn prevented us from populating
@@ -1343,7 +1344,13 @@ fn find_existential_constraints<'a, 'tcx>(
     struct ConstraintLocator<'a, 'tcx: 'a> {
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         def_id: DefId,
-        found: Option<(Span, ty::Ty<'tcx>)>,
+        // First found type span, actual type, mapping from the existential type's generic
+        // parameters to the concrete type's generic parameters
+        //
+        // The mapping is an index for each use site of a generic parameter in the concrete type
+        //
+        // The indices index into the generic parameters on the existential type.
+        found: Option<(Span, ty::Ty<'tcx>, Vec<usize>)>,
     }
 
     impl<'a, 'tcx> ConstraintLocator<'a, 'tcx> {
@@ -1358,23 +1365,106 @@ fn check(&mut self, def_id: DefId) {
                 .tcx
                 .typeck_tables_of(def_id)
                 .concrete_existential_types
-                .get(&self.def_id)
-                .cloned();
-            if let Some(ty) = ty {
+                .get(&self.def_id);
+            if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty {
                 // FIXME(oli-obk): trace the actual span from inference to improve errors
                 let span = self.tcx.def_span(def_id);
-                if let Some((prev_span, prev_ty)) = self.found {
-                    if ty != prev_ty {
+                // used to quickly look up the position of a generic parameter
+                let mut index_map: FxHashMap<ty::ParamTy, usize> = FxHashMap::default();
+                // skip binder is ok, since we only use this to find generic parameters and their
+                // positions.
+                for (idx, subst) in substs.iter().enumerate() {
+                    if let UnpackedKind::Type(ty) = subst.unpack() {
+                        if let ty::Param(p) = ty.sty {
+                            if index_map.insert(p, idx).is_some() {
+                                // there was already an entry for `p`, meaning a generic parameter
+                                // was used twice
+                                self.tcx.sess.span_err(
+                                    span,
+                                    &format!("defining existential type use restricts existential \
+                                    type by using the generic parameter `{}` twice", p.name),
+                                );
+                                return;
+                            }
+                        } else {
+                            self.tcx.sess.delay_span_bug(
+                                span,
+                                &format!(
+                                    "non-defining exist ty use in defining scope: {:?}, {:?}",
+                                    concrete_type, substs,
+                                ),
+                            );
+                        }
+                    }
+                }
+                // compute the index within the existential type for each generic parameter used in
+                // the concrete type
+                let indices = concrete_type
+                    .subst(self.tcx, substs)
+                    .walk()
+                    .filter_map(|t| match &t.sty {
+                        ty::Param(p) => Some(*index_map.get(p).unwrap()),
+                        _ => None,
+                    }).collect();
+                let is_param = |ty: ty::Ty| match ty.sty {
+                    ty::Param(_) => true,
+                    _ => false,
+                };
+                if !substs.types().all(is_param) {
+                    self.tcx.sess.span_err(
+                        span,
+                        "defining existential type use does not fully define existential type",
+                    );
+                } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found {
+                    let mut ty = concrete_type.walk().fuse();
+                    let mut p_ty = prev_ty.walk().fuse();
+                    let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.sty, &p.sty) {
+                        // type parameters are equal to any other type parameter for the purpose of
+                        // concrete type equality, as it is possible to obtain the same type just
+                        // by passing matching parameters to a function.
+                        (ty::Param(_), ty::Param(_)) => true,
+                        _ => t == p,
+                    });
+                    if !iter_eq || ty.next().is_some() || p_ty.next().is_some() {
                         // found different concrete types for the existential type
                         let mut err = self.tcx.sess.struct_span_err(
                             span,
-                            "defining existential type use differs from previous",
+                            "concrete type differs from previous defining existential type use",
+                        );
+                        err.span_label(
+                            span,
+                            format!("expected `{}`, got `{}`", prev_ty, concrete_type),
+                        );
+                        err.span_note(prev_span, "previous use here");
+                        err.emit();
+                    } else if indices != *prev_indices {
+                        // found "same" concrete types, but the generic parameter order differs
+                        let mut err = self.tcx.sess.struct_span_err(
+                            span,
+                            "concrete type's generic parameters differ from previous defining use",
                         );
+                        use std::fmt::Write;
+                        let mut s = String::new();
+                        write!(s, "expected [").unwrap();
+                        let list = |s: &mut String, indices: &Vec<usize>| {
+                            let mut indices = indices.iter().cloned();
+                            if let Some(first) = indices.next() {
+                                write!(s, "`{}`", substs[first]).unwrap();
+                                for i in indices {
+                                    write!(s, ", `{}`", substs[i]).unwrap();
+                                }
+                            }
+                        };
+                        list(&mut s, prev_indices);
+                        write!(s, "], got [").unwrap();
+                        list(&mut s, &indices);
+                        write!(s, "]").unwrap();
+                        err.span_label(span, s);
                         err.span_note(prev_span, "previous use here");
                         err.emit();
                     }
                 } else {
-                    self.found = Some((span, ty));
+                    self.found = Some((span, concrete_type, indices));
                 }
             }
         }
@@ -1433,7 +1523,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
     }
 
     match locator.found {
-        Some((_, ty)) => ty,
+        Some((_, ty, _)) => ty,
         None => {
             let span = tcx.def_span(def_id);
             tcx.sess.span_err(span, "could not find defining uses");
index d8ade50c79c8201be5eec36ece2c62552562aa2b..542e076d88d64c6d242e8fdfe4dba806c863b187 100644 (file)
@@ -8,11 +8,12 @@ trait TraitWithAssoc {
 }
 
 existential type Foo<V>: Trait<V>;
+//~^ ERROR could not find defining uses
 
 trait Trait<U> {}
 
 impl<W> Trait<W> for () {}
 
-fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR non-defining
+fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR does not fully define
     ()
 }
index 8e822ca6d8bc71e10fda4e091df35b04351735cc..f51f1c9a4e563a2cd7c574d01ffbc88bb748bad1 100644 (file)
@@ -1,16 +1,16 @@
-error: non-defining existential type use in defining scope
-  --> $DIR/bound_reduction2.rs:16:1
+error: defining existential type use does not fully define existential type
+  --> $DIR/bound_reduction2.rs:17:1
    |
-LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR non-defining
+LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR does not fully define
 LL | |     ()
 LL | | }
    | |_^
-   |
-note: used non-generic type <T as TraitWithAssoc>::Assoc for generic parameter
-  --> $DIR/bound_reduction2.rs:10:22
+
+error: could not find defining uses
+  --> $DIR/bound_reduction2.rs:10:1
    |
 LL | existential type Foo<V>: Trait<V>;
-   |                      ^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
index c51fca75a24e928c834c111f2e35b6f760fe356a..a8670cc07f2e1370494dd82736fa27b7091e7b5d 100644 (file)
@@ -9,6 +9,6 @@ fn foo() -> Foo {
     ""
 }
 
-fn bar() -> Foo { //~ ERROR defining existential type use differs from previous
+fn bar() -> Foo { //~ ERROR concrete type differs from previous
     42i32
 }
index f782a002297329eb8f3e886ef8e12c815d0ce851..3f9ed96400b54ac4e29d670dc5dc4190d9ab3c95 100644 (file)
@@ -1,10 +1,10 @@
-error: defining existential type use differs from previous
+error: concrete type differs from previous defining existential type use
   --> $DIR/different_defining_uses.rs:12:1
    |
-LL | / fn bar() -> Foo { //~ ERROR defining existential type use differs from previous
+LL | / fn bar() -> Foo { //~ ERROR concrete type differs from previous
 LL | |     42i32
 LL | | }
-   | |_^
+   | |_^ expected `&'static str`, got `i32`
    |
 note: previous use here
   --> $DIR/different_defining_uses.rs:8:1
index c6c6ae8d2dccffea5c4112d6c9be38713303ca5a..13ada63e4bc45fa256ee6f9286feb19f419be862 100644 (file)
@@ -9,10 +9,10 @@ fn foo() -> Foo {
     ""
 }
 
-fn bar() -> Foo { //~ ERROR defining existential type use differs from previous
+fn bar() -> Foo { //~ ERROR concrete type differs from previous
     panic!()
 }
 
-fn boo() -> Foo { //~ ERROR defining existential type use differs from previous
+fn boo() -> Foo { //~ ERROR concrete type differs from previous
     loop {}
 }
index 04b0cf277845514567e8f8e3dbd4cf17b627fc77..e29256a5014f9fede3c8eecc84b6a96c14288712 100644 (file)
@@ -1,10 +1,10 @@
-error: defining existential type use differs from previous
+error: concrete type differs from previous defining existential type use
   --> $DIR/different_defining_uses_never_type.rs:12:1
    |
-LL | / fn bar() -> Foo { //~ ERROR defining existential type use differs from previous
+LL | / fn bar() -> Foo { //~ ERROR concrete type differs from previous
 LL | |     panic!()
 LL | | }
-   | |_^
+   | |_^ expected `&'static str`, got `()`
    |
 note: previous use here
   --> $DIR/different_defining_uses_never_type.rs:8:1
@@ -14,13 +14,13 @@ LL | |     ""
 LL | | }
    | |_^
 
-error: defining existential type use differs from previous
+error: concrete type differs from previous defining existential type use
   --> $DIR/different_defining_uses_never_type.rs:16:1
    |
-LL | / fn boo() -> Foo { //~ ERROR defining existential type use differs from previous
+LL | / fn boo() -> Foo { //~ ERROR concrete type differs from previous
 LL | |     loop {}
 LL | | }
-   | |_^
+   | |_^ expected `&'static str`, got `()`
    |
 note: previous use here
   --> $DIR/different_defining_uses_never_type.rs:8:1
index 3bd104251fb700abdb7a49da585a077ec513b23a..ce3ab88a1c0bbe8cb3113075863571659568bff4 100644 (file)
@@ -8,6 +8,6 @@ fn my_iter<T>(t: T) -> MyIter<T> {
     std::iter::once(t)
 }
 
-fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR defining existential type use differs from previous
+fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR concrete type differs from previous
     Some(t).into_iter()
 }
index 234bcf232ae794d58be14cdf7c2c8bd7d694fca6..3f129658b8fd0d119e865201c98db329e6d927e2 100644 (file)
@@ -1,10 +1,10 @@
-error: defining existential type use differs from previous
+error: concrete type differs from previous defining existential type use
   --> $DIR/generic_different_defining_uses.rs:11:1
    |
-LL | / fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR defining existential type use differs from previous
+LL | / fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR concrete type differs from previous
 LL | |     Some(t).into_iter()
 LL | | }
-   | |_^
+   | |_^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
    |
 note: previous use here
   --> $DIR/generic_different_defining_uses.rs:7:1
index 380fbdeb8c27ca8d18a6eb3204783a1e54188d6a..3f8753333aa7a2b77fd3000ece68ff39f3e8efd0 100644 (file)
@@ -1,9 +1,14 @@
 #![feature(existential_type)]
 
+use std::fmt::Debug;
+
 fn main() {}
 
-existential type Two<T, U>: 'static; //~ ERROR type parameter `U` is unused
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+//~^ could not find defining uses
 
-fn one<T: 'static>(t: T) -> Two<T, T> {
+fn one<T: Debug>(t: T) -> Two<T, T> {
+//~^ ERROR defining existential type use restricts existential type
     t
 }
index 66706c210541c77a27fa440328cfae4618788639..d4deda999da16b4f29925f3b6c5c7bcffe4c828d 100644 (file)
@@ -1,9 +1,17 @@
-error[E0091]: type parameter `U` is unused
-  --> $DIR/generic_duplicate_param_use.rs:5:25
+error: defining existential type use restricts existential type by using the generic parameter `T` twice
+  --> $DIR/generic_duplicate_param_use.rs:11:1
    |
-LL | existential type Two<T, U>: 'static; //~ ERROR type parameter `U` is unused
-   |                         ^ unused type parameter
+LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
+LL | | //~^ ERROR defining existential type use restricts existential type
+LL | |     t
+LL | | }
+   | |_^
 
-error: aborting due to previous error
+error: could not find defining uses
+  --> $DIR/generic_duplicate_param_use.rs:8:1
+   |
+LL | existential type Two<T, U>: Debug;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0091`.
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use10.rs b/src/test/ui/existential_types/generic_duplicate_param_use10.rs
new file mode 100644 (file)
index 0000000..10f2c63
--- /dev/null
@@ -0,0 +1,12 @@
+// compile-pass
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
+    (t, 4u32)
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use2.rs b/src/test/ui/existential_types/generic_duplicate_param_use2.rs
new file mode 100644 (file)
index 0000000..3842292
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn one<T: Debug>(t: T) -> Two<T, T> {
+//~^ defining existential type use restricts existential type
+    t
+}
+
+fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+    t
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use2.stderr b/src/test/ui/existential_types/generic_duplicate_param_use2.stderr
new file mode 100644 (file)
index 0000000..0a8be32
--- /dev/null
@@ -0,0 +1,11 @@
+error: defining existential type use restricts existential type by using the generic parameter `T` twice
+  --> $DIR/generic_duplicate_param_use2.rs:10:1
+   |
+LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
+LL | | //~^ defining existential type use restricts existential type
+LL | |     t
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use3.rs b/src/test/ui/existential_types/generic_duplicate_param_use3.rs
new file mode 100644 (file)
index 0000000..05c77c8
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn one<T: Debug>(t: T) -> Two<T, T> {
+//~^ defining existential type use restricts existential type
+    t
+}
+
+fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+    t
+}
+
+fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+//~^ concrete type's generic parameters differ from previous defining use
+    u
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use3.stderr b/src/test/ui/existential_types/generic_duplicate_param_use3.stderr
new file mode 100644 (file)
index 0000000..1c96c15
--- /dev/null
@@ -0,0 +1,28 @@
+error: defining existential type use restricts existential type by using the generic parameter `T` twice
+  --> $DIR/generic_duplicate_param_use3.rs:10:1
+   |
+LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
+LL | | //~^ defining existential type use restricts existential type
+LL | |     t
+LL | | }
+   | |_^
+
+error: concrete type's generic parameters differ from previous defining use
+  --> $DIR/generic_duplicate_param_use3.rs:19:1
+   |
+LL | / fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+LL | | //~^ concrete type's generic parameters differ from previous defining use
+LL | |     u
+LL | | }
+   | |_^ expected [`T`], got [`U`]
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use3.rs:15:1
+   |
+LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+LL | |     t
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use4.rs b/src/test/ui/existential_types/generic_duplicate_param_use4.rs
new file mode 100644 (file)
index 0000000..609dbe0
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn one<T: Debug>(t: T) -> Two<T, T> {
+//~^ ERROR defining existential type use restricts existential type
+    t
+}
+
+fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+    u
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use4.stderr b/src/test/ui/existential_types/generic_duplicate_param_use4.stderr
new file mode 100644 (file)
index 0000000..24b1caf
--- /dev/null
@@ -0,0 +1,11 @@
+error: defining existential type use restricts existential type by using the generic parameter `T` twice
+  --> $DIR/generic_duplicate_param_use4.rs:10:1
+   |
+LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
+LL | | //~^ ERROR defining existential type use restricts existential type
+LL | |     t
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use5.rs b/src/test/ui/existential_types/generic_duplicate_param_use5.rs
new file mode 100644 (file)
index 0000000..3f4a23b
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+    (t, u)
+}
+
+fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+//~^ concrete type differs from previous
+    (u, t)
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use5.stderr b/src/test/ui/existential_types/generic_duplicate_param_use5.stderr
new file mode 100644 (file)
index 0000000..1666238
--- /dev/null
@@ -0,0 +1,19 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/generic_duplicate_param_use5.rs:14:1
+   |
+LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | | //~^ concrete type differs from previous
+LL | |     (u, t)
+LL | | }
+   | |_^ expected `(T, U)`, got `(U, T)`
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use5.rs:10:1
+   |
+LL | / fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |     (t, u)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use6.rs b/src/test/ui/existential_types/generic_duplicate_param_use6.rs
new file mode 100644 (file)
index 0000000..3b8c563
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+// test that unused generic parameters are ok
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+    (t, t)
+}
+
+fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+//~^ concrete type differs from previous
+    (u, t)
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use6.stderr b/src/test/ui/existential_types/generic_duplicate_param_use6.stderr
new file mode 100644 (file)
index 0000000..da49a83
--- /dev/null
@@ -0,0 +1,19 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/generic_duplicate_param_use6.rs:14:1
+   |
+LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | | //~^ concrete type differs from previous
+LL | |     (u, t)
+LL | | }
+   | |_^ expected `(T, T)`, got `(U, T)`
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use6.rs:10:1
+   |
+LL | / fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |     (t, t)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use7.rs b/src/test/ui/existential_types/generic_duplicate_param_use7.rs
new file mode 100644 (file)
index 0000000..2bcac31
--- /dev/null
@@ -0,0 +1,25 @@
+// compile-pass
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<A, B>: Debug;
+
+fn two<T: Debug + Copy, U>(t: T, u: U) -> Two<T, U> {
+    (t, t)
+}
+
+fn three<T: Debug, U>(t: T, t2: T, u: U) -> Two<T, U> {
+    (t, t2)
+}
+
+fn four<T: Debug, U, V>(t: T, t2: T, u: U, v: V) -> Two<T, U> {
+    (t, t2)
+}
+
+fn five<X, Y: Debug>(x: X, y: Y, y2: Y) -> Two<Y, X> {
+    (y, y2)
+}
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use8.rs b/src/test/ui/existential_types/generic_duplicate_param_use8.rs
new file mode 100644 (file)
index 0000000..83501ad
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
+    (t, 4u32)
+}
+
+fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
+//~^ concrete type differs from previous
+    (u, 4u32)
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use8.stderr b/src/test/ui/existential_types/generic_duplicate_param_use8.stderr
new file mode 100644 (file)
index 0000000..80c7441
--- /dev/null
@@ -0,0 +1,19 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/generic_duplicate_param_use8.rs:13:1
+   |
+LL | / fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
+LL | | //~^ concrete type differs from previous
+LL | |     (u, 4u32)
+LL | | }
+   | |_^ expected `(T, u32)`, got `(U, u32)`
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use8.rs:9:1
+   |
+LL | / fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
+LL | |     (t, 4u32)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use9.rs b/src/test/ui/existential_types/generic_duplicate_param_use9.rs
new file mode 100644 (file)
index 0000000..4c68972
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<A, B>: Debug;
+
+trait Foo {
+    type Bar: Debug;
+    const BAR: Self::Bar;
+}
+
+fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
+    (t, u, T::BAR)
+}
+
+fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+    (t, u, 42) //~^ ERROR concrete type differs from previous
+}
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use9.stderr b/src/test/ui/existential_types/generic_duplicate_param_use9.stderr
new file mode 100644 (file)
index 0000000..a3ce480
--- /dev/null
@@ -0,0 +1,18 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/generic_duplicate_param_use9.rs:18:1
+   |
+LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |     (t, u, 42) //~^ ERROR concrete type differs from previous
+LL | | }
+   | |_^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use9.rs:14:1
+   |
+LL | / fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
+LL | |     (t, u, T::BAR)
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
index caa8f0f2ee1bcb1e7ab5c46f7d7122a2ca250a24..75af5d9570ff2ca7a4a3676719e5f710aec82c6d 100644 (file)
@@ -3,8 +3,9 @@
 fn main() {}
 
 existential type Cmp<T>: 'static;
+//~^ ERROR could not find defining uses
 
 // not a defining use, because it doesn't define *all* possible generics
-fn cmp() -> Cmp<u32> { //~ ERROR non-defining existential type use in defining scope
+fn cmp() -> Cmp<u32> { //~ ERROR defining existential type use does not fully define
     5u32
 }
index 41877791e9ae9e43c6bffa955b6f30eb1d758453..8dd88006be9c63f84eeefcbc75d8ce1d9ac15b8b 100644 (file)
@@ -1,16 +1,16 @@
-error: non-defining existential type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:8:1
+error: defining existential type use does not fully define existential type
+  --> $DIR/generic_nondefining_use.rs:9:1
    |
-LL | / fn cmp() -> Cmp<u32> { //~ ERROR non-defining existential type use in defining scope
+LL | / fn cmp() -> Cmp<u32> { //~ ERROR defining existential type use does not fully define
 LL | |     5u32
 LL | | }
    | |_^
-   |
-note: used non-generic type u32 for generic parameter
-  --> $DIR/generic_nondefining_use.rs:5:22
+
+error: could not find defining uses
+  --> $DIR/generic_nondefining_use.rs:5:1
    |
 LL | existential type Cmp<T>: 'static;
-   |                      ^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/existential_types/not_a_defining_use.rs b/src/test/ui/existential_types/not_a_defining_use.rs
new file mode 100644 (file)
index 0000000..3f81f51
--- /dev/null
@@ -0,0 +1,40 @@
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {}
+
+existential type Two<T, U>: Debug;
+
+fn two<T: Debug>(t: T) -> Two<T, u32> {
+    //~^ ERROR defining existential type use does not fully define existential type
+    (t, 4i8)
+}
+
+fn three<T: Debug, U>(t: T) -> Two<T, U> {
+    (t, 5i8)
+}
+
+trait Bar {
+    type Blub: Debug;
+    const FOO: Self::Blub;
+}
+
+impl Bar for u32 {
+    type Blub = i32;
+    const FOO: i32 = 42;
+}
+
+// this should work! But it requires `two` and `three` not to be defining uses,
+// just restricting uses
+fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> { //~ concrete type differs from previous
+    (t, <U as Bar>::FOO)
+}
+
+fn is_sync<T: Sync>() {}
+
+fn asdfl() {
+    //FIXME(oli-obk): these currently cause cycle errors
+    //is_sync::<Two<i32, u32>>();
+    //is_sync::<Two<i32, *const i32>>();
+}
diff --git a/src/test/ui/existential_types/not_a_defining_use.stderr b/src/test/ui/existential_types/not_a_defining_use.stderr
new file mode 100644 (file)
index 0000000..288a32f
--- /dev/null
@@ -0,0 +1,27 @@
+error: defining existential type use does not fully define existential type
+  --> $DIR/not_a_defining_use.rs:9:1
+   |
+LL | / fn two<T: Debug>(t: T) -> Two<T, u32> {
+LL | |     //~^ ERROR defining existential type use does not fully define existential type
+LL | |     (t, 4i8)
+LL | | }
+   | |_^
+
+error: concrete type differs from previous defining existential type use
+  --> $DIR/not_a_defining_use.rs:30:1
+   |
+LL | / fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> { //~ concrete type differs from previous
+LL | |     (t, <U as Bar>::FOO)
+LL | | }
+   | |_^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
+   |
+note: previous use here
+  --> $DIR/not_a_defining_use.rs:14:1
+   |
+LL | / fn three<T: Debug, U>(t: T) -> Two<T, U> {
+LL | |     (t, 5i8)
+LL | | }
+   | |_^
+
+error: aborting due to 2 previous errors
+
index bd7b343b402f50357cd3ee3f33a1373c9802ceb6..7af6508788129e868c5c8d6c2370762e252c53da 100644 (file)
@@ -1,15 +1,18 @@
+// compile-pass
 #![feature(existential_type)]
 
 fn main() {
 }
 
-existential type PartiallyDefined<T>: 'static; //~ `T` is unused
+// test that unused generic parameters are ok
+existential type PartiallyDefined<T>: 'static;
 
 fn partially_defined<T: std::fmt::Debug>(_: T) -> PartiallyDefined<T> {
     4u32
 }
 
-existential type PartiallyDefined2<T>: 'static; //~ `T` is unused
+// test that unused generic parameters are ok
+existential type PartiallyDefined2<T>: 'static;
 
 fn partially_defined2<T: std::fmt::Debug>(_: T) -> PartiallyDefined2<T> {
     4u32
diff --git a/src/test/ui/existential_types/unused_generic_param.stderr b/src/test/ui/existential_types/unused_generic_param.stderr
deleted file mode 100644 (file)
index 348aed3..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0091]: type parameter `T` is unused
-  --> $DIR/unused_generic_param.rs:6:35
-   |
-LL | existential type PartiallyDefined<T>: 'static; //~ `T` is unused
-   |                                   ^ unused type parameter
-
-error[E0091]: type parameter `T` is unused
-  --> $DIR/unused_generic_param.rs:12:36
-   |
-LL | existential type PartiallyDefined2<T>: 'static; //~ `T` is unused
-   |                                    ^ unused type parameter
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0091`.