Skip to content

Commit 2ee0694

Browse files
author
Alexander Regueiro
committed
Added feature gate.
1 parent 92d5676 commit 2ee0694

File tree

6 files changed

+84
-51
lines changed

6 files changed

+84
-51
lines changed

src/librustc_feature/active.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ declare_features! (
497497
/// Allows the use of raw-dylibs (RFC 2627).
498498
(active, raw_dylib, "1.40.0", Some(58713), None),
499499

500-
/// Allows `#[track_caller]` to be used which provides
500+
/// Allows `#[track_caller]` to be used, which provides
501501
/// accurate caller location reporting during panic (RFC 2091).
502502
(active, track_caller, "1.40.0", Some(47809), None),
503503

@@ -524,7 +524,7 @@ declare_features! (
524524
/// Allows the use of `if` and `match` in constants.
525525
(active, const_if_match, "1.41.0", Some(49146), None),
526526

527-
/// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
527+
/// Allows the use of `#[cfg(sanitize = "option")]`; set when `-Zsanitizer` is used.
528528
(active, cfg_sanitize, "1.41.0", Some(39699), None),
529529

530530
/// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern.
@@ -553,10 +553,10 @@ declare_features! (
553553
/// Allows the use of `no_sanitize` attribute.
554554
(active, no_sanitize, "1.42.0", Some(39699), None),
555555

556-
// Allows limiting the evaluation steps of const expressions
556+
/// Allows limiting the evaluation steps of const expressions.
557557
(active, const_eval_limit, "1.43.0", Some(67217), None),
558558

559-
/// Allow negative trait implementations.
559+
/// Allows negative trait implementations.
560560
(active, negative_impls, "1.44.0", Some(68318), None),
561561

562562
/// Allows the use of `#[target_feature]` on safe functions.
@@ -565,6 +565,10 @@ declare_features! (
565565
/// Allow conditional compilation depending on rust version
566566
(active, cfg_version, "1.45.0", Some(64796), None),
567567

568+
/// Allows upcasting trait objects via supertraits.
569+
/// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
570+
(active, trait_upcasting, "1.45.0", Some(65991), None),
571+
568572
// -------------------------------------------------------------------------
569573
// feature-group-end: actual feature gates
570574
// -------------------------------------------------------------------------

src/librustc_infer/infer/error_reporting/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1686,7 +1686,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16861686
let trait_ref = Binder::bind(TraitRef::identity(self.tcx, exp_found.found));
16871687
let supertraits = crate::traits::supertraits(self.tcx, trait_ref);
16881688
if supertraits.into_iter().any(|trait_ref| trait_ref.def_id() == exp_found.expected) {
1689-
diag.note("enable the `trait_upcasting` feature to permit upcasting of trait objects");
1689+
diag.note("add `#![feature(trait_upcasting)]` to the crate attributes to enable");
16901690
}
16911691
}
16921692

src/librustc_span/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,7 @@ symbols! {
751751
transparent,
752752
transparent_enums,
753753
transparent_unions,
754+
trait_upcasting,
754755
trivial_bounds,
755756
Try,
756757
try_blocks,

src/librustc_trait_selection/traits/select.rs

+45-46
Original file line numberDiff line numberDiff line change
@@ -2956,52 +2956,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
29562956
});
29572957
let source_ty = tcx.mk_dynamic(existential_predicates, region_b);
29582958

2959-
/*
2960-
// Require that the traits involved in this upcast are **equal**;
2961-
// only the **lifetime bound** is changed.
2962-
//
2963-
// FIXME: This condition is arguably too strong -- it would
2964-
// suffice for the source trait to be a *subtype* of the target
2965-
// trait. In particular, changing from something like
2966-
// `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be
2967-
// permitted. And, indeed, in the in commit
2968-
// 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this
2969-
// condition was loosened. However, when the leak check was
2970-
// added back, using subtype here actually guides the coercion
2971-
// code in such a way that it accepts `old-lub-glb-object.rs`.
2972-
// This is probably a good thing, but I've modified this to `.eq`
2973-
// because I want to continue rejecting that test (as we have
2974-
// done for quite some time) before we are firmly comfortable
2975-
// with what our behavior should be there. -nikomatsakis
2976-
let InferOk { obligations, .. } = self
2977-
.infcx
2978-
.at(&obligation.cause, obligation.param_env)
2979-
.eq(target, source_ty) // FIXME -- see above
2980-
.map_err(|_| Unimplemented)?;
2981-
nested.extend(obligations);
2982-
*/
2983-
2984-
// Register obligations for `dyn TraitA1 [TraitA2...]: TraitB1 [TraitB2...]`.
2985-
nested.extend(
2986-
data_b.iter()
2987-
// HACK(alexreg | nikomatsakis): we handle auto traits specially here
2988-
// because of cases like like `dyn Foo + Send + 'a` ->
2989-
// `dyn Foo + Send + 'b`, which requires proving the obligation
2990-
// `dyn Foo + Send: Send`. This is unfortunately ambiguous under the
2991-
// current trait solver model: it holds both because `Send` is a supertrait
2992-
// of `Foo + Send` and because there's an automatic impl of `Send` for the
2993-
// trait object.
2994-
.filter(|predicate| {
2995-
match predicate.skip_binder() {
2996-
ty::ExistentialPredicate::AutoTrait(did) =>
2997-
!data_a.auto_traits().any(|did_a| did_a == *did),
2998-
_ => true,
2999-
}
3000-
})
3001-
.map(|predicate|
3002-
predicate_to_obligation(predicate.with_self_ty(tcx, source_ty))
3003-
),
3004-
);
2959+
if tcx.features().trait_upcasting {
2960+
// Register obligations for `dyn TraitA1 [TraitA2...]: TraitB1 [TraitB2...]`.
2961+
nested.extend(
2962+
data_b.iter()
2963+
// HACK(alexreg | nikomatsakis): we handle auto traits specially here
2964+
// because of cases like like `dyn Foo + Send + 'a` ->
2965+
// `dyn Foo + Send + 'b`, which requires proving the obligation
2966+
// `dyn Foo + Send: Send`. This is unfortunately ambiguous under the
2967+
// current trait solver model: it holds both because `Send` is a
2968+
// supertrait of `Foo + Send` and because there's an automatic impl of
2969+
// `Send` for the trait object.
2970+
.filter(|predicate| {
2971+
match predicate.skip_binder() {
2972+
ty::ExistentialPredicate::AutoTrait(did) =>
2973+
!data_a.auto_traits().any(|did_a| did_a == *did),
2974+
_ => true,
2975+
}
2976+
})
2977+
.map(|predicate|
2978+
predicate_to_obligation(predicate.with_self_ty(tcx, source_ty))
2979+
),
2980+
);
2981+
} else {
2982+
// Require that the traits involved in this upcast are **equal**;
2983+
// only the **lifetime bound** is changed.
2984+
//
2985+
// FIXME: This condition is arguably too strong -- it would
2986+
// suffice for the source trait to be a *subtype* of the target
2987+
// trait. In particular, changing from something like
2988+
// `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be
2989+
// permitted. And, indeed, in the in commit
2990+
// 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this
2991+
// condition was loosened. However, when the leak check was
2992+
// added back, using subtype here actually guides the coercion
2993+
// code in such a way that it accepts `old-lub-glb-object.rs`.
2994+
// This is probably a good thing, but I've modified this to `.eq`
2995+
// because I want to continue rejecting that test (as we have
2996+
// done for quite some time) before we are firmly comfortable
2997+
// with what our behavior should be there. -nikomatsakis
2998+
let InferOk { obligations, .. } = self.infcx
2999+
.at(&obligation.cause, obligation.param_env)
3000+
.eq(target, source_ty) // FIXME: see above.
3001+
.map_err(|_| Unimplemented)?;
3002+
nested.extend(obligations);
3003+
}
30053004

30063005
// Register an obligation for `'a: 'b`.
30073006
let outlives = ty::OutlivesPredicate(region_a, region_b);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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 mismatched types [E0308]
13+
//~| NOTE expected type `&dyn Foo`
14+
//~| NOTE expected trait `Foo`, found trait `Bar`
15+
//~| NOTE add `#![feature(trait_upcasting)]` to the crate attributes to enable
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/feature-gate-trait_upcasting.rs:11:25
3+
|
4+
LL | let foo: &dyn Foo = bar;
5+
| ^^^ expected trait `Foo`, found trait `Bar`
6+
|
7+
= note: add `#![feature(trait_upcasting)]` to the crate attributes to enable
8+
= note: expected type `&dyn Foo`
9+
found type `&dyn Bar`
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)