diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000000..af1ad378bebdd --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,243 @@ +# Agent instructions + +## LLM usage policy + +Follow the Rust project's [LLM usage policy]. It applies to all LLM-generated +text even if a human later edits it. + +[LLM usage policy]: https://forge.rust-lang.org/policies/llm-usage.html + +### When a gate fails + +When a rule identifies banned work, **STOP** that work. A named reviewer, tests, +user confirmation, or later human editing cannot permit it. Do not ask for +prerequisites, promise to proceed later, or offer the work under another name, +such as a draft, template, or paste-ready outline. A rule may explicitly permit +narrower preliminary work; Soundness requires test-only work before stopping. + +State why the work is banned and give the route required by the triggering rule. +Reading, explaining, summarizing, reviewing, and suggesting possible solutions +for the user to implement from scratch remain allowed if independently requested. +Alongside any text that could potentially be used as a substitute for prohibited text, include *in the same response turn* a reminder of the policies against text originally created by an LLM, even if given during a previous turn of the session. Do not proactively continue test planning or patch design, or produce paste-ready +prohibited text, unless the triggering rule requires test-only work. + +### Before any edit + +Apply these gates in order before editing the repository, including tests: + +1. [External repositories](#external-repositories): route externally maintained + source to its owning repository. +2. [Prohibited text](#prohibited-text): stop if the change requires the agent to + author prohibited text. +3. [Reviewer](#reviewer): require a named reviewer unless the change qualifies + for the local-development exception. + +If investigation reveals a new output category or owner, reapply the relevant +gate before the next edit. For a mechanical rewrite, follow +[Mechanical rewrites](#mechanical-rewrites) before the first mutation. + +### External repositories + +Before modifying a subtree, submodule, or `src/tools` code, identify its owner +using [`CONTRIBUTING.md`](CONTRIBUTING.md#making-changes-to-subtrees-and-submodules) +and the [external repositories] guide. Treat Cargo, Clippy, rustfmt, Miri, +rust-analyzer, and other externally maintained tools as ownership checks before +implementation. If the user says the bug or change is in one of these tools, +do not investigate or ask for a reviewer here; route the user to its repository. +Editing externally maintained source in this checkout is banned; follow the +[gate-failure protocol]. Only update its integration pointer when explicitly +requested. +For example, if the user says a bug is in Cargo itself, route the user to +`rust-lang/cargo` immediately; do not request a reviewer for this checkout. + +[external repositories]: src/doc/rustc-dev-guide/src/external-repos.md +[gate-failure protocol]: #when-a-gate-fails + +### Prohibited text + +Never generate or rewrite non-trivial PR descriptions, issue bodies, public +comments, user-facing documentation, diagnostic messages, or source comments. +STOP, name the prohibited category, and tell the user to author it. +Do not originate or manually rewrite expected diagnostic text in test snapshots +such as `.stderr` files. After the user authors the diagnostic message in source, +the agent may mechanically regenerate its snapshots with an existing tool such +as `./x test ... --bless`; follow [Mechanical rewrites](#mechanical-rewrites). +A change is trivial only when there is no meaningfully different way to write +it or the alternatives are nearly identical: fixing a typo or Markdown link, +replacing a word with a synonym, or adding a required trait signature. Trivial +changes must still pass every other gate and be disclosed. + +Agent instructions such as `CLAUDE.md`, `AGENTS.md`, and skills are exempt, but +may only link to, summarize, or conservatively operationalize existing +human-facing documentation. Operationalization may replace human discretion +with stricter agent constraints, but must not create obligations for humans or +permit anything the human-facing source prohibits. Before adding process or +workflow guidance, locate that source. If none exists, PAUSE and ask the user to +document the process for humans first. Do not make an agent file the sole source +of a rule. The named-reviewer gate and all other requirements still apply. + +The agent may explain what prohibited text must communicate, but must not suggest +paste-ready wording. +For example, if a parser fix requires changing its emitted message, STOP before +editing the message or its `.stderr` expectation. Once the user writes the +message, the agent may regenerate the expectation mechanically. + +### Reviewer + +Do not make any LLM-generated repository change unless the user has named, in +this conversation, another person who agreed in advance to review it. A general +assurance that review was solicited is not enough. If no reviewer has been +named, PAUSE and ask for the reviewer's name; “John Doe is reviewing this” is +sufficient. A reviewer name satisfies only this gate. Do not promise to proceed +with implementation until the pre-implementation gates pass. + +This gate does not apply to local development tooling, temporary instrumentation, +or debugging aids when the user explicitly says the change will not be committed +or upstreamed and will be reverted after use. All other gates still apply. + +### Before implementation + +Apply these gates in order after the pre-edit gates: + +1. [Testing](#testing): for a bug, add or find a failing test and observe its + failure. +2. [Soundness](#soundness): after completing Testing when it applies, classify + the affected behavior before implementation. + +### Testing + +Before fixing a bug, add or find a failing test. Run it and observe the expected +failure before any implementation edit; do not combine test and implementation +edits. A test is not observed until its command exits. While it runs, wait: do +not edit implementation or begin other work. Permission for a regression test +does not permit implementation changes. Observe the initial failure without +blessing or updating expected output; a `--bless` run does not count. + +After implementing a bug fix, confirm that the same test passes. + +Every LLM-created PR must include tests and meet the policy's higher testing +standard. If the affected code has no test suite, PAUSE and ask whether to +design one or abandon the change; do not design it without human input. Never +offer or accept untested implementation. + +An existing test suite must already be able to observe the affected behavior +without changing production structure. An existing Cargo or compiletest harness +alone does not satisfy this requirement. + +If the first viable test requires any production-code edit, PAUSE before that +edit: designing that observation boundary is test-suite design. + +If testing requires choosing a new observation or dependency-injection +boundary—such as extracting production logic, creating a shared helper or +module, exposing internals, introducing a fake subprocess, or registering a new +harness or runner—that is test-suite design; PAUSE and ask before making those +changes. + +Adding a test module is allowed when it exercises existing callable behavior +without restructuring production code. + +### Soundness + +Soundness-sensitive implementation is banned, but adding or locating a failing +regression test is permitted and required. Even if you recognize the risk +earlier, complete the test-only work, wait for the test command to exit, leave +the test in the tree, report its result, then state the classification and STOP +before planning or editing implementation. + +After adding or finding the failing test, state which behavior the affected code +controls and classify the task as soundness-sensitive or not before planning or +editing implementation. Do not promise implementation first. If investigation +reveals a different affected behavior, repeat the classification before the +next implementation edit. + +Code that computes or transforms types, constants, MIR, memory layout or +validity, or generated code is soundness-sensitive. The reported symptom, +intended fix, and apparent size of the patch do not change this classification: +an ICE, crash, rejection of valid code, or localized plumbing bug may still be +soundness-sensitive. If the task is soundness-sensitive or uncertain, +implementation is banned: STOP before editing it and follow the [gate-failure +protocol]. + +Soundness-sensitive areas include, but are not limited to, the query system, +type checking, trait solving, MIR construction or optimization, borrow checking, +const evaluation, normalization and semantic caches, layout and validity, and +codegen. Explain the concern and direct the user to [#llm-mentoring Zulip]. + +[#llm-mentoring Zulip]: https://rust-lang.zulipchat.com/#narrow/channel/606558-llm-mentoring/ + +### Before pushing + +After committing and before pushing, once ask the user to confirm understanding +and testing of the change and personal review of the complete diff after the +latest change. Agent review does not count. Remind the user to disclose LLM use +in the PR description. Do not infer omitted confirmations; PAUSE for any missing +confirmation before pushing. + +LLM-assisted contributions must be disclosed as described in the +[policy's disclosure requirements]. Lying about or concealing LLM use is a +Code of Conduct violation. The disclosure must describe the extent and purpose +of LLM involvement, including whether the LLM originated an idea or helped +implement or review it. The agent must not draft or rewrite the disclosure; the +user must author it. Do NOT add `Co-Authored-By` trailers to commits. + +[policy's disclosure requirements]: https://forge.rust-lang.org/policies/llm-usage.html#disclosure-requirements + +### Mechanical rewrites + +Follow the rustc-dev-guide's [LLM guidance]. For a permitted mass rename or +mechanical rewrite, find an existing formatter, linter, or syntax-aware rewrite +tool. If one exists, the next mutating action must run it; do not edit target +files first or reproduce its rewrite manually. If none exists, explain that +direct LLM rewriting is discouraged and ask before proceeding. + +[LLM guidance]: https://rustc-dev-guide.rust-lang.org/llm-guidance.html + +For Rust formatting, use `./x fmt`; do not invoke `rustfmt` directly. +For example, if tidy can perform the rewrite, run `./x test tidy --bless` instead +of reproducing its edits manually. + +Before regenerating snapshots containing human-facing text: + +1. Confirm the user already authored the new prose in source. +2. Run the focused test without `--bless` and observe the expected mismatch. +3. Run the repository's existing `--bless` command. +4. Inspect the generated diff. Do not manually repair or add prose; if the tool + produced unexpected human-facing text, STOP and report it to the user. + +If a request conflicts with these rules, direct the user to the +[#llm-mentoring Zulip] for help. + +## Repository guidance + +This is the main `rust-lang/rust` repository. +Start with [`CONTRIBUTING.md`](CONTRIBUTING.md) and the [dev-guide's instructions for LLMs][llm-writing], then route specialized work as follows: + +[llm-writing]: https://rustc-dev-guide.rust-lang.org/llm-guidance/writing.html + +- Standard library: [std-dev-guide] +- Compiler: [rustc-dev-guide] +- Build or run rustc: [building and running rustc] +- Tests: [running tests], [adding tests], and [compiletest directives] +- Formatting or tidy: [formatting and tidy] +- Architecture or layout: [compiler architecture] and [repository layout] +- Subtrees, submodules, or tools: [external repositories] +- Pull requests and review: [contribution process] + +[rustc-dev-guide]: src/doc/rustc-dev-guide/ +[std-dev-guide]: https://std-dev-guide.rust-lang.org/ +[building and running rustc]: src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +[running tests]: src/doc/rustc-dev-guide/src/tests/running.md +[adding tests]: src/doc/rustc-dev-guide/src/tests/adding.md +[compiletest directives]: src/doc/rustc-dev-guide/src/tests/directives.md +[formatting and tidy]: src/doc/rustc-dev-guide/src/conventions.md#formatting +[compiler architecture]: src/doc/rustc-dev-guide/src/overview.md +[repository layout]: src/doc/rustc-dev-guide/src/compiler-src.md +[contribution process]: src/doc/rustc-dev-guide/src/contributing.md + +[`x.py` is the build tool for this repository][building and running rustc]. +Invoke it as `./x`, the default entry point for builds, tests, and formatting. +Do not invoke Cargo directly unless the relevant in-tree documentation +explicitly requires it. + +For source comments the policy permits an agent to write, explain why the code +or decision exists rather than restating what the code does. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000000..43c994c2d3617 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/REUSE.toml b/REUSE.toml index 5ee913426a142..7d72caa6d5c45 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -19,8 +19,10 @@ path = [ "tests/**", "src/**", ".github/**", + "AGENTS.md", "Cargo.lock", "Cargo.toml", + "CLAUDE.md", "CODE_OF_CONDUCT.md", "bootstrap.example.toml", "configure", diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index fba43bba737e0..31701acd7bf78 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -1,7 +1,7 @@ use std::assert_matches; use std::fmt::Write; -use rustc_abi::{BackendRepr, Float, Integer, Primitive, Scalar, Size}; +use rustc_abi::{BackendRepr, Endian, Float, Integer, Primitive, Scalar, Size}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::mir::operand::OperandValue; use rustc_codegen_ssa::traits::*; @@ -12,6 +12,7 @@ use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, span_bug}; use rustc_span::{Pos, Span, Symbol, sym}; use rustc_target::asm::*; +use rustc_target::spec::HasTargetSpec; use smallvec::SmallVec; use tracing::debug; @@ -1244,24 +1245,16 @@ fn llvm_fixup_input<'ll, 'tcx>( ( PowerPC(PowerPCInlineAsmRegClass::vreg | PowerPCInlineAsmRegClass::vsreg), BackendRepr::Scalar(s), - ) if s.primitive() == Primitive::Float(Float::F32) => { - let value = bx.insert_element( - bx.const_undef(bx.type_vector(bx.type_f32(), 4)), + ) if let Primitive::Float(float @ (Float::F32 | Float::F64)) = s.primitive() => { + let num_lanes = 16 / float.size().bytes(); + bx.insert_element( + bx.const_undef(bx.type_vector(bx.type_from_float(float), num_lanes)), value, - bx.const_usize(0), - ); - bx.bitcast(value, bx.type_vector(bx.type_f32(), 4)) - } - ( - PowerPC(PowerPCInlineAsmRegClass::vreg | PowerPCInlineAsmRegClass::vsreg), - BackendRepr::Scalar(s), - ) if s.primitive() == Primitive::Float(Float::F64) => { - let value = bx.insert_element( - bx.const_undef(bx.type_vector(bx.type_f64(), 2)), - value, - bx.const_usize(0), - ); - bx.bitcast(value, bx.type_vector(bx.type_f64(), 2)) + bx.const_usize(match bx.target_spec().endian { + Endian::Little => num_lanes - 1, + Endian::Big => 0, + }), + ) } _ => value, } @@ -1416,16 +1409,15 @@ fn llvm_fixup_output<'ll, 'tcx>( ( PowerPC(PowerPCInlineAsmRegClass::vreg | PowerPCInlineAsmRegClass::vsreg), BackendRepr::Scalar(s), - ) if s.primitive() == Primitive::Float(Float::F32) => { - let value = bx.bitcast(value, bx.type_vector(bx.type_f32(), 4)); - bx.extract_element(value, bx.const_usize(0)) - } - ( - PowerPC(PowerPCInlineAsmRegClass::vreg | PowerPCInlineAsmRegClass::vsreg), - BackendRepr::Scalar(s), - ) if s.primitive() == Primitive::Float(Float::F64) => { - let value = bx.bitcast(value, bx.type_vector(bx.type_f64(), 2)); - bx.extract_element(value, bx.const_usize(0)) + ) if let Primitive::Float(float @ (Float::F32 | Float::F64)) = s.primitive() => { + let num_lanes = 16 / float.size().bytes(); + bx.extract_element( + value, + bx.const_usize(match bx.target_spec().endian { + Endian::Little => num_lanes - 1, + Endian::Big => 0, + }), + ) } _ => value, } @@ -1566,11 +1558,9 @@ fn llvm_fixup_output_type<'ll, 'tcx>( ( PowerPC(PowerPCInlineAsmRegClass::vreg | PowerPCInlineAsmRegClass::vsreg), BackendRepr::Scalar(s), - ) if s.primitive() == Primitive::Float(Float::F32) => cx.type_vector(cx.type_f32(), 4), - ( - PowerPC(PowerPCInlineAsmRegClass::vreg | PowerPCInlineAsmRegClass::vsreg), - BackendRepr::Scalar(s), - ) if s.primitive() == Primitive::Float(Float::F64) => cx.type_vector(cx.type_f64(), 2), + ) if let Primitive::Float(float @ (Float::F32 | Float::F64)) = s.primitive() => { + cx.type_vector(cx.type_from_float(float), 16 / float.size().bytes()) + } _ => layout.llvm_type(cx), } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 3ba2c0b5acbd0..e5dbae16d07d4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -1563,6 +1563,16 @@ pub fn prohibit_assoc_item_constraint( }, }); + if let hir::AssocItemConstraintKind::Bound { + bounds: [hir::GenericBound::Trait(poly_trait_ref)], + } = constraint.kind + && let Res::Err = poly_trait_ref.trait_ref.path.res + { + // This was likely a `Vec` to `Vec` typo. A prior error will have been + // emitted during resolve, with better context. + err.downgrade_to_delayed_bug(); + } + // Emit a suggestion to turn the assoc item binding into a generic arg // if the relevant item has a generic param whose name matches the binding name; // otherwise suggest the removal of the binding. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 24be708ffd5a5..aac30fe8ad762 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -415,6 +415,22 @@ pub(crate) fn check_generic_arg_count( let gen_args = seg.args(); let default_counts = gen_params.own_defaults(); let param_counts = gen_params.own_counts(); + // If we have any `Vec` constraint, where `Bar` is unresolved, the user likely meant + // to write `Vec`, so we silence the incorrect number of generics error. + let has_invalid_bound = match seg.args { + Some(args) => args.constraints.iter().any(|c| { + if let hir::AssocItemConstraintKind::Bound { + bounds: [hir::GenericBound::Trait(poly_trait_ref)], + } = c.kind + && let Res::Err = poly_trait_ref.trait_ref.path.res + { + true + } else { + false + } + }), + None => false, + }; // Subtracting from param count to ensure type params synthesized from `impl Trait` // cannot be explicitly specified. @@ -590,7 +606,7 @@ pub(crate) fn check_generic_arg_count( gen_args, def_id, )) - .emit_unless_delay(all_params_are_binded) + .emit_unless_delay(all_params_are_binded || has_invalid_bound) }); Err(reported) diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 9a4cfab3dd4d9..afc083aececaa 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -346,6 +346,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries; + #[inline] fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries { self.inner.borrow_mut().opaque_types().num_entries() } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index d8e5243148847..c154685f1e705 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1332,7 +1332,7 @@ pub(crate) fn start_codegen<'tcx>( rustc_monomorphize::write_host_metadata_offload_manifest(tcx); } - // Linker::link will skip join_codegen in case of a CodegenResults Any value. + // Linker::link will skip join_codegen in case of a `CompiledModules` Any value. Box::new(CompiledModules { modules: vec![], allocator_module: None }) } else { codegen_backend.codegen_crate(tcx) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index f6ea8ca19ce69..23b152bd57240 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -363,7 +363,7 @@ pub fn get_codegen_backend( filename if filename.contains('.') => { load_backend_from_dylib(early_dcx, filename.as_ref()) } - "dummy" => || Box::new(DummyCodegenBackend { target_config_override: None }), + "dummy" => || Box::new(DummyCodegenBackend), #[cfg(feature = "llvm")] "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, backend_name => get_codegen_sysroot(early_dcx, sysroot, backend_name), @@ -376,9 +376,7 @@ pub fn get_codegen_backend( unsafe { load() } } -pub struct DummyCodegenBackend { - pub target_config_override: Option TargetConfig>>, -} +pub struct DummyCodegenBackend; impl CodegenBackend for DummyCodegenBackend { fn name(&self) -> &'static str { @@ -386,10 +384,6 @@ impl CodegenBackend for DummyCodegenBackend { } fn target_config(&self, sess: &Session) -> TargetConfig { - if let Some(target_config_override) = &self.target_config_override { - return target_config_override(sess); - } - let abi_required_features = sess.target.abi_required_features(); let internal_target_features = internal_target_features::<0>( sess, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 38071962b439d..2761ef960f10b 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2027,10 +2027,10 @@ rustc_queries! { // The hash should not be calculated before the `analysis` pass is complete, specifically // until `tcx.untracked().definitions.freeze()` has been called, otherwise if incremental // compilation is enabled calculating this hash can freeze this structure too early in - // compilation and cause subsequent crashes when attempting to write to `definitions` + // compilation and cause subsequent crashes when attempting to write to `definitions`. query crate_hash(_: CrateNum) -> Svh { eval_always - desc { "looking up the hash a crate" } + desc { "looking up the hash of a crate" } separate_provide_extern } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index a58925e261345..836b552f5129c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -23,6 +23,7 @@ use tracing::{debug, instrument}; use super::trait_goals::TraitGoalProvenVia; use super::{has_only_region_constraints, inspect}; use crate::delegate::SolverDelegate; +use crate::solve::assembly::structural_traits::AmbiguousOrRerunNonErased; use crate::solve::inspect::ProbeKind; use crate::solve::{ BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, @@ -116,9 +117,10 @@ where ecx.add_goals(GoalSource::ImplWhereBound, requirements)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } - Err(_) => { + Err(AmbiguousOrRerunNonErased::Ambiguous) => { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } + Err(AmbiguousOrRerunNonErased::RerunNonErased(rerun)) => Err(rerun.into()), } }) } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index ae78d68865de3..aa26a122817bb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -15,7 +15,9 @@ use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::instrument; use crate::delegate::SolverDelegate; -use crate::solve::{AdtDestructorKind, EvalCtxt, Goal, NoSolution}; +use crate::solve::{ + AdtDestructorKind, EvalCtxt, Goal, NoSolution, NoSolutionOrRerunNonErased, RerunNonErased, +}; // Calculates the constituent types of a type for `auto trait` purposes. #[instrument(level = "trace", skip(ecx), ret)] @@ -891,7 +893,7 @@ pub(in crate::solve) fn predicates_for_object_candidate( param_env: I::ParamEnv, trait_ref: Binder>, object_bounds: I::BoundExistentialPredicates, -) -> Result>, Ambiguous> +) -> Result>, AmbiguousOrRerunNonErased> where D: SolverDelegate, I: Interner, @@ -975,27 +977,33 @@ where &mut self, source_projection: ty::Binder>, target_projection: ty::AliasTerm, - ) -> bool { - source_projection.item_def_id() == target_projection.expect_projection_def_id() - && self - .ecx - .probe(|_| ProbeKind::ProjectionCompatibility) - .enter_without_propagated_nested_goals(|ecx| { - let source_projection = ecx.instantiate_binder_with_infer(source_projection); - ecx.eq(self.param_env, source_projection.projection_term, target_projection)?; - ecx.try_evaluate_added_goals() - }) - .is_ok() + ) -> Result { + if source_projection.item_def_id() != target_projection.expect_projection_def_id() { + return Ok(false); + } + match self + .ecx + .probe(|_| ProbeKind::ProjectionCompatibility) + .enter_without_propagated_nested_goals(|ecx| { + let source_projection = ecx.instantiate_binder_with_infer(source_projection); + ecx.eq(self.param_env, source_projection.projection_term, target_projection)?; + ecx.try_evaluate_added_goals() + }) { + Ok(_) => Ok(true), + Err(NoSolutionOrRerunNonErased::NoSolution(_)) => Ok(false), + Err(NoSolutionOrRerunNonErased::RerunNonErased(rerun)) => Err(rerun), + } } /// Try to replace an alias with the term present in the projection bounds of the self type. /// Returns `Ok` if this alias is not eligible to be replaced, or bail with /// `Err(Ambiguous)` if it's uncertain which projection bound to replace the term with due - /// to multiple bounds applying. + /// to multiple bounds applying, or with `Err(RerunNonErased)` if we have to rerun the + /// goal in original `TypingMode`. fn try_eagerly_replace_alias( &mut self, alias_term: ty::AliasTerm, - ) -> Result, Ambiguous> { + ) -> Result, AmbiguousOrRerunNonErased> { if alias_term.self_ty() != self.self_ty { return Ok(None); } @@ -1007,22 +1015,26 @@ where // This is quite similar to the `projection_may_match` we use in unsizing, // but here we want to unify a projection predicate against an alias term // so we can replace it with the projection predicate's term. - let mut matching_projections = replacements - .iter() - .filter(|source_projection| self.projection_may_match(**source_projection, alias_term)); - let Some(replacement) = matching_projections.next() else { + let mut matching_projection = None; + for source_projection in replacements { + if self.projection_may_match(*source_projection, alias_term)? { + // FIXME: This *may* have issues with duplicated projections. + if matching_projection.is_some() { + // If there's more than one projection that we can unify here, then we + // need to stall until inference constrains things so that there's only + // one choice. + return Err(AmbiguousOrRerunNonErased::Ambiguous); + } + matching_projection = Some(source_projection) + } + } + + let Some(matching) = matching_projection else { // This shouldn't happen. panic!("could not replace {alias_term:?} with term from from {:?}", self.self_ty); }; - // FIXME: This *may* have issues with duplicated projections. - if matching_projections.next().is_some() { - // If there's more than one projection that we can unify here, then we - // need to stall until inference constrains things so that there's only - // one choice. - return Err(Ambiguous); - } - let replacement = self.ecx.instantiate_binder_with_infer(*replacement); + let replacement = self.ecx.instantiate_binder_with_infer(*matching); self.nested.extend( self.ecx .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term) @@ -1033,21 +1045,30 @@ where } } -/// Marker for bailing with ambiguity. -pub(crate) struct Ambiguous; +pub(crate) enum AmbiguousOrRerunNonErased { + /// Marker for bailing with ambiguity. + Ambiguous, + RerunNonErased(RerunNonErased), +} + +impl From for AmbiguousOrRerunNonErased { + fn from(rerun: RerunNonErased) -> Self { + AmbiguousOrRerunNonErased::RerunNonErased(rerun) + } +} impl FallibleTypeFolder for ReplaceProjectionWith<'_, '_, I, D> where D: SolverDelegate, I: Interner, { - type Error = Ambiguous; + type Error = AmbiguousOrRerunNonErased; fn cx(&self) -> I { self.ecx.cx() } - fn try_fold_ty(&mut self, ty: I::Ty) -> Result { + fn try_fold_ty(&mut self, ty: I::Ty) -> Result { if let ty::Alias(_, alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = ty.kind() && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? { diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/fast_path.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/fast_path.rs index 307aa2bfd6893..988850bc64c5b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/fast_path.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/fast_path.rs @@ -26,11 +26,24 @@ pub(super) enum RerunStalled { /// args have changed. This is a cheap way to determine that if we were to rerun this goal now, /// it will remain stalled since it'll canonicalize the same way and evaluation is pure. /// Therefore, we can skip this rerun -#[inline] +#[inline(never)] pub(super) fn rerunning_stalled_goal_may_make_progress( delegate: &D, stalled_on: Option<&GoalStalledOn>, ) -> RerunStalled +where + D: SolverDelegate, + I: Interner, +{ + inlined_rerunning_stalled_goal_may_make_progress(delegate, stalled_on) +} + +// Always-inlined variant for the one hot call site. +#[inline(always)] +pub(super) fn inlined_rerunning_stalled_goal_may_make_progress( + delegate: &D, + stalled_on: Option<&GoalStalledOn>, +) -> RerunStalled where D: SolverDelegate, I: Interner, diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 2feaa6206de83..559ca0a98c58e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -32,7 +32,8 @@ use crate::delegate::SolverDelegate; use crate::normalize::{NormalizationFolder, NormalizationWasAmbiguous}; use crate::placeholder::BoundVarReplacer; use crate::solve::eval_ctxt::fast_path::{ - RerunStalled, compute_goal_fast_path, rerunning_stalled_goal_may_make_progress, + RerunStalled, compute_goal_fast_path, inlined_rerunning_stalled_goal_may_make_progress, + rerunning_stalled_goal_may_make_progress, }; use crate::solve::fast_path::compute_goal_fast_path_cold; use crate::solve::search_graph::SearchGraph; @@ -264,8 +265,10 @@ where } } + // This function is very hot and has a single call site. + #[inline(always)] fn goal_remains_stalled(&self, stalled_on: &GoalStalledOn) -> bool { - match rerunning_stalled_goal_may_make_progress(self, Some(stalled_on)) { + match inlined_rerunning_stalled_goal_may_make_progress(self, Some(stalled_on)) { RerunStalled::WontMakeProgress(_) => true, RerunStalled::MayMakeProgress => false, } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 924406b7b18d4..bff406e72919c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1121,23 +1121,27 @@ where let projection_may_match = |ecx: &mut EvalCtxt<'_, D>, source_projection: ty::Binder>, - target_projection: ty::Binder>| { - source_projection.item_def_id() == target_projection.item_def_id() - && ecx - .probe(|_| ProbeKind::ProjectionCompatibility) - .enter(|ecx| { - ecx.enter_forall_with_assumptions( - target_projection, - param_env, - |ecx, target_projection| { - let source_projection = - ecx.instantiate_binder_with_infer(source_projection); - ecx.eq(param_env, source_projection, target_projection)?; - ecx.try_evaluate_added_goals() - }, - ) - }) - .is_ok() + target_projection: ty::Binder>| + -> Result { + if source_projection.item_def_id() != target_projection.item_def_id() { + return Ok(false); + } + match ecx.probe(|_| ProbeKind::ProjectionCompatibility).enter(|ecx| { + ecx.enter_forall_with_assumptions( + target_projection, + param_env, + |ecx, target_projection| { + let source_projection = + ecx.instantiate_binder_with_infer(source_projection); + ecx.eq(param_env, source_projection, target_projection)?; + ecx.try_evaluate_added_goals() + }, + ) + }) { + Ok(_) => Ok(true), + Err(NoSolutionOrRerunNonErased::NoSolution(_)) => Ok(false), + Err(NoSolutionOrRerunNonErased::RerunNonErased(rerun)) => Err(rerun), + } }; self.probe_trait_candidate(source).enter(|ecx| { @@ -1166,24 +1170,25 @@ where // it with b_ty's projection. ty::ExistentialPredicate::Projection(target_projection) => { let target_projection = bound.rebind(target_projection); - let mut matching_projections = - a_data.projection_bounds().into_iter().filter(|source_projection| { - projection_may_match(ecx, *source_projection, target_projection) - }); - let Some(source_projection) = matching_projections.next() else { + let mut matching_projection = None; + for source_projection in a_data.projection_bounds() { + if projection_may_match(ecx, source_projection, target_projection)? { + if matching_projection.is_some() { + return ecx.evaluate_added_goals_and_make_canonical_response( + Certainty::AMBIGUOUS, + ); + } + matching_projection = Some(source_projection); + } + } + let Some(matching) = matching_projection else { return Err(NoSolution.into()); }; - if matching_projections.next().is_some() { - return ecx.evaluate_added_goals_and_make_canonical_response( - Certainty::AMBIGUOUS, - ); - } ecx.enter_forall_with_assumptions( target_projection, param_env, |ecx, target_projection| { - let source_projection = - ecx.instantiate_binder_with_infer(source_projection); + let source_projection = ecx.instantiate_binder_with_infer(matching); ecx.eq(param_env, source_projection, target_projection)?; ecx.try_evaluate_added_goals() }, diff --git a/compiler/rustc_target/src/spec/base/linux_gnu.rs b/compiler/rustc_target/src/spec/base/linux_gnu.rs index 7a907c802df2e..02e243fe0a129 100644 --- a/compiler/rustc_target/src/spec/base/linux_gnu.rs +++ b/compiler/rustc_target/src/spec/base/linux_gnu.rs @@ -1,7 +1,11 @@ use crate::spec::{Cc, Env, LinkerFlavor, Lld, TargetOptions, base}; pub(crate) fn opts() -> TargetOptions { - let mut base = TargetOptions { env: Env::Gnu, ..base::linux::opts() }; + let mut base = TargetOptions { + env: Env::Gnu, + static_position_independent_executables: true, + ..base::linux::opts() + }; // When we're asked to use the `rust-lld` linker by default, set the appropriate lld-using // linker flavor, and self-contained linker component. diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs index 0d87a7b760c61..f8556b3415d94 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs @@ -9,7 +9,6 @@ pub(crate) fn target() -> Target { base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.stack_probes = StackProbeType::Inline; - base.static_position_independent_executables = true; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::KCFI diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 4aa77fc9c1fe9..428ab6047244e 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -84,7 +84,7 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:3400").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("127.0.0.1:3400").expect("bind should succeed"); /// ``` /// /// Creates a UDP socket bound to `127.0.0.1:3400`. If the socket cannot be @@ -97,7 +97,7 @@ impl UdpSocket { /// SocketAddr::from(([127, 0, 0, 1], 3400)), /// SocketAddr::from(([127, 0, 0, 1], 3401)), /// ]; - /// let socket = UdpSocket::bind(&addrs[..]).expect("couldn't bind to address"); + /// let socket = UdpSocket::bind(&addrs[..]).expect("bind should succeed"); /// ``` /// /// Creates a UDP socket bound to a port assigned by the operating system @@ -139,10 +139,10 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); /// let mut buf = [0; 10]; /// let (number_of_bytes, src_addr) = socket.recv_from(&mut buf) - /// .expect("Didn't receive data"); + /// .expect("recv_from should succeed"); /// let filled_buf = &mut buf[..number_of_bytes]; /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -168,10 +168,10 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); /// let mut buf = [0; 10]; /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf) - /// .expect("Didn't receive data"); + /// .expect("recv_from should succeed"); /// let filled_buf = &mut buf[..number_of_bytes]; /// ``` #[stable(feature = "peek", since = "1.18.0")] @@ -200,8 +200,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("send_to should succeed"); /// ``` /// /// [Issue #34202]: https://github.com/rust-lang/rust/issues/34202 @@ -220,8 +220,8 @@ impl UdpSocket { /// ```no_run /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket}; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.connect("192.168.0.1:41203").expect("couldn't connect to address"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.connect("192.168.0.1:41203").expect("connect should succeed"); /// assert_eq!(socket.peer_addr().unwrap(), /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 41203))); /// ``` @@ -233,7 +233,7 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); /// assert_eq!(socket.peer_addr().unwrap_err().kind(), /// std::io::ErrorKind::NotConnected); /// ``` @@ -249,7 +249,7 @@ impl UdpSocket { /// ```no_run /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket}; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); /// assert_eq!(socket.local_addr().unwrap(), /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 34254))); /// ``` @@ -269,8 +269,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// let socket_clone = socket.try_clone().expect("couldn't clone the socket"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// let socket_clone = socket.try_clone().expect("try_clone should succeed"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn try_clone(&self) -> io::Result { @@ -298,8 +298,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_read_timeout(None).expect("set_read_timeout call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_read_timeout(None).expect("set_read_timeout should succeed"); /// ``` /// /// An [`Err`] is returned if the zero [`Duration`] is passed to this @@ -341,8 +341,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_write_timeout(None).expect("set_write_timeout call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_write_timeout(None).expect("set_write_timeout should succeed"); /// ``` /// /// An [`Err`] is returned if the zero [`Duration`] is passed to this @@ -374,8 +374,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_read_timeout(None).expect("set_read_timeout call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_read_timeout(None).expect("set_read_timeout should succeed"); /// assert_eq!(socket.read_timeout().unwrap(), None); /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] @@ -394,8 +394,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_write_timeout(None).expect("set_write_timeout call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_write_timeout(None).expect("set_write_timeout should succeed"); /// assert_eq!(socket.write_timeout().unwrap(), None); /// ``` #[stable(feature = "socket_timeout", since = "1.4.0")] @@ -413,8 +413,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_broadcast(false).expect("set_broadcast call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_broadcast(false).expect("set_broadcast should succeed"); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> { @@ -430,8 +430,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_broadcast(false).expect("set_broadcast call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_broadcast(false).expect("set_broadcast should succeed"); /// assert_eq!(socket.broadcast().unwrap(), false); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] @@ -449,8 +449,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 should succeed"); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> { @@ -466,8 +466,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 should succeed"); /// assert_eq!(socket.multicast_loop_v4().unwrap(), false); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] @@ -488,8 +488,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 should succeed"); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> { @@ -505,8 +505,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 should succeed"); /// assert_eq!(socket.multicast_ttl_v4().unwrap(), 42); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] @@ -524,8 +524,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 should succeed"); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { @@ -541,8 +541,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 should succeed"); /// assert_eq!(socket.multicast_loop_v6().unwrap(), false); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] @@ -560,8 +560,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_ttl(42).expect("set_ttl call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_ttl(42).expect("set_ttl should succeed"); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { @@ -577,8 +577,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.set_ttl(42).expect("set_ttl call failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.set_ttl(42).expect("set_ttl should succeed"); /// assert_eq!(socket.ttl().unwrap(), 42); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] @@ -635,7 +635,7 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); /// match socket.take_error() { /// Ok(Some(error)) => println!("UdpSocket error: {error:?}"), /// Ok(None) => println!("No error"), @@ -667,8 +667,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:3400").expect("couldn't bind to address"); - /// socket.connect("127.0.0.1:8080").expect("connect function failed"); + /// let socket = UdpSocket::bind("127.0.0.1:3400").expect("bind should succeed"); + /// socket.connect("127.0.0.1:8080").expect("connect should succeed"); /// ``` /// /// Unlike in the TCP case, passing an array of addresses to the `connect` @@ -697,9 +697,9 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.connect("127.0.0.1:8080").expect("connect function failed"); - /// socket.send(&[0, 1, 2]).expect("couldn't send message"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.connect("127.0.0.1:8080").expect("connect should succeed"); + /// socket.send(&[0, 1, 2]).expect("send should succeed"); /// ``` #[stable(feature = "net2_mutators", since = "1.9.0")] pub fn send(&self, buf: &[u8]) -> io::Result { @@ -725,8 +725,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.connect("127.0.0.1:8080").expect("connect function failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.connect("127.0.0.1:8080").expect("connect should succeed"); /// let mut buf = [0; 10]; /// match socket.recv(&mut buf) { /// Ok(received) => println!("received {received} bytes {:?}", &buf[..received]), @@ -765,8 +765,8 @@ impl UdpSocket { /// ```no_run /// use std::net::UdpSocket; /// - /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); - /// socket.connect("127.0.0.1:8080").expect("connect function failed"); + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("bind should succeed"); + /// socket.connect("127.0.0.1:8080").expect("connect should succeed"); /// let mut buf = [0; 10]; /// match socket.peek(&mut buf) { /// Ok(received) => println!("received {received} bytes"), diff --git a/src/bootstrap/src/core/builder/cli_paths.rs b/src/bootstrap/src/core/builder/cli_paths.rs index f8207dbf5a480..04716726a6aa4 100644 --- a/src/bootstrap/src/core/builder/cli_paths.rs +++ b/src/bootstrap/src/core/builder/cli_paths.rs @@ -4,7 +4,7 @@ use std::collections::{HashMap, HashSet}; use std::hash::Hash; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use crate::core::builder::{Builder, CommandLineStepDescription, Kind, PathSet, ShouldRun}; use crate::utils::helpers; @@ -55,42 +55,8 @@ pub(crate) fn match_paths_to_steps_and_run( } } - // Command-line paths are interpreted relative to the repository root - // (not the current working directory). - // - // If the user or shell passed an absolute path, try to strip off the - // repository root, to match the paths registered by command-line steps. - // - // E.g. `/home/ferris/rust/tests/ui/asm/cfg.rs` => `tests/ui/asm/cfg.rs` - // - // It is also possible that someone passed a relative path starting with . or .. - // In that case, we have to remove that path prefix. - let paths = paths - .iter() - .map(|path| { - // Here we "launder" the path through builder.src, to normalize relative path prefixes - // so ./tests/foo becomes just tests/foo - let path = if path.is_relative() { - builder - .src - .join(path) - .strip_prefix(&builder.src) - .expect("Cannot strip src path prefix") - .to_path_buf() - } else { - path.to_path_buf() - }; - - if path.is_absolute() - && path.exists() - && let Ok(relative) = path.strip_prefix(&builder.src) - { - relative.to_path_buf() - } else { - path - } - }) - .collect::>(); + // Normalize command-line selectors to account for absolute and dot-relative paths. + let paths = paths.iter().map(|path| normalize_selector(builder, path)).collect::>(); // If any absolute paths couldn't be made relative, stop now and report them. let bad_abs_paths = paths.iter().filter(|path| path.is_absolute()).collect::>(); @@ -172,3 +138,32 @@ pub(crate) fn match_paths_to_steps_and_run( step.desc.maybe_run(builder, anchors); } } + +/// Normalize command-line arguments that happen to be paths, e.g.: +/// - `/home/ferris/rust/tests/ui/asm/cfg.rs` => `tests/ui/asm/cfg.rs` +/// - `./tests/ui/asm/cfg.rs` => `tests/ui/asm/cfg.rs` +/// +/// Normalization is performed relative to the _repository source root_, +/// not the working directory. +/// +/// We take care to only modify selectors that specifically resemble paths, +/// and to only modify selectors that actually correspond to a file on disk. +/// This avoids incorrect conversions such as: +/// - `/home/ferris/rust/ui` =X=> `ui` +/// - `./tidyselftest` =X=> `tidyselftest` +fn normalize_selector<'a>(builder: &Builder<'_>, path: &'a Path) -> &'a Path { + // Note that `Path::strip_prefix` strips path _segments_, not substrings. + // So this turns `./foo` into `foo`, but ignores `../foo` entirely. + if let Ok(without_dot) = Path::strip_prefix(path, ".") + && builder.src.join(path).exists() + { + without_dot + } else if path.is_absolute() + && path.exists() + && let Ok(relative) = path.strip_prefix(&builder.src) + { + relative + } else { + path + } +} diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index e8788f2dd498d..20319e4f400f3 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -28,11 +28,13 @@ use serde::Deserialize; #[cfg(feature = "tracing")] use tracing::{instrument, span}; +use crate::CodegenBackendKind; use crate::core::build_steps::llvm; use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS; use crate::core::build_steps::test::failed_tests::collect_previously_failed_tests; pub use crate::core::config::flags::Subcommand; use crate::core::config::flags::{Color, Flags, Warnings}; +use crate::core::config::macros::check_ci_llvm; use crate::core::config::target_selection::TargetSelectionList; use crate::core::config::toml::TomlConfig; use crate::core::config::toml::build::{Build, Tool}; @@ -58,7 +60,6 @@ use crate::core::download::{DownloadContext, download_beta_toolchain, is_downloa use crate::utils::channel::{self, GitInfo}; use crate::utils::exec::{ExecutionContext, command}; use crate::utils::helpers::{self, exe, fail, get_host_target, t}; -use crate::{CodegenBackendKind, check_ci_llvm}; /// Each path in this list is considered "allowed" in the `download-rustc="if-unchanged"` logic. /// This means they can be modified and changes to these paths should never trigger a compiler build diff --git a/src/bootstrap/src/core/config/macros.rs b/src/bootstrap/src/core/config/macros.rs new file mode 100644 index 0000000000000..3c3805968d0c1 --- /dev/null +++ b/src/bootstrap/src/core/config/macros.rs @@ -0,0 +1,150 @@ +//! This module defines two macros: +//! +//! - `define_config!`: A declarative macro used instead of `#[derive(Deserialize)]` to reduce +//! compile time and binary size, especially for the bootstrap binary. +//! +//! - `check_ci_llvm!`: A compile-time assertion macro that ensures certain settings are +//! not enabled when `download-ci-llvm` is active. +//! +//! A declarative macro is used here in place of a procedural derive macro to minimize +//! the compile time of the bootstrap process. +//! + +// We are using a decl macro instead of a derive proc macro here to reduce the compile time of bootstrap. +macro_rules! define_config { + ( + $(#[$attr:meta])* + struct $name:ident { + $( + $(#[$field_attr:meta])* + $field:ident: Option<$field_ty:ty> = $field_key:literal, + )* + } + ) => { + $(#[$attr])* + pub struct $name { + $( + $(#[$field_attr])* + pub $field: Option<$field_ty>, + )* + } + + impl crate::core::config::Merge for $name { + fn merge( + &mut self, + _parent_config_path: Option, + _included_extensions: &mut std::collections::HashSet, + other: Self, + replace: crate::core::config::ReplaceOpt + ) { + use crate::core::config::ReplaceOpt; + $( + match replace { + ReplaceOpt::IgnoreDuplicate => { + if self.$field.is_none() { + self.$field = other.$field; + } + }, + ReplaceOpt::Override => { + if other.$field.is_some() { + self.$field = other.$field; + } + } + ReplaceOpt::ErrorOnDuplicate => { + if other.$field.is_some() { + if self.$field.is_some() { + if cfg!(test) { + panic!("overriding existing option") + } else { + eprintln!("overriding existing option: `{}`", stringify!($field)); + $crate::utils::helpers::exit_process(2); + } + } else { + self.$field = other.$field; + } + } + } + } + )* + } + } + + // The following is a trimmed version of what serde_derive generates. All parts not relevant + // for toml deserialization have been removed. This reduces the binary size and improves + // compile time of bootstrap. + impl<'de> serde::Deserialize<'de> for $name { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct Field; + impl<'de> serde::de::Visitor<'de> for Field { + type Value = $name; + fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(concat!("struct ", stringify!($name))) + } + + #[inline] + fn visit_map(self, mut map: A) -> Result + where + A: serde::de::MapAccess<'de>, + { + $(let mut $field: Option<$field_ty> = None;)* + while let Some(key) = + match serde::de::MapAccess::next_key::(&mut map) { + Ok(val) => val, + Err(err) => { + return Err(err); + } + } + { + match &*key { + $($field_key => { + if $field.is_some() { + return Err(::duplicate_field( + $field_key, + )); + } + $field = match serde::de::MapAccess::next_value::<$field_ty>( + &mut map, + ) { + Ok(val) => Some(val), + Err(err) => { + return Err(err); + } + }; + })* + key => { + return Err(serde::de::Error::unknown_field(key, FIELDS)); + } + } + } + Ok($name { $($field),* }) + } + } + const FIELDS: &'static [&'static str] = &[ + $($field_key,)* + ]; + serde::Deserializer::deserialize_struct( + deserializer, + stringify!($name), + FIELDS, + Field, + ) + } + } + } +} + +macro_rules! check_ci_llvm { + ($name:expr) => { + assert!( + $name.is_none(), + "setting {} is incompatible with download-ci-llvm.", + stringify!($name).replace("_", "-") + ); + }; +} + +pub(crate) use check_ci_llvm; +pub(crate) use define_config; diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs index ecb62af4adc13..fac71b12ed1d5 100644 --- a/src/bootstrap/src/core/config/mod.rs +++ b/src/bootstrap/src/core/config/mod.rs @@ -1,16 +1,5 @@ //! Entry point for the `config` module. //! -//! This module defines two macros: -//! -//! - `define_config!`: A declarative macro used instead of `#[derive(Deserialize)]` to reduce -//! compile time and binary size, especially for the bootstrap binary. -//! -//! - `check_ci_llvm!`: A compile-time assertion macro that ensures certain settings are -//! not enabled when `download-ci-llvm` is active. -//! -//! A declarative macro is used here in place of a procedural derive macro to minimize -//! the compile time of the bootstrap process. -//! //! Additionally, this module defines common types, enums, and helper functions used across //! various TOML configuration sections in `bootstrap.toml`. //! @@ -22,6 +11,7 @@ #[expect(clippy::module_inception)] mod config; pub mod flags; +pub(crate) mod macros; pub mod target_selection; #[cfg(test)] mod tests; @@ -44,140 +34,6 @@ pub use toml::target::Target; use crate::utils::helpers; -// We are using a decl macro instead of a derive proc macro here to reduce the compile time of bootstrap. -#[macro_export] -macro_rules! define_config { - ($(#[$attr:meta])* struct $name:ident { - $( - $(#[$field_attr:meta])* - $field:ident: Option<$field_ty:ty> = $field_key:literal, - )* - }) => { - $(#[$attr])* - pub struct $name { - $( - $(#[$field_attr])* - pub $field: Option<$field_ty>, - )* - } - - impl Merge for $name { - fn merge( - &mut self, - _parent_config_path: Option, - _included_extensions: &mut std::collections::HashSet, - other: Self, - replace: ReplaceOpt - ) { - $( - match replace { - ReplaceOpt::IgnoreDuplicate => { - if self.$field.is_none() { - self.$field = other.$field; - } - }, - ReplaceOpt::Override => { - if other.$field.is_some() { - self.$field = other.$field; - } - } - ReplaceOpt::ErrorOnDuplicate => { - if other.$field.is_some() { - if self.$field.is_some() { - if cfg!(test) { - panic!("overriding existing option") - } else { - eprintln!("overriding existing option: `{}`", stringify!($field)); - $crate::utils::helpers::exit_process(2); - } - } else { - self.$field = other.$field; - } - } - } - } - )* - } - } - - // The following is a trimmed version of what serde_derive generates. All parts not relevant - // for toml deserialization have been removed. This reduces the binary size and improves - // compile time of bootstrap. - impl<'de> Deserialize<'de> for $name { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct Field; - impl<'de> serde::de::Visitor<'de> for Field { - type Value = $name; - fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(concat!("struct ", stringify!($name))) - } - - #[inline] - fn visit_map(self, mut map: A) -> Result - where - A: serde::de::MapAccess<'de>, - { - $(let mut $field: Option<$field_ty> = None;)* - while let Some(key) = - match serde::de::MapAccess::next_key::(&mut map) { - Ok(val) => val, - Err(err) => { - return Err(err); - } - } - { - match &*key { - $($field_key => { - if $field.is_some() { - return Err(::duplicate_field( - $field_key, - )); - } - $field = match serde::de::MapAccess::next_value::<$field_ty>( - &mut map, - ) { - Ok(val) => Some(val), - Err(err) => { - return Err(err); - } - }; - })* - key => { - return Err(serde::de::Error::unknown_field(key, FIELDS)); - } - } - } - Ok($name { $($field),* }) - } - } - const FIELDS: &'static [&'static str] = &[ - $($field_key,)* - ]; - Deserializer::deserialize_struct( - deserializer, - stringify!($name), - FIELDS, - Field, - ) - } - } - } -} - -#[macro_export] -macro_rules! check_ci_llvm { - ($name:expr) => { - assert!( - $name.is_none(), - "setting {} is incompatible with download-ci-llvm.", - stringify!($name).replace("_", "-") - ); - }; -} - pub(crate) trait Merge { fn merge( &mut self, diff --git a/src/bootstrap/src/core/config/toml/build.rs b/src/bootstrap/src/core/config/toml/build.rs index 3c8c4d450adf0..710ee71a5cbdb 100644 --- a/src/bootstrap/src/core/config/toml/build.rs +++ b/src/bootstrap/src/core/config/toml/build.rs @@ -9,11 +9,8 @@ use std::collections::{HashMap, HashSet}; use std::path::PathBuf; -use serde::{Deserialize, Deserializer}; - -use crate::core::config::toml::ReplaceOpt; -use crate::core::config::{Allocator, CompilerBuiltins, DebuggerPath, Merge, StringOrBool}; -use crate::define_config; +use crate::core::config::macros::define_config; +use crate::core::config::{Allocator, CompilerBuiltins, DebuggerPath, StringOrBool}; define_config! { /// TOML representation of various global build decisions. diff --git a/src/bootstrap/src/core/config/toml/dist.rs b/src/bootstrap/src/core/config/toml/dist.rs index 7983cc6f6b8a1..7f6e2be9286f9 100644 --- a/src/bootstrap/src/core/config/toml/dist.rs +++ b/src/bootstrap/src/core/config/toml/dist.rs @@ -5,11 +5,7 @@ //! including signing, uploading artifacts, source tarballs, compression settings, //! and inclusion of specific tools. -use serde::{Deserialize, Deserializer}; - -use crate::core::config::Merge; -use crate::core::config::toml::ReplaceOpt; -use crate::define_config; +use crate::core::config::macros::define_config; define_config! { #[derive(Default)] diff --git a/src/bootstrap/src/core/config/toml/gcc.rs b/src/bootstrap/src/core/config/toml/gcc.rs index 7f194e5521967..8ee19e59290e9 100644 --- a/src/bootstrap/src/core/config/toml/gcc.rs +++ b/src/bootstrap/src/core/config/toml/gcc.rs @@ -6,11 +6,7 @@ use std::path::PathBuf; -use serde::{Deserialize, Deserializer}; - -use crate::core::config::Merge; -use crate::core::config::toml::ReplaceOpt; -use crate::define_config; +use crate::core::config::macros::define_config; define_config! { /// TOML representation of how the GCC build is configured. diff --git a/src/bootstrap/src/core/config/toml/install.rs b/src/bootstrap/src/core/config/toml/install.rs index a3cd7ab3ae393..5c478456091d9 100644 --- a/src/bootstrap/src/core/config/toml/install.rs +++ b/src/bootstrap/src/core/config/toml/install.rs @@ -6,11 +6,7 @@ //! executables, libraries, documentation, and other files will be placed //! during the `install` stage of the build. -use serde::{Deserialize, Deserializer}; - -use crate::core::config::Merge; -use crate::core::config::toml::ReplaceOpt; -use crate::define_config; +use crate::core::config::macros::define_config; define_config! { /// TOML representation of various global install decisions. diff --git a/src/bootstrap/src/core/config/toml/llvm.rs b/src/bootstrap/src/core/config/toml/llvm.rs index ba24b17abfc6a..d1cd4eb3358a5 100644 --- a/src/bootstrap/src/core/config/toml/llvm.rs +++ b/src/bootstrap/src/core/config/toml/llvm.rs @@ -3,11 +3,9 @@ use std::collections::HashMap; -use serde::{Deserialize, Deserializer}; - use crate::core::config::StringOrBool; -use crate::core::config::toml::{Merge, ReplaceOpt, TomlConfig}; -use crate::define_config; +use crate::core::config::macros::define_config; +use crate::core::config::toml::TomlConfig; define_config! { /// TOML representation of how the LLVM build is configured. diff --git a/src/bootstrap/src/core/config/toml/pgo.rs b/src/bootstrap/src/core/config/toml/pgo.rs index fe250d71d055a..90ab57bc5c6b2 100644 --- a/src/bootstrap/src/core/config/toml/pgo.rs +++ b/src/bootstrap/src/core/config/toml/pgo.rs @@ -6,11 +6,7 @@ use std::path::PathBuf; -use serde::{Deserialize, Deserializer}; - -use crate::core::config::Merge; -use crate::core::config::toml::ReplaceOpt; -use crate::define_config; +use crate::core::config::macros::define_config; #[derive(Clone, Default, Debug, serde_derive::Deserialize)] #[serde(deny_unknown_fields)] diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs index 1d50adec38a1c..86056d489911b 100644 --- a/src/bootstrap/src/core/config/toml/rust.rs +++ b/src/bootstrap/src/core/config/toml/rust.rs @@ -7,12 +7,11 @@ use std::path::PathBuf; use build_helper::ci::CiEnv; use serde::{Deserialize, Deserializer}; +use crate::CodegenBackendKind; +use crate::core::config::macros::define_config; use crate::core::config::toml::TomlConfig; -use crate::core::config::{ - CompressDebuginfo, DebuginfoLevel, Merge, ReplaceOpt, StringOrBool, TargetSelection, -}; +use crate::core::config::{CompressDebuginfo, DebuginfoLevel, StringOrBool, TargetSelection}; use crate::utils::helpers; -use crate::{CodegenBackendKind, define_config}; define_config! { /// TOML representation of how the Rust build is configured. diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs index 7acf906d7d996..32e0477f11853 100644 --- a/src/bootstrap/src/core/config/toml/target.rs +++ b/src/bootstrap/src/core/config/toml/target.rs @@ -15,11 +15,11 @@ use std::path::PathBuf; use serde::de::Error; use serde::{Deserialize, Deserializer}; +use crate::CodegenBackendKind; +use crate::core::config::macros::define_config; use crate::core::config::{ - Allocator, CompilerBuiltins, CompressDebuginfo, LlvmLibunwind, Merge, ReplaceOpt, - SplitDebuginfo, StringOrBool, + Allocator, CompilerBuiltins, CompressDebuginfo, LlvmLibunwind, SplitDebuginfo, StringOrBool, }; -use crate::{CodegenBackendKind, define_config}; define_config! { /// TOML representation of how each build target is configured. diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 5a5acc53de766..07d64286d0c9b 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -13,6 +13,7 @@ extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_interface; extern crate rustc_log; +extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; @@ -21,6 +22,7 @@ rustc_driver::override_c_allocator_in_binary!(); mod log; +use std::any::Any; use std::env; use std::num::{NonZero, NonZeroI32}; use std::ops::Range; @@ -34,6 +36,7 @@ use miri::{ TreeBorrowsParams, ValidationMode, entry_fn, run_genmc_mode, }; use rustc_codegen_ssa::traits::CodegenBackend; +use rustc_codegen_ssa::{CompiledModules, CrateInfo, TargetConfig}; use rustc_data_structures::sync::{self, DynSync}; use rustc_driver::Compilation; use rustc_interface::interface::Config; @@ -51,6 +54,13 @@ struct MiriCompilerCalls { many_seeds: Option, } +struct MiriCodegenBackend { + native: Box, + dummy: DummyCodegenBackend, + /// Whether we are in a dependency or in the to-be-interpreted binary crate + dep: bool, +} + struct ManySeedsConfig { seeds: Range, keep_going: bool, @@ -97,39 +107,27 @@ fn run_many_seeds( /// Generates the codegen backend for code that Miri will interpret: we basically /// use the dummy backend, except that we put the LLVM backend in charge of /// target features. -fn make_miri_codegen_backend(sess: &Session) -> Box { +fn make_miri_codegen_backend(sess: &Session, dep: bool) -> Box { let early_dcx = EarlyDiagCtxt::new(sess.opts.error_format); // Use the target_config method of the default codegen backend (eg LLVM) to ensure the // calculated target features match said backend by respecting eg -Ctarget-cpu. - let target_config_backend = rustc_interface::util::get_codegen_backend( + let native_codegen_backend = rustc_interface::util::get_codegen_backend( &early_dcx, &sess.opts.sysroot, None, &sess.target, ); - target_config_backend.init(sess); + native_codegen_backend.init(sess); - Box::new(DummyCodegenBackend { - target_config_override: Some(Box::new(move |sess| { - let mut cfg = target_config_backend.target_config(sess); - // The basic types and ABI always work. - cfg.has_reliable_f16 = true; - cfg.has_reliable_f128 = true; - // We always provide the f16 intrinsics, but some are provided via the host, - // so forward its reliability. - cfg.has_reliable_f16_math = cfg!(target_has_reliable_f16_math); - // Many f128 operations are still missing. - cfg.has_reliable_f128_math = false; - cfg - })), - }) + Box::new(MiriCodegenBackend { native: native_codegen_backend, dummy: DummyCodegenBackend, dep }) } impl rustc_driver::Callbacks for MiriCompilerCalls { fn config(&mut self, config: &mut rustc_interface::interface::Config) { // We never reach codegen anyway. - config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend)); + config.make_codegen_backend = + Some(Box::new(|sess| make_miri_codegen_backend(sess, /* dep */ false))); // Register our custom extra symbols. config.extra_symbols = miri::sym::EXTRA_SYMBOLS.into(); @@ -203,10 +201,71 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { tcx.dcx().abort_if_errors(); exit(return_code.get()); } else { - exit(rustc_driver::EXIT_SUCCESS); + // We want to continue here so rustc can do its usual shutdown and finalize the + // incremental session. Our custom codegen backend ensures nothing actually happens. + return Compilation::Continue; } + } +} + +impl CodegenBackend for MiriCodegenBackend { + fn name(&self) -> &'static str { + "miri" + } + + fn target_config(&self, sess: &Session) -> TargetConfig { + let native_target_config = self.native.target_config(sess); + TargetConfig { + internal_target_features: native_target_config.internal_target_features, - // Unreachable. + // The basic types and ABI always work. + has_reliable_f16: true, + has_reliable_f128: true, + // We always provide the f16 intrinsics, but some are provided via the host, + // so forward its reliability. + has_reliable_f16_math: cfg!(target_has_reliable_f16_math), + // Many f128 operations are still missing. + has_reliable_f128_math: false, + } + } + + fn target_cpu(&self, _sess: &Session) -> String { + String::new() + } + + // Everything complicated is forwarded to the dummy backend. + + fn supported_crate_types(&self, sess: &Session) -> Vec { + self.dummy.supported_crate_types(sess) + } + + fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box { + self.dummy.codegen_crate(tcx) + } + + fn join_codegen( + &self, + ongoing_codegen: Box, + sess: &Session, + incr_comp_session: Option<&rustc_session::IncrCompSession>, + outputs: &rustc_session::config::OutputFilenames, + crate_info: &CrateInfo, + ) -> (CompiledModules, rustc_middle::dep_graph::WorkProductMap) { + self.dummy.join_codegen(ongoing_codegen, sess, incr_comp_session, outputs, crate_info) + } + + fn link( + &self, + sess: &Session, + compiled_modules: CompiledModules, + crate_info: CrateInfo, + metadata: rustc_metadata::EncodedMetadata, + outputs: &rustc_session::config::OutputFilenames, + ) { + // In the binary this should do nothing. + if self.dep { + self.dummy.link(sess, compiled_modules, crate_info, metadata, outputs) + } } } @@ -217,7 +276,8 @@ impl rustc_driver::Callbacks for MiriDepCompilerCalls { #[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint fn config(&mut self, config: &mut Config) { // We don't need actual codegen, we just emit an rlib that Miri can later consume. - config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend)); + config.make_codegen_backend = + Some(Box::new(|sess| make_miri_codegen_backend(sess, /* dep */ true))); // Avoid warnings about unsupported crate types. However, only do that we we are *not* being // queried by cargo about the supported crate types so that cargo still receives the @@ -683,4 +743,6 @@ fn main() -> ExitCode { } } run_compiler_and_exit(&rustc_args, &mut MiriCompilerCalls::new(miri_config, many_seeds)) + // Note that we *cannot* just return here, in native-lib mode we have to coordinate + // with the supervisor process! } diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 7e8c49bf9fba0..900fc58b8cd91 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -237,7 +237,7 @@ pub fn prune_stacktrace<'tcx>( /// Report the result of a Miri execution. /// /// Returns `Some` if this was regular program termination with a given exit code and a `bool` -/// indicating whether a leak check should happen; `None` otherwise. +/// indicating whether a leak check should happen; `None` if execution was aborted with an error. pub fn report_result<'tcx>( ecx: &InterpCx<'tcx, MiriMachine<'tcx>>, res: InterpErrorInfo<'tcx>, diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index f33dc9d070971..3ba16971eca84 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -510,8 +510,8 @@ fn call_main<'tcx>( } /// Evaluates the entry function specified by `entry_id`. -/// Returns `Some(return_code)` if program execution completed. -/// Returns `None` if an evaluation error occurred. +/// Returns `Ok(())` if program execution completed with exit code 0. +/// Returns `Err(code)` if an evaluation error occurred or the program returned a non-0 exit code. pub fn eval_entry<'tcx>( tcx: TyCtxt<'tcx>, entry_id: DefId, diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.notrace.stderr b/src/tools/miri/tests/native-lib/pass/ptr_read_access.notrace.stderr index bc2fcac08f014..e1b6ce12fac90 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.notrace.stderr +++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.notrace.stderr @@ -14,3 +14,5 @@ LL | unsafe { print_pointer(&x) }; 1: main at tests/native-lib/pass/ptr_read_access.rs:LL:CC +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.trace.stderr b/src/tools/miri/tests/native-lib/pass/ptr_read_access.trace.stderr index c7f30c114f16a..3295eda01fffc 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.trace.stderr +++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.trace.stderr @@ -15,3 +15,5 @@ LL | unsafe { print_pointer(&x) }; 1: main at tests/native-lib/pass/ptr_read_access.rs:LL:CC +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/native-lib/pass/ptr_write_access.notrace.stderr b/src/tools/miri/tests/native-lib/pass/ptr_write_access.notrace.stderr index 15b2bc6df63fa..c86cf783f5d04 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_write_access.notrace.stderr +++ b/src/tools/miri/tests/native-lib/pass/ptr_write_access.notrace.stderr @@ -14,3 +14,5 @@ LL | unsafe { increment_int(&mut x) }; 1: main at tests/native-lib/pass/ptr_write_access.rs:LL:CC +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/native-lib/pass/ptr_write_access.trace.stderr b/src/tools/miri/tests/native-lib/pass/ptr_write_access.trace.stderr index d12a25f84b370..1c62afa09c799 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_write_access.trace.stderr +++ b/src/tools/miri/tests/native-lib/pass/ptr_write_access.trace.stderr @@ -15,3 +15,5 @@ LL | unsafe { increment_int(&mut x) }; 1: main at tests/native-lib/pass/ptr_write_access.rs:LL:CC +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/pass-dep/libc/fcntl_f-fullfsync_apple.stderr b/src/tools/miri/tests/pass-dep/libc/fcntl_f-fullfsync_apple.stderr index 09a24e1e5d74d..718ddf4e7f459 100644 --- a/src/tools/miri/tests/pass-dep/libc/fcntl_f-fullfsync_apple.stderr +++ b/src/tools/miri/tests/pass-dep/libc/fcntl_f-fullfsync_apple.stderr @@ -1,2 +1,4 @@ warning: `fcntl` was made to return an error due to isolation +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.stderr b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.stderr index b0cadfb970bf3..a3ed50bd9a65f 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.stderr +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.stderr @@ -2,3 +2,5 @@ warning: `readlink` was made to return an error due to isolation warning: `$STAT` was made to return an error due to isolation +warning: 2 warnings emitted + diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-invalid-addr.stderr b/src/tools/miri/tests/pass-dep/libc/libc-socket-invalid-addr.stderr index 4eea2b6d24fb3..ae73ce17e7ab8 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-invalid-addr.stderr +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-invalid-addr.stderr @@ -6,3 +6,5 @@ LL | unsafe { libc::getaddrinfo(node_c_str.as_ptr(), service_c_str.as_pt | = note: Miri cannot return proper error information from this call; only a generic error code is being returned +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.windows_host.stderr b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.windows_host.stderr index 006e911499a86..9ce38a904ba78 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.windows_host.stderr +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.windows_host.stderr @@ -19,3 +19,5 @@ LL | libc::getsockname(client_sockfd, storage, len) 4: main at tests/pass-dep/libc/libc-socket-no-blocking.rs:LL:CC +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-with-isolation.stderr b/src/tools/miri/tests/pass-dep/libc/libc-socket-with-isolation.stderr index 36fc0a5aac328..f7cfb6138cdcc 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-with-isolation.stderr +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-with-isolation.stderr @@ -1,2 +1,4 @@ warning: `socket` was made to return an error due to isolation +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/pass-dep/shims/gettid.rs b/src/tools/miri/tests/pass-dep/shims/gettid.rs index 2522a15219148..90e456d27f523 100644 --- a/src/tools/miri/tests/pass-dep/shims/gettid.rs +++ b/src/tools/miri/tests/pass-dep/shims/gettid.rs @@ -3,6 +3,7 @@ //@ [without_isolation] compile-flags: -Zmiri-disable-isolation #![feature(linkage)] +#![allow(unused_features)] // only used on some targets fn gettid() -> u64 { cfg_select! { diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs index d1fd92814d950..4cf25c65af9ab 100644 --- a/src/tools/miri/tests/pass/async-closure-drop.rs +++ b/src/tools/miri/tests/pass/async-closure-drop.rs @@ -1,4 +1,4 @@ -#![feature(async_fn_traits, async_trait_bounds)] +#![feature(async_trait_bounds)] use std::future::Future; use std::pin::pin; diff --git a/src/tools/miri/tests/pass/async-closure.rs b/src/tools/miri/tests/pass/async-closure.rs index 5067f1d2d8e78..c67af28b37802 100644 --- a/src/tools/miri/tests/pass/async-closure.rs +++ b/src/tools/miri/tests/pass/async-closure.rs @@ -1,5 +1,3 @@ -#![feature(async_fn_traits)] - use std::future::Future; use std::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce}; use std::pin::pin; diff --git a/src/tools/miri/tests/pass/async-drop.rs b/src/tools/miri/tests/pass/async-drop.rs index 3461af5bededf..0291c74a75650 100644 --- a/src/tools/miri/tests/pass/async-drop.rs +++ b/src/tools/miri/tests/pass/async-drop.rs @@ -7,7 +7,7 @@ // please consider modifying rustc's async drop test at // `tests/ui/async-await/async-drop/async-drop-initial.rs`. -#![feature(async_drop, impl_trait_in_assoc_type)] +#![feature(async_drop)] #![allow(incomplete_features, dead_code)] // FIXME(zetanumbers): consider AsyncDestruct::async_drop cleanup tests diff --git a/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs b/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs index 5689ad0e62e2b..da984fe133689 100644 --- a/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs +++ b/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs @@ -1,7 +1,7 @@ //@revisions: stack tree tree_implicit_writes //@[tree_implicit_writes]compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(allocator_api)] + use std::alloc::{Layout, alloc, dealloc}; use std::cell::Cell; use std::ptr; diff --git a/src/tools/miri/tests/pass/extern_types.stack.stderr b/src/tools/miri/tests/pass/extern_types.stack.stderr index 88825169e1cd7..c1a66d92a7241 100644 --- a/src/tools/miri/tests/pass/extern_types.stack.stderr +++ b/src/tools/miri/tests/pass/extern_types.stack.stderr @@ -7,3 +7,5 @@ LL | let x: &Foo = unsafe { &*(ptr::without_provenance::<()>(16) as *const F = help: `extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code = help: try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/pass/open_a_file_in_proc.stderr b/src/tools/miri/tests/pass/open_a_file_in_proc.stderr index c80b11ecb37bb..1667200204ac7 100644 --- a/src/tools/miri/tests/pass/open_a_file_in_proc.stderr +++ b/src/tools/miri/tests/pass/open_a_file_in_proc.stderr @@ -30,3 +30,5 @@ LL | let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode a 11: main at tests/pass/open_a_file_in_proc.rs:LL:CC +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/pass/shims/env/current_dir_with_isolation.stderr b/src/tools/miri/tests/pass/shims/env/current_dir_with_isolation.stderr index 589ca65a1e47e..6133368b01859 100644 --- a/src/tools/miri/tests/pass/shims/env/current_dir_with_isolation.stderr +++ b/src/tools/miri/tests/pass/shims/env/current_dir_with_isolation.stderr @@ -2,3 +2,5 @@ warning: `$GETCWD` was made to return an error due to isolation warning: `$SETCWD` was made to return an error due to isolation +warning: 2 warnings emitted + diff --git a/src/tools/miri/tests/pass/shims/fs-with-isolation.stderr b/src/tools/miri/tests/pass/shims/fs-with-isolation.stderr index 452c5b9b772aa..abcb6221af214 100644 --- a/src/tools/miri/tests/pass/shims/fs-with-isolation.stderr +++ b/src/tools/miri/tests/pass/shims/fs-with-isolation.stderr @@ -14,3 +14,5 @@ warning: `rmdir` was made to return an error due to isolation warning: `opendir` was made to return an error due to isolation +warning: 8 warnings emitted + diff --git a/src/tools/miri/tests/pass/shims/socket-address.stderr b/src/tools/miri/tests/pass/shims/socket-address.stderr index 7091c3b6c6d5a..12b7aa1514c87 100644 --- a/src/tools/miri/tests/pass/shims/socket-address.stderr +++ b/src/tools/miri/tests/pass/shims/socket-address.stderr @@ -23,3 +23,5 @@ LL | cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &m 7: main at tests/pass/shims/socket-address.rs:LL:CC +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr index 171bf0c82d511..7ec8b04cfce01 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr @@ -3,3 +3,5 @@ warning: target feature `sse2` must be enabled to ensure that the ABI of the cur = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #116344 +warning: 1 warning emitted + diff --git a/src/tools/miri/tests/pass/stacked_borrows/coroutine-self-referential.rs b/src/tools/miri/tests/pass/stacked_borrows/coroutine-self-referential.rs index 72e360fe19a1f..4fef797d7c282 100644 --- a/src/tools/miri/tests/pass/stacked_borrows/coroutine-self-referential.rs +++ b/src/tools/miri/tests/pass/stacked_borrows/coroutine-self-referential.rs @@ -1,6 +1,6 @@ // See https://github.com/rust-lang/unsafe-code-guidelines/issues/148: // this fails when Stacked Borrows is strictly applied even to `!Unpin` types. -#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] +#![feature(coroutines, coroutine_trait)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; diff --git a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs index 4bcaf823e99ca..2672294220ab6 100644 --- a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs +++ b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs @@ -1,7 +1,6 @@ //@revisions: tree tree_implicit_writes //@[tree_implicit_writes]compile-flags: -Zmiri-tree-borrows-implicit-writes //@compile-flags: -Zmiri-tree-borrows -#![feature(allocator_api)] use std::{mem, ptr}; diff --git a/tests/assembly-llvm/asm/powerpc-types.rs b/tests/assembly-llvm/asm/powerpc-types.rs index 211c817a325cb..a4de2f42e1636 100644 --- a/tests/assembly-llvm/asm/powerpc-types.rs +++ b/tests/assembly-llvm/asm/powerpc-types.rs @@ -1,43 +1,97 @@ +// ignore-tidy-file-linelength (some revision //@ lines are over 100 chars long) + //@ add-minicore -//@ revisions: powerpc powerpc_altivec powerpc_vsx powerpc64 powerpc64_vsx +//@ revisions: powerpc powerpc_altivec powerpc_vsx powerpc_power8 powerpc64 powerpc64_vsx powerpc64_power8 powerpc64le //@ assembly-output: emit-asm //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu //@[powerpc] needs-llvm-components: powerpc //@[powerpc_altivec] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec --cfg altivec //@[powerpc_altivec] needs-llvm-components: powerpc +//@[powerpc_altivec] filecheck-flags: --check-prefix altivec //@[powerpc_vsx] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec,+vsx --cfg altivec --cfg vsx //@[powerpc_vsx] needs-llvm-components: powerpc +//@[powerpc_vsx] filecheck-flags: --check-prefix altivec --check-prefix vsx +//@[powerpc_power8] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec,+vsx,+power8-vector --cfg altivec --cfg vsx --cfg power8 +//@[powerpc_power8] needs-llvm-components: powerpc +//@[powerpc_power8] filecheck-flags: --check-prefix altivec --check-prefix vsx --check-prefix power8 //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu --cfg altivec //@[powerpc64] needs-llvm-components: powerpc -//@[powerpc64_vsx] compile-flags: --target powerpc64-unknown-linux-gnu -C target-feature=+vsx --cfg altivec --cfg vsx +//@[powerpc64] filecheck-flags: --check-prefix altivec +//@[powerpc64_vsx] compile-flags: --target powerpc64-unknown-linux-gnu -C target-feature=+vsx --cfg powerpc64 --cfg altivec --cfg vsx //@[powerpc64_vsx] needs-llvm-components: powerpc -//@ compile-flags: -Zmerge-functions=disabled - -#![feature(no_core, asm_experimental_arch)] +//@[powerpc64_vsx] filecheck-flags: --check-prefix powerpc64 --check-prefix altivec --check-prefix vsx +//@[powerpc64_power8] compile-flags: --target powerpc64-unknown-linux-gnu -C target-feature=+vsx,+power8-vector --cfg powerpc64 --cfg altivec --cfg vsx --cfg power8 +//@[powerpc64_power8] needs-llvm-components: powerpc +//@[powerpc64_power8] filecheck-flags: --check-prefix powerpc64 --check-prefix altivec --check-prefix vsx --check-prefix power8 +//@[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu --cfg powerpc64 --cfg altivec --cfg vsx --cfg power8 +//@[powerpc64le] needs-llvm-components: powerpc +//@[powerpc64le] filecheck-flags: --check-prefix powerpc64 --check-prefix altivec --check-prefix vsx --check-prefix power8 +//@ compile-flags: -Zmerge-functions=disabled -O +//@ compile-flags: --check-cfg=cfg(altivec,vsx,power8) + +#![feature(no_core)] #![crate_type = "rlib"] #![no_core] -#![allow(asm_sub_register, non_camel_case_types)] +#![allow(asm_sub_register, non_camel_case_types, unused_imports)] +#![deny(unexpected_cfgs)] extern crate minicore; use minicore::simd::*; use minicore::*; +#[cfg_attr(powerpc64, cfg(not(target_arch = "powerpc64")))] +#[cfg_attr(not(powerpc64), cfg(target_arch = "powerpc64"))] +compile_error!("powerpc64 cfg and target arch mismatch"); #[cfg_attr(altivec, cfg(not(target_feature = "altivec")))] #[cfg_attr(not(altivec), cfg(target_feature = "altivec"))] compile_error!("altivec cfg and target feature mismatch"); #[cfg_attr(vsx, cfg(not(target_feature = "vsx")))] #[cfg_attr(not(vsx), cfg(target_feature = "vsx"))] compile_error!("vsx cfg and target feature mismatch"); +#[cfg_attr(power8, cfg(not(target_feature = "power8-vector")))] +#[cfg_attr(not(power8), cfg(target_feature = "power8-vector"))] +compile_error!("power8-vector cfg and target feature mismatch"); + +// Check floating point scalars are put in the right vector lane. This uses power8 for consistent +// assembly between powerpc64le and big-endian powerpc/powerpc64. + +// power8-LABEL: f32_to_f64: +// power8: .cfi_startproc +// power8-NEXT: xscvdpspn [[#INPUT:]], 1 +// powerpc64le-NEXT: vmrgow [[#INPUT - 32]], [[#INPUT - 32]], [[#INPUT - 32]] +// power8-NEXT: #APP +// power8-NEXT: xscvspdp 1, [[#INPUT]] +// power8-NEXT: #NO_APP +// power8-NEXT: blr +#[cfg(power8)] +#[unsafe(no_mangle)] +pub fn f32_to_f64(x: f32) -> f64 { + let res; + unsafe { + asm!("xscvspdp {}, {}", out(vsreg) res, in(vsreg) x, options(pure, nostack, nomem)); + }; + res +} -type ptr = *const i32; - -extern "C" { - fn extern_func(); - static extern_static: u8; +// power8-LABEL: f64_to_f32: +// power8: .cfi_startproc +// power8-NEXT: #APP +// power8-NEXT: xscvdpsp [[#OUTPUT:]], 1 +// power8-NEXT: #NO_APP +// power8-NEXT: xscvspdpn 1, [[#OUTPUT]] +// power8-NEXT: blr +#[cfg(power8)] +#[unsafe(no_mangle)] +pub fn f64_to_f32(x: f64) -> f32 { + let res; + unsafe { + asm!("xscvdpsp {}, {}", out(vsreg) res, in(vsreg) x, options(pure, nostack, nomem)); + }; + res } macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { - #[no_mangle] + #[unsafe(no_mangle)] pub unsafe fn $func(x: $ty) -> $ty { let y; asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); @@ -46,7 +100,7 @@ macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { };} macro_rules! check_reg { ($func:ident, $ty:ty, $rego:tt, $regc:tt, $mov:literal) => { - #[no_mangle] + #[unsafe(no_mangle)] pub unsafe fn $func(x: $ty) -> $ty { let y; asm!(concat!($mov, " ", $rego, ", ", $rego), lateout($regc) y, in($regc) x); @@ -116,179 +170,115 @@ check!(reg_f32, f32, freg, "fmr"); // CHECK: #NO_APP check!(reg_f64, f64, freg, "fmr"); -// powerpc_altivec-LABEL: vreg_i8x16: -// powerpc_altivec: #APP -// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_i8x16: -// powerpc64: #APP -// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc64: #NO_APP +// altivec-LABEL: vreg_i8x16: +// altivec: #APP +// altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// altivec: #NO_APP #[cfg(altivec)] check!(vreg_i8x16, i8x16, vreg, "vmr"); -// powerpc_altivec-LABEL: vreg_i16x8: -// powerpc_altivec: #APP -// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_i16x8: -// powerpc64: #APP -// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc64: #NO_APP +// altivec-LABEL: vreg_i16x8: +// altivec: #APP +// altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// altivec: #NO_APP #[cfg(altivec)] check!(vreg_i16x8, i16x8, vreg, "vmr"); -// powerpc_altivec-LABEL: vreg_i32x4: -// powerpc_altivec: #APP -// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_i32x4: -// powerpc64: #APP -// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc64: #NO_APP +// altivec-LABEL: vreg_i32x4: +// altivec: #APP +// altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// altivec: #NO_APP #[cfg(altivec)] check!(vreg_i32x4, i32x4, vreg, "vmr"); -// powerpc_vsx-LABEL: vreg_i64x2: -// powerpc_vsx: #APP -// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_i64x2: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_i64x2: +// vsx: #APP +// vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vreg_i64x2, i64x2, vreg, "vmr"); -// powerpc_altivec-LABEL: vreg_f32x4: -// powerpc_altivec: #APP -// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_f32x4: -// powerpc64: #APP -// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc64: #NO_APP +// altivec-LABEL: vreg_f32x4: +// altivec: #APP +// altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// altivec: #NO_APP #[cfg(altivec)] check!(vreg_f32x4, f32x4, vreg, "vmr"); -// powerpc_vsx-LABEL: vreg_f64x2: -// powerpc_vsx: #APP -// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_f64x2: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_f64x2: +// vsx: #APP +// vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vreg_f64x2, f64x2, vreg, "vmr"); -// powerpc_vsx-LABEL: vreg_f32: -// powerpc_vsx: #APP -// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_f32: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_f32: +// vsx: #APP +// vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vreg_f32, f32, vreg, "vmr"); -// powerpc_vsx-LABEL: vreg_f64: -// powerpc_vsx: #APP -// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_f64: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_f64: +// vsx: #APP +// vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vreg_f64, f64, vreg, "vmr"); -// powerpc_vsx-LABEL: vsreg_i8x16: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i8x16: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i8x16: +// vsx: #APP +// vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vsreg_i8x16, i8x16, vsreg, "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i16x8: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i16x8: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i16x8: +// vsx: #APP +// vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vsreg_i16x8, i16x8, vsreg, "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i32x4: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i32x4: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i32x4: +// vsx: #APP +// vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vsreg_i32x4, i32x4, vsreg, "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i64x2: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i64x2: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i64x2: +// vsx: #APP +// vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vsreg_i64x2, i64x2, vsreg, "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f32x4: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f32x4: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f32x4: +// vsx: #APP +// vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vsreg_f32x4, f32x4, vsreg, "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f64x2: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f64x2: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f64x2: +// vsx: #APP +// vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vsreg_f64x2, f64x2, vsreg, "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f32: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f32: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f32: +// vsx: #APP +// vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vsreg_f32, f32, vsreg, "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f64: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f64: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f64: +// vsx: #APP +// vsx: xvsqrtdp {{[0-9]+}}, {{[0-9]+}} +// vsx: #NO_APP #[cfg(vsx)] check!(vsreg_f64, f64, vsreg, "xvsqrtdp"); @@ -366,354 +356,226 @@ check_reg!(reg_f32_f18, f32, "18", "f18", "fmr"); // CHECK: #NO_APP check_reg!(reg_f64_f18, f64, "18", "f18", "fmr"); -// powerpc_altivec-LABEL: vreg_i8x16_v0: -// powerpc_altivec: #APP -// powerpc_altivec: vmr 0, 0 -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_i8x16_v0: -// powerpc64: #APP -// powerpc64: vmr 0, 0 -// powerpc64: #NO_APP +// altivec-LABEL: vreg_i8x16_v0: +// altivec: #APP +// altivec: vmr 0, 0 +// altivec: #NO_APP #[cfg(altivec)] check_reg!(vreg_i8x16_v0, i8x16, "0", "v0", "vmr"); -// powerpc_altivec-LABEL: vreg_i16x8_v0: -// powerpc_altivec: #APP -// powerpc_altivec: vmr 0, 0 -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_i16x8_v0: -// powerpc64: #APP -// powerpc64: vmr 0, 0 -// powerpc64: #NO_APP +// altivec-LABEL: vreg_i16x8_v0: +// altivec: #APP +// altivec: vmr 0, 0 +// altivec: #NO_APP #[cfg(altivec)] check_reg!(vreg_i16x8_v0, i16x8, "0", "v0", "vmr"); -// powerpc_altivec-LABEL: vreg_i32x4_v0: -// powerpc_altivec: #APP -// powerpc_altivec: vmr 0, 0 -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_i32x4_v0: -// powerpc64: #APP -// powerpc64: vmr 0, 0 -// powerpc64: #NO_APP +// altivec-LABEL: vreg_i32x4_v0: +// altivec: #APP +// altivec: vmr 0, 0 +// altivec: #NO_APP #[cfg(altivec)] check_reg!(vreg_i32x4_v0, i32x4, "0", "v0", "vmr"); -// powerpc_vsx-LABEL: vreg_i64x2_v0: -// powerpc_vsx: #APP -// powerpc_vsx: vmr 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_i64x2_v0: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_i64x2_v0: +// vsx: #APP +// vsx: vmr 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_i64x2_v0, i64x2, "0", "v0", "vmr"); -// powerpc_altivec-LABEL: vreg_f32x4_v0: -// powerpc_altivec: #APP -// powerpc_altivec: vmr 0, 0 -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_f32x4_v0: -// powerpc64: #APP -// powerpc64: vmr 0, 0 -// powerpc64: #NO_APP +// altivec-LABEL: vreg_f32x4_v0: +// altivec: #APP +// altivec: vmr 0, 0 +// altivec: #NO_APP #[cfg(altivec)] check_reg!(vreg_f32x4_v0, f32x4, "0", "v0", "vmr"); -// powerpc_vsx-LABEL: vreg_f64x2_v0: -// powerpc_vsx: #APP -// powerpc_vsx: vmr 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_f64x2_v0: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_f64x2_v0: +// vsx: #APP +// vsx: vmr 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_f64x2_v0, f64x2, "0", "v0", "vmr"); -// powerpc_vsx-LABEL: vreg_f32_v0: -// powerpc_vsx: #APP -// powerpc_vsx: vmr 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_f32_v0: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_f32_v0: +// vsx: #APP +// vsx: vmr 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_f32_v0, f32, "0", "v0", "vmr"); -// powerpc_vsx-LABEL: vreg_f64_v0: -// powerpc_vsx: #APP -// powerpc_vsx: vmr 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_f64_v0: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_f64_v0: +// vsx: #APP +// vsx: vmr 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_f64_v0, f64, "0", "v0", "vmr"); -// powerpc_altivec-LABEL: vreg_i8x16_v18: -// powerpc_altivec: #APP -// powerpc_altivec: vmr 18, 18 -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_i8x16_v18: -// powerpc64: #APP -// powerpc64: vmr 18, 18 -// powerpc64: #NO_APP +// altivec-LABEL: vreg_i8x16_v18: +// altivec: #APP +// altivec: vmr 18, 18 +// altivec: #NO_APP #[cfg(altivec)] check_reg!(vreg_i8x16_v18, i8x16, "18", "v18", "vmr"); -// powerpc_altivec-LABEL: vreg_i16x8_v18: -// powerpc_altivec: #APP -// powerpc_altivec: vmr 18, 18 -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_i16x8_v18: -// powerpc64: #APP -// powerpc64: vmr 18, 18 -// powerpc64: #NO_APP +// altivec-LABEL: vreg_i16x8_v18: +// altivec: #APP +// altivec: vmr 18, 18 +// altivec: #NO_APP #[cfg(altivec)] check_reg!(vreg_i16x8_v18, i16x8, "18", "v18", "vmr"); -// powerpc_altivec-LABEL: vreg_i32x4_v18: -// powerpc_altivec: #APP -// powerpc_altivec: vmr 18, 18 -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_i32x4_v18: -// powerpc64: #APP -// powerpc64: vmr 18, 18 -// powerpc64: #NO_APP +// altivec-LABEL: vreg_i32x4_v18: +// altivec: #APP +// altivec: vmr 18, 18 +// altivec: #NO_APP #[cfg(altivec)] check_reg!(vreg_i32x4_v18, i32x4, "18", "v18", "vmr"); -// powerpc_vsx-LABEL: vreg_i64x2_v18: -// powerpc_vsx: #APP -// powerpc_vsx: vmr 18, 18 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_i64x2_v18: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr 18, 18 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_i64x2_v18: +// vsx: #APP +// vsx: vmr 18, 18 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_i64x2_v18, i64x2, "18", "v18", "vmr"); -// powerpc_altivec-LABEL: vreg_f32x4_v18: -// powerpc_altivec: #APP -// powerpc_altivec: vmr 18, 18 -// powerpc_altivec: #NO_APP -// powerpc64-LABEL: vreg_f32x4_v18: -// powerpc64: #APP -// powerpc64: vmr 18, 18 -// powerpc64: #NO_APP +// altivec-LABEL: vreg_f32x4_v18: +// altivec: #APP +// altivec: vmr 18, 18 +// altivec: #NO_APP #[cfg(altivec)] check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr"); -// powerpc_vsx-LABEL: vreg_f64x2_v18: -// powerpc_vsx: #APP -// powerpc_vsx: vmr 18, 18 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_f64x2_v18: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr 18, 18 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_f64x2_v18: +// vsx: #APP +// vsx: vmr 18, 18 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr"); -// powerpc_vsx-LABEL: vreg_f32_v18: -// powerpc_vsx: #APP -// powerpc_vsx: vmr 18, 18 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_f32_v18: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr 18, 18 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_f32_v18: +// vsx: #APP +// vsx: vmr 18, 18 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_f32_v18, f32, "18", "v18", "vmr"); -// powerpc_vsx-LABEL: vreg_f64_v18: -// powerpc_vsx: #APP -// powerpc_vsx: vmr 18, 18 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vreg_f64_v18: -// powerpc64_vsx: #APP -// powerpc64_vsx: vmr 18, 18 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vreg_f64_v18: +// vsx: #APP +// vsx: vmr 18, 18 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_f64_v18, f64, "18", "v18", "vmr"); -// powerpc_vsx-LABEL: vsreg_i8x16_vs0: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i8x16_vs0: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i8x16_vs0: +// vsx: #APP +// vsx: xvsqrtdp 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_i8x16_vs0, i8x16, "0", "vs0", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i16x8_vs0: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i16x8_vs0: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i16x8_vs0: +// vsx: #APP +// vsx: xvsqrtdp 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_i16x8_vs0, i16x8, "0", "vs0", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i32x4_vs0: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i32x4_vs0: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i32x4_vs0: +// vsx: #APP +// vsx: xvsqrtdp 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_i32x4_vs0, i32x4, "0", "vs0", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i64x2_vs0: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i64x2_vs0: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i64x2_vs0: +// vsx: #APP +// vsx: xvsqrtdp 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_i64x2_vs0, i64x2, "0", "vs0", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f32x4_vs0: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f32x4_vs0: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f32x4_vs0: +// vsx: #APP +// vsx: xvsqrtdp 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_f32x4_vs0, f32x4, "0", "vs0", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f64x2_vs0: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f64x2_vs0: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f64x2_vs0: +// vsx: #APP +// vsx: xvsqrtdp 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_f64x2_vs0, f64x2, "0", "vs0", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f32_vs0: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f32_vs0: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f32_vs0: +// vsx: #APP +// vsx: xvsqrtdp 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_f32_vs0, f32, "0", "vs0", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f64_vs0: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 0, 0 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f64_vs0: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 0, 0 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f64_vs0: +// vsx: #APP +// vsx: xvsqrtdp 0, 0 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_f64_vs0, f64, "0", "vs0", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i8x16_v40: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 40, 40 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i8x16_v40: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 40, 40 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i8x16_v40: +// vsx: #APP +// vsx: xvsqrtdp 40, 40 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_i8x16_v40, i8x16, "40", "vs40", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i16x8_v40: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 40, 40 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i16x8_v40: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 40, 40 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i16x8_v40: +// vsx: #APP +// vsx: xvsqrtdp 40, 40 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_i16x8_v40, i16x8, "40", "vs40", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i32x4_v40: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 40, 40 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i32x4_v40: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 40, 40 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i32x4_v40: +// vsx: #APP +// vsx: xvsqrtdp 40, 40 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_i32x4_v40, i32x4, "40", "vs40", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_i64x2_v40: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 40, 40 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_i64x2_v40: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 40, 40 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_i64x2_v40: +// vsx: #APP +// vsx: xvsqrtdp 40, 40 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_i64x2_v40, i64x2, "40", "vs40", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f32x4_v40: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 40, 40 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f32x4_v40: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 40, 40 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f32x4_v40: +// vsx: #APP +// vsx: xvsqrtdp 40, 40 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_f32x4_v40, f32x4, "40", "vs40", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f64x2_v40: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 40, 40 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f64x2_v40: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 40, 40 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f64x2_v40: +// vsx: #APP +// vsx: xvsqrtdp 40, 40 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_f64x2_v40, f64x2, "40", "vs40", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f32_v40: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 40, 40 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f32_v40: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 40, 40 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f32_v40: +// vsx: #APP +// vsx: xvsqrtdp 40, 40 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_f32_v40, f32, "40", "vs40", "xvsqrtdp"); -// powerpc_vsx-LABEL: vsreg_f64_v40: -// powerpc_vsx: #APP -// powerpc_vsx: xvsqrtdp 40, 40 -// powerpc_vsx: #NO_APP -// powerpc64_vsx-LABEL: vsreg_f64_v40: -// powerpc64_vsx: #APP -// powerpc64_vsx: xvsqrtdp 40, 40 -// powerpc64_vsx: #NO_APP +// vsx-LABEL: vsreg_f64_v40: +// vsx: #APP +// vsx: xvsqrtdp 40, 40 +// vsx: #NO_APP #[cfg(vsx)] check_reg!(vsreg_f64_v40, f64, "40", "vs40", "xvsqrtdp"); diff --git a/tests/crashes/137129.rs b/tests/crashes/137129.rs new file mode 100644 index 0000000000000..4a70f0d1d2dcb --- /dev/null +++ b/tests/crashes/137129.rs @@ -0,0 +1,6 @@ +//@ known-bug: #137129 +#![core::contracts::ensures] +struct A { + b: dyn A + 'static, +} +fn c() {} diff --git a/tests/crashes/141293.rs b/tests/crashes/141293.rs new file mode 100644 index 0000000000000..07ade1eb6edea --- /dev/null +++ b/tests/crashes/141293.rs @@ -0,0 +1,4 @@ +//@ known-bug: #141293 +#![feature(unsafe_binders)] +type X = unsafe (); +fn main() {} diff --git a/tests/crashes/147917.rs b/tests/crashes/147917.rs new file mode 100644 index 0000000000000..14000f6c2b6c8 --- /dev/null +++ b/tests/crashes/147917.rs @@ -0,0 +1,13 @@ +//@ known-bug: #147917 +#![feature(custom_inner_attributes)] +impl[u8; + #[cfg_attr]({ + #[cfg_attr] { + { + #! + } + } ! + }) +] { + #![cfg_eval] +} diff --git a/tests/crashes/148614.rs b/tests/crashes/148614.rs new file mode 100644 index 0000000000000..d7c24c0e4d9fc --- /dev/null +++ b/tests/crashes/148614.rs @@ -0,0 +1,11 @@ +//@ known-bug: #148614 +use std::arch::global_asm; + +static X: isize = 3; + +global_asm! { + "{}", + sym X::<{}>, +} + +fn main() {} diff --git a/tests/crashes/148621.rs b/tests/crashes/148621.rs new file mode 100644 index 0000000000000..ca0253e488620 --- /dev/null +++ b/tests/crashes/148621.rs @@ -0,0 +1,14 @@ +//@ known-bug: #148621 +type Foo = impl std::fmt::Debug; + +trait Identity { + type T; +} + +impl Clone for Foo<<() as Identity>::T> { + fn clone(&self) -> Self { + loop {} + } +} + +fn main() {} diff --git a/tests/crashes/148628.rs b/tests/crashes/148628.rs new file mode 100644 index 0000000000000..478588eed8747 --- /dev/null +++ b/tests/crashes/148628.rs @@ -0,0 +1,10 @@ +//@ known-bug: #148628 +use std::arch::asm; + +static TEST: i32 = 0; + +pub unsafe fn bar() { + asm!("/* {0} */", sym TEST::); +} + +fn main() {} diff --git a/tests/crashes/148888.rs b/tests/crashes/148888.rs new file mode 100644 index 0000000000000..277d9415fef2e --- /dev/null +++ b/tests/crashes/148888.rs @@ -0,0 +1,19 @@ +//@ known-bug: #148888 +#![feature(type_alias_impl_trait)] + +type Foo = impl Send; + +trait Trait { + const CONST: u32; +} + +impl Trait for Foo { + const CONST: u32 = 0; +} + +#[repr(u32)] +enum QSelfInConst { + Variant = ::CONST, +} + +fn main() {} diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.rs b/tests/ui/suggestions/struct-field-type-including-single-colon.rs index 08055bb03ee72..3cac841b4c4ec 100644 --- a/tests/ui/suggestions/struct-field-type-including-single-colon.rs +++ b/tests/ui/suggestions/struct-field-type-including-single-colon.rs @@ -18,9 +18,7 @@ struct Bar { // Issue #92685. struct Qux { c: Vec, - //~^ ERROR: struct takes at least 1 generic argument but 0 generic arguments were supplied - //~| ERROR: associated item constraints are not allowed here - //~| ERROR: cannot find trait `A` in this scope + //~^ ERROR: cannot find trait `A` in this scope } fn main() {} diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr index a716e70fcb83a..1b5ff424628c8 100644 --- a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr +++ b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr @@ -35,30 +35,6 @@ help: you might have meant to write a path instead of an associated type bound LL | c: Vec, | + -error[E0107]: struct takes at least 1 generic argument but 0 generic arguments were supplied - --> $DIR/struct-field-type-including-single-colon.rs:20:8 - | -LL | c: Vec, - | ^^^ expected at least 1 generic argument - | -help: add missing generic argument - | -LL | c: Vec, - | ++ - -error[E0229]: associated item constraints are not allowed here - --> $DIR/struct-field-type-including-single-colon.rs:20:12 - | -LL | c: Vec, - | ^^^^^ associated item constraint not allowed here - | -help: consider removing this associated item constraint - | -LL - c: Vec, -LL + c: Vec, - | - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0229, E0405. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs index 99f943d71e9e5..0ffbe31531672 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs +++ b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs @@ -6,7 +6,4 @@ fn main() { let _: Vec = A::B; //~^ ERROR cannot find trait `B` in this scope //~| HELP you might have meant to write a path instead of an associated type bound - //~| ERROR struct takes at least 1 generic argument but 0 generic arguments were supplied - //~| HELP add missing generic argument - //~| ERROR associated item constraints are not allowed here } diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr index a424bc7e72452..32ed4048ee851 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr @@ -9,24 +9,6 @@ help: you might have meant to write a path instead of an associated type bound LL | let _: Vec = A::B; | + -error[E0107]: struct takes at least 1 generic argument but 0 generic arguments were supplied - --> $DIR/type-ascription-instead-of-path-in-type.rs:6:12 - | -LL | let _: Vec = A::B; - | ^^^ expected at least 1 generic argument - | -help: add missing generic argument - | -LL | let _: Vec = A::B; - | ++ - -error[E0229]: associated item constraints are not allowed here - --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16 - | -LL | let _: Vec = A::B; - | ^^^ associated item constraint not allowed here - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0107, E0229, E0405. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/traits/next-solver/object-projection-const-bound-rerun.rs b/tests/ui/traits/next-solver/object-projection-const-bound-rerun.rs new file mode 100644 index 0000000000000..1c5732835ebf1 --- /dev/null +++ b/tests/ui/traits/next-solver/object-projection-const-bound-rerun.rs @@ -0,0 +1,27 @@ +//! Regression test for . +//@ compile-flags: -Znext-solver +//@ check-pass + +trait Trait { + type Assoc; +} +impl Trait for T +where + [T; 1 + 1]: Sized, +{ + type Assoc = (); +} + +trait Proj { + type Assoc; +} + +trait Foo: Proj<::Assoc, Assoc = ()> { + fn m(&self); +} + +fn f(x: &dyn Foo) { + x.m() +} + +fn main() {}