From 2ad3fcb1a68c6f62c74a6aa6de096f691dbb7a95 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 16:47:26 +0100 Subject: [PATCH 01/12] Remove a wrong multiplier on relocation offset computation --- src/librustc_mir/interpret/memory.rs | 8 ++++---- src/test/ui/consts/promoted_regression.rs | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/consts/promoted_regression.rs diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 97d7e1586b811..f296e69d82265 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -707,10 +707,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations.extend( relocations .iter() - .map(|&(offset, reloc)| { - (offset + dest.offset - src.offset + (i * size * relocations.len() as u64), - reloc) - }) + .map(|&(offset, reloc)| ( + offset + dest.offset - src.offset + (i * size), + reloc, + )) ); } diff --git a/src/test/ui/consts/promoted_regression.rs b/src/test/ui/consts/promoted_regression.rs new file mode 100644 index 0000000000000..68b9a20ecf90b --- /dev/null +++ b/src/test/ui/consts/promoted_regression.rs @@ -0,0 +1,9 @@ +// compile-pass + +fn main() { + let _ = &[("", ""); 3]; +} + +const FOO: &[(&str, &str)] = &[("", ""); 3]; +const BAR: &[(&str, &str); 5] = &[("", ""); 5]; +const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11]; From 11ebef97eaf7cf5d6927559a6103b61becaf8308 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 18 Dec 2018 10:08:37 +0100 Subject: [PATCH 02/12] Explain the math --- src/librustc_mir/interpret/memory.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index f296e69d82265..1260fdab64d0a 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -707,10 +707,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations.extend( relocations .iter() - .map(|&(offset, reloc)| ( - offset + dest.offset - src.offset + (i * size), - reloc, - )) + .map(|&(offset, reloc)| { + // compute offset for current repetition + let dest_offset = dest.offset + (i * size); + ( + // shift offsets from source allocation to destination allocation + offset + dest_offset - src.offset, + reloc, + ) + }) ); } From a4968a72ef3ac2ace13511268d31afaeb3b78637 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 14:20:42 +0100 Subject: [PATCH 03/12] Fix a recently introduces regression --- src/librustc_mir/transform/qualify_consts.rs | 2 +- .../consts/static_mut_containing_mut_ref.rs | 7 +++++++ .../consts/static_mut_containing_mut_ref2.rs | 8 ++++++++ .../static_mut_containing_mut_ref2.stderr | 9 +++++++++ src/test/ui/write-to-static-mut-in-static.rs | 4 ++-- .../ui/write-to-static-mut-in-static.stderr | 20 ++++++++++++++++--- 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref2.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref2.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index bcee6d75b5a4a..bc0feb166ae1b 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -517,7 +517,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Only allow statics (not consts) to refer to other statics. if self.mode == Mode::Static || self.mode == Mode::StaticMut { - if context.is_mutating_use() { + if self.mode == Mode::Static && context.is_mutating_use() { // this is not strictly necessary as miri will also bail out // For interior mutability we can't really catch this statically as that // goes through raw pointers and intermediate temporaries, so miri has diff --git a/src/test/ui/consts/static_mut_containing_mut_ref.rs b/src/test/ui/consts/static_mut_containing_mut_ref.rs new file mode 100644 index 0000000000000..27e1a111163b1 --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref.rs @@ -0,0 +1,7 @@ +// compile-pass + +static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42]; + +pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE }; + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs new file mode 100644 index 0000000000000..aa9bfb4aeab2d --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -0,0 +1,8 @@ +#![feature(const_let)] + +static mut STDERR_BUFFER_SPACE: u8 = 0; + +pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; +//~^ references in statics may only refer to immutable values + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr new file mode 100644 index 0000000000000..72923431c90ed --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr @@ -0,0 +1,9 @@ +error[E0017]: references in statics may only refer to immutable values + --> $DIR/static_mut_containing_mut_ref2.rs:5:46 + | +LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0017`. diff --git a/src/test/ui/write-to-static-mut-in-static.rs b/src/test/ui/write-to-static-mut-in-static.rs index 191f09b54ee73..983b5d48e60fc 100644 --- a/src/test/ui/write-to-static-mut-in-static.rs +++ b/src/test/ui/write-to-static-mut-in-static.rs @@ -12,10 +12,10 @@ pub static mut A: u32 = 0; pub static mut B: () = unsafe { A = 1; }; -//~^ ERROR cannot mutate statics in the initializer of another static +//~^ ERROR could not evaluate static initializer pub static mut C: u32 = unsafe { C = 1; 0 }; -//~^ ERROR cannot mutate statics in the initializer of another static +//~^ ERROR cycle detected pub static D: u32 = D; diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr index 673a71b4642f3..335f849fb2472 100644 --- a/src/test/ui/write-to-static-mut-in-static.stderr +++ b/src/test/ui/write-to-static-mut-in-static.stderr @@ -1,14 +1,28 @@ -error: cannot mutate statics in the initializer of another static +error[E0080]: could not evaluate static initializer --> $DIR/write-to-static-mut-in-static.rs:14:33 | LL | pub static mut B: () = unsafe { A = 1; }; - | ^^^^^ + | ^^^^^ tried to modify a static's initial value from another static's initializer -error: cannot mutate statics in the initializer of another static +error[E0391]: cycle detected when const-evaluating `C` --> $DIR/write-to-static-mut-in-static.rs:17:34 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^ + | +note: ...which requires const-evaluating `C`... + --> $DIR/write-to-static-mut-in-static.rs:17:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating `C`, completing the cycle +note: cycle used when const-evaluating + checking `C` + --> $DIR/write-to-static-mut-in-static.rs:17:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors +Some errors occurred: E0080, E0391. +For more information about an error, try `rustc --explain E0080`. From f6f28d89e221fc03c021cf079816da0fc6ac07dc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 14:36:10 +0100 Subject: [PATCH 04/12] Also test projections --- src/test/ui/consts/static_mut_containing_mut_ref2.rs | 2 +- src/test/ui/consts/static_mut_containing_mut_ref3.rs | 8 ++++++++ src/test/ui/consts/static_mut_containing_mut_ref3.stderr | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref3.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref3.stderr diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index aa9bfb4aeab2d..aeb69b2652cbf 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -3,6 +3,6 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; -//~^ references in statics may only refer to immutable values +//~^ ERROR references in statics may only refer to immutable values fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.rs b/src/test/ui/consts/static_mut_containing_mut_ref3.rs new file mode 100644 index 0000000000000..0bc7faa9afdec --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref3.rs @@ -0,0 +1,8 @@ +#![feature(const_let)] + +static mut FOO: (u8, u8) = (42, 43); + +static mut BAR: () = unsafe { FOO.0 = 99; }; +//~^ ERROR could not evaluate static initializer + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.stderr b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr new file mode 100644 index 0000000000000..cae53c6fee9dd --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/static_mut_containing_mut_ref3.rs:5:31 + | +LL | static mut BAR: () = unsafe { FOO.0 = 99; }; + | ^^^^^^^^^^ tried to modify a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From e5126cfcc91b043d334b0849c60e6a4a80f6b674 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 21 Dec 2018 13:39:45 +0100 Subject: [PATCH 05/12] Update tests to changes on master --- src/test/ui/consts/static_mut_containing_mut_ref2.rs | 1 + .../ui/consts/static_mut_containing_mut_ref2.stderr | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index aeb69b2652cbf..4180b1e295ab0 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -4,5 +4,6 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; //~^ ERROR references in statics may only refer to immutable values +//~| ERROR static contains unimplemented expression type fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr index 72923431c90ed..f0ae1545056b7 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr @@ -4,6 +4,13 @@ error[E0017]: references in statics may only refer to immutable values LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error: aborting due to previous error +error[E0019]: static contains unimplemented expression type + --> $DIR/static_mut_containing_mut_ref2.rs:5:45 + | +LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0017`. +Some errors occurred: E0017, E0019. +For more information about an error, try `rustc --explain E0017`. From 55242502f015d1952ff49a779173dc0815ab9918 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 16 Dec 2018 00:00:46 +0200 Subject: [PATCH 06/12] fix trait objects with a Self-having projection va This follows ALT2 in the issue. Fixes #56288. --- src/librustc/traits/object_safety.rs | 21 +++++++++++++- src/librustc_typeck/astconv.rs | 28 +++++++++++++++++-- ...ject-with-self-in-projection-output-bad.rs | 22 +++++++++++++++ ...-with-self-in-projection-output-bad.stderr | 12 ++++++++ ...ect-with-self-in-projection-output-good.rs | 23 +++++++++++++++ 5 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs create mode 100644 src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr create mode 100644 src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 2909daf22b3ba..a9afe755c1466 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -190,7 +190,26 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { // In the case of a trait predicate, we can skip the "self" type. data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty()) } - ty::Predicate::Projection(..) | + ty::Predicate::Projection(ref data) => { + // And similarly for projections. This should be redundant with + // the previous check because any projection should have a + // matching `Trait` predicate with the same inputs, but we do + // the check to be safe. + // + // Note that we *do* allow projection *outputs* to contain + // `self` (i.e., `trait Foo: Bar { type Result; }`), + // we just require the user to specify *both* outputs + // in the object type (i.e., `dyn Foo`). + // + // This is ALT2 in issue #56288, see that for discussion of the + // possible alternatives. + data.skip_binder() + .projection_ty + .trait_ref(self) + .input_types() + .skip(1) + .any(|t| t.has_self_ty()) + } ty::Predicate::WellFormed(..) | ty::Predicate::ObjectSafe(..) | ty::Predicate::TypeOutlives(..) | diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4fbbe58445254..dd9b9cea615d7 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1013,6 +1013,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { let mut associated_types = BTreeSet::default(); for tr in traits::elaborate_trait_ref(tcx, principal) { + debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr); match tr { ty::Predicate::Trait(pred) => { associated_types.extend(tcx.associated_items(pred.def_id()) @@ -1020,8 +1021,31 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o { .map(|item| item.def_id)); } ty::Predicate::Projection(pred) => { - // Include projections defined on supertraits. - projection_bounds.push((pred, DUMMY_SP)) + // A `Self` within the original bound will be substituted with a + // `TRAIT_OBJECT_DUMMY_SELF`, so check for that. + let references_self = + pred.skip_binder().ty.walk().any(|t| t == dummy_self); + + // If the projection output contains `Self`, force the user to + // elaborate it explicitly to avoid a bunch of complexity. + // + // The "classicaly useful" case is the following: + // ``` + // trait MyTrait: FnMut() -> ::MyOutput { + // type MyOutput; + // } + // ``` + // + // Here, the user could theoretically write `dyn MyTrait`, + // but actually supporting that would "expand" to an infinitely-long type + // `fix $ τ → dyn MyTrait::MyOutput`. + // + // Instead, we force the user to write `dyn MyTrait`, + // which is uglier but works. See the discussion in #56288 for alternatives. + if !references_self { + // Include projections defined on supertraits, + projection_bounds.push((pred, DUMMY_SP)) + } } _ => () } diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs new file mode 100644 index 0000000000000..b157ef6ed5d99 --- /dev/null +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs @@ -0,0 +1,22 @@ +trait Base { + type Output; +} + +trait Helper: Base::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from the trait `Base`) must be specified +} diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr new file mode 100644 index 0000000000000..c2e274b0245f7 --- /dev/null +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr @@ -0,0 +1,12 @@ +error[E0191]: the value of the associated type `Output` (from the trait `Base`) must be specified + --> $DIR/trait-object-with-self-in-projection-output-bad.rs:20:17 + | +LL | type Output; + | ------------ `Output` defined here +... +LL | let _x: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs new file mode 100644 index 0000000000000..07681086e16ef --- /dev/null +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs @@ -0,0 +1,23 @@ +// compile-pass + +trait Base { + type Output; +} + +trait Helper: Base::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box> = Box::new(2u32); +} From 64abe6954adbefbf379fc2dc21cff7d448b8e8d8 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 18 Dec 2018 00:33:21 +0200 Subject: [PATCH 07/12] improve tests as suggested by review comments --- ...ject-with-self-in-projection-output-bad.rs | 28 +++++++++++ ...-with-self-in-projection-output-bad.stderr | 13 ++++- ...ect-with-self-in-projection-output-good.rs | 5 ++ ...n-projection-output-repeated-supertrait.rs | 48 +++++++++++++++++++ 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs index b157ef6ed5d99..766bd147431b4 100644 --- a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.rs @@ -1,3 +1,7 @@ +// Regression test for #56288. Checks that if a supertrait defines an associated type +// projection that references `Self`, then that associated type must still be explicitly +// specified in the `dyn Trait` variant, since we don't know what `Self` is anymore. + trait Base { type Output; } @@ -16,7 +20,31 @@ impl Helper for u32 type Target = i32; } +trait ConstI32 { + type Out; +} + +impl ConstI32 for T { + type Out = i32; +} + +// Test that you still need to manually give a projection type if the Output type +// is normalizable. +trait NormalizableHelper: + Base::Out> +{ + type Target; +} + +impl NormalizableHelper for u32 +{ + type Target = i32; +} + fn main() { let _x: Box> = Box::new(2u32); //~^ ERROR the value of the associated type `Output` (from the trait `Base`) must be specified + + let _y: Box> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from the trait `Base`) must be specified } diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr index c2e274b0245f7..350f8ea850709 100644 --- a/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-bad.stderr @@ -1,5 +1,5 @@ error[E0191]: the value of the associated type `Output` (from the trait `Base`) must be specified - --> $DIR/trait-object-with-self-in-projection-output-bad.rs:20:17 + --> $DIR/trait-object-with-self-in-projection-output-bad.rs:45:17 | LL | type Output; | ------------ `Output` defined here @@ -7,6 +7,15 @@ LL | type Output; LL | let _x: Box> = Box::new(2u32); | ^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified -error: aborting due to previous error +error[E0191]: the value of the associated type `Output` (from the trait `Base`) must be specified + --> $DIR/trait-object-with-self-in-projection-output-bad.rs:48:17 + | +LL | type Output; + | ------------ `Output` defined here +... +LL | let _y: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` must be specified + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0191`. diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs index 07681086e16ef..793d556d08ca2 100644 --- a/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs @@ -1,5 +1,10 @@ // compile-pass +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` can be ok if it is referencing a projection (of +// `Self::Target`, in this case). Note that we still require the user to manually +// specify both `Target` and `Output` for now. + trait Base { type Output; } diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs new file mode 100644 index 0000000000000..46c083f930591 --- /dev/null +++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs @@ -0,0 +1,48 @@ +// compile-pass + +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` is ok if there is another occurence of +// the same supertrait that specifies the projection explicitly, even if +// the projection's associated type is not explicitly specified in the object type. +// +// Note that in order for this to compile, we need the `Self`-referencing projection +// to normalize fairly directly to a concrete type, otherwise the trait resolver +// will hate us. +// +// There is a test in `trait-object-with-self-in-projection-output-bad.rs` that +// having a normalizing, but `Self`-containing projection does not *by itself* +// allow you to avoid writing the projected type (`Output`, in this example) +// explicitly. + +trait ConstI32 { + type Out; +} + +impl ConstI32 for T { + type Out = i32; +} + +trait Base { + type Output; +} + +trait NormalizingHelper: Base::Out> + Base { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl NormalizingHelper for u32 +{ + type Target = i32; +} + +fn main() { + // Make sure this works both with and without the associated type + // being specified. + let _x: Box> = Box::new(2u32); + let _y: Box> = Box::new(2u32); +} From e3a4e97822db1666d9d8affedfa3b97c8ce446e8 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 11 Dec 2018 00:05:35 +0000 Subject: [PATCH 08/12] Fixed issue #56199. --- src/librustc/ty/mod.rs | 84 +++++++++++++++++---------- src/librustc_typeck/check/callee.rs | 2 +- src/librustc_typeck/check/mod.rs | 67 ++++++++++++++------- src/test/ui/issues/issue-56199.rs | 23 ++++++++ src/test/ui/issues/issue-56199.stderr | 30 ++++++++++ 5 files changed, 151 insertions(+), 55 deletions(-) create mode 100644 src/test/ui/issues/issue-56199.rs create mode 100644 src/test/ui/issues/issue-56199.stderr diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4633ab1166347..c3bb1afd98f23 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1754,17 +1754,19 @@ bitflags! { pub struct AdtFlags: u32 { const NO_ADT_FLAGS = 0; const IS_ENUM = 1 << 0; - const IS_PHANTOM_DATA = 1 << 1; - const IS_FUNDAMENTAL = 1 << 2; - const IS_UNION = 1 << 3; - const IS_BOX = 1 << 4; + const IS_UNION = 1 << 1; + const IS_STRUCT = 1 << 2; + const IS_TUPLE_STRUCT = 1 << 3; + const IS_PHANTOM_DATA = 1 << 4; + const IS_FUNDAMENTAL = 1 << 5; + const IS_BOX = 1 << 6; /// Indicates whether the type is an `Arc`. - const IS_ARC = 1 << 5; + const IS_ARC = 1 << 7; /// Indicates whether the type is an `Rc`. - const IS_RC = 1 << 6; + const IS_RC = 1 << 8; /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`. /// (i.e., this flag is never set unless this ADT is an enum). - const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 7; + const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 9; } } @@ -2079,31 +2081,43 @@ impl<'a, 'gcx, 'tcx> AdtDef { repr: ReprOptions) -> Self { debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); let mut flags = AdtFlags::NO_ADT_FLAGS; + + if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") { + debug!("found non-exhaustive variant list for {:?}", did); + flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; + } + flags |= match kind { + AdtKind::Enum => AdtFlags::IS_ENUM, + AdtKind::Union => AdtFlags::IS_UNION, + AdtKind::Struct => AdtFlags::IS_STRUCT, + }; + + if let AdtKind::Struct = kind { + let variant_def = &variants[VariantIdx::new(0)]; + let def_key = tcx.def_key(variant_def.did); + match def_key.disambiguated_data.data { + DefPathData::StructCtor => flags |= AdtFlags::IS_TUPLE_STRUCT, + _ => (), + } + } + let attrs = tcx.get_attrs(did); if attr::contains_name(&attrs, "fundamental") { - flags = flags | AdtFlags::IS_FUNDAMENTAL; + flags |= AdtFlags::IS_FUNDAMENTAL; } if Some(did) == tcx.lang_items().phantom_data() { - flags = flags | AdtFlags::IS_PHANTOM_DATA; + flags |= AdtFlags::IS_PHANTOM_DATA; } if Some(did) == tcx.lang_items().owned_box() { - flags = flags | AdtFlags::IS_BOX; + flags |= AdtFlags::IS_BOX; } if Some(did) == tcx.lang_items().arc() { - flags = flags | AdtFlags::IS_ARC; + flags |= AdtFlags::IS_ARC; } if Some(did) == tcx.lang_items().rc() { - flags = flags | AdtFlags::IS_RC; - } - if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") { - debug!("found non-exhaustive variant list for {:?}", did); - flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; - } - match kind { - AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM, - AdtKind::Union => flags = flags | AdtFlags::IS_UNION, - AdtKind::Struct => {} + flags |= AdtFlags::IS_RC; } + AdtDef { did, variants, @@ -2114,25 +2128,31 @@ impl<'a, 'gcx, 'tcx> AdtDef { #[inline] pub fn is_struct(&self) -> bool { - !self.is_union() && !self.is_enum() + self.flags.contains(AdtFlags::IS_STRUCT) + } + + /// If this function returns `true`, it implies that `is_struct` must return `true`. + #[inline] + pub fn is_tuple_struct(&self) -> bool { + self.flags.contains(AdtFlags::IS_TUPLE_STRUCT) } #[inline] pub fn is_union(&self) -> bool { - self.flags.intersects(AdtFlags::IS_UNION) + self.flags.contains(AdtFlags::IS_UNION) } #[inline] pub fn is_enum(&self) -> bool { - self.flags.intersects(AdtFlags::IS_ENUM) + self.flags.contains(AdtFlags::IS_ENUM) } #[inline] pub fn is_variant_list_non_exhaustive(&self) -> bool { - self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) + self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) } - /// Returns the kind of the ADT - Struct or Enum. + /// Returns the kind of the ADT. #[inline] pub fn adt_kind(&self) -> AdtKind { if self.is_enum() { @@ -2161,33 +2181,33 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } - /// Returns whether this type is #[fundamental] for the purposes + /// Returns whether this type is `#[fundamental]` for the purposes /// of coherence checking. #[inline] pub fn is_fundamental(&self) -> bool { - self.flags.intersects(AdtFlags::IS_FUNDAMENTAL) + self.flags.contains(AdtFlags::IS_FUNDAMENTAL) } /// Returns `true` if this is PhantomData. #[inline] pub fn is_phantom_data(&self) -> bool { - self.flags.intersects(AdtFlags::IS_PHANTOM_DATA) + self.flags.contains(AdtFlags::IS_PHANTOM_DATA) } /// Returns `true` if this is `Arc`. pub fn is_arc(&self) -> bool { - self.flags.intersects(AdtFlags::IS_ARC) + self.flags.contains(AdtFlags::IS_ARC) } /// Returns `true` if this is `Rc`. pub fn is_rc(&self) -> bool { - self.flags.intersects(AdtFlags::IS_RC) + self.flags.contains(AdtFlags::IS_RC) } /// Returns `true` if this is Box. #[inline] pub fn is_box(&self) -> bool { - self.flags.intersects(AdtFlags::IS_BOX) + self.flags.contains(AdtFlags::IS_BOX) } /// Returns whether this type has a destructor. diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7a71cf57a2f27..3ed1ab21e817f 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::Local(id) | Def::Upvar(id, ..) => { Some(self.tcx.hir.span(id)) } - _ => self.tcx.hir.span_if_local(def.def_id()) + _ => def.opt_def_id().and_then(|did| self.tcx.hir.span_if_local(did)), }; if let Some(span) = def_span { let label = match (unit_variant, inner_callee_path) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a107cec9ef41b..57d808d9d78fa 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -98,7 +98,8 @@ use rustc::mir::interpret::{ConstValue, GlobalId}; use rustc::ty::subst::{CanonicalUserSubsts, UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; -use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind}; +use rustc::ty::{self, AdtKind, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, + RegionKind}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::query::Providers; @@ -3222,8 +3223,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return_expr_ty); } - // A generic function for checking the then and else in an if - // or if-else. + // A generic function for checking the 'then' and 'else' clauses in an 'if' + // or 'if-else' expression. fn check_then_else(&self, cond_expr: &'gcx hir::Expr, then_expr: &'gcx hir::Expr, @@ -3548,8 +3549,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // we don't look at stability attributes on // struct-like enums (yet...), but it's definitely not - // a bug to have construct one. - if adt_kind != ty::AdtKind::Enum { + // a bug to have constructed one. + if adt_kind != AdtKind::Enum { tcx.check_stability(v_field.did, Some(expr_id), field.span); } @@ -5161,26 +5162,48 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }).unwrap_or(false); let mut new_def = def; - let (def_id, ty) = if let Def::SelfCtor(impl_def_id) = def { - let ty = self.impl_self_ty(span, impl_def_id).ty; - - match ty.ty_adt_def() { - Some(adt_def) if adt_def.is_struct() => { - let variant = adt_def.non_enum_variant(); - new_def = Def::StructCtor(variant.did, variant.ctor_kind); - (variant.did, self.tcx.type_of(variant.did)) - } - _ => { - (impl_def_id, self.tcx.types.err) + let (def_id, ty) = match def { + Def::SelfCtor(impl_def_id) => { + let ty = self.impl_self_ty(span, impl_def_id).ty; + let adt_def = ty.ty_adt_def(); + + match adt_def { + Some(adt_def) if adt_def.is_tuple_struct() => { + let variant = adt_def.non_enum_variant(); + new_def = Def::StructCtor(variant.did, variant.ctor_kind); + (variant.did, self.tcx.type_of(variant.did)) + } + _ => { + let mut err = self.tcx.sess.struct_span_err(span, + "the `Self` constructor can only be used with tuple or unit structs"); + if let Some(adt_def) = adt_def { + match adt_def.adt_kind() { + AdtKind::Enum => { + err.note("did you mean to use one of the enum's variants?"); + }, + AdtKind::Union => {}, + AdtKind::Struct => { + err.span_label( + span, + format!("did you mean `Self {{ /* fields */ }}`?"), + ); + } + } + } + err.emit(); + + (impl_def_id, self.tcx.types.err) + } } } - } else { - let def_id = def.def_id(); + _ => { + let def_id = def.def_id(); - // The things we are substituting into the type should not contain - // escaping late-bound regions, and nor should the base type scheme. - let ty = self.tcx.type_of(def_id); - (def_id, ty) + // The things we are substituting into the type should not contain + // escaping late-bound regions, and nor should the base type scheme. + let ty = self.tcx.type_of(def_id); + (def_id, ty) + } }; let substs = AstConv::create_substs_for_generic_args( diff --git a/src/test/ui/issues/issue-56199.rs b/src/test/ui/issues/issue-56199.rs new file mode 100644 index 0000000000000..bbd51823cf1af --- /dev/null +++ b/src/test/ui/issues/issue-56199.rs @@ -0,0 +1,23 @@ + +enum Foo {} +struct Bar {} + +impl Foo { + fn foo() { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple structs + } +} + +impl Bar { + fn bar() { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple structs + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-56199.stderr b/src/test/ui/issues/issue-56199.stderr new file mode 100644 index 0000000000000..feb88e926b2d8 --- /dev/null +++ b/src/test/ui/issues/issue-56199.stderr @@ -0,0 +1,30 @@ +error: the `Self` constructor can only be used with tuple structs + --> $DIR/issue-56199.rs:7:17 + | +LL | let _ = Self; + | ^^^^ + | + = note: did you mean to use one of the enum's variants? + +error: the `Self` constructor can only be used with tuple structs + --> $DIR/issue-56199.rs:9:17 + | +LL | let _ = Self(); + | ^^^^ + | + = note: did you mean to use one of the enum's variants? + +error: the `Self` constructor can only be used with tuple structs + --> $DIR/issue-56199.rs:16:17 + | +LL | let _ = Self; + | ^^^^ did you mean `Self { /* fields */ }`? + +error: the `Self` constructor can only be used with tuple structs + --> $DIR/issue-56199.rs:18:17 + | +LL | let _ = Self(); + | ^^^^ did you mean `Self { /* fields */ }`? + +error: aborting due to 4 previous errors + From 48d930c68ee948adfabcfa00051f4ab44a93b77e Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Sat, 15 Dec 2018 04:33:54 +0000 Subject: [PATCH 09/12] Added test for issue #56835. --- src/test/ui/issues/issue-56835.rs | 10 ++++++++++ src/test/ui/issues/issue-56835.stderr | 15 +++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/test/ui/issues/issue-56835.rs create mode 100644 src/test/ui/issues/issue-56835.stderr diff --git a/src/test/ui/issues/issue-56835.rs b/src/test/ui/issues/issue-56835.rs new file mode 100644 index 0000000000000..0b3a665ccf9fd --- /dev/null +++ b/src/test/ui/issues/issue-56835.rs @@ -0,0 +1,10 @@ + +pub struct Foo {} + +impl Foo { + fn bar(Self(foo): Self) {} + //~^ ERROR the `Self` constructor can only be used with tuple structs + //~^^ ERROR expected tuple struct/variant, found self constructor `Self` [E0164] +} + +fn main() {} diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr new file mode 100644 index 0000000000000..32bbc49ffd991 --- /dev/null +++ b/src/test/ui/issues/issue-56835.stderr @@ -0,0 +1,15 @@ +error: the `Self` constructor can only be used with tuple structs + --> $DIR/issue-56835.rs:5:12 + | +LL | fn bar(Self(foo): Self) {} + | ^^^^^^^^^ did you mean `Self { /* fields */ }`? + +error[E0164]: expected tuple struct/variant, found self constructor `Self` + --> $DIR/issue-56835.rs:5:12 + | +LL | fn bar(Self(foo): Self) {} + | ^^^^^^^^^ not a tuple variant or struct + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0164`. From 33417ae39170a06d98483de9340d0f815b66f436 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Thu, 13 Dec 2018 15:35:45 +0000 Subject: [PATCH 10/12] Fixed minor issues raised in review. --- src/librustc/ty/mod.rs | 16 ++++++++-------- src/librustc_typeck/check/mod.rs | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c3bb1afd98f23..3adb7f1c5f371 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1756,7 +1756,7 @@ bitflags! { const IS_ENUM = 1 << 0; const IS_UNION = 1 << 1; const IS_STRUCT = 1 << 2; - const IS_TUPLE_STRUCT = 1 << 3; + const HAS_CTOR = 1 << 3; const IS_PHANTOM_DATA = 1 << 4; const IS_FUNDAMENTAL = 1 << 5; const IS_BOX = 1 << 6; @@ -2096,7 +2096,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { let variant_def = &variants[VariantIdx::new(0)]; let def_key = tcx.def_key(variant_def.did); match def_key.disambiguated_data.data { - DefPathData::StructCtor => flags |= AdtFlags::IS_TUPLE_STRUCT, + DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR, _ => (), } } @@ -2131,12 +2131,6 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.flags.contains(AdtFlags::IS_STRUCT) } - /// If this function returns `true`, it implies that `is_struct` must return `true`. - #[inline] - pub fn is_tuple_struct(&self) -> bool { - self.flags.contains(AdtFlags::IS_TUPLE_STRUCT) - } - #[inline] pub fn is_union(&self) -> bool { self.flags.contains(AdtFlags::IS_UNION) @@ -2181,6 +2175,12 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + /// If this function returns `true`, it implies that `is_struct` must return `true`. + #[inline] + pub fn has_ctor(&self) -> bool { + self.flags.contains(AdtFlags::HAS_CTOR) + } + /// Returns whether this type is `#[fundamental]` for the purposes /// of coherence checking. #[inline] diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 57d808d9d78fa..c7e923967b8b3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5168,7 +5168,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let adt_def = ty.ty_adt_def(); match adt_def { - Some(adt_def) if adt_def.is_tuple_struct() => { + Some(adt_def) if adt_def.has_ctor() => { let variant = adt_def.non_enum_variant(); new_def = Def::StructCtor(variant.did, variant.ctor_kind); (variant.did, self.tcx.type_of(variant.did)) @@ -5181,8 +5181,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { AdtKind::Enum => { err.note("did you mean to use one of the enum's variants?"); }, - AdtKind::Union => {}, - AdtKind::Struct => { + AdtKind::Struct | + AdtKind::Union => { err.span_label( span, format!("did you mean `Self {{ /* fields */ }}`?"), From e6c53328015ebff467c960431f6335f07575c35b Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Sat, 15 Dec 2018 17:31:46 +0000 Subject: [PATCH 11/12] Corrected expected test err messages. --- src/test/ui/issues/issue-56199.rs | 8 ++++---- src/test/ui/issues/issue-56199.stderr | 8 ++++---- src/test/ui/issues/issue-56835.rs | 2 +- src/test/ui/issues/issue-56835.stderr | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/ui/issues/issue-56199.rs b/src/test/ui/issues/issue-56199.rs index bbd51823cf1af..83d4e31b5d126 100644 --- a/src/test/ui/issues/issue-56199.rs +++ b/src/test/ui/issues/issue-56199.rs @@ -5,18 +5,18 @@ struct Bar {} impl Foo { fn foo() { let _ = Self; - //~^ ERROR the `Self` constructor can only be used with tuple structs + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs let _ = Self(); - //~^ ERROR the `Self` constructor can only be used with tuple structs + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs } } impl Bar { fn bar() { let _ = Self; - //~^ ERROR the `Self` constructor can only be used with tuple structs + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs let _ = Self(); - //~^ ERROR the `Self` constructor can only be used with tuple structs + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs } } diff --git a/src/test/ui/issues/issue-56199.stderr b/src/test/ui/issues/issue-56199.stderr index feb88e926b2d8..6e3c7fd17b437 100644 --- a/src/test/ui/issues/issue-56199.stderr +++ b/src/test/ui/issues/issue-56199.stderr @@ -1,4 +1,4 @@ -error: the `Self` constructor can only be used with tuple structs +error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:7:17 | LL | let _ = Self; @@ -6,7 +6,7 @@ LL | let _ = Self; | = note: did you mean to use one of the enum's variants? -error: the `Self` constructor can only be used with tuple structs +error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:9:17 | LL | let _ = Self(); @@ -14,13 +14,13 @@ LL | let _ = Self(); | = note: did you mean to use one of the enum's variants? -error: the `Self` constructor can only be used with tuple structs +error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:16:17 | LL | let _ = Self; | ^^^^ did you mean `Self { /* fields */ }`? -error: the `Self` constructor can only be used with tuple structs +error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:18:17 | LL | let _ = Self(); diff --git a/src/test/ui/issues/issue-56835.rs b/src/test/ui/issues/issue-56835.rs index 0b3a665ccf9fd..c16550e370179 100644 --- a/src/test/ui/issues/issue-56835.rs +++ b/src/test/ui/issues/issue-56835.rs @@ -3,7 +3,7 @@ pub struct Foo {} impl Foo { fn bar(Self(foo): Self) {} - //~^ ERROR the `Self` constructor can only be used with tuple structs + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs //~^^ ERROR expected tuple struct/variant, found self constructor `Self` [E0164] } diff --git a/src/test/ui/issues/issue-56835.stderr b/src/test/ui/issues/issue-56835.stderr index 32bbc49ffd991..b7c3b142ec452 100644 --- a/src/test/ui/issues/issue-56835.stderr +++ b/src/test/ui/issues/issue-56835.stderr @@ -1,4 +1,4 @@ -error: the `Self` constructor can only be used with tuple structs +error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56835.rs:5:12 | LL | fn bar(Self(foo): Self) {} From 1cf854f3ef1ce64ef61d105a9aa25427e04a6313 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 1 Jan 2019 17:26:04 +0100 Subject: [PATCH 12/12] fix test output --- src/test/ui/consts/static_mut_containing_mut_ref2.rs | 1 - .../ui/consts/static_mut_containing_mut_ref2.stderr | 11 ++--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index 4180b1e295ab0..aeb69b2652cbf 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -4,6 +4,5 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; //~^ ERROR references in statics may only refer to immutable values -//~| ERROR static contains unimplemented expression type fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr index f0ae1545056b7..72923431c90ed 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr @@ -4,13 +4,6 @@ error[E0017]: references in statics may only refer to immutable values LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error[E0019]: static contains unimplemented expression type - --> $DIR/static_mut_containing_mut_ref2.rs:5:45 - | -LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0017, E0019. -For more information about an error, try `rustc --explain E0017`. +For more information about this error, try `rustc --explain E0017`.