diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index af071c706856e..4e2bef94982cc 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -33,3 +33,6 @@ c682aa162b0d41e21cc6748f4fecfe01efb69d1f 1fcae03369abb4c2cc180cd5a49e1f4440a81300 # Breaking up of compiletest runtest.rs 60600a6fa403216bfd66e04f948b1822f6450af7 + +# std: move futex implementations into sys::sync::futex +7232830d10b6af772e0e4670a2ff61dd23830ed8 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 93388ddd24075..872c8a0ade1ab 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,5 +1,16 @@ + +- [ ] I did not use an LLM to create a change in this PR. +- [ ] I used an LLM to create a change in this PR, and I have explained below how it was used. + [`fn inferred_outlives_of`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/mod.rs#L20 [`fn inferred_outlives_crate`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/mod.rs#L83 - [`fn insert_required_predicates_to_be_wf`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs#L89 - [`fn check_explicit_predicates`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs#L238 - [`fn insert_outlives_predicate`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/utils.rs#L15 + [`fn insert_required_clauses_to_be_wf`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs#L89 + [`fn check_explicit_clauses`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs#L238 + [`fn insert_outlives_clause`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/utils.rs#L15 [nostatic]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/utils.rs#L159-L165 ## implicit implied bounds diff --git a/src/doc/rustc-dev-guide/src/typing-parameter-envs.md b/src/doc/rustc-dev-guide/src/typing-parameter-envs.md index f5a19ea328696..8e13f9fb43327 100644 --- a/src/doc/rustc-dev-guide/src/typing-parameter-envs.md +++ b/src/doc/rustc-dev-guide/src/typing-parameter-envs.md @@ -25,7 +25,7 @@ such as `ConstArgHasType` or (some) implied bounds. In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. A `ParamEnv` can also be created with arbitrary sets of clauses that are not derived from a specific item, -such as in [`compare_method_predicate_entailment`][method_pred_entailment] where we create a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. +such as in [`compare_method_clause_entailment`][method_clause_entailment] where we create a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. --- @@ -76,7 +76,7 @@ fn foo2(a: T) { ``` [clauses_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/clauses_of/fn.clauses_of.html -[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html +[method_clause_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_clause_entailment.html [query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env [normalization]: normalization.md @@ -111,7 +111,7 @@ Creating an empty environment with `ParamEnv::empty` is typically only done eith or as part of some analysis that do not expect to ever encounter generic parameters (e.g. various parts of coherence/orphan check). -Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (e.g. [`compare_method_predicate_entailment`][method_pred_entailment]). +Creating an env from an arbitrary set of where clauses is usually unnecessary and should only be done if the environment you need does not correspond to an actual item in the source code (e.g. [`compare_method_clause_entailment`][method_clause_entailment]). [param_env_new]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.new [normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html @@ -124,7 +124,7 @@ Creating an env from an arbitrary set of where clauses is usually unnecessary an [mirtypeck_param_env]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/struct.TypeChecker.html#structfield.param_env [env_empty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.empty [param_env_query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#structfield.param_env -[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html +[method_clause_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_clause_entailment.html [predicate_emitting_relation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/relate/combine/trait.PredicateEmittingRelation.html [tenv_mono]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypingEnv.html#method.fully_monomorphized [compiler_help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index f9e97530214fe..52dc58f65bb8b 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -516,10 +516,6 @@ Parallelism used by compilation stages converting backend IR to object files. In any case the parallelism here may be additionally limited dynamically by jobserver passed from a higher level build system like cargo. -Note: the backend parallelism limit may currently work incorrectly if `jobs-frontend` or `jobs` -have larger value than `jobs-backend`, or if the inherited jobserver can give a larger number -of tokens. - ### Linker parallelism Parallelism used by linker when combining object files into a final binary. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1e0c06cb031a7..9186b76f5d2b2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -432,9 +432,9 @@ pub(crate) fn clean_clause<'tcx>( let bound_clause = clause.kind(); match bound_clause.skip_binder() { ty::ClauseKind::Trait(pred) => clean_poly_trait_predicate(bound_clause.rebind(pred), cx), - ty::ClauseKind::RegionOutlives(pred) => Some(clean_region_outlives_predicate(pred, cx.tcx)), + ty::ClauseKind::RegionOutlives(pred) => Some(clean_region_outlives_clause(pred, cx.tcx)), ty::ClauseKind::TypeOutlives(pred) => { - Some(clean_type_outlives_predicate(bound_clause.rebind(pred), cx)) + Some(clean_type_outlives_clause(bound_clause.rebind(pred), cx)) } ty::ClauseKind::Projection(pred) => { Some(clean_projection_predicate(bound_clause.rebind(pred), cx)) @@ -467,11 +467,11 @@ fn clean_poly_trait_predicate<'tcx>( }) } -fn clean_region_outlives_predicate<'tcx>( - pred: ty::RegionOutlivesPredicate<'tcx>, +fn clean_region_outlives_clause<'tcx>( + clause: ty::RegionOutlivesClause<'tcx>, tcx: TyCtxt<'tcx>, ) -> WherePredicate { - let ty::OutlivesPredicate(a, b) = pred; + let ty::OutlivesClause(a, b) = clause; WherePredicate::RegionPredicate { lifetime: clean_middle_region(a, tcx).expect("failed to clean lifetime"), @@ -481,14 +481,14 @@ fn clean_region_outlives_predicate<'tcx>( } } -fn clean_type_outlives_predicate<'tcx>( - pred: ty::Binder<'tcx, ty::TypeOutlivesPredicate<'tcx>>, +fn clean_type_outlives_clause<'tcx>( + clause: ty::Binder<'tcx, ty::TypeOutlivesClause<'tcx>>, cx: &mut DocContext<'tcx>, ) -> WherePredicate { - let ty::OutlivesPredicate(ty, lt) = pred.skip_binder(); + let ty::OutlivesClause(ty, lt) = clause.skip_binder(); WherePredicate::BoundPredicate { - ty: clean_middle_ty(pred.rebind(ty), cx, None, None), + ty: clean_middle_ty(clause.rebind(ty), cx, None, None), bounds: vec![GenericBound::Outlives( clean_middle_region(lt, cx.tcx).expect("failed to clean lifetimes"), )], @@ -903,7 +903,7 @@ fn clean_ty_generics_inner<'tcx>( ty::ClauseKind::Trait(pred) if let ty::Param(param) = pred.self_ty().kind() => { Some(param.index) } - ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) + ty::ClauseKind::TypeOutlives(ty::OutlivesClause(ty, _reg)) if let ty::Param(param) = ty.kind() => { Some(param.index) @@ -2401,7 +2401,7 @@ fn clean_middle_opaque_bounds<'tcx>( let bound_predicate = bound.kind(); let trait_ref = match bound_predicate.skip_binder() { ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref), - ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => { + ty::ClauseKind::TypeOutlives(ty::OutlivesClause(_ty, reg)) => { return clean_middle_region(reg, cx.tcx).map(GenericBound::Outlives); } _ => return None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 2b7f9c4dbb7fa..7ba409626ea89 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -217,34 +217,37 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions let result = interface::run_compiler(config, |compiler| { let krate = rustc_interface::passes::parse(&compiler.sess); - let collector = rustc_interface::create_and_enter_global_ctxt(compiler, krate, |tcx| { - let crate_name = tcx.crate_name(LOCAL_CRATE).to_string(); - let opts = scrape_test_config(tcx, crate_name, args_path); - - let hir_collector = HirCollector::new( - ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()), - tcx, - ); - let tests = hir_collector.collect_crate(); - if extract_doctests { - let mut collector = extracted::ExtractedDocTests::new(); - tests.into_iter().for_each(|t| collector.add_test(t, &opts, &options)); - - let stdout = std::io::stdout(); - let mut stdout = stdout.lock(); - if let Err(error) = serde_json::ser::to_writer(&mut stdout, &collector) { - eprintln!(); - Err(format!("Failed to generate JSON output for doctests: {error:?}")) + let (collector, _incr_comp_session) = + rustc_interface::create_and_enter_global_ctxt(compiler, krate, |tcx| { + let crate_name = tcx.crate_name(LOCAL_CRATE).to_string(); + let opts = scrape_test_config(tcx, crate_name, args_path); + + let hir_collector = HirCollector::new( + ErrorCodes::from(compiler.sess.opts.unstable_features.is_nightly_build()), + tcx, + ); + let tests = hir_collector.collect_crate(); + if extract_doctests { + let mut collector = extracted::ExtractedDocTests::new(); + tests.into_iter().for_each(|t| collector.add_test(t, &opts, &options)); + + let stdout = std::io::stdout(); + let mut stdout = stdout.lock(); + if let Err(error) = serde_json::ser::to_writer(&mut stdout, &collector) { + eprintln!(); + Err(format!("Failed to generate JSON output for doctests: {error:?}")) + } else { + Ok(None) + } } else { - Ok(None) - } - } else { - let mut collector = CreateRunnableDocTests::new(options, opts); - tests.into_iter().for_each(|t| collector.add_test(t, Some(compiler.sess.dcx()))); + let mut collector = CreateRunnableDocTests::new(options, opts); + tests + .into_iter() + .for_each(|t| collector.add_test(t, Some(compiler.sess.dcx()))); - Ok(Some(collector)) - } - }); + Ok(Some(collector)) + } + }); compiler.sess.dcx().abort_if_errors(); collector diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 7e46b2f593e49..eb382f368905f 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -12,7 +12,8 @@ use rustc_hir::attrs::{ }; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::DefId; -use rustc_hir::{HeaderSafety, Safety, find_attr}; +use rustc_hir::{HeaderSafety, Safety, find_attr, intravisit}; +use rustc_hir_pretty::PpAnn; use rustc_metadata::rendered_const; use rustc_middle::ty::TyCtxt; use rustc_middle::{bug, ty}; @@ -1243,7 +1244,10 @@ fn maybe_from_hir_attr(attr: &hir::Attribute, item_id: ItemId, tcx: TyCtxt<'_>) } fn other_attr(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Attribute { - let mut s = rustc_hir_pretty::attribute_to_string(&tcx, attr); + let mut s = rustc_hir_pretty::attribute_to_string( + &(&tcx as &dyn intravisit::HirTyCtxt<'_>) as &dyn PpAnn, + attr, + ); assert_eq!(s.pop(), Some('\n')); Attribute::Other(s) } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8bf0d7160db8e..fbb8492d8d3ec 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -874,21 +874,24 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { id: ast::DUMMY_NODE_ID, is_placeholder: false, }; - rustc_interface::create_and_enter_global_ctxt(compiler, krate, |tcx| { - let has_dep_info = render_options.dep_info().is_some(); - if render_options.emit.contains(&EmitType::HtmlNonStaticFiles) { - markdown::render_and_write(file, render_options, edition)?; - } - if has_dep_info { - // Register the loaded external files in the source map so they show up in depinfo. - // We can't load them via the source map because it gets created after we process the options. - for external_path in &loaded_paths { - let _ = compiler.sess.source_map().load_binary_file(external_path); + let (res, _incr_comp_session) = + rustc_interface::create_and_enter_global_ctxt(compiler, krate, |tcx| { + let has_dep_info = render_options.dep_info().is_some(); + if render_options.emit.contains(&EmitType::HtmlNonStaticFiles) { + markdown::render_and_write(file, render_options, edition)?; } - rustc_interface::passes::write_dep_info(tcx); - } - Ok(()) - }) + if has_dep_info { + // Register the loaded external files in the source map so they show up in depinfo. + // We can't load them via the source map because it gets created after we process the options. + for external_path in &loaded_paths { + let _ = + compiler.sess.source_map().load_binary_file(external_path); + } + rustc_interface::passes::write_dep_info(tcx); + } + Ok(()) + }); + res }), ); } @@ -997,7 +1000,7 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { unreachable!() } } - }) + }); }) } diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs index e38ba801c0bf7..9fc9f9944465c 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs @@ -6,6 +6,7 @@ use clippy_utils::{is_in_const_context, is_wild, peel_blocks_with_stmt}; use rustc_hir::{Arm, Expr, PatKind}; use rustc_lint::LateContext; use rustc_span::symbol::{kw, sym}; +use rustc_hir::intravisit; use super::MATCH_WILD_ERR_ARM; @@ -19,7 +20,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<' if ex_ty.is_diag_item(cx, sym::Result) { for arm in arms { if let PatKind::TupleStruct(ref path, inner, _) = arm.pat.kind { - let path_str = rustc_hir_pretty::qpath_to_string(&cx.tcx, path); + let path_str = rustc_hir_pretty::qpath_to_string(#[allow(trivial_casts)] &(&cx.tcx as &dyn intravisit::HirTyCtxt<'_>), path); if path_str == "Err" { let mut matching_wild = inner.iter().any(is_wild); let mut ident_bind_name = kw::Underscore; diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_mut_passed.rs b/src/tools/clippy/clippy_lints/src/unnecessary_mut_passed.rs index 60a6688927ab5..43721fa252837 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_mut_passed.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_mut_passed.rs @@ -6,6 +6,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; use rustc_session::declare_lint_pass; use std::iter; +use rustc_hir_pretty::PpAnn; +use rustc_hir::intravisit; declare_clippy_lint! { /// ### What it does @@ -51,7 +53,8 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed { cx, &mut arguments.iter(), cx.typeck_results().expr_ty(fn_expr), - &rustc_hir_pretty::qpath_to_string(&cx.tcx, path), + #[allow(trivial_casts)] + &rustc_hir_pretty::qpath_to_string(&(&cx.tcx as &dyn intravisit::HirTyCtxt<'_>) as &dyn PpAnn, path), "function", ); } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 479199414d7ec..734ca79518090 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -719,8 +719,15 @@ fn check_proc_macro_dep_list(root: &Path, cargo: &Path, bless: bool, check: &mut // Remove the proc-macro crates themselves proc_macro_deps.retain(|pkg| !is_proc_macro_pkg(&metadata[pkg])); // Sort and deduplicate the crate names. - let proc_macro_deps = - proc_macro_deps.into_iter().map(|dep| metadata[dep].name.as_ref()).collect::>(); + // Cargo package names may contain `-`, but will normalize these to `_` before passing to rustc. + // As bootstrap parses the `--crate-name` flag, use the name of the actual lib target which has + // been normalized. + let proc_macro_deps = proc_macro_deps + .into_iter() + .filter_map(|dep| { + metadata[dep].targets.iter().find_map(|target| target.is_lib().then_some(&target.name)) + }) + .collect::>(); let expected = { use std::fmt::Write; diff --git a/tests/codegen-llvm/lib-optimizations/memchr-result.rs b/tests/codegen-llvm/lib-optimizations/memchr-result.rs new file mode 100644 index 0000000000000..77abc33adde83 --- /dev/null +++ b/tests/codegen-llvm/lib-optimizations/memchr-result.rs @@ -0,0 +1,26 @@ +// Ensure `memchr` communicates that a returned index is in bounds. +//@ compile-flags: -Copt-level=3 -Zinline-mir=false +//@ only-x86_64 + +#![crate_type = "lib"] +#![feature(slice_internals)] + +extern crate core; + +use core::slice::memchr::memrchr; + +// CHECK-LABEL: @find_char +#[no_mangle] +pub fn find_char(haystack: &str, needle: char) -> Option { + // CHECK-NOT: phi { i64, i64 } + // CHECK: ret { i64, i64 } + haystack.find(needle) +} + +// CHECK-LABEL: @rfind_byte +#[no_mangle] +pub fn rfind_byte(haystack: &[u8], needle: u8) -> Option { + // CHECK-NOT: panic_bounds_check + // CHECK: ret { i1, i8 } + memrchr(needle, haystack).map(|index| haystack[index]) +} diff --git a/tests/crashes/126268.rs b/tests/crashes/102252-2.rs similarity index 86% rename from tests/crashes/126268.rs rename to tests/crashes/102252-2.rs index 82e52fa115dc9..ccb15b82736e2 100644 --- a/tests/crashes/126268.rs +++ b/tests/crashes/102252-2.rs @@ -1,4 +1,5 @@ -//@ known-bug: #126268 +//@ known-bug: #102252 + #![feature(min_specialization)] trait Trait {} @@ -16,3 +17,5 @@ struct DatasetIter<'a, R: Data> { pub struct ArrayBase {} impl<'a> Trait for DatasetIter<'a, ArrayBase> {} + +fn main() {} diff --git a/tests/crashes/125014.rs b/tests/crashes/125014.rs deleted file mode 100644 index b29042ee5983a..0000000000000 --- a/tests/crashes/125014.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: rust-lang/rust#125014 -//@ compile-flags: -Znext-solver=coherence -#![feature(specialization)] - -trait Foo {} - -impl Foo for ::Output {} - -impl Foo for u32 {} - -trait Assoc { - type Output; -} -impl Output for u32 {} -impl Assoc for ::Output { - default type Output = bool; -} diff --git a/tests/run-make/autodiff/type-trees/slice-dst-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/slice-dst-typetree/rmake.rs new file mode 100644 index 0000000000000..e0c8c87ca9e33 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/slice-dst-typetree/rmake.rs @@ -0,0 +1,19 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + rustc() + .input("test.rs") + .arg("-Zautodiff=Enable,NoPostopt") + .opt_level("0") + .arg("-Clto=fat") + .emit("llvm-ir") + .run(); + + let ir = rfs::read("test.ll"); + llvm_filecheck().patterns("slice-dst.check").check_prefix("OSSTR").stdin_buf(&ir).run(); + llvm_filecheck().patterns("slice-dst.check").check_prefix("HEADER").stdin_buf(&ir).run(); + llvm_filecheck().patterns("slice-dst.check").check_prefix("ZST").stdin_buf(&ir).run(); +} diff --git a/tests/run-make/autodiff/type-trees/slice-dst-typetree/slice-dst.check b/tests/run-make/autodiff/type-trees/slice-dst-typetree/slice-dst.check new file mode 100644 index 0000000000000..4b149c9ee090c --- /dev/null +++ b/tests/run-make/autodiff/type-trees/slice-dst-typetree/slice-dst.check @@ -0,0 +1,14 @@ +; Preserve element metadata for the `OsStr` regression from #160327. +OSSTR-LABEL: define void @split_once( +OSSTR-NOT: define +OSSTR: call void @llvm.memcpy{{.*}}"enzyme_type"="{[0]:Pointer, [0,0]:Pointer, [0,0,-1]:Integer, [0,16]:Pointer, [0,16,-1]:Integer}" + +; Preserve both data layout and length metadata for a prefixed slice-tail DST. +HEADER-LABEL: define{{.*}}@header_sum( +HEADER-SAME: ptr{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float}" +HEADER-SAME: i64 "enzyme_type"="{[0]:Integer}" + +; ZST elements produce no child metadata under the slice data pointer. +ZST-LABEL: define{{.*}}@zst_slice_len( +ZST-SAME: ptr{{.*}}"enzyme_type"="{[-1]:Pointer}" +ZST-SAME: i64 "enzyme_type"="{[0]:Integer}" diff --git a/tests/run-make/autodiff/type-trees/slice-dst-typetree/test.rs b/tests/run-make/autodiff/type-trees/slice-dst-typetree/test.rs new file mode 100644 index 0000000000000..e34a8c71f4cc5 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/slice-dst-typetree/test.rs @@ -0,0 +1,51 @@ +#![crate_type = "lib"] +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; +use std::ffi::OsStr; + +// Reduced from `clap_lex::OsStrExt::split_once`. +#[no_mangle] +#[inline(never)] +pub fn split_once<'s>(arg: &'s OsStr, needle: &str) -> Option<(&'s OsStr, &'s OsStr)> { + let bytes = arg.as_encoded_bytes(); + let index = bytes.windows(needle.len()).position(|window| window == needle.as_bytes())?; + let (first, second) = bytes.split_at(index + needle.len()); + unsafe { + Some(( + OsStr::from_encoded_bytes_unchecked(first), + OsStr::from_encoded_bytes_unchecked(second), + )) + } +} + +#[repr(C)] +pub struct Header { + tag: f32, + data: T, +} + +#[autodiff_reverse(d_header_sum, Duplicated, Active)] +#[no_mangle] +#[inline(never)] +pub fn header_sum(value: &Header<[f32]>) -> f32 { + value.tag + value.data.iter().sum::() +} + +#[no_mangle] +pub fn exercise_header_sum(value: &Header<[f32]>, derivative: &mut Header<[f32]>) -> f32 { + d_header_sum(value, derivative, 1.0) +} + +// ZST slice elements yield an empty child TypeTree; element size 0 is expected. +#[autodiff_reverse(d_zst_slice_len, Duplicated, Active)] +#[no_mangle] +#[inline(never)] +pub fn zst_slice_len(slice: &[()]) -> f32 { + slice.len() as f32 +} + +#[no_mangle] +pub fn exercise_zst_slice_len(slice: &[()], derivative: &mut [()]) -> f32 { + d_zst_slice_len(slice, derivative, 1.0) +} diff --git a/tests/rustdoc-js/auxiliary/interner.rs b/tests/rustdoc-js/auxiliary/interner.rs index 8af3b732ef7a0..c61d5a4dfec72 100644 --- a/tests/rustdoc-js/auxiliary/interner.rs +++ b/tests/rustdoc-js/auxiliary/interner.rs @@ -68,8 +68,8 @@ pub trait Interner: Sized { type PlaceholderRegion: Copy + Debug + Hash + Ord + PlaceholderLike; type Predicate: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags; type TraitPredicate: Copy + Debug + Hash + Eq; - type RegionOutlivesPredicate: Copy + Debug + Hash + Eq; - type TypeOutlivesPredicate: Copy + Debug + Hash + Eq; + type RegionOutlivesClause: Copy + Debug + Hash + Eq; + type TypeOutlivesClause: Copy + Debug + Hash + Eq; type ProjectionPredicate: Copy + Debug + Hash + Eq; type NormalizesTo: Copy + Debug + Hash + Eq; type SubtypePredicate: Copy + Debug + Hash + Eq; diff --git a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs index 610a4990a5a4b..5ddaed75aa323 100644 --- a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs @@ -16,8 +16,8 @@ use rustc_codegen_ssa::{CompiledModules, CrateInfo}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::WorkProductMap; use rustc_middle::ty::TyCtxt; -use rustc_session::Session; use rustc_session::config::OutputFilenames; +use rustc_session::{IncrCompSession, Session}; struct TheBackend; @@ -38,6 +38,7 @@ impl CodegenBackend for TheBackend { &self, ongoing_codegen: Box, _sess: &Session, + _incr_comp_session: Option<&IncrCompSession>, _outputs: &OutputFilenames, _crate_info: &CrateInfo, ) -> (CompiledModules, WorkProductMap) { diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index d99d9c42d547f..ae0f41a205bf4 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -76,10 +76,11 @@ fn compile(code: String, output: PathBuf, sysroot: Sysroot, linker: Option<&Path interface::run_compiler(config, |compiler| { let krate = rustc_interface::passes::parse(&compiler.sess); - let linker = rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| { - let _ = tcx.analysis(()); - Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend) - }); - linker.link(&compiler.sess, &*compiler.codegen_backend); + let (linker, incr_comp_session) = + rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| { + let _ = tcx.analysis(()); + Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend) + }); + linker.link(&compiler.sess, incr_comp_session, &*compiler.codegen_backend); }); } diff --git a/tests/ui/associated-types/normalization-generality-2.rs b/tests/ui/associated-types/normalization-generality-2.rs index 2a50f7e449add..2e7f317bd6f68 100644 --- a/tests/ui/associated-types/normalization-generality-2.rs +++ b/tests/ui/associated-types/normalization-generality-2.rs @@ -5,7 +5,7 @@ // Ensures that we don't regress on "implementation is not general enough" when // normalizating under binders. Unlike `normalization-generality.rs`, this also produces -// type outlives predicates that we must ignore. +// type outlives clauses that we must ignore. pub unsafe trait Yokeable<'a> { type Output: 'a; diff --git a/tests/ui/compile-flags/jobs/jobs-pass-link.rs b/tests/ui/compile-flags/jobs/jobs-pass-link.rs index 70058dfcf7bf6..847a0d10ff977 100644 --- a/tests/ui/compile-flags/jobs/jobs-pass-link.rs +++ b/tests/ui/compile-flags/jobs/jobs-pass-link.rs @@ -1,4 +1,4 @@ //@ build-pass -//@ compile-flags: -Z unstable-options --jobs-linker 2 +//@ compile-flags: -Z unstable-options --jobs-linker 2 --jobs-backend 1 fn main() {} diff --git a/tests/ui/fmt/no-inline-literals-out-of-range.stderr b/tests/ui/fmt/no-inline-literals-out-of-range.stderr index 0800fb2497619..744a4e5625fef 100644 --- a/tests/ui/fmt/no-inline-literals-out-of-range.stderr +++ b/tests/ui/fmt/no-inline-literals-out-of-range.stderr @@ -13,8 +13,9 @@ LL + format_args!("{}", 0x8f_u8); // issue #115423 | help: to use as a negative number (decimal `-113`), consider using the type `u8` for the literal and cast it to `i8` | -LL | format_args!("{}", 0x8f_u8 as i8); // issue #115423 - | +++++ +LL - format_args!("{}", 0x8f_i8); // issue #115423 +LL + format_args!("{}", 0x8f_u8.cast_signed()); // issue #115423 + | error: literal out of range for `u8` --> $DIR/no-inline-literals-out-of-range.rs:6:24 @@ -50,8 +51,8 @@ LL | format_args!("{}", 0xffff_ffff); // treat unsuffixed literals as i32 = help: consider using the type `u32` instead help: to use as a negative number (decimal `-1`), consider using the type `u32` for the literal and cast it to `i32` | -LL | format_args!("{}", 0xffff_ffffu32 as i32); // treat unsuffixed literals as i32 - | ++++++++++ +LL | format_args!("{}", 0xffff_ffffu32.cast_signed()); // treat unsuffixed literals as i32 + | +++++++++++++++++ error: aborting due to 5 previous errors diff --git a/tests/ui/lint/type-overflow.stderr b/tests/ui/lint/type-overflow.stderr index 065c530adcf57..66d856dac3bdf 100644 --- a/tests/ui/lint/type-overflow.stderr +++ b/tests/ui/lint/type-overflow.stderr @@ -26,8 +26,9 @@ LL + let fail = 0b1000_0001u8; | help: to use as a negative number (decimal `-127`), consider using the type `u8` for the literal and cast it to `i8` | -LL | let fail = 0b1000_0001u8 as i8; - | +++++ +LL - let fail = 0b1000_0001i8; +LL + let fail = 0b1000_0001u8.cast_signed(); + | warning: literal out of range for `i64` --> $DIR/type-overflow.rs:15:16 @@ -43,8 +44,9 @@ LL + let fail = 0x8000_0000_0000_0000u64; | help: to use as a negative number (decimal `-9223372036854775808`), consider using the type `u64` for the literal and cast it to `i64` | -LL | let fail = 0x8000_0000_0000_0000u64 as i64; - | ++++++ +LL - let fail = 0x8000_0000_0000_0000i64; +LL + let fail = 0x8000_0000_0000_0000u64.cast_signed(); + | warning: literal out of range for `u32` --> $DIR/type-overflow.rs:19:16 @@ -64,8 +66,8 @@ LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; = help: consider using the type `u128` instead help: to use as a negative number (decimal `-170141183460469231731687303715884105728`), consider using the type `u128` for the literal and cast it to `i128` | -LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128 as i128; - | ++++++++++++ +LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128.cast_signed(); + | ++++++++++++++++++ warning: literal out of range for `i32` --> $DIR/type-overflow.rs:27:16 diff --git a/tests/ui/resolve/macro-determinacy-non-module-issue-160195.env_first.stderr b/tests/ui/resolve/macro-determinacy-non-module-issue-160195.env_first.stderr new file mode 100644 index 0000000000000..cf8c7221c2367 --- /dev/null +++ b/tests/ui/resolve/macro-determinacy-non-module-issue-160195.env_first.stderr @@ -0,0 +1,8 @@ +error: `env!()` takes 1 or 2 arguments + --> $DIR/macro-determinacy-non-module-issue-160195.rs:12:22 + | +LL | include!(concat!(env!())); + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/resolve/macro-determinacy-non-module-issue-160195.env_second.stderr b/tests/ui/resolve/macro-determinacy-non-module-issue-160195.env_second.stderr new file mode 100644 index 0000000000000..cf8c7221c2367 --- /dev/null +++ b/tests/ui/resolve/macro-determinacy-non-module-issue-160195.env_second.stderr @@ -0,0 +1,8 @@ +error: `env!()` takes 1 or 2 arguments + --> $DIR/macro-determinacy-non-module-issue-160195.rs:12:22 + | +LL | include!(concat!(env!())); + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/resolve/macro-determinacy-non-module-issue-160195.rs b/tests/ui/resolve/macro-determinacy-non-module-issue-160195.rs new file mode 100644 index 0000000000000..ca08a665e907b --- /dev/null +++ b/tests/ui/resolve/macro-determinacy-non-module-issue-160195.rs @@ -0,0 +1,21 @@ +//@ revisions: env_first env_second + +#[cfg(env_first)] +pub mod env { + #[derive(Default)] + pub struct BusinessData; +} + +pub mod interface { + use crate::env::{self}; + + include!(concat!(env!())); //~ ERROR `env!()` takes 1 or 2 arguments +} + +#[cfg(env_second)] +pub mod env { + #[derive(Default)] + pub struct BusinessData; +} + +fn main() {} diff --git a/tests/ui/specialization/associated-types-in-default-impl-bounds.rs b/tests/ui/specialization/associated-types-in-default-impl-bounds.rs new file mode 100644 index 0000000000000..ea7188810db07 --- /dev/null +++ b/tests/ui/specialization/associated-types-in-default-impl-bounds.rs @@ -0,0 +1,18 @@ +//@ check-pass + +#![allow(incomplete_features)] +#![feature(specialization)] + +// Tests that you can use a trait's associated types in the bounds of a default impl. +// Regression test for #52396. + +trait Foo { + type Baz; + fn bar(&self, _: Self::Baz); +} + +default impl> Foo for A { + fn bar(&self, _: isize) { } +} + +fn main() {} diff --git a/tests/ui/specialization/default-assoc-type-recursion-issue-80700.rs b/tests/ui/specialization/default-assoc-type-recursion-issue-80700.rs new file mode 100644 index 0000000000000..e013610121efe --- /dev/null +++ b/tests/ui/specialization/default-assoc-type-recursion-issue-80700.rs @@ -0,0 +1,35 @@ +//@ check-pass + +#![feature(specialization)] +#![allow(incomplete_features)] + +// Tests that a blanket impl supplying a `default type` does not make a +// recursive trait requirement diverge. +// Regression test for #80700. + +use std::marker::PhantomData; + +struct Nil; +struct Cons(PhantomData<(Head, Tail)>); +struct Error; + +trait GetLast { + type Output; +} + +impl GetLast for T { + default type Output = Error; +} + +impl GetLast for Cons { + type Output = Nil; +} + +impl GetLast for Cons> +where + Cons: GetLast, +{ + type Output = as GetLast>::Output; +} + +fn main() {} diff --git a/tests/ui/specialization/default-impl-coherence-overlap-issue-77026.rs b/tests/ui/specialization/default-impl-coherence-overlap-issue-77026.rs new file mode 100644 index 0000000000000..6d610805608af --- /dev/null +++ b/tests/ui/specialization/default-impl-coherence-overlap-issue-77026.rs @@ -0,0 +1,27 @@ +//@ check-fail + +#![feature(specialization)] +#![allow(incomplete_features)] + +// `default impl` still participates in coherence. However, we shouldn't get an overflow here. +// Regresion test for #77026. + +pub enum Either { + Left(L), + Right(R), +} + +default impl From for Either { + fn from(l: L) -> Self { + Either::Left(l) + } +} + +impl From for Either { + //~^ ERROR conflicting implementations of trait `From<_>` for type `Either<_, _>` + fn from(r: R) -> Self { + Either::Right(r) + } +} + +fn main() {} diff --git a/tests/ui/specialization/default-impl-coherence-overlap-issue-77026.stderr b/tests/ui/specialization/default-impl-coherence-overlap-issue-77026.stderr new file mode 100644 index 0000000000000..c9b30bf2f6495 --- /dev/null +++ b/tests/ui/specialization/default-impl-coherence-overlap-issue-77026.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `From<_>` for type `Either<_, _>` + --> $DIR/default-impl-coherence-overlap-issue-77026.rs:20:1 + | +LL | default impl From for Either { + | ------------------------------------------- first implementation here +... +LL | impl From for Either { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Either<_, _>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/default-impl-not-a-candidate-issue-48515.rs b/tests/ui/specialization/default-impl-not-a-candidate-issue-48515.rs new file mode 100644 index 0000000000000..4e31dcf117daa --- /dev/null +++ b/tests/ui/specialization/default-impl-not-a-candidate-issue-48515.rs @@ -0,0 +1,64 @@ +//@ check-fail + +#![feature(specialization)] +#![allow(incomplete_features)] + +// Tests that we don't overflow when using `default impl`. +// Regression test for #48515, #98478, and #117909. + +// #48515 + +trait TypeString { + fn type_string() -> &'static str; +} + +default impl TypeString for T { + fn type_string() -> &'static str { + "unknown type" + } +} + +impl TypeString for () { + fn type_string() -> &'static str { + "()" + } +} + +// #98478 + +trait Spam {} + +trait SpamMore: Spam {} + +default impl Spam for T where T: SpamMore {} + +struct A; + +impl SpamMore for A {} +//~^ ERROR the trait bound `A: Spam` is not satisfied + +fn needs_spam() {} + +// #117909 + +trait Set { + fn contains(&self, bit: T); +} + +default impl Set<&T> for S +where + S: Set, +{ + fn contains(&self, _: &T) {} +} + +fn main() { + let _ = ::type_string(); + //~^ ERROR the trait bound `usize: TypeString` is not satisfied + + needs_spam::(); + //~^ ERROR the trait bound `A: Spam` is not satisfied + + 0u32.contains(()); + //~^ ERROR no method named `contains` found for type `u32` in the current scope +} diff --git a/tests/ui/specialization/default-impl-not-a-candidate-issue-48515.stderr b/tests/ui/specialization/default-impl-not-a-candidate-issue-48515.stderr new file mode 100644 index 0000000000000..91df5005d7095 --- /dev/null +++ b/tests/ui/specialization/default-impl-not-a-candidate-issue-48515.stderr @@ -0,0 +1,63 @@ +error[E0277]: the trait bound `A: Spam` is not satisfied + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:37:19 + | +LL | impl SpamMore for A {} + | ^ unsatisfied trait bound + | +help: the trait `Spam` is not implemented for `A` + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:35:1 + | +LL | struct A; + | ^^^^^^^^ +note: required by a bound in `SpamMore` + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:31:17 + | +LL | trait SpamMore: Spam {} + | ^^^^ required by this bound in `SpamMore` + +error[E0277]: the trait bound `usize: TypeString` is not satisfied + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:56:14 + | +LL | let _ = ::type_string(); + | ^^^^^ the trait `TypeString` is not implemented for `usize` + | +help: the trait `TypeString` is implemented for `()` + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:21:1 + | +LL | impl TypeString for () { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `A: Spam` is not satisfied + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:59:18 + | +LL | needs_spam::(); + | ^ unsatisfied trait bound + | +help: the trait `Spam` is not implemented for `A` + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:35:1 + | +LL | struct A; + | ^^^^^^^^ +note: required by a bound in `needs_spam` + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:40:18 + | +LL | fn needs_spam() {} + | ^^^^ required by this bound in `needs_spam` + +error[E0599]: no method named `contains` found for type `u32` in the current scope + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:62:10 + | +LL | 0u32.contains(()); + | ^^^^^^^^ method not found in `u32` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Set` defines an item `contains`, perhaps you need to implement it + --> $DIR/default-impl-not-a-candidate-issue-48515.rs:44:1 + | +LL | trait Set { + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-impl-not-an-impl.rs b/tests/ui/specialization/default-impl-not-an-impl.rs new file mode 100644 index 0000000000000..2b0902173158e --- /dev/null +++ b/tests/ui/specialization/default-impl-not-an-impl.rs @@ -0,0 +1,71 @@ +//@ check-fail + +#![feature(specialization)] +#![allow(incomplete_features)] + +// Tests that a `default impl` does not count as an *actual* impl, so it cannot +// be used to satisfy trait bounds. + +// A `default impl` may omit trait items, but a real impl may not. + +trait Gapped { + fn a(&self) -> u32; + fn b(&self) -> u32; +} + +default impl Gapped for T { + fn a(&self) -> u32 { + 1 + } +} + +impl Gapped for u8 {} +//~^ ERROR not all trait items implemented, missing: `b` + +// A `default impl` that defines *every* trait item is still not an impl. + +trait Foo { + fn f(&self) -> u32; +} + +default impl Foo for T { + fn f(&self) -> u32 { + 1 + } +} + +fn need_foo(t: &T) -> u32 { + t.f() +} + +trait Bar { + fn b(&self) -> u32; +} + +impl Bar for T { + fn b(&self) -> u32 { + self.f() + } +} + +fn need_bar(t: &T) -> u32 { + t.b() +} + +fn main() { + // as a bound (UFCS `::f` is the same trait-selection path, omitted) + need_foo(&0u32); + //~^ ERROR the trait bound `u32: Foo` is not satisfied + + // as a method-probe candidate + 0u32.f(); + //~^ ERROR no method named `f` found for type `u32` in the current scope + + // when building a vtable + let _: &dyn Foo = &0u32; + //~^ ERROR the trait bound `u32: Foo` is not satisfied + + // transitively, as another impl's where-clause + need_bar(&0i64); + //~^ ERROR the trait bound `i64: Bar` is not satisfied +} diff --git a/tests/ui/specialization/default-impl-not-an-impl.stderr b/tests/ui/specialization/default-impl-not-an-impl.stderr new file mode 100644 index 0000000000000..cde757b3f98a7 --- /dev/null +++ b/tests/ui/specialization/default-impl-not-an-impl.stderr @@ -0,0 +1,69 @@ +error[E0046]: not all trait items implemented, missing: `b` + --> $DIR/default-impl-not-an-impl.rs:22:1 + | +LL | fn b(&self) -> u32; + | ------------------- `b` from trait +... +LL | impl Gapped for u8 {} + | ^^^^^^^^^^^^^^^^^^ missing `b` in implementation + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/default-impl-not-an-impl.rs:57:14 + | +LL | need_foo(&0u32); + | -------- ^^^^^ the trait `Foo` is not implemented for `u32` + | | + | required by a bound introduced by this call + | +note: required by a bound in `need_foo` + --> $DIR/default-impl-not-an-impl.rs:37:16 + | +LL | fn need_foo(t: &T) -> u32 { + | ^^^ required by this bound in `need_foo` + +error[E0599]: no method named `f` found for type `u32` in the current scope + --> $DIR/default-impl-not-an-impl.rs:61:10 + | +LL | 0u32.f(); + | ^ method not found in `u32` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `f`, perhaps you need to implement it + --> $DIR/default-impl-not-an-impl.rs:27:1 + | +LL | trait Foo { + | ^^^^^^^^^ + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/default-impl-not-an-impl.rs:65:23 + | +LL | let _: &dyn Foo = &0u32; + | ^^^^^ the trait `Foo` is not implemented for `u32` + | + = note: required for the cast from `&u32` to `&dyn Foo` + +error[E0277]: the trait bound `i64: Bar` is not satisfied + --> $DIR/default-impl-not-an-impl.rs:69:14 + | +LL | need_bar(&0i64); + | -------- ^^^^^ the trait `Foo` is not implemented for `i64` + | | + | required by a bound introduced by this call + | +note: required for `i64` to implement `Bar` + --> $DIR/default-impl-not-an-impl.rs:45:14 + | +LL | impl Bar for T { + | --- ^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `need_bar` + --> $DIR/default-impl-not-an-impl.rs:51:16 + | +LL | fn need_bar(t: &T) -> u32 { + | ^^^ required by this bound in `need_bar` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0046, E0277, E0599. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/specialization/default-impl-partial-and-inherits.rs b/tests/ui/specialization/default-impl-partial-and-inherits.rs new file mode 100644 index 0000000000000..a2c622daafb08 --- /dev/null +++ b/tests/ui/specialization/default-impl-partial-and-inherits.rs @@ -0,0 +1,111 @@ +//@ run-pass + +#![feature(specialization)] +#![allow(incomplete_features)] + +// Tests that a `default impl` does not need all items, but does contribute to +// the chain of specialization. + +// A partial `default impl` at each level of a 3-level chain. + +trait Foo { + type Assoc; + const N: u32; + fn from_root(&self) -> &'static str; + fn from_mid(&self) -> &'static str; + fn from_leaf(&self) -> &'static str; + fn from_trait(&self) -> &'static str { + "trait body" + } +} + +// root: assoc type, assoc const, one method +default impl Foo for T { + type Assoc = u8; + const N: u32 = 1; + fn from_root(&self) -> &'static str { + "root" + } +} + +// middle: one method +default impl Foo for T { + fn from_mid(&self) -> &'static str { + "mid" + } +} + +// leaf: one method. Everything else must come from the two ancestors, except +// `from_trait`, which no impl in the chain defines. +impl Foo for u32 { + fn from_leaf(&self) -> &'static str { + "leaf" + } +} + +// sibling leaf: overrides every inherited item, including assoc type and const +impl Foo for i8 { + type Assoc = bool; + const N: u32 = 2; + fn from_root(&self) -> &'static str { + "i8 root" + } + fn from_mid(&self) -> &'static str { + "i8 mid" + } + fn from_leaf(&self) -> &'static str { + "i8 leaf" + } + fn from_trait(&self) -> &'static str { + "i8 trait" + } +} + +fn generic(t: &T) -> [&'static str; 4] { + [t.from_root(), t.from_mid(), t.from_leaf(), t.from_trait()] +} + +// An empty `default impl`, and an empty real impl that inherits every item. + +trait Marker { + type A; + fn m(&self) -> &'static str; +} + +// Contributes nothing at all, and is still accepted. +default impl Marker for T {} + +// Covers every item of the trait. +default impl Marker for T { + type A = u8; + fn m(&self) -> &'static str { + "from default impl" + } +} + +// Declaration of intent and nothing else. This is what the `default impl` above +// is missing, and the only thing it is missing. +impl Marker for u32 {} + +fn main() { + // inherited across the chain, via a concrete receiver... + assert_eq!(0u32.from_root(), "root"); + assert_eq!(0u32.from_mid(), "mid"); + assert_eq!(0u32.from_leaf(), "leaf"); + assert_eq!(0u32.from_trait(), "trait body"); + assert_eq!(::N, 1); + // The omitting impl finalizes the ancestor's definition, so this normalizes. + let _: ::Assoc = 0u8; + + // ...and through a generic bound + assert_eq!(generic(&0u32), ["root", "mid", "leaf", "trait body"]); + assert_eq!(generic(&0i8), ["i8 root", "i8 mid", "i8 leaf", "i8 trait"]); + assert_eq!(::N, 2); + let _: ::Assoc = true; + + // empty impl really does implement: method, projection, and vtable + assert_eq!(0u32.m(), "from default impl"); + let _: ::A = 0u8; + let _: &dyn Marker = &0u32; + +} diff --git a/tests/ui/specialization/default-type-normalize-issue-50318.rs b/tests/ui/specialization/default-type-normalize-issue-50318.rs new file mode 100644 index 0000000000000..b69acfe47a929 --- /dev/null +++ b/tests/ui/specialization/default-type-normalize-issue-50318.rs @@ -0,0 +1,24 @@ +//@ check-fail +//@ known-bug: #50318 + +#![feature(specialization)] +#![allow(incomplete_features)] + +// Tests that we can normalize a `default type`. + +trait Trait { + type AssocType; +} + +struct Struct {} + +impl Trait for Struct { + default type AssocType = i32; +} + +type AssocType = ::AssocType; + +fn main() { + assert_eq!(std::any::type_name::(), "i32"); + let x: AssocType = 0; +} diff --git a/tests/ui/specialization/default-type-normalize-issue-50318.stderr b/tests/ui/specialization/default-type-normalize-issue-50318.stderr new file mode 100644 index 0000000000000..b0d69287adac2 --- /dev/null +++ b/tests/ui/specialization/default-type-normalize-issue-50318.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/default-type-normalize-issue-50318.rs:23:24 + | +LL | let x: AssocType = 0; + | --------- ^ expected associated type, found integer + | | + | expected due to this + | + = note: expected associated type `::AssocType` + found type `{integer}` + = help: consider constraining the associated type `::AssocType` to `{integer}` or calling a method that returns `::AssocType` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + = note: the associated type `::AssocType` is defined as `{integer}` in the implementation, but the where-bound `Struct` shadows this definition + see issue #152409 for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/default-type-self-projection-ice-issue-125014.next.stderr b/tests/ui/specialization/default-type-self-projection-ice-issue-125014.next.stderr new file mode 100644 index 0000000000000..7280c8213e5dd --- /dev/null +++ b/tests/ui/specialization/default-type-self-projection-ice-issue-125014.next.stderr @@ -0,0 +1,66 @@ +error[E0277]: the trait bound `u16: A` is not satisfied + --> $DIR/default-type-self-projection-ice-issue-125014.rs:18:12 + | +LL | impl A for ::B { + | ^^^^^^^^^^^^^ the trait `A` is not implemented for `u16` + | +help: the trait `A` is implemented for `::B` + --> $DIR/default-type-self-projection-ice-issue-125014.rs:18:1 + | +LL | impl A for ::B { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `u16: A` is not satisfied + --> $DIR/default-type-self-projection-ice-issue-125014.rs:18:12 + | +LL | impl A for ::B { + | ^^^^^^^^^^^^^ the trait `A` is not implemented for `u16` + | +help: the trait `A` is implemented for `::B` + --> $DIR/default-type-self-projection-ice-issue-125014.rs:18:1 + | +LL | impl A for ::B { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `u16: A` is not satisfied + --> $DIR/default-type-self-projection-ice-issue-125014.rs:23:22 + | +LL | default type B = (); + | ^^ the trait `A` is not implemented for `u16` + | +help: the trait `A` is implemented for `::B` + --> $DIR/default-type-self-projection-ice-issue-125014.rs:18:1 + | +LL | impl A for ::B { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `u16: A` is not satisfied + --> $DIR/default-type-self-projection-ice-issue-125014.rs:18:12 + | +LL | impl A for ::B { + | ^^^^^^^^^^^^^ the trait `A` is not implemented for `u16` + | +help: the trait `A` is implemented for `::B` + --> $DIR/default-type-self-projection-ice-issue-125014.rs:18:1 + | +LL | impl A for ::B { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `u16: A` is not satisfied + --> $DIR/default-type-self-projection-ice-issue-125014.rs:18:12 + | +LL | impl A for ::B { + | ^^^^^^^^^^^^^ the trait `A` is not implemented for `u16` + | +help: the trait `A` is implemented for `::B` + --> $DIR/default-type-self-projection-ice-issue-125014.rs:18:1 + | +LL | impl A for ::B { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-type-self-projection-ice-issue-125014.rs b/tests/ui/specialization/default-type-self-projection-ice-issue-125014.rs new file mode 100644 index 0000000000000..9b4e3eade03b6 --- /dev/null +++ b/tests/ui/specialization/default-type-self-projection-ice-issue-125014.rs @@ -0,0 +1,27 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[current] known-bug: #125014 +//@[current] failure-status: 101 +//@[current] dont-check-compiler-stderr + +// Tests that we don't ICE when a `default type` is potentially used as a self-type in an impl. +// Regression for #125014. + +#![feature(specialization)] +#![allow(incomplete_features)] + +trait A { + type B; +} + +impl A for ::B { + //[next]~^ ERROR the trait bound `u16: A` is not satisfied + //[next]~^^ ERROR the trait bound `u16: A` is not satisfied + //[next]~^^^ ERROR the trait bound `u16: A` is not satisfied + //[next]~^^^^ ERROR the trait bound `u16: A` is not satisfied + default type B = (); + //[next]~^ ERROR the trait bound `u16: A` is not satisfied +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs b/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs index 3bb2480e9e2be..57319e0e7bb21 100644 --- a/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs +++ b/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs @@ -8,7 +8,7 @@ trait HasMethod { fn method(&self); } -#[rustc_unsafe_specialization_marker] +#[unsafe(rustc_allow_lifetime_dependent_specialization)] trait Marker: HasMethod {} trait Spec { diff --git a/tests/ui/specialization/min_specialization/specialization_marker.rs b/tests/ui/specialization/min_specialization/specialization_marker.rs index 93462d02ea578..55de99d7557f4 100644 --- a/tests/ui/specialization/min_specialization/specialization_marker.rs +++ b/tests/ui/specialization/min_specialization/specialization_marker.rs @@ -1,14 +1,14 @@ -// Test that `rustc_unsafe_specialization_marker` is only allowed on marker traits. +// Test that `rustc_allow_lifetime_dependent_specialization` is only allowed on marker traits. #![feature(rustc_attrs)] -#[rustc_unsafe_specialization_marker] +#[unsafe(rustc_allow_lifetime_dependent_specialization)] trait SpecMarker { fn f(); //~^ ERROR marker traits } -#[rustc_unsafe_specialization_marker] +#[unsafe(rustc_allow_lifetime_dependent_specialization)] trait SpecMarker2 { type X; //~^ ERROR marker traits diff --git a/tests/ui/specialization/min_specialization/specialize_on_marker.rs b/tests/ui/specialization/min_specialization/specialize_on_marker.rs index f7bc057d3ba8a..8e1acf319f340 100644 --- a/tests/ui/specialization/min_specialization/specialize_on_marker.rs +++ b/tests/ui/specialization/min_specialization/specialize_on_marker.rs @@ -1,4 +1,4 @@ -// Test that specializing on a `rustc_unsafe_specialization_marker` trait is +// Test that specializing on a `rustc_allow_lifetime_dependent_specialization` trait is // allowed. //@ check-pass @@ -6,7 +6,7 @@ #![feature(min_specialization)] #![feature(rustc_attrs)] -#[rustc_unsafe_specialization_marker] +#[unsafe(rustc_allow_lifetime_dependent_specialization)] trait SpecMarker {} trait X { diff --git a/tests/ui/specialization/spec-influences-inference-issue-36262.rs b/tests/ui/specialization/spec-influences-inference-issue-36262.rs new file mode 100644 index 0000000000000..1e96fd5065097 --- /dev/null +++ b/tests/ui/specialization/spec-influences-inference-issue-36262.rs @@ -0,0 +1,128 @@ +//@ edition: 2021 +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass +//@[current] known-bug: #36262 +//@[current] dont-check-compiler-stderr + +// Tests that specialization does not leak into type inference. +// Regression for #36262 and duplicate issues. + +#![feature(specialization)] +#![allow(incomplete_features)] + +// Site 1: the receiver's type parameter, observed through a return position (#36262). +mod receiver_return { + struct My(T); + + trait Conv { + fn conv(self) -> T; + } + + impl Conv for My { + default fn conv(self) -> T { + self.0 + } + } + + impl Conv for My { + fn conv(self) -> u32 { + self.0 + } + } + + fn use_it() { + // Should infer `i32`; the sole `My` impl steers it to `u32`. + let x = My(0); + let _ = x.conv() + 0i32; + } +} + +// Site 2: a method argument's trait type parameter (#91973, #38516, #67918). +mod method_arg { + struct Foo; + + trait Bar { + fn bar(&self, _: T); + } + + impl Bar for Foo { + default fn bar(&self, _: T) {} + } + + impl Bar for Foo { + fn bar(&self, _: bool) {} + } + + fn use_it() { + // Should infer `{integer}`; the sole `Bar` impl steers it to `bool`. + Foo.bar(42); + } +} + +// Site 3: an explicit `_` in a UFCS trait reference (#40718). +mod ufcs_infer { + use std::vec; + + struct Foo(T); + + impl Foo { + fn build>(it: I) -> Foo { + // The second argument should infer to `I::IntoIter`; the sole + // `vec::IntoIter` impl steers it there. + >::from_iter(it.into_iter()) + } + } + + trait SpecExtend { + fn from_iter(iter: I) -> Self; + } + + impl SpecExtend for Foo + where + I: Iterator, + { + default fn from_iter(_: I) -> Self { + panic!() + } + } + + impl SpecExtend> for Foo { + fn from_iter(_: vec::IntoIter) -> Self { + panic!() + } + } +} + +// Site 4: an operator, where the sole specialization is derive-generated (#55243). +mod derived_specializer { + use std::borrow::Borrow; + + #[derive(PartialEq)] + struct MyString(String); + + impl Borrow for MyString { + fn borrow(&self) -> &str { + &self.0 + } + } + + impl PartialEq for MyString + where + Rhs: ?Sized + Borrow, + { + default fn eq(&self, rhs: &Rhs) -> bool { + self.0 == rhs.borrow() + } + } + + fn use_it() { + // Should select `PartialEq`; the derived `PartialEq` is the + // sole specialization and inference commits `Rhs = MyString`. + let s = MyString(String::from("Hello, world!")); + let _ = s == "Hello, world!"; + } +} + +fn main() {} diff --git a/tests/ui/specialization/specialized-impl-projection-issue-32483.rs b/tests/ui/specialization/specialized-impl-projection-issue-32483.rs new file mode 100644 index 0000000000000..5b26679422a40 --- /dev/null +++ b/tests/ui/specialization/specialized-impl-projection-issue-32483.rs @@ -0,0 +1,27 @@ +//@ check-pass + +#![allow(incomplete_features)] +#![feature(specialization)] + +// Tests that we allow some projections in specialized impls. +// Regression test for issue #32483. + +pub trait Foo { + type TypeA; + type TypeB: Bar; +} + +pub trait Bar { +} + +pub struct ImplsBar; +impl Bar for ImplsBar { +} + +impl Foo for T { + type TypeA = u8; + // WF checking `TypeB` here requires us to project `Self::TypeA` + default type TypeB = ImplsBar; +} + +fn main() {} diff --git a/tests/ui/specialization/trait-alias-specialization-issue-74809.rs b/tests/ui/specialization/trait-alias-specialization-issue-74809.rs new file mode 100644 index 0000000000000..e62532e8ab033 --- /dev/null +++ b/tests/ui/specialization/trait-alias-specialization-issue-74809.rs @@ -0,0 +1,44 @@ +//@ check-pass + +#![feature(specialization)] +#![feature(trait_alias)] +#![allow(incomplete_features)] + +// Tests that we can specialize on a trait alias. +// Regression test for #74809. + +pub trait Marker1 {} +pub trait Marker2 {} + +pub trait CombinedMarker = Marker1 + Marker2; + +pub struct Container { + p: std::marker::PhantomData<(T, U)>, +} + +pub struct Struct; +impl Marker1 for Struct {} + +pub trait Trait { + fn do_thing(&self); +} + +impl> Trait for Container { + default fn do_thing(&self) { + println!("default behavior"); + } +} + +impl> Trait for Container { + default fn do_thing(&self) { + println!("partially specialized behavior"); + } +} + +impl Trait for Container { + fn do_thing(&self) { + println!("fully specialized behavior") + } +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/unconstrained-var-specialization.rs b/tests/ui/traits/const-traits/unconstrained-var-specialization.rs index 4330e0aead1ac..d48880deefaf9 100644 --- a/tests/ui/traits/const-traits/unconstrained-var-specialization.rs +++ b/tests/ui/traits/const-traits/unconstrained-var-specialization.rs @@ -13,7 +13,7 @@ pub trait Iterator { type Item; } -#[rustc_unsafe_specialization_marker] +#[unsafe(rustc_allow_lifetime_dependent_specialization)] pub trait MoreSpecificThanIterator: Iterator {} pub trait Tr { diff --git a/tests/ui/traits/next-solver/global-where-bound-normalization.rs b/tests/ui/traits/next-solver/global-where-bound-normalization.rs index e57fbf378a0d2..914a54f1aabb0 100644 --- a/tests/ui/traits/next-solver/global-where-bound-normalization.rs +++ b/tests/ui/traits/next-solver/global-where-bound-normalization.rs @@ -20,7 +20,7 @@ impl Proj for MyField { type Assoc = u8; } -// While wf-checking the global bounds of `fn foo`, elaborating this outlives predicate triggered a +// While wf-checking the global bounds of `fn foo`, elaborating this outlives clause triggered a // cycle in the search graph along a particular probe path, which was not an actual solution. // That cycle then resulted in a forced false-positive ambiguity due to a performance hack in the // search graph and then ended up floundering the root goal evaluation.