Change:
<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this code: I expected to see this happen: This should probably continue to compile as before, unless proven to be equivalent. Instead, this happened: The detection for seems to be a little too aggressive, so it's flagging the coercion as feature-gated in beta even though a deref coercion is available: Playground: <!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: 1.55.0 : <!-- Provide the version you are using that has the regression. --: <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<!--<details<summaryBacktrace</summary<p</p</details--(not applicable) <!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. modify labels: +regression-from-stable-to-{channel} -regression-untriaged -- modify labels: +regression-from-stable-to-beta -regression-untriaged
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-high
Bisection: searched nightlies: from nightly-2020-01-01 to nightly-2021-09-23 regressed nightly: nightly-2021-08-01 searched commits: from to regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.0</summaryHost triple: x86_64-unknown-linux-gnu Reproduce with: </details
There is a that discusses this issue. Tagging this with T-lang since this is a change in semantics. label +A-traits +F-trait_upcasting +T-lang +T-compiler
I'm not sure what the proper procedure is in this case, but I just noticed this hit stable in 1.56.0 (without the lint appearing beforehand) and broke my crate I'll work around it on my end, since I need this to continue work on a downstream crate.
Hmm, it seems that the fix didn't get backported to 1.56. Does 1.57-beta work?
It does indeed: The playground uses as of writing this.

Discussion:
"rustc_hir", "rustc_index", "rustc_infer", <ins> "rustc_lint_defs", </ins> "rustc_macros", "rustc_middle", "rustc_parse_format",

BREAK_WITH_LABEL_AND_LOOP, UNUSED_ATTRIBUTES, NON_EXHAUSTIVE_OMITTED_PATTERNS, <ins> DEREF_INTO_DYN_SUPERTRAIT, </ins> ] }

Allow, "detect when patterns of types marked `non_exhaustive` are missed", } <ins> declare_lint! { /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the /// `Deref` implementation with a `dyn SuperTrait` type as `Output`. /// /// These implementations will become shadowed when the `trait_upcasting` feature is stablized. /// The `deref` functions will no longer be called implicitly, so there might be behavior change. /// /// ### Example /// /// ```rust,compile_fail /// #![deny(deref_into_dyn_supertrait)] /// #![allow(dead_code)] /// /// use core::ops::Deref; /// /// trait A {} /// trait B: A {} /// impl<'a> Deref for dyn 'a + B { ///     type Target = dyn A; ///     fn deref(&self) -> &Self::Target { ///         todo!() ///     } /// } /// /// fn take_a(_: &dyn A) { } /// /// fn take_b(b: &dyn B) { ///     take_a(b); /// } /// ``` /// /// {{produces}} /// /// ### Explanation /// /// The dyn upcasting coercion feature adds new coercion rules, taking priority /// over certain other coercion rules, which will cause some behavior change. pub DEREF_INTO_DYN_SUPERTRAIT, Warn, "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future", @future_incompatible = FutureIncompatibleInfo { reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>", }; } </ins>

rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } <ins> rustc_lint_defs = { path = "../rustc_lint_defs" } </ins> rustc_macros = { path = "../rustc_macros" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" }

//! //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly use rustc_hir as hir; <ins> use rustc_hir::def_id::DefId; use rustc_infer::traits::TraitEngine; </ins> use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; <ins> use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; </ins> use rustc_middle::ty::print::with_no_trimmed_paths; <del> use rustc_middle::ty::{self, Ty, TypeFoldable}; </del> <ins> use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; </ins> use rustc_target::spec::abi::Abi; <ins> use crate::traits; </ins> use crate::traits::coherence::Conflict; <ins> use crate::traits::query::evaluate_obligation::InferCtxtExt; </ins> use crate::traits::{util, SelectionResult}; use crate::traits::{Overflow, Unimplemented};

}) } <ins> /// Temporary migration for #89190 fn need_migrate_deref_output_trait_object( &mut self, ty: Ty<'tcx>, cause: &traits::ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option<(Ty<'tcx>, DefId)> { let tcx = self.tcx(); if tcx.features().trait_upcasting { return None; } // <ty as Deref> let trait_ref = ty::TraitRef { def_id: tcx.lang_items().deref_trait()?, substs: tcx.mk_substs_trait(ty, &[]), }; let obligation = traits::Obligation::new( cause.clone(), param_env, ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), ); if !self.infcx.predicate_may_hold(&obligation) { return None; } let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot(); let normalized_ty = fulfillcx.normalize_projection_type( &self.infcx, param_env, ty::ProjectionTy { item_def_id: tcx.lang_items().deref_target()?, substs: trait_ref.substs, }, cause.clone(), ); let data = if let ty::Dynamic(ref data, ..) = normalized_ty.kind() { data } else { return None; }; let def_id = data.principal_def_id()?; return Some((normalized_ty, def_id)); } </ins> /// Searches for unsizing that might apply to `obligation`. fn assemble_candidates_for_unsizing( &mut self,

let principal_a = data_a.principal().unwrap(); let target_trait_did = principal_def_id_b.unwrap(); let source_trait_ref = principal_a.with_self_ty(self.tcx(), source); <ins> if let Some((deref_output_ty, deref_output_trait_did)) = self .need_migrate_deref_output_trait_object( source, &obligation.cause, obligation.param_env, ) { if deref_output_trait_did == target_trait_did { self.tcx().struct_span_lint_hir( DEREF_INTO_DYN_SUPERTRAIT, obligation.cause.body_id, obligation.cause.span, |lint| { lint.build(&format!( "`{}` implements `Deref` with supertrait `{}` as output", source, deref_output_ty )).emit(); }, ); return; } } </ins> for (idx, upcast_trait_ref) in util::supertraits(self.tcx(), source_trait_ref).enumerate() {

<ins> #![deny(deref_into_dyn_supertrait)] extern crate core; use core::ops::Deref; // issue 89190 trait A {} trait B: A {} impl<'a> Deref for dyn 'a + B { type Target = dyn A; fn deref(&self) -> &Self::Target { todo!() } } fn take_a(_: &dyn A) {} fn whoops(b: &dyn B) { take_a(b) //~^ ERROR `dyn B` implements `Deref` with supertrait `(dyn A + 'static)` as output //~^^ WARN this was previously accepted by the compiler but is being phased out; } fn main() {} </ins>

<ins> error: `dyn B` implements `Deref` with supertrait `(dyn A + 'static)` as output --> $DIR/migrate-lint-deny.rs:20:12 | LL |     take_a(b) |            ^ | note: the lint level is defined here --> $DIR/migrate-lint-deny.rs:1:9 | LL | #![deny(deref_into_dyn_supertrait)] |         ^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460> error: aborting due to previous error </ins>