Rollup merge of #120233 - oli-obk:revert_trait_obj_upcast_stabilization, r=lcnr
Revert stabilization of trait_upcasting feature Reverts #118133 This reverts commit6d2b84b3ed
, reversing changes made to73bc12199e
. The feature has a soundness bug: * #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.
This commit is contained in:
commit
a787232abb
72 changed files with 437 additions and 112 deletions
|
@ -339,9 +339,6 @@ declare_features! (
|
||||||
/// Allows `#[track_caller]` to be used which provides
|
/// Allows `#[track_caller]` to be used which provides
|
||||||
/// accurate caller location reporting during panic (RFC 2091).
|
/// accurate caller location reporting during panic (RFC 2091).
|
||||||
(accepted, track_caller, "1.46.0", Some(47809)),
|
(accepted, track_caller, "1.46.0", Some(47809)),
|
||||||
/// Allows dyn upcasting trait objects via supertraits.
|
|
||||||
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
|
|
||||||
(accepted, trait_upcasting, "1.76.0", Some(65991)),
|
|
||||||
/// Allows #[repr(transparent)] on univariant enums (RFC 2645).
|
/// Allows #[repr(transparent)] on univariant enums (RFC 2645).
|
||||||
(accepted, transparent_enums, "1.42.0", Some(60405)),
|
(accepted, transparent_enums, "1.42.0", Some(60405)),
|
||||||
/// Allows indexing tuples.
|
/// Allows indexing tuples.
|
||||||
|
|
|
@ -584,6 +584,9 @@ declare_features! (
|
||||||
(unstable, thread_local, "1.0.0", Some(29594)),
|
(unstable, thread_local, "1.0.0", Some(29594)),
|
||||||
/// Allows defining `trait X = A + B;` alias items.
|
/// Allows defining `trait X = A + B;` alias items.
|
||||||
(unstable, trait_alias, "1.24.0", Some(41517)),
|
(unstable, trait_alias, "1.24.0", Some(41517)),
|
||||||
|
/// Allows dyn upcasting trait objects via supertraits.
|
||||||
|
/// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
|
||||||
|
(unstable, trait_upcasting, "1.56.0", Some(65991)),
|
||||||
/// Allows for transmuting between arrays with sizes that contain generic consts.
|
/// Allows for transmuting between arrays with sizes that contain generic consts.
|
||||||
(unstable, transmute_generic_consts, "1.70.0", Some(109929)),
|
(unstable, transmute_generic_consts, "1.70.0", Some(109929)),
|
||||||
/// Allows #[repr(transparent)] on unions (RFC 2645).
|
/// Allows #[repr(transparent)] on unions (RFC 2645).
|
||||||
|
|
|
@ -625,6 +625,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
)];
|
)];
|
||||||
|
|
||||||
let mut has_unsized_tuple_coercion = false;
|
let mut has_unsized_tuple_coercion = false;
|
||||||
|
let mut has_trait_upcasting_coercion = None;
|
||||||
|
|
||||||
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
|
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
|
||||||
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
|
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
|
||||||
|
@ -692,6 +693,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
// these here and emit a feature error if coercion doesn't fail
|
// these here and emit a feature error if coercion doesn't fail
|
||||||
// due to another reason.
|
// due to another reason.
|
||||||
match impl_source {
|
match impl_source {
|
||||||
|
traits::ImplSource::Builtin(
|
||||||
|
BuiltinImplSource::TraitUpcasting { .. },
|
||||||
|
_,
|
||||||
|
) => {
|
||||||
|
has_trait_upcasting_coercion =
|
||||||
|
Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
|
||||||
|
}
|
||||||
traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
|
traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
|
||||||
has_unsized_tuple_coercion = true;
|
has_unsized_tuple_coercion = true;
|
||||||
}
|
}
|
||||||
|
@ -702,6 +710,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some((sub, sup)) = has_trait_upcasting_coercion
|
||||||
|
&& !self.tcx().features().trait_upcasting
|
||||||
|
{
|
||||||
|
// Renders better when we erase regions, since they're not really the point here.
|
||||||
|
let (sub, sup) = self.tcx.erase_regions((sub, sup));
|
||||||
|
let mut err = feature_err(
|
||||||
|
&self.tcx.sess,
|
||||||
|
sym::trait_upcasting,
|
||||||
|
self.cause.span,
|
||||||
|
format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"),
|
||||||
|
);
|
||||||
|
err.note(format!("required when coercing `{source}` into `{target}`"));
|
||||||
|
err.emit();
|
||||||
|
}
|
||||||
|
|
||||||
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
|
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
|
||||||
feature_err(
|
feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
use rustc_session::lint::FutureIncompatibilityReason;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
use rustc_trait_selection::traits::supertraits;
|
use rustc_trait_selection::traits::supertraits;
|
||||||
|
|
||||||
|
@ -12,6 +13,9 @@ declare_lint! {
|
||||||
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
|
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
|
||||||
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
|
/// `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
|
/// ### Example
|
||||||
///
|
///
|
||||||
/// ```rust,compile_fail
|
/// ```rust,compile_fail
|
||||||
|
@ -40,10 +44,15 @@ declare_lint! {
|
||||||
///
|
///
|
||||||
/// ### Explanation
|
/// ### Explanation
|
||||||
///
|
///
|
||||||
/// The implicit dyn upcasting coercion take priority over those `Deref` impls.
|
/// 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,
|
pub DEREF_INTO_DYN_SUPERTRAIT,
|
||||||
Warn,
|
Warn,
|
||||||
"`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion",
|
"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
|
||||||
|
@future_incompatible = FutureIncompatibleInfo {
|
||||||
|
reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
|
||||||
|
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);
|
declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#![feature(iter_intersperse)]
|
#![feature(iter_intersperse)]
|
||||||
#![feature(iter_order_by)]
|
#![feature(iter_order_by)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
|
@ -532,7 +532,6 @@ pub enum BuiltinSpecialModuleNameUsed {
|
||||||
// deref_into_dyn_supertrait.rs
|
// deref_into_dyn_supertrait.rs
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(lint_supertrait_as_deref_target)]
|
#[diag(lint_supertrait_as_deref_target)]
|
||||||
#[help]
|
|
||||||
pub struct SupertraitAsDerefTarget<'a> {
|
pub struct SupertraitAsDerefTarget<'a> {
|
||||||
pub self_ty: Ty<'a>,
|
pub self_ty: Ty<'a>,
|
||||||
pub supertrait_principal: PolyExistentialTraitRef<'a>,
|
pub supertrait_principal: PolyExistentialTraitRef<'a>,
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#![feature(associated_type_bounds)]
|
#![feature(associated_type_bounds)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
|
||||||
#![feature(trusted_step)]
|
#![feature(trusted_step)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![feature(try_reserve_kind)]
|
#![feature(try_reserve_kind)]
|
||||||
|
|
|
@ -9,10 +9,13 @@
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use hir::LangItem;
|
use hir::LangItem;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_infer::traits::ObligationCause;
|
||||||
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
|
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
|
||||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
||||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||||
|
|
||||||
|
use crate::traits;
|
||||||
|
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use crate::traits::util;
|
use crate::traits::util;
|
||||||
|
|
||||||
use super::BuiltinImplConditions;
|
use super::BuiltinImplConditions;
|
||||||
|
@ -723,6 +726,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Temporary migration for #89190
|
||||||
|
fn need_migrate_deref_output_trait_object(
|
||||||
|
&mut self,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
cause: &ObligationCause<'tcx>,
|
||||||
|
) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
if tcx.features().trait_upcasting {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// <ty as Deref>
|
||||||
|
let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
|
||||||
|
|
||||||
|
let obligation =
|
||||||
|
traits::Obligation::new(tcx, cause.clone(), param_env, ty::Binder::dummy(trait_ref));
|
||||||
|
if !self.infcx.predicate_may_hold(&obligation) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.infcx.probe(|_| {
|
||||||
|
let ty = traits::normalize_projection_type(
|
||||||
|
self,
|
||||||
|
param_env,
|
||||||
|
ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args),
|
||||||
|
cause.clone(),
|
||||||
|
0,
|
||||||
|
// We're *intentionally* throwing these away,
|
||||||
|
// since we don't actually use them.
|
||||||
|
&mut vec![],
|
||||||
|
)
|
||||||
|
.ty()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Searches for unsizing that might apply to `obligation`.
|
/// Searches for unsizing that might apply to `obligation`.
|
||||||
fn assemble_candidates_for_unsizing(
|
fn assemble_candidates_for_unsizing(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -780,6 +822,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
let principal_a = a_data.principal().unwrap();
|
let principal_a = a_data.principal().unwrap();
|
||||||
let target_trait_did = principal_def_id_b.unwrap();
|
let target_trait_did = principal_def_id_b.unwrap();
|
||||||
let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
|
let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
|
||||||
|
if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object(
|
||||||
|
source,
|
||||||
|
obligation.param_env,
|
||||||
|
&obligation.cause,
|
||||||
|
) {
|
||||||
|
if deref_trait_ref.def_id() == target_trait_did {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (idx, upcast_trait_ref) in
|
for (idx, upcast_trait_ref) in
|
||||||
util::supertraits(self.tcx(), source_trait_ref).enumerate()
|
util::supertraits(self.tcx(), source_trait_ref).enumerate()
|
||||||
|
|
|
@ -113,6 +113,7 @@
|
||||||
#![feature(slice_flatten)]
|
#![feature(slice_flatten)]
|
||||||
#![feature(error_generic_member_access)]
|
#![feature(error_generic_member_access)]
|
||||||
#![feature(error_in_core)]
|
#![feature(error_in_core)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
|
||||||
#![feature(utf8_chunks)]
|
#![feature(utf8_chunks)]
|
||||||
#![feature(is_ascii_octdigit)]
|
#![feature(is_ascii_octdigit)]
|
||||||
#![feature(get_many_mut)]
|
#![feature(get_many_mut)]
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# `trait_upcasting`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: [#65991]
|
||||||
|
|
||||||
|
[#65991]: https://github.com/rust-lang/rust/issues/65991
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a
|
||||||
|
trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo`
|
||||||
|
so long as `Bar: Foo`.
|
||||||
|
|
||||||
|
```rust,edition2018
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
trait Bar: Foo {}
|
||||||
|
|
||||||
|
impl Foo for i32 {}
|
||||||
|
|
||||||
|
impl<T: Foo + ?Sized> Bar for T {}
|
||||||
|
|
||||||
|
let bar: &dyn Bar = &123;
|
||||||
|
let foo: &dyn Foo = bar;
|
||||||
|
```
|
|
@ -10,7 +10,7 @@
|
||||||
#![feature(nonzero_ops)]
|
#![feature(nonzero_ops)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(lint_reasons)]
|
#![feature(lint_reasons)]
|
||||||
#![feature(int_roundings)]
|
#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
|
||||||
// Configure clippy and other lints
|
// Configure clippy and other lints
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::collapsible_else_if,
|
clippy::collapsible_else_if,
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
||||||
fn a(&self) -> i32 {
|
fn a(&self) -> i32 {
|
||||||
10
|
10
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//@revisions: stack tree
|
//@revisions: stack tree
|
||||||
//@[tree]compile-flags: -Zmiri-tree-borrows
|
//@[tree]compile-flags: -Zmiri-tree-borrows
|
||||||
#![feature(allocator_api)]
|
#![allow(incomplete_features)] // for trait upcasting
|
||||||
|
#![feature(allocator_api, trait_upcasting)]
|
||||||
|
|
||||||
use std::alloc::Layout;
|
use std::alloc::Layout;
|
||||||
use std::alloc::{AllocError, Allocator};
|
use std::alloc::{AllocError, Allocator};
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
basic();
|
basic();
|
||||||
diamond();
|
diamond();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// build-pass
|
// build-pass
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
pub trait A {}
|
pub trait A {}
|
||||||
pub trait B {}
|
pub trait B {}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(dyn_star)]
|
#![feature(dyn_star, trait_upcasting)]
|
||||||
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
|
||||||
trait A: B {}
|
trait A: B {}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/no-unsize-coerce-dyn-trait.rs:1:12
|
--> $DIR/no-unsize-coerce-dyn-trait.rs:1:12
|
||||||
|
|
|
|
||||||
LL | #![feature(dyn_star)]
|
LL | #![feature(dyn_star, trait_upcasting)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// known-bug: #104800
|
// known-bug: #104800
|
||||||
|
|
||||||
#![feature(dyn_star)]
|
#![feature(dyn_star, trait_upcasting)]
|
||||||
|
|
||||||
trait Foo: Bar {
|
trait Foo: Bar {
|
||||||
fn hello(&self);
|
fn hello(&self);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/upcast.rs:3:12
|
--> $DIR/upcast.rs:3:12
|
||||||
|
|
|
|
||||||
LL | #![feature(dyn_star)]
|
LL | #![feature(dyn_star, trait_upcasting)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||||
|
|
13
tests/ui/feature-gates/feature-gate-trait_upcasting.rs
Normal file
13
tests/ui/feature-gates/feature-gate-trait_upcasting.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
trait Bar: Foo {}
|
||||||
|
|
||||||
|
impl Foo for () {}
|
||||||
|
|
||||||
|
impl Bar for () {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let bar: &dyn Bar = &();
|
||||||
|
let foo: &dyn Foo = bar;
|
||||||
|
//~^ ERROR trait upcasting coercion is experimental [E0658]
|
||||||
|
}
|
14
tests/ui/feature-gates/feature-gate-trait_upcasting.stderr
Normal file
14
tests/ui/feature-gates/feature-gate-trait_upcasting.stderr
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0658]: cannot cast `dyn Bar` to `dyn Foo`, trait upcasting coercion is experimental
|
||||||
|
--> $DIR/feature-gate-trait_upcasting.rs:11:25
|
||||||
|
|
|
||||||
|
LL | let foo: &dyn Foo = bar;
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
|
||||||
|
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
= note: required when coercing `&dyn Bar` into `&dyn Foo`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,5 +1,6 @@
|
||||||
// compile-flags: -Znext-solver
|
// compile-flags: -Znext-solver
|
||||||
// check-pass
|
// check-pass
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait A {}
|
trait A {}
|
||||||
trait B: A {}
|
trait B: A {}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// check-pass
|
// check-pass
|
||||||
// compile-flags: -Znext-solver
|
// compile-flags: -Znext-solver
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
pub trait A {}
|
pub trait A {}
|
||||||
pub trait B: A {}
|
pub trait B: A {}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// compile-flags: -Znext-solver
|
// compile-flags: -Znext-solver
|
||||||
// check-pass
|
// check-pass
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo: Bar<i32> + Bar<u32> {}
|
trait Foo: Bar<i32> + Bar<u32> {}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
|
|
||||||
// Although we *elaborate* `T: Alias` to `i32: B`, we should
|
// Although we *elaborate* `T: Alias` to `i32: B`, we should
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/alias-where-clause-isnt-supertrait.rs:26:5
|
--> $DIR/alias-where-clause-isnt-supertrait.rs:27:5
|
||||||
|
|
|
|
||||||
LL | fn test(x: &dyn C) -> &dyn B {
|
LL | fn test(x: &dyn C) -> &dyn B {
|
||||||
| ------ expected `&dyn B` because of return type
|
| ------ expected `&dyn B` because of return type
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
||||||
fn a(&self) -> i32 {
|
fn a(&self) -> i32 {
|
||||||
10
|
10
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {}
|
trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {}
|
||||||
trait Bar<T: Default + ToString> {
|
trait Bar<T: Default + ToString> {
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
warning: this `Deref` implementation is covered by an implicit supertrait coercion
|
|
||||||
--> $DIR/deref-lint-regions.rs:8:1
|
|
||||||
|
|
|
||||||
LL | impl<'a> Deref for dyn Foo<'a> {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
|
|
||||||
LL |
|
|
||||||
LL | type Target = dyn Bar<'a>;
|
|
||||||
| -------------------------- target type is a supertrait of `dyn Foo<'_>`
|
|
||||||
|
|
|
||||||
= help: consider removing this implementation or replacing it with a method instead
|
|
||||||
= note: `#[warn(deref_into_dyn_supertrait)]` on by default
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
warning: this `Deref` implementation is covered by an implicit supertrait coercion
|
|
||||||
--> $DIR/deref-lint.rs:9:1
|
|
||||||
|
|
|
||||||
LL | impl<'a> Deref for dyn 'a + B {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
|
|
||||||
...
|
|
||||||
LL | type Target = dyn A;
|
|
||||||
| -------------------- target type is a supertrait of `dyn B`
|
|
||||||
|
|
|
||||||
= help: consider removing this implementation or replacing it with a method instead
|
|
||||||
= note: `#[warn(deref_into_dyn_supertrait)]` on by default
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ impl Foo for () {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Deref for dyn Foo + 'a {
|
impl<'a> Deref for dyn Foo + 'a {
|
||||||
|
//~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
|
||||||
|
//~| WARN this will change its meaning in a future release!
|
||||||
type Target = dyn Bar<u32> + 'a;
|
type Target = dyn Bar<u32> + 'a;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
@ -30,5 +32,4 @@ fn main() {
|
||||||
let x: &dyn Foo = &();
|
let x: &dyn Foo = &();
|
||||||
let y = take_dyn(x);
|
let y = take_dyn(x);
|
||||||
let z: u32 = y;
|
let z: u32 = y;
|
||||||
//~^ ERROR mismatched types
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
error[E0308]: mismatched types
|
error: this `Deref` implementation is covered by an implicit supertrait coercion
|
||||||
--> $DIR/deref-upcast-behavioral-change.rs:32:18
|
--> $DIR/deref-upcast-behavioral-change.rs:17:1
|
||||||
|
|
|
|
||||||
LL | let z: u32 = y;
|
LL | impl<'a> Deref for dyn Foo + 'a {
|
||||||
| --- ^ expected `u32`, found `i32`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
|
||||||
| |
|
...
|
||||||
| expected due to this
|
LL | type Target = dyn Bar<u32> + 'a;
|
||||||
|
| -------------------------------- target type is a supertrait of `dyn Foo`
|
||||||
|
|
|
|
||||||
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
|
= warning: this will change its meaning in a future release!
|
||||||
|
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/deref-upcast-behavioral-change.rs:1:9
|
||||||
|
|
|
|
||||||
LL | let z: u32 = y.try_into().unwrap();
|
LL | #![deny(deref_into_dyn_supertrait)]
|
||||||
| ++++++++++++++++++++
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
||||||
fn a(&self) -> i32 {
|
fn a(&self) -> i32 {
|
||||||
10
|
10
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// revisions: current next
|
// revisions: current next
|
||||||
//[next] compile-flags: -Znext-solver
|
//[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait A: B {
|
trait A: B {
|
||||||
type Assoc;
|
type Assoc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/illegal-upcast-from-impl.rs:14:66
|
--> $DIR/illegal-upcast-from-impl.rs:16:66
|
||||||
|
|
|
|
||||||
LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
|
LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
|
||||||
| ----------------------- ^ expected trait `Super`, found trait `Sub`
|
| ----------------------- ^ expected trait `Super`, found trait `Sub`
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/illegal-upcast-from-impl.rs:14:66
|
--> $DIR/illegal-upcast-from-impl.rs:16:66
|
||||||
|
|
|
|
||||||
LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
|
LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
|
||||||
| ----------------------- ^ expected trait `Super`, found trait `Sub`
|
| ----------------------- ^ expected trait `Super`, found trait `Sub`
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// revisions: current next
|
// revisions: current next
|
||||||
//[next] compile-flags: -Znext-solver
|
//[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Super {
|
trait Super {
|
||||||
type Assoc;
|
type Assoc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![deny(deref_into_dyn_supertrait)]
|
#![deny(deref_into_dyn_supertrait)]
|
||||||
|
#![feature(trait_upcasting)] // remove this and the test compiles
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/inference-behavior-change-deref.rs:33:18
|
--> $DIR/inference-behavior-change-deref.rs:34:18
|
||||||
|
|
|
|
||||||
LL | let z: u32 = y;
|
LL | let z: u32 = y;
|
||||||
| --- ^ expected `u32`, found `i32`
|
| --- ^ expected `u32`, found `i32`
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
fn a(&self) -> i32 {
|
fn a(&self) -> i32 {
|
||||||
10
|
10
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:51:35
|
--> $DIR/invalid-upcast.rs:53:35
|
||||||
|
|
|
|
||||||
LL | let _: &dyn std::fmt::Debug = baz;
|
LL | let _: &dyn std::fmt::Debug = baz;
|
||||||
| -------------------- ^^^ expected trait `Debug`, found trait `Baz`
|
| -------------------- ^^^ expected trait `Debug`, found trait `Baz`
|
||||||
|
@ -10,7 +10,7 @@ LL | let _: &dyn std::fmt::Debug = baz;
|
||||||
found reference `&dyn Baz`
|
found reference `&dyn Baz`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:53:24
|
--> $DIR/invalid-upcast.rs:55:24
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Send = baz;
|
LL | let _: &dyn Send = baz;
|
||||||
| --------- ^^^ expected trait `Send`, found trait `Baz`
|
| --------- ^^^ expected trait `Send`, found trait `Baz`
|
||||||
|
@ -21,7 +21,7 @@ LL | let _: &dyn Send = baz;
|
||||||
found reference `&dyn Baz`
|
found reference `&dyn Baz`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:55:24
|
--> $DIR/invalid-upcast.rs:57:24
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Sync = baz;
|
LL | let _: &dyn Sync = baz;
|
||||||
| --------- ^^^ expected trait `Sync`, found trait `Baz`
|
| --------- ^^^ expected trait `Sync`, found trait `Baz`
|
||||||
|
@ -32,7 +32,7 @@ LL | let _: &dyn Sync = baz;
|
||||||
found reference `&dyn Baz`
|
found reference `&dyn Baz`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:58:25
|
--> $DIR/invalid-upcast.rs:60:25
|
||||||
|
|
|
|
||||||
LL | let bar: &dyn Bar = baz;
|
LL | let bar: &dyn Bar = baz;
|
||||||
| -------- ^^^ expected trait `Bar`, found trait `Baz`
|
| -------- ^^^ expected trait `Bar`, found trait `Baz`
|
||||||
|
@ -43,7 +43,7 @@ LL | let bar: &dyn Bar = baz;
|
||||||
found reference `&dyn Baz`
|
found reference `&dyn Baz`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:60:35
|
--> $DIR/invalid-upcast.rs:62:35
|
||||||
|
|
|
|
||||||
LL | let _: &dyn std::fmt::Debug = bar;
|
LL | let _: &dyn std::fmt::Debug = bar;
|
||||||
| -------------------- ^^^ expected trait `Debug`, found trait `Bar`
|
| -------------------- ^^^ expected trait `Debug`, found trait `Bar`
|
||||||
|
@ -54,7 +54,7 @@ LL | let _: &dyn std::fmt::Debug = bar;
|
||||||
found reference `&dyn Bar`
|
found reference `&dyn Bar`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:62:24
|
--> $DIR/invalid-upcast.rs:64:24
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Send = bar;
|
LL | let _: &dyn Send = bar;
|
||||||
| --------- ^^^ expected trait `Send`, found trait `Bar`
|
| --------- ^^^ expected trait `Send`, found trait `Bar`
|
||||||
|
@ -65,7 +65,7 @@ LL | let _: &dyn Send = bar;
|
||||||
found reference `&dyn Bar`
|
found reference `&dyn Bar`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:64:24
|
--> $DIR/invalid-upcast.rs:66:24
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Sync = bar;
|
LL | let _: &dyn Sync = bar;
|
||||||
| --------- ^^^ expected trait `Sync`, found trait `Bar`
|
| --------- ^^^ expected trait `Sync`, found trait `Bar`
|
||||||
|
@ -76,7 +76,7 @@ LL | let _: &dyn Sync = bar;
|
||||||
found reference `&dyn Bar`
|
found reference `&dyn Bar`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:67:25
|
--> $DIR/invalid-upcast.rs:69:25
|
||||||
|
|
|
|
||||||
LL | let foo: &dyn Foo = baz;
|
LL | let foo: &dyn Foo = baz;
|
||||||
| -------- ^^^ expected trait `Foo`, found trait `Baz`
|
| -------- ^^^ expected trait `Foo`, found trait `Baz`
|
||||||
|
@ -87,7 +87,7 @@ LL | let foo: &dyn Foo = baz;
|
||||||
found reference `&dyn Baz`
|
found reference `&dyn Baz`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:69:35
|
--> $DIR/invalid-upcast.rs:71:35
|
||||||
|
|
|
|
||||||
LL | let _: &dyn std::fmt::Debug = foo;
|
LL | let _: &dyn std::fmt::Debug = foo;
|
||||||
| -------------------- ^^^ expected trait `Debug`, found trait `Foo`
|
| -------------------- ^^^ expected trait `Debug`, found trait `Foo`
|
||||||
|
@ -98,7 +98,7 @@ LL | let _: &dyn std::fmt::Debug = foo;
|
||||||
found reference `&dyn Foo`
|
found reference `&dyn Foo`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:71:24
|
--> $DIR/invalid-upcast.rs:73:24
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Send = foo;
|
LL | let _: &dyn Send = foo;
|
||||||
| --------- ^^^ expected trait `Send`, found trait `Foo`
|
| --------- ^^^ expected trait `Send`, found trait `Foo`
|
||||||
|
@ -109,7 +109,7 @@ LL | let _: &dyn Send = foo;
|
||||||
found reference `&dyn Foo`
|
found reference `&dyn Foo`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:73:24
|
--> $DIR/invalid-upcast.rs:75:24
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Sync = foo;
|
LL | let _: &dyn Sync = foo;
|
||||||
| --------- ^^^ expected trait `Sync`, found trait `Foo`
|
| --------- ^^^ expected trait `Sync`, found trait `Foo`
|
||||||
|
@ -120,7 +120,7 @@ LL | let _: &dyn Sync = foo;
|
||||||
found reference `&dyn Foo`
|
found reference `&dyn Foo`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:76:25
|
--> $DIR/invalid-upcast.rs:78:25
|
||||||
|
|
|
|
||||||
LL | let foo: &dyn Foo = bar;
|
LL | let foo: &dyn Foo = bar;
|
||||||
| -------- ^^^ expected trait `Foo`, found trait `Bar`
|
| -------- ^^^ expected trait `Foo`, found trait `Bar`
|
||||||
|
@ -131,7 +131,7 @@ LL | let foo: &dyn Foo = bar;
|
||||||
found reference `&dyn Bar`
|
found reference `&dyn Bar`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:78:35
|
--> $DIR/invalid-upcast.rs:80:35
|
||||||
|
|
|
|
||||||
LL | let _: &dyn std::fmt::Debug = foo;
|
LL | let _: &dyn std::fmt::Debug = foo;
|
||||||
| -------------------- ^^^ expected trait `Debug`, found trait `Foo`
|
| -------------------- ^^^ expected trait `Debug`, found trait `Foo`
|
||||||
|
@ -142,7 +142,7 @@ LL | let _: &dyn std::fmt::Debug = foo;
|
||||||
found reference `&dyn Foo`
|
found reference `&dyn Foo`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:80:24
|
--> $DIR/invalid-upcast.rs:82:24
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Send = foo;
|
LL | let _: &dyn Send = foo;
|
||||||
| --------- ^^^ expected trait `Send`, found trait `Foo`
|
| --------- ^^^ expected trait `Send`, found trait `Foo`
|
||||||
|
@ -153,7 +153,7 @@ LL | let _: &dyn Send = foo;
|
||||||
found reference `&dyn Foo`
|
found reference `&dyn Foo`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/invalid-upcast.rs:82:24
|
--> $DIR/invalid-upcast.rs:84:24
|
||||||
|
|
|
|
||||||
LL | let _: &dyn Sync = foo;
|
LL | let _: &dyn Sync = foo;
|
||||||
| --------- ^^^ expected trait `Sync`, found trait `Foo`
|
| --------- ^^^ expected trait `Sync`, found trait `Foo`
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
struct Test {
|
struct Test {
|
||||||
func: Box<dyn FnMut() + 'static>,
|
func: Box<dyn FnMut() + 'static>,
|
||||||
|
|
14
tests/ui/traits/trait-upcasting/issue-11515.current.stderr
Normal file
14
tests/ui/traits/trait-upcasting/issue-11515.current.stderr
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
|
||||||
|
--> $DIR/issue-11515.rs:10:38
|
||||||
|
|
|
||||||
|
LL | let test = Box::new(Test { func: closure });
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
|
||||||
|
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
= note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
14
tests/ui/traits/trait-upcasting/issue-11515.next.stderr
Normal file
14
tests/ui/traits/trait-upcasting/issue-11515.next.stderr
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
|
||||||
|
--> $DIR/issue-11515.rs:10:38
|
||||||
|
|
|
||||||
|
LL | let test = Box::new(Test { func: closure });
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
|
||||||
|
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
= note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,4 +1,3 @@
|
||||||
// check-pass
|
|
||||||
// revisions: current next
|
// revisions: current next
|
||||||
//[next] compile-flags: -Znext-solver
|
//[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
@ -8,5 +7,5 @@ struct Test {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
|
let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
|
||||||
let test = Box::new(Test { func: closure });
|
let test = Box::new(Test { func: closure }); //~ ERROR trait upcasting coercion is experimental [E0658]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
||||||
fn a(&self) -> i32 {
|
fn a(&self) -> i32 {
|
||||||
10
|
10
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// check-pass
|
#![deny(deref_into_dyn_supertrait)]
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
@ -6,7 +6,8 @@ trait Bar<'a> {}
|
||||||
trait Foo<'a>: Bar<'a> {}
|
trait Foo<'a>: Bar<'a> {}
|
||||||
|
|
||||||
impl<'a> Deref for dyn Foo<'a> {
|
impl<'a> Deref for dyn Foo<'a> {
|
||||||
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
|
//~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
|
||||||
|
//~| WARN this will change its meaning in a future release!
|
||||||
type Target = dyn Bar<'a>;
|
type Target = dyn Bar<'a>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
|
@ -0,0 +1,19 @@
|
||||||
|
error: this `Deref` implementation is covered by an implicit supertrait coercion
|
||||||
|
--> $DIR/migrate-lint-deny-regions.rs:8:1
|
||||||
|
|
|
||||||
|
LL | impl<'a> Deref for dyn Foo<'a> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
|
||||||
|
...
|
||||||
|
LL | type Target = dyn Bar<'a>;
|
||||||
|
| -------------------------- target type is a supertrait of `dyn Foo<'_>`
|
||||||
|
|
|
||||||
|
= warning: this will change its meaning in a future release!
|
||||||
|
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/migrate-lint-deny-regions.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![deny(deref_into_dyn_supertrait)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// check-pass
|
#![deny(deref_into_dyn_supertrait)]
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
@ -7,7 +7,8 @@ trait A {}
|
||||||
trait B: A {}
|
trait B: A {}
|
||||||
|
|
||||||
impl<'a> Deref for dyn 'a + B {
|
impl<'a> Deref for dyn 'a + B {
|
||||||
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
|
//~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
|
||||||
|
//~| WARN this will change its meaning in a future release!
|
||||||
|
|
||||||
type Target = dyn A;
|
type Target = dyn A;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
19
tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
Normal file
19
tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
error: this `Deref` implementation is covered by an implicit supertrait coercion
|
||||||
|
--> $DIR/migrate-lint-deny.rs:9:1
|
||||||
|
|
|
||||||
|
LL | impl<'a> Deref for dyn 'a + B {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
|
||||||
|
...
|
||||||
|
LL | type Target = dyn A;
|
||||||
|
| -------------------- target type is a supertrait of `dyn B`
|
||||||
|
|
|
||||||
|
= warning: this will change its meaning in a future release!
|
||||||
|
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/migrate-lint-deny.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![deny(deref_into_dyn_supertrait)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -10,6 +10,7 @@ trait Foo: Bar<i32> {
|
||||||
|
|
||||||
impl<'a> Deref for dyn Foo + 'a {
|
impl<'a> Deref for dyn Foo + 'a {
|
||||||
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
|
//~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
|
||||||
|
//~| WARN this will change its meaning in a future release!
|
||||||
type Target = dyn Bar<u32> + 'a;
|
type Target = dyn Bar<u32> + 'a;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
|
|
@ -3,11 +3,12 @@ warning: this `Deref` implementation is covered by an implicit supertrait coerci
|
||||||
|
|
|
|
||||||
LL | impl<'a> Deref for dyn Foo + 'a {
|
LL | impl<'a> Deref for dyn Foo + 'a {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
|
||||||
LL |
|
...
|
||||||
LL | type Target = dyn Bar<u32> + 'a;
|
LL | type Target = dyn Bar<u32> + 'a;
|
||||||
| -------------------------------- target type is a supertrait of `dyn Foo`
|
| -------------------------------- target type is a supertrait of `dyn Foo`
|
||||||
|
|
|
|
||||||
= help: consider removing this implementation or replacing it with a method instead
|
= warning: this will change its meaning in a future release!
|
||||||
|
= note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
|
||||||
= note: `#[warn(deref_into_dyn_supertrait)]` on by default
|
= note: `#[warn(deref_into_dyn_supertrait)]` on by default
|
||||||
|
|
||||||
warning: 1 warning emitted
|
warning: 1 warning emitted
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// check-fail
|
// check-fail
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Bar<T> {
|
trait Bar<T> {
|
||||||
fn bar(&self, _: T) {}
|
fn bar(&self, _: T) {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/multiple-occurrence-ambiguousity.rs:19:26
|
--> $DIR/multiple-occurrence-ambiguousity.rs:20:26
|
||||||
|
|
|
|
||||||
LL | let t: &dyn Bar<_> = s;
|
LL | let t: &dyn Bar<_> = s;
|
||||||
| ----------- ^ expected trait `Bar`, found trait `Foo`
|
| ----------- ^ expected trait `Bar`, found trait `Foo`
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
// revisions: current next
|
// revisions: current next
|
||||||
//[next] compile-flags: -Znext-solver
|
//[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Mirror {
|
trait Mirror {
|
||||||
type Assoc;
|
type Assoc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait A {
|
trait A {
|
||||||
fn foo_a(&self);
|
fn foo_a(&self);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
|
||||||
fn a(&self) -> i32 {
|
fn a(&self) -> i32 {
|
||||||
10
|
10
|
||||||
|
|
|
@ -1,64 +1,64 @@
|
||||||
error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope
|
error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope
|
||||||
--> $DIR/subtrait-method.rs:53:9
|
--> $DIR/subtrait-method.rs:55:9
|
||||||
|
|
|
|
||||||
LL | bar.c();
|
LL | bar.c();
|
||||||
| ^ help: there is a method with a similar name: `a`
|
| ^ help: there is a method with a similar name: `a`
|
||||||
|
|
|
|
||||||
= help: items from traits can only be used if the trait is implemented and in scope
|
= help: items from traits can only be used if the trait is implemented and in scope
|
||||||
note: `Baz` defines an item `c`, perhaps you need to implement it
|
note: `Baz` defines an item `c`, perhaps you need to implement it
|
||||||
--> $DIR/subtrait-method.rs:25:1
|
--> $DIR/subtrait-method.rs:27:1
|
||||||
|
|
|
|
||||||
LL | trait Baz: Bar {
|
LL | trait Baz: Bar {
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
|
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
|
||||||
--> $DIR/subtrait-method.rs:57:9
|
|
||||||
|
|
|
||||||
LL | foo.b();
|
|
||||||
| ^ help: there is a method with a similar name: `a`
|
|
||||||
|
|
|
||||||
= help: items from traits can only be used if the trait is implemented and in scope
|
|
||||||
note: `Bar` defines an item `b`, perhaps you need to implement it
|
|
||||||
--> $DIR/subtrait-method.rs:15:1
|
|
||||||
|
|
|
||||||
LL | trait Bar: Foo {
|
|
||||||
| ^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
|
|
||||||
--> $DIR/subtrait-method.rs:59:9
|
--> $DIR/subtrait-method.rs:59:9
|
||||||
|
|
|
|
||||||
|
LL | foo.b();
|
||||||
|
| ^ help: there is a method with a similar name: `a`
|
||||||
|
|
|
||||||
|
= help: items from traits can only be used if the trait is implemented and in scope
|
||||||
|
note: `Bar` defines an item `b`, perhaps you need to implement it
|
||||||
|
--> $DIR/subtrait-method.rs:17:1
|
||||||
|
|
|
||||||
|
LL | trait Bar: Foo {
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
|
||||||
|
--> $DIR/subtrait-method.rs:61:9
|
||||||
|
|
|
||||||
LL | foo.c();
|
LL | foo.c();
|
||||||
| ^ help: there is a method with a similar name: `a`
|
| ^ help: there is a method with a similar name: `a`
|
||||||
|
|
|
|
||||||
= help: items from traits can only be used if the trait is implemented and in scope
|
= help: items from traits can only be used if the trait is implemented and in scope
|
||||||
note: `Baz` defines an item `c`, perhaps you need to implement it
|
note: `Baz` defines an item `c`, perhaps you need to implement it
|
||||||
--> $DIR/subtrait-method.rs:25:1
|
--> $DIR/subtrait-method.rs:27:1
|
||||||
|
|
|
|
||||||
LL | trait Baz: Bar {
|
LL | trait Baz: Bar {
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
|
error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
|
||||||
--> $DIR/subtrait-method.rs:63:9
|
--> $DIR/subtrait-method.rs:65:9
|
||||||
|
|
|
|
||||||
LL | foo.b();
|
LL | foo.b();
|
||||||
| ^ help: there is a method with a similar name: `a`
|
| ^ help: there is a method with a similar name: `a`
|
||||||
|
|
|
|
||||||
= help: items from traits can only be used if the trait is implemented and in scope
|
= help: items from traits can only be used if the trait is implemented and in scope
|
||||||
note: `Bar` defines an item `b`, perhaps you need to implement it
|
note: `Bar` defines an item `b`, perhaps you need to implement it
|
||||||
--> $DIR/subtrait-method.rs:15:1
|
--> $DIR/subtrait-method.rs:17:1
|
||||||
|
|
|
|
||||||
LL | trait Bar: Foo {
|
LL | trait Bar: Foo {
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
|
error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
|
||||||
--> $DIR/subtrait-method.rs:65:9
|
--> $DIR/subtrait-method.rs:67:9
|
||||||
|
|
|
|
||||||
LL | foo.c();
|
LL | foo.c();
|
||||||
| ^ help: there is a method with a similar name: `a`
|
| ^ help: there is a method with a similar name: `a`
|
||||||
|
|
|
|
||||||
= help: items from traits can only be used if the trait is implemented and in scope
|
= help: items from traits can only be used if the trait is implemented and in scope
|
||||||
note: `Baz` defines an item `c`, perhaps you need to implement it
|
note: `Baz` defines an item `c`, perhaps you need to implement it
|
||||||
--> $DIR/subtrait-method.rs:25:1
|
--> $DIR/subtrait-method.rs:27:1
|
||||||
|
|
|
|
||||||
LL | trait Baz: Bar {
|
LL | trait Baz: Bar {
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
|
error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
|
||||||
--> $DIR/type-checking-test-1.rs:17:13
|
--> $DIR/type-checking-test-1.rs:19:13
|
||||||
|
|
|
|
||||||
LL | let _ = x as &dyn Bar<_>; // Ambiguous
|
LL | let _ = x as &dyn Bar<_>; // Ambiguous
|
||||||
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
|
error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
|
||||||
--> $DIR/type-checking-test-1.rs:17:13
|
--> $DIR/type-checking-test-1.rs:19:13
|
||||||
|
|
|
|
||||||
LL | let _ = x as &dyn Bar<_>; // Ambiguous
|
LL | let _ = x as &dyn Bar<_>; // Ambiguous
|
||||||
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// revisions: current next
|
// revisions: current next
|
||||||
//[next] compile-flags: -Znext-solver
|
//[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo: Bar<i32> + Bar<u32> {}
|
trait Foo: Bar<i32> + Bar<u32> {}
|
||||||
trait Bar<T> {
|
trait Bar<T> {
|
||||||
fn bar(&self) -> Option<T> {
|
fn bar(&self) -> Option<T> {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo<T>: Bar<i32> + Bar<T> {}
|
trait Foo<T>: Bar<i32> + Bar<T> {}
|
||||||
trait Bar<T> {
|
trait Bar<T> {
|
||||||
fn bar(&self) -> Option<T> {
|
fn bar(&self) -> Option<T> {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
|
error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
|
||||||
--> $DIR/type-checking-test-2.rs:17:13
|
--> $DIR/type-checking-test-2.rs:19:13
|
||||||
|
|
|
|
||||||
LL | let _ = x as &dyn Bar<u32>; // Error
|
LL | let _ = x as &dyn Bar<u32>; // Error
|
||||||
| ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
| ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||||
|
|
||||||
error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
|
error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
|
||||||
--> $DIR/type-checking-test-2.rs:22:13
|
--> $DIR/type-checking-test-2.rs:24:13
|
||||||
|
|
|
|
||||||
LL | let a = x as &dyn Bar<_>; // Ambiguous
|
LL | let a = x as &dyn Bar<_>; // Ambiguous
|
||||||
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
| ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo<'a>: Bar<'a> {}
|
trait Foo<'a>: Bar<'a> {}
|
||||||
trait Bar<'a> {}
|
trait Bar<'a> {}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/type-checking-test-3.rs:9:13
|
--> $DIR/type-checking-test-3.rs:11:13
|
||||||
|
|
|
|
||||||
LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
|
LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
@ -7,7 +7,7 @@ LL | let _ = x as &dyn Bar<'a>; // Error
|
||||||
| ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
| ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/type-checking-test-3.rs:14:13
|
--> $DIR/type-checking-test-3.rs:16:13
|
||||||
|
|
|
|
||||||
LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) {
|
LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Foo<'a>: Bar<'a, 'a> {}
|
trait Foo<'a>: Bar<'a, 'a> {}
|
||||||
trait Bar<'a, 'b> {
|
trait Bar<'a, 'b> {
|
||||||
fn get_b(&self) -> Option<&'a u32> {
|
fn get_b(&self) -> Option<&'a u32> {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/type-checking-test-4.rs:13:13
|
--> $DIR/type-checking-test-4.rs:15:13
|
||||||
|
|
|
|
||||||
LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
|
LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
@ -7,7 +7,7 @@ LL | let _ = x as &dyn Bar<'static, 'a>; // Error
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/type-checking-test-4.rs:18:13
|
--> $DIR/type-checking-test-4.rs:20:13
|
||||||
|
|
|
|
||||||
LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
|
LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
@ -15,7 +15,7 @@ LL | let _ = x as &dyn Bar<'a, 'static>; // Error
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/type-checking-test-4.rs:24:5
|
--> $DIR/type-checking-test-4.rs:26:5
|
||||||
|
|
|
|
||||||
LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
@ -24,7 +24,7 @@ LL | y.get_b() // ERROR
|
||||||
| ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
| ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/type-checking-test-4.rs:29:5
|
--> $DIR/type-checking-test-4.rs:31:5
|
||||||
|
|
|
|
||||||
LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
@ -32,7 +32,7 @@ LL | <_ as Bar>::get_b(x) // ERROR
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
| ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/type-checking-test-4.rs:34:5
|
--> $DIR/type-checking-test-4.rs:36:5
|
||||||
|
|
|
|
||||||
LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
@ -40,7 +40,7 @@ LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/type-checking-test-4.rs:42:5
|
--> $DIR/type-checking-test-4.rs:44:5
|
||||||
|
|
|
|
||||||
LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
|
||||||
|
--> $DIR/upcast-through-struct-tail.rs:10:5
|
||||||
|
|
|
||||||
|
LL | x
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
|
||||||
|
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
= note: required when coercing `Box<Wrapper<(dyn A + 'a)>>` into `Box<Wrapper<(dyn B + 'a)>>`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
|
||||||
|
--> $DIR/upcast-through-struct-tail.rs:10:5
|
||||||
|
|
|
||||||
|
LL | x
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
|
||||||
|
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
= note: required when coercing `Box<Wrapper<(dyn A + 'a)>>` into `Box<Wrapper<(dyn B + 'a)>>`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,4 +1,3 @@
|
||||||
// check-pass
|
|
||||||
// revisions: current next
|
// revisions: current next
|
||||||
//[next] compile-flags: -Znext-solver
|
//[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
@ -9,6 +8,7 @@ trait B {}
|
||||||
|
|
||||||
fn test<'a>(x: Box<Wrapper<dyn A + 'a>>) -> Box<Wrapper<dyn B + 'a>> {
|
fn test<'a>(x: Box<Wrapper<dyn A + 'a>>) -> Box<Wrapper<dyn B + 'a>> {
|
||||||
x
|
x
|
||||||
|
//~^ ERROR cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
69
tests/ui/traits/upcast_soundness_bug.rs
Normal file
69
tests/ui/traits/upcast_soundness_bug.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#![feature(trait_upcasting)]
|
||||||
|
// known-bug: #120222
|
||||||
|
// check-pass
|
||||||
|
//! This will segfault at runtime.
|
||||||
|
|
||||||
|
pub trait SupSupA {
|
||||||
|
fn method(&self) {}
|
||||||
|
}
|
||||||
|
pub trait SupSupB {}
|
||||||
|
impl<T> SupSupA for T {}
|
||||||
|
impl<T> SupSupB for T {}
|
||||||
|
|
||||||
|
pub trait Super<T>: SupSupA + SupSupB {}
|
||||||
|
|
||||||
|
pub trait Unimplemented {}
|
||||||
|
|
||||||
|
pub trait Trait<T1, T2>: Super<T1> + Super<T2> {
|
||||||
|
fn missing_method(&self)
|
||||||
|
where
|
||||||
|
T1: Unimplemented,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, T> Super<T> for S {}
|
||||||
|
|
||||||
|
impl<S, T1, T2> Trait<T1, T2> for S {}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn user1() -> &'static dyn Trait<u8, u8> {
|
||||||
|
&()
|
||||||
|
/* VTABLE:
|
||||||
|
.L__unnamed_2:
|
||||||
|
.quad core::ptr::drop_in_place<()>
|
||||||
|
.asciz "\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000"
|
||||||
|
.quad example::SupSupA::method
|
||||||
|
.quad .L__unnamed_4 // SupSupB vtable (pointer)
|
||||||
|
.zero 8 // null pointer for missing_method
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn user2() -> &'static dyn Trait<u8, u16> {
|
||||||
|
&()
|
||||||
|
/* VTABLE:
|
||||||
|
.L__unnamed_3:
|
||||||
|
.quad core::ptr::drop_in_place<()>
|
||||||
|
.asciz "\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000"
|
||||||
|
.quad example::SupSupA::method
|
||||||
|
.quad .L__unnamed_4 // SupSupB vtable (pointer)
|
||||||
|
.quad .L__unnamed_5 // Super<u16> vtable (pointer)
|
||||||
|
.zero 8 // null pointer for missing_method
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let p: *const dyn Trait<u8, u8> = &();
|
||||||
|
let p = p as *const dyn Trait<u8, u16>; // <- this is bad!
|
||||||
|
let p = p as *const dyn Super<u16>; // <- this upcast accesses improper vtable entry
|
||||||
|
// accessing from L__unnamed_2 the position for the 'Super<u16> vtable (pointer)',
|
||||||
|
// thus reading 'null pointer for missing_method'
|
||||||
|
|
||||||
|
let p = p as *const dyn SupSupB; // <- this upcast dereferences (null) pointer from that entry
|
||||||
|
// to read the SupSupB vtable (pointer)
|
||||||
|
|
||||||
|
// SEGFAULT
|
||||||
|
|
||||||
|
println!("{:?}", p);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue