Skip to content

Commit ddd690e

Browse files
authored
Rollup merge of rust-lang#120233 - oli-obk:revert_trait_obj_upcast_stabilization, r=lcnr
Revert stabilization of trait_upcasting feature Reverts rust-lang#118133 This reverts commit 6d2b84b, reversing changes made to 73bc121. The feature has a soundness bug: * rust-lang#120222 It is unclear to me whether we'll actually want to destabilize, but I thought it was still prudent to open the PR for easy destabilization once we get there.
2 parents e3e5f22 + 483382b commit ddd690e

File tree

72 files changed

+427
-102
lines changed

Some content is hidden

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

72 files changed

+427
-102
lines changed

compiler/rustc_feature/src/accepted.rs

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

compiler/rustc_feature/src/unstable.rs

+3
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,9 @@ declare_features! (
584584
(unstable, thread_local, "1.0.0", Some(29594)),
585585
/// Allows defining `trait X = A + B;` alias items.
586586
(unstable, trait_alias, "1.24.0", Some(41517)),
587+
/// Allows dyn upcasting trait objects via supertraits.
588+
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
589+
(unstable, trait_upcasting, "1.56.0", Some(65991)),
587590
/// Allows for transmuting between arrays with sizes that contain generic consts.
588591
(unstable, transmute_generic_consts, "1.70.0", Some(109929)),
589592
/// Allows #[repr(transparent)] on unions (RFC 2645).

compiler/rustc_hir_typeck/src/coercion.rs

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

627627
let mut has_unsized_tuple_coercion = false;
628+
let mut has_trait_upcasting_coercion = None;
628629

629630
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
630631
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -692,6 +693,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
692693
// these here and emit a feature error if coercion doesn't fail
693694
// due to another reason.
694695
match impl_source {
696+
traits::ImplSource::Builtin(
697+
BuiltinImplSource::TraitUpcasting { .. },
698+
_,
699+
) => {
700+
has_trait_upcasting_coercion =
701+
Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
702+
}
695703
traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
696704
has_unsized_tuple_coercion = true;
697705
}
@@ -702,6 +710,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
702710
}
703711
}
704712

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

compiler/rustc_lint/src/deref_into_dyn_supertrait.rs

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

66
use rustc_hir as hir;
77
use rustc_middle::ty;
8+
use rustc_session::lint::FutureIncompatibilityReason;
89
use rustc_span::sym;
910
use rustc_trait_selection::traits::supertraits;
1011

1112
declare_lint! {
1213
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
1314
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
1415
///
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+
///
1519
/// ### Example
1620
///
1721
/// ```rust,compile_fail
@@ -40,10 +44,15 @@ declare_lint! {
4044
///
4145
/// ### Explanation
4246
///
43-
/// The implicit dyn upcasting coercion take priority over those `Deref` impls.
47+
/// The dyn upcasting coercion feature adds new coercion rules, taking priority
48+
/// over certain other coercion rules, which will cause some behavior change.
4449
pub DEREF_INTO_DYN_SUPERTRAIT,
4550
Warn,
46-
"`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion",
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+
};
4756
}
4857

4958
declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);

compiler/rustc_lint/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#![feature(iter_intersperse)]
3636
#![feature(iter_order_by)]
3737
#![feature(let_chains)]
38+
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
3839
#![feature(min_specialization)]
3940
#![feature(never_type)]
4041
#![feature(rustc_attrs)]

compiler/rustc_lint/src/lints.rs

-1
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,6 @@ pub enum BuiltinSpecialModuleNameUsed {
532532
// deref_into_dyn_supertrait.rs
533533
#[derive(LintDiagnostic)]
534534
#[diag(lint_supertrait_as_deref_target)]
535-
#[help]
536535
pub struct SupertraitAsDerefTarget<'a> {
537536
pub self_ty: Ty<'a>,
538537
pub supertrait_principal: PolyExistentialTraitRef<'a>,

compiler/rustc_middle/src/lib.rs

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

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

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

17+
use crate::traits;
18+
use crate::traits::query::evaluate_obligation::InferCtxtExt;
1619
use crate::traits::util;
1720

1821
use super::BuiltinImplConditions;
@@ -723,6 +726,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
723726
})
724727
}
725728

729+
/// Temporary migration for #89190
730+
fn need_migrate_deref_output_trait_object(
731+
&mut self,
732+
ty: Ty<'tcx>,
733+
param_env: ty::ParamEnv<'tcx>,
734+
cause: &ObligationCause<'tcx>,
735+
) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
736+
let tcx = self.tcx();
737+
if tcx.features().trait_upcasting {
738+
return None;
739+
}
740+
741+
// <ty as Deref>
742+
let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
743+
744+
let obligation =
745+
traits::Obligation::new(tcx, cause.clone(), param_env, ty::Binder::dummy(trait_ref));
746+
if !self.infcx.predicate_may_hold(&obligation) {
747+
return None;
748+
}
749+
750+
self.infcx.probe(|_| {
751+
let ty = traits::normalize_projection_type(
752+
self,
753+
param_env,
754+
ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args),
755+
cause.clone(),
756+
0,
757+
// We're *intentionally* throwing these away,
758+
// since we don't actually use them.
759+
&mut vec![],
760+
)
761+
.ty()
762+
.unwrap();
763+
764+
if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None }
765+
})
766+
}
767+
726768
/// Searches for unsizing that might apply to `obligation`.
727769
fn assemble_candidates_for_unsizing(
728770
&mut self,
@@ -780,6 +822,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
780822
let principal_a = a_data.principal().unwrap();
781823
let target_trait_did = principal_def_id_b.unwrap();
782824
let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
825+
if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object(
826+
source,
827+
obligation.param_env,
828+
&obligation.cause,
829+
) {
830+
if deref_trait_ref.def_id() == target_trait_did {
831+
return;
832+
}
833+
}
783834

784835
for (idx, upcast_trait_ref) in
785836
util::supertraits(self.tcx(), source_trait_ref).enumerate()

library/core/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
#![feature(slice_flatten)]
114114
#![feature(error_generic_member_access)]
115115
#![feature(error_in_core)]
116+
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
116117
#![feature(utf8_chunks)]
117118
#![feature(is_ascii_octdigit)]
118119
#![feature(get_many_mut)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# `trait_upcasting`
2+
3+
The tracking issue for this feature is: [#65991]
4+
5+
[#65991]: https://github.com/rust-lang/rust/issues/65991
6+
7+
------------------------
8+
9+
The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a
10+
trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo`
11+
so long as `Bar: Foo`.
12+
13+
```rust,edition2018
14+
#![feature(trait_upcasting)]
15+
#![allow(incomplete_features)]
16+
17+
trait Foo {}
18+
19+
trait Bar: Foo {}
20+
21+
impl Foo for i32 {}
22+
23+
impl<T: Foo + ?Sized> Bar for T {}
24+
25+
let bar: &dyn Bar = &123;
26+
let foo: &dyn Foo = bar;
27+
```

src/tools/miri/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#![feature(nonzero_ops)]
1111
#![feature(let_chains)]
1212
#![feature(lint_reasons)]
13-
#![feature(int_roundings)]
13+
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
1414
// Configure clippy and other lints
1515
#![allow(
1616
clippy::collapsible_else_if,

src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#![feature(trait_upcasting)]
2+
#![allow(incomplete_features)]
3+
14
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
25
fn a(&self) -> i32 {
36
10

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

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

56
use std::alloc::Layout;
67
use std::alloc::{AllocError, Allocator};

src/tools/miri/tests/pass/dyn-upcast.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#![feature(trait_upcasting)]
2+
#![allow(incomplete_features)]
3+
14
fn main() {
25
basic();
36
diamond();

tests/ui/codegen/issue-99551.rs

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

34
pub trait A {}
45
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)]
1+
#![feature(dyn_star, trait_upcasting)]
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)]
4+
LL | #![feature(dyn_star, trait_upcasting)]
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)]
3+
#![feature(dyn_star, trait_upcasting)]
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)]
4+
LL | #![feature(dyn_star, trait_upcasting)]
55
| ^^^^^^^^
66
|
77
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
trait Foo {}
2+
3+
trait Bar: Foo {}
4+
5+
impl Foo for () {}
6+
7+
impl Bar for () {}
8+
9+
fn main() {
10+
let bar: &dyn Bar = &();
11+
let foo: &dyn Foo = bar;
12+
//~^ ERROR trait upcasting coercion is experimental [E0658]
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0658]: cannot cast `dyn Bar` to `dyn Foo`, trait upcasting coercion is experimental
2+
--> $DIR/feature-gate-trait_upcasting.rs:11:25
3+
|
4+
LL | let foo: &dyn Foo = bar;
5+
| ^^^
6+
|
7+
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
8+
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
9+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10+
= note: required when coercing `&dyn Bar` into `&dyn Foo`
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0658`.

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

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// compile-flags: -Znext-solver
22
// check-pass
3+
#![feature(trait_upcasting)]
34

45
trait A {}
56
trait B: A {}

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

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// check-pass
22
// compile-flags: -Znext-solver
3+
#![feature(trait_upcasting)]
34

45
pub trait A {}
56
pub trait B: A {}

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

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// compile-flags: -Znext-solver
22
// check-pass
3+
#![feature(trait_upcasting)]
34

45
trait Foo: Bar<i32> + Bar<u32> {}
56

tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(trait_upcasting)]
12
#![feature(trait_alias)]
23

34
// Although we *elaborate* `T: Alias` to `i32: B`, we should

tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/alias-where-clause-isnt-supertrait.rs:26:5
2+
--> $DIR/alias-where-clause-isnt-supertrait.rs:27:5
33
|
44
LL | fn test(x: &dyn C) -> &dyn B {
55
| ------ expected `&dyn B` because of return type

tests/ui/traits/trait-upcasting/basic.rs

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

3+
#![feature(trait_upcasting)]
4+
35
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
46
fn a(&self) -> i32 {
57
10

tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs

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

34
trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {}
45
trait Bar<T: Default + ToString> {

tests/ui/traits/trait-upcasting/deref-lint-regions.stderr

-14
This file was deleted.

0 commit comments

Comments
 (0)