From 11a5386256c3d9bf835cf51f0798dfffa51d00f0 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 22 Nov 2022 19:52:46 +0000 Subject: [PATCH 1/3] Move `get_associated_type` from `clippy` to `rustc_lint` --- compiler/rustc_lint/src/context.rs | 17 ++++++++++++ .../src/methods/iter_overeager_cloned.rs | 4 +-- .../src/methods/unnecessary_iter_cloned.rs | 4 +-- .../src/methods/unnecessary_to_owned.rs | 27 ++++++++++++------- src/tools/clippy/clippy_utils/src/ty.rs | 19 +------------ 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 589b4d6a10ff1..67cf66f470829 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -1245,6 +1245,23 @@ impl<'tcx> LateContext<'tcx> { AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]).unwrap() } + + /// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`. + /// Do not invoke without first verifying that the type implements the trait. + pub fn get_associated_type( + &self, + self_ty: Ty<'tcx>, + trait_id: DefId, + name: &str, + ) -> Option> { + let tcx = self.tcx; + tcx.associated_items(trait_id) + .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) + .and_then(|assoc| { + let proj = tcx.mk_projection(assoc.def_id, tcx.mk_substs_trait(self_ty, [])); + tcx.try_normalize_erasing_regions(self.param_env, proj).ok() + }) + } } impl<'tcx> abi::HasDataLayout for LateContext<'tcx> { diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs index 06a39c5997e20..b4210d875104b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::{get_associated_type, implements_trait, is_copy}; +use clippy_utils::ty::{implements_trait, is_copy}; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; @@ -25,7 +25,7 @@ pub(super) fn check<'tcx>( && let Some(method_id) = typeck.type_dependent_def_id(cloned_call.hir_id) && cx.tcx.trait_of_item(method_id) == Some(iter_id) && let cloned_recv_ty = typeck.expr_ty_adjusted(cloned_recv) - && let Some(iter_assoc_ty) = get_associated_type(cx, cloned_recv_ty, iter_id, "Item") + && let Some(iter_assoc_ty) = cx.get_associated_type(cloned_recv_ty, iter_id, "Item") && matches!(*iter_assoc_ty.kind(), ty::Ref(_, ty, _) if !is_copy(cx, ty)) { if needs_into_iter diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 4eb579af7a12a..52a4ff7d1ae4f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -2,7 +2,7 @@ use super::utils::clone_or_copy_needed; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::ForLoop; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait}; +use clippy_utils::ty::{get_iterator_item_ty, implements_trait}; use clippy_utils::{fn_def_id, get_parent_expr}; use rustc_errors::Applicability; use rustc_hir::{def_id::DefId, Expr, ExprKind}; @@ -54,7 +54,7 @@ pub fn check_for_loop_iter( if let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator); let collection_ty = cx.typeck_results().expr_ty(collection); if implements_trait(cx, collection_ty, into_iterator_trait_id, &[]); - if let Some(into_iter_item_ty) = get_associated_type(cx, collection_ty, into_iterator_trait_id, "Item"); + if let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item"); if iter_item_ty == into_iter_item_ty; if let Some(collection_snippet) = snippet_opt(cx, collection.span); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 375ebc903b400..8b000cd754cd1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -2,9 +2,11 @@ use super::implicit_clone::is_clone_like; use super::unnecessary_iter_cloned::{self, is_into_iter}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs}; +use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs}; use clippy_utils::visitors::find_all_ret_expressions; -use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty}; +use clippy_utils::{ + fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty, +}; use clippy_utils::{meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node}; @@ -18,7 +20,9 @@ use rustc_middle::ty::EarlyBinder; use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; use rustc_semver::RustcVersion; use rustc_span::{sym, Symbol}; -use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; +use rustc_trait_selection::traits::{ + query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause, +}; use std::cmp::max; use super::UNNECESSARY_TO_OWNED; @@ -146,7 +150,7 @@ fn check_addr_of_expr( if_chain! { if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref); if implements_trait(cx, receiver_ty, deref_trait_id, &[]); - if get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(target_ty); + if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty); then { if n_receiver_refs > 0 { span_lint_and_sugg( @@ -341,13 +345,13 @@ fn get_input_traits_and_projections<'tcx>( if trait_predicate.trait_ref.self_ty() == input { trait_predicates.push(trait_predicate); } - }, + } PredicateKind::Projection(projection_predicate) => { if projection_predicate.projection_ty.self_ty() == input { projection_predicates.push(projection_predicate); } - }, - _ => {}, + } + _ => {} } } (trait_predicates, projection_predicates) @@ -462,7 +466,12 @@ fn is_cloned_or_copied(cx: &LateContext<'_>, method_name: Symbol, method_def_id: /// Returns true if the named method can be used to convert the receiver to its "owned" /// representation. -fn is_to_owned_like<'a>(cx: &LateContext<'a>, call_expr: &Expr<'a>, method_name: Symbol, method_def_id: DefId) -> bool { +fn is_to_owned_like<'a>( + cx: &LateContext<'a>, + call_expr: &Expr<'a>, + method_name: Symbol, + method_def_id: DefId, +) -> bool { is_clone_like(cx, method_name.as_str(), method_def_id) || is_cow_into_owned(cx, method_name, method_def_id) || is_to_string_on_string_like(cx, call_expr, method_name, method_def_id) @@ -490,7 +499,7 @@ fn is_to_string_on_string_like<'a>( && let GenericArgKind::Type(ty) = generic_arg.unpack() && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef) - && (get_associated_type(cx, ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) || + && (cx.get_associated_type(ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) || implements_trait(cx, ty, as_ref_trait_id, &[cx.tcx.types.str_.into()])) { true } else { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 1b65b701409e4..8284dc5c28c0b 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -117,24 +117,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { cx.tcx .get_diagnostic_item(sym::Iterator) - .and_then(|iter_did| get_associated_type(cx, ty, iter_did, "Item")) -} - -/// Returns the associated type `name` for `ty` as an implementation of `trait_id`. -/// Do not invoke without first verifying that the type implements the trait. -pub fn get_associated_type<'tcx>( - cx: &LateContext<'tcx>, - ty: Ty<'tcx>, - trait_id: DefId, - name: &str, -) -> Option> { - cx.tcx - .associated_items(trait_id) - .find_by_name_and_kind(cx.tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) - .and_then(|assoc| { - let proj = cx.tcx.mk_projection(assoc.def_id, cx.tcx.mk_substs_trait(ty, [])); - cx.tcx.try_normalize_erasing_regions(cx.param_env, proj).ok() - }) + .and_then(|iter_did| cx.get_associated_type(ty, iter_did, "Item")) } /// Get the diagnostic name of a type, e.g. `sym::HashMap`. To check if a type From 0d4a5c725a3f0cbc2f2597be7e9dec9ba27409ff Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 22 Nov 2022 21:33:19 +0000 Subject: [PATCH 2/3] Make `deref_into_dyn_supertrait` lint the impl and not the usage --- .../src/deref_into_dyn_supertrait.rs | 85 +++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_lint_defs/src/builtin.rs | 46 ---------- .../src/traits/select/candidate_assembly.rs | 12 --- .../trait-upcasting/migrate-lint-deny.rs | 6 +- .../trait-upcasting/migrate-lint-deny.stderr | 14 ++- 6 files changed, 102 insertions(+), 64 deletions(-) create mode 100644 compiler/rustc_lint/src/deref_into_dyn_supertrait.rs diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs new file mode 100644 index 0000000000000..74081f2da6fee --- /dev/null +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -0,0 +1,85 @@ +use crate::{LateContext, LateLintPass, LintContext}; + +use rustc_errors::DelayDm; +use rustc_hir as hir; +use rustc_middle::{traits::util::supertraits, ty}; + +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 stabilized. + /// 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 ", + }; +} + +declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]); + +impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { + // `Deref` is being implemented for `t` + if let hir::ItemKind::Impl(impl_) = item.kind + && let Some(trait_) = &impl_.of_trait + && let t = cx.tcx.type_of(item.owner_id) + && let opt_did @ Some(did) = trait_.trait_def_id() + && opt_did == cx.tcx.lang_items().deref_trait() + // `t` is `dyn t_principal` + && let ty::Dynamic(data, _, ty::Dyn) = t.kind() + && let Some(t_principal) = data.principal() + // `::Target` is `dyn target_principal` + && let Some(target) = cx.get_associated_type(t, did, "Target") + && let ty::Dynamic(data, _, ty::Dyn) = target.kind() + && let Some(target_principal) = data.principal() + // `target_principal` is a supertrait of `t_principal` + && supertraits(cx.tcx, t_principal.with_self_ty(cx.tcx, cx.tcx.types.trait_object_dummy_self)) + .any(|sup| sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(cx.tcx, x)) == target_principal) + { + cx.struct_span_lint( + DEREF_INTO_DYN_SUPERTRAIT, + item.span, + DelayDm(|| { + format!( + "`{t}` implements `Deref` with supertrait `{target_principal}` as output" + ) + }), + |lint| lint, + ) + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index ebb7de70e0570..b6027476adfd9 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -49,6 +49,7 @@ extern crate tracing; mod array_into_iter; pub mod builtin; mod context; +mod deref_into_dyn_supertrait; mod early; mod enum_intrinsics_non_enums; mod errors; @@ -87,6 +88,7 @@ use rustc_span::Span; use array_into_iter::ArrayIntoIter; use builtin::*; +use deref_into_dyn_supertrait::*; use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums; use for_loops_over_fallibles::*; use hidden_unicode_codepoints::*; @@ -192,6 +194,7 @@ macro_rules! late_lint_mod_passes { $args, [ ForLoopsOverFallibles: ForLoopsOverFallibles, + DerefIntoDynSupertrait: DerefIntoDynSupertrait, HardwiredLints: HardwiredLints, ImproperCTypesDeclarations: ImproperCTypesDeclarations, ImproperCTypesDefinitions: ImproperCTypesDefinitions, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index b80facb1759ef..df0e17dea3c05 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3262,7 +3262,6 @@ declare_lint_pass! { UNUSED_TUPLE_STRUCT_FIELDS, NON_EXHAUSTIVE_OMITTED_PATTERNS, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, - DEREF_INTO_DYN_SUPERTRAIT, DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, DUPLICATE_MACRO_ATTRIBUTES, SUSPICIOUS_AUTO_TRAIT_IMPLS, @@ -3764,51 +3763,6 @@ declare_lint! { "invisible directionality-changing codepoints in comment" } -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 stabilized. - /// 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 ", - }; -} - declare_lint! { /// The `duplicate_macro_attributes` lint detects when a `#[test]`-like built-in macro /// attribute is duplicated on an item. This lint may trigger on `bench`, `cfg_eval`, `test` diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3b107d9570f14..93abd3cb8e150 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -6,11 +6,9 @@ //! //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly use hir::LangItem; -use rustc_errors::DelayDm; use rustc_hir as hir; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; -use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TypeVisitable}; use rustc_target::spec::abi::Abi; @@ -811,16 +809,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &obligation.cause, ) { if deref_trait_ref.def_id() == target_trait_did { - self.tcx().struct_span_lint_hir( - DEREF_INTO_DYN_SUPERTRAIT, - obligation.cause.body_id, - obligation.cause.span, - DelayDm(|| format!( - "`{}` implements `Deref` with supertrait `{}` as output", - source, deref_trait_ref - )), - |lint| lint, - ); return; } } diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs index 5f5a2574bab03..ae36115be7b56 100644 --- a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs +++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs @@ -7,7 +7,11 @@ use core::ops::Deref; // issue 89190 trait A {} trait B: A {} + impl<'a> Deref for dyn 'a + B { + //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as output + //~| WARN this was previously accepted by the compiler but is being phased out; + type Target = dyn A; fn deref(&self) -> &Self::Target { todo!() @@ -18,8 +22,6 @@ fn take_a(_: &dyn A) {} fn whoops(b: &dyn B) { take_a(b) - //~^ ERROR `dyn B` implements `Deref` with supertrait `A` as output - //~^^ WARN this was previously accepted by the compiler but is being phased out; } fn main() {} diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr index 41381a3ffd1c6..03317d09eb682 100644 --- a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr +++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr @@ -1,8 +1,14 @@ -error: `dyn B` implements `Deref` with supertrait `A` as output - --> $DIR/migrate-lint-deny.rs:20:12 +error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as output + --> $DIR/migrate-lint-deny.rs:11:1 | -LL | take_a(b) - | ^ +LL | / impl<'a> Deref for dyn 'a + B { +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ | = 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 From 20f3de5ab1151e68e727b5e1c22bcafca738bb7e Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 23 Nov 2022 16:12:51 +0000 Subject: [PATCH 3/3] Use nicer spans for `deref_into_dyn_supertrait` --- .../rustc_lint/src/deref_into_dyn_supertrait.rs | 13 ++++++++++--- .../traits/trait-upcasting/migrate-lint-deny.rs | 2 +- .../trait-upcasting/migrate-lint-deny.stderr | 15 ++++++--------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 74081f2da6fee..1d29a234a3c88 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -3,6 +3,7 @@ use crate::{LateContext, LateLintPass, LintContext}; use rustc_errors::DelayDm; use rustc_hir as hir; use rustc_middle::{traits::util::supertraits, ty}; +use rustc_span::sym; declare_lint! { /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the @@ -72,13 +73,19 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { { cx.struct_span_lint( DEREF_INTO_DYN_SUPERTRAIT, - item.span, + cx.tcx.def_span(item.owner_id.def_id), DelayDm(|| { format!( - "`{t}` implements `Deref` with supertrait `{target_principal}` as output" + "`{t}` implements `Deref` with supertrait `{target_principal}` as target" ) }), - |lint| lint, + |lint| { + if let Some(target_span) = impl_.items.iter().find_map(|i| (i.ident.name == sym::Target).then_some(i.span)) { + lint.span_label(target_span, "target type is set here"); + } + + lint + }, ) } } diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs index ae36115be7b56..d624187561ed7 100644 --- a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs +++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs @@ -9,7 +9,7 @@ trait A {} trait B: A {} impl<'a> Deref for dyn 'a + B { - //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as output + //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as target //~| WARN this was previously accepted by the compiler but is being phased out; type Target = dyn A; diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr index 03317d09eb682..4533b1163425c 100644 --- a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr +++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr @@ -1,14 +1,11 @@ -error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as output +error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target --> $DIR/migrate-lint-deny.rs:11:1 | -LL | / impl<'a> Deref for dyn 'a + B { -LL | | -LL | | -LL | | -... | -LL | | } -LL | | } - | |_^ +LL | impl<'a> Deref for dyn 'a + B { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | type Target = dyn A; + | -------------------- target type is set here | = 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