Skip to content

Commit 6d2b84b

Browse files
committed
Auto merge of #118133 - Urgau:stabilize_trait_upcasting, r=WaffleLapkin
Stabilize RFC3324 dyn upcasting coercion This PR stabilize the `trait_upcasting` feature, aka rust-lang/rfcs#3324. The FCP was completed here: #65991 (comment). ~~And also remove the `deref_into_dyn_supertrait` lint which is now handled by dyn upcasting coercion.~~ Heavily inspired by #101718 Fixes #65991
2 parents 73bc121 + 4c2d6de commit 6d2b84b

File tree

69 files changed

+97
-347
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+97
-347
lines changed

compiler/rustc_feature/src/accepted.rs

+3
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,9 @@ declare_features! (
338338
/// Allows `#[track_caller]` to be used which provides
339339
/// accurate caller location reporting during panic (RFC 2091).
340340
(accepted, track_caller, "1.46.0", Some(47809), None),
341+
/// Allows dyn upcasting trait objects via supertraits.
342+
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
343+
(accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991), None),
341344
/// Allows #[repr(transparent)] on univariant enums (RFC 2645).
342345
(accepted, transparent_enums, "1.42.0", Some(60405), None),
343346
/// Allows indexing tuples.

compiler/rustc_feature/src/unstable.rs

-3
Original file line numberDiff line numberDiff line change
@@ -562,9 +562,6 @@ declare_features! (
562562
(unstable, thread_local, "1.0.0", Some(29594), None),
563563
/// Allows defining `trait X = A + B;` alias items.
564564
(unstable, trait_alias, "1.24.0", Some(41517), None),
565-
/// Allows dyn upcasting trait objects via supertraits.
566-
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
567-
(unstable, trait_upcasting, "1.56.0", Some(65991), None),
568565
/// Allows for transmuting between arrays with sizes that contain generic consts.
569566
(unstable, transmute_generic_consts, "1.70.0", Some(109929), None),
570567
/// Allows #[repr(transparent)] on unions (RFC 2645).

compiler/rustc_hir_typeck/src/coercion.rs

-23
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
626626
)];
627627

628628
let mut has_unsized_tuple_coercion = false;
629-
let mut has_trait_upcasting_coercion = None;
630629

631630
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
632631
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -694,13 +693,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
694693
// these here and emit a feature error if coercion doesn't fail
695694
// due to another reason.
696695
match impl_source {
697-
traits::ImplSource::Builtin(
698-
BuiltinImplSource::TraitUpcasting { .. },
699-
_,
700-
) => {
701-
has_trait_upcasting_coercion =
702-
Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
703-
}
704696
traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
705697
has_unsized_tuple_coercion = true;
706698
}
@@ -711,21 +703,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
711703
}
712704
}
713705

714-
if let Some((sub, sup)) = has_trait_upcasting_coercion
715-
&& !self.tcx().features().trait_upcasting
716-
{
717-
// Renders better when we erase regions, since they're not really the point here.
718-
let (sub, sup) = self.tcx.erase_regions((sub, sup));
719-
let mut err = feature_err(
720-
&self.tcx.sess.parse_sess,
721-
sym::trait_upcasting,
722-
self.cause.span,
723-
format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"),
724-
);
725-
err.note(format!("required when coercing `{source}` into `{target}`"));
726-
err.emit();
727-
}
728-
729706
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
730707
feature_err(
731708
&self.tcx.sess.parse_sess,

compiler/rustc_lint/messages.ftl

+3-2
Original file line numberDiff line numberDiff line change
@@ -490,8 +490,9 @@ lint_requested_level = requested on the command line with `{$level} {$lint_name}
490490
491491
lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
492492
493-
lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
494-
.label = target type is set here
493+
lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion
494+
.help = consider removing this implementation or replacing it with a method instead
495+
.label = target type is a supertrait of `{$t}`
495496
496497
lint_suspicious_double_ref_clone =
497498
using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type

compiler/rustc_lint/src/deref_into_dyn_supertrait.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@ use crate::{
55

66
use rustc_hir as hir;
77
use rustc_middle::ty;
8-
use rustc_session::lint::FutureIncompatibilityReason;
98
use rustc_span::sym;
109
use rustc_trait_selection::traits::supertraits;
1110

1211
declare_lint! {
1312
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
1413
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
1514
///
16-
/// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
17-
/// The `deref` functions will no longer be called implicitly, so there might be behavior change.
18-
///
1915
/// ### Example
2016
///
2117
/// ```rust,compile_fail
@@ -44,15 +40,10 @@ declare_lint! {
4440
///
4541
/// ### Explanation
4642
///
47-
/// The dyn upcasting coercion feature adds new coercion rules, taking priority
48-
/// over certain other coercion rules, which will cause some behavior change.
43+
/// The implicit dyn upcasting coercion take priority over those `Deref` impls.
4944
pub DEREF_INTO_DYN_SUPERTRAIT,
5045
Warn,
51-
"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
52-
@future_incompatible = FutureIncompatibleInfo {
53-
reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
54-
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
55-
};
46+
"`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion",
5647
}
5748

5849
declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);
@@ -90,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
9081
cx.emit_spanned_lint(
9182
DEREF_INTO_DYN_SUPERTRAIT,
9283
tcx.def_span(item.owner_id.def_id),
93-
SupertraitAsDerefTarget { t, target_principal, label },
84+
SupertraitAsDerefTarget { t, label },
9485
);
9586
}
9687
}

compiler/rustc_lint/src/lints.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ use rustc_errors::{
1010
};
1111
use rustc_hir::def_id::DefId;
1212
use rustc_macros::{LintDiagnostic, Subdiagnostic};
13-
use rustc_middle::ty::{
14-
inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
15-
};
13+
use rustc_middle::ty::{inhabitedness::InhabitedPredicate, Clause, Ty, TyCtxt};
1614
use rustc_session::parse::ParseSess;
1715
use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
1816

@@ -556,9 +554,9 @@ pub enum BuiltinSpecialModuleNameUsed {
556554
// deref_into_dyn_supertrait.rs
557555
#[derive(LintDiagnostic)]
558556
#[diag(lint_supertrait_as_deref_target)]
557+
#[help]
559558
pub struct SupertraitAsDerefTarget<'a> {
560559
pub t: Ty<'a>,
561-
pub target_principal: PolyExistentialTraitRef<'a>,
562560
#[subdiagnostic]
563561
pub label: Option<SupertraitAsDerefTargetLabel>,
564562
}

compiler/rustc_middle/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
#![feature(associated_type_bounds)]
5050
#![feature(rustc_attrs)]
5151
#![feature(control_flow_enum)]
52-
#![feature(trait_upcasting)]
52+
#![cfg_attr(bootstrap, feature(trait_upcasting))]
5353
#![feature(trusted_step)]
5454
#![feature(try_blocks)]
5555
#![feature(try_reserve_kind)]

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

-51
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,10 @@
99
use hir::def_id::DefId;
1010
use hir::LangItem;
1111
use rustc_hir as hir;
12-
use rustc_infer::traits::ObligationCause;
1312
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
1413
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
1514
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
1615

17-
use crate::traits;
18-
use crate::traits::query::evaluate_obligation::InferCtxtExt;
1916
use crate::traits::util;
2017

2118
use super::BuiltinImplConditions;
@@ -690,45 +687,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
690687
})
691688
}
692689

693-
/// Temporary migration for #89190
694-
fn need_migrate_deref_output_trait_object(
695-
&mut self,
696-
ty: Ty<'tcx>,
697-
param_env: ty::ParamEnv<'tcx>,
698-
cause: &ObligationCause<'tcx>,
699-
) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
700-
let tcx = self.tcx();
701-
if tcx.features().trait_upcasting {
702-
return None;
703-
}
704-
705-
// <ty as Deref>
706-
let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
707-
708-
let obligation =
709-
traits::Obligation::new(tcx, cause.clone(), param_env, ty::Binder::dummy(trait_ref));
710-
if !self.infcx.predicate_may_hold(&obligation) {
711-
return None;
712-
}
713-
714-
self.infcx.probe(|_| {
715-
let ty = traits::normalize_projection_type(
716-
self,
717-
param_env,
718-
ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args),
719-
cause.clone(),
720-
0,
721-
// We're *intentionally* throwing these away,
722-
// since we don't actually use them.
723-
&mut vec![],
724-
)
725-
.ty()
726-
.unwrap();
727-
728-
if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None }
729-
})
730-
}
731-
732690
/// Searches for unsizing that might apply to `obligation`.
733691
fn assemble_candidates_for_unsizing(
734692
&mut self,
@@ -786,15 +744,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
786744
let principal_a = a_data.principal().unwrap();
787745
let target_trait_did = principal_def_id_b.unwrap();
788746
let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
789-
if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object(
790-
source,
791-
obligation.param_env,
792-
&obligation.cause,
793-
) {
794-
if deref_trait_ref.def_id() == target_trait_did {
795-
return;
796-
}
797-
}
798747

799748
for (idx, upcast_trait_ref) in
800749
util::supertraits(self.tcx(), source_trait_ref).enumerate()

library/core/tests/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@
111111
#![feature(slice_flatten)]
112112
#![feature(error_generic_member_access)]
113113
#![feature(error_in_core)]
114-
#![feature(trait_upcasting)]
114+
#![cfg_attr(bootstrap, feature(trait_upcasting))]
115115
#![feature(utf8_chunks)]
116116
#![feature(is_ascii_octdigit)]
117117
#![feature(get_many_mut)]

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

-27
This file was deleted.

src/tools/miri/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#![feature(round_ties_even)]
1212
#![feature(let_chains)]
1313
#![feature(lint_reasons)]
14-
#![feature(trait_upcasting)]
14+
#![cfg_attr(bootstrap, feature(trait_upcasting))]
1515
// Configure clippy and other lints
1616
#![allow(
1717
clippy::collapsible_else_if,

src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.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: PartialEq<i32> + std::fmt::Debug + Send + Sync {
52
fn a(&self) -> i32 {
63
10

src/tools/miri/tests/pass/box-custom-alloc.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//@revisions: stack tree
22
//@[tree]compile-flags: -Zmiri-tree-borrows
3-
#![allow(incomplete_features)] // for trait upcasting
4-
#![feature(allocator_api, trait_upcasting)]
3+
#![feature(allocator_api)]
54

65
use std::alloc::Layout;
76
use std::alloc::{AllocError, Allocator};

src/tools/miri/tests/pass/dyn-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
fn main() {
52
basic();
63
diamond();

tests/ui/codegen/issue-99551.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// build-pass
2-
#![feature(trait_upcasting)]
32

43
pub trait A {}
54
pub trait B {}

tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(dyn_star, trait_upcasting)]
1+
#![feature(dyn_star)]
22
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
33

44
trait A: B {}

tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
22
--> $DIR/no-unsize-coerce-dyn-trait.rs:1:12
33
|
4-
LL | #![feature(dyn_star, trait_upcasting)]
4+
LL | #![feature(dyn_star)]
55
| ^^^^^^^^
66
|
77
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information

tests/ui/dyn-star/upcast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// known-bug: #104800
22

3-
#![feature(dyn_star, trait_upcasting)]
3+
#![feature(dyn_star)]
44

55
trait Foo: Bar {
66
fn hello(&self);

tests/ui/dyn-star/upcast.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
22
--> $DIR/upcast.rs:3:12
33
|
4-
LL | #![feature(dyn_star, trait_upcasting)]
4+
LL | #![feature(dyn_star)]
55
| ^^^^^^^^
66
|
77
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information

tests/ui/feature-gates/feature-gate-trait_upcasting.rs

-13
This file was deleted.

tests/ui/feature-gates/feature-gate-trait_upcasting.stderr

-13
This file was deleted.

tests/ui/traits/new-solver/normalize-unsize-rhs.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// compile-flags: -Ztrait-solver=next
22
// check-pass
33

4-
#![feature(trait_upcasting)]
5-
64
trait A {}
75
trait B: A {}
86

tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// check-pass
22
// compile-flags: -Ztrait-solver=next
33

4-
#![feature(trait_upcasting)]
5-
64
pub trait A {}
75
pub trait B: A {}
86

tests/ui/traits/new-solver/upcast-right-substs.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// compile-flags: -Ztrait-solver=next
22
// check-pass
33

4-
#![feature(trait_upcasting)]
5-
64
trait Foo: Bar<i32> + Bar<u32> {}
75

86
trait Bar<T> {}

tests/ui/traits/new-solver/upcast-wrong-substs.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// compile-flags: -Ztrait-solver=next
22

3-
#![feature(trait_upcasting)]
4-
53
trait Foo: Bar<i32> + Bar<u32> {}
64

75
trait Bar<T> {}

0 commit comments

Comments
 (0)