From ba3b536e204df7108def541a86bbe5d7d599cfbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 22 May 2024 11:37:02 +0200 Subject: [PATCH 01/18] Fix `io::Take::read_buf` --- library/std/src/io/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 0b57d01f27346..98e7b40bdc6ec 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2941,7 +2941,7 @@ impl Read for Take { } let mut cursor = sliced_buf.unfilled(); - self.inner.read_buf(cursor.reborrow())?; + let result = self.inner.read_buf(cursor.reborrow()); let new_init = cursor.init_ref().len(); let filled = sliced_buf.len(); @@ -2956,13 +2956,14 @@ impl Read for Take { } self.limit -= filled as u64; + + result } else { let written = buf.written(); - self.inner.read_buf(buf.reborrow())?; + let result = self.inner.read_buf(buf.reborrow()); self.limit -= (buf.written() - written) as u64; + result } - - Ok(()) } } From 04710e27d260b82865b3d4949e2e84b59c35ed66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 22 May 2024 11:41:19 +0200 Subject: [PATCH 02/18] Fix `io::BufReader` uses of `read_buf` --- library/std/src/io/buffered/bufreader.rs | 2 +- library/std/src/io/buffered/bufreader/buffer.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index e51dde994de45..438df70505b20 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -349,7 +349,7 @@ impl Read for BufReader { let prev = cursor.written(); let mut rem = self.fill_buf()?; - rem.read_buf(cursor.reborrow())?; + rem.read_buf(cursor.reborrow())?; // actually never fails self.consume(cursor.written() - prev); //slice impl of read_buf known to never unfill buf diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index 1bf84d8bef312..68b024bb98aac 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -133,11 +133,13 @@ impl Buffer { buf.set_init(self.initialized); } - reader.read_buf(buf.unfilled())?; + let result = reader.read_buf(buf.unfilled()); self.pos = 0; self.filled = buf.len(); self.initialized = buf.init_len(); + + result?; } Ok(self.buffer()) } From bf768886d1c040d323165999cd0aeb6c86e2a71b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 22 May 2024 11:47:58 +0200 Subject: [PATCH 03/18] Fix `io::default_read_to_end` uses of `read_buf` --- library/std/src/io/mod.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 98e7b40bdc6ec..954062a489c78 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -474,18 +474,28 @@ pub(crate) fn default_read_to_end( } let mut cursor = read_buf.unfilled(); - loop { + let result = loop { match r.read_buf(cursor.reborrow()) { - Ok(()) => break, Err(e) if e.is_interrupted() => continue, - Err(e) => return Err(e), + // Do not stop now in case of error: we might have received both data + // and an error + res => break res, } - } + }; let unfilled_but_initialized = cursor.init_ref().len(); let bytes_read = cursor.written(); let was_fully_initialized = read_buf.init_len() == buf_len; + // SAFETY: BorrowedBuf's invariants mean this much memory is initialized. + unsafe { + let new_len = bytes_read + buf.len(); + buf.set_len(new_len); + } + + // Now that all data is pushed to the vector, we can fail without data loss + result?; + if bytes_read == 0 { return Ok(buf.len() - start_len); } @@ -499,12 +509,6 @@ pub(crate) fn default_read_to_end( // store how much was initialized but not filled initialized = unfilled_but_initialized; - // SAFETY: BorrowedBuf's invariants mean this much memory is initialized. - unsafe { - let new_len = bytes_read + buf.len(); - buf.set_len(new_len); - } - // Use heuristics to determine the max read size if no initial size hint was provided if size_hint.is_none() { // The reader is returning short reads but it doesn't call ensure_init(). From 4b8a66c908be909ab9d451565d3959ffea45357d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Mon, 23 Sep 2024 17:38:18 +0200 Subject: [PATCH 04/18] Add tests --- library/std/src/io/tests.rs | 63 +++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index f551dcd401efc..56b71c47dc73c 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -735,6 +735,69 @@ fn read_buf_full_read() { assert_eq!(BufReader::new(FullRead).fill_buf().unwrap().len(), DEFAULT_BUF_SIZE); } +struct DataAndErrorReader(&'static [u8]); + +impl Read for DataAndErrorReader { + fn read(&mut self, _buf: &mut [u8]) -> io::Result { + panic!("We want tests to use `read_buf`") + } + + fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf).unwrap(); + Err(io::Error::other("error")) + } +} + +#[test] +fn read_buf_data_and_error_take() { + let mut buf = [0; 64]; + let mut buf = io::BorrowedBuf::from(buf.as_mut_slice()); + + let mut r = DataAndErrorReader(&[4, 5, 6]).take(1); + assert!(r.read_buf(buf.unfilled()).is_err()); + assert_eq!(buf.filled(), &[4]); + + assert!(r.read_buf(buf.unfilled()).is_ok()); + assert_eq!(buf.filled(), &[4]); + assert_eq!(r.get_ref().0, &[5, 6]); +} + +#[test] +fn read_buf_data_and_error_buf() { + let mut r = BufReader::new(DataAndErrorReader(&[4, 5, 6])); + + assert!(r.fill_buf().is_err()); + assert_eq!(r.fill_buf().unwrap(), &[4, 5, 6]); +} + +#[test] +fn read_buf_data_and_error_read_to_end() { + let mut r = DataAndErrorReader(&[4, 5, 6]); + + let mut v = Vec::with_capacity(200); + assert!(r.read_to_end(&mut v).is_err()); + + assert_eq!(v, &[4, 5, 6]); +} + +#[test] +fn read_to_end_error() { + struct ErrorReader; + + impl Read for ErrorReader { + fn read(&mut self, _buf: &mut [u8]) -> io::Result { + Err(io::Error::other("error")) + } + } + + let mut r = [4, 5, 6].chain(ErrorReader); + + let mut v = Vec::with_capacity(200); + assert!(r.read_to_end(&mut v).is_err()); + + assert_eq!(v, &[4, 5, 6]); +} + #[test] // Miri does not support signalling OOM #[cfg_attr(miri, ignore)] From d77664bed945fbbd5ab102f59a38b1ef0e728b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Mon, 23 Sep 2024 17:40:04 +0200 Subject: [PATCH 05/18] Add a comment to `Read::read_buf` --- library/std/src/io/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 954062a489c78..dd6458c38c6e9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -978,6 +978,8 @@ pub trait Read { /// with uninitialized buffers. The new data will be appended to any existing contents of `buf`. /// /// The default implementation delegates to `read`. + /// + /// This method makes it possible to return both data and an error but it is advised against. #[unstable(feature = "read_buf", issue = "78485")] fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> { default_read_buf(|b| self.read(b), buf) From d4ee408afc59b36ff59b6fd12d47c1beeba8e985 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 25 Sep 2024 19:19:22 -0400 Subject: [PATCH 06/18] Check allow instantiating object trait binder when upcasting and in new solver --- .../src/solve/trait_goals.rs | 6 ++--- .../src/traits/select/mod.rs | 6 ++--- tests/ui/coercion/sub-principals.rs | 27 +++++++++++++++++++ .../higher-ranked-upcasting-ok.current.stderr | 22 --------------- .../higher-ranked-upcasting-ok.next.stderr | 14 ---------- .../higher-ranked-upcasting-ok.rs | 10 ++++--- .../higher-ranked-upcasting-ub.current.stderr | 8 +++--- tests/ui/traits/trait-upcasting/sub.rs | 26 ++++++++++++++++++ 8 files changed, 69 insertions(+), 50 deletions(-) create mode 100644 tests/ui/coercion/sub-principals.rs delete mode 100644 tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.current.stderr delete mode 100644 tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.next.stderr create mode 100644 tests/ui/traits/trait-upcasting/sub.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 781ca127e151e..0befe7f5e8a2c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -896,7 +896,7 @@ where && ecx .probe(|_| ProbeKind::UpcastProjectionCompatibility) .enter(|ecx| -> Result<(), NoSolution> { - ecx.eq(param_env, source_projection, target_projection)?; + ecx.sub(param_env, source_projection, target_projection)?; let _ = ecx.try_evaluate_added_goals()?; Ok(()) }) @@ -909,7 +909,7 @@ where // Check that a's supertrait (upcast_principal) is compatible // with the target (b_ty). ty::ExistentialPredicate::Trait(target_principal) => { - ecx.eq( + ecx.sub( param_env, upcast_principal.unwrap(), bound.rebind(target_principal), @@ -934,7 +934,7 @@ where Certainty::AMBIGUOUS, ); } - ecx.eq(param_env, source_projection, target_projection)?; + ecx.sub(param_env, source_projection, target_projection)?; } // Check that b_ty's auto traits are present in a_ty's bounds. ty::ExistentialPredicate::AutoTrait(def_id) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cbc17a058f6d1..2922a4898e983 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2582,12 +2582,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> { nested.extend( self.infcx .at(&obligation.cause, obligation.param_env) - .eq( + .sup( DefineOpaqueTypes::Yes, + bound.rebind(target_principal), upcast_principal.map_bound(|trait_ref| { ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) }), - bound.rebind(target_principal), ) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), @@ -2620,7 +2620,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { nested.extend( self.infcx .at(&obligation.cause, obligation.param_env) - .eq(DefineOpaqueTypes::Yes, source_projection, target_projection) + .sup(DefineOpaqueTypes::Yes, target_projection, source_projection) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), ); diff --git a/tests/ui/coercion/sub-principals.rs b/tests/ui/coercion/sub-principals.rs new file mode 100644 index 0000000000000..c38769f0d0986 --- /dev/null +++ b/tests/ui/coercion/sub-principals.rs @@ -0,0 +1,27 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Verify that the unsize goal can cast a higher-ranked trait goal to +// a non-higer-ranked instantiation. + +#![feature(unsize)] + +use std::marker::Unsize; + +fn test() +where + T: Unsize, +{ +} + +fn main() { + test:: Fn(&'a ()) -> &'a (), dyn Fn(&'static ()) -> &'static ()>(); + + trait Foo<'a, 'b> {} + test:: Foo<'a, 'b>, dyn for<'a> Foo<'a, 'a>>(); + + trait Bar<'a> {} + test:: Bar<'a>, dyn Bar<'_>>(); +} diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.current.stderr b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.current.stderr deleted file mode 100644 index 098ab71e946e9..0000000000000 --- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.current.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/higher-ranked-upcasting-ok.rs:17:5 - | -LL | x - | ^ one type is more general than the other - | - = note: expected existential trait ref `for<'a, 'b> Supertrait<'a, 'b>` - found existential trait ref `for<'a> Supertrait<'a, 'a>` - -error[E0308]: mismatched types - --> $DIR/higher-ranked-upcasting-ok.rs:17:5 - | -LL | x - | ^ one type is more general than the other - | - = note: expected existential trait ref `for<'a, 'b> Supertrait<'a, 'b>` - found existential trait ref `for<'a> Supertrait<'a, 'a>` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.next.stderr b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.next.stderr deleted file mode 100644 index ac516fd697535..0000000000000 --- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.next.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/higher-ranked-upcasting-ok.rs:17:5 - | -LL | fn ok(x: &dyn for<'a, 'b> Subtrait<'a, 'b>) -> &dyn for<'a> Supertrait<'a, 'a> { - | ------------------------------- expected `&dyn for<'a> Supertrait<'a, 'a>` because of return type -LL | x - | ^ expected trait `Supertrait`, found trait `Subtrait` - | - = note: expected reference `&dyn for<'a> Supertrait<'a, 'a>` - found reference `&dyn for<'a, 'b> Subtrait<'a, 'b>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs index 0074320317970..7f793e1269fd7 100644 --- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs +++ b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs @@ -1,19 +1,21 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver +//@ check-pass // We should be able to instantiate a binder during trait upcasting. // This test could be `check-pass`, but we should make sure that we // do so in both trait solvers. + #![feature(trait_upcasting)] -#![crate_type = "rlib"] -trait Supertrait<'a, 'b> {} +trait Supertrait<'a, 'b> {} trait Subtrait<'a, 'b>: Supertrait<'a, 'b> {} impl<'a> Supertrait<'a, 'a> for () {} impl<'a> Subtrait<'a, 'a> for () {} fn ok(x: &dyn for<'a, 'b> Subtrait<'a, 'b>) -> &dyn for<'a> Supertrait<'a, 'a> { - x //~ ERROR mismatched types - //[current]~^ ERROR mismatched types + x } + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.current.stderr b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.current.stderr index bac8298326879..e5885ea35a71e 100644 --- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.current.stderr +++ b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.current.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | x | ^ one type is more general than the other | - = note: expected existential trait ref `for<'a> Supertrait<'a, 'a>` - found existential trait ref `for<'a, 'b> Supertrait<'a, 'b>` + = note: expected existential trait ref `for<'a, 'b> Supertrait<'a, 'b>` + found existential trait ref `for<'a> Supertrait<'a, 'a>` error[E0308]: mismatched types --> $DIR/higher-ranked-upcasting-ub.rs:22:5 @@ -13,8 +13,8 @@ error[E0308]: mismatched types LL | x | ^ one type is more general than the other | - = note: expected existential trait ref `for<'a> Supertrait<'a, 'a>` - found existential trait ref `for<'a, 'b> Supertrait<'a, 'b>` + = note: expected existential trait ref `for<'a, 'b> Supertrait<'a, 'b>` + found existential trait ref `for<'a> Supertrait<'a, 'a>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/trait-upcasting/sub.rs b/tests/ui/traits/trait-upcasting/sub.rs new file mode 100644 index 0000000000000..255c4895b7f36 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/sub.rs @@ -0,0 +1,26 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Verify that the unsize goal can cast a higher-ranked trait goal to +// a non-higer-ranked instantiation. + +#![feature(unsize)] + +use std::marker::Unsize; + +fn test() +where + T: Unsize, +{ +} + +fn main() { + test:: Fn(&'a ()) -> &'a (), dyn FnOnce(&'static ()) -> &'static ()>(); + + trait Foo: for<'a> Bar<'a> {} + trait Bar<'a> {} + test::>(); + test::>(); +} From fa3215daad3f845acbbf31222b84f13d6d4d56e3 Mon Sep 17 00:00:00 2001 From: Asger Hautop Drewsen Date: Fri, 27 Sep 2024 10:05:52 +0200 Subject: [PATCH 07/18] Reference UNSPECIFIED instead of INADDR_ANY in join_multicast_v4 --- library/std/src/net/udp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index d4252cb87ac22..8c9e31f9c157c 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -579,8 +579,8 @@ impl UdpSocket { /// This function specifies a new multicast group for this socket to join. /// The address must be a valid multicast address, and `interface` is the /// address of the local interface with which the system should join the - /// multicast group. If it's equal to `INADDR_ANY` then an appropriate - /// interface is chosen by the system. + /// multicast group. If it's equal to [`UNSPECIFIED`](Ipv4Addr::UNSPECIFIED) + /// then an appropriate interface is chosen by the system. #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { self.0.join_multicast_v4(multiaddr, interface) From 0bf928968bf442ba0e4d50e8d716edf2dd43cbbc Mon Sep 17 00:00:00 2001 From: surechen Date: Fri, 27 Sep 2024 16:37:43 +0800 Subject: [PATCH 08/18] Make clashing_extern_declarations considering generic args for ADT field fixes #130851 --- compiler/rustc_lint/src/foreign_modules.rs | 6 +-- .../lint/clashing-extern-fn-issue-130851.rs | 42 +++++++++++++++++++ .../clashing-extern-fn-issue-130851.stderr | 31 ++++++++++++++ 3 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 tests/ui/lint/clashing-extern-fn-issue-130851.rs create mode 100644 tests/ui/lint/clashing-extern-fn-issue-130851.stderr diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 1ead377607f1b..816882962bef6 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -280,7 +280,7 @@ fn structurally_same_type_impl<'tcx>( ensure_sufficient_stack(|| { match (a.kind(), b.kind()) { - (&Adt(a_def, _), &Adt(b_def, _)) => { + (&Adt(a_def, a_gen_args), &Adt(b_def, b_gen_args)) => { // Only `repr(C)` types can be compared structurally. if !(a_def.repr().c() && b_def.repr().c()) { return false; @@ -304,8 +304,8 @@ fn structurally_same_type_impl<'tcx>( seen_types, tcx, param_env, - tcx.type_of(a_did).instantiate_identity(), - tcx.type_of(b_did).instantiate_identity(), + tcx.type_of(a_did).instantiate(tcx, a_gen_args), + tcx.type_of(b_did).instantiate(tcx, b_gen_args), ckind, ) }, diff --git a/tests/ui/lint/clashing-extern-fn-issue-130851.rs b/tests/ui/lint/clashing-extern-fn-issue-130851.rs new file mode 100644 index 0000000000000..1b2fdf1d3fca5 --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn-issue-130851.rs @@ -0,0 +1,42 @@ +//@ build-pass +#![warn(clashing_extern_declarations)] + +#[repr(C)] +pub struct A { + a: [u16; 4], +} +#[repr(C)] +pub struct B { + b: [u32; 4], +} + +pub mod a { + extern "C" { + pub fn foo(_: super::A); + } +} +pub mod b { + extern "C" { + pub fn foo(_: super::B); + //~^ WARN `foo` redeclared with a different signature + } +} + +#[repr(C)] +pub struct G { + g: [T; 4], +} + +pub mod x { + extern "C" { + pub fn bar(_: super::G); + } +} +pub mod y { + extern "C" { + pub fn bar(_: super::G); + //~^ WARN `bar` redeclared with a different signature + } +} + +fn main() {} diff --git a/tests/ui/lint/clashing-extern-fn-issue-130851.stderr b/tests/ui/lint/clashing-extern-fn-issue-130851.stderr new file mode 100644 index 0000000000000..c38ec40404751 --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn-issue-130851.stderr @@ -0,0 +1,31 @@ +warning: `foo` redeclared with a different signature + --> $DIR/clashing-extern-fn-issue-130851.rs:20:9 + | +LL | pub fn foo(_: super::A); + | ------------------------ `foo` previously declared here +... +LL | pub fn foo(_: super::B); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(A)` + found `unsafe extern "C" fn(B)` +note: the lint level is defined here + --> $DIR/clashing-extern-fn-issue-130851.rs:2:9 + | +LL | #![warn(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `bar` redeclared with a different signature + --> $DIR/clashing-extern-fn-issue-130851.rs:37:9 + | +LL | pub fn bar(_: super::G); + | ----------------------------- `bar` previously declared here +... +LL | pub fn bar(_: super::G); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(G)` + found `unsafe extern "C" fn(G)` + +warning: 2 warnings emitted + From 3b9db47f07e2b609dc2acf45b0eaa7239ef76f49 Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Fri, 27 Sep 2024 14:34:48 -0400 Subject: [PATCH 09/18] rustdoc: update `ProcMacro` docs section on helper attributes I believe the mention of attribute macros in the section on proc macro helper attributes is erroneous. As far as I can tell, attribute macros cannot define helper attributes. The following attribute macro is not valid (fails to build), no matter how I try to define (or skip defining) the helpers: ```rust #[proc_macro_attribute(attributes(helper))] pub fn attribute_helpers(_attr: TokenStream, item: TokenStream) -> TokenStream { item } ``` The [language reference](https://doc.rust-lang.org/reference/procedural-macros.html#attribute-macros) also doesn't seem to mention attribute macro helpers. The helpers subsection is inside the section on derive macros. --- src/rustdoc-json-types/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index ef21779b09931..b3707cf615714 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -1168,7 +1168,7 @@ pub struct ProcMacro { pub kind: MacroKind, /// Helper attributes defined by a macro to be used inside it. /// - /// Defined only for attribute & derive macros. + /// Defined only for derive macros. /// /// E.g. the [`Default`] derive macro defines a `#[default]` helper attribute so that one can /// do: From 282d04489adefc09286160719676a309e26ddd07 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 27 Sep 2024 11:45:59 -0700 Subject: [PATCH 10/18] Revert "ci: Try to remove unused Xcode dirs" This reverts commit 06f49f6d5326440192b8d31d69fa490dbfe01cfe. --- src/ci/scripts/select-xcode.sh | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/ci/scripts/select-xcode.sh b/src/ci/scripts/select-xcode.sh index d635d4384727f..569c4a4136d97 100755 --- a/src/ci/scripts/select-xcode.sh +++ b/src/ci/scripts/select-xcode.sh @@ -1,6 +1,5 @@ #!/bin/bash # This script selects the Xcode instance to use. -# It also tries to do some cleanup in CI jobs of unused Xcodes. set -euo pipefail IFS=$'\n\t' @@ -8,21 +7,5 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" if isMacOS; then - # This additional step is to try to remove an Xcode we aren't using because each one is HUGE - old_xcode="$(xcode-select --print-path)" - old_xcode="${old_xcode%/*}" # pop a dir - old_xcode="${old_xcode%/*}" # twice - if [[ $old_xcode =~ $SELECT_XCODE ]]; then - echo "xcode-select.sh's brutal hack may not be necessary?" - exit 1 - elif [[ $SELECT_XCODE =~ "16" ]]; then - echo "Using Xcode 16? Please fix xcode-select.sh" - exit 1 - fi - if [ $CI ]; then # just in case someone sources this on their real computer - sudo rm -rf "${old_xcode}" - xcode_16="${old_xcode%/*}/Xcode-16.0.0.app" - sudo rm -rf "${xcode_16}" - fi sudo xcode-select -s "${SELECT_XCODE}" fi From a2a4ea0850b7324fcf0bb1779d3b1f288835b2f4 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 27 Sep 2024 11:47:07 -0700 Subject: [PATCH 11/18] Partially revert "ci: Use mv instead of cp in upload step" This partially reverts commit fe7c97c2e732de8dfc93ef21ee84ccfbc04c7d0c. I kept a mv, not a cp, for the one that shuffles major artifacts around, because the size of those artifacts are big enough to matter, sometimes. I don't think the diagnostic info will be that heavy, by comparison. --- src/ci/scripts/upload-artifacts.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh index 61c187fa77c01..0bc91f6ba7152 100755 --- a/src/ci/scripts/upload-artifacts.sh +++ b/src/ci/scripts/upload-artifacts.sh @@ -23,14 +23,14 @@ if [[ "${DEPLOY-0}" -eq "1" ]] || [[ "${DEPLOY_ALT-0}" -eq "1" ]]; then fi # CPU usage statistics. -mv build/cpu-usage.csv "${upload_dir}/cpu-${CI_JOB_NAME}.csv" +cp build/cpu-usage.csv "${upload_dir}/cpu-${CI_JOB_NAME}.csv" # Build metrics generated by x.py. -mv "${build_dir}/metrics.json" "${upload_dir}/metrics-${CI_JOB_NAME}.json" +cp "${build_dir}/metrics.json" "${upload_dir}/metrics-${CI_JOB_NAME}.json" # Toolstate data. if [[ -n "${DEPLOY_TOOLSTATES_JSON+x}" ]]; then - mv /tmp/toolstate/toolstates.json "${upload_dir}/${DEPLOY_TOOLSTATES_JSON}" + cp /tmp/toolstate/toolstates.json "${upload_dir}/${DEPLOY_TOOLSTATES_JSON}" fi echo "Files that will be uploaded:" From 8302f2e35fe7d9fc4cafbe2d5057775e82fc9690 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 27 Sep 2024 19:27:48 +0200 Subject: [PATCH 12/18] add even more tests for ptr-to-ptr casts on trait objects --- ...ptr-to-trait-obj-different-regions-misc.rs | 6 ++++ ...to-trait-obj-different-regions-misc.stderr | 35 +++++++++++++++---- tests/ui/cast/ptr-to-trait-obj-ok.rs | 34 +++++++++++++++++- tests/ui/cast/ptr-to-trait-obj-ok.stderr | 24 +++++++++++++ 4 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 tests/ui/cast/ptr-to-trait-obj-ok.stderr diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs index d7c6c50d8bebc..18566acc07fe4 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs @@ -15,6 +15,12 @@ fn change_lt_ba<'a, 'b: 'a>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> { x as _ //~ error: lifetime may not live long enough } +fn change_lt_hr<'a>(x: *mut dyn Trait<'a>) -> *mut dyn for<'b> Trait<'b> { + x as _ //~ error: lifetime may not live long enough + //~^ error: mismatched types + //~| one type is more general than the other +} + trait Assocked { type Assoc: ?Sized; } diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr index 6069f4f3b5563..6f590585c4a46 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr @@ -61,7 +61,29 @@ LL | x as _ = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:25:5 + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:19:5 + | +LL | fn change_lt_hr<'a>(x: *mut dyn Trait<'a>) -> *mut dyn for<'b> Trait<'b> { + | -- lifetime `'a` defined here +LL | x as _ + | ^^^^^^ cast requires that `'a` must outlive `'static` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound + | +LL | fn change_lt_hr<'a>(x: *mut dyn Trait<'a>) -> *mut dyn for<'b> Trait<'b> + 'a { + | ++++ + +error[E0308]: mismatched types + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:19:5 + | +LL | x as _ + | ^^^^^^ one type is more general than the other + | + = note: expected trait object `dyn for<'b> Trait<'b>` + found trait object `dyn Trait<'_>` + +error: lifetime may not live long enough + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:31:5 | LL | fn change_assoc_0<'a, 'b>( | -- -- lifetime `'b` defined here @@ -77,7 +99,7 @@ LL | x as _ = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:25:5 + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:31:5 | LL | fn change_assoc_0<'a, 'b>( | -- -- lifetime `'b` defined here @@ -97,7 +119,7 @@ help: `'b` and `'a` must be the same: replace one with the other = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:32:5 + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:38:5 | LL | fn change_assoc_1<'a, 'b>( | -- -- lifetime `'b` defined here @@ -113,7 +135,7 @@ LL | x as _ = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:32:5 + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:38:5 | LL | fn change_assoc_1<'a, 'b>( | -- -- lifetime `'b` defined here @@ -133,12 +155,13 @@ help: `'b` and `'a` must be the same: replace one with the other = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:39:20 + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:45:20 | LL | fn extend_to_static<'a>(ptr: *const dyn Trait<'a>) { | -- lifetime `'a` defined here LL | require_static(ptr as _) | ^^^^^^^^ cast requires that `'a` must outlive `'static` -error: aborting due to 9 previous errors +error: aborting due to 11 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/cast/ptr-to-trait-obj-ok.rs b/tests/ui/cast/ptr-to-trait-obj-ok.rs index 656c99c58dc9a..f30472667b748 100644 --- a/tests/ui/cast/ptr-to-trait-obj-ok.rs +++ b/tests/ui/cast/ptr-to-trait-obj-ok.rs @@ -1,4 +1,4 @@ -//@ check-pass +//@ check-fail trait Trait<'a> {} @@ -10,8 +10,40 @@ fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trai x as _ } +fn cast_away_higher_ranked<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut dyn Trait<'a> { + x as _ +} + fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) { x as _ } +// If it is possible to coerce from the source to the target type modulo +// regions, then we skip the HIR checks for ptr-to-ptr casts and possibly +// insert an unsizing coercion into the MIR before the ptr-to-ptr cast. +// By wrapping the target type, we ensure that no coercion happens +// and also test the non-coercion cast behavior. +struct Wrapper(T); + +fn remove_auto_wrap<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut Wrapper> { + x as _ +} + +fn cast_inherent_lt_wrap<'a, 'b>( + x: *mut (dyn Trait<'static> + 'a), +) -> *mut Wrapper + 'b> { + x as _ +} + +fn cast_away_higher_ranked_wrap<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut Wrapper> { + x as _ + //~^ error: lifetime may not live long enough + //~| error: mismatched types + //~| one type is more general than the other +} + +fn unprincipled_wrap<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { + x as _ +} + fn main() {} diff --git a/tests/ui/cast/ptr-to-trait-obj-ok.stderr b/tests/ui/cast/ptr-to-trait-obj-ok.stderr new file mode 100644 index 0000000000000..8de07691c213f --- /dev/null +++ b/tests/ui/cast/ptr-to-trait-obj-ok.stderr @@ -0,0 +1,24 @@ +error: lifetime may not live long enough + --> $DIR/ptr-to-trait-obj-ok.rs:39:5 + | +LL | fn cast_away_higher_ranked_wrap<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut Wrapper> { + | -- lifetime `'a` defined here +LL | x as _ + | ^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `Wrapper>` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance + +error[E0308]: mismatched types + --> $DIR/ptr-to-trait-obj-ok.rs:39:5 + | +LL | x as _ + | ^^^^^^ one type is more general than the other + | + = note: expected trait object `dyn for<'b> Trait<'b>` + found trait object `dyn Trait<'_>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 53f45c4332fa3703bc6866699a40df5fba2fd8ca Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 27 Sep 2024 20:02:43 +0200 Subject: [PATCH 13/18] borrowck: use subtyping instead of equality for ptr-to-ptr casts --- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- tests/ui/cast/ptr-to-trait-obj-ok.rs | 5 +--- tests/ui/cast/ptr-to-trait-obj-ok.stderr | 24 ------------------- 3 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 tests/ui/cast/ptr-to-trait-obj-ok.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 16e51e82f85e0..6b17879de262d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2437,7 +2437,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj); - self.eq_types( + self.sub_types( src_obj, dst_obj, location.to_locations(), diff --git a/tests/ui/cast/ptr-to-trait-obj-ok.rs b/tests/ui/cast/ptr-to-trait-obj-ok.rs index f30472667b748..dbeee9d29441e 100644 --- a/tests/ui/cast/ptr-to-trait-obj-ok.rs +++ b/tests/ui/cast/ptr-to-trait-obj-ok.rs @@ -1,4 +1,4 @@ -//@ check-fail +//@ check-pass trait Trait<'a> {} @@ -37,9 +37,6 @@ fn cast_inherent_lt_wrap<'a, 'b>( fn cast_away_higher_ranked_wrap<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut Wrapper> { x as _ - //~^ error: lifetime may not live long enough - //~| error: mismatched types - //~| one type is more general than the other } fn unprincipled_wrap<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper { diff --git a/tests/ui/cast/ptr-to-trait-obj-ok.stderr b/tests/ui/cast/ptr-to-trait-obj-ok.stderr deleted file mode 100644 index 8de07691c213f..0000000000000 --- a/tests/ui/cast/ptr-to-trait-obj-ok.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-ok.rs:39:5 - | -LL | fn cast_away_higher_ranked_wrap<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut Wrapper> { - | -- lifetime `'a` defined here -LL | x as _ - | ^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = note: requirement occurs because of a mutable pointer to `Wrapper>` - = note: mutable pointers are invariant over their type parameter - = help: see for more information about variance - -error[E0308]: mismatched types - --> $DIR/ptr-to-trait-obj-ok.rs:39:5 - | -LL | x as _ - | ^^^^^^ one type is more general than the other - | - = note: expected trait object `dyn for<'b> Trait<'b>` - found trait object `dyn Trait<'_>` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. From 4fb097a5de14399b86dda519e1e597104a15b3b2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 26 Sep 2024 23:20:59 -0400 Subject: [PATCH 14/18] Instantiate binders when checking supertrait upcasting --- compiler/rustc_infer/src/infer/at.rs | 19 +++- .../src/solve/eval_ctxt/mod.rs | 16 ++-- .../src/solve/trait_goals.rs | 49 ++++++---- .../src/traits/select/mod.rs | 96 +++++++++++++++---- 4 files changed, 132 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 9f6a17638664e..37f7f04db3f83 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -159,7 +159,24 @@ impl<'a, 'tcx> At<'a, 'tcx> { ToTrace::to_trace(self.cause, true, expected, actual), self.param_env, define_opaque_types, - ); + ToTrace::to_trace(self.cause, expected, actual), + expected, + actual, + ) + } + + /// Makes `expected == actual`. + pub fn eq_trace( + self, + define_opaque_types: DefineOpaqueTypes, + trace: TypeTrace<'tcx>, + expected: T, + actual: T, + ) -> InferResult<'tcx, ()> + where + T: Relate>, + { + let mut fields = CombineFields::new(self.infcx, trace, self.param_env, define_opaque_types); fields.equate(StructurallyRelateAliases::No).relate(expected, actual)?; Ok(InferOk { value: (), diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 12ad0724b5cb1..932875b759fb4 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -448,10 +448,10 @@ where } } } else { - self.delegate.enter_forall(kind, |kind| { - let goal = goal.with(self.cx(), ty::Binder::dummy(kind)); - self.add_goal(GoalSource::InstantiateHigherRanked, goal); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.enter_forall(kind, |ecx, kind| { + let goal = goal.with(ecx.cx(), ty::Binder::dummy(kind)); + ecx.add_goal(GoalSource::InstantiateHigherRanked, goal); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } } @@ -840,12 +840,14 @@ where self.delegate.instantiate_binder_with_infer(value) } + /// `enter_forall`, but takes `&mut self` and passes it back through the + /// callback since it can't be aliased during the call. pub(super) fn enter_forall + Copy, U>( - &self, + &mut self, value: ty::Binder, - f: impl FnOnce(T) -> U, + f: impl FnOnce(&mut Self, T) -> U, ) -> U { - self.delegate.enter_forall(value, f) + self.delegate.enter_forall(value, |value| f(self, value)) } pub(super) fn resolve_vars_if_possible(&self, value: T) -> T diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 0befe7f5e8a2c..493bbf1e66527 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -895,10 +895,13 @@ where source_projection.item_def_id() == target_projection.item_def_id() && ecx .probe(|_| ProbeKind::UpcastProjectionCompatibility) - .enter(|ecx| -> Result<(), NoSolution> { - ecx.sub(param_env, source_projection, target_projection)?; - let _ = ecx.try_evaluate_added_goals()?; - Ok(()) + .enter(|ecx| -> Result<_, NoSolution> { + ecx.enter_forall(target_projection, |ecx, target_projection| { + let source_projection = + ecx.instantiate_binder_with_infer(source_projection); + ecx.eq(param_env, source_projection, target_projection)?; + ecx.try_evaluate_added_goals() + }) }) .is_ok() }; @@ -909,11 +912,14 @@ where // Check that a's supertrait (upcast_principal) is compatible // with the target (b_ty). ty::ExistentialPredicate::Trait(target_principal) => { - ecx.sub( - param_env, - upcast_principal.unwrap(), - bound.rebind(target_principal), - )?; + let source_principal = upcast_principal.unwrap(); + let target_principal = bound.rebind(target_principal); + ecx.enter_forall(target_principal, |ecx, target_principal| { + let source_principal = + ecx.instantiate_binder_with_infer(source_principal); + ecx.eq(param_env, source_principal, target_principal)?; + ecx.try_evaluate_added_goals() + })?; } // Check that b_ty's projection is satisfied by exactly one of // a_ty's projections. First, we look through the list to see if @@ -934,7 +940,12 @@ where Certainty::AMBIGUOUS, ); } - ecx.sub(param_env, source_projection, target_projection)?; + ecx.enter_forall(target_projection, |ecx, target_projection| { + let source_projection = + ecx.instantiate_binder_with_infer(source_projection); + ecx.eq(param_env, source_projection, target_projection)?; + ecx.try_evaluate_added_goals() + })?; } // Check that b_ty's auto traits are present in a_ty's bounds. ty::ExistentialPredicate::AutoTrait(def_id) => { @@ -1187,17 +1198,15 @@ where ) -> Result>, NoSolution>, ) -> Result, NoSolution> { self.probe_trait_candidate(source).enter(|ecx| { - ecx.add_goals( - GoalSource::ImplWhereBound, - constituent_tys(ecx, goal.predicate.self_ty())? - .into_iter() - .map(|ty| { - ecx.enter_forall(ty, |ty| { - goal.with(ecx.cx(), goal.predicate.with_self_ty(ecx.cx(), ty)) - }) + let goals = constituent_tys(ecx, goal.predicate.self_ty())? + .into_iter() + .map(|ty| { + ecx.enter_forall(ty, |ecx, ty| { + goal.with(ecx.cx(), goal.predicate.with_self_ty(ecx.cx(), ty)) }) - .collect::>(), - ); + }) + .collect::>(); + ecx.add_goals(GoalSource::ImplWhereBound, goals); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2922a4898e983..c3042ab963671 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -16,6 +16,7 @@ use rustc_hir::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; +use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::relate::TypeRelation; use rustc_infer::traits::TraitObligation; use rustc_middle::bug; @@ -44,7 +45,7 @@ use super::{ TraitQueryMode, const_evaluatable, project, util, wf, }; use crate::error_reporting::InferCtxtErrorExt; -use crate::infer::{InferCtxt, InferCtxtExt, InferOk, TypeFreshener}; +use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::solve::InferCtxtSelectExt as _; use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt}; @@ -2579,16 +2580,32 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Check that a_ty's supertrait (upcast_principal) is compatible // with the target (b_ty). ty::ExistentialPredicate::Trait(target_principal) => { + let hr_source_principal = upcast_principal.map_bound(|trait_ref| { + ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) + }); + let hr_target_principal = bound.rebind(target_principal); + nested.extend( self.infcx - .at(&obligation.cause, obligation.param_env) - .sup( - DefineOpaqueTypes::Yes, - bound.rebind(target_principal), - upcast_principal.map_bound(|trait_ref| { - ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) - }), - ) + .enter_forall(hr_target_principal, |target_principal| { + let source_principal = + self.infcx.instantiate_binder_with_fresh_vars( + obligation.cause.span, + HigherRankedType, + hr_source_principal, + ); + self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( + DefineOpaqueTypes::Yes, + ToTrace::to_trace( + &obligation.cause, + true, + hr_target_principal, + hr_source_principal, + ), + target_principal, + source_principal, + ) + }) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), ); @@ -2599,19 +2616,41 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // return ambiguity. Otherwise, if exactly one matches, equate // it with b_ty's projection. ty::ExistentialPredicate::Projection(target_projection) => { - let target_projection = bound.rebind(target_projection); + let hr_target_projection = bound.rebind(target_projection); + let mut matching_projections = - a_data.projection_bounds().filter(|source_projection| { + a_data.projection_bounds().filter(|&hr_source_projection| { // Eager normalization means that we can just use can_eq // here instead of equating and processing obligations. - source_projection.item_def_id() == target_projection.item_def_id() - && self.infcx.can_eq( - obligation.param_env, - *source_projection, - target_projection, - ) + hr_source_projection.item_def_id() == hr_target_projection.item_def_id() + && self.infcx.probe(|_| { + self.infcx + .enter_forall(hr_target_projection, |target_projection| { + let source_projection = + self.infcx.instantiate_binder_with_fresh_vars( + obligation.cause.span, + HigherRankedType, + hr_source_projection, + ); + self.infcx + .at(&obligation.cause, obligation.param_env) + .eq_trace( + DefineOpaqueTypes::Yes, + ToTrace::to_trace( + &obligation.cause, + true, + hr_target_projection, + hr_source_projection, + ), + target_projection, + source_projection, + ) + }) + .is_ok() + }) }); - let Some(source_projection) = matching_projections.next() else { + + let Some(hr_source_projection) = matching_projections.next() else { return Err(SelectionError::Unimplemented); }; if matching_projections.next().is_some() { @@ -2619,8 +2658,25 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } nested.extend( self.infcx - .at(&obligation.cause, obligation.param_env) - .sup(DefineOpaqueTypes::Yes, target_projection, source_projection) + .enter_forall(hr_target_projection, |target_projection| { + let source_projection = + self.infcx.instantiate_binder_with_fresh_vars( + obligation.cause.span, + HigherRankedType, + hr_source_projection, + ); + self.infcx.at(&obligation.cause, obligation.param_env).eq_trace( + DefineOpaqueTypes::Yes, + ToTrace::to_trace( + &obligation.cause, + true, + hr_target_projection, + hr_source_projection, + ), + target_projection, + source_projection, + ) + }) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), ); From d753aba3b342a286fbaa198b43154cf7fbe68692 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 26 Sep 2024 23:22:48 -0400 Subject: [PATCH 15/18] Get rid of a_is_expected from ToTrace --- compiler/rustc_infer/src/infer/at.rs | 145 +++++------------- .../src/traits/select/mod.rs | 3 - 2 files changed, 36 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 37f7f04db3f83..6ce47db8b9bd2 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -92,12 +92,7 @@ impl<'tcx> InferCtxt<'tcx> { } pub trait ToTrace<'tcx>: Relate> + Copy { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx>; + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx>; } impl<'a, 'tcx> At<'a, 'tcx> { @@ -116,7 +111,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { { let mut fields = CombineFields::new( self.infcx, - ToTrace::to_trace(self.cause, true, expected, actual), + ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, ); @@ -136,7 +131,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { { let mut fields = CombineFields::new( self.infcx, - ToTrace::to_trace(self.cause, true, expected, actual), + ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, ); @@ -154,10 +149,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let mut fields = CombineFields::new( - self.infcx, - ToTrace::to_trace(self.cause, true, expected, actual), - self.param_env, + self.eq_trace( define_opaque_types, ToTrace::to_trace(self.cause, expected, actual), expected, @@ -209,7 +201,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { assert!(self.infcx.next_trait_solver()); let mut fields = CombineFields::new( self.infcx, - ToTrace::to_trace(self.cause, true, expected, actual), + ToTrace::to_trace(self.cause, expected, actual), self.param_env, DefineOpaqueTypes::Yes, ); @@ -301,7 +293,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { { let mut fields = CombineFields::new( self.infcx, - ToTrace::to_trace(self.cause, true, expected, actual), + ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, ); @@ -323,7 +315,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { { let mut fields = CombineFields::new( self.infcx, - ToTrace::to_trace(self.cause, true, expected, actual), + ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, ); @@ -333,18 +325,13 @@ impl<'a, 'tcx> At<'a, 'tcx> { } impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { match (a, b) { (ImplSubject::Trait(trait_ref_a), ImplSubject::Trait(trait_ref_b)) => { - ToTrace::to_trace(cause, a_is_expected, trait_ref_a, trait_ref_b) + ToTrace::to_trace(cause, trait_ref_a, trait_ref_b) } (ImplSubject::Inherent(ty_a), ImplSubject::Inherent(ty_b)) => { - ToTrace::to_trace(cause, a_is_expected, ty_a, ty_b) + ToTrace::to_trace(cause, ty_a, ty_b) } (ImplSubject::Trait(_), ImplSubject::Inherent(_)) | (ImplSubject::Inherent(_), ImplSubject::Trait(_)) => { @@ -355,65 +342,45 @@ impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { } impl<'tcx> ToTrace<'tcx> for Ty<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())), } } } impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::Regions(ExpectedFound::new(true, a, b)), } } } impl<'tcx> ToTrace<'tcx> for Const<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())), } } } impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), values: match (a.unpack(), b.unpack()) { (GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => { - ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b)) + ValuePairs::Regions(ExpectedFound::new(true, a, b)) } (GenericArgKind::Type(a), GenericArgKind::Type(b)) => { - ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())) + ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())) } (GenericArgKind::Const(a), GenericArgKind::Const(b)) => { - ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())) + ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())) } ( @@ -436,72 +403,47 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { } impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::Terms(ExpectedFound::new(true, a, b)), } } } impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::TraitRefs(ExpectedFound::new(true, a, b)), } } } impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Aliases(ExpectedFound::new(true, a.into(), b.into())), } } } impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::Aliases(ExpectedFound::new(true, a, b)), } } } impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), values: ValuePairs::PolySigs(ExpectedFound::new( - a_is_expected, + true, ty::Binder::dummy(a), ty::Binder::dummy(b), )), @@ -510,43 +452,28 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> { } impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::PolySigs(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::PolySigs(ExpectedFound::new(true, a, b)), } } } impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(true, a, b)), } } } impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> { - fn to_trace( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Self, - b: Self, - ) -> TypeTrace<'tcx> { + fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::ExistentialProjection(ExpectedFound::new(true, a, b)), } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c3042ab963671..dbe05a3332843 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2598,7 +2598,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { DefineOpaqueTypes::Yes, ToTrace::to_trace( &obligation.cause, - true, hr_target_principal, hr_source_principal, ), @@ -2638,7 +2637,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { DefineOpaqueTypes::Yes, ToTrace::to_trace( &obligation.cause, - true, hr_target_projection, hr_source_projection, ), @@ -2669,7 +2667,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { DefineOpaqueTypes::Yes, ToTrace::to_trace( &obligation.cause, - true, hr_target_projection, hr_source_projection, ), From bcf8cf29433ed2d74dbe5598ccd7db1d1c20ed2e Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 26 Sep 2024 10:34:08 -0700 Subject: [PATCH 16/18] tests: issue-69488.rs => load-preserves-partial-init-issue-69488.rs --- src/tools/tidy/src/issues.txt | 1 - .../consts/{issue-69488.rs => load-preserves-partial-init.rs} | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) rename tests/ui/consts/{issue-69488.rs => load-preserves-partial-init.rs} (80%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 2071abefbe17e..9d3b090abb6e7 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -795,7 +795,6 @@ ui/consts/issue-68684.rs ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs ui/consts/issue-69310-array-size-lit-wrong-ty.rs ui/consts/issue-69312.rs -ui/consts/issue-69488.rs ui/consts/issue-69532.rs ui/consts/issue-6991.rs ui/consts/issue-70773-mir-typeck-lt-norm.rs diff --git a/tests/ui/consts/issue-69488.rs b/tests/ui/consts/load-preserves-partial-init.rs similarity index 80% rename from tests/ui/consts/issue-69488.rs rename to tests/ui/consts/load-preserves-partial-init.rs index d528d6a88de60..d97e9cb3d9df6 100644 --- a/tests/ui/consts/issue-69488.rs +++ b/tests/ui/consts/load-preserves-partial-init.rs @@ -1,6 +1,9 @@ //@ run-pass #![feature(const_ptr_write)] +// issue: https://github.com/rust-lang/rust/issues/69488 +// Loads of partially-initialized data could produce completely-uninitialized results. +// Test to make sure that we no longer do such a "deinitializing" load. // Or, equivalently: `MaybeUninit`. pub union BagOfBits { From a1fbf251b81b165016d4f29ea9a9e08647275957 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 27 Sep 2024 14:04:42 -0700 Subject: [PATCH 17/18] tests: issue-14309.* => repr-rust-is-undefined.* --- src/tools/tidy/src/issues.txt | 1 - .../repr-rust-is-undefined.rs} | 4 ++++ .../repr-rust-is-undefined.stderr} | 22 +++++++++---------- 3 files changed, 15 insertions(+), 12 deletions(-) rename tests/ui/lint/{issue-14309.rs => improper_ctypes/repr-rust-is-undefined.rs} (70%) rename tests/ui/lint/{issue-14309.stderr => improper_ctypes/repr-rust-is-undefined.stderr} (79%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 9d3b090abb6e7..89535079772ef 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2744,7 +2744,6 @@ ui/lint/issue-111359.rs ui/lint/issue-112489.rs ui/lint/issue-117949.rs ui/lint/issue-121070-let-range.rs -ui/lint/issue-14309.rs ui/lint/issue-14837.rs ui/lint/issue-17718-const-naming.rs ui/lint/issue-1866.rs diff --git a/tests/ui/lint/issue-14309.rs b/tests/ui/lint/improper_ctypes/repr-rust-is-undefined.rs similarity index 70% rename from tests/ui/lint/issue-14309.rs rename to tests/ui/lint/improper_ctypes/repr-rust-is-undefined.rs index 328a4c982b81e..379c4132404bf 100644 --- a/tests/ui/lint/issue-14309.rs +++ b/tests/ui/lint/improper_ctypes/repr-rust-is-undefined.rs @@ -1,6 +1,10 @@ #![deny(improper_ctypes)] #![allow(dead_code)] +// issue https://github.com/rust-lang/rust/issues/14309 +// Validates we lint on repr(Rust) structs and not repr(C) structs in FFI, to implement RFC 79: +// https://rust-lang.github.io/rfcs/0079-undefined-struct-layout.html + struct A { x: i32 } diff --git a/tests/ui/lint/issue-14309.stderr b/tests/ui/lint/improper_ctypes/repr-rust-is-undefined.stderr similarity index 79% rename from tests/ui/lint/issue-14309.stderr rename to tests/ui/lint/improper_ctypes/repr-rust-is-undefined.stderr index 9ce62a6b8044b..5f0465bcf00c7 100644 --- a/tests/ui/lint/issue-14309.stderr +++ b/tests/ui/lint/improper_ctypes/repr-rust-is-undefined.stderr @@ -1,5 +1,5 @@ error: `extern` block uses type `A`, which is not FFI-safe - --> $DIR/issue-14309.rs:30:15 + --> $DIR/repr-rust-is-undefined.rs:34:15 | LL | fn foo(x: A); | ^ not FFI-safe @@ -7,18 +7,18 @@ LL | fn foo(x: A); = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/issue-14309.rs:4:1 + --> $DIR/repr-rust-is-undefined.rs:8:1 | LL | struct A { | ^^^^^^^^ note: the lint level is defined here - --> $DIR/issue-14309.rs:1:9 + --> $DIR/repr-rust-is-undefined.rs:1:9 | LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ error: `extern` block uses type `A`, which is not FFI-safe - --> $DIR/issue-14309.rs:31:15 + --> $DIR/repr-rust-is-undefined.rs:35:15 | LL | fn bar(x: B); | ^ not FFI-safe @@ -26,13 +26,13 @@ LL | fn bar(x: B); = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/issue-14309.rs:4:1 + --> $DIR/repr-rust-is-undefined.rs:8:1 | LL | struct A { | ^^^^^^^^ error: `extern` block uses type `A`, which is not FFI-safe - --> $DIR/issue-14309.rs:33:15 + --> $DIR/repr-rust-is-undefined.rs:37:15 | LL | fn qux(x: A2); | ^^ not FFI-safe @@ -40,13 +40,13 @@ LL | fn qux(x: A2); = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/issue-14309.rs:4:1 + --> $DIR/repr-rust-is-undefined.rs:8:1 | LL | struct A { | ^^^^^^^^ error: `extern` block uses type `A`, which is not FFI-safe - --> $DIR/issue-14309.rs:34:16 + --> $DIR/repr-rust-is-undefined.rs:38:16 | LL | fn quux(x: B2); | ^^ not FFI-safe @@ -54,13 +54,13 @@ LL | fn quux(x: B2); = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/issue-14309.rs:4:1 + --> $DIR/repr-rust-is-undefined.rs:8:1 | LL | struct A { | ^^^^^^^^ error: `extern` block uses type `A`, which is not FFI-safe - --> $DIR/issue-14309.rs:36:16 + --> $DIR/repr-rust-is-undefined.rs:40:16 | LL | fn fred(x: D); | ^ not FFI-safe @@ -68,7 +68,7 @@ LL | fn fred(x: D); = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/issue-14309.rs:4:1 + --> $DIR/repr-rust-is-undefined.rs:8:1 | LL | struct A { | ^^^^^^^^ From 19d5568ad3a83d48b152f5c7182c364005ee969e Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 27 Sep 2024 14:12:57 -0700 Subject: [PATCH 18/18] tests: issue-34798.rs => allow-phantomdata-in-ffi.rs --- src/tools/tidy/src/issues.txt | 1 - .../allow-phantomdata-in-ffi.rs} | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) rename tests/ui/lint/{issue-34798.rs => improper_ctypes/allow-phantomdata-in-ffi.rs} (71%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 89535079772ef..86cae849b9782 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2750,7 +2750,6 @@ ui/lint/issue-1866.rs ui/lint/issue-19102.rs ui/lint/issue-20343.rs ui/lint/issue-30302.rs -ui/lint/issue-34798.rs ui/lint/issue-35075.rs ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs ui/lint/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs diff --git a/tests/ui/lint/issue-34798.rs b/tests/ui/lint/improper_ctypes/allow-phantomdata-in-ffi.rs similarity index 71% rename from tests/ui/lint/issue-34798.rs rename to tests/ui/lint/improper_ctypes/allow-phantomdata-in-ffi.rs index 064fc7c4ad69b..a90159d2b5894 100644 --- a/tests/ui/lint/issue-34798.rs +++ b/tests/ui/lint/improper_ctypes/allow-phantomdata-in-ffi.rs @@ -1,6 +1,8 @@ //@ run-pass #![forbid(improper_ctypes)] #![allow(dead_code)] +// issue https://github.com/rust-lang/rust/issues/34798 +// We allow PhantomData in FFI so bindgen can bind templated C++ structs with "unused generic args" #[repr(C)] pub struct Foo {