From 8ba9b1019c6e6c514826c5466e84d93f665f975f Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 5 Jul 2019 16:24:58 -0400 Subject: [PATCH 1/7] Fix cycle error with existential types Fixes #61863 We now allow uses of 'existential type's that aren't defining uses - that is, uses which don't constrain the underlying concrete type. To make this work correctly, we also modify eq_opaque_type_and_type to not try to apply additional constraints to an opaque type. If we have code like this: ``` existential type Foo; fn foo1() -> Foo { ... } fn foo2() -> Foo { foo1() } ``` then 'foo2' doesn't end up constraining 'Foo', which means that 'foo2' will end up using the type 'Foo' internally - that is, an actual 'TyKind::Opaque'. We don't want to equate this to the underlying concrete type - we just need to enforce the basic equality constraint between the two types (here, the return type of 'foo1' and the return type of 'foo2') --- .../borrow_check/nll/type_check/mod.rs | 25 +++++++++- src/librustc_typeck/check/writeback.rs | 48 ++++++++++--------- src/test/run-pass/existential_type_const.rs | 17 +++++++ .../run-pass/existential_type_const.stderr | 6 +++ src/test/run-pass/existential_type_fns.rs | 25 ++++++++++ .../existential-types-with-cycle-error.rs | 2 +- .../existential-types-with-cycle-error.stderr | 24 +--------- .../existential-types-with-cycle-error2.rs | 2 +- ...existential-types-with-cycle-error2.stderr | 24 +--------- .../no_inferrable_concrete_type.rs | 6 +-- .../no_inferrable_concrete_type.stderr | 21 +------- 11 files changed, 104 insertions(+), 96 deletions(-) create mode 100644 src/test/run-pass/existential_type_const.rs create mode 100644 src/test/run-pass/existential_type_const.stderr create mode 100644 src/test/run-pass/existential_type_fns.rs diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index cdbbe1d02bd..8bc377b401e 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1253,17 +1253,38 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &anon_ty, locations.span(body), )); + + let revealed_ty_is_opaque = revealed_ty.is_impl_trait(); + debug!( "eq_opaque_type_and_type: \ instantiated output_ty={:?} \ opaque_type_map={:#?} \ - revealed_ty={:?}", - output_ty, opaque_type_map, revealed_ty + revealed_ty={:?} \ + revealed_ty_is_opaque={}", + output_ty, opaque_type_map, revealed_ty, revealed_ty_is_opaque ); obligations.add(infcx .at(&ObligationCause::dummy(), param_env) .eq(output_ty, revealed_ty)?); + // This is 'true' when we're using an existential + // type without 'revelaing' it. For example, code like this: + // + // existential type Foo: Debug; + // fn foo1() -> Foo { ... } + // fn foo2() -> Foo { foo1() } + // + // In 'foo2', we're not revealing the type of 'Foo' - we're + // just treating it as the opaque type. All of the constraints + // in our 'opaque_type_map' apply to the concrete type, + // not to the opaque type itself. Therefore, it's enough + // to simply equate the output and opque 'revealed_type', + // as we do above + if revealed_ty_is_opaque { + return Ok(InferOk { value: None, obligations: obligations.into_vec() }); + } + for (&opaque_def_id, opaque_decl) in &opaque_type_map { let opaque_defn_ty = tcx.type_of(opaque_def_id); let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs); diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index a2632b20c2e..14bd2f0fa7e 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -576,36 +576,38 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { }) }; + let mut skip_add = false; + if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.sty { 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); + debug!("Skipping adding concrete definition for opaque type {:?} {:?}", + opaque_defn, defin_ty_def_id); + skip_add = true; } } if !opaque_defn.substs.has_local_value() { - let new = ty::ResolvedOpaqueTy { - concrete_type: definition_ty, - substs: opaque_defn.substs, - }; + if !skip_add { + let new = ty::ResolvedOpaqueTy { + concrete_type: definition_ty, + substs: opaque_defn.substs, + }; - let old = self.tables - .concrete_existential_types - .insert(def_id, new); - if let Some(old) = old { - 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: {:?}, {:?}, {:?}, {:?}", - def_id, - definition_ty, - opaque_defn, - old, - ); + let old = self.tables + .concrete_existential_types + .insert(def_id, new); + if let Some(old) = old { + 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: {:?}, {:?}, {:?}, {:?}", + def_id, + definition_ty, + opaque_defn, + old, + ); + } } } } else { diff --git a/src/test/run-pass/existential_type_const.rs b/src/test/run-pass/existential_type_const.rs new file mode 100644 index 00000000000..333e15f3445 --- /dev/null +++ b/src/test/run-pass/existential_type_const.rs @@ -0,0 +1,17 @@ +#![feature(existential_type)] +#![feature(impl_trait_in_bindings)] +//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + +// Ensures that consts can constrain an existential type + +use std::fmt::Debug; + +// Type `Foo` refers to a type that implements the `Debug` trait. +// The concrete type to which `Foo` refers is inferred from this module, +// and this concrete type is hidden from outer modules (but not submodules). +pub existential type Foo: Debug; + +const _FOO: Foo = 5; + +fn main() { +} diff --git a/src/test/run-pass/existential_type_const.stderr b/src/test/run-pass/existential_type_const.stderr new file mode 100644 index 00000000000..b6d83fb1703 --- /dev/null +++ b/src/test/run-pass/existential_type_const.stderr @@ -0,0 +1,6 @@ +warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + --> $DIR/existential_type_const.rs:2:12 + | +LL | #![feature(impl_trait_in_bindings)] + | ^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/src/test/run-pass/existential_type_fns.rs b/src/test/run-pass/existential_type_fns.rs new file mode 100644 index 00000000000..e477dca9aad --- /dev/null +++ b/src/test/run-pass/existential_type_fns.rs @@ -0,0 +1,25 @@ +#![feature(existential_type)] + +// Regression test for issue #61863 + +pub trait MyTrait {} + +#[derive(Debug)] +pub struct MyStruct { + v: u64 +} + +impl MyTrait for MyStruct {} + +pub fn bla() -> TE { + return MyStruct {v:1} +} + +pub fn bla2() -> TE { + bla() +} + + +existential type TE: MyTrait; + +fn main() {} diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error.rs b/src/test/ui/existential_types/existential-types-with-cycle-error.rs index 3f0190892eb..38fcabb5cc1 100644 --- a/src/test/ui/existential_types/existential-types-with-cycle-error.rs +++ b/src/test/ui/existential_types/existential-types-with-cycle-error.rs @@ -1,7 +1,7 @@ #![feature(existential_type)] existential type Foo: Fn() -> Foo; -//~^ ERROR: cycle detected when processing `Foo` +//~^ ERROR: could not find defining uses fn crash(x: Foo) -> Foo { x diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error.stderr b/src/test/ui/existential_types/existential-types-with-cycle-error.stderr index 56057a9caa4..98a269d5271 100644 --- a/src/test/ui/existential_types/existential-types-with-cycle-error.stderr +++ b/src/test/ui/existential_types/existential-types-with-cycle-error.stderr @@ -1,30 +1,8 @@ -error[E0391]: cycle detected when processing `Foo` +error: could not find defining uses --> $DIR/existential-types-with-cycle-error.rs:3:1 | LL | existential type Foo: Fn() -> Foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires processing `crash`... - --> $DIR/existential-types-with-cycle-error.rs:6:25 - | -LL | fn crash(x: Foo) -> Foo { - | _________________________^ -LL | | x -LL | | } - | |_^ - = note: ...which again requires processing `Foo`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/existential-types-with-cycle-error.rs:1:1 - | -LL | / #![feature(existential_type)] -LL | | -LL | | existential type Foo: Fn() -> Foo; -LL | | -... | -LL | | -LL | | } - | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error2.rs b/src/test/ui/existential_types/existential-types-with-cycle-error2.rs index 29410309ef2..f9e6bdb67d4 100644 --- a/src/test/ui/existential_types/existential-types-with-cycle-error2.rs +++ b/src/test/ui/existential_types/existential-types-with-cycle-error2.rs @@ -5,7 +5,7 @@ pub trait Bar { } existential type Foo: Bar; -//~^ ERROR: cycle detected when processing `Foo` +//~^ ERROR: could not find defining uses fn crash(x: Foo) -> Foo { x diff --git a/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr b/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr index 8c7bf52470a..830305d8631 100644 --- a/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr +++ b/src/test/ui/existential_types/existential-types-with-cycle-error2.stderr @@ -1,30 +1,8 @@ -error[E0391]: cycle detected when processing `Foo` +error: could not find defining uses --> $DIR/existential-types-with-cycle-error2.rs:7:1 | LL | existential type Foo: Bar; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires processing `crash`... - --> $DIR/existential-types-with-cycle-error2.rs:10:25 - | -LL | fn crash(x: Foo) -> Foo { - | _________________________^ -LL | | x -LL | | } - | |_^ - = note: ...which again requires processing `Foo`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/existential-types-with-cycle-error2.rs:1:1 - | -LL | / #![feature(existential_type)] -LL | | -LL | | pub trait Bar { -LL | | type Item; -... | -LL | | -LL | | } - | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/existential_types/no_inferrable_concrete_type.rs b/src/test/ui/existential_types/no_inferrable_concrete_type.rs index 6bbe8bdc0cd..eec8a4be63d 100644 --- a/src/test/ui/existential_types/no_inferrable_concrete_type.rs +++ b/src/test/ui/existential_types/no_inferrable_concrete_type.rs @@ -1,9 +1,9 @@ -// Issue 52985: Cause cycle error if user code provides no use case that allows an existential type -// to be inferred to a concrete type. This results in an infinite cycle during type normalization. +// Issue 52985: user code provides no use case that allows an existential type +// We now emit a 'could not find defining uses' error #![feature(existential_type)] -existential type Foo: Copy; //~ cycle detected +existential type Foo: Copy; //~ could not find defining uses // make compiler happy about using 'Foo' fn bar(x: Foo) -> Foo { x } diff --git a/src/test/ui/existential_types/no_inferrable_concrete_type.stderr b/src/test/ui/existential_types/no_inferrable_concrete_type.stderr index 4605332ef5b..bc9a883c836 100644 --- a/src/test/ui/existential_types/no_inferrable_concrete_type.stderr +++ b/src/test/ui/existential_types/no_inferrable_concrete_type.stderr @@ -1,27 +1,8 @@ -error[E0391]: cycle detected when processing `Foo` +error: could not find defining uses --> $DIR/no_inferrable_concrete_type.rs:6:1 | LL | existential type Foo: Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires processing `bar`... - --> $DIR/no_inferrable_concrete_type.rs:9:23 - | -LL | fn bar(x: Foo) -> Foo { x } - | ^^^^^ - = note: ...which again requires processing `Foo`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/no_inferrable_concrete_type.rs:4:1 - | -LL | / #![feature(existential_type)] -LL | | -LL | | existential type Foo: Copy; -LL | | -... | -LL | | let _: Foo = std::mem::transmute(0u8); -LL | | } - | |_^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0391`. From ec626992fe40ed7752145955d2a2e60228335987 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 5 Jul 2019 18:45:56 -0400 Subject: [PATCH 2/7] Fix bug when opaque type was nested in another type. Previously, types like (Foo, u8) would not be handled correctly (where Foo is an 'existential type') --- .../borrow_check/nll/type_check/mod.rs | 63 ++++++++++--------- src/test/run-pass/existential_type_tuple.rs | 32 ++++++++++ 2 files changed, 67 insertions(+), 28 deletions(-) create mode 100644 src/test/run-pass/existential_type_tuple.rs diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 8bc377b401e..a505750b1a1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1253,51 +1253,58 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &anon_ty, locations.span(body), )); - - let revealed_ty_is_opaque = revealed_ty.is_impl_trait(); - debug!( "eq_opaque_type_and_type: \ instantiated output_ty={:?} \ opaque_type_map={:#?} \ - revealed_ty={:?} \ - revealed_ty_is_opaque={}", - output_ty, opaque_type_map, revealed_ty, revealed_ty_is_opaque + revealed_ty={:?}", + output_ty, opaque_type_map, revealed_ty ); obligations.add(infcx .at(&ObligationCause::dummy(), param_env) .eq(output_ty, revealed_ty)?); - // This is 'true' when we're using an existential - // type without 'revelaing' it. For example, code like this: - // - // existential type Foo: Debug; - // fn foo1() -> Foo { ... } - // fn foo2() -> Foo { foo1() } - // - // In 'foo2', we're not revealing the type of 'Foo' - we're - // just treating it as the opaque type. All of the constraints - // in our 'opaque_type_map' apply to the concrete type, - // not to the opaque type itself. Therefore, it's enough - // to simply equate the output and opque 'revealed_type', - // as we do above - if revealed_ty_is_opaque { - return Ok(InferOk { value: None, obligations: obligations.into_vec() }); - } - for (&opaque_def_id, opaque_decl) in &opaque_type_map { let opaque_defn_ty = tcx.type_of(opaque_def_id); let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs); let opaque_defn_ty = renumber::renumber_regions(infcx, &opaque_defn_ty); + let concrete_is_opaque = infcx + .resolve_vars_if_possible(&opaque_decl.concrete_ty).is_impl_trait(); + debug!( - "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}", + "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?} \ + concrete_is_opaque={}", opaque_decl.concrete_ty, infcx.resolve_vars_if_possible(&opaque_decl.concrete_ty), - opaque_defn_ty + opaque_defn_ty, + concrete_is_opaque ); - obligations.add(infcx - .at(&ObligationCause::dummy(), param_env) - .eq(opaque_decl.concrete_ty, opaque_defn_ty)?); + + // concrete_is_opaque is 'true' when we're using an existential + // type without 'revelaing' it. For example, code like this: + // + // existential type Foo: Debug; + // fn foo1() -> Foo { ... } + // fn foo2() -> Foo { foo1() } + // + // In 'foo2', we're not revealing the type of 'Foo' - we're + // just treating it as the opaque type. + // + // When this occurs, we do *not* want to try to equate + // the concrete type with the underlying defining type + // of the existential type - this will always fail, since + // the defining type of an existential type is always + // some other type (e.g. not itself) + // Essentially, none of the normal obligations apply here - + // we're just passing around some unknown opaque type, + // without actually looking at the underlying type it + // gets 'revealed' into + + if !concrete_is_opaque { + obligations.add(infcx + .at(&ObligationCause::dummy(), param_env) + .eq(opaque_decl.concrete_ty, opaque_defn_ty)?); + } } debug!("eq_opaque_type_and_type: equated"); diff --git a/src/test/run-pass/existential_type_tuple.rs b/src/test/run-pass/existential_type_tuple.rs new file mode 100644 index 00000000000..31c145ea89a --- /dev/null +++ b/src/test/run-pass/existential_type_tuple.rs @@ -0,0 +1,32 @@ +#![feature(existential_type)] + +#![allow(dead_code)] + +pub trait MyTrait {} + +impl MyTrait for bool {} + +struct Blah { + my_foo: Foo, + my_u8: u8 +} + +impl Blah { + fn new() -> Blah { + Blah { + my_foo: make_foo(), + my_u8: 12 + } + } + fn into_inner(self) -> (Foo, u8) { + (self.my_foo, self.my_u8) + } +} + +fn make_foo() -> Foo { + true +} + +existential type Foo: MyTrait; + +fn main() {} From 2f051605f3f5bacfbb66ece3ecfcacd048d38b5b Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 5 Jul 2019 18:53:34 -0400 Subject: [PATCH 3/7] Remove unecessary doc comment --- src/test/run-pass/existential_type_const.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/run-pass/existential_type_const.rs b/src/test/run-pass/existential_type_const.rs index 333e15f3445..f8b66167967 100644 --- a/src/test/run-pass/existential_type_const.rs +++ b/src/test/run-pass/existential_type_const.rs @@ -6,9 +6,6 @@ use std::fmt::Debug; -// Type `Foo` refers to a type that implements the `Debug` trait. -// The concrete type to which `Foo` refers is inferred from this module, -// and this concrete type is hidden from outer modules (but not submodules). pub existential type Foo: Debug; const _FOO: Foo = 5; From 2ab8d618823a51f347407cf7299110ad42f26616 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 5 Jul 2019 18:59:11 -0400 Subject: [PATCH 4/7] s/consts/`const` items/ Co-Authored-By: Mazdak Farrokhzad --- src/test/run-pass/existential_type_const.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-pass/existential_type_const.rs b/src/test/run-pass/existential_type_const.rs index f8b66167967..1f80475cb77 100644 --- a/src/test/run-pass/existential_type_const.rs +++ b/src/test/run-pass/existential_type_const.rs @@ -2,7 +2,7 @@ #![feature(impl_trait_in_bindings)] //~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash -// Ensures that consts can constrain an existential type +// Ensures that `const` items can constrain an `existential type`. use std::fmt::Debug; From 36008327cc3214afaf5ce5bacdf2fdf236422caf Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 5 Jul 2019 19:10:29 -0400 Subject: [PATCH 5/7] Address review comments --- src/librustc_mir/borrow_check/nll/type_check/mod.rs | 6 +++--- src/librustc_typeck/check/writeback.rs | 5 +++++ .../existential_types}/existential_type_const.rs | 2 ++ .../existential_types}/existential_type_const.stderr | 0 .../existential_types}/existential_type_fns.rs | 2 ++ .../existential_types}/existential_type_tuple.rs | 3 ++- 6 files changed, 14 insertions(+), 4 deletions(-) rename src/test/{run-pass => ui/existential_types}/existential_type_const.rs (95%) rename src/test/{run-pass => ui/existential_types}/existential_type_const.stderr (100%) rename src/test/{run-pass => ui/existential_types}/existential_type_fns.rs (95%) rename src/test/{run-pass => ui/existential_types}/existential_type_tuple.rs (96%) diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a505750b1a1..1194872c0af 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1280,14 +1280,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { concrete_is_opaque ); - // concrete_is_opaque is 'true' when we're using an existential - // type without 'revelaing' it. For example, code like this: + // concrete_is_opaque is `true` when we're using an existential + // type without 'revealing' it. For example, code like this: // // existential type Foo: Debug; // fn foo1() -> Foo { ... } // fn foo2() -> Foo { foo1() } // - // In 'foo2', we're not revealing the type of 'Foo' - we're + // In `foo2`, we're not revealing the type of `Foo` - we're // just treating it as the opaque type. // // When this occurs, we do *not* want to try to equate diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 14bd2f0fa7e..831f9daa52d 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -587,6 +587,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } if !opaque_defn.substs.has_local_value() { + // We only want to add an entry into `concrete_existential_types` + // if we actually found a defining usage of this existential type. + // Otherwise, we do nothing - we'll either find a defining usage + // in some other location, or we'll end up emitting an error due + // to the lack of defining usage if !skip_add { let new = ty::ResolvedOpaqueTy { concrete_type: definition_ty, diff --git a/src/test/run-pass/existential_type_const.rs b/src/test/ui/existential_types/existential_type_const.rs similarity index 95% rename from src/test/run-pass/existential_type_const.rs rename to src/test/ui/existential_types/existential_type_const.rs index 1f80475cb77..55920b85dd7 100644 --- a/src/test/run-pass/existential_type_const.rs +++ b/src/test/ui/existential_types/existential_type_const.rs @@ -1,3 +1,5 @@ +// check-pass + #![feature(existential_type)] #![feature(impl_trait_in_bindings)] //~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash diff --git a/src/test/run-pass/existential_type_const.stderr b/src/test/ui/existential_types/existential_type_const.stderr similarity index 100% rename from src/test/run-pass/existential_type_const.stderr rename to src/test/ui/existential_types/existential_type_const.stderr diff --git a/src/test/run-pass/existential_type_fns.rs b/src/test/ui/existential_types/existential_type_fns.rs similarity index 95% rename from src/test/run-pass/existential_type_fns.rs rename to src/test/ui/existential_types/existential_type_fns.rs index e477dca9aad..6f22eef2849 100644 --- a/src/test/run-pass/existential_type_fns.rs +++ b/src/test/ui/existential_types/existential_type_fns.rs @@ -1,3 +1,5 @@ +// check-pass + #![feature(existential_type)] // Regression test for issue #61863 diff --git a/src/test/run-pass/existential_type_tuple.rs b/src/test/ui/existential_types/existential_type_tuple.rs similarity index 96% rename from src/test/run-pass/existential_type_tuple.rs rename to src/test/ui/existential_types/existential_type_tuple.rs index 31c145ea89a..0f134a52897 100644 --- a/src/test/run-pass/existential_type_tuple.rs +++ b/src/test/ui/existential_types/existential_type_tuple.rs @@ -1,5 +1,6 @@ -#![feature(existential_type)] +// check-pass +#![feature(existential_type)] #![allow(dead_code)] pub trait MyTrait {} From 66b2b97e0774f50f9ba4de3c8806559ce787fe37 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 5 Jul 2019 20:06:41 -0400 Subject: [PATCH 6/7] Fix test stderr --- src/test/ui/existential_types/existential_type_const.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/existential_types/existential_type_const.stderr b/src/test/ui/existential_types/existential_type_const.stderr index b6d83fb1703..3499b6e20d5 100644 --- a/src/test/ui/existential_types/existential_type_const.stderr +++ b/src/test/ui/existential_types/existential_type_const.stderr @@ -1,5 +1,5 @@ warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash - --> $DIR/existential_type_const.rs:2:12 + --> $DIR/existential_type_const.rs:4:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ From 2f4196205336df8550a4bfb3045d3d1c350f02bf Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 5 Jul 2019 20:15:31 -0400 Subject: [PATCH 7/7] Add explanation to 'existential_type_const' test --- src/test/ui/existential_types/existential_type_const.rs | 4 ++++ src/test/ui/existential_types/existential_type_const.stderr | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/ui/existential_types/existential_type_const.rs b/src/test/ui/existential_types/existential_type_const.rs index 55920b85dd7..646e9a73424 100644 --- a/src/test/ui/existential_types/existential_type_const.rs +++ b/src/test/ui/existential_types/existential_type_const.rs @@ -1,6 +1,10 @@ // check-pass #![feature(existential_type)] +// Currently, the `existential_type` feature implicitly +// depends on `impl_trait_in_bindings` in order to work properly. +// Specifically, this line requires `impl_trait_in_bindings` to be enabled: +// https://github.com/rust-lang/rust/blob/481068a707679257e2a738b40987246e0420e787/src/librustc_typeck/check/mod.rs#L856 #![feature(impl_trait_in_bindings)] //~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash diff --git a/src/test/ui/existential_types/existential_type_const.stderr b/src/test/ui/existential_types/existential_type_const.stderr index 3499b6e20d5..049b4f75dd2 100644 --- a/src/test/ui/existential_types/existential_type_const.stderr +++ b/src/test/ui/existential_types/existential_type_const.stderr @@ -1,5 +1,5 @@ warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash - --> $DIR/existential_type_const.rs:4:12 + --> $DIR/existential_type_const.rs:8:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^