diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 47b248f26c300..9736aabf29009 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -925,7 +925,8 @@ impl DynCompatibilityViolationSolution { err.span_suggestion( add_self_sugg.1, format!( - "consider turning `{name}` into a method by giving it a `&self` argument" + "consider turning `{name}` into a method by giving it a `&self` \ + argument, so that it is accessible through the trait object's vtable" ), add_self_sugg.0, Applicability::MaybeIncorrect, @@ -933,8 +934,8 @@ impl DynCompatibilityViolationSolution { err.span_suggestion( make_sized_sugg.1, format!( - "alternatively, consider constraining `{name}` so it does not apply to \ - trait objects" + "alternatively, consider constraining `{name}` so it is explicitly \ + marked as not applying to trait objects" ), make_sized_sugg.0, Applicability::MaybeIncorrect, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 01b3026ff4e5b..593bd9588673f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2536,34 +2536,187 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span: Span, trait_pred: ty::PolyTraitClause<'tcx>, ) -> bool { + if !trait_pred.self_ty().skip_binder().is_unit() { + return false; + } let node = self.tcx.hir_node_by_def_id(obligation.cause.body_def_id); - if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn {sig, body: body_id, .. }, .. }) = node + if let hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn { sig, body: body_id, .. }, .. + }) = node && let hir::ExprKind::Block(blk, _) = &self.tcx.hir_body(*body_id).value.kind && sig.decl.output.span().overlaps(span) - && blk.expr.is_none() - && trait_pred.self_ty().skip_binder().is_unit() - && let Some(stmt) = blk.stmts.last() + && let Some(candidate) = self.removable_trailing_semicolon(blk, obligation, trait_pred) + { + // A function body has a single return type, so keeping the value can't break any + // other use of it. + self.emit_semicolon_removal_suggestion( + err, + trait_pred, + candidate, + Applicability::MachineApplicable, + ); + return true; + } + self.suggest_semicolon_removal_in_closure_arg(obligation, err, trait_pred) + } + + /// If the value of `block` is discarded by a trailing semicolon and keeping it would satisfy + /// `trait_pred`, return that statement, its expression and the type of that expression. + fn removable_trailing_semicolon( + &self, + block: &hir::Block<'tcx>, + obligation: &PredicateObligation<'tcx>, + trait_pred: ty::PolyTraitClause<'tcx>, + ) -> Option<(&'tcx hir::Stmt<'tcx>, &'tcx hir::Expr<'tcx>, Ty<'tcx>)> { + if block.expr.is_none() + && let Some(stmt) = block.stmts.last() && let hir::StmtKind::Semi(expr) = stmt.kind + && !stmt.span.from_expansion() + && !matches!(expr.kind, hir::ExprKind::Err(_)) // Only suggest this if the expression behind the semicolon implements the predicate && let Some(typeck_results) = &self.typeck_results - && let Some(ty) = typeck_results.expr_ty_opt(expr) + && let Some(ty) = + typeck_results.expr_ty_opt(expr).map(|ty| self.resolve_vars_if_possible(ty)) && self.predicate_may_hold(&self.mk_trait_obligation_with_new_self_ty( obligation.param_env, trait_pred.map_bound(|trait_pred| (trait_pred, ty)) )) { - err.span_label( - expr.span, - format!( - "this expression has type `{}`, which implements `{}`", - ty, - trait_pred.print_modifiers_and_trait_path() - ), - ); - err.span_suggestion( - self.tcx.sess.source_map().end_point(stmt.span), - "remove this semicolon", - "", - Applicability::MachineApplicable, + Some((stmt, expr, ty)) + } else { + None + } + } + + fn emit_semicolon_removal_suggestion( + &self, + err: &mut Diag<'_>, + trait_pred: ty::PolyTraitClause<'tcx>, + (stmt, expr, ty): (&hir::Stmt<'_>, &hir::Expr<'_>, Ty<'tcx>), + applicability: Applicability, + ) { + err.span_label( + expr.span, + format!( + "this expression has type `{}`, which implements `{}`", + ty, + trait_pred.print_modifiers_and_trait_path() + ), + ); + err.span_suggestion( + self.tcx.sess.source_map().end_point(stmt.span), + "remove this semicolon", + "", + applicability, + ); + } + + /// Detect when a closure argument returns `()` because of a trailing semicolon and that makes + /// a trait bound on the function's generic param fail, and suggest removing the semicolon: + /// + /// ```text + /// fn bar(_: impl Fn() -> R) {} + /// bar(|| { 5u8; }) + /// // - help: remove this semicolon + /// ``` + fn suggest_semicolon_removal_in_closure_arg( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diag<'_>, + trait_pred: ty::PolyTraitClause<'tcx>, + ) -> bool { + let &ObligationCauseCode::WhereClauseInExpr(callee_def_id, _, hir_id, idx) = + obligation.cause.code().peel_derives() + else { + return false; + }; + // This cause code is used for the clauses of any item named in an expression, like an + // associated const or a type alias, and `fn_sig` is only defined for functions. + if !matches!(self.tcx.def_kind(callee_def_id), DefKind::Fn | DefKind::AssocFn) { + return false; + } + let hir::Node::Expr(expr) = self.tcx.hir_node(hir_id) else { + return false; + }; + let Some(typeck_results) = &self.typeck_results else { + return false; + }; + let args: Vec<&hir::Expr<'_>> = + match expr.kind { + hir::ExprKind::MethodCall(_, receiver, args, _) => { + iter::once(receiver).chain(args).collect() + } + // For a call like `bar(..)` the obligation is attached to the callee path expression, + // so the arguments live in its parent. + _ => match self.tcx.parent_hir_node(expr.hir_id) { + hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Call(callee, args), .. + }) if callee.hir_id == expr.hir_id => args.iter().collect(), + _ => return false, + }, + }; + // Work with the callee's own clauses and signature, where the failing bound is still + // written in terms of the generic param it was declared on. + let clauses = self.tcx.clauses_of(callee_def_id).instantiate_identity(self.tcx); + let Some(ty::ClauseKind::Trait(failed)) = clauses + .clauses + .get(idx) + .map(|clause| clause.as_ref().skip_norm_wip().kind().skip_binder()) + else { + return false; + }; + let sig = + self.tcx.fn_sig(callee_def_id).instantiate_identity().skip_norm_wip().skip_binder(); + let mut candidates = args.into_iter().enumerate().filter_map(|(i, arg)| { + // The bound has to be on what the closure returns. A bound on an unrelated param that + // also happened to be inferred as `()` would not be satisfied by removing a semicolon. + let declared = sig.inputs().get(i)?.peel_refs(); + if !clauses.clauses.iter().any(|clause| { + matches!( + clause.as_ref().skip_norm_wip().kind().skip_binder(), + ty::ClauseKind::Projection(proj) + if self.tcx.is_lang_item(proj.def_id(), LangItem::FnOnceOutput) + && proj.projection_term.self_ty() == declared + && proj.term.as_type() == Some(failed.self_ty()) + ) + }) { + return None; + } + // The error can be reported while the closure argument is still being checked, before + // its own type is recorded, so identify closures syntactically and only fall back to + // the argument's type (e.g. for a closure bound to a variable and passed by path). + let closure_def_id = match arg.kind { + hir::ExprKind::Closure(closure) => closure.def_id, + _ => match typeck_results + .expr_ty_adjusted_opt(arg) + .map(|ty| *self.resolve_vars_if_possible(ty).peel_refs().kind()) + { + Some(ty::Closure(def_id, _)) => def_id.as_local()?, + _ => return None, + }, + }; + let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) = + self.tcx.hir_node_by_def_id(closure_def_id) + else { + return None; + }; + let hir::ExprKind::Block(block, None) = self.tcx.hir_body(closure.body).value.kind + else { + return None; + }; + self.removable_trailing_semicolon(block, obligation, trait_pred) + }); + // Only emit the suggestion when a single closure argument matches, to avoid pointing at + // an unrelated closure. + if let Some(candidate) = candidates.next() + && candidates.next().is_none() + { + // The same closure can be passed to somewhere else that expects it to return `()`, + // where keeping the value would introduce a new error. + self.emit_semicolon_removal_suggestion( + err, + trait_pred, + candidate, + Applicability::MaybeIncorrect, ); return true; } diff --git a/rust-bors.toml b/rust-bors.toml index 94a1f7cf60816..01a41d6ae5990 100644 --- a/rust-bors.toml +++ b/rust-bors.toml @@ -84,20 +84,34 @@ label_prefix = "ec2" region = "us-east-2" images = { "x86_64ami" = "latest-gha-runner-ami" + "arm64ami" = "latest-gha-runner-ami-arm64" } jit_runner = "organization" -# Prices per hour of on-demand compute in us-east-2 (as of Aug 2026) -# See rough assessment of build speed for dist-x86_64-quick in https://github.com/rust-lang/simpleinfra/issues/1132 -# m8a.2x 8 vCPU, 32 GB $0.48688/hr -# c8a.4x 16 vCPU, 32 GB $0.86216/hr -# c8a.8x 32 vCPU, 64 GB $1.72432/hr -# c8a.12x 48 vCPU, 96 GB $2.58648/hr -# CodeBuild 36 vCPU $4.78799/hr allowed_instances = [ + # AMD Zen 5 (x86_64) instances, a subset of these is used in production. + # Prices per hour of on-demand compute in us-east-2 (as of Aug 2026) + # See rough assessment of build speed for dist-x86_64-quick in https://github.com/rust-lang/simpleinfra/issues/1132 + # m8a.2x 8 vCPU, 32 GB $0.48688/hr + # c8a.4x 16 vCPU, 32 GB $0.86216/hr + # c8a.8x 32 vCPU, 64 GB $1.72432/hr + # c8a.12x 48 vCPU, 96 GB $2.58648/hr + # CodeBuild 36 vCPU $4.78799/hr "m8a.2xlarge", "c8a.4xlarge", "c8a.8xlarge", "c8a.12xlarge", + + # Graviton 4 (aarch64) instances, currently just for experimentation + "m8g.2xlarge", + "c8g.4xlarge", + "c8g.8xlarge", + "c8g.12xlarge", + + # Graviton 5 (aarch64) instances, currently just for experimentation + "m9g.2xlarge", + "c9g.4xlarge", + "c9g.8xlarge", + "c9g.12xlarge", ] # Enable unrolling of rollup member PRs after rollup merge diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 08121a9a693b7..ce84df0d6d9bb 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -15,18 +15,6 @@ runners: free_disk: true <<: *base-job - - &job-linux-4c-largedisk - os: ubuntu-24.04-4core-16gb - <<: *base-job - - - &job-linux-8c - os: ubuntu-24.04-8core-32gb - <<: *base-job - - - &job-linux-16c - os: ubuntu-24.04-16core-64gb - <<: *base-job - - &job-macos-15 os: macos-15 # macOS 15 Arm64 <<: *base-job @@ -65,14 +53,12 @@ runners: os: codebuild-ubuntu-22-36c-$github.run_id-$github.run_attempt <<: *base-job - - &job-linux-8c-codebuild - free_disk: true - codebuild: true - os: codebuild-ubuntu-22-8c-$github.run_id-$github.run_attempt + - &job-linux-x86-32c-ec2 + os: ec2-x86_64ami-c8a.8xlarge-x64-linux-$github.run_id-$github.run_attempt <<: *base-job - - &job-linux-32c-ec2 - os: ec2-x86_64ami-c8a.8xlarge-x64-linux-$github.run_id-$github.run_attempt + - &job-linux-x86-8c-ec2 + os: ec2-x86_64ami-m8a.2xlarge-x64-linux-$github.run_id-$github.run_attempt <<: *base-job envs: @@ -179,7 +165,7 @@ pr: # These jobs automatically inherit envs.try, to avoid repeating # it in each job definition. try: - - <<: [*job-dist-x86_64-linux, *job-linux-32c-ec2] + - <<: [*job-dist-x86_64-linux, *job-linux-x86-32c-ec2] name: dist-x86_64-linux-quick # Jobs that only run when explicitly invoked in one of the following ways: @@ -203,7 +189,7 @@ optional: DIST_TRY_BUILD: 1 # We repeat the try job here so that it can be explicitly executed using `@bors try jobs`, to test # full x64 Linux dist try builds on EC2. - - <<: [*job-dist-x86_64-linux, *job-linux-32c-ec2] + - <<: [*job-dist-x86_64-linux, *job-linux-x86-32c-ec2] name: dist-x86_64-linux-quick # Main CI jobs that have to be green to merge a commit into the default branch. @@ -312,14 +298,14 @@ auto: - name: dist-x86_64-illumos <<: *job-linux-4c - - <<: [*job-dist-x86_64-linux, *job-linux-32c-ec2] + - <<: [*job-dist-x86_64-linux, *job-linux-x86-32c-ec2] - name: dist-x86_64-linux-alt env: IMAGE: dist-x86_64-linux CODEGEN_BACKENDS: llvm,cranelift DOCKER_SCRIPT: dist-alt.sh - <<: *job-linux-8c + <<: *job-linux-x86-8c-ec2 - name: dist-x86_64-musl env: diff --git a/tests/crashes/153005.rs b/tests/crashes/153005.rs new file mode 100644 index 0000000000000..44b4e029958cd --- /dev/null +++ b/tests/crashes/153005.rs @@ -0,0 +1,15 @@ +//@ known-bug: #153005 +#![feature(non_lifetime_binders)] +#![feature(derive_coerce_pointee)] + +#[derive(core::marker::CoercePointee)] +#[repr(transparent)] +struct _Ptr5<'a, #[pointee] T: ?Sized, X> +where + for V: Sized, +{ + data: &'a T, + x: core::marker::PhantomData, +} + +fn main() {} diff --git a/tests/crashes/153362.rs b/tests/crashes/153362.rs new file mode 100644 index 0000000000000..0a8e4ddae6283 --- /dev/null +++ b/tests/crashes/153362.rs @@ -0,0 +1,6 @@ +//@ known-bug: #153362 +struct ThinDst { + b: unsafe<> (), +} + +const C1: &ThinDst = unsafe { std::mem::transmute(b"d".as_ptr()) }; diff --git a/tests/crashes/153375.rs b/tests/crashes/153375.rs new file mode 100644 index 0000000000000..46ed4be3b829b --- /dev/null +++ b/tests/crashes/153375.rs @@ -0,0 +1,15 @@ +//@ known-bug: #153375 +//@ aux-build: aux153375.rs +extern crate aux153375; +use aux153375::Request; + +struct Bar<'ws>(&'ws ()); + +impl<'ws> Request for Bar<'ws> { + type A<'a> + = u8 + where + Self: 'a; + + fn f(_: Self::A<'_>) -> impl Sized {} +} diff --git a/tests/crashes/153947.rs b/tests/crashes/153947.rs new file mode 100644 index 0000000000000..39bc8c074cfc0 --- /dev/null +++ b/tests/crashes/153947.rs @@ -0,0 +1,10 @@ +//@ known-bug: #153947 +#![expect(drop_bounds)] +pub struct Thing(T) where [T]: Sized, Self: Drop; +impl Drop for Thing where [T]: Sized, Self: Drop { + fn drop(&mut self) {} +} +impl Drop for Thing where [T]: Sized, Self: Drop { + fn drop(&mut self) {} +} +fn main() {} diff --git a/tests/crashes/154296.rs b/tests/crashes/154296.rs new file mode 100644 index 0000000000000..d904a4d82e426 --- /dev/null +++ b/tests/crashes/154296.rs @@ -0,0 +1,12 @@ +//@ known-bug: #154296 +//@ edition: 2024 +mod m1 { + mod inner { + pub struct S; + } + pub use inner::*; + #[derive(Debug)] + pub struct S; +} +use m1::*; +use S; diff --git a/tests/crashes/154779.rs b/tests/crashes/154779.rs new file mode 100644 index 0000000000000..e6c03e88b0b90 --- /dev/null +++ b/tests/crashes/154779.rs @@ -0,0 +1,4 @@ +//@ known-bug: #154779 +struct Data([[&'static str]; 1]); +const _: &'static Data = &*(&[] as *const Data) ; +fn main() {} diff --git a/tests/crashes/154782.rs b/tests/crashes/154782.rs new file mode 100644 index 0000000000000..d5fdfb84b48ce --- /dev/null +++ b/tests/crashes/154782.rs @@ -0,0 +1,9 @@ +//@ known-bug: #154782 +//@ edition: 2024 +#![feature(pin_ergonomics)] +use core::pin::Pin; +fn test_idempotency(x: Pin<&mut T>) { + || { + x.poll(loop {}); + }; +} diff --git a/tests/crashes/154871.rs b/tests/crashes/154871.rs new file mode 100644 index 0000000000000..c106028623d75 --- /dev/null +++ b/tests/crashes/154871.rs @@ -0,0 +1,7 @@ +//@ known-bug: #154871 +struct Struct { + b: unsafe<> (), +} +fn main() { + std::ptr::null::; +} diff --git a/tests/crashes/auxiliary/aux132985.rs b/tests/crashes/auxiliary/aux132985.rs deleted file mode 100644 index 7ae5567bdc59d..0000000000000 --- a/tests/crashes/auxiliary/aux132985.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(adt_const_params)] - -use std::marker::ConstParamTy; - -#[derive(Eq, PartialEq, ConstParamTy)] -pub struct Foo; diff --git a/tests/crashes/auxiliary/aux153375.rs b/tests/crashes/auxiliary/aux153375.rs new file mode 100644 index 0000000000000..c5f09489181b6 --- /dev/null +++ b/tests/crashes/auxiliary/aux153375.rs @@ -0,0 +1,6 @@ +pub trait Request { + type A<'a> + where + Self: 'a; + fn f(_: Self::A<'_>) -> impl Sized; +} diff --git a/tests/crashes/auxiliary/overlapping_spans_helper.rs b/tests/crashes/auxiliary/overlapping_spans_helper.rs deleted file mode 100644 index e449fcd36c376..0000000000000 --- a/tests/crashes/auxiliary/overlapping_spans_helper.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Auxiliary lib for the issue 147973 regression test with ICEs due to overlapping spans. - -#[macro_export] -macro_rules! identity { - ($x:ident) => { - $x - }; -} - -#[macro_export] -macro_rules! do_loop { - ($x:ident) => { - for $crate::identity!($x) in $x {} - }; -} diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr index 7b299fa3cab74..72d9f3b5b736d 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr @@ -79,11 +79,11 @@ LL | trait A { fn g(b: B) -> B; } | - ^ ...because associated function `g` has no `self` parameter | | | this trait is not dyn compatible... -help: consider turning `g` into a method by giving it a `&self` argument +help: consider turning `g` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | trait A { fn g(&self, b: B) -> B; } | ++++++ -help: alternatively, consider constraining `g` so it does not apply to trait objects +help: alternatively, consider constraining `g` so it is explicitly marked as not applying to trait objects | LL | trait A { fn g(b: B) -> B where Self: Sized; } | +++++++++++++++++ @@ -121,11 +121,11 @@ LL | trait B { fn f(a: A) -> A; } | - ^ ...because associated function `f` has no `self` parameter | | | this trait is not dyn compatible... -help: consider turning `f` into a method by giving it a `&self` argument +help: consider turning `f` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | trait B { fn f(&self, a: A) -> A; } | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects +help: alternatively, consider constraining `f` so it is explicitly marked as not applying to trait objects | LL | trait B { fn f(a: A) -> A where Self: Sized; } | +++++++++++++++++ diff --git a/tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr b/tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr index 46ed6a48a77fa..2978278bb286d 100644 --- a/tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr +++ b/tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr @@ -13,11 +13,11 @@ LL | trait Qiz { LL | fn qiz(); | ^^^ ...because associated function `qiz` has no `self` parameter = help: only type `Foo` implements `Qiz`; consider using it directly instead. -help: consider turning `qiz` into a method by giving it a `&self` argument +help: consider turning `qiz` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn qiz(&self); | +++++ -help: alternatively, consider constraining `qiz` so it does not apply to trait objects +help: alternatively, consider constraining `qiz` so it is explicitly marked as not applying to trait objects | LL | fn qiz() where Self: Sized; | +++++++++++++++++ @@ -37,11 +37,11 @@ LL | trait Qiz { LL | fn qiz(); | ^^^ ...because associated function `qiz` has no `self` parameter = help: only type `Foo` implements `Qiz`; consider using it directly instead. -help: consider turning `qiz` into a method by giving it a `&self` argument +help: consider turning `qiz` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn qiz(&self); | +++++ -help: alternatively, consider constraining `qiz` so it does not apply to trait objects +help: alternatively, consider constraining `qiz` so it is explicitly marked as not applying to trait objects | LL | fn qiz() where Self: Sized; | +++++++++++++++++ diff --git a/tests/ui/dyn-compatibility/no-static.stderr b/tests/ui/dyn-compatibility/no-static.stderr index c1d5dd6f562f7..836b98471ec80 100644 --- a/tests/ui/dyn-compatibility/no-static.stderr +++ b/tests/ui/dyn-compatibility/no-static.stderr @@ -13,11 +13,11 @@ LL | trait Foo { LL | fn foo() {} | ^^^ ...because associated function `foo` has no `self` parameter = help: only type `Bar` implements `Foo`; consider using it directly instead. -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn foo(&self) {} | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | fn foo() where Self: Sized {} | +++++++++++++++++ @@ -37,11 +37,11 @@ LL | trait Foo { LL | fn foo() {} | ^^^ ...because associated function `foo` has no `self` parameter = help: only type `Bar` implements `Foo`; consider using it directly instead. -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn foo(&self) {} | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | fn foo() where Self: Sized {} | +++++++++++++++++ diff --git a/tests/ui/dyn-compatibility/spurious-dyn-compat-errors-58734.stderr b/tests/ui/dyn-compatibility/spurious-dyn-compat-errors-58734.stderr index 5461579b911f5..d10e95f16a950 100644 --- a/tests/ui/dyn-compatibility/spurious-dyn-compat-errors-58734.stderr +++ b/tests/ui/dyn-compatibility/spurious-dyn-compat-errors-58734.stderr @@ -28,11 +28,11 @@ LL | trait Trait { LL | fn dyn_incompatible() -> Self; | ^^^^^^^^^^^^^^^^ ...because associated function `dyn_incompatible` has no `self` parameter = help: only type `()` implements `Trait`; consider using it directly instead. -help: consider turning `dyn_incompatible` into a method by giving it a `&self` argument +help: consider turning `dyn_incompatible` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn dyn_incompatible(&self) -> Self; | +++++ -help: alternatively, consider constraining `dyn_incompatible` so it does not apply to trait objects +help: alternatively, consider constraining `dyn_incompatible` so it is explicitly marked as not applying to trait objects | LL | fn dyn_incompatible() -> Self where Self: Sized; | +++++++++++++++++ diff --git a/tests/ui/dyn-compatibility/static-constructor-prevents-dyn-no-api-guidance.rs b/tests/ui/dyn-compatibility/static-constructor-prevents-dyn-no-api-guidance.rs new file mode 100644 index 0000000000000..71e096c5d31f1 --- /dev/null +++ b/tests/ui/dyn-compatibility/static-constructor-prevents-dyn-no-api-guidance.rs @@ -0,0 +1,9 @@ +trait Factory { + fn create() -> Box; + //~^ ERROR the trait `Factory` is not dyn compatible +} + +fn use_factory(_: &dyn Factory) {} +//~^ ERROR the trait `Factory` is not dyn compatible + +fn main() {} diff --git a/tests/ui/dyn-compatibility/static-constructor-prevents-dyn-no-api-guidance.stderr b/tests/ui/dyn-compatibility/static-constructor-prevents-dyn-no-api-guidance.stderr new file mode 100644 index 0000000000000..3a670f2741473 --- /dev/null +++ b/tests/ui/dyn-compatibility/static-constructor-prevents-dyn-no-api-guidance.stderr @@ -0,0 +1,54 @@ +error[E0038]: the trait `Factory` is not dyn compatible + --> $DIR/static-constructor-prevents-dyn-no-api-guidance.rs:6:20 + | +LL | fn use_factory(_: &dyn Factory) {} + | ^^^^^^^^^^^ `Factory` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/static-constructor-prevents-dyn-no-api-guidance.rs:2:8 + | +LL | trait Factory { + | ------- this trait is not dyn compatible... +LL | fn create() -> Box; + | ^^^^^^ ...because associated function `create` has no `self` parameter +help: consider turning `create` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable + | +LL | fn create(&self) -> Box; + | +++++ +help: alternatively, consider constraining `create` so it is explicitly marked as not applying to trait objects + | +LL | fn create() -> Box where Self: Sized; + | +++++++++++++++++ + +error[E0038]: the trait `Factory` is not dyn compatible + --> $DIR/static-constructor-prevents-dyn-no-api-guidance.rs:2:24 + | +LL | fn create() -> Box; + | ^^^^^^^^^^^ `Factory` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/static-constructor-prevents-dyn-no-api-guidance.rs:2:8 + | +LL | trait Factory { + | ------- this trait is not dyn compatible... +LL | fn create() -> Box; + | ^^^^^^ ...because associated function `create` has no `self` parameter +help: consider turning `create` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable + | +LL | fn create(&self) -> Box; + | +++++ +help: alternatively, consider constraining `create` so it is explicitly marked as not applying to trait objects + | +LL | fn create() -> Box where Self: Sized; + | +++++++++++++++++ +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn create() -> Box; +LL + fn create() -> Box; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/taint-const-eval.stderr b/tests/ui/dyn-compatibility/taint-const-eval.stderr index e4be9870fdc44..acbeb27fdc963 100644 --- a/tests/ui/dyn-compatibility/taint-const-eval.stderr +++ b/tests/ui/dyn-compatibility/taint-const-eval.stderr @@ -12,11 +12,11 @@ LL | trait Qux { | --- this trait is not dyn compatible... LL | fn bar(); | ^^^ ...because associated function `bar` has no `self` parameter -help: consider turning `bar` into a method by giving it a `&self` argument +help: consider turning `bar` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn bar(&self); | +++++ -help: alternatively, consider constraining `bar` so it does not apply to trait objects +help: alternatively, consider constraining `bar` so it is explicitly marked as not applying to trait objects | LL | fn bar() where Self: Sized; | +++++++++++++++++ diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr index a8787a01a6f6a..fa38465318b2b 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr @@ -17,11 +17,11 @@ LL | fn foo() -> Self; B consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn foo(&self) -> Self; | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ @@ -67,11 +67,11 @@ LL | fn foo() -> Self; B consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn foo(&self) -> Self; | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ @@ -100,11 +100,11 @@ help: consider using an opaque type instead LL - fn car() -> dyn DynIncompatible { LL + fn car() -> impl DynIncompatible { | -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn foo(&self) -> Self; | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ @@ -134,11 +134,11 @@ help: consider using an opaque type instead LL - fn car() -> dyn DynIncompatible { LL + fn car() -> impl DynIncompatible { | -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn foo(&self) -> Self; | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ diff --git a/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.stderr b/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.stderr index c26df459d2564..6071fddbdac1c 100644 --- a/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.stderr +++ b/tests/ui/parallel-rustc/recursive-trait-fn-sig-issue-142064.stderr @@ -40,11 +40,11 @@ LL | trait A { fn foo() -> A; } | - ^^^ ...because associated function `foo` has no `self` parameter | | | this trait is not dyn compatible... -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | trait A { fn foo(&self) -> A; } | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | trait A { fn foo() -> A where Self: Sized; } | +++++++++++++++++ @@ -95,11 +95,11 @@ LL | trait A { fn foo() -> A; } | - ^^^ ...because associated function `foo` has no `self` parameter | | | this trait is not dyn compatible... -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | trait A { fn foo(&self) -> A; } | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | trait A { fn foo() -> A where Self: Sized; } | +++++++++++++++++ diff --git a/tests/ui/privacy/private-tuple-struct-field-self-arg-issue-81447.rs b/tests/ui/privacy/private-tuple-struct-field-self-arg-issue-81447.rs new file mode 100644 index 0000000000000..84c1d7b883a7b --- /dev/null +++ b/tests/ui/privacy/private-tuple-struct-field-self-arg-issue-81447.rs @@ -0,0 +1,20 @@ +// Regression test for https://github.com/rust-lang/rust/issues/81447 +// Checks that the lint for private fields is prioritized over the self lint. + +mod some_module { + pub struct Test(T); +} + +use some_module::Test; + +struct TestBuilder; + +impl TestBuilder { + fn build(self) -> Test { + //~^ ERROR missing generics for struct `Test` + Test(self) + //~^ ERROR cannot initialize a tuple struct which contains private fields + } +} + +fn main() {} diff --git a/tests/ui/privacy/private-tuple-struct-field-self-arg-issue-81447.stderr b/tests/ui/privacy/private-tuple-struct-field-self-arg-issue-81447.stderr new file mode 100644 index 0000000000000..eb1e32a7d02ab --- /dev/null +++ b/tests/ui/privacy/private-tuple-struct-field-self-arg-issue-81447.stderr @@ -0,0 +1,29 @@ +error[E0107]: missing generics for struct `Test` + --> $DIR/private-tuple-struct-field-self-arg-issue-81447.rs:13:23 + | +LL | fn build(self) -> Test { + | ^^^^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/private-tuple-struct-field-self-arg-issue-81447.rs:5:16 + | +LL | pub struct Test(T); + | ^^^^ - +help: add missing generic argument + | +LL | fn build(self) -> Test { + | +++ + +error[E0423]: cannot initialize a tuple struct which contains private fields + --> $DIR/private-tuple-struct-field-self-arg-issue-81447.rs:15:9 + | +LL | Test(self) + | ^^^^ + | + = note: a struct named `Test` exists in another namespace + = note: constructor is not visible here due to private fields + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0423. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/rust-2018/auxiliary/time.rs b/tests/ui/rust-2018/auxiliary/time.rs new file mode 100644 index 0000000000000..a03d3d1fb5341 --- /dev/null +++ b/tests/ui/rust-2018/auxiliary/time.rs @@ -0,0 +1,3 @@ +pub fn now() -> u32 { + 0 +} diff --git a/tests/ui/rust-2018/extern-crate-alias-shadowed-by-module-55759.rs b/tests/ui/rust-2018/extern-crate-alias-shadowed-by-module-55759.rs new file mode 100644 index 0000000000000..c2ca2a970a169 --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-alias-shadowed-by-module-55759.rs @@ -0,0 +1,19 @@ +// Regression test for . +// `rust_2018_idioms` used to suggest rewriting this `extern crate` as `use time as +// std_time;`. Because a local module shares the crate's name, the rewritten import is +// ambiguous (E0659), so applying the suggestion produced code that did not compile. +//@ edition: 2018 +//@ aux-build: time.rs +//@ check-pass + +#![warn(rust_2018_idioms)] + +extern crate time as std_time; + +pub mod time { + pub fn f() { + let _ = crate::std_time::now(); + } +} + +fn main() {} diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr index e401277a0209f..e231d57a26d91 100644 --- a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr +++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr @@ -12,11 +12,11 @@ LL | trait Qux { | --- this trait is not dyn compatible... LL | fn bar() -> i32; | ^^^ ...because associated function `bar` has no `self` parameter -help: consider turning `bar` into a method by giving it a `&self` argument +help: consider turning `bar` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn bar(&self) -> i32; | +++++ -help: alternatively, consider constraining `bar` so it does not apply to trait objects +help: alternatively, consider constraining `bar` so it is explicitly marked as not applying to trait objects | LL | fn bar() -> i32 where Self: Sized; | +++++++++++++++++ @@ -51,11 +51,11 @@ LL | trait Qux { | --- this trait is not dyn compatible... LL | fn bar() -> i32; | ^^^ ...because associated function `bar` has no `self` parameter -help: consider turning `bar` into a method by giving it a `&self` argument +help: consider turning `bar` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn bar(&self) -> i32; | +++++ -help: alternatively, consider constraining `bar` so it does not apply to trait objects +help: alternatively, consider constraining `bar` so it is explicitly marked as not applying to trait objects | LL | fn bar() -> i32 where Self: Sized; | +++++++++++++++++ diff --git a/tests/ui/suggestions/closure-arg-trailing-semicolon.rs b/tests/ui/suggestions/closure-arg-trailing-semicolon.rs new file mode 100644 index 0000000000000..de5ecd1ddaa3a --- /dev/null +++ b/tests/ui/suggestions/closure-arg-trailing-semicolon.rs @@ -0,0 +1,76 @@ +//! Check that a trailing semicolon in a closure body that makes the closure return `()` and fail +//! a trait bound on the function's generic param gets a "remove this semicolon" suggestion, like +//! `-> impl Trait` function bodies already do. +//! +//! Issue: (closure case). + +trait Bar {} +impl Bar for u8 {} +//~^ HELP the trait `Bar` is implemented for `u8` +//~| HELP the trait `Bar` is implemented for `u8` +//~| HELP the trait `Bar` is implemented for `u8` +//~| HELP the trait `Bar` is implemented for `u8` +//~| HELP the trait `Bar` is implemented for `u8` + +fn bar(_: impl Fn() -> R) {} + +fn two(_: impl Fn() -> (), _: impl Fn() -> R) {} + +fn unrelated(_: impl Fn() -> ()) -> R { + loop {} +} + +struct S; +impl S { + fn run(&self, _: impl Fn() -> R) {} +} + +trait Callable { + const CALL: fn(); +} + +impl Callable for () { + const CALL: fn() = || {}; +} + +fn main() { + bar(|| { 5u8; }); + //~^ ERROR the trait bound `(): Bar` is not satisfied + //~| HELP remove this semicolon + + S.run(|| { 5u8; }); + //~^ ERROR the trait bound `(): Bar` is not satisfied + //~| HELP remove this semicolon + + let c = || { 5u8; }; + //~^ HELP remove this semicolon + bar(c); + //~^ ERROR the trait bound `(): Bar` is not satisfied + + // No suggestion: the last statement isn't an expression with a semicolon. + bar(|| { fn why() {} }); + //~^ ERROR the trait bound `(): Bar` is not satisfied + + // No suggestion: the tail expression's type doesn't implement `Bar`. + bar(|| { "x"; }); + //~^ ERROR the trait bound `(): Bar` is not satisfied + + // No suggestion: the closure body is empty. + bar(|| {}); + //~^ ERROR the trait bound `(): Bar` is not satisfied + + // Only the second closure returns the type the failing bound is on. + two(|| { 5u8; }, || { 7u8; }); + //~^ ERROR the trait bound `(): Bar` is not satisfied + //~| HELP remove this semicolon + + // No suggestion: `R` is the return type of `unrelated` and is inferred as `()` from the + // expected type, so keeping the closure's value would not satisfy the bound. + let _: () = unrelated(|| { 5u8; }); + //~^ ERROR the trait bound `(): Bar` is not satisfied + + // No suggestion: the failing clause belongs to an associated const, which has no signature to + // match a closure argument against. + <() as Callable<()>>::CALL(); + //~^ ERROR the trait bound `(): Bar` is not satisfied +} diff --git a/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr b/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr new file mode 100644 index 0000000000000..f0f9ef83345c7 --- /dev/null +++ b/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr @@ -0,0 +1,154 @@ +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/closure-arg-trailing-semicolon.rs:37:5 + | +LL | bar(|| { 5u8; }); + | ^^^^^^^^^----^^^ + | | | | + | | | help: remove this semicolon + | | this expression has type `u8`, which implements `Bar` + | the trait `Bar` is not implemented for `()` + | +note: required by a bound in `bar` + --> $DIR/closure-arg-trailing-semicolon.rs:15:11 + | +LL | fn bar(_: impl Fn() -> R) {} + | ^^^ required by this bound in `bar` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/closure-arg-trailing-semicolon.rs:41:7 + | +LL | S.run(|| { 5u8; }); + | ^^^ ---- help: remove this semicolon + | | | + | | this expression has type `u8`, which implements `Bar` + | the trait `Bar` is not implemented for `()` + | +note: required by a bound in `S::run` + --> $DIR/closure-arg-trailing-semicolon.rs:25:15 + | +LL | fn run(&self, _: impl Fn() -> R) {} + | ^^^ required by this bound in `S::run` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/closure-arg-trailing-semicolon.rs:47:5 + | +LL | let c = || { 5u8; }; + | ---- help: remove this semicolon + | | + | this expression has type `u8`, which implements `Bar` +LL | +LL | bar(c); + | ^^^^^^ the trait `Bar` is not implemented for `()` + | +note: required by a bound in `bar` + --> $DIR/closure-arg-trailing-semicolon.rs:15:11 + | +LL | fn bar(_: impl Fn() -> R) {} + | ^^^ required by this bound in `bar` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/closure-arg-trailing-semicolon.rs:51:5 + | +LL | bar(|| { fn why() {} }); + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `()` + | +help: the trait `Bar` is implemented for `u8` + --> $DIR/closure-arg-trailing-semicolon.rs:8:1 + | +LL | impl Bar for u8 {} + | ^^^^^^^^^^^^^^^ +note: required by a bound in `bar` + --> $DIR/closure-arg-trailing-semicolon.rs:15:11 + | +LL | fn bar(_: impl Fn() -> R) {} + | ^^^ required by this bound in `bar` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/closure-arg-trailing-semicolon.rs:55:5 + | +LL | bar(|| { "x"; }); + | ^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `()` + | +help: the trait `Bar` is implemented for `u8` + --> $DIR/closure-arg-trailing-semicolon.rs:8:1 + | +LL | impl Bar for u8 {} + | ^^^^^^^^^^^^^^^ +note: required by a bound in `bar` + --> $DIR/closure-arg-trailing-semicolon.rs:15:11 + | +LL | fn bar(_: impl Fn() -> R) {} + | ^^^ required by this bound in `bar` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/closure-arg-trailing-semicolon.rs:59:5 + | +LL | bar(|| {}); + | ^^^^^^^^^^ the trait `Bar` is not implemented for `()` + | +help: the trait `Bar` is implemented for `u8` + --> $DIR/closure-arg-trailing-semicolon.rs:8:1 + | +LL | impl Bar for u8 {} + | ^^^^^^^^^^^^^^^ +note: required by a bound in `bar` + --> $DIR/closure-arg-trailing-semicolon.rs:15:11 + | +LL | fn bar(_: impl Fn() -> R) {} + | ^^^ required by this bound in `bar` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/closure-arg-trailing-semicolon.rs:63:5 + | +LL | two(|| { 5u8; }, || { 7u8; }); + | ^^^^^^^^^^^^^^^^^^^^^^----^^^ + | | | | + | | | help: remove this semicolon + | | this expression has type `u8`, which implements `Bar` + | the trait `Bar` is not implemented for `()` + | +note: required by a bound in `two` + --> $DIR/closure-arg-trailing-semicolon.rs:17:11 + | +LL | fn two(_: impl Fn() -> (), _: impl Fn() -> R) {} + | ^^^ required by this bound in `two` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/closure-arg-trailing-semicolon.rs:69:17 + | +LL | let _: () = unrelated(|| { 5u8; }); + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `()` + | +help: the trait `Bar` is implemented for `u8` + --> $DIR/closure-arg-trailing-semicolon.rs:8:1 + | +LL | impl Bar for u8 {} + | ^^^^^^^^^^^^^^^ +note: required by a bound in `unrelated` + --> $DIR/closure-arg-trailing-semicolon.rs:19:17 + | +LL | fn unrelated(_: impl Fn() -> ()) -> R { + | ^^^ required by this bound in `unrelated` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/closure-arg-trailing-semicolon.rs:74:21 + | +LL | <() as Callable<()>>::CALL(); + | ^^ the trait `Bar` is not implemented for `()` + | +help: the trait `Bar` is implemented for `u8` + --> $DIR/closure-arg-trailing-semicolon.rs:8:1 + | +LL | impl Bar for u8 {} + | ^^^^^^^^^^^^^^^ +note: required by a bound in `Callable::CALL` + --> $DIR/closure-arg-trailing-semicolon.rs:28:19 + | +LL | trait Callable { + | ^^^ required by this bound in `Callable::CALL` +LL | const CALL: fn(); + | ---- required by a bound in this associated constant + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr index 4ccf65b68bf75..c3e044dbb1c14 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr @@ -32,11 +32,11 @@ LL | trait B { | - this trait is not dyn compatible... LL | fn f(a: dyn B) -> dyn B; | ^ ...because associated function `f` has no `self` parameter -help: consider turning `f` into a method by giving it a `&self` argument +help: consider turning `f` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn f(&self, a: dyn B) -> dyn B; | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects +help: alternatively, consider constraining `f` so it is explicitly marked as not applying to trait objects | LL | fn f(a: dyn B) -> dyn B where Self: Sized; | +++++++++++++++++ diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr index bda1d01e23ff9..11c70c89d8b41 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr @@ -32,11 +32,11 @@ LL | trait B { | - this trait is not dyn compatible... LL | fn f(a: dyn B) -> dyn B; | ^ ...because associated function `f` has no `self` parameter -help: consider turning `f` into a method by giving it a `&self` argument +help: consider turning `f` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn f(&self, a: dyn B) -> dyn B; | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects +help: alternatively, consider constraining `f` so it is explicitly marked as not applying to trait objects | LL | fn f(a: dyn B) -> dyn B where Self: Sized; | +++++++++++++++++ diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr index c275cdccaa8c1..17c819660f51d 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr @@ -14,11 +14,11 @@ LL | fn foo() where Self: Other, { } | ^^^ ...because associated function `foo` has no `self` parameter LL | fn bar(self: ()) {} | ^^ ...because method `bar`'s `self` parameter cannot be dispatched on -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn foo(&self) where Self: Other, { } | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | fn foo() where Self: Other, Self: Sized { } | +++++++++++ diff --git a/tests/ui/traits/issue-72410.stderr b/tests/ui/traits/issue-72410.stderr index c9e133437dd86..33feb9e4269f8 100644 --- a/tests/ui/traits/issue-72410.stderr +++ b/tests/ui/traits/issue-72410.stderr @@ -12,11 +12,11 @@ LL | pub trait Bar { | --- this trait is not dyn compatible... LL | fn map() | ^^^ ...because associated function `map` has no `self` parameter -help: consider turning `map` into a method by giving it a `&self` argument +help: consider turning `map` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn map(&self) | +++++ -help: alternatively, consider constraining `map` so it does not apply to trait objects +help: alternatively, consider constraining `map` so it is explicitly marked as not applying to trait objects | LL | where for<'a> &'a mut [dyn Bar]:, Self: Sized ; | +++++++++++++ diff --git a/tests/ui/traits/missing-for-type-in-impl.e2015.stderr b/tests/ui/traits/missing-for-type-in-impl.e2015.stderr index 1dc351eb9e730..df5d35000afce 100644 --- a/tests/ui/traits/missing-for-type-in-impl.e2015.stderr +++ b/tests/ui/traits/missing-for-type-in-impl.e2015.stderr @@ -48,11 +48,11 @@ LL | trait Foo { | --- this trait is not dyn compatible... LL | fn id(me: T) -> T; | ^^ ...because associated function `id` has no `self` parameter -help: consider turning `id` into a method by giving it a `&self` argument +help: consider turning `id` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn id(&self, me: T) -> T; | ++++++ -help: alternatively, consider constraining `id` so it does not apply to trait objects +help: alternatively, consider constraining `id` so it is explicitly marked as not applying to trait objects | LL | fn id(me: T) -> T where Self: Sized; | +++++++++++++++++ diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr index 707aa9e9713db..78a0743d9f87c 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr @@ -12,11 +12,11 @@ LL | trait FromResidual::Residual> { | ------------ this trait is not dyn compatible... LL | fn from_residual(residual: R) -> Self; | ^^^^^^^^^^^^^ ...because associated function `from_residual` has no `self` parameter -help: consider turning `from_residual` into a method by giving it a `&self` argument +help: consider turning `from_residual` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn from_residual(&self, residual: R) -> Self; | ++++++ -help: alternatively, consider constraining `from_residual` so it does not apply to trait objects +help: alternatively, consider constraining `from_residual` so it is explicitly marked as not applying to trait objects | LL | fn from_residual(residual: R) -> Self where Self: Sized; | +++++++++++++++++ diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr index c5637b435262c..4536957566747 100644 --- a/tests/ui/traits/object/safety.stderr +++ b/tests/ui/traits/object/safety.stderr @@ -13,11 +13,11 @@ LL | trait Tr { LL | fn foo(); | ^^^ ...because associated function `foo` has no `self` parameter = help: only type `St` implements `Tr`; consider using it directly instead. -help: consider turning `foo` into a method by giving it a `&self` argument +help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn foo(&self); | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects +help: alternatively, consider constraining `foo` so it is explicitly marked as not applying to trait objects | LL | fn foo() where Self: Sized; | +++++++++++++++++