From 1ab0e6c6b8c95fdc82e0990b4ab6953ac59ffe9c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 26 Jul 2024 12:04:05 +0200 Subject: [PATCH 01/18] added support for GNU/Hurd on x86_64 --- compiler/rustc_target/src/spec/mod.rs | 1 + .../spec/targets/x86_64_unknown_hurd_gnu.rs | 26 +++++++++++++++++++ src/doc/rustc/src/platform-support.md | 1 + src/doc/rustc/src/platform-support/hurd.md | 7 ++--- tests/assembly/targets/targets-elf.rs | 3 +++ 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 946947124c6eb..8fdd12e3d9bdb 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1644,6 +1644,7 @@ supported_targets! { ("x86_64-unknown-haiku", x86_64_unknown_haiku), ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu), + ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu), ("aarch64-apple-darwin", aarch64_apple_darwin), ("arm64e-apple-darwin", arm64e_apple_darwin), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs new file mode 100644 index 0000000000000..3fb7484b36ba4 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs @@ -0,0 +1,26 @@ +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; + +pub fn target() -> Target { + let mut base = base::hurd_gnu::opts(); + base.cpu = "x86-64".into(); + base.plt_by_default = false; + base.max_atomic_width = Some(64); + base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); + base.stack_probes = StackProbeType::Inline; + base.supports_xray = true; + + Target { + llvm_target: "x86_64-unknown-hurd-gnu".into(), + metadata: crate::spec::TargetMetadata { + description: Some("64-bit GNU/Hurd".into()), + tier: Some(3), + host_tools: Some(true), + std: Some(true), + }, + pointer_width: 64, + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), + arch: "x86_64".into(), + options: base, + } +} diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 0c7f4e7bf1b43..16b237a604226 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -377,6 +377,7 @@ target | std | host | notes [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl 1.2.3 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku +[`x86_64-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 64-bit GNU/Hurd [`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit `x86_64-unknown-l4re-uclibc` | ? | | [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD diff --git a/src/doc/rustc/src/platform-support/hurd.md b/src/doc/rustc/src/platform-support/hurd.md index ddf40213ed49d..2521f79dc5e65 100644 --- a/src/doc/rustc/src/platform-support/hurd.md +++ b/src/doc/rustc/src/platform-support/hurd.md @@ -1,4 +1,4 @@ -# `i686-unknown-hurd-gnu` +# `i686-unknown-hurd-gnu` and `x86_64-unknown-hurd-gnu` **Tier: 3** @@ -16,7 +16,8 @@ The GNU/Hurd target supports `std` and uses the standard ELF file format. ## Building the target -This target can be built by adding `i686-unknown-hurd-gnu` as target in the rustc list. +This target can be built by adding `i686-unknown-hurd-gnu` and +`x86_64-unknown-hurd-gnu` as targets in the rustc list. ## Building Rust programs @@ -32,4 +33,4 @@ Tests can be run in the same way as a regular binary. ## Cross-compilation toolchains and C code The target supports C code, the GNU toolchain calls the target -`i686-unknown-gnu`. +`i686-unknown-gnu` and `x86_64-unknown-gnu`. diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 762df40a44b9b..9c365de62646a 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -537,6 +537,9 @@ //@ revisions: x86_64_unknown_haiku //@ [x86_64_unknown_haiku] compile-flags: --target x86_64-unknown-haiku //@ [x86_64_unknown_haiku] needs-llvm-components: x86 +//@ revisions: x86_64_unknown_hurd_gnu +//@ [x86_64_unknown_hurd_gnu] compile-flags: --target x86_64-unknown-hurd-gnu +//@ [x86_64_unknown_hurd_gnu] needs-llvm-components: x86 //@ revisions: x86_64_unknown_hermit //@ [x86_64_unknown_hermit] compile-flags: --target x86_64-unknown-hermit //@ [x86_64_unknown_hermit] needs-llvm-components: x86 From 1ef4f5d9248b3885035cfd269cca050b6d94c3dc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Aug 2024 12:21:35 +0200 Subject: [PATCH 02/18] clarify that addr_of creates read-only pointers --- library/core/src/ptr/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 859fad9e069ca..b83a18027193e 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -2285,6 +2285,10 @@ impl fmt::Debug for F { /// `addr_of!(expr)` is equivalent to `&raw const expr`. The macro is *soft-deprecated*; /// use `&raw const` instead. /// +/// It is still an open question whether writing through an `addr_of!`-created pointer is permitted +/// or not. Until that is decided, the same rules as for shared references apply: it is UB to write +/// through a pointer created with this operation, except for bytes located inside an `UnsafeCell`. +/// /// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned /// and points to initialized data. For cases where those requirements do not hold, /// raw pointers should be used instead. However, `&expr as *const _` creates a reference From b5bd0fe48a0427a82804759a5acd795851c65e4b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Aug 2024 15:08:45 +0200 Subject: [PATCH 03/18] addr_of on places derived from raw pointers should preserve permissions --- library/core/src/ptr/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index b83a18027193e..5a9c5ed5be3b4 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -2285,9 +2285,13 @@ impl fmt::Debug for F { /// `addr_of!(expr)` is equivalent to `&raw const expr`. The macro is *soft-deprecated*; /// use `&raw const` instead. /// -/// It is still an open question whether writing through an `addr_of!`-created pointer is permitted -/// or not. Until that is decided, the same rules as for shared references apply: it is UB to write -/// through a pointer created with this operation, except for bytes located inside an `UnsafeCell`. +/// It is still an open question under which conditions writing through an `addr_of!`-created +/// pointer is permitted. If the place `expr` evaluates to is based on a raw pointer, then the +/// result of `addr_of!` inherits all permissions from that raw pointer. However, if the place is +/// based on a reference, local variable, or `static`, then until all details are decided, the same +/// rules as for shared references apply: it is UB to write through a pointer created with this +/// operation, except for bytes located inside an `UnsafeCell`. Use `&raw mut` (or [`addr_of_mut`]) +/// to create a raw pointer that definitely permits mutation. /// /// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned /// and points to initialized data. For cases where those requirements do not hold, From 21edc735170642d541adb5a2a4c07159e75f8cb0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 30 Aug 2024 15:31:49 +1000 Subject: [PATCH 04/18] bootstrap: Try to track down why `initial_libdir` sometimes fails Determining this path occasionally fails locally for unknown reasons, resulting in the build failing with an unhelpful `StripPrefixError(())` panic message. In order to track down why that's happening, include some relevant information in the panic message when that failure occurs. --- src/bootstrap/src/lib.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 268392c5fb118..4cb2e343730ca 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -332,14 +332,20 @@ impl Build { .trim() .to_string(); - let initial_libdir = initial_target_dir - .parent() - .unwrap() - .parent() - .unwrap() - .strip_prefix(&initial_sysroot) - .unwrap() - .to_path_buf(); + // FIXME(Zalathar): Determining this path occasionally fails locally for + // unknown reasons, so we print some extra context to help track down why. + let find_initial_libdir = || { + let initial_libdir = + initial_target_dir.parent()?.parent()?.strip_prefix(&initial_sysroot).ok()?; + Some(initial_libdir.to_path_buf()) + }; + let Some(initial_libdir) = find_initial_libdir() else { + panic!( + "couldn't determine `initial_libdir` \ + from target dir {initial_target_dir:?} \ + and sysroot {initial_sysroot:?}" + ) + }; let version = std::fs::read_to_string(src.join("src").join("version")) .expect("failed to read src/version"); From 39e3adda53a01a90056392c1d75308a48a40024b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 30 Aug 2024 12:27:04 +0200 Subject: [PATCH 05/18] Make `./x.py compiler/` aware of the crate's features --- src/bootstrap/src/core/build_steps/check.rs | 2 +- src/bootstrap/src/core/build_steps/clippy.rs | 2 +- src/bootstrap/src/core/build_steps/compile.rs | 5 +++-- src/bootstrap/src/core/build_steps/doc.rs | 2 +- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/bootstrap/src/core/metadata.rs | 10 +++++++++- src/bootstrap/src/lib.rs | 19 ++++++++++++++----- 7 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 7f7faf077d047..ba12e64c4a26f 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -228,7 +228,7 @@ impl Step for Rustc { self.override_build_kind.unwrap_or(builder.kind), ); - rustc_cargo(builder, &mut cargo, target, &compiler); + rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); // For ./x.py clippy, don't run with --all-targets because // linting tests and benchmarks can produce very noisy results diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index a2bb03cd5ac81..a0992350722fe 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -197,7 +197,7 @@ impl Step for Rustc { Kind::Clippy, ); - rustc_cargo(builder, &mut cargo, target, &compiler); + rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); // Explicitly pass -p for all compiler crates -- this will force cargo // to also lint the tests/benches/examples for these crates, rather diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index edf18e2ebf33b..3d2f3a4b2e4ee 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -983,7 +983,7 @@ impl Step for Rustc { Kind::Build, ); - rustc_cargo(builder, &mut cargo, target, &compiler); + rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); // NB: all RUSTFLAGS should be added to `rustc_cargo()` so they will be // consistently applied by check/doc/test modes too. @@ -1042,10 +1042,11 @@ pub fn rustc_cargo( cargo: &mut Cargo, target: TargetSelection, compiler: &Compiler, + crates: &[String], ) { cargo .arg("--features") - .arg(builder.rustc_features(builder.kind, target)) + .arg(builder.rustc_features(builder.kind, target, crates)) .arg("--manifest-path") .arg(builder.src.join("compiler/rustc/Cargo.toml")); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index ffb617c642baf..f604cdbe27914 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -826,7 +826,7 @@ impl Step for Rustc { // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 // cargo.rustdocflag("--generate-link-to-definition"); - compile::rustc_cargo(builder, &mut cargo, target, &compiler); + compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); cargo.arg("-Zskip-rustdoc-fingerprint"); // Only include compiler crates, no dependencies of those, such as `libc`. diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index cc01afd4c18c6..af5734de96944 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2692,7 +2692,7 @@ impl Step for Crate { } } Mode::Rustc => { - compile::rustc_cargo(builder, &mut cargo, target, &compiler); + compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); } _ => panic!("can only test libraries"), }; diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index 1016607fc8318..d665544f59339 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeMap; use std::path::PathBuf; use serde_derive::Deserialize; @@ -21,6 +22,7 @@ struct Package { manifest_path: String, dependencies: Vec, targets: Vec, + features: BTreeMap>, } /// For more information, see the output of @@ -51,7 +53,13 @@ pub fn build(build: &mut Build) { .map(|dep| dep.name) .collect(); let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib")); - let krate = Crate { name: name.clone(), deps, path, has_lib }; + let krate = Crate { + name: name.clone(), + deps, + path, + has_lib, + features: package.features.keys().cloned().collect(), + }; let relative_path = krate.local_path(build); build.crates.insert(name.clone(), krate); let existing_path = build.crate_paths.insert(relative_path, name); diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 268392c5fb118..fe013b0fd0211 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -183,6 +183,7 @@ struct Crate { deps: HashSet, path: PathBuf, has_lib: bool, + features: Vec, } impl Crate { @@ -666,16 +667,24 @@ impl Build { } /// Gets the space-separated set of activated features for the compiler. - fn rustc_features(&self, kind: Kind, target: TargetSelection) -> String { + fn rustc_features(&self, kind: Kind, target: TargetSelection, crates: &[String]) -> String { + let possible_features_by_crates: HashSet<_> = crates + .iter() + .flat_map(|krate| &self.crates[krate].features) + .map(std::ops::Deref::deref) + .collect(); + let check = |feature: &str| -> bool { + crates.is_empty() || possible_features_by_crates.contains(feature) + }; let mut features = vec![]; - if self.config.jemalloc { + if self.config.jemalloc && check("jemalloc") { features.push("jemalloc"); } - if self.config.llvm_enabled(target) || kind == Kind::Check { + if (self.config.llvm_enabled(target) || kind == Kind::Check) && check("llvm") { features.push("llvm"); } // keep in sync with `bootstrap/compile.rs:rustc_cargo_env` - if self.config.rustc_parallel { + if self.config.rustc_parallel && check("rustc_use_parallel_compiler") { features.push("rustc_use_parallel_compiler"); } @@ -684,7 +693,7 @@ impl Build { // which is everything (including debug/trace/etc.) // if its unset, if debug_assertions is on, then debug_logging will also be on // as well as tracing *ignoring* this feature when debug_assertions is on - if !self.config.rust_debug_logging { + if !self.config.rust_debug_logging && check("max_level_info") { features.push("max_level_info"); } From 040239465aefc09f8c837ff9d4d66ca6297e5c5c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 9 Aug 2024 09:52:12 +0200 Subject: [PATCH 06/18] Add an internal lint that warns when accessing untracked data --- compiler/rustc_data_structures/src/steal.rs | 1 + compiler/rustc_feature/src/builtin_attrs.rs | 6 +++ compiler/rustc_lint/messages.ftl | 3 ++ compiler/rustc_lint/src/internal.rs | 24 +++++++++-- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint/src/lints.rs | 7 ++++ compiler/rustc_passes/src/check_attr.rs | 40 ++++--------------- compiler/rustc_span/src/symbol.rs | 1 + .../crates/hir-expand/src/inert_attr_macro.rs | 3 ++ .../internal-lints/query_completeness.rs | 16 ++++++++ .../internal-lints/query_completeness.stderr | 15 +++++++ 11 files changed, 82 insertions(+), 35 deletions(-) create mode 100644 tests/ui-fulldeps/internal-lints/query_completeness.rs create mode 100644 tests/ui-fulldeps/internal-lints/query_completeness.stderr diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs index 0f2c0eee27d2f..aaa95f6b7f19e 100644 --- a/compiler/rustc_data_structures/src/steal.rs +++ b/compiler/rustc_data_structures/src/steal.rs @@ -57,6 +57,7 @@ impl Steal { /// /// This should not be used within rustc as it leaks information not tracked /// by the query system, breaking incremental compilation. + #[cfg_attr(not(bootstrap), rustc_lint_untracked_query_information)] pub fn is_stolen(&self) -> bool { self.value.borrow().is_none() } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index e2491922b8df6..e86421f2150db 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -793,6 +793,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE ), + // Used by the `rustc::untracked_query_information` lint to warn methods which + // might not be stable during incremental compilation. + rustc_attr!( + rustc_lint_untracked_query_information, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE + ), // Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic // APIs. Any function with this attribute will be checked by that lint. rustc_attr!( diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 353345958337c..759320b9eb65f 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -699,6 +699,9 @@ lint_ptr_null_checks_ref = references are not nullable, so checking them for nul lint_query_instability = using `{$query}` can result in unstable query results .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale +lint_query_untracked = `{$method}` accesses information that is not tracked by the query system + .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale + lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}` lint_range_use_inclusive_range = use an inclusive range instead diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 2e8116b8ba892..9d637c1eb7f84 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -17,8 +17,8 @@ use tracing::debug; use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, - NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, - TykindKind, TypeIrInherentUsage, UntranslatableDiag, + NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified, + TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -88,7 +88,18 @@ declare_tool_lint! { report_in_external_macro: true } -declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY]); +declare_tool_lint! { + /// The `untracked_query_information` lint detects use of methods which leak information not + /// tracked by the query system, such as whether a `Steal` value has already been stolen. In + /// order not to break incremental compilation, such methods must be used very carefully or not + /// at all. + pub rustc::UNTRACKED_QUERY_INFORMATION, + Allow, + "require explicit opt-in when accessing information not tracked by the query system", + report_in_external_macro: true +} + +declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]); impl LateLintPass<'_> for QueryStability { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { @@ -102,6 +113,13 @@ impl LateLintPass<'_> for QueryStability { QueryInstability { query: cx.tcx.item_name(def_id) }, ); } + if cx.tcx.has_attr(def_id, sym::rustc_lint_untracked_query_information) { + cx.emit_span_lint( + UNTRACKED_QUERY_INFORMATION, + span, + QueryUntracked { method: cx.tcx.item_name(def_id) }, + ); + } } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c5a5c5b30afef..105a90de03407 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -609,6 +609,7 @@ fn register_internals(store: &mut LintStore) { vec![ LintId::of(DEFAULT_HASH_TYPES), LintId::of(POTENTIAL_QUERY_INSTABILITY), + LintId::of(UNTRACKED_QUERY_INFORMATION), LintId::of(USAGE_OF_TY_TYKIND), LintId::of(PASS_BY_VALUE), LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO), diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 7ca282b7c8541..9050f36acba7b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -894,6 +894,13 @@ pub(crate) struct QueryInstability { pub query: Symbol, } +#[derive(LintDiagnostic)] +#[diag(lint_query_untracked)] +#[note] +pub(crate) struct QueryUntracked { + pub method: Symbol, +} + #[derive(LintDiagnostic)] #[diag(lint_span_use_eq_ctxt)] pub(crate) struct SpanUseEqCtxtDiag; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 21478a44b0e14..e41f89a3c9da9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -125,7 +125,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::inline, ..] => self.check_inline(hir_id, attr, span, target), [sym::coverage, ..] => self.check_coverage(attr, span, target), [sym::optimize, ..] => self.check_optimize(hir_id, attr, target), - [sym::no_sanitize, ..] => self.check_no_sanitize(hir_id, attr, span, target), + [sym::no_sanitize, ..] => { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) + } [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target), [sym::marker, ..] => self.check_marker(hir_id, attr, span, target), [sym::target_feature, ..] => { @@ -166,10 +168,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item) } [sym::rustc_lint_query_instability, ..] => { - self.check_rustc_lint_query_instability(hir_id, attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr, span, target) + } + [sym::rustc_lint_untracked_query_information, ..] => { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } [sym::rustc_lint_diagnostics, ..] => { - self.check_rustc_lint_diagnostics(hir_id, attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } [sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target), [sym::rustc_lint_opt_deny_field_access, ..] => { @@ -452,11 +457,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that `#[no_sanitize(..)]` is applied to a function or method. - fn check_no_sanitize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) - } - fn check_generic_attr( &self, hir_id: HirId, @@ -1635,30 +1635,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that the `#[rustc_lint_query_instability]` attribute is only applied to a function - /// or method. - fn check_rustc_lint_query_instability( - &self, - hir_id: HirId, - attr: &Attribute, - span: Span, - target: Target, - ) { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) - } - - /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or - /// method. - fn check_rustc_lint_diagnostics( - &self, - hir_id: HirId, - attr: &Attribute, - span: Span, - target: Target, - ) { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) - } - /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct. fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) { match target { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3476520960585..cc63769d51df6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1653,6 +1653,7 @@ symbols! { rustc_lint_opt_deny_field_access, rustc_lint_opt_ty, rustc_lint_query_instability, + rustc_lint_untracked_query_information, rustc_macro_transparency, rustc_main, rustc_mir, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs index ee15b1b5ce9d5..5c25a55362e64 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs @@ -464,6 +464,9 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ // Used by the `rustc::potential_query_instability` lint to warn methods which // might not be stable during incremental compilation. rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), + // Used by the `rustc::untracked_query_information` lint to warn methods which + // might break incremental compilation. + rustc_attr!(rustc_lint_untracked_query_information, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints // to assist in changes to diagnostic APIs. rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.rs b/tests/ui-fulldeps/internal-lints/query_completeness.rs new file mode 100644 index 0000000000000..50b0fb4c3fc02 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/query_completeness.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -Z unstable-options +// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run. +//@ ignore-stage1 (requires matching sysroot built with in-tree compiler) +#![feature(rustc_private)] +#![deny(rustc::untracked_query_information)] + +extern crate rustc_data_structures; + +use rustc_data_structures::steal::Steal; + +fn use_steal(x: Steal<()>) { + let _ = x.is_stolen(); + //~^ ERROR `is_stolen` accesses information that is not tracked by the query system +} + +fn main() {} diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.stderr b/tests/ui-fulldeps/internal-lints/query_completeness.stderr new file mode 100644 index 0000000000000..35bb867f40e8f --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/query_completeness.stderr @@ -0,0 +1,15 @@ +error: `is_stolen` accesses information that is not tracked by the query system + --> $DIR/query_completeness.rs:12:15 + | +LL | let _ = x.is_stolen(); + | ^^^^^^^^^ + | + = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale +note: the lint level is defined here + --> $DIR/query_completeness.rs:5:9 + | +LL | #![deny(rustc::untracked_query_information)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From b5d07fd3567f5ca42b677ffd9cf4756c5dbf12ba Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 3 Sep 2024 21:03:46 +0300 Subject: [PATCH 07/18] copy rustc rustlib artifacts from ci-rustc We recently had an issue because some rustlib files were missing (like: "error[E0463]: can't find crate for rustc_ast") when building tools that rely on rustc. This patch fixes that by copying those files as required. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/compile.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index eef548033f1c6..71e217bbbfc42 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -931,7 +931,12 @@ impl Step for Rustc { // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler, // so its artifacts can't be reused. if builder.download_rustc() && compiler.stage != 0 { - builder.ensure(Sysroot { compiler, force_recompile: false }); + let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false }); + cp_rustc_component_to_ci_sysroot( + builder, + &sysroot, + builder.config.ci_rustc_dev_contents(), + ); return compiler.stage; } From 98f74b4d047006aaa475b0252b61f0ca772372fb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 3 Sep 2024 21:50:08 +0200 Subject: [PATCH 08/18] explain why Rvalue::Len still exists --- compiler/rustc_middle/src/mir/syntax.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 748ca047754a9..22a4b688c517c 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1307,6 +1307,9 @@ pub enum Rvalue<'tcx> { /// If the type of the place is an array, this is the array length. For slices (`[T]`, not /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is /// ill-formed for places of other types. + /// + /// This cannot be a `UnOp(PtrMetadata, _)` because that expects a value, and we only + /// have a place, and `UnOp(PtrMetadata, RawPtr(place))` is not a thing. Len(Place<'tcx>), /// Performs essentially all of the casts that can be performed via `as`. From f3efe3de1597b530735fd81fd776870cbfc952f0 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 3 Sep 2024 17:04:28 -0400 Subject: [PATCH 09/18] Add compat note for trait solver change --- RELEASES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 6aba476103e7f..c1e157e5455b7 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -100,6 +100,9 @@ Compatibility Notes The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`. * The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data. +* [In very rare cases, a change in the internal evaluation order of the trait + solver may result in new fatal overflow errors.](https://github.com/rust-lang/rust/pull/126128) + From e2484be0c7047485649f761cf58014bc1df1e227 Mon Sep 17 00:00:00 2001 From: Literally Void Date: Tue, 3 Sep 2024 15:34:46 -0700 Subject: [PATCH 10/18] docs: add digit separators in `Duration` examples --- library/core/src/time.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 0390bb59a8984..c19eeedb35426 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -250,7 +250,7 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::from_millis(2569); + /// let duration = Duration::from_millis(2_569); /// /// assert_eq!(2, duration.as_secs()); /// assert_eq!(569_000_000, duration.subsec_nanos()); @@ -279,7 +279,7 @@ impl Duration { /// let duration = Duration::from_micros(1_000_002); /// /// assert_eq!(1, duration.as_secs()); - /// assert_eq!(2000, duration.subsec_nanos()); + /// assert_eq!(2_000, duration.subsec_nanos()); /// ``` #[stable(feature = "duration_from_micros", since = "1.27.0")] #[must_use] @@ -472,7 +472,7 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::new(5, 730023852); + /// let duration = Duration::new(5, 730_023_852); /// assert_eq!(duration.as_secs(), 5); /// ``` /// @@ -501,7 +501,7 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::from_millis(5432); + /// let duration = Duration::from_millis(5_432); /// assert_eq!(duration.as_secs(), 5); /// assert_eq!(duration.subsec_millis(), 432); /// ``` @@ -547,7 +547,7 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::from_millis(5010); + /// let duration = Duration::from_millis(5_010); /// assert_eq!(duration.as_secs(), 5); /// assert_eq!(duration.subsec_nanos(), 10_000_000); /// ``` @@ -566,8 +566,8 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::new(5, 730023852); - /// assert_eq!(duration.as_millis(), 5730); + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_millis(), 5_730); /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] @@ -584,8 +584,8 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::new(5, 730023852); - /// assert_eq!(duration.as_micros(), 5730023); + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_micros(), 5_730_023); /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] @@ -602,8 +602,8 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::new(5, 730023852); - /// assert_eq!(duration.as_nanos(), 5730023852); + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_nanos(), 5_730_023_852); /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] @@ -879,7 +879,7 @@ impl Duration { /// use std::time::Duration; /// /// let dur = Duration::new(2, 345_678_000); - /// assert_eq!(dur.as_millis_f64(), 2345.678); + /// assert_eq!(dur.as_millis_f64(), 2_345.678); /// ``` #[unstable(feature = "duration_millis_float", issue = "122451")] #[must_use] @@ -900,7 +900,7 @@ impl Duration { /// use std::time::Duration; /// /// let dur = Duration::new(2, 345_678_000); - /// assert_eq!(dur.as_millis_f32(), 2345.678); + /// assert_eq!(dur.as_millis_f32(), 2_345.678); /// ``` #[unstable(feature = "duration_millis_float", issue = "122451")] #[must_use] @@ -1017,7 +1017,7 @@ impl Duration { /// /// let dur = Duration::new(2, 700_000_000); /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641)); - /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0)); + /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847_800, 0)); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] #[must_use = "this returns the result of the operation, \ From 4df28b8bf1c3e9dade6ab29358effc99010f594b Mon Sep 17 00:00:00 2001 From: chenx97 Date: Wed, 4 Sep 2024 14:44:23 +0800 Subject: [PATCH 11/18] forward linker option to lint-docs --- src/bootstrap/src/core/build_steps/doc.rs | 3 +++ src/tools/lint-docs/src/lib.rs | 5 +++++ src/tools/lint-docs/src/main.rs | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index ffb617c642baf..ac68bbf805092 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1186,6 +1186,9 @@ impl Step for RustcBook { cmd.arg("--rustc"); cmd.arg(&rustc); cmd.arg("--rustc-target").arg(self.target.rustc_target_arg()); + if let Some(target_linker) = builder.linker(self.target) { + cmd.arg("--rustc-linker").arg(target_linker); + } if builder.is_verbose() { cmd.arg("--verbose"); } diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index 72bb9db7e7414..532a27b22aa6f 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -56,6 +56,8 @@ pub struct LintExtractor<'a> { pub rustc_path: &'a Path, /// The target arch to build the docs for. pub rustc_target: &'a str, + /// The target linker overriding `rustc`'s default + pub rustc_linker: Option<&'a str>, /// Verbose output. pub verbose: bool, /// Validate the style and the code example. @@ -459,6 +461,9 @@ impl<'a> LintExtractor<'a> { } cmd.arg("--error-format=json"); cmd.arg("--target").arg(self.rustc_target); + if let Some(target_linker) = self.rustc_linker { + cmd.arg(format!("-Clinker={target_linker}")); + } if options.contains(&"test") { cmd.arg("--test"); } diff --git a/src/tools/lint-docs/src/main.rs b/src/tools/lint-docs/src/main.rs index 2055fed2b480c..e377283b1a453 100644 --- a/src/tools/lint-docs/src/main.rs +++ b/src/tools/lint-docs/src/main.rs @@ -27,6 +27,7 @@ fn doit() -> Result<(), Box> { let mut out_path = None; let mut rustc_path = None; let mut rustc_target = None; + let mut rustc_linker = None; let mut verbose = false; let mut validate = false; while let Some(arg) = args.next() { @@ -55,6 +56,12 @@ fn doit() -> Result<(), Box> { None => return Err("--rustc-target requires a value".into()), }; } + "--rustc-linker" => { + rustc_linker = match args.next() { + Some(s) => Some(s), + None => return Err("--rustc-linker requires a value".into()), + }; + } "-v" | "--verbose" => verbose = true, "--validate" => validate = true, s => return Err(format!("unexpected argument `{}`", s).into()), @@ -77,6 +84,7 @@ fn doit() -> Result<(), Box> { out_path: &out_path.unwrap(), rustc_path: &rustc_path.unwrap(), rustc_target: &rustc_target.unwrap(), + rustc_linker: rustc_linker.as_deref(), verbose, validate, }; From 93b4b2d51cd55177fedf1a38173c7e9576e98d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 4 Sep 2024 11:43:38 +0200 Subject: [PATCH 12/18] Temporarily remove fmease from the review rotation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 1afcad7d1315c..f379f8cc7af50 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -914,6 +914,7 @@ cc = ["@kobzol"] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ + "fmease", "jhpratt", "joboet", "jyn514", From f7679d050793304eff9ff2a46a824cc5495e6f93 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 4 Sep 2024 12:29:44 +0200 Subject: [PATCH 13/18] propagate `tainted_by_errors` in `MirBorrowckCtxt::emit_errors` --- compiler/rustc_borrowck/src/lib.rs | 2 +- tests/ui/consts/missing_assoc_const_type.rs | 2 +- tests/ui/consts/missing_assoc_const_type.stderr | 8 +++++++- .../{crashes/124164.rs => ui/static/missing-type.rs} | 3 ++- tests/ui/static/missing-type.stderr | 8 ++++++++ .../126896.rs => ui/type-alias-impl-trait/taint.rs} | 8 ++++---- tests/ui/type-alias-impl-trait/taint.stderr | 12 ++++++++++++ 7 files changed, 35 insertions(+), 8 deletions(-) rename tests/{crashes/124164.rs => ui/static/missing-type.rs} (52%) create mode 100644 tests/ui/static/missing-type.stderr rename tests/{crashes/126896.rs => ui/type-alias-impl-trait/taint.rs} (59%) create mode 100644 tests/ui/type-alias-impl-trait/taint.stderr diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index ffb350b1d1f0f..d40dcfa58054a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2522,7 +2522,7 @@ mod diags { } pub(crate) fn emit_errors(&mut self) -> Option { - let mut res = None; + let mut res = self.infcx.tainted_by_errors(); // Buffer any move errors that we collected and de-duplicated. for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) { diff --git a/tests/ui/consts/missing_assoc_const_type.rs b/tests/ui/consts/missing_assoc_const_type.rs index 8d95e3dca633c..633998e9bc157 100644 --- a/tests/ui/consts/missing_assoc_const_type.rs +++ b/tests/ui/consts/missing_assoc_const_type.rs @@ -16,7 +16,7 @@ impl Range for TwoDigits { const fn digits(x: u8) -> usize { match x { - TwoDigits::FIRST..=TwoDigits::LAST => 0, + TwoDigits::FIRST..=TwoDigits::LAST => 0, //~ ERROR: could not evaluate constant pattern 0..=9 | 100..=255 => panic!(), } } diff --git a/tests/ui/consts/missing_assoc_const_type.stderr b/tests/ui/consts/missing_assoc_const_type.stderr index 28af1f0f321e6..ef7ff962d2d12 100644 --- a/tests/ui/consts/missing_assoc_const_type.stderr +++ b/tests/ui/consts/missing_assoc_const_type.stderr @@ -4,5 +4,11 @@ error: missing type for `const` item LL | const FIRST: = 10; | ^ help: provide a type for the associated constant: `u8` -error: aborting due to 1 previous error +error: could not evaluate constant pattern + --> $DIR/missing_assoc_const_type.rs:19:9 + | +LL | TwoDigits::FIRST..=TwoDigits::LAST => 0, + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/tests/crashes/124164.rs b/tests/ui/static/missing-type.rs similarity index 52% rename from tests/crashes/124164.rs rename to tests/ui/static/missing-type.rs index 8c9b4bddbe80d..2569f47b7c38c 100644 --- a/tests/crashes/124164.rs +++ b/tests/ui/static/missing-type.rs @@ -1,4 +1,5 @@ -//@ known-bug: #124164 +// reported as #124164 static S_COUNT: = std::sync::atomic::AtomicUsize::new(0); +//~^ ERROR: missing type for `static` item fn main() {} diff --git a/tests/ui/static/missing-type.stderr b/tests/ui/static/missing-type.stderr new file mode 100644 index 0000000000000..6489ceb700a2e --- /dev/null +++ b/tests/ui/static/missing-type.stderr @@ -0,0 +1,8 @@ +error: missing type for `static` item + --> $DIR/missing-type.rs:2:16 + | +LL | static S_COUNT: = std::sync::atomic::AtomicUsize::new(0); + | ^ help: provide a type for the static variable: `AtomicUsize` + +error: aborting due to 1 previous error + diff --git a/tests/crashes/126896.rs b/tests/ui/type-alias-impl-trait/taint.rs similarity index 59% rename from tests/crashes/126896.rs rename to tests/ui/type-alias-impl-trait/taint.rs index 49c539d7acc8a..dfb947637c042 100644 --- a/tests/crashes/126896.rs +++ b/tests/ui/type-alias-impl-trait/taint.rs @@ -1,6 +1,7 @@ -//@ known-bug: rust-lang/rust#126896 //@ compile-flags: -Zvalidate-mir -Zinline-mir=yes +// reported as rust-lang/rust#126896 + #![feature(type_alias_impl_trait)] type Two<'a, 'b> = impl std::fmt::Debug; @@ -9,9 +10,8 @@ fn set(x: &mut isize) -> isize { } fn d(x: Two) { - let c1 = || set(x); + let c1 = || set(x); //~ ERROR: expected generic lifetime parameter, found `'_` c1; } -fn main() { -} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/taint.stderr b/tests/ui/type-alias-impl-trait/taint.stderr new file mode 100644 index 0000000000000..17fcd4b7e9325 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/taint.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/taint.rs:13:17 + | +LL | type Two<'a, 'b> = impl std::fmt::Debug; + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | let c1 = || set(x); + | ^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0792`. From 49e3b9a2d2cf9bfbc5ada8e3d5dba8dee507dace Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 23 Aug 2024 16:38:20 +0200 Subject: [PATCH 14/18] fix ICE when `asm_const` and `const_refs_to_static` are combined --- .../rustc_borrowck/src/universal_regions.rs | 14 ++++++++++-- tests/ui/asm/const-refs-to-static.rs | 21 ++++++++++++++++++ tests/ui/asm/const-refs-to-static.stderr | 22 +++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 tests/ui/asm/const-refs-to-static.rs create mode 100644 tests/ui/asm/const-refs-to-static.stderr diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 9eabe817359c0..164be73f49296 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -29,7 +29,8 @@ use rustc_macros::extension; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt, + self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, + TyCtxt, TypeVisitableExt, }; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{kw, sym}; @@ -688,7 +689,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { defining_ty: DefiningTy<'tcx>, ) -> ty::Binder<'tcx, &'tcx ty::List>> { let tcx = self.infcx.tcx; - match defining_ty { + + let inputs_and_output = match defining_ty { DefiningTy::Closure(def_id, args) => { assert_eq!(self.mir_def.to_def_id(), def_id); let closure_sig = args.as_closure().sig(); @@ -798,6 +800,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // "output" (the type of the constant). assert_eq!(self.mir_def.to_def_id(), def_id); let ty = tcx.type_of(self.mir_def).instantiate_identity(); + let ty = indices.fold_to_region_vids(tcx, ty); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } @@ -807,7 +810,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let ty = args.as_inline_const().ty(); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } + }; + + // FIXME(#129952): We probably want a more principled approach here. + if let Err(terr) = inputs_and_output.skip_binder().error_reported() { + self.infcx.set_tainted_by_errors(terr); } + + inputs_and_output } } diff --git a/tests/ui/asm/const-refs-to-static.rs b/tests/ui/asm/const-refs-to-static.rs new file mode 100644 index 0000000000000..9fc010b576309 --- /dev/null +++ b/tests/ui/asm/const-refs-to-static.rs @@ -0,0 +1,21 @@ +//@ needs-asm-support +//@ ignore-nvptx64 +//@ ignore-spirv + +#![feature(const_refs_to_static)] + +use std::arch::{asm, global_asm}; +use std::ptr::addr_of; + +static FOO: u8 = 42; + +global_asm!("{}", const addr_of!(FOO)); +//~^ ERROR invalid type for `const` operand + +#[no_mangle] +fn inline() { + unsafe { asm!("{}", const addr_of!(FOO)) }; + //~^ ERROR invalid type for `const` operand +} + +fn main() {} diff --git a/tests/ui/asm/const-refs-to-static.stderr b/tests/ui/asm/const-refs-to-static.stderr new file mode 100644 index 0000000000000..8fd69da0d1e92 --- /dev/null +++ b/tests/ui/asm/const-refs-to-static.stderr @@ -0,0 +1,22 @@ +error: invalid type for `const` operand + --> $DIR/const-refs-to-static.rs:12:19 + | +LL | global_asm!("{}", const addr_of!(FOO)); + | ^^^^^^------------- + | | + | is a `*const u8` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/const-refs-to-static.rs:17:25 + | +LL | unsafe { asm!("{}", const addr_of!(FOO)) }; + | ^^^^^^------------- + | | + | is a `*const u8` + | + = help: `const` operands must be of an integer type + +error: aborting due to 2 previous errors + From e8472e84e3e1ef614b97896d42e0a6976fb02855 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 13 Aug 2024 17:38:24 -0400 Subject: [PATCH 15/18] Check unnormalized signature on pointer cast --- compiler/rustc_borrowck/src/type_check/mod.rs | 71 +++++++++++++++++-- ...ed-references-plus-variance-early-bound.rs | 11 +++ ...eferences-plus-variance-early-bound.stderr | 10 +++ ...d-references-plus-variance-unnormalized.rs | 17 +++++ ...ferences-plus-variance-unnormalized.stderr | 14 ++++ ...unds-on-nested-references-plus-variance.rs | 7 +- ...-on-nested-references-plus-variance.stderr | 10 +++ 7 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 224f8d5c893d7..3c9a43883ad64 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1979,19 +1979,76 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match cast_kind { CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => { - let fn_sig = op.ty(body, tcx).fn_sig(tcx); + let src_sig = op.ty(body, tcx).fn_sig(tcx); + + // HACK: This shouldn't be necessary... We can remove this when we actually + // get binders with where clauses, then elaborate implied bounds into that + // binder, and implement a higher-ranked subtyping algorithm that actually + // respects these implied bounds. + // + // This protects against the case where we are casting from a higher-ranked + // fn item to a non-higher-ranked fn pointer, where the cast throws away + // implied bounds that would've needed to be checked at the call site. This + // only works when we're casting to a non-higher-ranked fn ptr, since + // placeholders in the target signature could have untracked implied + // bounds, resulting in incorrect errors. + // + // We check that this signature is WF before subtyping the signature with + // the target fn sig. + if src_sig.has_bound_regions() + && let ty::FnPtr(target_fn_tys, target_hdr) = *ty.kind() + && let target_sig = target_fn_tys.with(target_hdr) + && let Some(target_sig) = target_sig.no_bound_vars() + { + let src_sig = self.infcx.instantiate_binder_with_fresh_vars( + span, + BoundRegionConversionTime::HigherRankedType, + src_sig, + ); + let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig)); + self.prove_predicate( + ty::ClauseKind::WellFormed(src_ty.into()), + location.to_locations(), + ConstraintCategory::Cast { unsize_to: None }, + ); + + let src_ty = self.normalize(src_ty, location); + if let Err(terr) = self.sub_types( + src_ty, + *ty, + location.to_locations(), + ConstraintCategory::Cast { unsize_to: None }, + ) { + span_mirbug!( + self, + rvalue, + "equating {:?} with {:?} yields {:?}", + target_sig, + src_sig, + terr + ); + }; + } + + let src_ty = Ty::new_fn_ptr(tcx, src_sig); + // HACK: We want to assert that the signature of the source fn is + // well-formed, because we don't enforce that via the WF of FnDef + // types normally. This should be removed when we improve the tracking + // of implied bounds of fn signatures. + self.prove_predicate( + ty::ClauseKind::WellFormed(src_ty.into()), + location.to_locations(), + ConstraintCategory::Cast { unsize_to: None }, + ); // The type that we see in the fcx is like // `foo::<'a, 'b>`, where `foo` is the path to a // function definition. When we extract the // signature, it comes from the `fn_sig` query, // and hence may contain unnormalized results. - let fn_sig = self.normalize(fn_sig, location); - - let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig); - + let src_ty = self.normalize(src_ty, location); if let Err(terr) = self.sub_types( - ty_fn_ptr_from, + src_ty, *ty, location.to_locations(), ConstraintCategory::Cast { unsize_to: None }, @@ -2000,7 +2057,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self, rvalue, "equating {:?} with {:?} yields {:?}", - ty_fn_ptr_from, + src_ty, ty, terr ); diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs new file mode 100644 index 0000000000000..16095f66da715 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs @@ -0,0 +1,11 @@ +static UNIT: &'static &'static () = &&(); + +fn foo<'a: 'a, 'b: 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v } + +fn bad<'a, T>(x: &'a T) -> &'static T { + let f: fn(_, &'a T) -> &'static T = foo; + //~^ ERROR lifetime may not live long enough + f(UNIT, x) +} + +fn main() {} diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr new file mode 100644 index 0000000000000..4925576e5a09b --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-on-nested-references-plus-variance-early-bound.rs:6:12 + | +LL | fn bad<'a, T>(x: &'a T) -> &'static T { + | -- lifetime `'a` defined here +LL | let f: fn(_, &'a T) -> &'static T = foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 1 previous error + diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs new file mode 100644 index 0000000000000..b842b21224d4e --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs @@ -0,0 +1,17 @@ +trait ToArg { + type Arg; +} +impl ToArg for U { + type Arg = T; +} + +fn extend_inner<'a, 'b>(x: &'a str) -> <&'b &'a () as ToArg<&'b str>>::Arg { x } +fn extend<'a, 'b>(x: &'a str) -> &'b str { + (extend_inner as fn(_) -> _)(x) + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let y = extend(&String::from("Hello World")); + println!("{}", y); +} diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr new file mode 100644 index 0000000000000..a2ac0d897b666 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-on-nested-references-plus-variance-unnormalized.rs:10:5 + | +LL | fn extend<'a, 'b>(x: &'a str) -> &'b str { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | (extend_inner as fn(_) -> _)(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 1 previous error + diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs index f3401f34eec73..d40418a4e9027 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs @@ -1,15 +1,10 @@ -//@ check-pass -//@ known-bug: #25860 - -// Should fail. The combination of variance and implied bounds for nested -// references allows us to infer a longer lifetime than we can prove. - static UNIT: &'static &'static () = &&(); fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v } fn bad<'a, T>(x: &'a T) -> &'static T { let f: fn(_, &'a T) -> &'static T = foo; + //~^ ERROR lifetime may not live long enough f(UNIT, x) } diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr new file mode 100644 index 0000000000000..1ad9ba31f37bc --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-on-nested-references-plus-variance.rs:6:12 + | +LL | fn bad<'a, T>(x: &'a T) -> &'static T { + | -- lifetime `'a` defined here +LL | let f: fn(_, &'a T) -> &'static T = foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 1 previous error + From 67804c57e7a53b96d79b49bf6e356e3ade4d943d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 Aug 2024 16:56:06 -0400 Subject: [PATCH 16/18] Adjust tests --- ...d-bounds-on-nested-references-plus-variance-2.rs | 13 +++++++++++++ ...n-nested-references-plus-variance-early-bound.rs | 2 ++ ...sted-references-plus-variance-early-bound.stderr | 2 +- ...-nested-references-plus-variance-unnormalized.rs | 2 ++ ...ted-references-plus-variance-unnormalized.stderr | 2 +- ...ied-bounds-on-nested-references-plus-variance.rs | 2 ++ ...bounds-on-nested-references-plus-variance.stderr | 2 +- 7 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs new file mode 100644 index 0000000000000..ca8b8b7e4d92b --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs @@ -0,0 +1,13 @@ +//@ check-pass +//@ known-bug: #25860 + +static UNIT: &'static &'static () = &&(); + +fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T, _: &()) -> &'a T { v } + +fn bad<'a, T>(x: &'a T) -> &'static T { + let f: fn(_, &'a T, &()) -> &'static T = foo; + f(UNIT, x, &()) +} + +fn main() {} diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs index 16095f66da715..226a6fa30163c 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs @@ -1,3 +1,5 @@ +// Regression test for #129021. + static UNIT: &'static &'static () = &&(); fn foo<'a: 'a, 'b: 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v } diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr index 4925576e5a09b..84d2a6d2b6a62 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/implied-bounds-on-nested-references-plus-variance-early-bound.rs:6:12 + --> $DIR/implied-bounds-on-nested-references-plus-variance-early-bound.rs:8:12 | LL | fn bad<'a, T>(x: &'a T) -> &'static T { | -- lifetime `'a` defined here diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs index b842b21224d4e..f30689901893c 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs @@ -1,3 +1,5 @@ +// Regression test for #129021. + trait ToArg { type Arg; } diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr index a2ac0d897b666..4cdb959786a56 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/implied-bounds-on-nested-references-plus-variance-unnormalized.rs:10:5 + --> $DIR/implied-bounds-on-nested-references-plus-variance-unnormalized.rs:12:5 | LL | fn extend<'a, 'b>(x: &'a str) -> &'b str { | -- -- lifetime `'b` defined here diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs index d40418a4e9027..6de81cba7281a 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs @@ -1,3 +1,5 @@ +// Regression test for #129021. + static UNIT: &'static &'static () = &&(); fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v } diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr index 1ad9ba31f37bc..c96fa92937b0c 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/implied-bounds-on-nested-references-plus-variance.rs:6:12 + --> $DIR/implied-bounds-on-nested-references-plus-variance.rs:8:12 | LL | fn bad<'a, T>(x: &'a T) -> &'static T { | -- lifetime `'a` defined here From a551cccb623e0c7c52f7db9bcc424c837f848ede Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Sep 2024 10:06:54 -0700 Subject: [PATCH 17/18] Remove wasm32-wasip2's tier 2 status from release notes It turns out the stars did not actually align for this to get released in Rust 1.81 alas. Full tier 2 status for `wasm32-wasip2` required two PRs: * #126967 - this made it into Rust 1.81 * #127867 - this didn't make the cut and is in Rust 1.82 instead This wasn't caught until just after today's release so the plan is to remove the release notes for 1.81 and coordinate to instead add these as release notes to 1.82. --- RELEASES.md | 1 - 1 file changed, 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 29c872eb44896..82954fad1e094 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -34,7 +34,6 @@ Compiler - [Add Tier 3 `std` Xtensa targets:](https://github.com/rust-lang/rust/pull/126380/) `xtensa-esp32-espidf`, `xtensa-esp32s2-espidf`, `xtensa-esp32s3-espidf` - [Add Tier 3 i686 Redox OS target:](https://github.com/rust-lang/rust/pull/126192/) `i686-unknown-redox` - [Promote `arm64ec-pc-windows-msvc` to Tier 2.](https://github.com/rust-lang/rust/pull/126039/) - - [Promote `wasm32-wasip2` to Tier 2.](https://github.com/rust-lang/rust/pull/126967/) - [Promote `loongarch64-unknown-linux-musl` to Tier 2 with host tools.](https://github.com/rust-lang/rust/pull/126298/) - [Enable full tools and profiler for LoongArch Linux targets.](https://github.com/rust-lang/rust/pull/127078/) - [Unconditionally warn on usage of `wasm32-wasi`.](https://github.com/rust-lang/rust/pull/126662/) (see compatibility note below) From f6e8a84eeae8b5f7291999966ab82d495ea7da26 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 5 Sep 2024 00:34:04 +0300 Subject: [PATCH 18/18] Make `Ty::boxed_ty` return an `Option` --- .../src/diagnostics/explain_borrow.rs | 3 ++- compiler/rustc_borrowck/src/diagnostics/mod.rs | 4 ++-- .../rustc_codegen_llvm/src/debuginfo/metadata.rs | 2 +- compiler/rustc_const_eval/src/interpret/call.rs | 2 +- .../src/method/prelude_edition_lints.rs | 3 +-- compiler/rustc_hir_typeck/src/method/probe.rs | 3 +-- compiler/rustc_lint/src/shadowed_into_iter.rs | 7 ++----- compiler/rustc_lint/src/types.rs | 6 ++++-- compiler/rustc_lint/src/unused.rs | 5 ++--- compiler/rustc_middle/src/ty/layout.rs | 6 ++++-- compiler/rustc_middle/src/ty/sty.rs | 15 ++++++++++----- compiler/rustc_middle/src/ty/util.rs | 2 +- .../src/elaborate_box_derefs.rs | 12 ++++++++---- compiler/rustc_monomorphize/src/collector.rs | 7 +++++-- compiler/rustc_monomorphize/src/lib.rs | 2 ++ .../src/error_reporting/infer/mod.rs | 3 +-- src/tools/clippy/clippy_lints/src/escape.rs | 6 +++--- src/tools/clippy/clippy_lints/src/methods/mod.rs | 4 ++-- .../clippy/clippy_lints/src/methods/utils.rs | 4 ++-- .../clippy_lints/src/unnecessary_box_returns.rs | 6 ++---- src/tools/clippy/clippy_utils/src/ty.rs | 4 ++-- 21 files changed, 58 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 91b02a36d0046..c720b0928feb0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -662,9 +662,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { // `&dyn Trait` ty::Ref(_, ty, _) if ty.is_trait() => true, // `Box` - _ if ty.is_box() && ty.boxed_ty().is_trait() => { + _ if ty.boxed_ty().is_some_and(Ty::is_trait) => { true } + // `dyn Trait` _ if ty.is_trait() => true, // Anything else. diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 5ab66963409a8..878ce6162e0f9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -345,9 +345,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { variant_index: Option, including_tuple_field: IncludingTupleField, ) -> Option { - if ty.is_box() { + if let Some(boxed_ty) = ty.boxed_ty() { // If the type is a box, the field is described from the boxed type - self.describe_field_from_ty(ty.boxed_ty(), field, variant_index, including_tuple_field) + self.describe_field_from_ty(boxed_ty, field, variant_index, including_tuple_field) } else { match *ty.kind() { ty::Adt(def, _) => { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 17a9630c6557b..d231b103964b6 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -456,7 +456,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> if def.is_box() && args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst()) => { - build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id) + build_pointer_or_reference_di_node(cx, t, t.expect_boxed_ty(), unique_type_id) } ty::FnDef(..) | ty::FnPtr(..) => build_subroutine_type_di_node(cx, unique_type_id), ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id), diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 82438eb5e7828..568a9a3a637be 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -189,7 +189,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::Ref(_, ty, _) => *ty, ty::RawPtr(ty, _) => *ty, // We only accept `Box` with the default allocator. - _ if ty.is_box_global(*self.tcx) => ty.boxed_ty(), + _ if ty.is_box_global(*self.tcx) => ty.expect_boxed_ty(), _ => return Ok(None), })) }; diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index 0790c6f9a5992..ac5e1040803e0 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -63,8 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Instead, the problem is that the array-into_iter hack will no longer // apply in Rust 2021. (ARRAY_INTO_ITER, "2021") - } else if self_ty.is_box() - && self_ty.boxed_ty().is_slice() + } else if self_ty.boxed_ty().is_some_and(Ty::is_slice) && !span.at_least_rust_2024() { // In this case, it wasn't really a prelude addition that was the problem. diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 0cf5403b3c085..4b3c52a1ed604 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1485,8 +1485,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Some trait methods are excluded for boxed slices before 2024. // (`boxed_slice.into_iter()` wants a slice iterator for compatibility.) - if self_ty.is_box() - && self_ty.boxed_ty().is_slice() + if self_ty.boxed_ty().is_some_and(Ty::is_slice) && !method_name.span.at_least_rust_2024() { let trait_def = self.tcx.trait_def(poly_trait_ref.def_id()); diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index bb9c7d85c2efc..bb122509d0a89 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -94,12 +94,9 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter { fn is_ref_to_array(ty: Ty<'_>) -> bool { if let ty::Ref(_, pointee_ty, _) = *ty.kind() { pointee_ty.is_array() } else { false } } - fn is_boxed_slice(ty: Ty<'_>) -> bool { - ty.is_box() && ty.boxed_ty().is_slice() - } fn is_ref_to_boxed_slice(ty: Ty<'_>) -> bool { if let ty::Ref(_, pointee_ty, _) = *ty.kind() { - is_boxed_slice(pointee_ty) + pointee_ty.boxed_ty().is_some_and(Ty::is_slice) } else { false } @@ -119,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter { .iter() .copied() .take_while(|ty| !is_ref_to_boxed_slice(*ty)) - .position(|ty| is_boxed_slice(ty)) + .position(|ty| ty.boxed_ty().is_some_and(Ty::is_slice)) { (BOXED_SLICE_INTO_ITER, "Box<[T]>", "2024", idx == 0) } else { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f2f7c0eaa4df8..b5e501b92f0d6 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1304,8 +1304,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match *ty.kind() { ty::Adt(def, args) => { - if def.is_box() && matches!(self.mode, CItemKind::Definition) { - if ty.boxed_ty().is_sized(tcx, self.cx.param_env) { + if let Some(boxed) = ty.boxed_ty() + && matches!(self.mode, CItemKind::Definition) + { + if boxed.is_sized(tcx, self.cx.param_env) { return FfiSafe; } else { return FfiUnsafe { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 761d30bac715a..b7f7b782c7722 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -283,9 +283,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } match *ty.kind() { - ty::Adt(..) if ty.is_box() => { - let boxed_ty = ty.boxed_ty(); - is_ty_must_use(cx, boxed_ty, expr, span) + ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => { + is_ty_must_use(cx, boxed, expr, span) .map(|inner| MustUsePath::Boxed(Box::new(inner))) } ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index d0a9039441dc4..8cec8eac1898a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1075,11 +1075,13 @@ where // the raw pointer, so size and align are set to the boxed type, but `pointee.safe` // will still be `None`. if let Some(ref mut pointee) = result { - if offset.bytes() == 0 && this.ty.is_box() { + if offset.bytes() == 0 + && let Some(boxed_ty) = this.ty.boxed_ty() + { debug_assert!(pointee.safe.is_none()); let optimize = tcx.sess.opts.optimize != OptLevel::No; pointee.safe = Some(PointerKind::Box { - unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()), + unpin: optimize && boxed_ty.is_unpin(tcx, cx.param_env()), global: this.ty.is_box_global(tcx), }); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 89ef30fa768e0..1f4f2c62d7084 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1170,14 +1170,19 @@ impl<'tcx> Ty<'tcx> { } } - /// Panics if called on any type other than `Box`. - pub fn boxed_ty(self) -> Ty<'tcx> { + pub fn boxed_ty(self) -> Option> { match self.kind() { - Adt(def, args) if def.is_box() => args.type_at(0), - _ => bug!("`boxed_ty` is called on non-box type {:?}", self), + Adt(def, args) if def.is_box() => Some(args.type_at(0)), + _ => None, } } + /// Panics if called on any type other than `Box`. + pub fn expect_boxed_ty(self) -> Ty<'tcx> { + self.boxed_ty() + .unwrap_or_else(|| bug!("`expect_boxed_ty` is called on non-box type {:?}", self)) + } + /// A scalar type is one that denotes an atomic datum, with no sub-components. /// (A RawPtr is scalar because it represents a non-managed pointer, so its /// contents are abstract to rustc.) @@ -1323,7 +1328,7 @@ impl<'tcx> Ty<'tcx> { /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly. pub fn builtin_deref(self, explicit: bool) -> Option> { match *self.kind() { - Adt(def, _) if def.is_box() => Some(self.boxed_ty()), + _ if let Some(boxed) = self.boxed_ty() => Some(boxed), Ref(_, ty, _) => Some(ty), RawPtr(ty, _) if explicit => Some(ty), _ => None, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index efbccca77c1f0..d70ff8258d04c 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1628,7 +1628,7 @@ impl<'tcx> ExplicitSelf<'tcx> { _ if is_self_ty(self_arg_ty) => ByValue, ty::Ref(region, ty, mutbl) if is_self_ty(ty) => ByReference(region, mutbl), ty::RawPtr(ty, mutbl) if is_self_ty(ty) => ByRawPointer(mutbl), - ty::Adt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => ByBox, + _ if self_arg_ty.boxed_ty().is_some_and(is_self_ty) => ByBox, _ => Other, } } diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index e5778f8a05d2e..97beb728bbc28 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -62,11 +62,13 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { let base_ty = self.local_decls[place.local].ty; // Derefer ensures that derefs are always the first projection - if place.projection.first() == Some(&PlaceElem::Deref) && base_ty.is_box() { + if let Some(PlaceElem::Deref) = place.projection.first() + && let Some(boxed_ty) = base_ty.boxed_ty() + { let source_info = self.local_decls[place.local].source_info; let (unique_ty, nonnull_ty, ptr_ty) = - build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did); + build_ptr_tys(tcx, boxed_ty, self.unique_did, self.nonnull_did); let ptr_local = self.patch.new_temp(ptr_ty, source_info.span); @@ -120,13 +122,15 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs { for (base, elem) in place.iter_projections() { let base_ty = base.ty(&body.local_decls, tcx).ty; - if elem == PlaceElem::Deref && base_ty.is_box() { + if let PlaceElem::Deref = elem + && let Some(boxed_ty) = base_ty.boxed_ty() + { // Clone the projections before us, since now we need to mutate them. let new_projections = new_projections.get_or_insert_with(|| base.projection.to_vec()); let (unique_ty, nonnull_ty, ptr_ty) = - build_ptr_tys(tcx, base_ty.boxed_ty(), unique_did, nonnull_did); + build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did); new_projections.extend_from_slice(&build_projection( unique_ty, nonnull_ty, ptr_ty, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 8515ab45de217..093697a290c00 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1041,8 +1041,11 @@ fn find_vtable_types_for_unsizing<'tcx>( match (source_ty.kind(), target_ty.kind()) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _)) | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b), - (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { - ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty()) + (_, _) + if let Some(source_boxed) = source_ty.boxed_ty() + && let Some(target_boxed) = target_ty.boxed_ty() => + { + ptr_vtable(source_boxed, target_boxed) } // T as dyn* Trait diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index b22e8e30465ea..91101ddd59022 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,5 +1,7 @@ // tidy-alphabetical-start #![feature(array_windows)] +#![feature(if_let_guard)] +#![feature(let_chains)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index bff2a184b19f0..65d21518491da 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -348,8 +348,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } if let Some(ty::error::ExpectedFound { found, .. }) = exp_found - && ty.is_box() - && ty.boxed_ty() == found + && ty.boxed_ty() == Some(found) && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { err.span_suggestion( diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index a5da52b0be50a..803606979410b 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { } fn is_non_trait_box(ty: Ty<'_>) -> bool { - ty.is_box() && !ty.boxed_ty().is_trait() + ty.boxed_ty().is_some_and(|boxed| !boxed.is_trait()) } struct EscapeDelegate<'a, 'tcx> { @@ -191,8 +191,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { fn is_large_box(&self, ty: Ty<'tcx>) -> bool { // Large types need to be boxed to avoid stack overflows. - if ty.is_box() { - self.cx.layout_of(ty.boxed_ty()).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack + if let Some(boxed_ty) = ty.boxed_ty() { + self.cx.layout_of(boxed_ty).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack } else { false } diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index d7126990edb1d..f61bb3a6bf481 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -5187,8 +5187,8 @@ impl SelfKind { fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool { if ty == parent_ty { true - } else if ty.is_box() { - ty.boxed_ty() == parent_ty + } else if let Some(boxed_ty) = ty.boxed_ty() { + boxed_ty == parent_ty } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) { if let ty::Adt(_, args) = ty.kind() { args.types().next().map_or(false, |t| t == parent_ty) diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs index 0d2b0a3131763..fe860e5ae2601 100644 --- a/src/tools/clippy/clippy_lints/src/methods/utils.rs +++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs @@ -16,7 +16,7 @@ pub(super) fn derefs_to_slice<'tcx>( fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool { match ty.kind() { ty::Slice(_) => true, - ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), + ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => may_slice(cx, boxed), ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec), ty::Array(_, size) => size.try_eval_target_usize(cx.tcx, cx.param_env).is_some(), ty::Ref(_, inner, _) => may_slice(cx, *inner), @@ -33,7 +33,7 @@ pub(super) fn derefs_to_slice<'tcx>( } else { match ty.kind() { ty::Slice(_) => Some(expr), - ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr), + _ if ty.boxed_ty().is_some_and(|boxed| may_slice(cx, boxed)) => Some(expr), ty::Ref(_, inner, _) => { if may_slice(cx, *inner) { Some(expr) diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs index 3f130bf5a6731..14f4aa6676b65 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs @@ -75,11 +75,9 @@ impl UnnecessaryBoxReturns { .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(def_id).skip_binder()) .output(); - if !return_ty.is_box() { + let Some(boxed_ty) = return_ty.boxed_ty() else { return; - } - - let boxed_ty = return_ty.boxed_ty(); + }; // It's sometimes useful to return Box if T is unsized, so don't lint those. // Also, don't lint if we know that T is very large, in which case returning diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index f80981c11af65..585134209ca3a 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -704,8 +704,8 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { - if ty.is_box() { - return ty_sig(cx, ty.boxed_ty()); + if let Some(boxed_ty) = ty.boxed_ty() { + return ty_sig(cx, boxed_ty); } match *ty.kind() { ty::Closure(id, subs) => {