From 4a8ba05a8361b5db3d8fd0907efd993be4d4d5b5 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Thu, 9 Nov 2023 17:24:19 +0100 Subject: [PATCH 1/6] Making `User` and `User<[T]>` `Send` --- library/std/src/sys/sgx/abi/usercalls/alloc.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 817c33b660370..f99cea360f1f4 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -185,6 +185,12 @@ pub struct UserRef(UnsafeCell); #[unstable(feature = "sgx_platform", issue = "56975")] pub struct User(NonNull>); +#[unstable(feature = "sgx_platform", issue = "56975")] +unsafe impl Send for User {} + +#[unstable(feature = "sgx_platform", issue = "56975")] +unsafe impl Send for User<[T]> {} + trait NewUserRef { unsafe fn new_userref(v: T) -> Self; } From a2b79cd92f41fd83f08194b43b034f9e227a33bb Mon Sep 17 00:00:00 2001 From: Patryk Wychowaniec Date: Tue, 5 Dec 2023 15:58:07 +0100 Subject: [PATCH 2/6] chore: Bump compiler_builtins Actually closes https://github.com/rust-lang/rust/issues/118079. --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1b5ea30f5042..cb9fcde8854d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -704,9 +704,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "compiler_builtins" -version = "0.1.103" +version = "0.1.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b73c3443a5fd2438d7ba4853c64e4c8efc2404a9e28a9234cc2d5eebc6c242" +checksum = "99c3f9035afc33f4358773239573f7d121099856753e1bbd2a6a5207098fc741" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index f666b18887cb1..3f889f668c743 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } libc = { version = "0.2.150", default-features = false, features = ['rustc-dep-of-std'], public = true } -compiler_builtins = { version = "0.1.103" } +compiler_builtins = { version = "0.1.104" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] } @@ -49,8 +49,8 @@ hermit-abi = { version = "0.3.2", features = ['rustc-dep-of-std'], public = true wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false } [target.'cfg(target_os = "uefi")'.dependencies] -r-efi = { version = "4.2.0", features = ['rustc-dep-of-std']} -r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std']} +r-efi = { version = "4.2.0", features = ['rustc-dep-of-std'] } +r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std'] } [features] backtrace = [ From e44b11f6952659e7cb4e66ee3b5ff47bb7bc6c31 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 7 Jan 2024 22:53:50 +0000 Subject: [PATCH 3/6] ~const trait or projection bounds do not imply non-const bounds --- compiler/rustc_hir_analysis/src/bounds.rs | 18 ---- .../src/collect/predicates_of.rs | 38 ++------ .../assoc-type-const-bound-usage.rs | 2 +- .../assoc-type-const-bound-usage.stderr | 16 ++-- .../const-fns-are-early-bound.rs | 86 +++++++++++++++++++ .../effects/minicore.rs | 17 ++-- .../effects/project.rs | 9 +- .../effects/project.stderr | 65 ++++++++++++++ .../trait-where-clause-const.stderr | 34 +++++--- .../unsatisfied-const-trait-bound.rs | 2 +- .../unsatisfied-const-trait-bound.stderr | 10 +-- 11 files changed, 214 insertions(+), 83 deletions(-) create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index b6688e0ce29e0..b69f679880dbf 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -45,24 +45,6 @@ impl<'tcx> Bounds<'tcx> { polarity: ty::ImplPolarity, ) { self.push_trait_bound_inner(tcx, trait_ref, span, polarity); - - // push a non-const (`host = true`) version of the bound if it is `~const`. - if tcx.features().effects - && let Some(host_effect_idx) = tcx.generics_of(trait_ref.def_id()).host_effect_index - && trait_ref.skip_binder().args.const_at(host_effect_idx) != tcx.consts.true_ - { - let generics = tcx.generics_of(trait_ref.def_id()); - let Some(host_index) = generics.host_effect_index else { return }; - let trait_ref = trait_ref.map_bound(|mut trait_ref| { - trait_ref.args = - tcx.mk_args_from_iter(trait_ref.args.iter().enumerate().map(|(n, arg)| { - if host_index == n { tcx.consts.true_.into() } else { arg } - })); - trait_ref - }); - - self.push_trait_bound_inner(tcx, trait_ref, span, polarity); - } } fn push_trait_bound_inner( diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 41520718aa8d1..ab9ed6ef98d9f 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate}; use rustc_span::symbol::Ident; -use rustc_span::{sym, Span, DUMMY_SP}; +use rustc_span::{Span, DUMMY_SP}; /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus @@ -38,38 +38,12 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic // an obligation and instead be skipped. Otherwise we'd use // `tcx.def_span(def_id);` let span = rustc_span::DUMMY_SP; - let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) { - // when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound, - // because only implementing `Self: Trait<.., false>` is currently not possible. - Some(( - ty::TraitRef::new( - tcx, - def_id, - ty::GenericArgs::for_item(tcx, def_id, |param, _| { - if param.is_host_effect() { - tcx.consts.true_.into() - } else { - tcx.mk_param_from_def(param) - } - }), - ) - .to_predicate(tcx), + + result.predicates = + tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( + ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), span, - )) - } else { - None - }; - result.predicates = tcx.arena.alloc_from_iter( - result - .predicates - .iter() - .copied() - .chain(std::iter::once(( - ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), - span, - ))) - .chain(non_const_bound), - ); + )))); } debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); result diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs index f41c1051fceaa..16b717bc18131 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs @@ -9,7 +9,7 @@ trait Foo { } const fn foo() { - ::Assoc::foo(); + ::Assoc::foo(); } fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr index 1b88839984f4d..268e337ee93e6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr @@ -6,15 +6,17 @@ LL | type Assoc: ~const Foo; | = note: this item cannot have `~const` trait bounds -error[E0308]: mismatched types - --> $DIR/assoc-type-const-bound-usage.rs:12:5 +error[E0277]: the trait bound `T: Foo` is not satisfied + --> $DIR/assoc-type-const-bound-usage.rs:12:6 | -LL | ::Assoc::foo(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `host`, found `true` +LL | ::Assoc::foo(); + | ^ the trait `Foo` is not implemented for `T` | - = note: expected constant `host` - found constant `true` +help: consider further restricting this bound + | +LL | const fn foo() { + | +++++ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs new file mode 100644 index 0000000000000..f3480fcc9eed4 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs @@ -0,0 +1,86 @@ +// check-pass + +#![crate_type = "lib"] +#![allow(internal_features)] +#![no_std] +#![no_core] +#![feature( + auto_traits, + const_trait_impl, + effects, + lang_items, + no_core, + staged_api, + unboxed_closures +)] +#![stable(feature = "minicore", since = "1.0.0")] + +fn test() { + fn is_const_fn(_: F) + where + F: const FnOnce<()>, + { + } + + const fn foo() {} + + is_const_fn(foo); +} + +/// ---------------------------------------------------------------------- /// +/// Const fn trait definitions + +#[const_trait] +#[lang = "fn"] +#[rustc_paren_sugar] +trait Fn: ~const FnMut { + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_mut"] +#[rustc_paren_sugar] +trait FnMut: ~const FnOnce { + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +#[const_trait] +#[lang = "fn_once"] +#[rustc_paren_sugar] +trait FnOnce { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +/// ---------------------------------------------------------------------- /// +/// All this other stuff needed for core. Unrelated to test. + +#[lang = "destruct"] +#[const_trait] +trait Destruct {} + +#[lang = "freeze"] +unsafe auto trait Freeze {} + +#[lang = "drop"] +#[const_trait] +trait Drop { + fn drop(&mut self); +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[lang = "tuple_trait"] +trait Tuple {} + +#[lang = "receiver"] +trait Receiver {} + +impl Receiver for &T {} + +impl Receiver for &mut T {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs index 59fb48e794cc3..84d9bcd7ac9f0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -40,7 +40,7 @@ const fn bar() { #[lang = "Try"] #[const_trait] -trait Try: FromResidual { +trait Try: FromResidual { type Output; type Residual; @@ -53,7 +53,7 @@ trait Try: FromResidual { // FIXME // #[const_trait] -trait FromResidual::Residual> { +trait FromResidual::Residual> { #[lang = "from_residual"] fn from_residual(residual: R) -> Self; } @@ -519,9 +519,14 @@ extern "rust-intrinsic" { called_in_const: F, called_at_rt: G, ) -> RET - /* where clauses enforced by built-in method confirmation: where - F: const FnOnce, - G: FnOnce, - */; + F: const FnOnce, + G: FnOnce; +} + +fn test_const_eval_select() { + const fn const_fn() {} + fn rt_fn() {} + + unsafe { const_eval_select((), const_fn, rt_fn); } } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs index b30d7743edfc4..e22eed3e0ef57 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.rs @@ -1,7 +1,12 @@ -// check-pass +// known-bug: #110395 +// FIXME: effects + #![feature(const_trait_impl, effects)] -pub trait Owo::T> {} +// This fails because `~const Uwu` doesn't imply (non-const) `Uwu`. + +// FIXME: #[const_trait] +pub trait Owo::T> {} #[const_trait] pub trait Uwu: Owo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr new file mode 100644 index 0000000000000..eac3ee9e4e22b --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/project.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:12:1 + | +LL | pub trait Uwu: Owo { + | ^^^^^^^^^^^^^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:12:1 + | +LL | / pub trait Uwu: Owo { +LL | | type T; +LL | | } + | |_^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:12:16 + | +LL | pub trait Uwu: Owo { + | ^^^ the trait `Uwu` is not implemented for `Self` + | +note: required by a bound in `Owo` + --> $DIR/project.rs:9:15 + | +LL | pub trait Owo::T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Owo` +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:5 + | +LL | type T; + | ^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { + | +++++ + +error[E0277]: the trait bound `Self: Uwu` is not satisfied + --> $DIR/project.rs:13:5 + | +LL | type T; + | ^^^^^^^ the trait `Uwu` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | pub trait Uwu: Owo + Uwu { + | +++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr index 2a9647da7823d..0141dcfb06f6b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -1,21 +1,35 @@ -error[E0308]: mismatched types +error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause-const.rs:21:5 | LL | T::b(); - | ^^^^^^ expected `host`, found `true` + | ^ the trait `~const Bar` is not implemented for `T` | - = note: expected constant `host` - found constant `true` +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause-const.rs:15:24 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^^^^^ required by this bound in `Foo::b` +help: consider further restricting this bound + | +LL | const fn test1() { + | ++++++++++++ -error[E0308]: mismatched types - --> $DIR/trait-where-clause-const.rs:23:5 +error[E0277]: the trait bound `T: ~const Bar` is not satisfied + --> $DIR/trait-where-clause-const.rs:23:12 | LL | T::c::(); - | ^^^^^^^^^^^ expected `host`, found `true` + | ^ the trait `~const Bar` is not implemented for `T` + | +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause-const.rs:16:13 + | +LL | fn c(); + | ^^^^^^^^^^ required by this bound in `Foo::c` +help: consider further restricting this bound | - = note: expected constant `host` - found constant `true` +LL | const fn test1() { + | ++++++++++++ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs index 62a7b31237842..8f441410c1784 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs @@ -30,4 +30,4 @@ fn accept0(_: Container<{ T::make() }>) {} // FIXME(effects): Instead of suggesting `+ const Trait`, suggest // changing `~const Trait` to `const Trait`. const fn accept1(_: Container<{ T::make() }>) {} -//~^ ERROR the trait bound `T: const Trait` is not satisfied +//~^ ERROR mismatched types diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr index 2fb4fc1aa2b8e..258f95b5c4a89 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr @@ -7,16 +7,14 @@ LL | fn accept0(_: Container<{ T::make() }>) {} = note: expected constant `false` found constant `true` -error[E0277]: the trait bound `T: const Trait` is not satisfied +error[E0308]: mismatched types --> $DIR/unsatisfied-const-trait-bound.rs:32:50 | LL | const fn accept1(_: Container<{ T::make() }>) {} - | ^ the trait `const Trait` is not implemented for `T` - | -help: consider further restricting this bound + | ^^^^^^^^^ expected `false`, found `host` | -LL | const fn accept1(_: Container<{ T::make() }>) {} - | +++++++++++++ + = note: expected constant `false` + found constant `host` error[E0277]: the trait bound `Ty: const Trait` is not satisfied --> $DIR/unsatisfied-const-trait-bound.rs:20:15 From 760673e97d48e131b87ec738cb7106c5f8abe55e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 8 Jan 2024 01:07:14 +0000 Subject: [PATCH 4/6] Remove logic in one_bound in astconv that prefers non-const bounds --- .../rustc_hir_analysis/src/astconv/mod.rs | 35 ++----------------- .../const-impl-trait.rs | 2 ++ .../const-impl-trait.stderr | 21 +++++------ 3 files changed, 13 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 092df257dbfae..70f0c9bc4325b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1032,7 +1032,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.trait_defines_associated_item_named(r.def_id(), assoc_kind, assoc_name) }); - let Some(mut bound) = matching_candidates.next() else { + let Some(bound) = matching_candidates.next() else { let reported = self.complain_about_assoc_item_not_found( all_candidates, &ty_param_name.to_string(), @@ -1046,38 +1046,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; debug!(?bound); - // look for a candidate that is not the same as our first bound, disregarding - // whether the bound is const. - let mut next_cand = matching_candidates.next(); - while let Some(mut bound2) = next_cand { - debug!(?bound2); - if bound2.bound_vars() != bound.bound_vars() { - break; - } - - let generics = tcx.generics_of(bound.def_id()); - let Some(host_index) = generics.host_effect_index else { break }; - - // always return the bound that contains the host param. - if let ty::ConstKind::Param(_) = bound2.skip_binder().args.const_at(host_index).kind() { - (bound, bound2) = (bound2, bound); - } - - let unconsted_args = bound - .skip_binder() - .args - .iter() - .enumerate() - .map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg }); - - if unconsted_args.eq(bound2.skip_binder().args.iter()) { - next_cand = matching_candidates.next(); - } else { - break; - } - } - - if let Some(bound2) = next_cand { + if let Some(bound2) = matching_candidates.next() { debug!(?bound2); let assoc_kind_str = assoc_kind_str(assoc_kind); diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs index 14d306fc31f6b..9d579e67a4be4 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs @@ -1,4 +1,6 @@ // known-bug: #110395 +// Broken until we have `&T: const Deref` impl in stdlib + #![allow(incomplete_features)] #![feature( associated_type_bounds, diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr index d0ca1b19ad17d..d4be71f2f4661 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: can't compare `()` with `()` - --> $DIR/const-impl-trait.rs:35:17 + --> $DIR/const-impl-trait.rs:37:17 | LL | assert!(cmp(&())); | --- ^^^ no implementation for `() == ()` @@ -9,23 +9,20 @@ LL | assert!(cmp(&())); = help: the trait `const PartialEq` is not implemented for `()` = help: the trait `PartialEq` is implemented for `()` note: required by a bound in `cmp` - --> $DIR/const-impl-trait.rs:12:23 + --> $DIR/const-impl-trait.rs:14:23 | LL | const fn cmp(a: &impl ~const PartialEq) -> bool { | ^^^^^^^^^^^^^^^^ required by this bound in `cmp` -error[E0277]: can't compare `&impl ~const PartialEq` with `&impl ~const PartialEq` - --> $DIR/const-impl-trait.rs:13:7 +error[E0369]: binary operation `==` cannot be applied to type `&impl ~const PartialEq` + --> $DIR/const-impl-trait.rs:15:7 | LL | a == a - | ^^ no implementation for `&impl ~const PartialEq == &impl ~const PartialEq` - | - = help: the trait `~const PartialEq<&impl ~const PartialEq>` is not implemented for `&impl ~const PartialEq` -help: consider dereferencing both sides of the expression - | -LL | *a == *a - | + + + | - ^^ - &impl ~const PartialEq + | | + | &impl ~const PartialEq error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0369. +For more information about an error, try `rustc --explain E0277`. From 684aa2c9d11d9e818ea65f7e4ebd194b97318ac7 Mon Sep 17 00:00:00 2001 From: David Koloski Date: Wed, 6 Dec 2023 18:25:13 +0000 Subject: [PATCH 5/6] Add support for shell argfiles --- Cargo.lock | 1 + compiler/rustc_driver_impl/Cargo.toml | 1 + compiler/rustc_driver_impl/src/args.rs | 107 +++++++++++++++--- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 + .../src/compiler-flags/shell-argfiles.md | 11 ++ src/tools/tidy/src/deps.rs | 1 + src/tools/tidy/src/ui_tests.rs | 6 +- .../shell-argfiles-badquotes-windows.rs | 11 ++ .../shell-argfiles-badquotes-windows.stderr | 2 + .../shell-argfiles-badquotes.args | 1 + .../shell-argfiles-badquotes.rs | 12 ++ .../shell-argfiles-badquotes.stderr | 2 + .../shell-argfiles-via-argfile-shell.args | 1 + .../shell-argfiles-via-argfile.args | 1 + .../shell-argfiles-via-argfile.rs | 10 ++ tests/ui/shell-argfiles/shell-argfiles.args | 3 + tests/ui/shell-argfiles/shell-argfiles.rs | 19 ++++ 18 files changed, 175 insertions(+), 17 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/shell-argfiles.md create mode 100644 tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.rs create mode 100644 tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr create mode 100644 tests/ui/shell-argfiles/shell-argfiles-badquotes.args create mode 100644 tests/ui/shell-argfiles/shell-argfiles-badquotes.rs create mode 100644 tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr create mode 100644 tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args create mode 100644 tests/ui/shell-argfiles/shell-argfiles-via-argfile.args create mode 100644 tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs create mode 100644 tests/ui/shell-argfiles/shell-argfiles.args create mode 100644 tests/ui/shell-argfiles/shell-argfiles.rs diff --git a/Cargo.lock b/Cargo.lock index b8192e333fe91..c7fa0b5675286 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3738,6 +3738,7 @@ dependencies = [ "rustc_trait_selection", "rustc_ty_utils", "serde_json", + "shlex", "time", "tracing", "windows", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 490429845538d..97a7dfef3b395 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -50,6 +50,7 @@ rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" +shlex = "1.0" time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] } tracing = { version = "0.1.35" } # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index b7407f5a508e4..5dfd37a6da4de 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -5,18 +5,92 @@ use std::io; use rustc_session::EarlyDiagCtxt; -fn arg_expand(arg: String) -> Result, Error> { - if let Some(path) = arg.strip_prefix('@') { - let file = match fs::read_to_string(path) { - Ok(file) => file, - Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { - return Err(Error::Utf8Error(Some(path.to_string()))); +/// Expands argfiles in command line arguments. +#[derive(Default)] +struct Expander { + shell_argfiles: bool, + next_is_unstable_option: bool, + expanded: Vec, +} + +impl Expander { + /// Handles the next argument. If the argument is an argfile, it is expanded + /// inline. + fn arg(&mut self, arg: &str) -> Result<(), Error> { + if let Some(argfile) = arg.strip_prefix('@') { + match argfile.split_once(':') { + Some(("shell", path)) if self.shell_argfiles => { + shlex::split(&Self::read_file(path)?) + .ok_or_else(|| Error::ShellParseError(path.to_string()))? + .into_iter() + .for_each(|arg| self.push(arg)); + } + _ => { + let contents = Self::read_file(argfile)?; + contents.lines().for_each(|arg| self.push(arg.to_string())); + } + } + } else { + self.push(arg.to_string()); + } + + Ok(()) + } + + /// Adds a command line argument verbatim with no argfile expansion. + fn push(&mut self, arg: String) { + // Unfortunately, we have to do some eager argparsing to handle unstable + // options which change the behavior of argfile arguments. + // + // Normally, all of the argfile arguments (e.g. `@args.txt`) are + // expanded into our arguments list *and then* the whole list of + // arguments are passed on to be parsed. However, argfile parsing + // options like `-Zshell_argfiles` need to change the behavior of that + // argument expansion. So we have to do a little parsing on our own here + // instead of leaning on the existing logic. + // + // All we care about are unstable options, so we parse those out and + // look for any that affect how we expand argfiles. This argument + // inspection is very conservative; we only change behavior when we see + // exactly the options we're looking for and everything gets passed + // through. + + if self.next_is_unstable_option { + self.inspect_unstable_option(&arg); + self.next_is_unstable_option = false; + } else if let Some(unstable_option) = arg.strip_prefix("-Z") { + if unstable_option.is_empty() { + self.next_is_unstable_option = true; + } else { + self.inspect_unstable_option(unstable_option); + } + } + + self.expanded.push(arg); + } + + /// Consumes the `Expander`, returning the expanded arguments. + fn finish(self) -> Vec { + self.expanded + } + + /// Parses any relevant unstable flags specified on the command line. + fn inspect_unstable_option(&mut self, option: &str) { + match option { + "shell-argfiles" => self.shell_argfiles = true, + _ => (), + } + } + + /// Reads the contents of a file as UTF-8. + fn read_file(path: &str) -> Result { + fs::read_to_string(path).map_err(|e| { + if e.kind() == io::ErrorKind::InvalidData { + Error::Utf8Error(Some(path.to_string())) + } else { + Error::IOError(path.to_string(), e) } - Err(err) => return Err(Error::IOError(path.to_string(), err)), - }; - Ok(file.lines().map(ToString::to_string).collect()) - } else { - Ok(vec![arg]) + }) } } @@ -24,20 +98,20 @@ fn arg_expand(arg: String) -> Result, Error> { /// If this function is intended to be used with command line arguments, /// `argv[0]` must be removed prior to calling it manually. pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec { - let mut args = Vec::new(); + let mut expander = Expander::default(); for arg in at_args { - match arg_expand(arg.clone()) { - Ok(arg) => args.extend(arg), - Err(err) => early_dcx.early_fatal(format!("Failed to load argument file: {err}")), + if let Err(err) = expander.arg(arg) { + early_dcx.early_fatal(format!("Failed to load argument file: {err}")); } } - args + expander.finish() } #[derive(Debug)] pub enum Error { Utf8Error(Option), IOError(String, io::Error), + ShellParseError(String), } impl fmt::Display for Error { @@ -46,6 +120,7 @@ impl fmt::Display for Error { Error::Utf8Error(None) => write!(fmt, "Utf8 error"), Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"), Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"), + Error::ShellParseError(path) => write!(fmt, "Invalid shell-style arguments in {path}"), } } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 75410db1e364c..7b5de4cc11720 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -700,6 +700,7 @@ fn test_unstable_options_tracking_hash() { untracked!(query_dep_graph, true); untracked!(self_profile, SwitchWithOptPath::Enabled(None)); untracked!(self_profile_events, Some(vec![String::new()])); + untracked!(shell_argfiles, true); untracked!(span_debug, true); untracked!(span_free_formats, true); untracked!(temps_dir, Some(String::from("abc"))); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0b0b67ef890b0..21113c298f04a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1875,6 +1875,8 @@ written to standard error output)"), query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes"), share_generics: Option = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), + shell_argfiles: bool = (false, parse_bool, [UNTRACKED], + "allow argument files to be specified with POSIX \"shell-style\" argument quoting"), show_span: Option = (None, parse_opt_string, [TRACKED], "show spans for compiler debugging (expr|pat|ty)"), simulate_remapped_rust_src_base: Option = (None, parse_opt_pathbuf, [TRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/shell-argfiles.md b/src/doc/unstable-book/src/compiler-flags/shell-argfiles.md new file mode 100644 index 0000000000000..4f3c780972de5 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/shell-argfiles.md @@ -0,0 +1,11 @@ +# `shell-argfiles` + +-------------------- + +The `-Zshell-argfiles` compiler flag allows argfiles to be parsed using POSIX +"shell-style" quoting. When enabled, the compiler will use `shlex` to parse the +arguments from argfiles specified with `@shell:`. + +Because this feature controls the parsing of input arguments, the +`-Zshell-argfiles` flag must be present before the argument specifying the +shell-style arguemnt file. diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3c00027b9fdc9..62d48315d434e 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -325,6 +325,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "sha1", "sha2", "sharded-slab", + "shlex", "smallvec", "snap", "stable_deref_trait", diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index b4745d4883c55..ab0e647e13043 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1849; -const ROOT_ENTRY_LIMIT: usize = 867; +const ROOT_ENTRY_LIMIT: usize = 868; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files @@ -36,6 +36,10 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ "tests/ui/unused-crate-deps/test.mk", // why would you use make "tests/ui/proc-macro/auxiliary/included-file.txt", // more include "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer + "tests/ui/shell-argfiles/shell-argfiles.args", // passing args via a file + "tests/ui/shell-argfiles/shell-argfiles-badquotes.args", // passing args via a file + "tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args", // passing args via a file + "tests/ui/shell-argfiles/shell-argfiles-via-argfile.args", // passing args via a file ]; fn check_entries(tests_path: &Path, bad: &mut bool) { diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.rs b/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.rs new file mode 100644 index 0000000000000..800735cf3a768 --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.rs @@ -0,0 +1,11 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. This test uses backslash as the path separator for the command +// line arguments and is only run on windows. +// +// only-windows +// compile-flags: --cfg cmdline_set -Z shell-argfiles @shell:{{src-base}}\shell-argfiles\shell-argfiles-badquotes.args + +fn main() { +} diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr b/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr new file mode 100644 index 0000000000000..14adb1f740abb --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr @@ -0,0 +1,2 @@ +error: Failed to load argument file: Invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args + diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes.args b/tests/ui/shell-argfiles/shell-argfiles-badquotes.args new file mode 100644 index 0000000000000..c0d531adf3ffb --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes.args @@ -0,0 +1 @@ +"--cfg" "unquoted_set diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes.rs b/tests/ui/shell-argfiles/shell-argfiles-badquotes.rs new file mode 100644 index 0000000000000..f9160143a0410 --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes.rs @@ -0,0 +1,12 @@ +// Check to see if we can get parameters from an @argsfile file +// +// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path +// separators. We have a duplicated version of this test that uses backslash as +// the path separator for the command line arguments that is only run on +// windows. +// +// ignore-windows +// compile-flags: --cfg cmdline_set -Z shell-argfiles @shell:{{src-base}}/shell-argfiles/shell-argfiles-badquotes.args + +fn main() { +} diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr b/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr new file mode 100644 index 0000000000000..14adb1f740abb --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr @@ -0,0 +1,2 @@ +error: Failed to load argument file: Invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args + diff --git a/tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args b/tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args new file mode 100644 index 0000000000000..4e66d5a039529 --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args @@ -0,0 +1 @@ +"--cfg" "shell_args_set" \ No newline at end of file diff --git a/tests/ui/shell-argfiles/shell-argfiles-via-argfile.args b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.args new file mode 100644 index 0000000000000..d0af54e24e33c --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.args @@ -0,0 +1 @@ +-Zshell-argfiles \ No newline at end of file diff --git a/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs new file mode 100644 index 0000000000000..d71e3218f53b8 --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs @@ -0,0 +1,10 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-pass +// compile-flags: @{{src-base}}/shell-argfiles/shell-argfiles-via-argfile.args @shell:{{src-base}}/shell-argfiles/shell-argfiles-via-argfile-shell.args + +#[cfg(not(shell_args_set))] +compile_error!("shell_args_set not set"); + +fn main() { +} diff --git a/tests/ui/shell-argfiles/shell-argfiles.args b/tests/ui/shell-argfiles/shell-argfiles.args new file mode 100644 index 0000000000000..e5bb4b807ec4d --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles.args @@ -0,0 +1,3 @@ +--cfg unquoted_set +'--cfg' 'single_quoted_set' +"--cfg" "double_quoted_set" diff --git a/tests/ui/shell-argfiles/shell-argfiles.rs b/tests/ui/shell-argfiles/shell-argfiles.rs new file mode 100644 index 0000000000000..9bc252ea628a9 --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles.rs @@ -0,0 +1,19 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-pass +// compile-flags: --cfg cmdline_set -Z shell-argfiles @shell:{{src-base}}/shell-argfiles/shell-argfiles.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unquoted_set))] +compile_error!("unquoted_set not set"); + +#[cfg(not(single_quoted_set))] +compile_error!("single_quoted_set not set"); + +#[cfg(not(double_quoted_set))] +compile_error!("double_quoted_set not set"); + +fn main() { +} From 18a1ca6a1779d3a0ad506666de8e3fdd03704d9c Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Tue, 9 Jan 2024 04:40:54 +0100 Subject: [PATCH 6/6] core: panic: fix broken link Signed-off-by: Miguel Ojeda --- library/core/src/macros/panic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index 60100c2655a6e..6bd23b3072ed9 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md @@ -56,7 +56,7 @@ For more detailed information about error handling check out the [book] or the [`panic_any`]: ../std/panic/fn.panic_any.html [`Box`]: ../std/boxed/struct.Box.html [`Any`]: crate::any::Any -[`format!` syntax]: ../std/fmt/index.html +[formatting syntax]: ../std/fmt/index.html [book]: ../book/ch09-00-error-handling.html [`std::result`]: ../std/result/index.html