Skip to content

Commit 81b4025

Browse files
committed
Stablize trait_upcasting feature
1 parent 0d56e34 commit 81b4025

37 files changed

+93
-347
lines changed

compiler/rustc_feature/src/accepted.rs

+3
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ declare_features! (
303303
/// Allows `#[track_caller]` to be used which provides
304304
/// accurate caller location reporting during panic (RFC 2091).
305305
(accepted, track_caller, "1.46.0", Some(47809), None),
306+
/// Allows upcasting trait objects via supertraits.
307+
/// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
308+
(accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991), None),
306309
/// Allows #[repr(transparent)] on univariant enums (RFC 2645).
307310
(accepted, transparent_enums, "1.42.0", Some(60405), None),
308311
/// Allows indexing tuples.

compiler/rustc_feature/src/active.rs

-3
Original file line numberDiff line numberDiff line change
@@ -507,9 +507,6 @@ declare_features! (
507507
(active, thread_local, "1.0.0", Some(29594), None),
508508
/// Allows defining `trait X = A + B;` alias items.
509509
(active, trait_alias, "1.24.0", Some(41517), None),
510-
/// Allows upcasting trait objects via supertraits.
511-
/// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
512-
(incomplete, trait_upcasting, "1.56.0", Some(65991), None),
513510
/// Allows #[repr(transparent)] on unions (RFC 2645).
514511
(active, transparent_unions, "1.37.0", Some(60405), None),
515512
/// Allows inconsistent bounds in where clauses.

compiler/rustc_lint/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,11 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
519519
"now allowed, see issue #59159 \
520520
<https://github.com/rust-lang/rust/issues/59159> for more information",
521521
);
522+
store.register_removed(
523+
"deref_into_dyn_supertrait",
524+
"overridden by dyn upcasting coercion, see issue #89460 \
525+
<https://github.com/rust-lang/rust/issues/89460> for more information",
526+
);
522527
}
523528

524529
fn register_internals(store: &mut LintStore) {

compiler/rustc_lint_defs/src/builtin.rs

-46
Original file line numberDiff line numberDiff line change
@@ -3361,7 +3361,6 @@ declare_lint_pass! {
33613361
UNUSED_TUPLE_STRUCT_FIELDS,
33623362
NON_EXHAUSTIVE_OMITTED_PATTERNS,
33633363
TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
3364-
DEREF_INTO_DYN_SUPERTRAIT,
33653364
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
33663365
DUPLICATE_MACRO_ATTRIBUTES,
33673366
SUSPICIOUS_AUTO_TRAIT_IMPLS,
@@ -3863,51 +3862,6 @@ declare_lint! {
38633862
"invisible directionality-changing codepoints in comment"
38643863
}
38653864

3866-
declare_lint! {
3867-
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
3868-
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
3869-
///
3870-
/// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
3871-
/// The `deref` functions will no longer be called implicitly, so there might be behavior change.
3872-
///
3873-
/// ### Example
3874-
///
3875-
/// ```rust,compile_fail
3876-
/// #![deny(deref_into_dyn_supertrait)]
3877-
/// #![allow(dead_code)]
3878-
///
3879-
/// use core::ops::Deref;
3880-
///
3881-
/// trait A {}
3882-
/// trait B: A {}
3883-
/// impl<'a> Deref for dyn 'a + B {
3884-
/// type Target = dyn A;
3885-
/// fn deref(&self) -> &Self::Target {
3886-
/// todo!()
3887-
/// }
3888-
/// }
3889-
///
3890-
/// fn take_a(_: &dyn A) { }
3891-
///
3892-
/// fn take_b(b: &dyn B) {
3893-
/// take_a(b);
3894-
/// }
3895-
/// ```
3896-
///
3897-
/// {{produces}}
3898-
///
3899-
/// ### Explanation
3900-
///
3901-
/// The dyn upcasting coercion feature adds new coercion rules, taking priority
3902-
/// over certain other coercion rules, which will cause some behavior change.
3903-
pub DEREF_INTO_DYN_SUPERTRAIT,
3904-
Warn,
3905-
"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
3906-
@future_incompatible = FutureIncompatibleInfo {
3907-
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
3908-
};
3909-
}
3910-
39113865
declare_lint! {
39123866
/// The `duplicate_macro_attributes` lint detects when a `#[test]`-like built-in macro
39133867
/// attribute is duplicated on an item. This lint may trigger on `bench`, `cfg_eval`, `test`

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+1-80
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,12 @@
77
//! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
88
use hir::LangItem;
99
use rustc_hir as hir;
10-
use rustc_hir::def_id::DefId;
11-
use rustc_infer::traits::ObligationCause;
1210
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
13-
use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT;
1411
use rustc_middle::ty::print::with_no_trimmed_paths;
15-
use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable};
12+
use rustc_middle::ty::{self, TypeVisitable};
1613
use rustc_target::spec::abi::Abi;
1714

18-
use crate::traits;
1915
use crate::traits::coherence::Conflict;
20-
use crate::traits::query::evaluate_obligation::InferCtxtExt;
2116
use crate::traits::{util, SelectionResult};
2217
use crate::traits::{Ambiguous, ErrorReporting, Overflow, Unimplemented};
2318

@@ -702,56 +697,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
702697
})
703698
}
704699

705-
/// Temporary migration for #89190
706-
fn need_migrate_deref_output_trait_object(
707-
&mut self,
708-
ty: Ty<'tcx>,
709-
param_env: ty::ParamEnv<'tcx>,
710-
cause: &ObligationCause<'tcx>,
711-
) -> Option<(Ty<'tcx>, DefId)> {
712-
let tcx = self.tcx();
713-
if tcx.features().trait_upcasting {
714-
return None;
715-
}
716-
717-
// <ty as Deref>
718-
let trait_ref = ty::TraitRef {
719-
def_id: tcx.lang_items().deref_trait()?,
720-
substs: tcx.mk_substs_trait(ty, &[]),
721-
};
722-
723-
let obligation = traits::Obligation::new(
724-
cause.clone(),
725-
param_env,
726-
ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
727-
);
728-
if !self.infcx.predicate_may_hold(&obligation) {
729-
return None;
730-
}
731-
732-
let ty = traits::normalize_projection_type(
733-
self,
734-
param_env,
735-
ty::ProjectionTy {
736-
item_def_id: tcx.lang_items().deref_target()?,
737-
substs: trait_ref.substs,
738-
},
739-
cause.clone(),
740-
0,
741-
// We're *intentionally* throwing these away,
742-
// since we don't actually use them.
743-
&mut vec![],
744-
)
745-
.ty()
746-
.unwrap();
747-
748-
if let ty::Dynamic(data, ..) = ty.kind() {
749-
Some((ty, data.principal_def_id()?))
750-
} else {
751-
None
752-
}
753-
}
754-
755700
/// Searches for unsizing that might apply to `obligation`.
756701
fn assemble_candidates_for_unsizing(
757702
&mut self,
@@ -809,30 +754,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
809754
let principal_a = data_a.principal().unwrap();
810755
let target_trait_did = principal_def_id_b.unwrap();
811756
let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
812-
if let Some((deref_output_ty, deref_output_trait_did)) = self
813-
.need_migrate_deref_output_trait_object(
814-
source,
815-
obligation.param_env,
816-
&obligation.cause,
817-
)
818-
{
819-
if deref_output_trait_did == target_trait_did {
820-
self.tcx().struct_span_lint_hir(
821-
DEREF_INTO_DYN_SUPERTRAIT,
822-
obligation.cause.body_id,
823-
obligation.cause.span,
824-
|lint| {
825-
lint.build(&format!(
826-
"`{}` implements `Deref` with supertrait `{}` as output",
827-
source,
828-
deref_output_ty
829-
)).emit();
830-
},
831-
);
832-
return;
833-
}
834-
}
835-
836757
for (idx, upcast_trait_ref) in
837758
util::supertraits(self.tcx(), source_trait_ref).enumerate()
838759
{

compiler/rustc_typeck/src/check/coercion.rs

-24
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
631631
)];
632632

633633
let mut has_unsized_tuple_coercion = false;
634-
let mut has_trait_upcasting_coercion = None;
635634

636635
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
637636
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -644,15 +643,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
644643
let trait_pred = match bound_predicate.skip_binder() {
645644
ty::PredicateKind::Trait(trait_pred) if traits.contains(&trait_pred.def_id()) => {
646645
if unsize_did == trait_pred.def_id() {
647-
let self_ty = trait_pred.self_ty();
648646
let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty();
649-
if let (ty::Dynamic(ref data_a, ..), ty::Dynamic(ref data_b, ..)) =
650-
(self_ty.kind(), unsize_ty.kind())
651-
&& data_a.principal_def_id() != data_b.principal_def_id()
652-
{
653-
debug!("coerce_unsized: found trait upcasting coercion");
654-
has_trait_upcasting_coercion = Some((self_ty, unsize_ty));
655-
}
656647
if let ty::Tuple(..) = unsize_ty.kind() {
657648
debug!("coerce_unsized: found unsized tuple coercion");
658649
has_unsized_tuple_coercion = true;
@@ -722,21 +713,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
722713
.emit();
723714
}
724715

725-
if let Some((sub, sup)) = has_trait_upcasting_coercion
726-
&& !self.tcx().features().trait_upcasting
727-
{
728-
// Renders better when we erase regions, since they're not really the point here.
729-
let (sub, sup) = self.tcx.erase_regions((sub, sup));
730-
let mut err = feature_err(
731-
&self.tcx.sess.parse_sess,
732-
sym::trait_upcasting,
733-
self.cause.span,
734-
&format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"),
735-
);
736-
err.note(&format!("required when coercing `{source}` into `{target}`"));
737-
err.emit();
738-
}
739-
740716
Ok(coercion)
741717
}
742718

src/doc/unstable-book/src/language-features/trait-upcasting.md

-27
This file was deleted.

src/test/ui/codegen/issue-99551.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
// build-pass
2-
#![feature(trait_upcasting)]
3-
#![allow(incomplete_features)]
42

53
pub trait A {}
64
pub trait B {}

src/test/ui/feature-gates/feature-gate-trait_upcasting.rs

-13
This file was deleted.

src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr

-13
This file was deleted.

src/test/ui/issues/issue-11515.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
// check-pass
2+
13
struct Test {
24
func: Box<dyn FnMut() + 'static>,
35
}
46

5-
6-
77
fn main() {
88
let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
9-
let test = Box::new(Test { func: closure }); //~ ERROR trait upcasting coercion is experimental [E0658]
9+
let test = Box::new(Test { func: closure });
1010
}

src/test/ui/issues/issue-11515.stderr

-13
This file was deleted.

src/test/ui/traits/trait-upcasting/basic.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
// run-pass
22

3-
#![feature(trait_upcasting)]
4-
#![allow(incomplete_features)]
5-
63
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
74
fn a(&self) -> i32 {
85
10

src/test/ui/traits/trait-upcasting/correct-supertrait-substitution.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
// run-pass
2-
#![feature(trait_upcasting)]
3-
#![allow(incomplete_features)]
42

53
trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {}
64
trait Bar<T: Default + ToString> {

src/test/ui/traits/trait-upcasting/diamond.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
// run-pass
22

3-
#![feature(trait_upcasting)]
4-
#![allow(incomplete_features)]
5-
63
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
74
fn a(&self) -> i32 {
85
10

src/test/ui/traits/trait-upcasting/invalid-upcast.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
#![feature(trait_upcasting)]
2-
#![allow(incomplete_features)]
3-
41
trait Foo {
52
fn a(&self) -> i32 {
63
10

0 commit comments

Comments
 (0)