From 16c0a84510648d25b8310a9c2c8ce27c417fb28f Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Mon, 6 Sep 2021 03:35:37 -0400 Subject: [PATCH 01/15] Fix ICE when `start` lang item has wrong generics --- compiler/rustc_hir/src/lang_items.rs | 2 +- .../run-make-fulldeps/target-specs/foo.rs | 2 +- .../lang-item-generic-requirements.rs | 16 ++++++++++--- .../lang-item-generic-requirements.stderr | 23 +++++++++++++------ 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index b85ed0cb4bbe5..9e323c3e93c70 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -299,7 +299,7 @@ language_item_table! { Oom, sym::oom, oom, Target::Fn, GenericRequirement::None; AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None; - Start, sym::start, start_fn, Target::Fn, GenericRequirement::None; + Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1); EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None; EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None; diff --git a/src/test/run-make-fulldeps/target-specs/foo.rs b/src/test/run-make-fulldeps/target-specs/foo.rs index 9ff33e24d04d7..83fdc452a3b13 100644 --- a/src/test/run-make-fulldeps/target-specs/foo.rs +++ b/src/test/run-make-fulldeps/target-specs/foo.rs @@ -11,7 +11,7 @@ trait Sized {} auto trait Freeze {} #[lang = "start"] -fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { +fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { 0 } diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.rs b/src/test/ui/lang-items/lang-item-generic-requirements.rs index d785749afc9c2..c0b958f2bf221 100644 --- a/src/test/ui/lang-items/lang-item-generic-requirements.rs +++ b/src/test/ui/lang-items/lang-item-generic-requirements.rs @@ -1,9 +1,8 @@ -// Checks whether declaring a lang item with the wrong number -// of generic arguments crashes the compiler (issue #83893, #87573, and part of #9307). +// Checks that declaring a lang item with the wrong number +// of generic arguments errors rather than crashing (issue #83893, #87573, part of #9307, #79559). #![feature(lang_items, no_core)] #![no_core] -#![crate_type = "lib"] #[lang = "sized"] trait MySized {} @@ -26,6 +25,14 @@ struct MyPhantomData; //~^ ERROR parameter `T` is never used //~| ERROR parameter `U` is never used +// When the `start` lang item is missing generics very odd things can happen, especially when +// it comes to cross-crate monomorphization +#[lang = "start"] +//~^ ERROR `start` language item must be applied to a function with 1 generic argument [E0718] +fn start(_: *const u8, _: isize, _: *const *const u8) -> isize { + 0 +} + fn ice() { // Use add let r = 5; @@ -42,3 +49,6 @@ fn ice() { // Use phantomdata let _ = MyPhantomData::<(), i32>; } + +// use `start` +fn main() {} diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.stderr b/src/test/ui/lang-items/lang-item-generic-requirements.stderr index add5938811c28..df5a77850f14d 100644 --- a/src/test/ui/lang-items/lang-item-generic-requirements.stderr +++ b/src/test/ui/lang-items/lang-item-generic-requirements.stderr @@ -1,5 +1,5 @@ error[E0718]: `add` language item must be applied to a trait with 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:11:1 + --> $DIR/lang-item-generic-requirements.rs:10:1 | LL | #[lang = "add"] | ^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | trait MyAdd<'a, T> {} | ------- this trait has 2 generic arguments error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:15:1 + --> $DIR/lang-item-generic-requirements.rs:14:1 | LL | #[lang = "drop_in_place"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | fn my_ptr_drop() {} | - this function has 0 generic arguments error[E0718]: `index` language item must be applied to a trait with 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:19:1 + --> $DIR/lang-item-generic-requirements.rs:18:1 | LL | #[lang = "index"] | ^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | trait MyIndex<'a, T> {} | ------- this trait has 2 generic arguments error[E0718]: `phantom_data` language item must be applied to a struct with 1 generic argument - --> $DIR/lang-item-generic-requirements.rs:23:1 + --> $DIR/lang-item-generic-requirements.rs:22:1 | LL | #[lang = "phantom_data"] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,8 +32,17 @@ LL | LL | struct MyPhantomData; | ------ this struct has 2 generic arguments +error[E0718]: `start` language item must be applied to a function with 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:30:1 + | +LL | #[lang = "start"] + | ^^^^^^^^^^^^^^^^^ +LL | +LL | fn start(_: *const u8, _: isize, _: *const *const u8) -> isize { + | - this function has 0 generic arguments + error[E0392]: parameter `T` is never used - --> $DIR/lang-item-generic-requirements.rs:25:22 + --> $DIR/lang-item-generic-requirements.rs:24:22 | LL | struct MyPhantomData; | ^ unused parameter @@ -42,7 +51,7 @@ LL | struct MyPhantomData; = help: if you intended `T` to be a const parameter, use `const T: usize` instead error[E0392]: parameter `U` is never used - --> $DIR/lang-item-generic-requirements.rs:25:25 + --> $DIR/lang-item-generic-requirements.rs:24:25 | LL | struct MyPhantomData; | ^ unused parameter @@ -50,7 +59,7 @@ LL | struct MyPhantomData; = help: consider removing `U` or referring to it in a field = help: if you intended `U` to be a const parameter, use `const U: usize` instead -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0392, E0718. For more information about an error, try `rustc --explain E0392`. From 05460d0efcf16ed1c437c721beafd65babd7c1ef Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Fri, 10 Sep 2021 09:33:06 -0400 Subject: [PATCH 02/15] update test --- src/test/run-make-fulldeps/target-specs/foo.rs | 2 +- src/tools/clippy/tests/ui/def_id_nocore.rs | 5 +++-- src/tools/clippy/tests/ui/def_id_nocore.stderr | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/run-make-fulldeps/target-specs/foo.rs b/src/test/run-make-fulldeps/target-specs/foo.rs index 83fdc452a3b13..d576a1dd28192 100644 --- a/src/test/run-make-fulldeps/target-specs/foo.rs +++ b/src/test/run-make-fulldeps/target-specs/foo.rs @@ -11,7 +11,7 @@ trait Sized {} auto trait Freeze {} #[lang = "start"] -fn start(_main: *const u8, _argc: isize, _argv: *const *const u8) -> isize { +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { 0 } diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs index cba7666c2d8a7..1ed78547a60cd 100644 --- a/src/tools/clippy/tests/ui/def_id_nocore.rs +++ b/src/tools/clippy/tests/ui/def_id_nocore.rs @@ -15,11 +15,12 @@ pub trait Copy {} pub unsafe trait Freeze {} #[lang = "start"] -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { 0 } +fn main() {} + struct A; impl A { diff --git a/src/tools/clippy/tests/ui/def_id_nocore.stderr b/src/tools/clippy/tests/ui/def_id_nocore.stderr index 702684f6b43a6..6210d7c6cfd80 100644 --- a/src/tools/clippy/tests/ui/def_id_nocore.stderr +++ b/src/tools/clippy/tests/ui/def_id_nocore.stderr @@ -1,5 +1,5 @@ error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> $DIR/def_id_nocore.rs:26:19 + --> $DIR/def_id_nocore.rs:27:19 | LL | pub fn as_ref(self) -> &'static str { | ^^^^ From b8deb93b22b8f67b53f400849aa233610e32381c Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 23 Sep 2021 11:29:52 +0000 Subject: [PATCH 03/15] Add test --- src/test/ui/typeck/call-block.rs | 3 +++ src/test/ui/typeck/call-block.stderr | 11 +++++++++++ 2 files changed, 14 insertions(+) create mode 100644 src/test/ui/typeck/call-block.rs create mode 100644 src/test/ui/typeck/call-block.stderr diff --git a/src/test/ui/typeck/call-block.rs b/src/test/ui/typeck/call-block.rs new file mode 100644 index 0000000000000..1d5244411a226 --- /dev/null +++ b/src/test/ui/typeck/call-block.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = {42}(); //~ ERROR expected function, found `_` +} diff --git a/src/test/ui/typeck/call-block.stderr b/src/test/ui/typeck/call-block.stderr new file mode 100644 index 0000000000000..20f61dd23ac4e --- /dev/null +++ b/src/test/ui/typeck/call-block.stderr @@ -0,0 +1,11 @@ +error[E0618]: expected function, found `_` + --> $DIR/call-block.rs:2:13 + | +LL | let _ = {42}(); + | ^^^^-- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. From 072d107b438207e2c2c83fdf8c22bb5e8699138e Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 23 Sep 2021 11:37:29 +0000 Subject: [PATCH 04/15] Resolve infered types when complaining about unexpected call type --- compiler/rustc_typeck/src/check/callee.rs | 1 + src/test/ui/typeck/call-block.rs | 2 +- src/test/ui/typeck/call-block.stderr | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 1cc06b8c2e544..6cdd38664c864 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -350,6 +350,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + let callee_ty = self.resolve_vars_if_possible(callee_ty); let mut err = type_error_struct!( self.tcx.sess, callee_expr.span, diff --git a/src/test/ui/typeck/call-block.rs b/src/test/ui/typeck/call-block.rs index 1d5244411a226..0390d7db040b4 100644 --- a/src/test/ui/typeck/call-block.rs +++ b/src/test/ui/typeck/call-block.rs @@ -1,3 +1,3 @@ fn main() { - let _ = {42}(); //~ ERROR expected function, found `_` + let _ = {42}(); //~ ERROR expected function, found `{integer}` } diff --git a/src/test/ui/typeck/call-block.stderr b/src/test/ui/typeck/call-block.stderr index 20f61dd23ac4e..68984bc1c453f 100644 --- a/src/test/ui/typeck/call-block.stderr +++ b/src/test/ui/typeck/call-block.stderr @@ -1,4 +1,4 @@ -error[E0618]: expected function, found `_` +error[E0618]: expected function, found `{integer}` --> $DIR/call-block.rs:2:13 | LL | let _ = {42}(); From 0f9c349834622fa337c8dab886af4041bcdad5bb Mon Sep 17 00:00:00 2001 From: Gus Wynn Date: Mon, 27 Sep 2021 08:43:30 -0700 Subject: [PATCH 05/15] lock types --- library/std/src/lib.rs | 1 + library/std/src/sync/mutex.rs | 6 +++++ library/std/src/sync/rwlock.rs | 12 +++++++++ src/test/ui/lint/must_not_suspend/mutex.rs | 13 ++++++++++ .../ui/lint/must_not_suspend/mutex.stderr | 26 +++++++++++++++++++ 5 files changed, 58 insertions(+) create mode 100644 src/test/ui/lint/must_not_suspend/mutex.rs create mode 100644 src/test/ui/lint/must_not_suspend/mutex.stderr diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f69baba9e733f..9d150b69f6a6d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -297,6 +297,7 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] +#![cfg_attr(not(bootstrap), feature(must_not_suspend))] #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index e1d6324c17e33..9abd4b547c77e 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -188,6 +188,12 @@ unsafe impl Sync for Mutex {} /// [`lock`]: Mutex::lock /// [`try_lock`]: Mutex::try_lock #[must_use = "if unused the Mutex will immediately unlock"] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "Holding a MutexGuard across suspend \ + points can cause deadlocks, delays, \ + and cause Future's to not implement `Send`" +)] #[stable(feature = "rust1", since = "1.0.0")] pub struct MutexGuard<'a, T: ?Sized + 'a> { lock: &'a Mutex, diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index e50d62d817376..1523d36323fd9 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -95,6 +95,12 @@ unsafe impl Sync for RwLock {} /// [`read`]: RwLock::read /// [`try_read`]: RwLock::try_read #[must_use = "if unused the RwLock will immediately unlock"] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "Holding a RwLockReadGuard across suspend \ + points can cause deadlocks, delays, \ + and cause Future's to not implement `Send`" +)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { lock: &'a RwLock, @@ -115,6 +121,12 @@ unsafe impl Sync for RwLockReadGuard<'_, T> {} /// [`write`]: RwLock::write /// [`try_write`]: RwLock::try_write #[must_use = "if unused the RwLock will immediately unlock"] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "Holding a RwLockWriteGuard across suspend \ + points can cause deadlocks, delays, \ + and cause Future's to not implement `Send`" +)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { lock: &'a RwLock, diff --git a/src/test/ui/lint/must_not_suspend/mutex.rs b/src/test/ui/lint/must_not_suspend/mutex.rs new file mode 100644 index 0000000000000..7bb895e7d3643 --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/mutex.rs @@ -0,0 +1,13 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +async fn other() {} + +pub async fn uhoh(m: std::sync::Mutex<()>) { + let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across + other().await; +} + +fn main() { +} diff --git a/src/test/ui/lint/must_not_suspend/mutex.stderr b/src/test/ui/lint/must_not_suspend/mutex.stderr new file mode 100644 index 0000000000000..69638fc20107c --- /dev/null +++ b/src/test/ui/lint/must_not_suspend/mutex.stderr @@ -0,0 +1,26 @@ +error: `MutexGuard` held across a suspend point, but should not be + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +LL | other().await; + | ------------- the value is held across this suspend point + | +note: the lint level is defined here + --> $DIR/mutex.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ +note: Holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Future's to not implement `Send` + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ + +error: aborting due to previous error + From 4cc3297dc403e9d4d2106b26418efe35d4bb1af2 Mon Sep 17 00:00:00 2001 From: Gus Wynn Date: Mon, 27 Sep 2021 08:49:36 -0700 Subject: [PATCH 06/15] #[feature] not required for lint result --- src/test/ui/lint/must_not_suspend/mutex.rs | 1 - src/test/ui/lint/must_not_suspend/mutex.stderr | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/ui/lint/must_not_suspend/mutex.rs b/src/test/ui/lint/must_not_suspend/mutex.rs index 7bb895e7d3643..596249b2e4e4f 100644 --- a/src/test/ui/lint/must_not_suspend/mutex.rs +++ b/src/test/ui/lint/must_not_suspend/mutex.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(must_not_suspend)] #![deny(must_not_suspend)] async fn other() {} diff --git a/src/test/ui/lint/must_not_suspend/mutex.stderr b/src/test/ui/lint/must_not_suspend/mutex.stderr index 69638fc20107c..47a84fdbc5731 100644 --- a/src/test/ui/lint/must_not_suspend/mutex.stderr +++ b/src/test/ui/lint/must_not_suspend/mutex.stderr @@ -1,5 +1,5 @@ error: `MutexGuard` held across a suspend point, but should not be - --> $DIR/mutex.rs:8:9 + --> $DIR/mutex.rs:7:9 | LL | let _guard = m.lock().unwrap(); | ^^^^^^ @@ -7,17 +7,17 @@ LL | other().await; | ------------- the value is held across this suspend point | note: the lint level is defined here - --> $DIR/mutex.rs:3:9 + --> $DIR/mutex.rs:2:9 | LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ note: Holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Future's to not implement `Send` - --> $DIR/mutex.rs:8:9 + --> $DIR/mutex.rs:7:9 | LL | let _guard = m.lock().unwrap(); | ^^^^^^ help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point - --> $DIR/mutex.rs:8:9 + --> $DIR/mutex.rs:7:9 | LL | let _guard = m.lock().unwrap(); | ^^^^^^ From 5d4048b66fa42ad44947bb004fdb7f8141ea65a2 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 27 Sep 2021 18:51:52 +0100 Subject: [PATCH 07/15] thread: implements available_concurrency on haiku --- library/std/src/sys/unix/thread.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 133ad3ea420b8..05f51a46168f6 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -338,8 +338,17 @@ pub fn available_concurrency() -> io::Result { } Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else if #[cfg(target_os = "haiku")] { + let mut sinfo: libc::system_info = crate::mem::zeroed(); + let res = libc::get_system_info(&mut sinfo); + + if res != libc::B_OK { + return Err(io::Error::last_os_error()); + } + + Ok(unsafe { NonZeroUsize::new_unchecked(sinfo.cpu_count as usize) }) } else { - // FIXME: implement on vxWorks, Redox, Haiku, l4re + // FIXME: implement on vxWorks, Redox, l4re Err(io::Error::new_const(io::ErrorKind::Unsupported, &"Getting the number of hardware threads is not supported on the target platform")) } } From dea3ee1ec435eaece47d4a2f89e73328e951b777 Mon Sep 17 00:00:00 2001 From: Marcel Hlopko Date: Fri, 10 Sep 2021 15:11:56 +0200 Subject: [PATCH 08/15] Add `pie` as another `relocation-model` value --- compiler/rustc_codegen_llvm/src/back/write.rs | 3 +- compiler/rustc_codegen_llvm/src/context.rs | 7 +++- compiler/rustc_codegen_llvm/src/lib.rs | 13 +++++-- compiler/rustc_codegen_llvm/src/mono_item.rs | 6 +++ compiler/rustc_codegen_ssa/src/back/link.rs | 8 +++- compiler/rustc_target/src/spec/mod.rs | 3 ++ src/doc/rustc/src/codegen-options/index.md | 4 ++ src/test/assembly/pic-relocation-model.rs | 35 +++++++++++++++++ src/test/assembly/pie-relocation-model.rs | 38 +++++++++++++++++++ src/test/codegen/pic-relocation-model.rs | 16 ++++++++ src/test/codegen/pie-relocation-model.rs | 21 ++++++++++ 11 files changed, 146 insertions(+), 8 deletions(-) create mode 100644 src/test/assembly/pic-relocation-model.rs create mode 100644 src/test/assembly/pie-relocation-model.rs create mode 100644 src/test/codegen/pic-relocation-model.rs create mode 100644 src/test/codegen/pie-relocation-model.rs diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 791604a18273d..e8484c24df9db 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -129,7 +129,8 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel { match relocation_model { RelocModel::Static => llvm::RelocModel::Static, - RelocModel::Pic => llvm::RelocModel::PIC, + // LLVM doesn't have a PIE relocation model, it represents PIE as PIC with an extra attribute. + RelocModel::Pic | RelocModel::Pie => llvm::RelocModel::PIC, RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic, RelocModel::Ropi => llvm::RelocModel::ROPI, RelocModel::Rwpi => llvm::RelocModel::RWPI, diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 2d397dc583534..e69d42c948285 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -190,11 +190,14 @@ pub unsafe fn create_module( let llvm_target = SmallCStr::new(&sess.target.llvm_target); llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); - if sess.relocation_model() == RelocModel::Pic { + let reloc_model = sess.relocation_model(); + if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) { llvm::LLVMRustSetModulePICLevel(llmod); // PIE is potentially more effective than PIC, but can only be used in executables. // If all our outputs are executables, then we can relax PIC to PIE. - if sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) { + if reloc_model == RelocModel::Pie + || sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) + { llvm::LLVMRustSetModulePIELevel(llmod); } } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 1da14344b1d26..0b06fe8bdcf9c 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -211,9 +211,16 @@ impl CodegenBackend for LlvmCodegenBackend { match req { PrintRequest::RelocationModels => { println!("Available relocation models:"); - for name in - &["static", "pic", "dynamic-no-pic", "ropi", "rwpi", "ropi-rwpi", "default"] - { + for name in &[ + "static", + "pic", + "pie", + "dynamic-no-pic", + "ropi", + "rwpi", + "ropi-rwpi", + "default", + ] { println!(" {}", name); } println!(); diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 8ba3e870fbb71..17bf55bf512fe 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -144,6 +144,12 @@ impl CodegenCx<'ll, 'tcx> { return true; } + // With pie relocation model calls of functions defined in the translation + // unit can use copy relocations. + if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration { + return true; + } + return false; } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 4fb51ecc1d347..0dcddb693de75 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1490,9 +1490,13 @@ fn exec_linker( fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind { let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) { (CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe, - (CrateType::Executable, false, RelocModel::Pic) => LinkOutputKind::DynamicPicExe, + (CrateType::Executable, false, RelocModel::Pic | RelocModel::Pie) => { + LinkOutputKind::DynamicPicExe + } (CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe, - (CrateType::Executable, true, RelocModel::Pic) => LinkOutputKind::StaticPicExe, + (CrateType::Executable, true, RelocModel::Pic | RelocModel::Pie) => { + LinkOutputKind::StaticPicExe + } (CrateType::Executable, true, _) => LinkOutputKind::StaticNoPicExe, (_, true, _) => LinkOutputKind::StaticDylib, (_, false, _) => LinkOutputKind::DynamicDylib, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 273221360b8b5..44eafde300181 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -287,6 +287,7 @@ impl ToJson for MergeFunctions { pub enum RelocModel { Static, Pic, + Pie, DynamicNoPic, Ropi, Rwpi, @@ -300,6 +301,7 @@ impl FromStr for RelocModel { Ok(match s { "static" => RelocModel::Static, "pic" => RelocModel::Pic, + "pie" => RelocModel::Pie, "dynamic-no-pic" => RelocModel::DynamicNoPic, "ropi" => RelocModel::Ropi, "rwpi" => RelocModel::Rwpi, @@ -314,6 +316,7 @@ impl ToJson for RelocModel { match *self { RelocModel::Static => "static", RelocModel::Pic => "pic", + RelocModel::Pie => "pie", RelocModel::DynamicNoPic => "dynamic-no-pic", RelocModel::Ropi => "ropi", RelocModel::Rwpi => "rwpi", diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 05384117ac175..4f8c4c66f8891 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -435,6 +435,10 @@ Equivalent to the "uppercase" `-fPIC` or `-fPIE` options in other compilers, depending on the produced crate types. \ This is the default model for majority of supported targets. +- `pie` - position independent executable, relocatable code but without support for symbol +interpositioning (replacing symbols by name using `LD_PRELOAD` and similar). Equivalent to the "uppercase" `-fPIE` option in other compilers. `pie` +code cannot be linked into shared libraries (you'll get a linking error on attempt to do this). + #### Special relocation models - `dynamic-no-pic` - relocatable external references, non-relocatable code. \ diff --git a/src/test/assembly/pic-relocation-model.rs b/src/test/assembly/pic-relocation-model.rs new file mode 100644 index 0000000000000..72471ffcdb0cb --- /dev/null +++ b/src/test/assembly/pic-relocation-model.rs @@ -0,0 +1,35 @@ +// revisions: x64 +// assembly-output: emit-asm +// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pic +// [x64] needs-llvm-components: x86 + + +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type="rlib"] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +// CHECK-LABEL: call_other_fn: +// CHECK: {{(jmpq|callq)}} *other_fn@GOTPCREL(%rip) +#[no_mangle] +pub fn call_other_fn() -> u8 { + unsafe { + other_fn() + } +} + +// CHECK-LABEL: other_fn: +// CHECK: callq *foreign_fn@GOTPCREL(%rip) +#[no_mangle] +#[inline(never)] +pub fn other_fn() -> u8 { + unsafe { + foreign_fn() + } +} + +extern "C" {fn foreign_fn() -> u8;} diff --git a/src/test/assembly/pie-relocation-model.rs b/src/test/assembly/pie-relocation-model.rs new file mode 100644 index 0000000000000..e40797e038d4b --- /dev/null +++ b/src/test/assembly/pie-relocation-model.rs @@ -0,0 +1,38 @@ +// revisions: x64 +// assembly-output: emit-asm +// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pie +// [x64] needs-llvm-components: x86 + + +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type="rlib"] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +// CHECK-LABEL: call_other_fn: +// With PIE local functions are called "directly". +// CHECK: {{(jmp|callq)}} other_fn +#[no_mangle] +pub fn call_other_fn() -> u8 { + unsafe { + other_fn() + } +} + +// CHECK-LABEL: other_fn: +// External functions are still called through GOT, since we don't know if the symbol +// is defined in the binary or in the shared library. +// CHECK: callq *foreign_fn@GOTPCREL(%rip) +#[no_mangle] +#[inline(never)] +pub fn other_fn() -> u8 { + unsafe { + foreign_fn() + } +} + +extern "C" {fn foreign_fn() -> u8;} diff --git a/src/test/codegen/pic-relocation-model.rs b/src/test/codegen/pic-relocation-model.rs new file mode 100644 index 0000000000000..6e1d5a6c3f271 --- /dev/null +++ b/src/test/codegen/pic-relocation-model.rs @@ -0,0 +1,16 @@ +// compile-flags: -C relocation-model=pic + +#![crate_type = "rlib"] + +// CHECK: define i8 @call_foreign_fn() +#[no_mangle] +pub fn call_foreign_fn() -> u8 { + unsafe { + foreign_fn() + } +} + +// CHECK: declare zeroext i8 @foreign_fn() +extern "C" {fn foreign_fn() -> u8;} + +// CHECK: !{i32 7, !"PIC Level", i32 2} diff --git a/src/test/codegen/pie-relocation-model.rs b/src/test/codegen/pie-relocation-model.rs new file mode 100644 index 0000000000000..06f93698f90af --- /dev/null +++ b/src/test/codegen/pie-relocation-model.rs @@ -0,0 +1,21 @@ +// compile-flags: -C relocation-model=pie + +#![crate_type = "rlib"] + +// With PIE we know local functions cannot be interpositioned, we can mark them +// as dso_local. +// CHECK: define dso_local i8 @call_foreign_fn() +#[no_mangle] +pub fn call_foreign_fn() -> u8 { + unsafe { + foreign_fn() + } +} + +// External functions are still marked as non-dso_local, since we don't know if the symbol +// is defined in the binary or in the shared library. +// CHECK: declare zeroext i8 @foreign_fn() +extern "C" {fn foreign_fn() -> u8;} + +// CHECK: !{i32 7, !"PIC Level", i32 2} +// CHECK: !{i32 7, !"PIE Level", i32 2} From cef736f8a05bab8d9a16f7120b5800670ef768ee Mon Sep 17 00:00:00 2001 From: Hirochika Matsumoto Date: Sun, 26 Sep 2021 00:53:37 +0900 Subject: [PATCH 09/15] Suggest similarly named assoc items in trait impls Previously, the compiler didn't suggest similarly named associated items unlike we do in many situations. This patch adds such diagnostics for associated functions, types and constants. --- compiler/rustc_resolve/src/diagnostics.rs | 30 +++++++- compiler/rustc_resolve/src/late.rs | 28 +++++-- .../rustc_resolve/src/late/diagnostics.rs | 38 +++++++++- compiler/rustc_resolve/src/lib.rs | 6 +- src/test/ui/error-codes/E0407.stderr | 5 +- src/test/ui/hygiene/assoc_item_ctxt.stderr | 5 +- .../ui/suggestions/suggest-trait-items.rs | 48 ++++++++++++ .../ui/suggestions/suggest-trait-items.stderr | 74 +++++++++++++++++++ 8 files changed, 216 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-trait-items.rs create mode 100644 src/test/ui/suggestions/suggest-trait-items.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 435c79d2daf45..b1d02f90be113 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -198,7 +198,7 @@ impl<'a> Resolver<'a> { err.span_label(first_use_span, format!("first use of `{}`", name)); err } - ResolutionError::MethodNotMemberOfTrait(method, trait_) => { + ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => { let mut err = struct_span_err!( self.session, span, @@ -208,9 +208,17 @@ impl<'a> Resolver<'a> { trait_ ); err.span_label(span, format!("not a member of trait `{}`", trait_)); + if let Some(candidate) = candidate { + err.span_suggestion( + method.span, + "there is an associated function with a similar name", + candidate.to_ident_string(), + Applicability::MaybeIncorrect, + ); + } err } - ResolutionError::TypeNotMemberOfTrait(type_, trait_) => { + ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => { let mut err = struct_span_err!( self.session, span, @@ -220,9 +228,17 @@ impl<'a> Resolver<'a> { trait_ ); err.span_label(span, format!("not a member of trait `{}`", trait_)); + if let Some(candidate) = candidate { + err.span_suggestion( + type_.span, + "there is an associated type with a similar name", + candidate.to_ident_string(), + Applicability::MaybeIncorrect, + ); + } err } - ResolutionError::ConstNotMemberOfTrait(const_, trait_) => { + ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => { let mut err = struct_span_err!( self.session, span, @@ -232,6 +248,14 @@ impl<'a> Resolver<'a> { trait_ ); err.span_label(span, format!("not a member of trait `{}`", trait_)); + if let Some(candidate) = candidate { + err.span_suggestion( + const_.span, + "there is an associated constant with a similar name", + candidate.to_ident_string(), + Applicability::MaybeIncorrect, + ); + } err } ResolutionError::VariableNotBoundInPattern(binding_error) => { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 3c48a76224fd9..9563325796538 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1309,14 +1309,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { use crate::ResolutionError::*; match &item.kind { AssocItemKind::Const(_default, _ty, _expr) => { - debug!("resolve_implementation AssocItemKind::Const",); + debug!("resolve_implementation AssocItemKind::Const"); // If this is a trait impl, ensure the const // exists in trait this.check_trait_item( item.ident, + &item.kind, ValueNS, item.span, - |n, s| ConstNotMemberOfTrait(n, s), + |i, s, c| ConstNotMemberOfTrait(i, s, c), ); // We allow arbitrary const expressions inside of associated consts, @@ -1338,6 +1339,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); } AssocItemKind::Fn(box FnKind(.., generics, _)) => { + debug!("resolve_implementation AssocItemKind::Fn"); // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( generics, @@ -1347,9 +1349,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // exists in trait this.check_trait_item( item.ident, + &item.kind, ValueNS, item.span, - |n, s| MethodNotMemberOfTrait(n, s), + |i, s, c| MethodNotMemberOfTrait(i, s, c), ); visit::walk_assoc_item( @@ -1366,6 +1369,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { _, _, )) => { + debug!("resolve_implementation AssocItemKind::TyAlias"); // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( generics, @@ -1375,9 +1379,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // exists in trait this.check_trait_item( item.ident, + &item.kind, TypeNS, item.span, - |n, s| TypeNotMemberOfTrait(n, s), + |i, s, c| TypeNotMemberOfTrait(i, s, c), ); visit::walk_assoc_item( @@ -1401,9 +1406,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }); } - fn check_trait_item(&mut self, ident: Ident, ns: Namespace, span: Span, err: F) - where - F: FnOnce(Symbol, &str) -> ResolutionError<'_>, + fn check_trait_item( + &mut self, + ident: Ident, + kind: &AssocItemKind, + ns: Namespace, + span: Span, + err: F, + ) where + F: FnOnce(Ident, &str, Option) -> ResolutionError<'_>, { // If there is a TraitRef in scope for an impl, then the method must be in the // trait. @@ -1420,8 +1431,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ) .is_err() { + let candidate = self.find_similarly_named_assoc_item(ident.name, kind); let path = &self.current_trait_ref.as_ref().unwrap().1.path; - self.report_error(span, err(ident.name, &path_names_to_string(path))); + self.report_error(span, err(ident, &path_names_to_string(path), candidate)); } } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 19136c6ceeb1f..0e6ca1856bb30 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -7,8 +7,8 @@ use crate::{PathResult, PathSource, Segment}; use rustc_ast::visit::FnKind; use rustc_ast::{ - self as ast, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, NodeId, Path, Ty, - TyKind, + self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind, + NodeId, Path, Ty, TyKind, }; use rustc_ast_pretty::pprust::path_segment_to_string; use rustc_data_structures::fx::FxHashSet; @@ -1144,6 +1144,40 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { true } + /// Given the target `ident` and `kind`, search for the similarly named associated item + /// in `self.current_trait_ref`. + crate fn find_similarly_named_assoc_item( + &mut self, + ident: Symbol, + kind: &AssocItemKind, + ) -> Option { + let module = if let Some((module, _)) = self.current_trait_ref { + module + } else { + return None; + }; + if ident == kw::Underscore { + // We do nothing for `_`. + return None; + } + + let resolutions = self.r.resolutions(module); + let targets = resolutions + .borrow() + .iter() + .filter_map(|(key, res)| res.borrow().binding.map(|binding| (key, binding.res()))) + .filter(|(_, res)| match (kind, res) { + (AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true, + (AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true, + (AssocItemKind::TyAlias(..), Res::Def(DefKind::AssocTy, _)) => true, + _ => false, + }) + .map(|(key, _)| key.ident.name) + .collect::>(); + + find_best_match_for_name(&targets, ident, None) + } + fn lookup_assoc_candidate( &mut self, ident: Ident, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 68db06370ffea..22d77d4432159 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -202,11 +202,11 @@ enum ResolutionError<'a> { /// parameter list. NameAlreadyUsedInParameterList(Symbol, Span), /// Error E0407: method is not a member of trait. - MethodNotMemberOfTrait(Symbol, &'a str), + MethodNotMemberOfTrait(Ident, &'a str, Option), /// Error E0437: type is not a member of trait. - TypeNotMemberOfTrait(Symbol, &'a str), + TypeNotMemberOfTrait(Ident, &'a str, Option), /// Error E0438: const is not a member of trait. - ConstNotMemberOfTrait(Symbol, &'a str), + ConstNotMemberOfTrait(Ident, &'a str, Option), /// Error E0408: variable `{}` is not bound in all patterns. VariableNotBoundInPattern(&'a BindingError), /// Error E0409: variable `{}` is bound in inconsistent ways within the same match arm. diff --git a/src/test/ui/error-codes/E0407.stderr b/src/test/ui/error-codes/E0407.stderr index 567fc879040d3..6f6d1ff6a8f41 100644 --- a/src/test/ui/error-codes/E0407.stderr +++ b/src/test/ui/error-codes/E0407.stderr @@ -2,7 +2,10 @@ error[E0407]: method `b` is not a member of trait `Foo` --> $DIR/E0407.rs:9:5 | LL | fn b() {} - | ^^^^^^^^^ not a member of trait `Foo` + | ^^^-^^^^^ + | | | + | | help: there is an associated function with a similar name: `a` + | not a member of trait `Foo` error: aborting due to previous error diff --git a/src/test/ui/hygiene/assoc_item_ctxt.stderr b/src/test/ui/hygiene/assoc_item_ctxt.stderr index 6e4fecf0ce4b2..517b1ff598888 100644 --- a/src/test/ui/hygiene/assoc_item_ctxt.stderr +++ b/src/test/ui/hygiene/assoc_item_ctxt.stderr @@ -2,7 +2,10 @@ error[E0407]: method `method` is not a member of trait `Tr` --> $DIR/assoc_item_ctxt.rs:35:13 | LL | fn method() {} - | ^^^^^^^^^^^^^^ not a member of trait `Tr` + | ^^^------^^^^^ + | | | + | | help: there is an associated function with a similar name: `method` + | not a member of trait `Tr` ... LL | mac_trait_impl!(); | ------------------ in this macro invocation diff --git a/src/test/ui/suggestions/suggest-trait-items.rs b/src/test/ui/suggestions/suggest-trait-items.rs new file mode 100644 index 0000000000000..9d42a73426096 --- /dev/null +++ b/src/test/ui/suggestions/suggest-trait-items.rs @@ -0,0 +1,48 @@ +trait Foo { + type Type; + + fn foo(); + fn bar(); + fn qux(); +} + +struct A; + +impl Foo for A { +//~^ ERROR not all trait items implemented + type Typ = (); + //~^ ERROR type `Typ` is not a member of trait + //~| HELP there is an associated type with a similar name + + fn fooo() {} + //~^ ERROR method `fooo` is not a member of trait + //~| HELP there is an associated function with a similar name + + fn barr() {} + //~^ ERROR method `barr` is not a member of trait + //~| HELP there is an associated function with a similar name + + fn quux() {} + //~^ ERROR method `quux` is not a member of trait + //~| HELP there is an associated function with a similar name +} +//~^ HELP implement the missing item +//~| HELP implement the missing item +//~| HELP implement the missing item +//~| HELP implement the missing item + +trait Bar { + const Const: i32; +} + +struct B; + +impl Bar for B { +//~^ ERROR not all trait items implemented + const Cnst: i32 = 0; + //~^ ERROR const `Cnst` is not a member of trait + //~| HELP there is an associated constant with a similar name +} +//~^ HELP implement the missing item + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-trait-items.stderr b/src/test/ui/suggestions/suggest-trait-items.stderr new file mode 100644 index 0000000000000..151bae7d1b9cb --- /dev/null +++ b/src/test/ui/suggestions/suggest-trait-items.stderr @@ -0,0 +1,74 @@ +error[E0437]: type `Typ` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:13:5 + | +LL | type Typ = (); + | ^^^^^---^^^^^^ + | | | + | | help: there is an associated type with a similar name: `Type` + | not a member of trait `Foo` + +error[E0407]: method `fooo` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:17:5 + | +LL | fn fooo() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `foo` + | not a member of trait `Foo` + +error[E0407]: method `barr` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:21:5 + | +LL | fn barr() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `bar` + | not a member of trait `Foo` + +error[E0407]: method `quux` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:25:5 + | +LL | fn quux() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `qux` + | not a member of trait `Foo` + +error[E0438]: const `Cnst` is not a member of trait `Bar` + --> $DIR/suggest-trait-items.rs:42:5 + | +LL | const Cnst: i32 = 0; + | ^^^^^^----^^^^^^^^^^ + | | | + | | help: there is an associated constant with a similar name: `Const` + | not a member of trait `Bar` + +error[E0046]: not all trait items implemented, missing: `Type`, `foo`, `bar`, `qux` + --> $DIR/suggest-trait-items.rs:11:1 + | +LL | type Type; + | ---------- `Type` from trait +LL | +LL | fn foo(); + | --------- `foo` from trait +LL | fn bar(); + | --------- `bar` from trait +LL | fn qux(); + | --------- `qux` from trait +... +LL | impl Foo for A { + | ^^^^^^^^^^^^^^ missing `Type`, `foo`, `bar`, `qux` in implementation + +error[E0046]: not all trait items implemented, missing: `Const` + --> $DIR/suggest-trait-items.rs:40:1 + | +LL | const Const: i32; + | ----------------- `Const` from trait +... +LL | impl Bar for B { + | ^^^^^^^^^^^^^^ missing `Const` in implementation + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0046, E0407, E0437, E0438. +For more information about an error, try `rustc --explain E0046`. From cb8e83caeba7268ebb3515468d348aea7af9fdae Mon Sep 17 00:00:00 2001 From: Gus Wynn Date: Tue, 28 Sep 2021 17:57:08 -0700 Subject: [PATCH 10/15] ref/refmut --- library/core/src/cell.rs | 10 ++++++++++ library/core/src/lib.rs | 1 + library/std/src/sync/mutex.rs | 2 +- library/std/src/sync/rwlock.rs | 2 +- src/test/ui/lint/must_not_suspend/mutex.stderr | 2 +- 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index e56b631dbaf8d..c0121eebb7fef 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1303,6 +1303,11 @@ impl Clone for BorrowRef<'_> { /// /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "Holding a Ref across suspend \ + points can cause BorrowErrors" +)] pub struct Ref<'b, T: ?Sized + 'b> { value: &'b T, borrow: BorrowRef<'b>, @@ -1679,6 +1684,11 @@ impl<'b> BorrowRefMut<'b> { /// /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr( + not(bootstrap), + must_not_suspend = "Holding a RefMut across suspend \ + points can cause BorrowErrors" +)] pub struct RefMut<'b, T: ?Sized + 'b> { value: &'b mut T, borrow: BorrowRefMut<'b>, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 265ba9f1bb91b..2230461b5f4b5 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -141,6 +141,7 @@ #![feature(link_llvm_intrinsics)] #![feature(llvm_asm)] #![feature(min_specialization)] +#![cfg_attr(not(bootstrap), feature(must_not_suspend))] #![feature(negative_impls)] #![feature(never_type)] #![feature(no_core)] diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index 9abd4b547c77e..06a97fd3f7610 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -192,7 +192,7 @@ unsafe impl Sync for Mutex {} not(bootstrap), must_not_suspend = "Holding a MutexGuard across suspend \ points can cause deadlocks, delays, \ - and cause Future's to not implement `Send`" + and cause Futures to not implement `Send`" )] #[stable(feature = "rust1", since = "1.0.0")] pub struct MutexGuard<'a, T: ?Sized + 'a> { diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 1523d36323fd9..aa1ce82d96799 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -99,7 +99,7 @@ unsafe impl Sync for RwLock {} not(bootstrap), must_not_suspend = "Holding a RwLockReadGuard across suspend \ points can cause deadlocks, delays, \ - and cause Future's to not implement `Send`" + and cause Futures to not implement `Send`" )] #[stable(feature = "rust1", since = "1.0.0")] pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { diff --git a/src/test/ui/lint/must_not_suspend/mutex.stderr b/src/test/ui/lint/must_not_suspend/mutex.stderr index 47a84fdbc5731..4e0d9343c2c71 100644 --- a/src/test/ui/lint/must_not_suspend/mutex.stderr +++ b/src/test/ui/lint/must_not_suspend/mutex.stderr @@ -11,7 +11,7 @@ note: the lint level is defined here | LL | #![deny(must_not_suspend)] | ^^^^^^^^^^^^^^^^ -note: Holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Future's to not implement `Send` +note: Holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send` --> $DIR/mutex.rs:7:9 | LL | let _guard = m.lock().unwrap(); From 6e973f08508fddc095c1cef20e07110c918e72e8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 27 Sep 2021 17:16:04 -0700 Subject: [PATCH 11/15] fix(lint): don't suggest refutable patterns to "fix" irrefutable bind In function arguments and let bindings, do not suggest changing `C` to `Foo::C` unless `C` is the only variant of `Foo`, because it won't work. The general warning is still kept, because code like this is confusing. Fixes #88730 --- .../src/thir/pattern/check_match.rs | 55 ++++++++++++------- src/test/ui/suggestions/issue-88730.rs | 16 ++++++ src/test/ui/suggestions/issue-88730.stderr | 21 +++++++ 3 files changed, 73 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/suggestions/issue-88730.rs create mode 100644 src/test/ui/suggestions/issue-88730.stderr diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 08f8850e78ed2..e28fd2c50814f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -39,6 +39,13 @@ fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBu struct_span_err!(sess, sp, E0004, "{}", &error_message) } +#[derive(PartialEq)] +enum RefutableFlag { + Irrefutable, + Refutable, +} +use RefutableFlag::*; + struct MatchVisitor<'a, 'p, 'tcx> { tcx: TyCtxt<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, @@ -73,13 +80,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> { hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None), }; self.check_irrefutable(&loc.pat, msg, sp); - self.check_patterns(&loc.pat); + self.check_patterns(&loc.pat, Irrefutable); } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { intravisit::walk_param(self, param); self.check_irrefutable(¶m.pat, "function argument", None); - self.check_patterns(¶m.pat); + self.check_patterns(¶m.pat, Irrefutable); } } @@ -113,9 +120,9 @@ impl PatCtxt<'_, '_> { } impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { - fn check_patterns(&self, pat: &Pat<'_>) { + fn check_patterns(&self, pat: &Pat<'_>, rf: RefutableFlag) { pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat)); - check_for_bindings_named_same_as_variants(self, pat); + check_for_bindings_named_same_as_variants(self, pat, rf); } fn lower_pattern( @@ -145,7 +152,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, expr: &hir::Expr<'_>, span: Span) { - self.check_patterns(pat); + self.check_patterns(pat, Refutable); let mut cx = self.new_cx(expr.hir_id); let tpat = self.lower_pattern(&mut cx, pat, &mut false); check_let_reachability(&mut cx, pat.hir_id, tpat, span); @@ -161,9 +168,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { for arm in arms { // Check the arm for some things unrelated to exhaustiveness. - self.check_patterns(&arm.pat); + self.check_patterns(&arm.pat, Refutable); if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard { - self.check_patterns(pat); + self.check_patterns(pat, Refutable); let tpat = self.lower_pattern(&mut cx, pat, &mut false); check_let_reachability(&mut cx, pat.hir_id, tpat, tpat.span()); } @@ -297,7 +304,11 @@ fn const_not_var( } } -fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_, '_>, pat: &Pat<'_>) { +fn check_for_bindings_named_same_as_variants( + cx: &MatchVisitor<'_, '_, '_>, + pat: &Pat<'_>, + rf: RefutableFlag, +) { pat.walk_always(|p| { if let hir::PatKind::Binding(_, _, ident, None) = p.kind { if let Some(ty::BindByValue(hir::Mutability::Not)) = @@ -310,25 +321,31 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_, '_>, pat: variant.ident == ident && variant.ctor_kind == CtorKind::Const }) { + let variant_count = edef.variants.len(); cx.tcx.struct_span_lint_hir( BINDINGS_WITH_VARIANT_NAME, p.hir_id, p.span, |lint| { let ty_path = cx.tcx.def_path_str(edef.did); - lint.build(&format!( + let mut err = lint.build(&format!( "pattern binding `{}` is named the same as one \ - of the variants of the type `{}`", + of the variants of the type `{}`", ident, ty_path - )) - .code(error_code!(E0170)) - .span_suggestion( - p.span, - "to match on the variant, qualify the path", - format!("{}::{}", ty_path, ident), - Applicability::MachineApplicable, - ) - .emit(); + )); + err.code(error_code!(E0170)); + // If this is an irrefutable pattern, and there's > 1 variant, + // then we can't actually match on this. Applying the below + // suggestion would produce code that breaks on `check_irrefutable`. + if rf == Refutable || variant_count == 1 { + err.span_suggestion( + p.span, + "to match on the variant, qualify the path", + format!("{}::{}", ty_path, ident), + Applicability::MachineApplicable, + ); + } + err.emit(); }, ) } diff --git a/src/test/ui/suggestions/issue-88730.rs b/src/test/ui/suggestions/issue-88730.rs new file mode 100644 index 0000000000000..e63210a3e987e --- /dev/null +++ b/src/test/ui/suggestions/issue-88730.rs @@ -0,0 +1,16 @@ +#![allow(unused, nonstandard_style)] +#![deny(bindings_with_variant_name)] + +// If an enum has two different variants, +// then it cannot be matched upon in a function argument. +// It still gets a warning, but no suggestions. +enum Foo { + C, + D, +} + +fn foo(C: Foo) {} //~ERROR + +fn main() { + let C = Foo::D; //~ERROR +} diff --git a/src/test/ui/suggestions/issue-88730.stderr b/src/test/ui/suggestions/issue-88730.stderr new file mode 100644 index 0000000000000..eb22b0ea5c83d --- /dev/null +++ b/src/test/ui/suggestions/issue-88730.stderr @@ -0,0 +1,21 @@ +error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-88730.rs:12:8 + | +LL | fn foo(C: Foo) {} + | ^ + | +note: the lint level is defined here + --> $DIR/issue-88730.rs:2:9 + | +LL | #![deny(bindings_with_variant_name)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-88730.rs:15:9 + | +LL | let C = Foo::D; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0170`. From 35f74c24a3c205eeb85717e4a0cd8535b7ac8f0e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Sep 2021 13:43:22 -0400 Subject: [PATCH 12/15] remove outdated comment --- compiler/rustc_const_eval/src/interpret/step.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index bcce19b28db97..bbf7f3a5c3d40 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -253,7 +253,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Len(place) => { - // FIXME(CTFE): don't allow computing the length of arrays in const eval let src = self.eval_place(place)?; let mplace = self.force_allocation(&src)?; let len = mplace.len(self)?; From 268bb46db29299d8946cafdc70d8c1eaf2756106 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Sep 2021 13:47:41 -0400 Subject: [PATCH 13/15] CTFE: extra assertions for Aggregate rvalues; remove unnecessarily eager special case --- compiler/rustc_const_eval/src/interpret/step.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index bbf7f3a5c3d40..e6037d561dedc 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -197,12 +197,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Aggregate(ref kind, ref operands) => { + // active_field_index is for union initialization. let (dest, active_field_index) = match **kind { mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { self.write_discriminant(variant_index, &dest)?; if adt_def.is_enum() { - (self.place_downcast(&dest, variant_index)?, active_field_index) + assert!(active_field_index.is_none()); + (self.place_downcast(&dest, variant_index)?, None) } else { + if active_field_index.is_some() { + assert_eq!(operands.len(), 1); + } (dest, active_field_index) } } @@ -211,12 +216,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for (i, operand) in operands.iter().enumerate() { let op = self.eval_operand(operand, None)?; - // Ignore zero-sized fields. - if !op.layout.is_zst() { - let field_index = active_field_index.unwrap_or(i); - let field_dest = self.place_field(&dest, field_index)?; - self.copy_op(&op, &field_dest)?; - } + let field_index = active_field_index.unwrap_or(i); + let field_dest = self.place_field(&dest, field_index)?; + self.copy_op(&op, &field_dest)?; } } From 1cf905fdab95d8fe022a2c0ec5ad72083c08d323 Mon Sep 17 00:00:00 2001 From: Ben Reeves Date: Thu, 30 Sep 2021 02:02:32 -0500 Subject: [PATCH 14/15] bootstrap: Update comment in config.library.toml. Downloading LLVM from CI works for all platforms now. --- src/bootstrap/defaults/config.library.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index 9874fdb767f62..9afa937f50d3b 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -10,6 +10,6 @@ bench-stage = 0 incremental = true [llvm] -# Will download LLVM from CI if available on your platform (Linux only for now) +# Will download LLVM from CI if available on your platform. # https://github.com/rust-lang/rust/issues/77084 tracks support for more platforms download-ci-llvm = "if-available" From 098d86236babe4fae142d2154be122b63726c4c9 Mon Sep 17 00:00:00 2001 From: Ben Reeves Date: Thu, 30 Sep 2021 11:25:20 -0500 Subject: [PATCH 15/15] bootstrap: Update comment (again) in config.library.toml --- src/bootstrap/defaults/config.library.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index 9afa937f50d3b..7bc054d3a49fc 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -11,5 +11,4 @@ incremental = true [llvm] # Will download LLVM from CI if available on your platform. -# https://github.com/rust-lang/rust/issues/77084 tracks support for more platforms download-ci-llvm = "if-available"