diff options
172 files changed, 2192 insertions, 784 deletions
diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 1dc5b0e9d08..f4e409e0d49 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -6,8 +6,6 @@ on: schedule: # Run weekly - cron: '0 0 * * Sun' - # Re-bump deps every 4 hours - - cron: '0 */4 * * *' workflow_dispatch: # Needed so we can run it manually permissions: @@ -42,7 +40,7 @@ jobs: # Exit with error if open and S-waiting-on-bors if [[ "$STATE" == "OPEN" && "$WAITING_ON_BORS" == "true" ]]; then - gh run cancel ${{ github.run_id }} + exit 1 fi update: @@ -65,10 +63,7 @@ jobs: - name: cargo update # Remove first line that always just says "Updating crates.io index" - # If there are no changes, cancel the job here - run: | - cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log - git status --porcelain | grep -q Cargo.lock || gh run cancel ${{ github.run_id }} + run: cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log - name: upload Cargo.lock artifact for use in PR uses: actions/upload-artifact@v4 with: @@ -95,11 +90,11 @@ jobs: uses: actions/checkout@v4 - name: download Cargo.lock from update job - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: Cargo-lock - name: download cargo-update log from update job - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: cargo-updates @@ -134,14 +129,14 @@ jobs: # Exit with error if PR is closed STATE=$(gh pr view cargo_update --repo $GITHUB_REPOSITORY --json state --jq '.state') if [[ "$STATE" != "OPEN" ]]; then - gh run cancel ${{ github.run_id }} + exit 1 fi gh pr edit cargo_update --title "${PR_TITLE}" --body-file body.md --repo $GITHUB_REPOSITORY - name: open new pull request - # Only run if there wasn't an existing PR and if this is the weekly run - if: steps.edit.outcome != 'success' && github.event.schedule == '0 0 * * Sun' + # Only run if there wasn't an existing PR + if: steps.edit.outcome != 'success' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: gh pr create --title "${PR_TITLE}" --body-file body.md --repo $GITHUB_REPOSITORY diff --git a/.mailmap b/.mailmap index 0d96f5f3d4f..93f5ca8157c 100644 --- a/.mailmap +++ b/.mailmap @@ -324,6 +324,7 @@ Katze <binary@benary.org> Keegan McAllister <mcallister.keegan@gmail.com> <kmcallister@mozilla.com> Kerem Kat <keremkat@gmail.com> Kevin Butler <haqkrs@gmail.com> +Kevin Reid <kpreid@switchb.org> <kpreid@google.com> Kevin Jiang <kwj2104@columbia.edu> Kornel Lesiński <kornel@geekhood.net> Krishna Sai Veera Reddy <veerareddy@email.arizona.edu> diff --git a/Cargo.lock b/Cargo.lock index 9163538765d..c4501d6e574 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3784,6 +3784,7 @@ dependencies = [ name = "rustc_driver_impl" version = "0.0.0" dependencies = [ + "ctrlc", "libc", "rustc_ast", "rustc_ast_lowering", diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 35bd7d37992..578369de4d6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -4,6 +4,7 @@ #![allow(rustc::untranslatable_diagnostic)] use either::Either; +use hir::ClosureKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan}; @@ -463,6 +464,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans { // We already suggest cloning for these cases in `explain_captures`. + } else if let UseSpans::ClosureUse { + closure_kind: + ClosureKind::Coroutine(CoroutineKind::Desugared(_, CoroutineSource::Block)), + args_span: _, + capture_kind_span: _, + path_span, + } = move_spans + { + self.suggest_cloning(err, ty, expr, path_span); } else if self.suggest_hoisting_call_outside_loop(err, expr) { // The place where the the type moves would be misleading to suggest clone. // #121466 @@ -621,7 +631,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // FIXME: We make sure that this is a normal top-level binding, - // but we could suggest `todo!()` for all uninitalized bindings in the pattern pattern + // but we could suggest `todo!()` for all uninitialized bindings in the pattern pattern if let hir::StmtKind::Let(hir::LetStmt { span, ty, init: None, pat, .. }) = &ex.kind && let hir::PatKind::Binding(..) = pat.kind @@ -749,7 +759,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { true } - /// In a move error that occurs on a call wihtin a loop, we try to identify cases where cloning + /// In a move error that occurs on a call within a loop, we try to identify cases where cloning /// the value would lead to a logic error. We infer these cases by seeing if the moved value is /// part of the logic to break the loop, either through an explicit `break` or if the expression /// is part of a `while let`. @@ -950,7 +960,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { { // FIXME: We could check that the call's *parent* takes `&mut val` to make the // suggestion more targeted to the `mk_iter(val).next()` case. Maybe do that only to - // check for wheter to suggest `let value` or `let mut value`. + // check for whether to suggest `let value` or `let mut value`. let span = in_loop.span; if !finder.found_breaks.is_empty() diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index a5a5ae73d77..1a32958d362 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -20,6 +20,7 @@ use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_session::config::OptLevel; use rustc_span::Span; use rustc_symbol_mangling::typeid::{ kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance, @@ -551,6 +552,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { layout: TyAndLayout<'tcx>, offset: Size, ) { + if bx.cx.sess().opts.optimize == OptLevel::No { + // Don't emit metadata we're not going to use + return; + } + if !scalar.is_uninit_valid() { bx.noundef_metadata(load); } @@ -667,6 +673,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { return; } + if self.cx.sess().opts.optimize == OptLevel::No { + // Don't emit metadata we're not going to use + return; + } + unsafe { let llty = self.cx.val_ty(load); let v = [ @@ -1630,7 +1641,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } let typeid = if let Some(instance) = instance { - typeid_for_instance(self.tcx, &instance, options) + typeid_for_instance(self.tcx, instance, options) } else { typeid_for_fnabi(self.tcx, fn_abi, options) }; @@ -1678,7 +1689,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } let kcfi_typeid = if let Some(instance) = instance { - kcfi_typeid_for_instance(self.tcx, &instance, options) + kcfi_typeid_for_instance(self.tcx, instance, options) } else { kcfi_typeid_for_fnabi(self.tcx, fn_abi, options) }; diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 78c0725a637..1a2498c75a7 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -141,17 +141,17 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { if self.tcx.sess.is_sanitizer_cfi_enabled() { if let Some(instance) = instance { - let typeid = typeid_for_instance(self.tcx, &instance, TypeIdOptions::empty()); + let typeid = typeid_for_instance(self.tcx, instance, TypeIdOptions::empty()); self.set_type_metadata(llfn, typeid); let typeid = - typeid_for_instance(self.tcx, &instance, TypeIdOptions::GENERALIZE_POINTERS); + typeid_for_instance(self.tcx, instance, TypeIdOptions::GENERALIZE_POINTERS); self.add_type_metadata(llfn, typeid); let typeid = - typeid_for_instance(self.tcx, &instance, TypeIdOptions::NORMALIZE_INTEGERS); + typeid_for_instance(self.tcx, instance, TypeIdOptions::NORMALIZE_INTEGERS); self.add_type_metadata(llfn, typeid); let typeid = typeid_for_instance( self.tcx, - &instance, + instance, TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS, ); self.add_type_metadata(llfn, typeid); @@ -182,7 +182,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } if let Some(instance) = instance { - let kcfi_typeid = kcfi_typeid_for_instance(self.tcx, &instance, options); + let kcfi_typeid = kcfi_typeid_for_instance(self.tcx, instance, options); self.set_kcfi_type_metadata(llfn, kcfi_typeid); } else { let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options); diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 0046190d20c..d6aae60c338 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -146,6 +146,8 @@ const_eval_intern_kind = {$kind -> *[other] {""} } +const_eval_interrupted = compilation was interrupted + const_eval_invalid_align_details = invalid align passed to `{$name}`: {$align} is {$err_kind -> [not_power_of_two] not a power of 2 diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 5a1c7cc4209..098a6201c4e 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -1,3 +1,5 @@ +use std::sync::atomic::Ordering::Relaxed; + use either::{Left, Right}; use rustc_hir::def::DefKind; @@ -22,6 +24,7 @@ use crate::interpret::{ InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, }; +use crate::CTRL_C_RECEIVED; // Returns a pointer to where the result lives #[instrument(level = "trace", skip(ecx, body))] @@ -79,7 +82,11 @@ fn eval_body_using_ecx<'mir, 'tcx, R: InterpretationResult<'tcx>>( ecx.storage_live_for_always_live_locals()?; // The main interpreter loop. - while ecx.step()? {} + while ecx.step()? { + if CTRL_C_RECEIVED.load(Relaxed) { + throw_exhaust!(Interrupted); + } + } // Intern the result intern_const_alloc_recursive(ecx, intern_kind, &ret)?; diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index cc32640408b..5c46ec799f1 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -884,6 +884,7 @@ impl ReportErrorExt for ResourceExhaustionInfo { ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached, ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted, ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full, + ResourceExhaustionInfo::Interrupted => const_eval_interrupted, } } fn add_args<G: EmissionGuarantee>(self, _: &mut Diag<'_, G>) {} diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 633caf8d092..50420aaec04 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -32,6 +32,8 @@ pub mod interpret; pub mod transform; pub mod util; +use std::sync::atomic::AtomicBool; + pub use errors::ReportErrorExt; use rustc_middle::{ty, util::Providers}; @@ -58,3 +60,8 @@ pub fn provide(providers: &mut Providers) { util::check_validity_requirement(tcx, init_kind, param_env_and_ty) }; } + +/// `rustc_driver::main` installs a handler that will set this to `true` if +/// the compiler has been sent a request to shut down, such as by a Ctrl-C. +/// This static lives here because it is only read by the interpreter. +pub static CTRL_C_RECEIVED: AtomicBool = AtomicBool::new(false); diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index fcc0afd3488..e4fb13822f8 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +ctrlc = "3.4.4" rustc_ast = { path = "../rustc_ast" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_passes = { path = "../rustc_ast_passes" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 716e31080dd..b4007aeb8d7 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -19,6 +19,7 @@ extern crate tracing; use rustc_ast as ast; use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults}; +use rustc_const_eval::CTRL_C_RECEIVED; use rustc_data_structures::profiling::{ get_resident_set_size, print_time_passes_entry, TimePassesFormat, }; @@ -1518,6 +1519,22 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) { } } +/// Install our usual `ctrlc` handler, which sets [`rustc_const_eval::CTRL_C_RECEIVED`]. +/// Making this handler optional lets tools can install a different handler, if they wish. +pub fn install_ctrlc_handler() { + ctrlc::set_handler(move || { + // Indicate that we have been signaled to stop. If we were already signaled, exit + // immediately. In our interpreter loop we try to consult this value often, but if for + // whatever reason we don't get to that check or the cleanup we do upon finding that + // this bool has become true takes a long time, the exit here will promptly exit the + // process on the second Ctrl-C. + if CTRL_C_RECEIVED.swap(true, Ordering::Relaxed) { + std::process::exit(1); + } + }) + .expect("Unable to install ctrlc handler"); +} + pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); @@ -1528,6 +1545,8 @@ pub fn main() -> ! { signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ()); + install_ctrlc_handler(); + let exit_code = catch_with_exit_code(|| { RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks) .set_using_internal_features(using_internal_features) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index cc0ab05d422..a70d2ebbd62 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2289,21 +2289,15 @@ pub enum ImplItemKind<'hir> { Type(&'hir Ty<'hir>), } -/// Bind a type to an associated type (i.e., `A = Foo`). +/// An associated item binding. /// -/// Bindings like `A: Debug` are represented as a special type `A = -/// $::Debug` that is understood by the HIR ty lowering code. +/// ### Examples /// -/// FIXME(alexreg): why have a separate type for the binding case, -/// wouldn't it be better to make the `ty` field an enum like the -/// following? -/// -/// ```ignore (pseudo-rust) -/// enum TypeBindingKind { -/// Equals(...), -/// Binding(...), -/// } -/// ``` +/// * `Trait<A = Ty, B = Ty>` +/// * `Trait<G<Ty> = Ty>` +/// * `Trait<A: Bound>` +/// * `Trait<C = { Ct }>` (under feature `associated_const_equality`) +/// * `Trait<f(): Bound>` (under feature `return_type_notation`) #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct TypeBinding<'hir> { pub hir_id: HirId, @@ -2336,7 +2330,7 @@ impl<'hir> From<AnonConst> for Term<'hir> { pub enum TypeBindingKind<'hir> { /// E.g., `Foo<Bar: Send>`. Constraint { bounds: &'hir [GenericBound<'hir>] }, - /// E.g., `Foo<Bar = ()>`, `Foo<Bar = ()>` + /// E.g., `Foo<Bar = ()>`. Equality { term: Term<'hir> }, } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index dbf86f5cf74..5d97019416f 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -199,6 +199,7 @@ language_item_table! { Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0); DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0); + DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0); DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None; Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 80be563686a..8c35da3ac7b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -9,8 +9,85 @@ use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamNa use super::HirTyLowerer; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { + /// Prohibit or lint against *bare* trait object types depending on the edition. + /// + /// *Bare* trait object types are ones that aren't preceeded by the keyword `dyn`. + /// In edition 2021 and onward we emit a hard error for them. + pub(super) fn prohibit_or_lint_bare_trait_object_ty( + &self, + self_ty: &hir::Ty<'_>, + in_path: bool, + ) { + let tcx = self.tcx(); + + let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = + self_ty.kind + else { + return; + }; + + let needs_bracket = in_path + && !tcx + .sess + .source_map() + .span_to_prev_source(self_ty.span) + .ok() + .is_some_and(|s| s.trim_end().ends_with('<')); + + let is_global = poly_trait_ref.trait_ref.path.is_global(); + + let mut sugg = vec![( + self_ty.span.shrink_to_lo(), + format!( + "{}dyn {}", + if needs_bracket { "<" } else { "" }, + if is_global { "(" } else { "" }, + ), + )]; + + if is_global || needs_bracket { + sugg.push(( + self_ty.span.shrink_to_hi(), + format!( + "{}{}", + if is_global { ")" } else { "" }, + if needs_bracket { ">" } else { "" }, + ), + )); + } + + if self_ty.span.edition().at_least_rust_2021() { + let msg = "trait objects must include the `dyn` keyword"; + let label = "add `dyn` keyword before this trait"; + let mut diag = + rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg); + if self_ty.span.can_be_used_for_suggestions() + && !self.maybe_suggest_impl_trait(self_ty, &mut diag) + { + // FIXME: Only emit this suggestion if the trait is object safe. + diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable); + } + // Check if the impl trait that we are considering is an impl of a local trait. + self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); + self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); + diag.stash(self_ty.span, StashKey::TraitMissingMethod); + } else { + let msg = "trait objects without an explicit `dyn` are deprecated"; + tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| { + if self_ty.span.can_be_used_for_suggestions() { + lint.multipart_suggestion_verbose( + "if this is an object-safe trait, use `dyn`", + sugg, + Applicability::MachineApplicable, + ); + } + self.maybe_suggest_blanket_trait_impl(self_ty, lint); + }); + } + } + /// Make sure that we are in the condition to suggest the blanket implementation. - pub(super) fn maybe_lint_blanket_trait_impl<G: EmissionGuarantee>( + fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>( &self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_, G>, @@ -75,9 +152,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Make sure that we are in the condition to suggest `impl Trait`. - fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool { + fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool { let tcx = self.tcx(); let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; + // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>` + // and suggest `Trait0<Ty = impl Trait1>`. let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { (sig, generics, None) @@ -186,71 +265,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { false } - pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { - let tcx = self.tcx(); - if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = - self_ty.kind - { - let needs_bracket = in_path - && !tcx - .sess - .source_map() - .span_to_prev_source(self_ty.span) - .ok() - .is_some_and(|s| s.trim_end().ends_with('<')); - - let is_global = poly_trait_ref.trait_ref.path.is_global(); - - let mut sugg = Vec::from_iter([( - self_ty.span.shrink_to_lo(), - format!( - "{}dyn {}", - if needs_bracket { "<" } else { "" }, - if is_global { "(" } else { "" }, - ), - )]); + fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) { + let mut parents = self.tcx().hir().parent_iter(self_ty.hir_id); - if is_global || needs_bracket { - sugg.push(( - self_ty.span.shrink_to_hi(), - format!( - "{}{}", - if is_global { ")" } else { "" }, - if needs_bracket { ">" } else { "" }, - ), - )); + if let Some((_, hir::Node::TypeBinding(binding))) = parents.next() + && let hir::TypeBindingKind::Equality { term: hir::Term::Ty(obj_ty) } = binding.kind + { + if let Some((_, hir::Node::TraitRef(..))) = parents.next() + && let Some((_, hir::Node::Ty(ty))) = parents.next() + && let hir::TyKind::TraitObject(..) = ty.kind + { + // Assoc ty bounds aren't permitted inside trait object types. + return; } - if self_ty.span.edition().at_least_rust_2021() { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; - let mut diag = - rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg); - if self_ty.span.can_be_used_for_suggestions() - && !self.maybe_lint_impl_trait(self_ty, &mut diag) - { - diag.multipart_suggestion_verbose( - label, - sugg, - Applicability::MachineApplicable, - ); - } - // check if the impl trait that we are considering is a impl of a local trait - self.maybe_lint_blanket_trait_impl(self_ty, &mut diag); - diag.stash(self_ty.span, StashKey::TraitMissingMethod); + let lo = if binding.gen_args.span_ext.is_dummy() { + binding.ident.span } else { - let msg = "trait objects without an explicit `dyn` are deprecated"; - tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| { - if self_ty.span.can_be_used_for_suggestions() { - lint.multipart_suggestion_verbose( - "if this is an object-safe trait, use `dyn`", - sugg, - Applicability::MachineApplicable, - ); - } - self.maybe_lint_blanket_trait_impl(self_ty, lint); - }); + binding.gen_args.span_ext + }; + let hi = obj_ty.span; + + if !lo.eq_ctxt(hi) { + return; } + + diag.span_suggestion_verbose( + lo.between(hi), + "you might have meant to write a bound here", + ": ", + Applicability::MaybeIncorrect, + ); } } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index a119ea450b4..a83b5b78f9c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2339,12 +2339,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - self.maybe_lint_bare_trait(hir_ty, in_path); + self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path); + let repr = match repr { TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, TraitObjectSyntax::DynStar => ty::DynStar, }; - self.lower_trait_object_ty( hir_ty.span, hir_ty.hir_id, diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 3ec5894700f..b7786ec219c 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -101,8 +101,9 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::middle; +use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::util; use rustc_session::parse::feature_err; use rustc_span::{symbol::sym, Span}; @@ -186,7 +187,12 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { let def_kind = tcx.def_kind(item_def_id); match def_kind { DefKind::Static { .. } => tcx.ensure().eval_static_initializer(item_def_id), - DefKind::Const => tcx.ensure().const_eval_poly(item_def_id.into()), + DefKind::Const if tcx.generics_of(item_def_id).params.is_empty() => { + let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty()); + let cid = GlobalId { instance, promoted: None }; + let param_env = ty::ParamEnv::reveal_all(); + tcx.ensure().eval_to_const_value_raw(param_env.and(cid)); + } _ => (), } }); diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 9b7db9e4c8e..e42db342f14 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -243,7 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let can_coerce_to_return_ty = match self.ret_coercion.as_ref() { Some(ret_coercion) => { let ret_ty = ret_coercion.borrow().expected_ty(); - let ret_ty = self.inh.infcx.shallow_resolve(ret_ty); + let ret_ty = self.infcx.shallow_resolve(ret_ty); self.can_coerce(arm_ty, ret_ty) && prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty)) // The match arms need to unify for the case of `impl Trait`. diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 40555bf14eb..36af5394015 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -848,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_vars, ); - let c_result = self.inh.infcx.canonicalize_response(result); + let c_result = self.infcx.canonicalize_response(result); self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); // Normalize only after registering in `user_provided_sigs`. diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 140618e97cc..fe1e4e74973 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -347,7 +347,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { .any(|n| roots_reachable_from_non_diverging.visited(n)); let infer_var_infos: UnordBag<_> = self - .inh .infer_var_info .borrow() .items() diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 8e0be7c7163..011607bacc6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -526,7 +526,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) { let scope_tree = self.tcx.region_scope_tree(def_id); let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, scope_tree, def_id) }; - let mut typeck_results = self.inh.typeck_results.borrow_mut(); + let mut typeck_results = self.typeck_results.borrow_mut(); typeck_results.rvalue_scopes = rvalue_scopes; } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index efa2862177e..74f27cfebbd 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -7,7 +7,7 @@ mod suggestions; use crate::coercion::DynamicCoerceMany; use crate::fallback::DivergingFallbackBehavior; use crate::fn_ctxt::checks::DivergingBlockBehavior; -use crate::{CoroutineTypes, Diverges, EnclosingBreakables, Inherited}; +use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt}; use hir::def_id::CRATE_DEF_ID; use rustc_errors::{DiagCtxt, ErrorGuaranteed}; use rustc_hir as hir; @@ -108,7 +108,7 @@ pub struct FnCtxt<'a, 'tcx> { pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>, - pub(super) inh: &'a Inherited<'tcx>, + pub(super) root_ctxt: &'a TypeckRootCtxt<'tcx>, pub(super) fallback_has_occurred: Cell<bool>, @@ -118,12 +118,12 @@ pub struct FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn new( - inh: &'a Inherited<'tcx>, + root_ctxt: &'a TypeckRootCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, ) -> FnCtxt<'a, 'tcx> { let (diverging_fallback_behavior, diverging_block_behavior) = - parse_never_type_options_attr(inh.tcx); + parse_never_type_options_attr(root_ctxt.tcx); FnCtxt { body_id, param_env, @@ -137,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { stack: Vec::new(), by_id: Default::default(), }), - inh, + root_ctxt, fallback_has_occurred: Cell::new(false), diverging_fallback_behavior, diverging_block_behavior, @@ -206,9 +206,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { - type Target = Inherited<'tcx>; + type Target = TypeckRootCtxt<'tcx>; fn deref(&self) -> &Self::Target { - self.inh + self.root_ctxt } } diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 1fa799dcec7..be5cd6e9d48 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -95,8 +95,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { Some(ref ty) => { let o_ty = self.fcx.lower_ty(ty); - let c_ty = - self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw)); + let c_ty = self.fcx.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw)); debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); self.fcx .typeck_results diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 0b67b37df29..3a16884d5c7 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -31,7 +31,6 @@ pub mod expr_use_visitor; mod fallback; mod fn_ctxt; mod gather_locals; -mod inherited; mod intrinsicck; mod mem_categorization; mod method; @@ -39,11 +38,12 @@ mod op; mod pat; mod place_op; mod rvalue_scopes; +mod typeck_root_ctxt; mod upvar; mod writeback; pub use fn_ctxt::FnCtxt; -pub use inherited::Inherited; +pub use typeck_root_ctxt::TypeckRootCtxt; use crate::check::check_fn; use crate::coercion::DynamicCoerceMany; @@ -170,11 +170,11 @@ fn typeck_with_fallback<'tcx>( let param_env = tcx.param_env(def_id); - let inh = Inherited::new(tcx, def_id); + let root_ctxt = TypeckRootCtxt::new(tcx, def_id); if let Some(inspector) = inspector { - inh.infcx.attach_obligation_inspector(inspector); + root_ctxt.infcx.attach_obligation_inspector(inspector); } - let mut fcx = FnCtxt::new(&inh, param_env, def_id); + let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id); if let Some(hir::FnSig { header, decl, .. }) = fn_sig { let fn_sig = if decl.output.get_infer_ret_ty().is_some() { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 4dc60f7c6da..861a00ce874 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -388,8 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !pat_adjustments.is_empty() { debug!("default binding mode is now {:?}", def_bm); - self.inh - .typeck_results + self.typeck_results .borrow_mut() .pat_adjustments_mut() .insert(pat.hir_id, pat_adjustments); @@ -614,7 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => BindingMode::convert(ba), }; // ...and store it in a side table: - self.inh.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm); + self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm); debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); @@ -2002,8 +2001,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx> { let tcx = self.tcx; - // FIXME(deref_patterns): use `DerefPure` for soundness - // FIXME(deref_patterns): use `DerefMut` when required + // Register a `DerefPure` bound, which is required by all `deref!()` pats. + self.register_bound( + expected, + tcx.require_lang_item(hir::LangItem::DerefPure, Some(span)), + self.misc(span), + ); // <expected as Deref>::Target let ty = Ty::new_projection( tcx, @@ -2013,6 +2016,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.normalize(span, ty); let ty = self.try_structurally_resolve_type(span, ty); self.check_pat(inner, ty, pat_info); + + // Check if the pattern has any `ref mut` bindings, which would require + // `DerefMut` to be emitted in MIR building instead of just `Deref`. + // We do this *after* checking the inner pattern, since we want to make + // sure to apply any match-ergonomics adjustments. + if self.typeck_results.borrow().pat_has_ref_mut_binding(inner) { + self.register_bound( + expected, + tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)), + self.misc(span), + ); + } + expected } diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index b0950ed2800..e493e6a0a7e 100644 --- a/compiler/rustc_hir_typeck/src/inherited.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -16,7 +16,8 @@ use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, Trai use std::cell::RefCell; use std::ops::Deref; -/// Closures defined within the function. For example: +// Data shared between a "typeck root" and its nested bodies, +/// e.g. closures defined within the function. For example: /// ```ignore (illustrative) /// fn foo() { /// bar(move|| { ... }) @@ -24,8 +25,9 @@ use std::ops::Deref; /// ``` /// Here, the function `foo()` and the closure passed to /// `bar()` will each have their own `FnCtxt`, but they will -/// share the inherited fields. -pub struct Inherited<'tcx> { +/// share the inference context, will process obligations together, +/// can access each other's local types (scoping permitted), etc. +pub struct TypeckRootCtxt<'tcx> { pub(super) infcx: InferCtxt<'tcx>, pub(super) typeck_results: RefCell<ty::TypeckResults<'tcx>>, @@ -65,14 +67,14 @@ pub struct Inherited<'tcx> { pub(super) infer_var_info: RefCell<UnordMap<ty::TyVid, ty::InferVarInfo>>, } -impl<'tcx> Deref for Inherited<'tcx> { +impl<'tcx> Deref for TypeckRootCtxt<'tcx> { type Target = InferCtxt<'tcx>; fn deref(&self) -> &Self::Target { &self.infcx } } -impl<'tcx> Inherited<'tcx> { +impl<'tcx> TypeckRootCtxt<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; @@ -83,7 +85,7 @@ impl<'tcx> Inherited<'tcx> { .build(); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); - Inherited { + TypeckRootCtxt { typeck_results, fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(&infcx)), infcx, diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 751d6de83f9..c86970635a5 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -482,6 +482,8 @@ pub enum ResourceExhaustionInfo { MemoryExhausted, /// The address space (of the target) is full. AddressSpaceFull, + /// The compiler got an interrupt signal (a user ran out of patience). + Interrupted, } /// A trait for machine-specific errors (or other "machine stop" conditions). diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 3b1d1a04d6f..9cbc4d10146 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -9,8 +9,7 @@ use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirId, OwnerId}; -use rustc_query_system::query::DefIdCacheSelector; -use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector}; +use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi; @@ -22,7 +21,7 @@ pub struct LocalCrate; /// The `Key` trait controls what types can legally be used as the key /// for a query. pub trait Key: Sized { - // N.B. Most of the keys down below have `type CacheSelector = DefaultCacheSelector<Self>;`, + // N.B. Most of the keys down below have `type Cache<V> = DefaultCache<Self, V>;`, // it would be reasonable to use associated type defaults, to remove the duplication... // // ...But r-a doesn't support them yet and using a default here causes r-a to not infer @@ -30,7 +29,7 @@ pub trait Key: Sized { // type defaults, please restrain from using them here <3 // // r-a issue: <https://github.com/rust-lang/rust-analyzer/issues/13693> - type CacheSelector; + type Cache<V>; /// In the event that a cycle occurs, if no explicit span has been /// given for a query with key `self`, what span should we use? @@ -56,7 +55,7 @@ pub trait AsLocalKey: Key { } impl Key for () { - type CacheSelector = SingleCacheSelector; + type Cache<V> = SingleCache<V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -64,7 +63,7 @@ impl Key for () { } impl<'tcx> Key for ty::InstanceDef<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.def_id()) @@ -81,7 +80,7 @@ impl<'tcx> AsLocalKey for ty::InstanceDef<'tcx> { } impl<'tcx> Key for ty::Instance<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.def_id()) @@ -89,7 +88,7 @@ impl<'tcx> Key for ty::Instance<'tcx> { } impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.instance.default_span(tcx) @@ -97,7 +96,7 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { } impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -105,7 +104,7 @@ impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) { } impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP @@ -113,7 +112,7 @@ impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> { } impl Key for CrateNum { - type CacheSelector = VecCacheSelector<Self>; + type Cache<V> = VecCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -130,7 +129,7 @@ impl AsLocalKey for CrateNum { } impl Key for OwnerId { - type CacheSelector = VecCacheSelector<Self>; + type Cache<V> = VecCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.to_def_id().default_span(tcx) @@ -142,7 +141,7 @@ impl Key for OwnerId { } impl Key for LocalDefId { - type CacheSelector = VecCacheSelector<Self>; + type Cache<V> = VecCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.to_def_id().default_span(tcx) @@ -154,7 +153,7 @@ impl Key for LocalDefId { } impl Key for DefId { - type CacheSelector = DefIdCacheSelector; + type Cache<V> = DefIdCache<V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(*self) @@ -176,7 +175,7 @@ impl AsLocalKey for DefId { } impl Key for LocalModDefId { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(*self) @@ -189,7 +188,7 @@ impl Key for LocalModDefId { } impl Key for ModDefId { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(*self) @@ -211,7 +210,7 @@ impl AsLocalKey for ModDefId { } impl Key for SimplifiedType { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -219,7 +218,7 @@ impl Key for SimplifiedType { } impl Key for (DefId, DefId) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) @@ -227,7 +226,7 @@ impl Key for (DefId, DefId) { } impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -235,7 +234,7 @@ impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) { } impl Key for (DefId, LocalDefId) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) @@ -243,7 +242,7 @@ impl Key for (DefId, LocalDefId) { } impl Key for (LocalDefId, DefId) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -251,7 +250,7 @@ impl Key for (LocalDefId, DefId) { } impl Key for (LocalDefId, LocalDefId) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -259,7 +258,7 @@ impl Key for (LocalDefId, LocalDefId) { } impl Key for (DefId, Ident) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.0) @@ -272,7 +271,7 @@ impl Key for (DefId, Ident) { } impl Key for (LocalDefId, LocalDefId, Ident) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) @@ -280,7 +279,7 @@ impl Key for (LocalDefId, LocalDefId, Ident) { } impl Key for (CrateNum, DefId) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.1.default_span(tcx) @@ -297,7 +296,7 @@ impl AsLocalKey for (CrateNum, DefId) { } impl Key for (CrateNum, SimplifiedType) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -314,7 +313,7 @@ impl AsLocalKey for (CrateNum, SimplifiedType) { } impl Key for (DefId, SimplifiedType) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -322,7 +321,7 @@ impl Key for (DefId, SimplifiedType) { } impl<'tcx> Key for GenericArgsRef<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -330,7 +329,7 @@ impl<'tcx> Key for GenericArgsRef<'tcx> { } impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -338,7 +337,7 @@ impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) { } impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { (self.0).def.default_span(tcx) @@ -346,7 +345,7 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) { } impl<'tcx> Key for (LocalDefId, DefId, GenericArgsRef<'tcx>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -354,7 +353,7 @@ impl<'tcx> Key for (LocalDefId, DefId, GenericArgsRef<'tcx>) { } impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.1.def_id) @@ -362,7 +361,7 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) { } impl<'tcx> Key for ty::PolyTraitRef<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.def_id()) @@ -370,7 +369,7 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> { } impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.def_id()) @@ -378,7 +377,7 @@ impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> { } impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.def_span(self.0.def_id()) @@ -386,7 +385,7 @@ impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) { } impl<'tcx> Key for GenericArg<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -394,7 +393,7 @@ impl<'tcx> Key for GenericArg<'tcx> { } impl<'tcx> Key for ty::Const<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -402,7 +401,7 @@ impl<'tcx> Key for ty::Const<'tcx> { } impl<'tcx> Key for Ty<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -418,7 +417,7 @@ impl<'tcx> Key for Ty<'tcx> { } impl<'tcx> Key for TyAndLayout<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -426,7 +425,7 @@ impl<'tcx> Key for TyAndLayout<'tcx> { } impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -434,7 +433,7 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) { } impl<'tcx> Key for &'tcx ty::List<ty::Clause<'tcx>> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -442,7 +441,7 @@ impl<'tcx> Key for &'tcx ty::List<ty::Clause<'tcx>> { } impl<'tcx> Key for ty::ParamEnv<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -450,7 +449,7 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> { } impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.value.default_span(tcx) @@ -462,7 +461,7 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { } impl Key for Symbol { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP @@ -470,7 +469,7 @@ impl Key for Symbol { } impl Key for Option<Symbol> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP @@ -480,7 +479,7 @@ impl Key for Option<Symbol> { /// Canonical query goals correspond to abstract trait operations that /// are not tied to any crate in particular. impl<'tcx, T: Clone> Key for Canonical<'tcx, T> { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP @@ -488,7 +487,7 @@ impl<'tcx, T: Clone> Key for Canonical<'tcx, T> { } impl Key for (Symbol, u32, u32) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP @@ -496,7 +495,7 @@ impl Key for (Symbol, u32, u32) { } impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP @@ -504,7 +503,7 @@ impl<'tcx> Key for (DefId, Ty<'tcx>, GenericArgsRef<'tcx>, ty::ParamEnv<'tcx>) { } impl<'tcx> Key for (Ty<'tcx>, abi::VariantIdx) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP @@ -512,7 +511,7 @@ impl<'tcx> Key for (Ty<'tcx>, abi::VariantIdx) { } impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP @@ -520,7 +519,7 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) { } impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -528,7 +527,7 @@ impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) { } impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { self.0.default_span(tcx) @@ -536,7 +535,7 @@ impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) { } impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { DUMMY_SP @@ -544,7 +543,7 @@ impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) { } impl Key for HirId { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.hir().span(*self) @@ -557,7 +556,7 @@ impl Key for HirId { } impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) { - type CacheSelector = DefaultCacheSelector<Self>; + type Cache<V> = DefaultCache<Self, V>; // Just forward to `Ty<'tcx>` diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 38cfd11a016..5e4454db3e2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -73,7 +73,7 @@ use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate}; use rustc_index::IndexVec; use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::{try_get_cached, CacheSelector, QueryCache, QueryMode, QueryState}; +use rustc_query_system::query::{try_get_cached, QueryCache, QueryMode, QueryState}; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::cstore::{CrateDepKind, CrateSource}; use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib}; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 8d88488e167..e3588a7afdc 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -336,9 +336,7 @@ macro_rules! define_callbacks { )) } - pub type Storage<'tcx> = < - <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>> - >::Cache; + pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache<Erase<$V>>; // Ensure that keys grow no larger than 64 bytes #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 65574f5702b..4fec5653a79 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -335,7 +335,7 @@ impl<'tcx> InstanceDef<'tcx> { fn fmt_instance( f: &mut fmt::Formatter<'_>, - instance: &Instance<'_>, + instance: Instance<'_>, type_length: Option<rustc_session::Limit>, ) -> fmt::Result { ty::tls::with(|tcx| { @@ -369,9 +369,9 @@ fn fmt_instance( } } -pub struct ShortInstance<'a, 'tcx>(pub &'a Instance<'tcx>, pub usize); +pub struct ShortInstance<'tcx>(pub Instance<'tcx>, pub usize); -impl<'a, 'tcx> fmt::Display for ShortInstance<'a, 'tcx> { +impl<'tcx> fmt::Display for ShortInstance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt_instance(f, self.0, Some(rustc_session::Limit(self.1))) } @@ -379,7 +379,7 @@ impl<'a, 'tcx> fmt::Display for ShortInstance<'a, 'tcx> { impl<'tcx> fmt::Display for Instance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt_instance(f, self, None) + fmt_instance(f, *self, None) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3f0a3a1a7bf..914b19efc7e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -804,7 +804,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } ty::Str => p!("str"), ty::Coroutine(did, args) => { - p!(write("{{")); + p!("{{"); let coroutine_kind = self.tcx().coroutine_kind(did).unwrap(); let should_print_movability = self.should_print_verbose() || matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_)); @@ -818,9 +818,17 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { if !self.should_print_verbose() { p!(write("{}", coroutine_kind)); - // FIXME(eddyb) should use `def_span`. - if let Some(did) = did.as_local() { - let span = self.tcx().def_span(did); + if coroutine_kind.is_fn_like() { + // If we are printing an `async fn` coroutine type, then give the path + // of the fn, instead of its span, because that will in most cases be + // more helpful for the reader than just a source location. + // + // This will look like: + // {async fn body of some_fn()} + let did_of_the_fn_item = self.tcx().parent(did); + p!(" of ", print_def_path(did_of_the_fn_item, args), "()"); + } else if let Some(local_did) = did.as_local() { + let span = self.tcx().def_span(local_did); p!(write( "@{}", // This may end up in stderr diagnostics but it may also be emitted @@ -828,7 +836,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { self.tcx().sess.source_map().span_to_embeddable_string(span) )); } else { - p!(write("@"), print_def_path(did, args)); + p!("@", print_def_path(did, args)); } } else { p!(print_def_path(did, args)); diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index d8541f4b25a..827b7e088ce 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -430,6 +430,31 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments } } + /// Does the pattern recursively contain a `ref mut` binding in it? + /// + /// This is used to determined whether a `deref` pattern should emit a `Deref` + /// or `DerefMut` call for its pattern scrutinee. + /// + /// This is computed from the typeck results since we want to make + /// sure to apply any match-ergonomics adjustments, which we cannot + /// determine from the HIR alone. + pub fn pat_has_ref_mut_binding(&self, pat: &'tcx hir::Pat<'tcx>) -> bool { + let mut has_ref_mut = false; + pat.walk(|pat| { + if let hir::PatKind::Binding(_, id, _, _) = pat.kind + && let Some(ty::BindByReference(ty::Mutability::Mut)) = + self.pat_binding_modes().get(id) + { + has_ref_mut = true; + // No need to continue recursing + false + } else { + true + } + }); + has_ref_mut + } + /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured /// by the closure. pub fn closure_min_captures_flattened( diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 6b7ab892a96..6d083e66a9b 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1006,6 +1006,10 @@ struct Candidate<'pat, 'tcx> { /// If the candidate matches, bindings and ascriptions must be established. extra_data: PatternExtraData<'tcx>, + /// If we filled `self.subcandidate`, we store here the span of the or-pattern they came from. + // Invariant: it is `None` iff `subcandidates.is_empty()`. + or_span: Option<Span>, + /// The block before the `bindings` have been established. pre_binding_block: Option<BasicBlock>, /// The pre-binding block of the next candidate. @@ -1028,6 +1032,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> { extra_data: flat_pat.extra_data, has_guard, subcandidates: Vec::new(), + or_span: None, otherwise_block: None, pre_binding_block: None, next_candidate_pre_binding_block: None, @@ -1280,7 +1285,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // // only generates a single switch. candidate.subcandidates = self.create_or_subcandidates(pats, candidate.has_guard); - candidate.match_pairs.pop(); + let first_match_pair = candidate.match_pairs.pop().unwrap(); + candidate.or_span = Some(first_match_pair.pattern.span); split_or_candidate = true; } } @@ -1290,8 +1296,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // At least one of the candidates has been split into subcandidates. // We need to change the candidate list to include those. let mut new_candidates = Vec::new(); - - for candidate in candidates { + for candidate in candidates.iter_mut() { candidate.visit_leaves(|leaf_candidate| new_candidates.push(leaf_candidate)); } self.match_simplified_candidates( @@ -1301,6 +1306,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { otherwise_block, &mut *new_candidates, ); + + for candidate in candidates { + self.merge_trivial_subcandidates(candidate); + } } else { self.match_simplified_candidates( span, @@ -1534,16 +1543,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut or_candidate_refs, ); candidate.subcandidates = or_candidates; - self.merge_trivial_subcandidates(candidate, self.source_info(or_span)); + candidate.or_span = Some(or_span); + self.merge_trivial_subcandidates(candidate); } /// Try to merge all of the subcandidates of the given candidate into one. /// This avoids exponentially large CFGs in cases like `(1 | 2, 3 | 4, ...)`. - fn merge_trivial_subcandidates( - &mut self, - candidate: &mut Candidate<'_, 'tcx>, - source_info: SourceInfo, - ) { + fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) { if candidate.subcandidates.is_empty() || candidate.has_guard { // FIXME(or_patterns; matthewjasper) Don't give up if we have a guard. return; @@ -1553,7 +1559,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Not `Iterator::all` because we don't want to short-circuit. for subcandidate in &mut candidate.subcandidates { - self.merge_trivial_subcandidates(subcandidate, source_info); + self.merge_trivial_subcandidates(subcandidate); // FIXME(or_patterns; matthewjasper) Try to be more aggressive here. can_merge &= @@ -1562,6 +1568,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if can_merge { let any_matches = self.cfg.start_new_block(); + let or_span = candidate.or_span.take().unwrap(); + let source_info = self.source_info(or_span); for subcandidate in mem::take(&mut candidate.subcandidates) { let or_block = subcandidate.pre_binding_block.unwrap(); self.cfg.goto(or_block, source_info, any_matches); diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 97b94a0b362..bf1906f370b 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -82,7 +82,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &*candidate.match_pairs { candidate.subcandidates = self.create_or_subcandidates(pats, has_guard); - candidate.match_pairs.pop(); + let first_match_pair = candidate.match_pairs.pop().unwrap(); + candidate.or_span = Some(first_match_pair.pattern.span); } candidate }) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 78c0615b165..5f74841151c 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -165,7 +165,7 @@ impl<'tcx> Inliner<'tcx> { caller_body: &mut Body<'tcx>, callsite: &CallSite<'tcx>, ) -> Result<std::ops::Range<BasicBlock>, &'static str> { - self.check_mir_is_available(caller_body, &callsite.callee)?; + self.check_mir_is_available(caller_body, callsite.callee)?; let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id()); let cross_crate_inlinable = self.tcx.cross_crate_inlinable(callsite.callee.def_id()); @@ -298,7 +298,7 @@ impl<'tcx> Inliner<'tcx> { fn check_mir_is_available( &self, caller_body: &Body<'tcx>, - callee: &Instance<'tcx>, + callee: Instance<'tcx>, ) -> Result<(), &'static str> { let caller_def_id = caller_body.source.def_id(); let callee_def_id = callee.def_id(); @@ -354,7 +354,7 @@ impl<'tcx> Inliner<'tcx> { // If we know for sure that the function we're calling will itself try to // call us, then we avoid inlining that function. - if self.tcx.mir_callgraph_reachable((*callee, caller_def_id.expect_local())) { + if self.tcx.mir_callgraph_reachable((callee, caller_def_id.expect_local())) { return Err("caller might be reachable from callee (query cycle avoidance)"); } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 94a95428ab0..b60ee7649b2 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1015,8 +1015,8 @@ fn build_construct_coroutine_by_move_shim<'tcx>( bug!(); }; - // We use `*mut Self` here because we only need to emit an ABI-compatible shim body, - // rather than match the signature exactly. + // We use `&mut Self` here because we only need to emit an ABI-compatible shim body, + // rather than match the signature exactly (which might take `&self` instead). // // The self type here is a coroutine-closure, not a coroutine, and we never read from // it because it never has any captures, because this is only true in the Fn/FnMut @@ -1025,7 +1025,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>( if receiver_by_ref { // Triple-check that there's no captures here. assert_eq!(args.as_coroutine_closure().tupled_upvars_ty(), tcx.types.unit); - self_ty = Ty::new_mut_ptr(tcx, self_ty); + self_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, self_ty); } let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| { diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 35a052166bd..c746041ebd8 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -19,6 +19,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); 'blocks: for block in body.basic_blocks_mut() { for stmt in block.statements.iter_mut() { + // Simplify `assume` of a known value: either a NOP or unreachable. if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind && let NonDivergingIntrinsic::Assume(discr) = intrinsic && let Operand::Constant(ref c) = discr diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index a51b1c34a1a..3285cbd0432 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -397,7 +397,7 @@ fn collect_items_rec<'tcx>( let instance = Instance::mono(tcx, def_id); // Sanity check whether this ended up being collected accidentally - debug_assert!(should_codegen_locally(tcx, &instance)); + debug_assert!(should_codegen_locally(tcx, instance)); let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() }; // Nested statics have no type. @@ -429,7 +429,7 @@ fn collect_items_rec<'tcx>( } MonoItem::Fn(instance) => { // Sanity check whether this ended up being collected accidentally - debug_assert!(should_codegen_locally(tcx, &instance)); + debug_assert!(should_codegen_locally(tcx, instance)); // Keep track of the monomorphization recursion depth recursion_depth_reset = Some(check_recursion_limit( @@ -474,7 +474,7 @@ fn collect_items_rec<'tcx>( } hir::InlineAsmOperand::SymStatic { path: _, def_id } => { let instance = Instance::mono(tcx, *def_id); - if should_codegen_locally(tcx, &instance) { + if should_codegen_locally(tcx, instance) { trace!("collecting static {:?}", def_id); used_items.push(dummy_spanned(MonoItem::Static(*def_id))); } @@ -557,7 +557,7 @@ fn collect_items_rec<'tcx>( /// If the type name is longer than before+after, it will be written to a file. fn shrunk_instance_name<'tcx>( tcx: TyCtxt<'tcx>, - instance: &Instance<'tcx>, + instance: Instance<'tcx>, ) -> (String, Option<PathBuf>) { let s = instance.to_string(); @@ -603,7 +603,7 @@ fn check_recursion_limit<'tcx>( if !recursion_limit.value_within_limit(adjusted_recursion_depth) { let def_span = tcx.def_span(def_id); let def_path_str = tcx.def_path_str(def_id); - let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance); + let (shrunk, written_to_path) = shrunk_instance_name(tcx, instance); let mut path = PathBuf::new(); let was_written = if let Some(written_to_path) = written_to_path { path = written_to_path; @@ -645,7 +645,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { // // Bail out in these cases to avoid that bad user experience. if !tcx.type_length_limit().value_within_limit(type_length) { - let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance); + let (shrunk, written_to_path) = shrunk_instance_name(tcx, instance); let span = tcx.def_span(instance.def_id()); let mut path = PathBuf::new(); let was_written = if let Some(path2) = written_to_path { @@ -892,7 +892,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { if let ty::Closure(def_id, args) = *source_ty.kind() { let instance = Instance::resolve_closure(self.tcx, def_id, args, ty::ClosureKind::FnOnce); - if should_codegen_locally(self.tcx, &instance) { + if should_codegen_locally(self.tcx, instance) { self.used_items.push(create_fn_mono_item(self.tcx, instance, span)); } } else { @@ -902,7 +902,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { mir::Rvalue::ThreadLocalRef(def_id) => { assert!(self.tcx.is_thread_local_static(def_id)); let instance = Instance::mono(self.tcx, def_id); - if should_codegen_locally(self.tcx, &instance) { + if should_codegen_locally(self.tcx, instance) { trace!("collecting thread-local static {:?}", def_id); self.used_items.push(respan(span, MonoItem::Static(def_id))); } @@ -929,7 +929,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { let tcx = self.tcx; let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| { let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source))); - if should_codegen_locally(tcx, &instance) { + if should_codegen_locally(tcx, instance) { this.used_items.push(create_fn_mono_item(tcx, instance, source)); } }; @@ -962,7 +962,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { } mir::InlineAsmOperand::SymStatic { def_id } => { let instance = Instance::mono(self.tcx, def_id); - if should_codegen_locally(self.tcx, &instance) { + if should_codegen_locally(self.tcx, instance) { trace!("collecting asm sym static {:?}", def_id); self.used_items.push(respan(source, MonoItem::Static(def_id))); } @@ -1051,7 +1051,7 @@ fn visit_instance_use<'tcx>( output: &mut MonoItems<'tcx>, ) { debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call); - if !should_codegen_locally(tcx, &instance) { + if !should_codegen_locally(tcx, instance) { return; } if let ty::InstanceDef::Intrinsic(def_id) = instance.def { @@ -1063,13 +1063,13 @@ fn visit_instance_use<'tcx>( // codegen a call to that function without generating code for the function itself. let def_id = tcx.lang_items().get(LangItem::PanicNounwind).unwrap(); let panic_instance = Instance::mono(tcx, def_id); - if should_codegen_locally(tcx, &panic_instance) { + if should_codegen_locally(tcx, panic_instance) { output.push(create_fn_mono_item(tcx, panic_instance, source)); } } else if tcx.has_attr(def_id, sym::rustc_intrinsic) { // Codegen the fallback body of intrinsics with fallback bodies let instance = ty::Instance::new(def_id, instance.args); - if should_codegen_locally(tcx, &instance) { + if should_codegen_locally(tcx, instance) { output.push(create_fn_mono_item(tcx, instance, source)); } } @@ -1107,7 +1107,7 @@ fn visit_instance_use<'tcx>( /// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we /// can just link to the upstream crate and therefore don't need a mono item. -pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool { +pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool { let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else { return true; }; @@ -1304,7 +1304,7 @@ fn create_mono_items_for_vtable_methods<'tcx>( None } VtblEntry::Method(instance) => { - Some(*instance).filter(|instance| should_codegen_locally(tcx, instance)) + Some(*instance).filter(|instance| should_codegen_locally(tcx, *instance)) } }) .map(|item| create_fn_mono_item(tcx, item, source)); @@ -1321,7 +1321,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt GlobalAlloc::Static(def_id) => { assert!(!tcx.is_thread_local_static(def_id)); let instance = Instance::mono(tcx, def_id); - if should_codegen_locally(tcx, &instance) { + if should_codegen_locally(tcx, instance) { trace!("collecting static {:?}", def_id); output.push(dummy_spanned(MonoItem::Static(def_id))); } @@ -1339,7 +1339,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt } } GlobalAlloc::Function(fn_instance) => { - if should_codegen_locally(tcx, &fn_instance) { + if should_codegen_locally(tcx, fn_instance) { trace!("collecting {:?} with {:#?}", alloc_id, fn_instance); output.push(create_fn_mono_item(tcx, fn_instance, DUMMY_SP)); } @@ -1474,7 +1474,7 @@ fn visit_mentioned_item<'tcx>( if let ty::Closure(def_id, args) = *source_ty.kind() { let instance = Instance::resolve_closure(tcx, def_id, args, ty::ClosureKind::FnOnce); - if should_codegen_locally(tcx, &instance) { + if should_codegen_locally(tcx, instance) { output.push(create_fn_mono_item(tcx, instance, span)); } } else { @@ -1736,7 +1736,7 @@ fn create_mono_items_for_default_impls<'tcx>( let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args); let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP); - if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance) { + if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, instance) { output.push(mono_item); } } diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 4ec842e8f85..9c4a6e69a3c 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -64,7 +64,7 @@ pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>( !instance.def_id().is_local() && tcx.is_compiler_builtins(LOCAL_CRATE) && tcx.codegen_fn_attrs(instance.def_id()).link_name.is_none() - && !should_codegen_locally(tcx, &instance) + && !should_codegen_locally(tcx, instance) } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index aa735f3de1f..8957d7d1bd3 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -14,10 +14,6 @@ parse_array_index_offset_of = array indexing not supported in offset_of parse_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed -parse_assoc_lifetime = associated lifetimes are not supported - .label = the lifetime is given here - .help = if you meant to specify a trait object, write `dyn Trait + 'lifetime` - parse_associated_static_item_not_allowed = associated `static` items are not allowed parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later @@ -445,6 +441,12 @@ parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated wit .suggestion = remove the lifetime annotation .label = annotated with lifetime here +parse_lifetime_in_eq_constraint = lifetimes are not permitted in this context + .label = lifetime is not allowed here + .context_label = this introduces an associated item binding + .help = if you meant to specify a trait object, write `dyn /* Trait */ + {$lifetime}` + .colon_sugg = you might have meant to write a bound here + parse_lone_slash = invalid trailing slash in literal .label = {parse_lone_slash} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 20ebfc6691b..a6eedabf689 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2631,13 +2631,22 @@ pub(crate) struct GenericsInPath { } #[derive(Diagnostic)] -#[diag(parse_assoc_lifetime)] +#[diag(parse_lifetime_in_eq_constraint)] #[help] -pub(crate) struct AssocLifetime { +pub(crate) struct LifetimeInEqConstraint { #[primary_span] - pub span: Span, #[label] - pub lifetime: Span, + pub span: Span, + pub lifetime: Ident, + #[label(parse_context_label)] + pub binding_label: Span, + #[suggestion( + parse_colon_sugg, + style = "verbose", + applicability = "maybe-incorrect", + code = ": " + )] + pub colon_sugg: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 9153f2b9d06..608cdd945ff 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -718,7 +718,11 @@ impl<'a> Parser<'a> { let bounds = self.parse_generic_bounds()?; AssocConstraintKind::Bound { bounds } } else if self.eat(&token::Eq) { - self.parse_assoc_equality_term(ident, self.prev_token.span)? + self.parse_assoc_equality_term( + ident, + gen_args.as_ref(), + self.prev_token.span, + )? } else { unreachable!(); }; @@ -753,11 +757,13 @@ impl<'a> Parser<'a> { } /// Parse the term to the right of an associated item equality constraint. - /// That is, parse `<term>` in `Item = <term>`. - /// Right now, this only admits types in `<term>`. + /// + /// That is, parse `$term` in `Item = $term` where `$term` is a type or + /// a const expression (wrapped in curly braces if complex). fn parse_assoc_equality_term( &mut self, ident: Ident, + gen_args: Option<&GenericArgs>, eq: Span, ) -> PResult<'a, AssocConstraintKind> { let arg = self.parse_generic_arg(None)?; @@ -769,9 +775,15 @@ impl<'a> Parser<'a> { c.into() } Some(GenericArg::Lifetime(lt)) => { - let guar = - self.dcx().emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span }); - self.mk_ty(span, ast::TyKind::Err(guar)).into() + let guar = self.dcx().emit_err(errors::LifetimeInEqConstraint { + span: lt.ident.span, + lifetime: lt.ident, + binding_label: span, + colon_sugg: gen_args + .map_or(ident.span, |args| args.span()) + .between(lt.ident.span), + }); + self.mk_ty(lt.ident.span, ast::TyKind::Err(guar)).into() } None => { let after_eq = eq.shrink_to_hi(); diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index c2e604b02b3..90f2bab65b1 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -1,9 +1,14 @@ -// Finds items that are externally reachable, to determine which items -// need to have their metadata (and possibly their AST) serialized. -// All items that can be referred to through an exported name are -// reachable, and when a reachable thing is inline or generic, it -// makes all other generics or inline functions that it references -// reachable as well. +//! Finds local items that are externally reachable, which means that other crates need access to +//! their compiled machine code or their MIR. +//! +//! An item is "externally reachable" if it is relevant for other crates. This obviously includes +//! all public items. However, some of these items cannot be compiled to machine code (because they +//! are generic), and for some the machine code is not sufficient (because we want to cross-crate +//! inline them). These items "need cross-crate MIR". When a reachable function `f` needs +//! cross-crate MIR, then all the functions it calls also become reachable, as they will be +//! necessary to use the MIR of `f` from another crate. Furthermore, an item can become "externally +//! reachable" by having a `const`/`const fn` return a pointer to that item, so we also need to +//! recurse into reachable `const`/`const fn`. use hir::def_id::LocalDefIdSet; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -21,7 +26,9 @@ use rustc_privacy::DefIdVisitor; use rustc_session::config::CrateType; use rustc_target::spec::abi::Abi; -fn item_might_be_inlined(tcx: TyCtxt<'_>, def_id: DefId) -> bool { +/// Determines whether this item is recursive for reachability. See `is_recursively_reachable_local` +/// below for details. +fn recursively_reachable(tcx: TyCtxt<'_>, def_id: DefId) -> bool { tcx.generics_of(def_id).requires_monomorphization(tcx) || tcx.cross_crate_inlinable(def_id) || tcx.is_const_fn(def_id) @@ -54,12 +61,20 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { let res = match expr.kind { hir::ExprKind::Path(ref qpath) => { + // This covers fn ptr casts but also "non-method" calls. Some(self.typeck_results().qpath_res(qpath, expr.hir_id)) } - hir::ExprKind::MethodCall(..) => self - .typeck_results() - .type_dependent_def(expr.hir_id) - .map(|(kind, def_id)| Res::Def(kind, def_id)), + hir::ExprKind::MethodCall(..) => { + // Method calls don't involve a full "path", so we need to determine the callee + // based on the receiver type. + // If this is a method call on a generic type, we might not be able to find the + // callee. That's why `reachable_set` also adds all potential callees for such + // calls, i.e. all trait impl items, to the reachable set. So here we only worry + // about the calls we can identify. + self.typeck_results() + .type_dependent_def(expr.hir_id) + .map(|(kind, def_id)| Res::Def(kind, def_id)) + } hir::ExprKind::Closure(&hir::Closure { def_id, .. }) => { self.reachable_symbols.insert(def_id); None @@ -96,16 +111,24 @@ impl<'tcx> ReachableContext<'tcx> { .expect("`ReachableContext::typeck_results` called outside of body") } - // Returns true if the given def ID represents a local item that is - // eligible for inlining and false otherwise. - fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool { + /// Returns true if the given def ID represents a local item that is recursive for reachability, + /// i.e. whether everything mentioned in here also needs to be considered reachable. + /// + /// There are two reasons why an item may be recursively reachable: + /// - It needs cross-crate MIR (see the module-level doc comment above). + /// - It is a `const` or `const fn`. This is *not* because we need the MIR to interpret them + /// (MIR for const-eval and MIR for codegen is separate, and MIR for const-eval is always + /// encoded). Instead, it is because `const fn` can create `fn()` pointers to other items + /// which end up in the evaluated result of the constant and can then be called from other + /// crates. Those items must be considered reachable. + fn is_recursively_reachable_local(&self, def_id: DefId) -> bool { let Some(def_id) = def_id.as_local() else { return false; }; match self.tcx.hir_node_by_def_id(def_id) { Node::Item(item) => match item.kind { - hir::ItemKind::Fn(..) => item_might_be_inlined(self.tcx, def_id.into()), + hir::ItemKind::Fn(..) => recursively_reachable(self.tcx, def_id.into()), _ => false, }, Node::TraitItem(trait_method) => match trait_method.kind { @@ -117,7 +140,7 @@ impl<'tcx> ReachableContext<'tcx> { Node::ImplItem(impl_item) => match impl_item.kind { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Fn(..) => { - item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) + recursively_reachable(self.tcx, impl_item.hir_id().owner.to_def_id()) } hir::ImplItemKind::Type(_) => false, }, @@ -174,7 +197,7 @@ impl<'tcx> ReachableContext<'tcx> { Node::Item(item) => { match item.kind { hir::ItemKind::Fn(.., body) => { - if item_might_be_inlined(self.tcx, item.owner_id.into()) { + if recursively_reachable(self.tcx, item.owner_id.into()) { self.visit_nested_body(body); } } @@ -228,7 +251,7 @@ impl<'tcx> ReachableContext<'tcx> { self.visit_nested_body(body); } hir::ImplItemKind::Fn(_, body) => { - if item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) { + if recursively_reachable(self.tcx, impl_item.hir_id().owner.to_def_id()) { self.visit_nested_body(body) } } @@ -316,7 +339,7 @@ impl<'tcx> ReachableContext<'tcx> { self.worklist.push(def_id); } _ => { - if self.def_id_represents_local_inlined_item(def_id.to_def_id()) { + if self.is_recursively_reachable_local(def_id.to_def_id()) { self.worklist.push(def_id); } else { self.reachable_symbols.insert(def_id); @@ -394,6 +417,7 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) } +/// See module-level doc comment above. fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet { let effective_visibilities = &tcx.effective_visibilities(()); @@ -427,14 +451,16 @@ fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet { } } { - // Some methods from non-exported (completely private) trait impls still have to be - // reachable if they are called from inlinable code. Generally, it's not known until - // monomorphization if a specific trait impl item can be reachable or not. So, we - // conservatively mark all of them as reachable. + // As explained above, we have to mark all functions called from reachable + // `item_might_be_inlined` items as reachable. The issue is, when those functions are + // generic and call a trait method, we have no idea where that call goes! So, we + // conservatively mark all trait impl items as reachable. // FIXME: One possible strategy for pruning the reachable set is to avoid marking impl // items of non-exported traits (or maybe all local traits?) unless their respective // trait items are used from inlinable code through method call syntax or UFCS, or their // trait is a lang item. + // (But if you implement this, don't forget to take into account that vtables can also + // make trait methods reachable!) let crate_items = tcx.hir_crate_items(()); for id in crate_items.free_items() { diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 674a0984ae9..c3fc036aed3 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -9,13 +9,6 @@ use rustc_span::def_id::DefId; use rustc_span::def_id::DefIndex; use std::fmt::Debug; use std::hash::Hash; -use std::marker::PhantomData; - -pub trait CacheSelector<'tcx, V> { - type Cache - where - V: Copy; -} pub trait QueryCache: Sized { type Key: Hash + Eq + Copy + Debug; @@ -29,14 +22,6 @@ pub trait QueryCache: Sized { fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)); } -pub struct DefaultCacheSelector<K>(PhantomData<K>); - -impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<'tcx, V> for DefaultCacheSelector<K> { - type Cache = DefaultCache<K, V> - where - V: Copy; -} - pub struct DefaultCache<K, V> { cache: Sharded<FxHashMap<K, (V, DepNodeIndex)>>, } @@ -81,14 +66,6 @@ where } } -pub struct SingleCacheSelector; - -impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for SingleCacheSelector { - type Cache = SingleCache<V> - where - V: Copy; -} - pub struct SingleCache<V> { cache: OnceLock<(V, DepNodeIndex)>, } @@ -123,14 +100,6 @@ where } } -pub struct VecCacheSelector<K>(PhantomData<K>); - -impl<'tcx, K: Idx, V: 'tcx> CacheSelector<'tcx, V> for VecCacheSelector<K> { - type Cache = VecCache<K, V> - where - V: Copy; -} - pub struct VecCache<K: Idx, V> { cache: Sharded<IndexVec<K, Option<(V, DepNodeIndex)>>>, } @@ -174,14 +143,6 @@ where } } -pub struct DefIdCacheSelector; - -impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for DefIdCacheSelector { - type Cache = DefIdCache<V> - where - V: Copy; -} - pub struct DefIdCache<V> { /// Stores the local DefIds in a dense map. Local queries are much more often dense, so this is /// a win over hashing query keys at marginal memory cost (~5% at most) compared to FxHashMap. diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 01b9d458f1e..91a0026f281 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -9,10 +9,7 @@ pub use self::job::{ }; mod caches; -pub use self::caches::{ - CacheSelector, DefIdCacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector, - VecCacheSelector, -}; +pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache}; mod config; pub use self::config::{HashResult, QueryConfig}; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 9bf3e9ccabd..48711f43518 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -19,6 +19,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::intern::Interned; use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan}; use rustc_hir::def::{self, DefKind, PartialRes}; +use rustc_hir::def_id::DefId; use rustc_middle::metadata::ModChild; use rustc_middle::metadata::Reexport; use rustc_middle::span_bug; @@ -250,6 +251,9 @@ struct UnresolvedImportError { note: Option<String>, suggestion: Option<Suggestion>, candidates: Option<Vec<ImportSuggestion>>, + segment: Option<Symbol>, + /// comes from `PathRes::Failed { module }` + module: Option<DefId>, } // Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;` @@ -579,16 +583,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &import.kind, import.span, ); - let err = UnresolvedImportError { - span: import.span, - label: None, - note: None, - suggestion: None, - candidates: None, - }; // FIXME: there should be a better way of doing this than // formatting this as a string then checking for `::` if path.contains("::") { + let err = UnresolvedImportError { + span: import.span, + label: None, + note: None, + suggestion: None, + candidates: None, + segment: None, + module: None, + }; errors.push((*import, err)) } } @@ -738,15 +744,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - match &import.kind { - ImportKind::Single { source, .. } => { - if let Some(ModuleOrUniformRoot::Module(module)) = import.imported_module.get() - && let Some(module) = module.opt_def_id() - { - self.find_cfg_stripped(&mut diag, &source.name, module) - } - } - _ => {} + if matches!(import.kind, ImportKind::Single { .. }) + && let Some(segment) = err.segment + && let Some(module) = err.module + { + self.find_cfg_stripped(&mut diag, &segment, module) } } @@ -916,10 +918,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span, label, suggestion, + module, + segment_name, .. } => { if no_ambiguity { assert!(import.imported_module.get().is_none()); + let module = if let Some(ModuleOrUniformRoot::Module(m)) = module { + m.opt_def_id() + } else { + None + }; let err = match self.make_path_suggestion( span, import.module_path.clone(), @@ -935,6 +944,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Applicability::MaybeIncorrect, )), candidates: None, + segment: Some(segment_name), + module, }, None => UnresolvedImportError { span, @@ -942,6 +953,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { note: None, suggestion, candidates: None, + segment: Some(segment_name), + module, }, }; return Some(err); @@ -990,6 +1003,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { note: None, suggestion: None, candidates: None, + segment: None, + module: None, }); } } @@ -1199,6 +1214,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } else { None }, + module: import.imported_module.get().and_then(|module| { + if let ModuleOrUniformRoot::Module(m) = module { + m.opt_def_id() + } else { + None + } + }), + segment: Some(ident.name), }) } else { // `resolve_ident_in_module` reported a privacy error. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index b2b339d2521..49b4a6efd3c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2531,7 +2531,17 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } ItemKind::Delegation(ref delegation) => { - self.resolve_delegation(delegation); + let span = delegation.path.segments.last().unwrap().ident.span; + self.with_generic_param_rib( + &[], + RibKind::Item(HasGenericParams::Yes(span), def_kind), + LifetimeRibKind::Generics { + binder: item.id, + kind: LifetimeBinderKind::Function, + span, + }, + |this| this.resolve_delegation(delegation), + ); } ItemKind::ExternCrate(..) => {} @@ -2819,7 +2829,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); } AssocItemKind::Delegation(delegation) => { - self.resolve_delegation(delegation); + self.with_generic_param_rib( + &[], + RibKind::AssocItem, + LifetimeRibKind::Generics { + binder: item.id, + kind: LifetimeBinderKind::Function, + span: delegation.path.segments.last().unwrap().ident.span, + }, + |this| this.resolve_delegation(delegation), + ); } AssocItemKind::Type(box TyAlias { generics, .. }) => self .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { @@ -3069,16 +3088,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } AssocItemKind::Delegation(box delegation) => { debug!("resolve_implementation AssocItemKind::Delegation"); - self.check_trait_item( - item.id, - item.ident, - &item.kind, - ValueNS, - item.span, - seen_trait_items, - |i, s, c| MethodNotMemberOfTrait(i, s, c), + self.with_generic_param_rib( + &[], + RibKind::AssocItem, + LifetimeRibKind::Generics { + binder: item.id, + kind: LifetimeBinderKind::Function, + span: delegation.path.segments.last().unwrap().ident.span, + }, + |this| { + this.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + seen_trait_items, + |i, s, c| MethodNotMemberOfTrait(i, s, c), + ); + + this.resolve_delegation(delegation) + }, ); - self.resolve_delegation(delegation); } AssocItemKind::MacCall(_) => { panic!("unexpanded macro in resolve!") diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index dfc2d029d4c..aa03adb7097 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -415,6 +415,19 @@ enum PathResult<'a> { label: String, suggestion: Option<Suggestion>, is_error_from_last_segment: bool, + /// The final module being resolved, for instance: + /// + /// ```compile_fail + /// mod a { + /// mod b { + /// mod c {} + /// } + /// } + /// + /// use a::not_exist::c; + /// ``` + /// + /// In this case, `module` will point to `a`. module: Option<ModuleOrUniformRoot<'a>>, /// The segment name of target segment_name: Symbol, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 73fcd2a76df..891ddb7af5b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -674,6 +674,7 @@ symbols! { deref_mut, deref_mut_method, deref_patterns, + deref_pure, deref_target, derive, derive_const, diff --git a/compiler/rustc_symbol_mangling/src/typeid.rs b/compiler/rustc_symbol_mangling/src/typeid.rs index 3bf564a4a16..1d28d2b732f 100644 --- a/compiler/rustc_symbol_mangling/src/typeid.rs +++ b/compiler/rustc_symbol_mangling/src/typeid.rs @@ -33,10 +33,10 @@ pub fn typeid_for_fnabi<'tcx>( /// Returns a type metadata identifier for the specified Instance. pub fn typeid_for_instance<'tcx>( tcx: TyCtxt<'tcx>, - instance: &Instance<'tcx>, + instance: Instance<'tcx>, options: TypeIdOptions, ) -> String { - typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options) + typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options) } /// Returns a KCFI type metadata identifier for the specified FnAbi. @@ -55,12 +55,12 @@ pub fn kcfi_typeid_for_fnabi<'tcx>( /// Returns a KCFI type metadata identifier for the specified Instance. pub fn kcfi_typeid_for_instance<'tcx>( tcx: TyCtxt<'tcx>, - instance: &Instance<'tcx>, + instance: Instance<'tcx>, options: TypeIdOptions, ) -> u32 { // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the // xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.) let mut hash: XxHash64 = Default::default(); - hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options).as_bytes()); + hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options).as_bytes()); hash.finish() as u32 } diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 3101015281b..1c6a0f9cf4d 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -1124,7 +1124,10 @@ pub fn typeid_for_instance<'tcx>( .trait_item_def_id .expect("Part of a trait implementation, but not linked to the def_id?"); let trait_method = tcx.associated_item(method_id); - if traits::is_vtable_safe_method(tcx, trait_ref.skip_binder().def_id, trait_method) { + let trait_id = trait_ref.skip_binder().def_id; + if traits::is_vtable_safe_method(tcx, trait_id, trait_method) + && tcx.object_safety_violations(trait_id).is_empty() + { // Trait methods will have a Self polymorphic parameter, where the concreteized // implementatation will not. We need to walk back to the more general trait method let trait_ref = tcx.instantiate_and_normalize_erasing_regions( @@ -1152,8 +1155,8 @@ pub fn typeid_for_instance<'tcx>( let fn_abi = tcx .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((instance, ty::List::empty()))) - .unwrap_or_else(|instance| { - bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance) + .unwrap_or_else(|error| { + bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}") }); typeid_for_fnabi(tcx, fn_abi, options) @@ -1182,6 +1185,7 @@ fn strip_receiver_auto<'tcx>( tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1)) } +#[instrument(skip(tcx), ret)] fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> { assert!(!poly_trait_ref.has_non_region_param()); let principal_pred = poly_trait_ref.map_bound(|trait_ref| { @@ -1199,6 +1203,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc ty::ParamEnv::reveal_all(), alias_ty.to_ty(tcx), ); + debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx)); ty::ExistentialPredicate::Projection(ty::ExistentialProjection { def_id: assoc_ty.def_id, args: ty::ExistentialTraitRef::erase_self_ty(tcx, super_trait_ref).args, diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index af1dfb6f7e9..65c3cf1a607 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -125,8 +125,12 @@ fn fn_sig_for_fn_abi<'tcx>( coroutine_kind = ty::ClosureKind::FnOnce; // Implementations of `FnMut` and `Fn` for coroutine-closures - // still take their receiver by ref. - if receiver_by_ref { Ty::new_mut_ptr(tcx, coroutine_ty) } else { coroutine_ty } + // still take their receiver by (mut) ref. + if receiver_by_ref { + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty) + } else { + coroutine_ty + } } else { tcx.closure_env_ty(coroutine_ty, coroutine_kind, env_region) }; diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index cfaf533088a..7c3fa2312e5 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -161,7 +161,7 @@ use core::marker::Unsize; use core::mem::{self, SizedTypeProperties}; use core::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce}; use core::ops::{ - CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DispatchFromDyn, Receiver, + CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver, }; use core::pin::Pin; use core::ptr::{self, addr_of_mut, NonNull, Unique}; @@ -1939,6 +1939,9 @@ impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> { } } +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<T: ?Sized, A: Allocator> DerefPure for Box<T, A> {} + #[unstable(feature = "receiver_trait", issue = "none")] impl<T: ?Sized, A: Allocator> Receiver for Box<T, A> {} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 02d155aaf12..ebc30c08910 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -122,6 +122,7 @@ #![feature(const_waker)] #![feature(core_intrinsics)] #![feature(deprecated_suggestion)] +#![feature(deref_pure_trait)] #![feature(dispatch_from_dyn)] #![feature(error_generic_member_access)] #![feature(error_in_core)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index facfc9d208e..569db54b137 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -260,7 +260,7 @@ use core::marker::{PhantomData, Unsize}; #[cfg(not(no_global_oom_handling))] use core::mem::size_of_val; use core::mem::{self, align_of_val_raw, forget, ManuallyDrop}; -use core::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver}; +use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; #[cfg(not(no_global_oom_handling))] use core::pin::Pin; @@ -2126,6 +2126,9 @@ impl<T: ?Sized, A: Allocator> Deref for Rc<T, A> { } } +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<T: ?Sized, A: Allocator> DerefPure for Rc<T, A> {} + #[unstable(feature = "receiver_trait", issue = "none")] impl<T: ?Sized> Receiver for Rc<T> {} diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index c4dcff1b1c4..7464df268cc 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -260,7 +260,7 @@ use crate::vec::Vec; /// # Representation /// /// A `String` is made up of three components: a pointer to some bytes, a -/// length, and a capacity. The pointer points to an internal buffer `String` +/// length, and a capacity. The pointer points to the internal buffer which `String` /// uses to store its data. The length is the number of bytes currently stored /// in the buffer, and the capacity is the size of the buffer in bytes. As such, /// the length will always be less than or equal to the capacity. @@ -2479,6 +2479,9 @@ impl ops::Deref for String { } } +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl ops::DerefPure for String {} + #[stable(feature = "derefmut_for_string", since = "1.3.0")] impl ops::DerefMut for String { #[inline] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 7e3e2fb38b1..4dea27221b7 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -21,7 +21,7 @@ use core::marker::{PhantomData, Unsize}; #[cfg(not(no_global_oom_handling))] use core::mem::size_of_val; use core::mem::{self, align_of_val_raw}; -use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; +use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -2107,6 +2107,9 @@ impl<T: ?Sized, A: Allocator> Deref for Arc<T, A> { } } +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<T: ?Sized, A: Allocator> DerefPure for Arc<T, A> {} + #[unstable(feature = "receiver_trait", issue = "none")] impl<T: ?Sized> Receiver for Arc<T> {} diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 94bed825bb2..3062f8664b7 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2772,6 +2772,9 @@ impl<T, A: Allocator> ops::DerefMut for Vec<T, A> { } } +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<T, A: Allocator> ops::DerefPure for Vec<T, A> {} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> { diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 3dc8c84e0bf..a02fcf50416 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -7,7 +7,8 @@ description = "The Rust Core Library" autotests = false autobenches = false # If you update this, be sure to update it in a bunch of other places too! -# As of 2022, it was the ci/pgo.sh script and the core-no-fp-fmt-parse test. +# As of 2024, it was src/tools/opt-dist, the core-no-fp-fmt-parse test and +# the version of the prelude imported in core/lib.rs. edition = "2021" [lib] diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index bdb6599abf5..bb668d2a673 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -1,5 +1,4 @@ use crate::cmp::BytewiseEq; -use crate::convert::TryInto; #[stable(feature = "rust1", since = "1.0.0")] impl<T, U, const N: usize> PartialEq<[U; N]> for [T; N] diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 8b5b48c59c2..2a447aafe72 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -6,7 +6,7 @@ use crate::borrow::{Borrow, BorrowMut}; use crate::cmp::Ordering; -use crate::convert::{Infallible, TryFrom}; +use crate::convert::Infallible; use crate::error::Error; use crate::fmt; use crate::hash::{self, Hash}; diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 8f612929110..f0c2636307f 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -1,7 +1,6 @@ //! Character conversions. use crate::char::TryFromCharError; -use crate::convert::TryFrom; use crate::error::Error; use crate::fmt; use crate::mem::transmute; diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 46a9006c146..0167d04c413 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -1,4 +1,3 @@ -use super::TryFrom; use crate::num::TryFromIntError; mod private { @@ -323,7 +322,6 @@ impl_try_from_lower_bounded!(isize => usize); #[cfg(target_pointer_width = "16")] mod ptr_try_from_impls { use super::TryFromIntError; - use crate::convert::TryFrom; impl_try_from_upper_bounded!(usize => u8); impl_try_from_unbounded!(usize => u16, u32, u64, u128); @@ -346,7 +344,6 @@ mod ptr_try_from_impls { #[cfg(target_pointer_width = "32")] mod ptr_try_from_impls { use super::TryFromIntError; - use crate::convert::TryFrom; impl_try_from_upper_bounded!(usize => u8, u16); impl_try_from_unbounded!(usize => u32, u64, u128); @@ -372,7 +369,6 @@ mod ptr_try_from_impls { #[cfg(target_pointer_width = "64")] mod ptr_try_from_impls { use super::TryFromIntError; - use crate::convert::TryFrom; impl_try_from_upper_bounded!(usize => u8, u16, u32); impl_try_from_unbounded!(usize => u64, u128); diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs index 54ed4c952fb..b8b96417d13 100644 --- a/library/core/src/iter/adapters/step_by.rs +++ b/library/core/src/iter/adapters/step_by.rs @@ -1,4 +1,3 @@ -use crate::convert::TryFrom; use crate::{ intrinsics, iter::{from_fn, TrustedLen, TrustedRandomAccess}, diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 055ead117ea..5eea764b28a 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -1,5 +1,4 @@ use crate::ascii::Char as AsciiChar; -use crate::convert::TryFrom; use crate::mem; use crate::net::{Ipv4Addr, Ipv6Addr}; use crate::num::NonZero; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index e1904ed220c..d2c9e1554b4 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -8,11 +8,11 @@ use super::super::ByRefSized; use super::super::TrustedRandomAccessNoCoerce; use super::super::{ArrayChunks, Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; use super::super::{FlatMap, Flatten}; -use super::super::{FromIterator, Intersperse, IntersperseWith, Product, Sum, Zip}; use super::super::{ Inspect, Map, MapWhile, MapWindows, Peekable, Rev, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, }; +use super::super::{Intersperse, IntersperseWith, Product, Sum, Zip}; fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f0448a98981..3bc1a87f848 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -270,6 +270,7 @@ #![feature(arm_target_feature)] #![feature(avx512_target_feature)] #![feature(hexagon_target_feature)] +#![feature(loongarch_target_feature)] #![feature(mips_target_feature)] #![feature(powerpc_target_feature)] #![feature(riscv_target_feature)] @@ -285,7 +286,7 @@ extern crate self as core; #[prelude_import] #[allow(unused)] -use prelude::v1::*; +use prelude::rust_2021::*; #[cfg(not(test))] // See #65860 #[macro_use] diff --git a/library/core/src/net/parser.rs b/library/core/src/net/parser.rs index 835ab9d73af..deea8212448 100644 --- a/library/core/src/net/parser.rs +++ b/library/core/src/net/parser.rs @@ -3,7 +3,6 @@ //! This module is "publicly exported" through the `FromStr` implementations //! below. -use crate::convert::{TryFrom, TryInto}; use crate::error::Error; use crate::fmt; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 2c7845d4304..3795a81c2c1 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -275,6 +275,25 @@ impl<T: ?Sized> DerefMut for &mut T { } } +/// Perma-unstable marker trait. Indicates that the type has a well-behaved [`Deref`] +/// (and, if applicable, [`DerefMut`]) implementation. This is relied on for soundness +/// of deref patterns. +/// +/// FIXME(deref_patterns): The precise semantics are undecided; the rough idea is that +/// successive calls to `deref`/`deref_mut` without intermediate mutation should be +/// idempotent, in the sense that they return the same value as far as pattern-matching +/// is concerned. Calls to `deref`/`deref_mut`` must leave the pointer itself likewise +/// unchanged. +#[unstable(feature = "deref_pure_trait", issue = "87121")] +#[cfg_attr(not(bootstrap), lang = "deref_pure")] +pub unsafe trait DerefPure {} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<T: ?Sized> DerefPure for &T {} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl<T: ?Sized> DerefPure for &mut T {} + /// Indicates that a struct can be used as a method receiver, without the /// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`, /// `Rc<T>`, `&T`, and `Pin<P>`. diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 4289a86f89b..ac808bec50e 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -165,6 +165,9 @@ pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssig #[stable(feature = "rust1", since = "1.0.0")] pub use self::deref::{Deref, DerefMut}; +#[unstable(feature = "deref_pure_trait", issue = "87121")] +pub use self::deref::DerefPure; + #[unstable(feature = "receiver_trait", issue = "none")] pub use self::deref::Receiver; diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 0083d15efae..631e1654ce0 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -553,7 +553,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; +use crate::iter::{self, FusedIterator, TrustedLen}; use crate::panicking::{panic, panic_str}; use crate::pin::Pin; use crate::{ diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index bc84fb5ccb0..68fce3960c7 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -1,4 +1,3 @@ -use crate::convert::{TryFrom, TryInto}; use crate::num::NonZero; #[cfg(debug_assertions)] use crate::ub_checks::assert_unsafe_precondition; diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 6879ac03f70..b2b627fe6a9 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -488,7 +488,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; +use crate::iter::{self, FusedIterator, TrustedLen}; use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::{convert, fmt, hint}; diff --git a/library/core/src/unit.rs b/library/core/src/unit.rs index 6656dd5c40b..d656005f3d4 100644 --- a/library/core/src/unit.rs +++ b/library/core/src/unit.rs @@ -1,5 +1,3 @@ -use crate::iter::FromIterator; - /// Collapses all unit items from an iterator into one. /// /// This is more useful when combined with higher-level abstractions, like diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs index 7a161b7e01d..48514e52587 100644 --- a/library/portable-simd/crates/core_simd/src/lib.rs +++ b/library/portable-simd/crates/core_simd/src/lib.rs @@ -45,10 +45,6 @@ #![unstable(feature = "portable_simd", issue = "86656")] //! Portable SIMD module. -#[prelude_import] -#[allow(unused_imports)] -use core::prelude::v1::*; - #[path = "mod.rs"] mod core_simd; pub use self::core_simd::simd; diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs index 6c8205b112c..8dbdfc0e1fe 100644 --- a/library/portable-simd/crates/core_simd/src/vector.rs +++ b/library/portable-simd/crates/core_simd/src/vector.rs @@ -4,7 +4,6 @@ use crate::simd::{ ptr::{SimdConstPtr, SimdMutPtr}, LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, }; -use core::convert::{TryFrom, TryInto}; /// A SIMD vector with the shape of `[T; N]` but the operations of `T`. /// diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 8a1ba436f72..f3cfc41bac7 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -2,6 +2,7 @@ use super::*; +use std::cell::RefCell; use std::marker::PhantomData; use std::sync::atomic::AtomicU32; @@ -189,61 +190,61 @@ struct Bridge<'a> { impl<'a> !Send for Bridge<'a> {} impl<'a> !Sync for Bridge<'a> {} -enum BridgeState<'a> { - /// No server is currently connected to this client. - NotConnected, +#[allow(unsafe_code)] +mod state { + use super::Bridge; + use std::cell::{Cell, RefCell}; + use std::ptr; - /// A server is connected and available for requests. - Connected(Bridge<'a>), - - /// Access to the bridge is being exclusively acquired - /// (e.g., during `BridgeState::with`). - InUse, -} + thread_local! { + static BRIDGE_STATE: Cell<*const ()> = const { Cell::new(ptr::null()) }; + } -enum BridgeStateL {} + pub(super) fn set<'bridge, R>(state: &RefCell<Bridge<'bridge>>, f: impl FnOnce() -> R) -> R { + struct RestoreOnDrop(*const ()); + impl Drop for RestoreOnDrop { + fn drop(&mut self) { + BRIDGE_STATE.set(self.0); + } + } -impl<'a> scoped_cell::ApplyL<'a> for BridgeStateL { - type Out = BridgeState<'a>; -} + let inner = ptr::from_ref(state).cast(); + let outer = BRIDGE_STATE.replace(inner); + let _restore = RestoreOnDrop(outer); -thread_local! { - static BRIDGE_STATE: scoped_cell::ScopedCell<BridgeStateL> = - const { scoped_cell::ScopedCell::new(BridgeState::NotConnected) }; -} + f() + } -impl BridgeState<'_> { - /// Take exclusive control of the thread-local - /// `BridgeState`, and pass it to `f`, mutably. - /// The state will be restored after `f` exits, even - /// by panic, including modifications made to it by `f`. - /// - /// N.B., while `f` is running, the thread-local state - /// is `BridgeState::InUse`. - fn with<R>(f: impl FnOnce(&mut BridgeState<'_>) -> R) -> R { - BRIDGE_STATE.with(|state| state.replace(BridgeState::InUse, f)) + pub(super) fn with<R>( + f: impl for<'bridge> FnOnce(Option<&RefCell<Bridge<'bridge>>>) -> R, + ) -> R { + let state = BRIDGE_STATE.get(); + // SAFETY: the only place where the pointer is set is in `set`. It puts + // back the previous value after the inner call has returned, so we know + // that as long as the pointer is not null, it came from a reference to + // a `RefCell<Bridge>` that outlasts the call to this function. Since `f` + // works the same for any lifetime of the bridge, including the actual + // one, we can lie here and say that the lifetime is `'static` without + // anyone noticing. + let bridge = unsafe { state.cast::<RefCell<Bridge<'static>>>().as_ref() }; + f(bridge) } } impl Bridge<'_> { fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R { - BridgeState::with(|state| match state { - BridgeState::NotConnected => { - panic!("procedural macro API is used outside of a procedural macro"); - } - BridgeState::InUse => { - panic!("procedural macro API is used while it's already in use"); - } - BridgeState::Connected(bridge) => f(bridge), + state::with(|state| { + let bridge = state.expect("procedural macro API is used outside of a procedural macro"); + let mut bridge = bridge + .try_borrow_mut() + .expect("procedural macro API is used while it's already in use"); + f(&mut bridge) }) } } pub(crate) fn is_available() -> bool { - BridgeState::with(|state| match state { - BridgeState::Connected(_) | BridgeState::InUse => true, - BridgeState::NotConnected => false, - }) + state::with(|s| s.is_some()) } /// A client-side RPC entry-point, which may be using a different `proc_macro` @@ -282,11 +283,7 @@ fn maybe_install_panic_hook(force_show_panics: bool) { HIDE_PANICS_DURING_EXPANSION.call_once(|| { let prev = panic::take_hook(); panic::set_hook(Box::new(move |info| { - let show = BridgeState::with(|state| match state { - BridgeState::NotConnected => true, - BridgeState::Connected(_) | BridgeState::InUse => force_show_panics, - }); - if show { + if force_show_panics || !is_available() { prev(info) } })); @@ -312,29 +309,24 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>( let (globals, input) = <(ExpnGlobals<Span>, A)>::decode(reader, &mut ()); // Put the buffer we used for input back in the `Bridge` for requests. - let new_state = - BridgeState::Connected(Bridge { cached_buffer: buf.take(), dispatch, globals }); - - BRIDGE_STATE.with(|state| { - state.set(new_state, || { - let output = f(input); - - // Take the `cached_buffer` back out, for the output value. - buf = Bridge::with(|bridge| bridge.cached_buffer.take()); - - // HACK(eddyb) Separate encoding a success value (`Ok(output)`) - // from encoding a panic (`Err(e: PanicMessage)`) to avoid - // having handles outside the `bridge.enter(|| ...)` scope, and - // to catch panics that could happen while encoding the success. - // - // Note that panics should be impossible beyond this point, but - // this is defensively trying to avoid any accidental panicking - // reaching the `extern "C"` (which should `abort` but might not - // at the moment, so this is also potentially preventing UB). - buf.clear(); - Ok::<_, ()>(output).encode(&mut buf, &mut ()); - }) - }) + let state = RefCell::new(Bridge { cached_buffer: buf.take(), dispatch, globals }); + + let output = state::set(&state, || f(input)); + + // Take the `cached_buffer` back out, for the output value. + buf = RefCell::into_inner(state).cached_buffer; + + // HACK(eddyb) Separate encoding a success value (`Ok(output)`) + // from encoding a panic (`Err(e: PanicMessage)`) to avoid + // having handles outside the `bridge.enter(|| ...)` scope, and + // to catch panics that could happen while encoding the success. + // + // Note that panics should be impossible beyond this point, but + // this is defensively trying to avoid any accidental panicking + // reaching the `extern "C"` (which should `abort` but might not + // at the moment, so this is also potentially preventing UB). + buf.clear(); + Ok::<_, ()>(output).encode(&mut buf, &mut ()); })) .map_err(PanicMessage::from) .unwrap_or_else(|e| { diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 67c72cf98d4..8553e8d5e4f 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -154,7 +154,7 @@ macro_rules! reverse_decode { mod arena; #[allow(unsafe_code)] mod buffer; -#[forbid(unsafe_code)] +#[deny(unsafe_code)] pub mod client; #[allow(unsafe_code)] mod closure; @@ -166,8 +166,6 @@ mod handle; #[forbid(unsafe_code)] mod rpc; #[allow(unsafe_code)] -mod scoped_cell; -#[allow(unsafe_code)] mod selfless_reify; #[forbid(unsafe_code)] pub mod server; diff --git a/library/proc_macro/src/bridge/scoped_cell.rs b/library/proc_macro/src/bridge/scoped_cell.rs deleted file mode 100644 index a8b34143908..00000000000 --- a/library/proc_macro/src/bridge/scoped_cell.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! `Cell` variant for (scoped) existential lifetimes. - -use std::cell::Cell; -use std::mem; - -/// Type lambda application, with a lifetime. -#[allow(unused_lifetimes)] -pub trait ApplyL<'a> { - type Out; -} - -/// Type lambda taking a lifetime, i.e., `Lifetime -> Type`. -pub trait LambdaL: for<'a> ApplyL<'a> {} - -impl<T: for<'a> ApplyL<'a>> LambdaL for T {} - -pub struct ScopedCell<T: LambdaL>(Cell<<T as ApplyL<'static>>::Out>); - -impl<T: LambdaL> ScopedCell<T> { - pub const fn new(value: <T as ApplyL<'static>>::Out) -> Self { - ScopedCell(Cell::new(value)) - } - - /// Sets the value in `self` to `replacement` while - /// running `f`, which gets the old value, mutably. - /// The old value will be restored after `f` exits, even - /// by panic, including modifications made to it by `f`. - #[rustc_confusables("swap")] - pub fn replace<'a, R>( - &self, - replacement: <T as ApplyL<'a>>::Out, - f: impl for<'b, 'c> FnOnce(&'b mut <T as ApplyL<'c>>::Out) -> R, - ) -> R { - /// Wrapper that ensures that the cell always gets filled - /// (with the original state, optionally changed by `f`), - /// even if `f` had panicked. - struct PutBackOnDrop<'a, T: LambdaL> { - cell: &'a ScopedCell<T>, - value: Option<<T as ApplyL<'static>>::Out>, - } - - impl<'a, T: LambdaL> Drop for PutBackOnDrop<'a, T> { - fn drop(&mut self) { - self.cell.0.set(self.value.take().unwrap()); - } - } - - let mut put_back_on_drop = PutBackOnDrop { - cell: self, - value: Some(self.0.replace(unsafe { - let erased = mem::transmute_copy(&replacement); - mem::forget(replacement); - erased - })), - }; - - f(put_back_on_drop.value.as_mut().unwrap()) - } - - /// Sets the value in `self` to `value` while running `f`. - pub fn set<R>(&self, value: <T as ApplyL<'_>>::Out, f: impl FnOnce() -> R) -> R { - self.replace(value, |_| f()) - } -} diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 5d0de2d06a0..8b3a9e82aad 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -97,7 +97,7 @@ use crate::time::SystemTime; /// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`). /// /// [`BufReader`]: io::BufReader -/// [`BufWriter`]: io::BufReader +/// [`BufWriter`]: io::BufWriter /// [`sync_all`]: File::sync_all /// [`write`]: File::write /// [`read`]: File::read diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index b968f8df34c..99b6da60c14 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -517,7 +517,7 @@ impl FileAttr { #[cfg(any(target_os = "horizon", target_os = "hurd"))] pub fn modified(&self) -> io::Result<SystemTime> { - Ok(SystemTime::from(self.stat.st_mtim)) + SystemTime::new(self.stat.st_mtim.tv_sec as i64, self.stat.st_mtim.tv_nsec as i64) } #[cfg(not(any( @@ -545,7 +545,7 @@ impl FileAttr { #[cfg(any(target_os = "horizon", target_os = "hurd"))] pub fn accessed(&self) -> io::Result<SystemTime> { - Ok(SystemTime::from(self.stat.st_atim)) + SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64) } #[cfg(any( diff --git a/library/stdarch b/library/stdarch -Subproject 56087ea170d878a7a57b3a5725e0c00f5f5cad7 +Subproject 967e7afd87cbea3232581a4a55031134ab88f59 diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 012d64e5344..d9c7032d0db 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1003,6 +1003,7 @@ impl Step for PlainSourceTarball { // Vendor all Cargo dependencies let mut cmd = Command::new(&builder.initial_cargo); cmd.arg("vendor") + .arg("--versioned-dirs") .arg("--sync") .arg(builder.src.join("./src/tools/cargo/Cargo.toml")) .arg("--sync") diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index f22a9ca604e..026c6907999 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -680,9 +680,13 @@ impl Step for Miri { .arg("--manifest-path") .arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml")); cargo.arg("--target").arg(target.rustc_target_arg()); - cargo.arg("--tests"); // don't run doctests, they are too confused by the staging cargo.arg("--").args(builder.config.test_args()); + // `prepare_tool_cargo` sets RUSTDOC to the bootstrap wrapper and RUSTDOC_REAL to a dummy path as this is a "run", not a "test". + // Also, we want the rustdoc from the "next" stage for the same reason that we build a std from the next stage. + // So let's just set that here, and bypass bootstrap's RUSTDOC (just like cargo-miri already ignores bootstrap's RUSTC_WRAPPER). + cargo.env("RUSTDOC", builder.rustdoc(compiler_std)); + // Tell `cargo miri` where to find things. cargo.env("MIRI_SYSROOT", &miri_sysroot); cargo.env("MIRI_HOST_SYSROOT", sysroot); diff --git a/src/doc/edition-guide b/src/doc/edition-guide -Subproject e1eead1181a691e56299294d5f1d62fe7a26d31 +Subproject 98b33e9a441457b0a491fe1be90e7de64eafc3e diff --git a/src/doc/reference b/src/doc/reference -Subproject 5afb503a4c1ea3c84370f8f4c08a1cddd1cdf6a +Subproject 984b36eca4b9293df04d5ba4eb5c4f77db0f51d diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject e093099709456e6fd74fecd2505fdf49a2471c1 +Subproject 7601e0c5ad29d5bd3b518700ea63fddfff5915a diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject 8a5d647f19b08998612146b1cb2ca47083db63e +Subproject ffa246b7fd95a96e1cd54883e613aed42c32547 diff --git a/src/doc/unstable-book/src/language-features/adt-const-params.md b/src/doc/unstable-book/src/language-features/adt-const-params.md new file mode 100644 index 00000000000..208bf5e4c15 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/adt-const-params.md @@ -0,0 +1,35 @@ +# `adt_const_params` + +The tracking issue for this feature is: [#95174] + +[#95174]: https://github.com/rust-lang/rust/issues/95174 + +------------------------ + +Allows for using more complex types for const parameters, such as structs or enums. + +```rust +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +enum Foo { + A, + B, + C, +} + +#[derive(ConstParamTy, PartialEq, Eq)] +struct Bar { + flag: bool, +} + +fn is_foo_a_and_bar_true<const F: Foo, const B: Bar>() -> bool { + match (F, B.flag) { + (Foo::A, true) => true, + _ => false, + } +} +``` diff --git a/src/tools/cargo b/src/tools/cargo -Subproject d438c80c45c24be676ef5867edc79d0a14910ef +Subproject 499a61ce7a0fc6a72040084862a68b2603e770e diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs index 07fbb1cb5c9..981a76d683d 100644 --- a/src/tools/clippy/clippy_lints/src/float_literal.rs +++ b/src/tools/clippy/clippy_lints/src/float_literal.rs @@ -83,7 +83,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { LitFloatType::Unsuffixed => None, }; let (is_whole, is_inf, mut float_str) = match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F16 => { + // FIXME(f16_f128): do a check like the others when parsing is available + return; + }, FloatTy::F32 => { let value = sym_str.parse::<f32>().unwrap(); @@ -94,7 +97,10 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { (value.fract() == 0.0, value.is_infinite(), formatter.format(value)) }, - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => { + // FIXME(f16_f128): do a check like the others when parsing is available + return; + }, }; if is_inf { @@ -139,10 +145,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { #[must_use] fn max_digits(fty: FloatTy) -> u32 { match fty { - FloatTy::F16 => unimplemented!("f16_f128"), + // FIXME(f16_f128): replace the magic numbers once `{f16,f128}::DIGITS` are available + FloatTy::F16 => 3, FloatTy::F32 => f32::DIGITS, FloatTy::F64 => f64::DIGITS, - FloatTy::F128 => unimplemented!("f16_f128"), + FloatTy::F128 => 33, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index bc5dd10cad0..e58d4776427 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -12,7 +12,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node}; -use rustc_hir_typeck::{FnCtxt, Inherited}; +use rustc_hir_typeck::{FnCtxt, TypeckRootCtxt}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::Mutability; @@ -438,8 +438,8 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< Node::Item(item) => { if let ItemKind::Fn(_, _, body_id) = &item.kind && let output_ty = return_ty(cx, item.owner_id) - && let inherited = Inherited::new(cx.tcx, item.owner_id.def_id) - && let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, item.owner_id.def_id) + && let root_ctxt = TypeckRootCtxt::new(cx.tcx, item.owner_id.def_id) + && let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, item.owner_id.def_id) && fn_ctxt.can_coerce(ty, output_ty) { if has_lifetime(output_ty) && has_lifetime(ty) { diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 7a7bb9f9c94..15f1890aa39 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -1,6 +1,6 @@ use rustc_hir as hir; use rustc_hir::Expr; -use rustc_hir_typeck::{cast, FnCtxt, Inherited}; +use rustc_hir_typeck::{cast, FnCtxt, TypeckRootCtxt}; use rustc_lint::LateContext; use rustc_middle::ty::cast::CastKind; use rustc_middle::ty::Ty; @@ -34,8 +34,8 @@ pub(super) fn check_cast<'tcx>( let hir_id = e.hir_id; let local_def_id = hir_id.owner.def_id; - let inherited = Inherited::new(cx.tcx, local_def_id); - let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, local_def_id); + let root_ctxt = TypeckRootCtxt::new(cx.tcx, local_def_id); + let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, local_def_id); if let Ok(check) = cast::CastCheck::new( &fn_ctxt, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 6ff47dbffbc..00fe1208c2f 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -708,6 +708,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-run-results", "check-stdout", "check-test-line-numbers-match", + "compare-output-lines-by-subset", "compile-flags", "dont-check-compiler-stderr", "dont-check-compiler-stdout", diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 1097fc6db72..2c5868d5b37 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -30,11 +30,16 @@ jobs: host_target: i686-pc-windows-msvc runs-on: ${{ matrix.os }} env: - RUST_BACKTRACE: 1 HOST_TARGET: ${{ matrix.host_target }} steps: - uses: actions/checkout@v3 + - name: Show Rust version (stable toolchain) + run: | + rustup show + rustc -Vv + cargo -V + # Cache the global cargo directory, but NOT the local `target` directory which # we cannot reuse anyway when the nightly changes (and it grows quite large # over time). @@ -58,7 +63,7 @@ jobs: if: ${{ steps.cache.outputs.cache-hit != 'true' }} run: cargo install -f rustup-toolchain-install-master - - name: Install "master" toolchain + - name: Install miri toolchain run: | if [[ ${{ github.event_name }} == 'schedule' ]]; then echo "Building against latest rustc git version" @@ -66,13 +71,13 @@ jobs: fi ./miri toolchain --host ${{ matrix.host_target }} - - name: Show Rust version + - name: Show Rust version (miri toolchain) run: | rustup show rustc -Vv cargo -V - - name: Test + - name: Test Miri run: ./ci/ci.sh style: diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index f2f3a642e0a..3416fb0d9ba 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -64,19 +64,22 @@ For example, you can (cross-)run the driver on a particular file by doing ./miri run tests/pass/hello.rs --target i686-unknown-linux-gnu ``` -and you can (cross-)run the entire test suite using: +Tests in ``pass-dep`` need to be run using ``./miri run --dep <filename>``. +For example: +```sh +./miri run --dep tests/pass-dep/shims/libc-fs.rs +``` + +You can (cross-)run the entire test suite using: ``` ./miri test MIRI_TEST_TARGET=i686-unknown-linux-gnu ./miri test ``` -If your target doesn't support libstd that should usually just work. However, if you are using a -custom target file, you might have to set `MIRI_NO_STD=1`. - `./miri test FILTER` only runs those tests that contain `FILTER` in their filename (including the base directory, e.g. `./miri test fail` will run all compile-fail tests). These filters are passed -to `cargo test`, so for multiple filers you need to use `./miri test -- FILTER1 FILTER2`. +to `cargo test`, so for multiple filters you need to use `./miri test -- FILTER1 FILTER2`. #### Fine grained logging @@ -178,6 +181,7 @@ to `.vscode/settings.json` in your local Miri clone: "cargo", "clippy", // make this `check` when working with a locally built rustc "--message-format=json", + "--all-targets", ], // Contrary to what the name suggests, this also affects proc macros. "rust-analyzer.cargo.buildScripts.overrideCommand": [ @@ -187,6 +191,7 @@ to `.vscode/settings.json` in your local Miri clone: "cargo", "check", "--message-format=json", + "--all-targets", ], } ``` diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index b043805291e..26e55b89708 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -505,6 +505,8 @@ binaries, and as such worth documenting: * `MIRI_LOCAL_CRATES` is set by `cargo-miri` to tell the Miri driver which crates should be given special treatment in diagnostics, in addition to the crate currently being compiled. +* `MIRI_ORIG_RUSTDOC` is set and read by different phases of `cargo-miri` to remember the + value of `RUSTDOC` from before it was overwritten. * `MIRI_VERBOSE` when set to any value tells the various `cargo-miri` phases to perform verbose logging. * `MIRI_HOST_SYSROOT` is set by bootstrap to tell `cargo-miri` which sysroot to use for *host* diff --git a/src/tools/miri/cargo-miri/src/main.rs b/src/tools/miri/cargo-miri/src/main.rs index c5fada6fe55..9fdd4c3e470 100644 --- a/src/tools/miri/cargo-miri/src/main.rs +++ b/src/tools/miri/cargo-miri/src/main.rs @@ -11,10 +11,18 @@ use std::{env, iter}; use crate::phases::*; +/// Returns `true` if our flags look like they may be for rustdoc, i.e., this is cargo calling us to +/// be rustdoc. It's hard to be sure as cargo does not have a RUSTDOC_WRAPPER or an env var that +/// would let us get a clear signal. +fn looks_like_rustdoc() -> bool { + // The `--test-run-directory` flag only exists for rustdoc and cargo always passes it. Perfect! + env::args().any(|arg| arg == "--test-run-directory") +} + fn main() { // Rustc does not support non-UTF-8 arguments so we make no attempt either. // (We do support non-UTF-8 environment variables though.) - let mut args = std::env::args(); + let mut args = env::args(); // Skip binary name. args.next().unwrap(); @@ -91,10 +99,16 @@ fn main() { // (see https://github.com/rust-lang/cargo/issues/10886). phase_rustc(args, RustcPhase::Build) } - _ => { - // Everything else must be rustdoc. But we need to get `first` "back onto the iterator", + _ if looks_like_rustdoc() => { + // This is probably rustdoc. But we need to get `first` "back onto the iterator", // it is some part of the rustdoc invocation. phase_rustdoc(iter::once(first).chain(args)); } + _ => { + show_error!( + "`cargo-miri` failed to recognize which phase of the build process this is, please report a bug.\nThe command-line arguments were: {:#?}", + Vec::from_iter(env::args()), + ); + } } } diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 81ff68545cc..8c0f605fd6e 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -202,6 +202,9 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) { cmd.env("MIRI_BE_RUSTC", "target"); // we better remember to *unset* this in the other phases! // Set rustdoc to us as well, so we can run doctests. + if let Some(orig_rustdoc) = env::var_os("RUSTDOC") { + cmd.env("MIRI_ORIG_RUSTDOC", orig_rustdoc); + } cmd.env("RUSTDOC", &cargo_miri_path); cmd.env("MIRI_LOCAL_CRATES", local_crates(&metadata)); @@ -581,9 +584,10 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) { let verbose = std::env::var("MIRI_VERBOSE") .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer")); - // phase_cargo_miri sets the RUSTDOC env var to ourselves, so we can't use that here; - // just default to a straight-forward invocation for now: - let mut cmd = Command::new("rustdoc"); + // phase_cargo_miri sets the RUSTDOC env var to ourselves, and puts a backup + // of the old value into MIRI_ORIG_RUSTDOC. So that's what we have to invoke now. + let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string()); + let mut cmd = Command::new(rustdoc); let extern_flag = "--extern"; let runtool_flag = "--runtool"; @@ -620,7 +624,7 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) { // The `--test-builder` and `--runtool` arguments are unstable rustdoc features, // which are disabled by default. We first need to enable them explicitly: - cmd.arg("-Z").arg("unstable-options"); + cmd.arg("-Zunstable-options"); // rustdoc needs to know the right sysroot. cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap()); diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 9d2c3f362e6..54c5d3087fd 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -13,6 +13,15 @@ function endgroup { begingroup "Building Miri" +# Special Windows hacks +if [ "$HOST_TARGET" = i686-pc-windows-msvc ]; then + # The $BASH variable is `/bin/bash` here, but that path does not actually work. There are some + # hacks in place somewhere to try to paper over this, but the hacks dont work either (see + # <https://github.com/rust-lang/miri/pull/3402>). So we hard-code the correct location for Github + # CI instead. + BASH="C:/Program Files/Git/usr/bin/bash" +fi + # Determine configuration for installed build echo "Installing release version of Miri" export RUSTFLAGS="-D warnings" @@ -58,12 +67,13 @@ function run_tests { MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic} # Also run some many-seeds tests. 64 seeds means this takes around a minute per test. + # (Need to invoke via explicit `bash -c` for Windows.) for FILE in tests/many-seeds/*.rs; do - MIRI_SEEDS=64 ./miri many-seeds ./miri run "$FILE" + MIRI_SEEDS=64 ./miri many-seeds "$BASH" -c "./miri run '$FILE'" done # Check that the benchmarks build and run, but without actually benchmarking. - HYPERFINE="bash -c" ./miri bench + HYPERFINE="'$BASH' -c" ./miri bench fi ## test-cargo-miri diff --git a/src/tools/miri/miri b/src/tools/miri/miri index 169f4521f2d..5f71fc94438 100755 --- a/src/tools/miri/miri +++ b/src/tools/miri/miri @@ -3,5 +3,5 @@ set -e # Instead of doing just `cargo run --manifest-path .. $@`, we invoke miri-script binary directly. Invoking `cargo run` goes through # rustup (that sets it's own environmental variables), which is undesirable. MIRI_SCRIPT_TARGET_DIR="$(dirname "$0")"/miri-script/target -cargo build $CARGO_EXTRA_FLAGS -q --target-dir "$MIRI_SCRIPT_TARGET_DIR" --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml +cargo +stable build $CARGO_EXTRA_FLAGS -q --target-dir "$MIRI_SCRIPT_TARGET_DIR" --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml "$MIRI_SCRIPT_TARGET_DIR"/debug/miri-script "$@" diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 7fff6ae80b4..66f323290b2 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -178,7 +178,7 @@ impl Command { .context("Please install rustup-toolchain-install-master by running 'cargo install rustup-toolchain-install-master'")?; let sh = Shell::new()?; sh.change_dir(miri_dir()?); - let new_commit = Some(sh.read_file("rust-version")?.trim().to_owned()); + let new_commit = sh.read_file("rust-version")?.trim().to_owned(); let current_commit = { let rustc_info = cmd!(sh, "rustc +miri --version -v").read(); if rustc_info.is_err() { @@ -193,7 +193,7 @@ impl Command { } }; // Check if we already are at that commit. - if current_commit == new_commit { + if current_commit.as_ref() == Some(&new_commit) { if active_toolchain()? != "miri" { cmd!(sh, "rustup override set miri").run()?; } @@ -202,7 +202,7 @@ impl Command { // Install and setup new toolchain. cmd!(sh, "rustup toolchain uninstall miri").run()?; - cmd!(sh, "rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy {flags...} -- {new_commit...}").run()?; + cmd!(sh, "rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy {flags...} -- {new_commit}").run()?; cmd!(sh, "rustup override set miri").run()?; // Cleanup. cmd!(sh, "cargo clean").run()?; @@ -380,9 +380,9 @@ impl Command { .env("MIRIFLAGS", miriflags) .quiet() .run(); - if status.is_err() { + if let Err(err) = status { println!("Failing seed: {seed}"); - break; + return Err(err.into()); } } Ok(()) diff --git a/src/tools/miri/miri.bat b/src/tools/miri/miri.bat index 959e54d8844..18baa683f65 100644 --- a/src/tools/miri/miri.bat +++ b/src/tools/miri/miri.bat @@ -5,7 +5,7 @@ set MIRI_SCRIPT_TARGET_DIR=%0\..\miri-script\target :: If any other steps are added, the "|| exit /b" must be appended to early :: return from the script. If not, it will continue execution. -cargo build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml || exit /b +cargo +stable build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml || exit /b :: Forwards all arguments to this file to the executable. :: We invoke the binary directly to avoid going through rustup, which would set some extra diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 9b89f016a77..fa06a069d54 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c3b05c6e5b5b59613350b8c2875b0add67ed74df +cb7c63606e53715f94f3ba04d38e50772e4cd23d diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index c12382527e7..8fffb91542f 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -276,7 +276,7 @@ fn run_compiler( // If no `--sysroot` is given, the `MIRI_SYSROOT` env var is consulted to find where // that sysroot lives, and that is passed to rustc. let sysroot_flag = "--sysroot"; - if !args.iter().any(|e| e == sysroot_flag) { + if !args.iter().any(|e| e.starts_with(sysroot_flag)) { // Using the built-in default here would be plain wrong, so we *require* // the env var to make sure things make sense. let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| { @@ -364,6 +364,10 @@ fn main() { let args = rustc_driver::args::raw_args(&early_dcx) .unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE)); + // Install the ctrlc handler that sets `rustc_const_eval::CTRL_C_RECEIVED`, even if + // MIRI_BE_RUSTC is set. + rustc_driver::install_ctrlc_handler(); + // If the environment asks us to actually be rustc, then do that. if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") { // Earliest rustc setup. diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 805c0580b2f..e2e18d3a734 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -3,12 +3,13 @@ use std::cell::RefCell; use std::collections::hash_map::Entry; use std::num::TryFromIntError; -use std::sync::atomic::{AtomicBool, Ordering::Relaxed}; +use std::sync::atomic::Ordering::Relaxed; use std::task::Poll; use std::time::{Duration, SystemTime}; use either::Either; +use rustc_const_eval::CTRL_C_RECEIVED; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_index::{Idx, IndexVec}; @@ -1045,21 +1046,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program /// termination). fn run_threads(&mut self) -> InterpResult<'tcx, !> { - static SIGNALED: AtomicBool = AtomicBool::new(false); - ctrlc::set_handler(move || { - // Indicate that we have ben signaled to stop. If we were already signaled, exit - // immediately. In our interpreter loop we try to consult this value often, but if for - // whatever reason we don't get to that check or the cleanup we do upon finding that - // this bool has become true takes a long time, the exit here will promptly exit the - // process on the second Ctrl-C. - if SIGNALED.swap(true, Relaxed) { - std::process::exit(1); - } - }) - .unwrap(); - let this = self.eval_context_mut(); + let this = self.eval_context_mut(); loop { - if SIGNALED.load(Relaxed) { + if CTRL_C_RECEIVED.load(Relaxed) { this.machine.handle_abnormal_termination(); std::process::exit(1); } diff --git a/src/tools/miri/test-cargo-miri/Cargo.lock b/src/tools/miri/test-cargo-miri/Cargo.lock index d5e57a66a8d..f75d68f4e29 100644 --- a/src/tools/miri/test-cargo-miri/Cargo.lock +++ b/src/tools/miri/test-cargo-miri/Cargo.lock @@ -3,6 +3,12 @@ version = 3 [[package]] +name = "anyhow" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" + +[[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -24,6 +30,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" name = "cargo-miri-test" version = "0.1.0" dependencies = [ + "anyhow", "autocfg", "byteorder 0.5.3", "byteorder 1.4.3", diff --git a/src/tools/miri/test-cargo-miri/Cargo.toml b/src/tools/miri/test-cargo-miri/Cargo.toml index 1688096fd9a..58c451741bb 100644 --- a/src/tools/miri/test-cargo-miri/Cargo.toml +++ b/src/tools/miri/test-cargo-miri/Cargo.toml @@ -22,6 +22,9 @@ issue_rust_86261 = { path = "issue-rust-86261" } byteorder_2 = { package = "byteorder", version = "0.5" } # to test dev-dependencies behave as expected, with renaming # Not actually used, but exercises some unique code path (`--extern` .so file). serde_derive = "1.0.185" +# Not actually used, but uses a custom build probe so let's make sure that works. +# (Ideally we'd check if the probe was successful, but that's not easily possible.) +anyhow = "1.0" [build-dependencies] autocfg = "1" diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs index fafeb9e0558..4cfc1843a7a 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs @@ -16,6 +16,10 @@ mod utils; fn main() { test_dup_stdout_stderr(); test_canonicalize_too_long(); + test_rename(); + test_ftruncate::<libc::off_t>(libc::ftruncate); + #[cfg(target_os = "linux")] + test_ftruncate::<libc::off64_t>(libc::ftruncate64); test_readlink(); test_file_open_unix_allow_two_args(); test_file_open_unix_needs_three_args(); @@ -133,6 +137,65 @@ fn test_readlink() { assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); } +fn test_rename() { + let path1 = prepare("miri_test_libc_fs_source.txt"); + let path2 = prepare("miri_test_libc_fs_rename_destination.txt"); + + let file = File::create(&path1).unwrap(); + drop(file); + + let c_path1 = CString::new(path1.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path2 = CString::new(path2.as_os_str().as_bytes()).expect("CString::new failed"); + + // Renaming should succeed + unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) }; + // Check that old file path isn't present + assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind()); + // Check that the file has moved successfully + assert!(path2.metadata().unwrap().is_file()); + + // Renaming a nonexistent file should fail + let res = unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) }; + assert_eq!(res, -1); + assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); + + remove_file(&path2).unwrap(); +} + +fn test_ftruncate<T: From<i32>>( + ftruncate: unsafe extern "C" fn(fd: libc::c_int, length: T) -> libc::c_int, +) { + // libc::off_t is i32 in target i686-unknown-linux-gnu + // https://docs.rs/libc/latest/i686-unknown-linux-gnu/libc/type.off_t.html + + let bytes = b"hello"; + let path = prepare("miri_test_libc_fs_ftruncate.txt"); + let mut file = File::create(&path).unwrap(); + file.write(bytes).unwrap(); + file.sync_all().unwrap(); + assert_eq!(file.metadata().unwrap().len(), 5); + + let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR) }; + + // Truncate to a bigger size + let mut res = unsafe { ftruncate(fd, T::from(10)) }; + assert_eq!(res, 0); + assert_eq!(file.metadata().unwrap().len(), 10); + + // Write after truncate + file.write(b"dup").unwrap(); + file.sync_all().unwrap(); + assert_eq!(file.metadata().unwrap().len(), 10); + + // Truncate to smaller size + res = unsafe { ftruncate(fd, T::from(2)) }; + assert_eq!(res, 0); + assert_eq!(file.metadata().unwrap().len(), 2); + + remove_file(&path).unwrap(); +} + #[cfg(target_os = "linux")] fn test_o_tmpfile_flag() { use std::fs::{create_dir, OpenOptions}; diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs new file mode 100644 index 00000000000..9b2fc2948bf --- /dev/null +++ b/src/tools/miri/tests/pass/async-closure-drop.rs @@ -0,0 +1,40 @@ +#![feature(async_closure, noop_waker, async_fn_traits)] + +use std::future::Future; +use std::pin::pin; +use std::task::*; + +pub fn block_on<T>(fut: impl Future<Output = T>) -> T { + let mut fut = pin!(fut); + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match fut.as_mut().poll(ctx) { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} + +async fn call_once(f: impl async FnOnce(DropMe)) { + f(DropMe("world")).await; +} + +#[derive(Debug)] +struct DropMe(&'static str); + +impl Drop for DropMe { + fn drop(&mut self) { + println!("{}", self.0); + } +} + +pub fn main() { + block_on(async { + let b = DropMe("hello"); + let async_closure = async move |a: DropMe| { + println!("{a:?} {b:?}"); + }; + call_once(async_closure).await; + }); +} diff --git a/src/tools/miri/tests/pass/async-closure-drop.stdout b/src/tools/miri/tests/pass/async-closure-drop.stdout new file mode 100644 index 00000000000..34cfdedc44a --- /dev/null +++ b/src/tools/miri/tests/pass/async-closure-drop.stdout @@ -0,0 +1,3 @@ +DropMe("world") DropMe("hello") +world +hello diff --git a/src/tools/miri/tests/pass/async-closure.rs b/src/tools/miri/tests/pass/async-closure.rs index 9b2fc2948bf..2f7ec2b9e6f 100644 --- a/src/tools/miri/tests/pass/async-closure.rs +++ b/src/tools/miri/tests/pass/async-closure.rs @@ -1,6 +1,7 @@ #![feature(async_closure, noop_waker, async_fn_traits)] use std::future::Future; +use std::ops::{AsyncFnMut, AsyncFnOnce}; use std::pin::pin; use std::task::*; @@ -16,25 +17,36 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T { } } -async fn call_once(f: impl async FnOnce(DropMe)) { - f(DropMe("world")).await; +async fn call_mut(f: &mut impl AsyncFnMut(i32)) { + f(0).await; } -#[derive(Debug)] -struct DropMe(&'static str); +async fn call_once(f: impl AsyncFnOnce(i32)) { + f(1).await; +} -impl Drop for DropMe { - fn drop(&mut self) { - println!("{}", self.0); - } +async fn call_normal<F: Future<Output = ()>>(f: &impl Fn(i32) -> F) { + f(0).await; +} + +async fn call_normal_once<F: Future<Output = ()>>(f: impl FnOnce(i32) -> F) { + f(1).await; } pub fn main() { block_on(async { - let b = DropMe("hello"); - let async_closure = async move |a: DropMe| { - println!("{a:?} {b:?}"); + let b = 2i32; + let mut async_closure = async move |a: i32| { + println!("{a} {b}"); }; + call_mut(&mut async_closure).await; call_once(async_closure).await; + + // No-capture closures implement `Fn`. + let async_closure = async move |a: i32| { + println!("{a}"); + }; + call_normal(&async_closure).await; + call_normal_once(async_closure).await; }); } diff --git a/src/tools/miri/tests/pass/async-closure.stdout b/src/tools/miri/tests/pass/async-closure.stdout index 34cfdedc44a..7baae1aa94f 100644 --- a/src/tools/miri/tests/pass/async-closure.stdout +++ b/src/tools/miri/tests/pass/async-closure.stdout @@ -1,3 +1,4 @@ -DropMe("world") DropMe("hello") -world -hello +0 2 +1 2 +0 +1 diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index 7f363ccdfe5..129d1dfd732 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -4,8 +4,11 @@ use std::ffi::OsString; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; use std::{env, process::Command}; -use ui_test::{color_eyre::Result, Config, Match, Mode, OutputConflictHandling}; -use ui_test::{status_emitter, CommandBuilder, Format, RustfixMode}; +use ui_test::color_eyre::eyre::{Context, Result}; +use ui_test::{ + status_emitter, CommandBuilder, Config, Format, Match, Mode, OutputConflictHandling, + RustfixMode, +}; fn miri_path() -> PathBuf { PathBuf::from(option_env!("MIRI").unwrap_or(env!("CARGO_BIN_EXE_miri"))) @@ -124,6 +127,9 @@ fn run_tests( // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find). config.program.envs.push(("MIRI_TEMP".into(), Some(tmpdir.to_owned().into()))); + // If a test ICEs, we want to see a backtrace. + config.program.envs.push(("RUST_BACKTRACE".into(), Some("1".into()))); + // Handle command-line arguments. let args = ui_test::Args::test()?; let default_bless = env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0"); @@ -223,7 +229,7 @@ fn ui( with_dependencies: Dependencies, tmpdir: &Path, ) -> Result<()> { - let msg = format!("## Running ui tests in {path} against miri for {target}"); + let msg = format!("## Running ui tests in {path} for {target}"); eprintln!("{}", msg.green().bold()); let with_dependencies = match with_dependencies { @@ -231,6 +237,7 @@ fn ui( WithoutDependencies => false, }; run_tests(mode, path, target, with_dependencies, tmpdir) + .with_context(|| format!("ui tests in {path} for {target} failed")) } fn get_target() -> String { diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 10fdfc0a65f..b74afa0d3e8 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -208,6 +208,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "byteorder", // via ruzstd in object in thorin-dwp "cc", "cfg-if", + "cfg_aliases", "compiler_builtins", "cpufeatures", "crc32fast", @@ -216,6 +217,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "crossbeam-epoch", "crossbeam-utils", "crypto-common", + "ctrlc", "darling", "darling_core", "darling_macro", @@ -281,6 +283,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "memmap2", "memoffset", "miniz_oxide", + "nix", "nu-ansi-term", "num-conv", "num_cpus", diff --git a/tests/codegen/intrinsics/typed_swap.rs b/tests/codegen/intrinsics/typed_swap.rs index b55fb8ee36f..e73931d1d54 100644 --- a/tests/codegen/intrinsics/typed_swap.rs +++ b/tests/codegen/intrinsics/typed_swap.rs @@ -24,9 +24,8 @@ pub unsafe fn swap_i32(x: &mut i32, y: &mut i32) { // CHECK-NOT: alloca // CHECK: %[[TEMP:.+]] = load i32, ptr %x, align 4 - // CHECK-SAME: !noundef + // OPT3-SAME: !noundef // OPT0: %[[TEMP2:.+]] = load i32, ptr %y, align 4 - // OPT0-SAME: !noundef // OPT0: store i32 %[[TEMP2]], ptr %x, align 4 // OPT0-NOT: memcpy // OPT3-NOT: load @@ -42,9 +41,9 @@ pub unsafe fn swap_pair(x: &mut (i32, u32), y: &mut (i32, u32)) { // CHECK-NOT: alloca // CHECK: load i32 - // CHECK-SAME: !noundef + // OPT3-SAME: !noundef // CHECK: load i32 - // CHECK-SAME: !noundef + // OPT3-SAME: !noundef // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x, ptr align 4 %y, i64 8, i1 false) // CHECK: store i32 // CHECK: store i32 @@ -57,10 +56,10 @@ pub unsafe fn swap_str<'a>(x: &mut &'a str, y: &mut &'a str) { // CHECK-NOT: alloca // CHECK: load ptr - // CHECK-SAME: !nonnull - // CHECK-SAME: !noundef + // OPT3-SAME: !nonnull + // OPT3-SAME: !noundef // CHECK: load i64 - // CHECK-SAME: !noundef + // OPT3-SAME: !noundef // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 16, i1 false) // CHECK: store ptr // CHECK: store i64 diff --git a/tests/codegen/loads.rs b/tests/codegen/loads.rs index b86b3dd3a19..ba4de77ce6f 100644 --- a/tests/codegen/loads.rs +++ b/tests/codegen/loads.rs @@ -1,4 +1,5 @@ -//@ compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 +//@ compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 -O + #![crate_type = "lib"] #![feature(generic_nonzero)] diff --git a/tests/codegen/overaligned-constant.rs b/tests/codegen/overaligned-constant.rs index 351c8ea8f4b..9e5b69ff267 100644 --- a/tests/codegen/overaligned-constant.rs +++ b/tests/codegen/overaligned-constant.rs @@ -16,7 +16,7 @@ fn main() { // CHECK-LABEL: @_ZN20overaligned_constant4main // CHECK: [[full:%_.*]] = alloca %SmallStruct, align 8 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[full]], ptr align 8 @0, i64 32, i1 false) - // CHECK: %b.0 = load i32, ptr @0, align 4, + // CHECK: %b.0 = load i32, ptr @0, align 4 // CHECK: %b.1 = load i32, ptr getelementptr inbounds ({{.*}}), align 4 let mut s = S(1); diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir index f51540bcfff..cab7bdb7e3c 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref -fn main::{closure#0}::{closure#1}(_1: *mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} { +fn main::{closure#0}::{closure#1}(_1: &mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} { let mut _0: {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10}; bb0: { diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir index f51540bcfff..cab7bdb7e3c 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref -fn main::{closure#0}::{closure#1}(_1: *mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} { +fn main::{closure#0}::{closure#1}(_1: &mut {async closure@$DIR/async_closure_shims.rs:49:29: 49:48}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10} { let mut _0: {async closure body@$DIR/async_closure_shims.rs:49:49: 51:10}; bb0: { diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir index 8b22743d2b0..7480324b177 100644 --- a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir @@ -9,7 +9,7 @@ storage_conflicts: BitMatrix(0x0) {}, } */ -fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>, _2: &mut Context<'_>) -> Poll<()> { +fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { debug _task_context => _4; let mut _0: std::task::Poll<()>; let mut _3: (); @@ -17,7 +17,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}> let mut _5: u32; bb0: { - _5 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16}))); + _5 = discriminant((*(_1.0: &mut {async fn body of a()}))); switchInt(move _5) -> [0: bb1, 1: bb4, otherwise: bb5]; } @@ -29,7 +29,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}> bb2: { _0 = Poll::<()>::Ready(move _3); - discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16}))) = 1; + discriminant((*(_1.0: &mut {async fn body of a()}))) = 1; return; } diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 2f7c4f7d402..d697ea49231 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -51,19 +51,19 @@ }, } */ -fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, _2: &mut Context<'_>) -> Poll<()> { +fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> { debug _task_context => _38; let mut _0: std::task::Poll<()>; let _3: (); - let mut _4: {async fn body@$DIR/async_await.rs:12:14: 12:16}; - let mut _5: {async fn body@$DIR/async_await.rs:12:14: 12:16}; - let mut _6: {async fn body@$DIR/async_await.rs:12:14: 12:16}; + let mut _4: {async fn body of a()}; + let mut _5: {async fn body of a()}; + let mut _6: {async fn body of a()}; let mut _7: (); let _8: (); let mut _9: std::task::Poll<()>; - let mut _10: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>; - let mut _11: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16}; - let mut _12: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16}; + let mut _10: std::pin::Pin<&mut {async fn body of a()}>; + let mut _11: &mut {async fn body of a()}; + let mut _12: &mut {async fn body of a()}; let mut _13: &mut std::task::Context<'_>; let mut _14: &mut std::task::Context<'_>; let mut _15: &mut std::task::Context<'_>; @@ -71,14 +71,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, let mut _18: !; let mut _19: &mut std::task::Context<'_>; let mut _20: (); - let mut _21: {async fn body@$DIR/async_await.rs:12:14: 12:16}; - let mut _22: {async fn body@$DIR/async_await.rs:12:14: 12:16}; - let mut _23: {async fn body@$DIR/async_await.rs:12:14: 12:16}; + let mut _21: {async fn body of a()}; + let mut _22: {async fn body of a()}; + let mut _23: {async fn body of a()}; let _24: (); let mut _25: std::task::Poll<()>; - let mut _26: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>; - let mut _27: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16}; - let mut _28: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16}; + let mut _26: std::pin::Pin<&mut {async fn body of a()}>; + let mut _27: &mut {async fn body of a()}; + let mut _28: &mut {async fn body of a()}; let mut _29: &mut std::task::Context<'_>; let mut _30: &mut std::task::Context<'_>; let mut _31: &mut std::task::Context<'_>; @@ -90,7 +90,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, let mut _38: &mut std::task::Context<'_>; let mut _39: u32; scope 1 { - debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}); + debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}); let _17: (); scope 2 { } @@ -99,7 +99,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, } } scope 4 { - debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}); + debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}); let _33: (); scope 5 { } @@ -109,7 +109,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, } bb0: { - _39 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))); + _39 = discriminant((*(_1.0: &mut {async fn body of b()}))); switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8]; } @@ -122,14 +122,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, } bb2: { - _4 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; + _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; } bb3: { StorageDead(_5); PlaceMention(_4); nop; - (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}) = move _4; + (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}) = move _4; goto -> bb4; } @@ -139,9 +139,9 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}); + _12 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}); _11 = &mut (*_12); - _10 = Pin::<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; + _10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; } bb5: { @@ -157,7 +157,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, bb6: { _13 = &mut (*_14); StorageDead(_15); - _9 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; + _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; } bb7: { @@ -186,7 +186,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, StorageDead(_4); StorageDead(_19); StorageDead(_20); - discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 3; + discriminant((*(_1.0: &mut {async fn body of b()}))) = 3; return; } @@ -199,7 +199,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, StorageDead(_12); StorageDead(_9); StorageDead(_8); - drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16})) -> [return: bb12, unwind unreachable]; + drop((((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()})) -> [return: bb12, unwind unreachable]; } bb11: { @@ -224,14 +224,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, } bb14: { - _21 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; + _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; } bb15: { StorageDead(_22); PlaceMention(_21); nop; - (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}) = move _21; + (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}) = move _21; goto -> bb16; } @@ -241,9 +241,9 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, StorageLive(_26); StorageLive(_27); StorageLive(_28); - _28 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}); + _28 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}); _27 = &mut (*_28); - _26 = Pin::<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; + _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; } bb17: { @@ -259,7 +259,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, bb18: { _29 = &mut (*_30); StorageDead(_31); - _25 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; + _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; } bb19: { @@ -283,7 +283,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, StorageDead(_21); StorageDead(_35); StorageDead(_36); - discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 4; + discriminant((*(_1.0: &mut {async fn body of b()}))) = 4; return; } @@ -296,7 +296,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, StorageDead(_28); StorageDead(_25); StorageDead(_24); - drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16})) -> [return: bb23, unwind unreachable]; + drop((((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind unreachable]; } bb22: { @@ -319,7 +319,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, bb25: { _0 = Poll::<()>::Ready(move _37); - discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 1; + discriminant((*(_1.0: &mut {async fn body of b()}))) = 1; return; } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index b189b4e73f4..0243e31cb1a 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -5,24 +5,24 @@ debug permit => (_1.0: ActionPermit<'_, T>); debug ctx => (*(_1.1: &mut std::task::Context<'_>)); let mut _0: (); - let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; + let mut _2: {async fn body of ActionPermit<'_, T>::perform()}; let mut _3: ActionPermit<'_, T>; - let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; + let mut _5: &mut {async fn body of ActionPermit<'_, T>::perform()}; let _6: (); let mut _7: std::task::Poll<()>; - let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>; + let mut _8: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; let mut _9: &mut std::task::Context<'_>; let mut _10: &mut std::task::Context<'_>; scope 1 { debug fut => _2; - let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>; + let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; scope 2 { debug fut => _4; scope 4 { } + scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) { + debug _task_context => _31; -+ debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>); ++ debug self => ((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})).0: ActionPermit<'_, T>); + let _11: ActionPermit<'_, T>; + let mut _12: std::future::Ready<()>; + let mut _13: std::future::Ready<()>; @@ -43,19 +43,19 @@ + let mut _30: (); + let mut _31: &mut std::task::Context<'_>; + let mut _32: u32; -+ let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; ++ let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()}; + scope 8 { -+ debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>); ++ debug self => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).0: ActionPermit<'_, T>); + let mut _15: std::future::Ready<()>; + scope 9 { -+ debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>); ++ debug __awaitee => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).1: std::future::Ready<()>); + let _26: (); + scope 10 { + } @@ -71,7 +71,7 @@ + } } scope 3 { -+ scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) { ++ scope 6 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) { + debug pointer => _5; + } } @@ -93,11 +93,11 @@ StorageLive(_4); StorageLive(_5); _5 = &mut _2; -- _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind unreachable]; +- _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked(move _5) -> [return: bb2, unwind unreachable]; - } - - bb2: { -+ _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 }; ++ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: _5 }; StorageDead(_5); StorageLive(_6); StorageLive(_7); @@ -106,7 +106,7 @@ StorageLive(_9); _10 = deref_copy (_1.1: &mut std::task::Context<'_>); _9 = &mut (*_10); -- _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable]; +- _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable]; + StorageLive(_11); + StorageLive(_15); + StorageLive(_16); @@ -123,7 +123,7 @@ + StorageLive(_38); + StorageLive(_39); + StorageLive(_40); -+ _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _32 = discriminant((*_33)); + switchInt(move _32) -> [0: bb3, 1: bb13, 3: bb12, otherwise: bb8]; } @@ -164,8 +164,8 @@ + bb3: { + _31 = move _9; -+ _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); -+ _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); ++ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>); + StorageLive(_12); + StorageLive(_13); @@ -183,7 +183,7 @@ - StorageDead(_2); - return; + StorageDead(_13); -+ _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + (((*_36) as variant#3).1: std::future::Ready<()>) = move _12; + goto -> bb5; + } @@ -194,7 +194,7 @@ + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); -+ _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); + _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb6, unwind unreachable]; @@ -236,7 +236,7 @@ + StorageDead(_12); + StorageDead(_28); + StorageDead(_29); -+ _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_38)) = 3; + goto -> bb2; + } @@ -251,13 +251,13 @@ + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind unreachable]; + } + + bb11: { + _7 = Poll::<()>::Ready(move _30); -+ _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_40)) = 1; + goto -> bb2; + } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index ed18c0a3adb..96a93cdda3d 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -5,24 +5,24 @@ debug permit => (_1.0: ActionPermit<'_, T>); debug ctx => (*(_1.1: &mut std::task::Context<'_>)); let mut _0: (); - let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; + let mut _2: {async fn body of ActionPermit<'_, T>::perform()}; let mut _3: ActionPermit<'_, T>; - let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; + let mut _5: &mut {async fn body of ActionPermit<'_, T>::perform()}; let _6: (); let mut _7: std::task::Poll<()>; - let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>; + let mut _8: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; let mut _9: &mut std::task::Context<'_>; let mut _10: &mut std::task::Context<'_>; scope 1 { debug fut => _2; - let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>; + let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; scope 2 { debug fut => _4; scope 4 { } + scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) { + debug _task_context => _31; -+ debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>); ++ debug self => ((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})).0: ActionPermit<'_, T>); + let _11: ActionPermit<'_, T>; + let mut _12: std::future::Ready<()>; + let mut _13: std::future::Ready<()>; @@ -43,21 +43,21 @@ + let mut _30: (); + let mut _31: &mut std::task::Context<'_>; + let mut _32: u32; -+ let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _41: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; -+ let mut _42: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}; ++ let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _41: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _42: &mut {async fn body of ActionPermit<'_, T>::perform()}; + scope 8 { -+ debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>); ++ debug self => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).0: ActionPermit<'_, T>); + let mut _15: std::future::Ready<()>; + scope 9 { -+ debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>); ++ debug __awaitee => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).1: std::future::Ready<()>); + let _26: (); + scope 10 { + } @@ -73,7 +73,7 @@ + } } scope 3 { -+ scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) { ++ scope 6 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) { + debug pointer => _5; + } } @@ -95,11 +95,11 @@ StorageLive(_4); StorageLive(_5); _5 = &mut _2; -- _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind: bb5]; +- _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked(move _5) -> [return: bb2, unwind: bb5]; - } - - bb2: { -+ _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 }; ++ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: _5 }; StorageDead(_5); StorageLive(_6); StorageLive(_7); @@ -108,7 +108,7 @@ StorageLive(_9); _10 = deref_copy (_1.1: &mut std::task::Context<'_>); _9 = &mut (*_10); -- _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5]; +- _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5]; + StorageLive(_11); + StorageLive(_15); + StorageLive(_16); @@ -127,7 +127,7 @@ + StorageLive(_40); + StorageLive(_41); + StorageLive(_42); -+ _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _32 = discriminant((*_33)); + switchInt(move _32) -> [0: bb5, 1: bb22, 2: bb21, 3: bb20, otherwise: bb10]; } @@ -181,8 +181,8 @@ - return; + bb5: { + _31 = move _9; -+ _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); -+ _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); ++ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>); + StorageLive(_12); + StorageLive(_13); @@ -200,7 +200,7 @@ - drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + bb6: { + StorageDead(_13); -+ _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + (((*_36) as variant#3).1: std::future::Ready<()>) = move _12; + goto -> bb7; } @@ -213,7 +213,7 @@ + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); -+ _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); + _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb8, unwind: bb15]; @@ -255,7 +255,7 @@ + StorageDead(_12); + StorageDead(_28); + StorageDead(_29); -+ _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_38)) = 3; + goto -> bb4; + } @@ -270,13 +270,13 @@ + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb13, unwind: bb19]; + } + + bb13: { + _7 = Poll::<()>::Ready(move _30); -+ _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_40)) = 1; + goto -> bb4; + } @@ -308,12 +308,12 @@ + + bb18 (cleanup): { + StorageDead(_12); -+ _41 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb19, unwind terminate(cleanup)]; + } + + bb19 (cleanup): { -+ _42 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}); ++ _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_42)) = 2; + goto -> bb2; + } diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index f1d18b0f7ff..f11c993340f 100644 --- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -26,18 +26,20 @@ _3 = _1; _2 = move _3 as [u32; 4] (Transmute); StorageDead(_3); - switchInt(_2[0 of 4]) -> [0: bb1, otherwise: bb6]; + switchInt(_2[0 of 4]) -> [0: bb1, otherwise: bb4]; } bb1: { - switchInt(_2[1 of 4]) -> [0: bb2, otherwise: bb6]; + switchInt(_2[1 of 4]) -> [0: bb2, otherwise: bb4]; } bb2: { - switchInt(_2[2 of 4]) -> [0: bb4, 4294901760: bb5, otherwise: bb6]; + switchInt(_2[2 of 4]) -> [0: bb3, 4294901760: bb3, otherwise: bb4]; } bb3: { + StorageLive(_4); + _4 = _2[3 of 4]; StorageLive(_5); StorageLive(_6); _6 = _4; @@ -46,27 +48,15 @@ _0 = Option::<[u8; 4]>::Some(move _5); StorageDead(_5); StorageDead(_4); - goto -> bb7; + goto -> bb5; } bb4: { - StorageLive(_4); - _4 = _2[3 of 4]; - goto -> bb3; - } - - bb5: { - StorageLive(_4); - _4 = _2[3 of 4]; - goto -> bb3; - } - - bb6: { _0 = Option::<[u8; 4]>::None; - goto -> bb7; + goto -> bb5; } - bb7: { + bb5: { StorageDead(_2); return; } diff --git a/tests/run-make/jobserver-error/Makefile b/tests/run-make/jobserver-error/Makefile index a7601b86715..9f34970f96f 100644 --- a/tests/run-make/jobserver-error/Makefile +++ b/tests/run-make/jobserver-error/Makefile @@ -4,9 +4,11 @@ include ../tools.mk # ignore-cross-compile # Test compiler behavior in case environment specifies wrong jobserver. +# Note that by default, the compiler uses file descriptors 0 (stdin), 1 (stdout), 2 (stderr), +# but also 3 and 4 for either end of the ctrl-c signal handler self-pipe. all: - bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr - + bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=5,5" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr - bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3</dev/null' 2>&1 | diff not_a_pipe.stderr - # This test randomly fails, see https://github.com/rust-lang/rust/issues/110321 diff --git a/tests/run-make/jobserver-error/cannot_open_fd.stderr b/tests/run-make/jobserver-error/cannot_open_fd.stderr index 343de5cd52c..7c421846535 100644 --- a/tests/run-make/jobserver-error/cannot_open_fd.stderr +++ b/tests/run-make/jobserver-error/cannot_open_fd.stderr @@ -1,4 +1,4 @@ -warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,3"`: cannot open file descriptor 3 from the jobserver environment variable value: Bad file descriptor (os error 9) +warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=5,5"`: cannot open file descriptor 5 from the jobserver environment variable value: Bad file descriptor (os error 9) | = note: the build environment is likely misconfigured diff --git a/tests/run-make/link-framework/Makefile b/tests/run-make/link-framework/Makefile new file mode 100644 index 00000000000..f33347ac7f8 --- /dev/null +++ b/tests/run-make/link-framework/Makefile @@ -0,0 +1,23 @@ +# only-macos +# +# Check that linking to a framework actually makes it to the linker. + +include ../tools.mk + +all: + $(RUSTC) dep-link-framework.rs + $(RUSTC) dep-link-weak-framework.rs + + $(RUSTC) empty.rs + otool -L $(TMPDIR)/no-link | $(CGREP) -v CoreFoundation + + $(RUSTC) link-framework.rs + otool -L $(TMPDIR)/link-framework | $(CGREP) CoreFoundation | $(CGREP) -v weak + + $(RUSTC) link-weak-framework.rs + otool -L $(TMPDIR)/link-weak-framework | $(CGREP) CoreFoundation | $(CGREP) weak + +# When linking the framework both normally, and weakly, the weak linking takes preference + + $(RUSTC) link-both.rs + otool -L $(TMPDIR)/link-both | $(CGREP) CoreFoundation | $(CGREP) weak diff --git a/tests/run-make/link-framework/dep-link-framework.rs b/tests/run-make/link-framework/dep-link-framework.rs new file mode 100644 index 00000000000..9bdeb2052d2 --- /dev/null +++ b/tests/run-make/link-framework/dep-link-framework.rs @@ -0,0 +1,4 @@ +#![crate_type = "rlib"] + +#[link(name = "CoreFoundation", kind = "framework")] +extern "C" {} diff --git a/tests/run-make/link-framework/dep-link-weak-framework.rs b/tests/run-make/link-framework/dep-link-weak-framework.rs new file mode 100644 index 00000000000..d3e1cf9c98f --- /dev/null +++ b/tests/run-make/link-framework/dep-link-weak-framework.rs @@ -0,0 +1,6 @@ +#![crate_type = "rlib"] +#![feature(link_arg_attribute)] + +#[link(name = "-weak_framework", kind = "link-arg", modifiers = "+verbatim")] +#[link(name = "CoreFoundation", kind = "link-arg", modifiers = "+verbatim")] +extern "C" {} diff --git a/tests/run-make/link-framework/empty.rs b/tests/run-make/link-framework/empty.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/run-make/link-framework/empty.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/link-framework/link-both.rs b/tests/run-make/link-framework/link-both.rs new file mode 100644 index 00000000000..31fc79e1929 --- /dev/null +++ b/tests/run-make/link-framework/link-both.rs @@ -0,0 +1,4 @@ +extern crate dep_link_framework; +extern crate dep_link_weak_framework; + +fn main() {} diff --git a/tests/run-make/link-framework/link-framework.rs b/tests/run-make/link-framework/link-framework.rs new file mode 100644 index 00000000000..e33e830248e --- /dev/null +++ b/tests/run-make/link-framework/link-framework.rs @@ -0,0 +1,3 @@ +extern crate dep_link_framework; + +fn main() {} diff --git a/tests/run-make/link-framework/link-weak-framework.rs b/tests/run-make/link-framework/link-weak-framework.rs new file mode 100644 index 00000000000..f0557f8013a --- /dev/null +++ b/tests/run-make/link-framework/link-weak-framework.rs @@ -0,0 +1,3 @@ +extern crate dep_link_weak_framework; + +fn main() {} diff --git a/tests/run-pass-valgrind/osx-frameworks.rs b/tests/run-pass-valgrind/osx-frameworks.rs deleted file mode 100644 index 71465c0d199..00000000000 --- a/tests/run-pass-valgrind/osx-frameworks.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ pretty-expanded FIXME #23616 - -#![feature(rustc_private)] - -extern crate libc; - -#[cfg(target_os = "macos")] -#[link(name = "CoreFoundation", kind = "framework")] -extern "C" { - fn CFRunLoopGetTypeID() -> libc::c_ulong; -} - -#[cfg(target_os = "macos")] -pub fn main() { - unsafe { - CFRunLoopGetTypeID(); - } -} - -#[cfg(not(target_os = "macos"))] -pub fn main() {} diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs new file mode 100644 index 00000000000..7df042d5f88 --- /dev/null +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs @@ -0,0 +1,30 @@ +// Regression test for issue #105056. +//@ edition: 2021 + +fn f(_: impl Trait<T = Copy>) {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP you might have meant to write a bound here +//~| ERROR the trait `Copy` cannot be made into an object + +fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP you might have meant to write a bound here +//~| ERROR only auto traits can be used as additional traits in a trait object +//~| HELP consider creating a new trait +//~| ERROR the trait `Eq` cannot be made into an object + +fn h(_: impl Trait<T<> = 'static + for<'a> Fn(&'a ())>) {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP you might have meant to write a bound here + +// Don't suggest assoc ty bound in trait object types, that's not valid: +type Obj = dyn Trait<T = Clone>; +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait + +trait Trait { type T; } + +fn main() {} diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr new file mode 100644 index 00000000000..13be2162c52 --- /dev/null +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr @@ -0,0 +1,91 @@ +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:20 + | +LL | fn f(_: impl Trait<T = Copy>) {} + | ^^^^^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:42 + | +LL | fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {} + | --------------- ^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Debug + Eq {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> + +error[E0038]: the trait `Eq` cannot be made into an object + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 + | +LL | fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {} + | ^^^^^^^^^^^^^^^^^^^^ `Eq` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: the trait cannot be made into an object because it uses `Self` as a type parameter + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:24 + | +LL | fn f(_: impl Trait<T = Copy>) {} + | ^^^^ + | +help: add `dyn` keyword before this trait + | +LL | fn f(_: impl Trait<T = dyn Copy>) {} + | +++ +help: you might have meant to write a bound here + | +LL | fn f(_: impl Trait<T: Copy>) {} + | ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 + | +LL | fn g(_: impl Trait<T = std::fmt::Debug + Eq>) {} + | ^^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | fn g(_: impl Trait<T = dyn std::fmt::Debug + Eq>) {} + | +++ +help: you might have meant to write a bound here + | +LL | fn g(_: impl Trait<T: std::fmt::Debug + Eq>) {} + | ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:18:26 + | +LL | fn h(_: impl Trait<T<> = 'static + for<'a> Fn(&'a ())>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | fn h(_: impl Trait<T<> = dyn 'static + for<'a> Fn(&'a ())>) {} + | +++ +help: you might have meant to write a bound here + | +LL | fn h(_: impl Trait<T<>: 'static + for<'a> Fn(&'a ())>) {} + | ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:24:26 + | +LL | type Obj = dyn Trait<T = Clone>; + | ^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | type Obj = dyn Trait<T = dyn Clone>; + | +++ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0038, E0225, E0782. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout index d6fb643702c..def967ba195 100644 --- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout +++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout @@ -1,17 +1,17 @@ -print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:21:21: 24:2}`: 3078 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of test()}`: 3078 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Suspend0`: 3077 bytes -print-type-size local `.__awaitee`: 3077 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2} +print-type-size local `.__awaitee`: 3077 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()} print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes -print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes print-type-size field `.value`: 3077 bytes -print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 3077 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 3077 bytes -print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}`: 3077 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 3077 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes @@ -20,29 +20,29 @@ print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 print-type-size padding: 1 bytes print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes print-type-size local `..coroutine_field4`: 1 bytes, type: bool -print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19} +print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()} print-type-size variant `Suspend1`: 3076 bytes print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size padding: 1026 bytes print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool -print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37} +print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body of big_fut()} print-type-size variant `Suspend2`: 2052 bytes print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size padding: 1 bytes print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes print-type-size local `..coroutine_field4`: 1 bytes, type: bool -print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19} +print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()} print-type-size variant `Returned`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes print-type-size variant `Panicked`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes -print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}>`: 1025 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes print-type-size field `.value`: 1025 bytes -print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}>`: 1025 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1025 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 1025 bytes -print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}`: 1025 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of big_fut()}`: 1025 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1024 bytes print-type-size upvar `.arg`: 1024 bytes @@ -52,13 +52,13 @@ print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.arg`: 1024 bytes print-type-size type: `std::mem::ManuallyDrop<bool>`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes -print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}>`: 1 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes print-type-size type: `std::mem::MaybeUninit<bool>`: 1 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 1 bytes -print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}>`: 1 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 1 bytes @@ -67,7 +67,7 @@ print-type-size discriminant: 1 bytes print-type-size variant `Ready`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size variant `Pending`: 0 bytes -print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}`: 1 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of wait()}`: 1 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Returned`: 0 bytes diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout index 589df102af4..67168a3d6ef 100644 --- a/tests/ui/async-await/future-sizes/large-arg.stdout +++ b/tests/ui/async-await/future-sizes/large-arg.stdout @@ -1,47 +1,47 @@ -print-type-size type: `{async fn body@$DIR/large-arg.rs:6:21: 8:2}`: 3076 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of test()}`: 3076 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Suspend0`: 3075 bytes -print-type-size local `.__awaitee`: 3075 bytes, type: {async fn body@$DIR/large-arg.rs:10:30: 12:2} +print-type-size local `.__awaitee`: 3075 bytes, type: {async fn body of a<[u8; 1024]>()} print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes -print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes print-type-size field `.value`: 3075 bytes -print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 3075 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 3075 bytes -print-type-size type: `{async fn body@$DIR/large-arg.rs:10:30: 12:2}`: 3075 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of a<[u8; 1024]>()}`: 3075 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size variant `Suspend0`: 3074 bytes print-type-size upvar `.t`: 1024 bytes -print-type-size local `.__awaitee`: 2050 bytes, type: {async fn body@$DIR/large-arg.rs:13:26: 15:2} +print-type-size local `.__awaitee`: 2050 bytes, type: {async fn body of b<[u8; 1024]>()} print-type-size variant `Returned`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.t`: 1024 bytes -print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:13:26: 15:2}>`: 2050 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes print-type-size field `.value`: 2050 bytes -print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:13:26: 15:2}>`: 2050 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 2050 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 2050 bytes -print-type-size type: `{async fn body@$DIR/large-arg.rs:13:26: 15:2}`: 2050 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of b<[u8; 1024]>()}`: 2050 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size variant `Suspend0`: 2049 bytes print-type-size upvar `.t`: 1024 bytes -print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/large-arg.rs:16:26: 18:2} +print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body of c<[u8; 1024]>()} print-type-size variant `Returned`: 1024 bytes print-type-size upvar `.t`: 1024 bytes print-type-size variant `Panicked`: 1024 bytes print-type-size upvar `.t`: 1024 bytes -print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:16:26: 18:2}>`: 1025 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes print-type-size field `.value`: 1025 bytes -print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:16:26: 18:2}>`: 1025 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1025 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 1025 bytes @@ -50,7 +50,7 @@ print-type-size discriminant: 1 bytes print-type-size variant `Ready`: 1024 bytes print-type-size field `.0`: 1024 bytes print-type-size variant `Pending`: 0 bytes -print-type-size type: `{async fn body@$DIR/large-arg.rs:16:26: 18:2}`: 1025 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of c<[u8; 1024]>()}`: 1025 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1024 bytes print-type-size upvar `.t`: 1024 bytes diff --git a/tests/ui/borrowck/cloning-in-async-block-121547.rs b/tests/ui/borrowck/cloning-in-async-block-121547.rs new file mode 100644 index 00000000000..b2d8dbae977 --- /dev/null +++ b/tests/ui/borrowck/cloning-in-async-block-121547.rs @@ -0,0 +1,11 @@ +//@ edition:2021 + +async fn clone_async_block(value: String) { + for _ in 0..10 { + async { //~ ERROR: use of moved value: `value` [E0382] + drop(value); + //~^ HELP: consider cloning the value if the performance cost is acceptable + }.await + } +} +fn main() {} diff --git a/tests/ui/borrowck/cloning-in-async-block-121547.stderr b/tests/ui/borrowck/cloning-in-async-block-121547.stderr new file mode 100644 index 00000000000..ae57e0018f8 --- /dev/null +++ b/tests/ui/borrowck/cloning-in-async-block-121547.stderr @@ -0,0 +1,22 @@ +error[E0382]: use of moved value: `value` + --> $DIR/cloning-in-async-block-121547.rs:5:9 + | +LL | async fn clone_async_block(value: String) { + | ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait +LL | for _ in 0..10 { + | -------------- inside of this loop +LL | / async { +LL | | drop(value); + | | ----- use occurs due to use in coroutine +LL | | +LL | | }.await + | |_________^ value moved here, in previous iteration of loop + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(value.clone()); + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/cfg/diagnostics-same-crate.rs b/tests/ui/cfg/diagnostics-same-crate.rs index 2d0907c6dfb..d9ff8d61e92 100644 --- a/tests/ui/cfg/diagnostics-same-crate.rs +++ b/tests/ui/cfg/diagnostics-same-crate.rs @@ -4,8 +4,12 @@ pub mod inner { //~^ NOTE found an item that was configured out #[cfg(FALSE)] - pub mod doesnt_exist { //~ NOTE found an item that was configured out + pub mod doesnt_exist { + //~^ NOTE found an item that was configured out + //~| NOTE found an item that was configured out + //~| NOTE found an item that was configured out pub fn hello() {} + pub mod hi {} } pub mod wrong { @@ -20,6 +24,15 @@ pub mod inner { } } +mod placeholder { + use super::inner::doesnt_exist; + //~^ ERROR unresolved import `super::inner::doesnt_exist` + //~| NOTE no `doesnt_exist` in `inner` + use super::inner::doesnt_exist::hi; + //~^ ERROR unresolved import `super::inner::doesnt_exist` + //~| NOTE could not find `doesnt_exist` in `inner` +} + #[cfg(i_dont_exist_and_you_can_do_nothing_about_it)] pub fn vanished() {} diff --git a/tests/ui/cfg/diagnostics-same-crate.stderr b/tests/ui/cfg/diagnostics-same-crate.stderr index 62a9d132de0..83a44587238 100644 --- a/tests/ui/cfg/diagnostics-same-crate.stderr +++ b/tests/ui/cfg/diagnostics-same-crate.stderr @@ -1,5 +1,29 @@ +error[E0432]: unresolved import `super::inner::doesnt_exist` + --> $DIR/diagnostics-same-crate.rs:28:9 + | +LL | use super::inner::doesnt_exist; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ no `doesnt_exist` in `inner` + | +note: found an item that was configured out + --> $DIR/diagnostics-same-crate.rs:7:13 + | +LL | pub mod doesnt_exist { + | ^^^^^^^^^^^^ + +error[E0432]: unresolved import `super::inner::doesnt_exist` + --> $DIR/diagnostics-same-crate.rs:31:23 + | +LL | use super::inner::doesnt_exist::hi; + | ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner` + | +note: found an item that was configured out + --> $DIR/diagnostics-same-crate.rs:7:13 + | +LL | pub mod doesnt_exist { + | ^^^^^^^^^^^^ + error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner` - --> $DIR/diagnostics-same-crate.rs:37:12 + --> $DIR/diagnostics-same-crate.rs:50:12 | LL | inner::doesnt_exist::hello(); | ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner` @@ -11,7 +35,7 @@ LL | pub mod doesnt_exist { | ^^^^^^^^^^^^ error[E0425]: cannot find function `uwu` in module `inner` - --> $DIR/diagnostics-same-crate.rs:32:12 + --> $DIR/diagnostics-same-crate.rs:45:12 | LL | inner::uwu(); | ^^^ not found in `inner` @@ -23,31 +47,31 @@ LL | pub fn uwu() {} | ^^^ error[E0425]: cannot find function `meow` in module `inner::right` - --> $DIR/diagnostics-same-crate.rs:41:19 + --> $DIR/diagnostics-same-crate.rs:54:19 | LL | inner::right::meow(); | ^^^^ not found in `inner::right` | note: found an item that was configured out - --> $DIR/diagnostics-same-crate.rs:18:16 + --> $DIR/diagnostics-same-crate.rs:22:16 | LL | pub fn meow() {} | ^^^^ = note: the item is gated behind the `what-a-cool-feature` feature error[E0425]: cannot find function `uwu` in this scope - --> $DIR/diagnostics-same-crate.rs:28:5 + --> $DIR/diagnostics-same-crate.rs:41:5 | LL | uwu(); | ^^^ not found in this scope error[E0425]: cannot find function `vanished` in this scope - --> $DIR/diagnostics-same-crate.rs:48:5 + --> $DIR/diagnostics-same-crate.rs:61:5 | LL | vanished(); | ^^^^^^^^ not found in this scope -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0425, E0433. +Some errors have detailed explanations: E0425, E0432, E0433. For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/consts/auxiliary/issue-63226.rs b/tests/ui/consts/auxiliary/issue-63226.rs index 2dc9539ba52..5bb0e694af7 100644 --- a/tests/ui/consts/auxiliary/issue-63226.rs +++ b/tests/ui/consts/auxiliary/issue-63226.rs @@ -2,13 +2,24 @@ pub struct VTable{ state:extern "C" fn(), } -impl VTable{ +impl VTable { pub const fn vtable()->&'static VTable{ Self::VTABLE } const VTABLE: &'static VTable = &VTable{state}; + + pub const VTABLE2: &'static VTable = + &VTable{state: state2}; } +pub const VTABLE3: &'static VTable = + &VTable{state: state3}; + +// Only referenced via a `pub const fn`, and yet reachable. extern "C" fn state() {} +// Only referenced via a associated `pub const`, and yet reachable. +extern "C" fn state2() {} +// Only referenced via a free `pub const`, and yet reachable. +extern "C" fn state3() {} diff --git a/tests/ui/consts/issue-63226.rs b/tests/ui/consts/issue-63226.rs index f8ceab33925..41e63c294ac 100644 --- a/tests/ui/consts/issue-63226.rs +++ b/tests/ui/consts/issue-63226.rs @@ -8,5 +8,7 @@ use issue_63226::VTable; static ICE_ICE:&'static VTable=VTable::vtable(); +static MORE_ICE:&'static VTable=VTable::VTABLE2; +static MORE_ICE3:&'static VTable=issue_63226::VTABLE3; fn main() {} diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs b/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs new file mode 100644 index 00000000000..d45e0bcd3b4 --- /dev/null +++ b/tests/ui/debuginfo/auxiliary/dylib-dep-helper-aux.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -g -Cstrip=none -Cforce-frame-pointers=yes + +#[inline(never)] +pub fn callback<F>(f: F) +where + F: FnOnce((&'static str, u32)), +{ + f((file!(), line!())) +} + +#[inline(always)] +pub fn callback_inlined<F>(f: F) +where + F: FnOnce((&'static str, u32)), +{ + f((file!(), line!())) +} diff --git a/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs b/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs new file mode 100644 index 00000000000..565d8b65de0 --- /dev/null +++ b/tests/ui/debuginfo/auxiliary/dylib-dep-helper.rs @@ -0,0 +1,19 @@ +//@ compile-flags: -g -Cstrip=none -Cforce-frame-pointers=yes + +#![crate_type = "cdylib"] +#![crate_type = "rlib"] + +#![allow(improper_ctypes_definitions)] + +type Pos = (&'static str, u32); + +macro_rules! pos { + () => { + (file!(), line!()) + }; +} + +#[no_mangle] +pub extern "C" fn foo(outer: Pos, inner: fn(Pos, Pos)) { + inner(outer, pos!()); +} diff --git a/tests/ui/debuginfo/backtrace-dylib-dep.rs b/tests/ui/debuginfo/backtrace-dylib-dep.rs new file mode 100644 index 00000000000..e2414073ede --- /dev/null +++ b/tests/ui/debuginfo/backtrace-dylib-dep.rs @@ -0,0 +1,114 @@ +// Check that backtrace info is correctly generated for dynamic libraries and is usable by a +// rust binary. +// Part of porting some backtrace tests to rustc: <https://github.com/rust-lang/rust/issues/122899>. +// Original test: +// <https://github.com/rust-lang/backtrace-rs/tree/6fa4b85b9962c3e1be8c2e5cc605cd078134152b/crates/dylib-dep> +// ignore-tidy-linelength +//@ ignore-android FIXME #17520 +//@ ignore-fuchsia Backtraces not symbolized +//@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written). +//@ needs-unwind +//@ compile-flags: -g -Copt-level=0 -Cstrip=none -Cforce-frame-pointers=yes +//@ aux-crate: dylib_dep_helper=dylib-dep-helper.rs +//@ aux-crate: auxiliary=dylib-dep-helper-aux.rs +//@ run-pass + +#![allow(improper_ctypes)] +#![allow(improper_ctypes_definitions)] + +extern crate dylib_dep_helper; +extern crate auxiliary; + +use std::backtrace::Backtrace; + +macro_rules! pos { + () => { + (file!(), line!()) + }; +} + +macro_rules! check { + ($($pos:expr),*) => ({ + verify(&[$($pos,)* pos!()]); + }) +} + +fn verify(filelines: &[Pos]) { + let trace = Backtrace::capture(); + eprintln!("-----------------------------------"); + eprintln!("looking for:"); + for (file, line) in filelines.iter().rev() { + eprintln!("\t{file}:{line}"); + } + eprintln!("found:\n{trace:#?}"); + let mut iter = filelines.iter().rev(); + // FIXME(jieyouxu): use proper `BacktraceFrame` accessors when it becomes available. Right now, + // this depends on the debug format of `Backtrace` which is of course fragile. + let backtrace = format!("{:#?}", trace); + while let Some((file, line)) = iter.next() { + // FIXME(jieyouxu): make this test use proper accessors on `BacktraceFrames` once it has + // them. + assert!(backtrace.contains(file), "expected backtrace to contain {}", file); + assert!(backtrace.contains(&line.to_string()), "expected backtrace to contain {}", line); + } +} + +type Pos = (&'static str, u32); + +extern "C" { + #[link_name = "foo"] + fn foo(p: Pos, cb: fn(Pos, Pos)); +} + +fn main() { + std::env::set_var("RUST_BACKTRACE", "1"); + + unsafe { + foo(pos!(), |a, b| { + check!(a, b) + }) + } + + outer(pos!()); +} + +#[inline(never)] +fn outer(main_pos: Pos) { + inner(main_pos, pos!()); + inner_inlined(main_pos, pos!()); +} + +#[inline(never)] +fn inner(main_pos: Pos, outer_pos: Pos) { + check!(main_pos, outer_pos); + check!(main_pos, outer_pos); + let inner_pos = pos!(); auxiliary::callback(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); +} + +#[inline(always)] +fn inner_inlined(main_pos: Pos, outer_pos: Pos) { + check!(main_pos, outer_pos); + check!(main_pos, outer_pos); + + #[inline(always)] + fn inner_further_inlined(main_pos: Pos, outer_pos: Pos, inner_pos: Pos) { + check!(main_pos, outer_pos, inner_pos); + } + inner_further_inlined(main_pos, outer_pos, pos!()); + + let inner_pos = pos!(); auxiliary::callback(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); auxiliary::callback_inlined(|aux_pos| { + check!(main_pos, outer_pos, inner_pos, aux_pos); + }); + + // this tests a distinction between two independent calls to the inlined function. + // (un)fortunately, LLVM somehow merges two consecutive such calls into one node. + inner_further_inlined(main_pos, outer_pos, pos!()); +} diff --git a/tests/ui/delegation/target-expr.rs b/tests/ui/delegation/target-expr.rs new file mode 100644 index 00000000000..b9c6fe92810 --- /dev/null +++ b/tests/ui/delegation/target-expr.rs @@ -0,0 +1,38 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait { + fn static_method(x: i32) -> i32 { x } +} + +struct F; + +struct S(F); +impl Trait for S {} + +fn foo(x: i32) -> i32 { x } + +fn bar<T: Default>(_: T) { + reuse Trait::static_method { + //~^ ERROR delegation with early bound generics is not supported yet + //~| ERROR mismatched types + let _ = T::Default(); + //~^ ERROR can't use generic parameters from outer item + } +} + +fn main() { + let y = 0; + reuse <S as Trait>::static_method { + let x = y; + //~^ ERROR can't capture dynamic environment in a fn item + foo(self); + + let reuse_ptr: fn(i32) -> i32 = static_method; + reuse_ptr(0) + } + self.0; + //~^ ERROR expected value, found module `self` + let z = x; + //~^ ERROR cannot find value `x` in this scope +} diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr new file mode 100644 index 00000000000..da0fac2f5e4 --- /dev/null +++ b/tests/ui/delegation/target-expr.stderr @@ -0,0 +1,65 @@ +error[E0401]: can't use generic parameters from outer item + --> $DIR/target-expr.rs:19:17 + | +LL | fn bar<T: Default>(_: T) { + | - type parameter from outer item +LL | reuse Trait::static_method { + | - help: try introducing a local generic parameter here: `T,` +... +LL | let _ = T::Default(); + | ^^^^^^^^^^ use of generic parameter from outer item + +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/target-expr.rs:27:17 + | +LL | let x = y; + | ^ + | + = help: use the `|| { ... }` closure form instead + +error[E0424]: expected value, found module `self` + --> $DIR/target-expr.rs:34:5 + | +LL | fn main() { + | ---- this function can't have a `self` parameter +... +LL | self.0; + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + +error[E0425]: cannot find value `x` in this scope + --> $DIR/target-expr.rs:36:13 + | +LL | let z = x; + | ^ + | +help: the binding `x` is available in a different scope in the same function + --> $DIR/target-expr.rs:27:13 + | +LL | let x = y; + | ^ + +error: delegation with early bound generics is not supported yet + --> $DIR/target-expr.rs:16:18 + | +LL | fn static_method(x: i32) -> i32 { x } + | ------------------------------- callee defined here +... +LL | reuse Trait::static_method { + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/target-expr.rs:16:32 + | +LL | reuse Trait::static_method { + | ________________________________^ +LL | | +LL | | +LL | | let _ = T::Default(); +LL | | +LL | | } + | |_____^ expected `i32`, found `()` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0401, E0424, E0425, E0434. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-const-items/hkl_where_bounds.rs b/tests/ui/generic-const-items/hkl_where_bounds.rs new file mode 100644 index 00000000000..cded518312a --- /dev/null +++ b/tests/ui/generic-const-items/hkl_where_bounds.rs @@ -0,0 +1,14 @@ +//! Test that nonsense bounds prevent consts from being evaluated at all. +//@ check-pass + +#![feature(generic_const_items)] +#![allow(incomplete_features)] +trait Trait { + const ASSOC: u32; +} + +// rustfmt eats the where bound +#[rustfmt::skip] +const ASSOC: u32 = <&'static ()>::ASSOC where for<'a> &'a (): Trait; + +fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/future.current.stderr b/tests/ui/higher-ranked/trait-bounds/future.current.stderr index 5a6381ad28e..673bc48a424 100644 --- a/tests/ui/higher-ranked/trait-bounds/future.current.stderr +++ b/tests/ui/higher-ranked/trait-bounds/future.current.stderr @@ -1,6 +1,6 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body@$DIR/future.rs:33:35: 35:2}: core::future::future::Future` +#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body of strlen()}: core::future::future::Future` #1 [codegen_select_candidate] computing candidate for `<strlen as Trait>` end of query stack diff --git a/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.rs b/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.rs new file mode 100644 index 00000000000..7445d8dc51e --- /dev/null +++ b/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.rs @@ -0,0 +1,78 @@ +// ICE: failed to get layout for [type error] +// issue: rust-lang/rust#92979 + +use std::fs; +use std::fs::File; +use std::io::Read; +use std::convert::TryInto; + +fn get_file_as_byte_vec(filename: &String) -> Vec<u8> { + let mut f = File::open(&filename).expect("no file found"); + let metadata = fs::metadata(&filename).expect("unable to read metadata"); + let mut buffer = vec![0; metadata.len() as usize]; + f.read(&mut buffer).expect("buffer overflow"); + + buffer +} + + + +fn demo<T, const N: usize>(v: Vec<T>) -> [T; N] { + v.try_into() + .unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len())) +} + + +fn main() { + + // Specify filepath + let file: &String = &String::from("SomeBinaryDataFileWith4ByteHeaders_f32s_and_u32s"); + + // Read file into a vector of bytes + let file_data = get_file_as_byte_vec(file); + + // Print length of vector and first few values + let length = file_data.len(); + println!("The read function read {} bytes", length); + println!("The first few bytes:"); + for i in 0..20{ + println!("{}", file_data[i]); + } + + // Manually count just to make sure + let mut n: u64 = 0; + for data in file_data{ + n += 1; + } + println!("We counted {} bytes", n); + assert!(n as usize == length, "Manual counting does not equal len method"); + + // Simulation parameters + const N: usize = 49627502; // Number of Particles + const bs: f64 = 125.0; // Box Size + const HEADER_INCREMENT: u64 = 4*1; + + // Initialize index and counter variables + let (mut j, mut pos, mut vel, mut id, mut mass): (u64, u64, u64, u64, u64) = (0, 0, 0, 0, 0); + + // Unpack Position Data + j += HEADER_INCREMENT; + let mut position: Vec<f32> = Vec::new(); + while position.len() < N*3 { + + let p: Vec<u8> = Vec::new(); + for item in 0i8..4 { + let item = item; + p.push(file_data[j as usize]); + j += 1; + } + &mut position[position.len()] = f32::from_be_bytes(demo(p)); + //~^ ERROR invalid left-hand side of assignment + } + + // Ensure position data is indeed position by checking values + for p in position { + assert!((p > 0.) & (p < 125.), "Not in box") + } + +} diff --git a/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.stderr b/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.stderr new file mode 100644 index 00000000000..a6b9e376896 --- /dev/null +++ b/tests/ui/layout/failed-to-get-layout-for-type-error-ice-92979.stderr @@ -0,0 +1,16 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/failed-to-get-layout-for-type-error-ice-92979.rs:69:39 + | +LL | &mut position[position.len()] = f32::from_be_bytes(demo(p)); + | ----------------------------- ^ + | | + | cannot assign to this expression + | +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *&mut position[position.len()] = f32::from_be_bytes(demo(p)); + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs new file mode 100644 index 00000000000..6380449124f --- /dev/null +++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.rs @@ -0,0 +1,59 @@ +// ICE argument to function with "rust-call" ABI is not a tuple +// issue: rust-lang/rust#81974 + +#![feature(unboxed_closures)] +#![feature(fn_traits)] + +use std::collections::HashMap; +use std::hash::Hash; + +struct CachedFun<A, B> { + cache: HashMap<A, B>, + fun: fn(&mut CachedFun<A, B>, A) -> B, +} + +impl<A: Eq + Hash, B> CachedFun<A, B> { + fn new(fun: fn(&mut Self, A) -> B) -> Self { + CachedFun { + cache: HashMap::new(), + fun, + } + } +} + +impl<A, B> FnOnce<A> for CachedFun<A, B> +//~^ ERROR type parameter to bare `FnOnce` trait must be a tuple +where + A: Eq + Hash + Clone, + B: Clone, +{ + type Output = B; + extern "rust-call" fn call_once(mut self, a: A) -> Self::Output { + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument + self.call_mut(a) + //~^ ERROR `A` is not a tuple + } +} + +impl<A, B> FnMut<A> for CachedFun<A, B> +//~^ ERROR type parameter to bare `FnMut` trait must be a tuple +where + A: Eq + Hash + Clone, + B: Clone, +{ + extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output { + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument + self.cache.get(&a).map(|a| a.clone()).unwrap_or_else(|| { + let b = (self.fun)(self, a.clone()); + self.cache.insert(a, b.clone()); + b + }) + } +} + +fn main() -> () { + let pesce = |y: &mut CachedFun<i32, i32>, x| x + 1; + let cachedcoso = CachedFun::new(pesce); + cachedcoso.call_once(1); + //~^ ERROR `i32` is not a tuple +} diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr new file mode 100644 index 00000000000..cceaddf7803 --- /dev/null +++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr @@ -0,0 +1,78 @@ +error[E0059]: type parameter to bare `FnOnce` trait must be a tuple + --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:24:12 + | +LL | impl<A, B> FnOnce<A> for CachedFun<A, B> + | ^^^^^^^^^ the trait `Tuple` is not implemented for `A` + | +note: required by a bound in `FnOnce` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL +help: consider further restricting this bound + | +LL | A: Eq + Hash + Clone + std::marker::Tuple, + | ++++++++++++++++++++ + +error[E0059]: type parameter to bare `FnMut` trait must be a tuple + --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:38:12 + | +LL | impl<A, B> FnMut<A> for CachedFun<A, B> + | ^^^^^^^^ the trait `Tuple` is not implemented for `A` + | +note: required by a bound in `FnMut` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL +help: consider further restricting this bound + | +LL | A: Eq + Hash + Clone + std::marker::Tuple, + | ++++++++++++++++++++ + +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:31:5 + | +LL | extern "rust-call" fn call_once(mut self, a: A) -> Self::Output { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A` + | +help: consider further restricting this bound + | +LL | A: Eq + Hash + Clone + std::marker::Tuple, + | ++++++++++++++++++++ + +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:44:5 + | +LL | extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A` + | +help: consider further restricting this bound + | +LL | A: Eq + Hash + Clone + std::marker::Tuple, + | ++++++++++++++++++++ + +error[E0277]: `A` is not a tuple + --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:33:23 + | +LL | self.call_mut(a) + | -------- ^ the trait `Tuple` is not implemented for `A` + | | + | required by a bound introduced by this call + | +note: required by a bound in `call_mut` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL +help: consider further restricting this bound + | +LL | A: Eq + Hash + Clone + std::marker::Tuple, + | ++++++++++++++++++++ + +error[E0277]: `i32` is not a tuple + --> $DIR/rust-call-abi-not-a-tuple-ice-81974.rs:57:26 + | +LL | cachedcoso.call_once(1); + | --------- ^ the trait `Tuple` is not implemented for `i32` + | | + | required by a bound introduced by this call + | +note: required by a bound in `call_once` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0059, E0277. +For more information about an error, try `rustc --explain E0059`. diff --git a/tests/ui/linkage-attr/framework.omit.stderr b/tests/ui/linkage-attr/framework.omit.stderr new file mode 100644 index 00000000000..5cb4d391437 --- /dev/null +++ b/tests/ui/linkage-attr/framework.omit.stderr @@ -0,0 +1,8 @@ +error: linking with `cc` failed: exit status: 1 + | + ld: Undefined symbols: + _CFRunLoopGetTypeID, referenced from: + clang: error: linker command failed with exit code 1 (use -v to see invocation) + + +error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/framework.rs b/tests/ui/linkage-attr/framework.rs new file mode 100644 index 00000000000..662ef4c429d --- /dev/null +++ b/tests/ui/linkage-attr/framework.rs @@ -0,0 +1,30 @@ +// Check that linking frameworks on Apple platforms works. +//@ only-macos +//@ revisions: omit link weak both +//@ [omit]build-fail +//@ [link]run-pass +//@ [weak]run-pass +//@ [both]run-pass + +// The linker's exact error output changes between Xcode versions. +//@ compare-output-lines-by-subset +//@ normalize-stderr-test: "Undefined symbols for architecture .*" -> "ld: Undefined symbols:" +//@ normalize-stderr-test: "._CFRunLoopGetTypeID.," -> "_CFRunLoopGetTypeID," + +#![cfg_attr(any(weak, both), feature(link_arg_attribute))] + +#[cfg_attr(any(link, both), link(name = "CoreFoundation", kind = "framework"))] +#[cfg_attr( + any(weak, both), + link(name = "-weak_framework", kind = "link-arg", modifiers = "+verbatim"), + link(name = "CoreFoundation", kind = "link-arg", modifiers = "+verbatim") +)] +extern "C" { + fn CFRunLoopGetTypeID() -> core::ffi::c_ulong; +} + +pub fn main() { + unsafe { + CFRunLoopGetTypeID(); + } +} diff --git a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs index 558fcdfe177..cb65f80b089 100644 --- a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs +++ b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs @@ -1,6 +1,6 @@ #[cfg(FALSE)] fn syntax() { - bar::<Item = 'a>(); //~ ERROR associated lifetimes are not supported + bar::<Item = 'a>(); //~ ERROR lifetimes are not permitted in this context } fn main() {} diff --git a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr index 39a6682fcae..606b737e723 100644 --- a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr +++ b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.stderr @@ -1,12 +1,17 @@ -error: associated lifetimes are not supported - --> $DIR/recover-assoc-lifetime-constraint.rs:3:11 +error: lifetimes are not permitted in this context + --> $DIR/recover-assoc-lifetime-constraint.rs:3:18 | LL | bar::<Item = 'a>(); - | ^^^^^^^-- - | | - | the lifetime is given here + | -------^^ + | | | + | | lifetime is not allowed here + | this introduces an associated item binding | - = help: if you meant to specify a trait object, write `dyn Trait + 'lifetime` + = help: if you meant to specify a trait object, write `dyn /* Trait */ + 'a` +help: you might have meant to write a bound here + | +LL | bar::<Item: 'a>(); + | ~ error: aborting due to 1 previous error diff --git a/tests/ui/pattern/deref-patterns/ref-mut.rs b/tests/ui/pattern/deref-patterns/ref-mut.rs new file mode 100644 index 00000000000..1918008a761 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/ref-mut.rs @@ -0,0 +1,17 @@ +#![feature(deref_patterns)] +//~^ WARN the feature `deref_patterns` is incomplete + +use std::rc::Rc; + +fn main() { + match &mut vec![1] { + deref!(x) => {} + _ => {} + } + + match &mut Rc::new(1) { + deref!(x) => {} + //~^ ERROR the trait bound `Rc<{integer}>: DerefMut` is not satisfied + _ => {} + } +} diff --git a/tests/ui/pattern/deref-patterns/ref-mut.stderr b/tests/ui/pattern/deref-patterns/ref-mut.stderr new file mode 100644 index 00000000000..41f1c3061ce --- /dev/null +++ b/tests/ui/pattern/deref-patterns/ref-mut.stderr @@ -0,0 +1,20 @@ +warning: the feature `deref_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/ref-mut.rs:1:12 + | +LL | #![feature(deref_patterns)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #87121 <https://github.com/rust-lang/rust/issues/87121> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `Rc<{integer}>: DerefMut` is not satisfied + --> $DIR/ref-mut.rs:13:9 + | +LL | deref!(x) => {} + | ^^^^^^^^^ the trait `DerefMut` is not implemented for `Rc<{integer}>` + | + = note: this error originates in the macro `deref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout index 1df4d85d09e..83a6962e4cd 100644 --- a/tests/ui/print_type_sizes/async.stdout +++ b/tests/ui/print_type_sizes/async.stdout @@ -1,11 +1,11 @@ -print-type-size type: `{async fn body@$DIR/async.rs:10:36: 13:2}`: 16386 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of test()}`: 16386 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 8192 bytes print-type-size upvar `.arg`: 8192 bytes print-type-size variant `Suspend0`: 16385 bytes print-type-size upvar `.arg`: 8192 bytes print-type-size local `.arg`: 8192 bytes -print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async.rs:8:17: 8:19} +print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()} print-type-size variant `Returned`: 8192 bytes print-type-size upvar `.arg`: 8192 bytes print-type-size variant `Panicked`: 8192 bytes @@ -16,9 +16,9 @@ print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment print-type-size variant `MaybeUninit`: 8192 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 8192 bytes -print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async.rs:8:17: 8:19}>`: 1 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes -print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async.rs:8:17: 8:19}>`: 1 bytes, alignment: 1 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes print-type-size variant `MaybeUninit`: 1 bytes print-type-size field `.uninit`: 0 bytes print-type-size field `.value`: 1 bytes @@ -27,7 +27,7 @@ print-type-size discriminant: 1 bytes print-type-size variant `Ready`: 0 bytes print-type-size field `.0`: 0 bytes print-type-size variant `Pending`: 0 bytes -print-type-size type: `{async fn body@$DIR/async.rs:8:17: 8:19}`: 1 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of wait()}`: 1 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Returned`: 0 bytes diff --git a/tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs b/tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs new file mode 100644 index 00000000000..dd604b6bf7d --- /dev/null +++ b/tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs @@ -0,0 +1,38 @@ +// Regression test for issue 123053, where associated types with lifetimes caused generation of the +// trait object type to fail, causing an ICE. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021 +//@ no-prefer-dynamic +//@ only-x86_64-unknown-linux-gnu +//@ build-pass + +trait Iterable { + type Item<'a> + where + Self: 'a; + type Iter<'a>: Iterator<Item = Self::Item<'a>> + where + Self: 'a; + + fn iter<'a>(&'a self) -> Self::Iter<'a>; +} + +impl<T> Iterable for [T] { + type Item<'a> = <std::slice::Iter<'a, T> as Iterator>::Item where T: 'a; + type Iter<'a> = std::slice::Iter<'a, T> where T: 'a; + + fn iter<'a>(&'a self) -> Self::Iter<'a> { + self.iter() + } +} + +fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option<I::Item<'a>> { + it.iter().next() +} + +fn main() { + let v = vec![1, 2, 3]; + + assert_eq!(Some(&1), get_first(&*v)); +} diff --git a/tests/ui/traits/trait-selection-ice-84727.rs b/tests/ui/traits/trait-selection-ice-84727.rs new file mode 100644 index 00000000000..08a282892a5 --- /dev/null +++ b/tests/ui/traits/trait-selection-ice-84727.rs @@ -0,0 +1,38 @@ +// ICE Where clause `Binder(..)` was applicable to `Obligation(..)` but now is not +// issue: rust-lang/rust#84727 + +struct Cell<Fg, Bg = Fg> { + foreground: Color<Fg>, + //~^ ERROR cannot find type `Color` in this scope + background: Color<Bg>, + //~^ ERROR cannot find type `Color` in this scope +} + +trait Over<Bottom, Output> { + fn over(self) -> Output; +} + +impl<TopFg, TopBg, BottomFg, BottomBg, NewFg, NewBg> + Over<Cell<BottomFg, BottomBg>, Cell<NewFg, NewBg>> for Cell<TopFg, TopBg> +where + Self: Over<Color<BottomBg>, Cell<NewFg>>, + //~^ ERROR cannot find type `Color` in this scope +{ + fn over(self) -> Cell<NewFg> { + //~^ ERROR mismatched types + self.over(); + } +} + +impl<'b, TopFg, TopBg, BottomFg, BottomBg> Over<&Cell<BottomFg, BottomBg>, ()> + for Cell<TopFg, TopBg> +where + Cell<TopFg, TopBg>: Over<Cell<BottomFg>, Cell<BottomFg>>, +{ + fn over(self) -> Cell<NewBg> { + //~^ ERROR cannot find type `NewBg` in this scope + self.over(); + } +} + +pub fn main() {} diff --git a/tests/ui/traits/trait-selection-ice-84727.stderr b/tests/ui/traits/trait-selection-ice-84727.stderr new file mode 100644 index 00000000000..d4bc4163897 --- /dev/null +++ b/tests/ui/traits/trait-selection-ice-84727.stderr @@ -0,0 +1,47 @@ +error[E0412]: cannot find type `Color` in this scope + --> $DIR/trait-selection-ice-84727.rs:5:17 + | +LL | foreground: Color<Fg>, + | ^^^^^ not found in this scope + +error[E0412]: cannot find type `Color` in this scope + --> $DIR/trait-selection-ice-84727.rs:7:17 + | +LL | background: Color<Bg>, + | ^^^^^ not found in this scope + +error[E0412]: cannot find type `Color` in this scope + --> $DIR/trait-selection-ice-84727.rs:18:16 + | +LL | Self: Over<Color<BottomBg>, Cell<NewFg>>, + | ^^^^^ not found in this scope + +error[E0412]: cannot find type `NewBg` in this scope + --> $DIR/trait-selection-ice-84727.rs:32:27 + | +LL | fn over(self) -> Cell<NewBg> { + | ^^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl<'b, TopFg, TopBg, BottomFg, BottomBg, NewBg> Over<&Cell<BottomFg, BottomBg>, ()> + | +++++++ + +error[E0308]: mismatched types + --> $DIR/trait-selection-ice-84727.rs:21:22 + | +LL | fn over(self) -> Cell<NewFg> { + | ---- ^^^^^^^^^^^ expected `Cell<NewFg>`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | +LL | self.over(); + | - help: remove this semicolon to return this value + | + = note: expected struct `Cell<NewFg>` + found unit type `()` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0412. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr index d7a0452727e..cd4982b2480 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr @@ -10,7 +10,7 @@ error: concrete type differs from previous defining opaque type use --> $DIR/hkl_forbidden4.rs:13:1 | LL | async fn operation(_: &mut ()) -> () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body@$DIR/hkl_forbidden4.rs:13:38: 16:2}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}` | note: previous use here --> $DIR/hkl_forbidden4.rs:15:5 diff --git a/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs new file mode 100644 index 00000000000..109a70c766d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs @@ -0,0 +1,26 @@ +//@ check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl<R: Duh, F: FnMut() -> R> Trait for F { + type Assoc = R; +} + +type Sendable = impl Send + Duh; + +type Foo = impl Trait<Assoc = Sendable>; + +fn foo() -> Foo { + || 42 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.rs b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.rs new file mode 100644 index 00000000000..4f9d54737dc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.rs @@ -0,0 +1,29 @@ +//@ check-pass + +// See https://doc.rust-lang.org/1.77.0/nightly-rustc/rustc_lint/opaque_hidden_inferred_bound/static.OPAQUE_HIDDEN_INFERRED_BOUND.html#example + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl<R: Duh, F: FnMut() -> R> Trait for F { + type Assoc = R; +} + +type Sendable = impl Send; + +type Foo = impl Trait<Assoc = Sendable>; + //~^ WARNING opaque type `Foo` does not satisfy its associated type bounds + +fn foo() -> Foo { + || 42 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.stderr b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.stderr new file mode 100644 index 00000000000..68def454c7f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903.stderr @@ -0,0 +1,13 @@ +warning: opaque type `Foo` does not satisfy its associated type bounds + --> $DIR/tait-in-function-return-type-issue-101903.rs:22:23 + | +LL | type Assoc: Duh; + | --- this associated type bound is unsatisfied for `Sendable` +... +LL | type Foo = impl Trait<Assoc = Sendable>; + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(opaque_hidden_inferred_bound)]` on by default + +warning: 1 warning emitted + diff --git a/triagebot.toml b/triagebot.toml index a42bafe148c..62a706fafe1 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -424,7 +424,15 @@ message_on_reopen = "Issue #{number} has been reopened. Pinging @*T-types*." [notify-zulip."A-edition-2021"] required_labels = ["C-bug"] -zulip_stream = 268952 # #edition 2021 +zulip_stream = 268952 # #edition +topic = "Edition Bugs" +message_on_add = """\ +Issue #{number} "{title}" has been added (previous edition 2021). +""" + +[notify-zulip."A-edition-2024"] +required_labels = ["C-bug"] +zulip_stream = 268952 # #edition topic = "Edition Bugs" message_on_add = """\ Issue #{number} "{title}" has been added. |
