RFC 2027: "first draft" of implementation
These are a squashed series of commits.
This commit is contained in:
parent
d28a9c38fe
commit
ef5acdeceb
@ -1146,10 +1146,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
let span = cause.span(self.tcx);
|
||||
|
||||
diag.span_label(span, terr.to_string());
|
||||
if let Some((sp, msg)) = secondary_span {
|
||||
diag.span_label(sp, msg);
|
||||
}
|
||||
// Ignore msg for object safe coercion
|
||||
// since E0038 message will be printed
|
||||
match terr {
|
||||
TypeError::ObjectUnsafeCoercion(_) => {}
|
||||
_ => {
|
||||
diag.span_label(span, terr.to_string());
|
||||
if let Some((sp, msg)) = secondary_span {
|
||||
diag.span_label(sp, msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some((expected, found)) = expected_found {
|
||||
match (terr, is_simple_error, expected == found) {
|
||||
@ -1169,6 +1176,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
&sort_string(values.found),
|
||||
);
|
||||
}
|
||||
(TypeError::ObjectUnsafeCoercion(_), ..) => {
|
||||
diag.note_unsuccessfull_coercion(found, expected);
|
||||
}
|
||||
(_, false, _) => {
|
||||
if let Some(exp_found) = exp_found {
|
||||
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
|
||||
@ -1267,6 +1277,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
let span = trace.cause.span(self.tcx);
|
||||
let failure_code = trace.cause.as_failure_code(terr);
|
||||
let mut diag = match failure_code {
|
||||
FailureCode::Error0038(did) => {
|
||||
let violations = self.tcx.object_safety_violations(did);
|
||||
self.tcx.report_object_safety_error(span, did, violations)
|
||||
}
|
||||
FailureCode::Error0317(failure_str) => {
|
||||
struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
|
||||
}
|
||||
@ -1628,6 +1642,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
enum FailureCode {
|
||||
Error0038(DefId),
|
||||
Error0317(&'static str),
|
||||
Error0580(&'static str),
|
||||
Error0308(&'static str),
|
||||
@ -1666,6 +1681,7 @@ impl<'tcx> ObligationCause<'tcx> {
|
||||
TypeError::IntrinsicCast => {
|
||||
Error0308("cannot coerce intrinsics to function pointers")
|
||||
}
|
||||
TypeError::ObjectUnsafeCoercion(did) => Error0038(did.clone()),
|
||||
_ => Error0308("mismatched types"),
|
||||
},
|
||||
}
|
||||
|
@ -790,15 +790,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
ty::Predicate::ObjectSafe(trait_def_id) => {
|
||||
let violations = self.tcx.object_safety_violations(trait_def_id);
|
||||
if let Some(err) = self.tcx.report_object_safety_error(
|
||||
self.tcx.report_object_safety_error(
|
||||
span,
|
||||
trait_def_id,
|
||||
violations,
|
||||
) {
|
||||
err
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
|
||||
@ -934,11 +930,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
TraitNotObjectSafe(did) => {
|
||||
let violations = self.tcx.object_safety_violations(did);
|
||||
if let Some(err) = self.tcx.report_object_safety_error(span, did, violations) {
|
||||
err
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
self.tcx.report_object_safety_error(span, did, violations)
|
||||
}
|
||||
|
||||
// already reported in the query
|
||||
@ -1493,11 +1485,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
span: Span,
|
||||
trait_def_id: DefId,
|
||||
violations: Vec<ObjectSafetyViolation>,
|
||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
||||
if self.sess.trait_methods_not_found.borrow().contains(&span) {
|
||||
// Avoid emitting error caused by non-existing method (#58734)
|
||||
return None;
|
||||
}
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let trait_str = self.def_path_str(trait_def_id);
|
||||
let span = self.sess.source_map().def_span(span);
|
||||
let mut err = struct_span_err!(
|
||||
@ -1515,7 +1503,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
};
|
||||
}
|
||||
}
|
||||
Some(err)
|
||||
|
||||
if self.sess.trait_methods_not_found.borrow().contains(&span) {
|
||||
// Avoid emitting error caused by non-existing method (#58734)
|
||||
err.cancel();
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1926,6 +1920,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
err.note(&format!("required for the cast to the object type `{}`",
|
||||
self.ty_to_string(object_ty)));
|
||||
}
|
||||
ObligationCauseCode::Coercion { source: _, target } => {
|
||||
err.note(&format!("required by cast to type `{}`",
|
||||
self.ty_to_string(target)));
|
||||
}
|
||||
ObligationCauseCode::RepeatVec => {
|
||||
err.note("the `Copy` trait is required because the \
|
||||
repeated element will be copied");
|
||||
|
@ -188,6 +188,9 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
/// Obligation incurred due to an object cast.
|
||||
ObjectCastObligation(/* Object type */ Ty<'tcx>),
|
||||
|
||||
/// Obligation incurred due to a coercion.
|
||||
Coercion { source: Ty<'tcx>, target: Ty<'tcx> },
|
||||
|
||||
// Various cases where expressions must be sized/copy/etc:
|
||||
/// L = X implies that L is Sized
|
||||
AssignmentLhsSized,
|
||||
|
@ -2246,7 +2246,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
if let Some(principal) = data.principal() {
|
||||
principal.with_self_ty(self.tcx(), self_ty)
|
||||
if !self.infcx.tcx.features().object_safe_for_dispatch {
|
||||
principal.with_self_ty(self.tcx(), self_ty)
|
||||
} else if self.tcx().is_object_safe(principal.def_id()) {
|
||||
principal.with_self_ty(self.tcx(), self_ty)
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Only auto-trait bounds exist.
|
||||
return;
|
||||
|
@ -481,6 +481,10 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
||||
.and_then(|r| Some(super::ObjectTypeBound(ty, r)))
|
||||
),
|
||||
super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
|
||||
super::Coercion { source, target } => Some(super::Coercion {
|
||||
source: tcx.lift(&source)?,
|
||||
target: tcx.lift(&target)?,
|
||||
}),
|
||||
super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
|
||||
super::TupleInitializerSized => Some(super::TupleInitializerSized),
|
||||
super::StructInitializerSized => Some(super::StructInitializerSized),
|
||||
|
@ -45,7 +45,7 @@ pub enum TypeError<'tcx> {
|
||||
ProjectionMismatched(ExpectedFound<DefId>),
|
||||
ProjectionBoundsLength(ExpectedFound<usize>),
|
||||
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
|
||||
|
||||
ObjectUnsafeCoercion(DefId),
|
||||
ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
|
||||
|
||||
IntrinsicCast,
|
||||
@ -179,6 +179,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
||||
IntrinsicCast => {
|
||||
write!(f, "cannot coerce intrinsics to function pointers")
|
||||
}
|
||||
ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -749,6 +749,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
|
||||
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
|
||||
ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
|
||||
IntrinsicCast => IntrinsicCast,
|
||||
ObjectUnsafeCoercion(ref x) => return tcx.lift(x).map(ObjectUnsafeCoercion),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1356,6 +1357,7 @@ EnumTypeFoldableImpl! {
|
||||
(ty::error::TypeError::ExistentialMismatch)(x),
|
||||
(ty::error::TypeError::ConstMismatch)(x),
|
||||
(ty::error::TypeError::IntrinsicCast),
|
||||
(ty::error::TypeError::ObjectUnsafeCoercion)(x),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,16 +380,21 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||
// obligations that don't refer to Self and
|
||||
// checking those
|
||||
|
||||
let cause = self.cause(traits::MiscObligation);
|
||||
let component_traits =
|
||||
data.auto_traits().chain(data.principal_def_id());
|
||||
self.out.extend(
|
||||
component_traits.map(|did| traits::Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::ObjectSafe(did)
|
||||
))
|
||||
);
|
||||
let defer_to_coercion =
|
||||
self.infcx.tcx.features().object_safe_for_dispatch;
|
||||
|
||||
if !defer_to_coercion {
|
||||
let cause = self.cause(traits::MiscObligation);
|
||||
let component_traits =
|
||||
data.auto_traits().chain(data.principal_def_id());
|
||||
self.out.extend(
|
||||
component_traits.map(|did| traits::Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::ObjectSafe(did)
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Inference variables are the complicated case, since we don't
|
||||
|
@ -152,6 +152,32 @@ impl Diagnostic {
|
||||
self.note_expected_found_extra(label, expected, found, &"", &"")
|
||||
}
|
||||
|
||||
pub fn note_unsuccessfull_coercion(&mut self,
|
||||
expected: DiagnosticStyledString,
|
||||
found: DiagnosticStyledString)
|
||||
-> &mut Self
|
||||
{
|
||||
let mut msg: Vec<_> =
|
||||
vec![(format!("required when trying to coerce from type `"),
|
||||
Style::NoStyle)];
|
||||
msg.extend(expected.0.iter()
|
||||
.map(|x| match *x {
|
||||
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
|
||||
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
|
||||
}));
|
||||
msg.push((format!("` to type '"), Style::NoStyle));
|
||||
msg.extend(found.0.iter()
|
||||
.map(|x| match *x {
|
||||
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
|
||||
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
|
||||
}));
|
||||
msg.push((format!("`"), Style::NoStyle));
|
||||
|
||||
// For now, just attach these as notes
|
||||
self.highlighted_note(msg);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn note_expected_found_extra(&mut self,
|
||||
label: &dyn fmt::Display,
|
||||
expected: DiagnosticStyledString,
|
||||
|
@ -209,6 +209,11 @@ impl<'a> DiagnosticBuilder<'a> {
|
||||
found_extra: &dyn fmt::Display,
|
||||
) -> &mut Self);
|
||||
|
||||
forward!(pub fn note_unsuccessfull_coercion(&mut self,
|
||||
expected: DiagnosticStyledString,
|
||||
found: DiagnosticStyledString,
|
||||
) -> &mut Self);
|
||||
|
||||
forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
|
||||
forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
|
||||
sp: S,
|
||||
|
@ -1275,8 +1275,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
span,
|
||||
item.trait_ref().def_id(),
|
||||
object_safety_violations
|
||||
)
|
||||
.map(|mut err| err.emit());
|
||||
).emit();
|
||||
return tcx.types.err;
|
||||
}
|
||||
}
|
||||
|
@ -428,21 +428,36 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
self.report_cast_to_unsized_type(fcx);
|
||||
} else if self.expr_ty.references_error() || self.cast_ty.references_error() {
|
||||
// No sense in giving duplicate error messages
|
||||
} else if self.try_coercion_cast(fcx) {
|
||||
self.trivial_cast_lint(fcx);
|
||||
debug!(" -> CoercionCast");
|
||||
fcx.tables.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id);
|
||||
|
||||
} else {
|
||||
match self.do_check(fcx) {
|
||||
Ok(k) => {
|
||||
debug!(" -> {:?}", k);
|
||||
match self.try_coercion_cast(fcx) {
|
||||
Ok(()) => {
|
||||
self.trivial_cast_lint(fcx);
|
||||
debug!(" -> CoercionCast");
|
||||
fcx.tables.borrow_mut()
|
||||
.set_coercion_cast(self.expr.hir_id.local_id);
|
||||
}
|
||||
Err(ty::error::TypeError::ObjectUnsafeCoercion(did)) => {
|
||||
self.report_object_unsafe_cast(&fcx, did);
|
||||
}
|
||||
Err(_) => {
|
||||
match self.do_check(fcx) {
|
||||
Ok(k) => {
|
||||
debug!(" -> {:?}", k);
|
||||
}
|
||||
Err(e) => self.report_cast_error(fcx, e),
|
||||
};
|
||||
}
|
||||
Err(e) => self.report_cast_error(fcx, e),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) {
|
||||
let violations = fcx.tcx.object_safety_violations(did);
|
||||
let mut err = fcx.tcx.report_object_safety_error(self.cast_span, did, violations);
|
||||
err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty)));
|
||||
err.emit();
|
||||
}
|
||||
|
||||
/// Checks a cast, and report an error if one exists. In some cases, this
|
||||
/// can return Ok and create type errors in the fcx rather than returning
|
||||
/// directly. coercion-cast is handled in check instead of here.
|
||||
@ -646,8 +661,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> bool {
|
||||
fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No).is_ok()
|
||||
fn try_coercion_cast(
|
||||
&self,
|
||||
fcx: &FnCtxt<'a, 'tcx>,
|
||||
) -> Result<(), ty::error::TypeError<'_>> {
|
||||
match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,10 +61,11 @@ use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
||||
use rustc::ty::adjustment::{
|
||||
Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast
|
||||
};
|
||||
use rustc::ty::{self, TypeAndMut, Ty, subst::SubstsRef};
|
||||
use rustc::ty::{self, TypeAndMut, Ty};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::error::TypeError;
|
||||
use rustc::ty::relate::RelateResult;
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::ops::Deref;
|
||||
use syntax::feature_gate;
|
||||
@ -196,9 +197,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
// a "spurious" type variable, and we don't want to have that
|
||||
// type variable in memory if the coercion fails.
|
||||
let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b));
|
||||
if unsize.is_ok() {
|
||||
debug!("coerce: unsize successful");
|
||||
return unsize;
|
||||
match unsize {
|
||||
Ok(_) => {
|
||||
debug!("coerce: unsize successful");
|
||||
return unsize;
|
||||
}
|
||||
Err(TypeError::ObjectUnsafeCoercion(did)) => {
|
||||
debug!("coerce: unsize not object safe");
|
||||
return Err(TypeError::ObjectUnsafeCoercion(did));
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
debug!("coerce: unsize failed");
|
||||
|
||||
@ -539,7 +547,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
let mut selcx = traits::SelectionContext::new(self);
|
||||
|
||||
// Create an obligation for `Source: CoerceUnsized<Target>`.
|
||||
let cause = ObligationCause::misc(self.cause.span, self.body_id);
|
||||
let cause = ObligationCause::new(
|
||||
self.cause.span,
|
||||
self.body_id,
|
||||
ObligationCauseCode::Coercion { source, target },
|
||||
);
|
||||
|
||||
// Use a FIFO queue for this custom fulfillment procedure.
|
||||
//
|
||||
@ -566,14 +578,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
let obligation = queue.remove(0);
|
||||
debug!("coerce_unsized resolve step: {:?}", obligation);
|
||||
let trait_ref = match obligation.predicate {
|
||||
ty::Predicate::Trait(ref t) if traits.contains(&t.def_id()) => {
|
||||
if unsize_did == t.def_id() {
|
||||
if let ty::Tuple(..) = &t.skip_binder().input_types().nth(1).unwrap().kind {
|
||||
ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
|
||||
if unsize_did == tr.def_id() {
|
||||
let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind;
|
||||
if let ty::Tuple(..) = sty {
|
||||
debug!("coerce_unsized: found unsized tuple coercion");
|
||||
has_unsized_tuple_coercion = true;
|
||||
}
|
||||
}
|
||||
t.clone()
|
||||
tr.clone()
|
||||
}
|
||||
_ => {
|
||||
coercion.obligations.push(obligation);
|
||||
|
@ -183,8 +183,11 @@ fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) {
|
||||
|
||||
for component_def_id in component_def_ids {
|
||||
if !tcx.is_object_safe(component_def_id) {
|
||||
// This is an error, but it will be reported by wfcheck. Ignore it here.
|
||||
// Without the 'object_safe_for_dispatch' feature this is an error
|
||||
// which will be reported by wfcheck. Ignore it here.
|
||||
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
|
||||
// With the feature enabled, the trait is not implemented automatically,
|
||||
// so this is valid.
|
||||
} else {
|
||||
let mut supertrait_def_ids =
|
||||
traits::supertrait_def_ids(tcx, component_def_id);
|
||||
|
@ -528,6 +528,9 @@ declare_features! (
|
||||
/// Enable accurate caller location reporting during panic (RFC 2091).
|
||||
(active, track_caller, "1.40.0", Some(47809), None),
|
||||
|
||||
/// Non-object safe trait objects safe to use but cannot be created in safe rust
|
||||
(active, object_safe_for_dispatch, "1.40.0", Some(43561), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -459,6 +459,7 @@ symbols! {
|
||||
no_std,
|
||||
not,
|
||||
note,
|
||||
object_safe_for_dispatch,
|
||||
Ok,
|
||||
omit_gdb_pretty_printer_section,
|
||||
on,
|
||||
|
18
src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs
Normal file
18
src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Check that unsafe trait object do not implement themselves
|
||||
// automatically
|
||||
|
||||
#![feature(object_safe_for_dispatch)]
|
||||
|
||||
trait Trait: Sized {
|
||||
fn call(&self);
|
||||
}
|
||||
|
||||
fn takes_t<S: Trait>(s: S) {
|
||||
s.call();
|
||||
}
|
||||
|
||||
fn takes_t_obj(t: &dyn Trait) {
|
||||
takes_t(t); //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,12 @@
|
||||
error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied
|
||||
--> $DIR/coherence-unsafe-trait-object-impl.rs:15:13
|
||||
|
|
||||
LL | fn takes_t<S: Trait>(s: S) {
|
||||
| ------- ----- required by this bound in `takes_t`
|
||||
...
|
||||
LL | takes_t(t);
|
||||
| ^ the trait `Trait` is not implemented for `&dyn Trait`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -1,16 +0,0 @@
|
||||
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
|
||||
--> $DIR/feature-gate-exhaustive-patterns.rs:7:9
|
||||
|
|
||||
LL | let Ok(_x) = foo();
|
||||
| ^^^^^^ pattern `Err(_)` not covered
|
||||
|
|
||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | if let Ok(_x) = foo() { /* */ }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0005`.
|
@ -0,0 +1,41 @@
|
||||
// Test that the use of the non object-safe trait objects
|
||||
// are gated by `object_safe_for_dispatch` feature gate.
|
||||
|
||||
trait NonObjectSafe1: Sized {}
|
||||
|
||||
trait NonObjectSafe2 {
|
||||
fn static_fn() {}
|
||||
}
|
||||
|
||||
trait NonObjectSafe3 {
|
||||
fn foo<T>(&self);
|
||||
}
|
||||
|
||||
trait NonObjectSafe4 {
|
||||
fn foo(&self, &Self);
|
||||
}
|
||||
|
||||
fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
|
||||
//~^ ERROR E0038
|
||||
}
|
||||
|
||||
fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 {
|
||||
//~^ ERROR E0038
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
|
||||
//~^ ERROR E0038
|
||||
}
|
||||
|
||||
fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> {
|
||||
//~^ ERROR E0038
|
||||
loop {}
|
||||
}
|
||||
|
||||
trait Trait {}
|
||||
|
||||
impl Trait for dyn NonObjectSafe1 {}
|
||||
//~^ ERROR E0038
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,46 @@
|
||||
error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
|
||||
--> $DIR/feature-gate-object_safe_for_dispatch.rs:18:1
|
||||
|
|
||||
LL | fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe1` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
|
||||
error[E0038]: the trait `NonObjectSafe2` cannot be made into an object
|
||||
--> $DIR/feature-gate-object_safe_for_dispatch.rs:22:1
|
||||
|
|
||||
LL | fn static_fn() {}
|
||||
| --------- associated function `static_fn` has no `self` parameter
|
||||
...
|
||||
LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe2` cannot be made into an object
|
||||
|
||||
error[E0038]: the trait `NonObjectSafe3` cannot be made into an object
|
||||
--> $DIR/feature-gate-object_safe_for_dispatch.rs:27:1
|
||||
|
|
||||
LL | fn foo<T>(&self);
|
||||
| --- method `foo` has generic type parameters
|
||||
...
|
||||
LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe3` cannot be made into an object
|
||||
|
||||
error[E0038]: the trait `NonObjectSafe4` cannot be made into an object
|
||||
--> $DIR/feature-gate-object_safe_for_dispatch.rs:31:1
|
||||
|
|
||||
LL | fn foo(&self, &Self);
|
||||
| --- method `foo` references the `Self` type in its parameters or return type
|
||||
...
|
||||
LL | fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe4` cannot be made into an object
|
||||
|
||||
error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
|
||||
--> $DIR/feature-gate-object_safe_for_dispatch.rs:38:6
|
||||
|
|
||||
LL | impl Trait for dyn NonObjectSafe1 {}
|
||||
| ^^^^^ the trait `NonObjectSafe1` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -17,6 +17,7 @@ LL | let test: &mut dyn Bar = &mut thing;
|
||||
| ^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
|
||||
= note: required by cast to type `&mut dyn Bar`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -14,6 +14,7 @@ LL | let _ = x
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Array>` for `&T`
|
||||
= note: required by cast to type `&dyn Array`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -14,6 +14,7 @@ LL | Box::new(());
|
||||
|
|
||||
= note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<()>`
|
||||
= note: required by cast to type `std::boxed::Box<dyn Foo>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:18:16
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:21:16
|
||||
|
|
||||
LL | fn take_param<T:Foo>(foo: &T) { }
|
||||
| ---------- --- required by this bound in `take_param`
|
||||
@ -10,7 +10,7 @@ LL | take_param(&x);
|
||||
= note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>`
|
||||
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:24:19
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:28:19
|
||||
|
|
||||
LL | let z = &x as &dyn Foo;
|
||||
| ^^^^^^^^ the trait `Foo` cannot be made into an object
|
||||
@ -18,13 +18,14 @@ LL | let z = &x as &dyn Foo;
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:24:13
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:28:13
|
||||
|
|
||||
LL | let z = &x as &dyn Foo;
|
||||
| ^^ the trait `Foo` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<{integer}>`
|
||||
= note: required by cast to type `&dyn Foo`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
@ -0,0 +1,25 @@
|
||||
error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:21:16
|
||||
|
|
||||
LL | fn take_param<T:Foo>(foo: &T) { }
|
||||
| ---------- --- required by this bound in `take_param`
|
||||
...
|
||||
LL | take_param(&x);
|
||||
| ^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>`
|
||||
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:28:13
|
||||
|
|
||||
LL | let z = &x as &dyn Foo;
|
||||
| ^^ the trait `Foo` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<i32>`
|
||||
= note: required by cast to type `&dyn Foo`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0038, E0277.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
@ -1,5 +1,8 @@
|
||||
// Test that Copy bounds inherited by trait are checked.
|
||||
//
|
||||
// revisions: curr object_safe_for_dispatch
|
||||
|
||||
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
use std::any::Any;
|
||||
@ -15,15 +18,17 @@ fn take_param<T:Foo>(foo: &T) { }
|
||||
|
||||
fn a() {
|
||||
let x: Box<_> = box 3;
|
||||
take_param(&x); //~ ERROR E0277
|
||||
take_param(&x); //[curr]~ ERROR E0277
|
||||
//[object_safe_for_dispatch]~^ ERROR E0277
|
||||
}
|
||||
|
||||
fn b() {
|
||||
let x: Box<_> = box 3;
|
||||
let y = &x;
|
||||
let z = &x as &dyn Foo;
|
||||
//~^ ERROR E0038
|
||||
//~| ERROR E0038
|
||||
//[curr]~^ ERROR E0038
|
||||
//[curr]~| ERROR E0038
|
||||
//[object_safe_for_dispatch]~^^^ ERROR E0038
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-associated-consts.rs:9:1
|
||||
--> $DIR/object-safety-associated-consts.rs:12:1
|
||||
|
|
||||
LL | const X: usize;
|
||||
| - the trait cannot contain associated consts like `X`
|
@ -0,0 +1,15 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-associated-consts.rs:14:5
|
||||
|
|
||||
LL | const X: usize;
|
||||
| - the trait cannot contain associated consts like `X`
|
||||
...
|
||||
LL | t
|
||||
| ^ the trait `Bar` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
|
||||
= note: required by cast to type `&dyn Bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -1,14 +1,18 @@
|
||||
// Check that we correctly prevent users from making trait objects
|
||||
// from traits with associated consts.
|
||||
//
|
||||
// revisions: curr object_safe_for_dispatch
|
||||
|
||||
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||
|
||||
trait Bar {
|
||||
const X: usize;
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
//~^ ERROR E0038
|
||||
//[curr]~^ ERROR E0038
|
||||
t
|
||||
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-generics.rs:14:1
|
||||
--> $DIR/object-safety-generics.rs:18:1
|
||||
|
|
||||
LL | fn bar<T>(&self, t: T);
|
||||
| --- method `bar` has generic type parameters
|
||||
@ -8,7 +8,7 @@ LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
||||
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-generics.rs:19:1
|
||||
--> $DIR/object-safety-generics.rs:24:1
|
||||
|
|
||||
LL | fn bar<T>(&self, t: T);
|
||||
| --- method `bar` has generic type parameters
|
@ -0,0 +1,27 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-generics.rs:20:5
|
||||
|
|
||||
LL | fn bar<T>(&self, t: T);
|
||||
| --- method `bar` has generic type parameters
|
||||
...
|
||||
LL | t
|
||||
| ^ the trait `Bar` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
|
||||
= note: required by cast to type `&dyn Bar`
|
||||
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-generics.rs:26:5
|
||||
|
|
||||
LL | fn bar<T>(&self, t: T);
|
||||
| --- method `bar` has generic type parameters
|
||||
...
|
||||
LL | t as &dyn Bar
|
||||
| ^ the trait `Bar` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
|
||||
= note: required by cast to type `&dyn Bar`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -1,6 +1,10 @@
|
||||
// Check that we correctly prevent users from making trait objects
|
||||
// from traits with generic methods, unless `where Self : Sized` is
|
||||
// present.
|
||||
// revisions: curr object_safe_for_dispatch
|
||||
|
||||
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||
|
||||
|
||||
trait Bar {
|
||||
fn bar<T>(&self, t: T);
|
||||
@ -12,13 +16,15 @@ trait Quux {
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
//~^ ERROR E0038
|
||||
//[curr]~^ ERROR E0038
|
||||
t
|
||||
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||
}
|
||||
|
||||
fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
|
||||
//~^ ERROR E0038
|
||||
//[curr]~^ ERROR E0038
|
||||
t as &dyn Bar
|
||||
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||
}
|
||||
|
||||
fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-mentions-Self.rs:17:1
|
||||
--> $DIR/object-safety-mentions-Self.rs:22:1
|
||||
|
|
||||
LL | fn bar(&self, x: &Self);
|
||||
| --- method `bar` references the `Self` type in its parameters or return type
|
||||
@ -8,10 +8,10 @@ LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
||||
|
||||
error[E0038]: the trait `Baz` cannot be made into an object
|
||||
--> $DIR/object-safety-mentions-Self.rs:22:1
|
||||
--> $DIR/object-safety-mentions-Self.rs:28:1
|
||||
|
|
||||
LL | fn bar(&self) -> Self;
|
||||
| --- method `bar` references the `Self` type in its parameters or return type
|
||||
LL | fn baz(&self) -> Self;
|
||||
| --- method `baz` references the `Self` type in its parameters or return type
|
||||
...
|
||||
LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object
|
@ -0,0 +1,27 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-mentions-Self.rs:24:5
|
||||
|
|
||||
LL | fn bar(&self, x: &Self);
|
||||
| --- method `bar` references the `Self` type in its parameters or return type
|
||||
...
|
||||
LL | t
|
||||
| ^ the trait `Bar` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
|
||||
= note: required by cast to type `&dyn Bar`
|
||||
|
||||
error[E0038]: the trait `Baz` cannot be made into an object
|
||||
--> $DIR/object-safety-mentions-Self.rs:30:5
|
||||
|
|
||||
LL | fn baz(&self) -> Self;
|
||||
| --- method `baz` references the `Self` type in its parameters or return type
|
||||
...
|
||||
LL | t
|
||||
| ^ the trait `Baz` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Baz>` for `&T`
|
||||
= note: required by cast to type `&dyn Baz`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -1,27 +1,34 @@
|
||||
// Check that we correctly prevent users from making trait objects
|
||||
// form traits that make use of `Self` in an argument or return
|
||||
// position, unless `where Self : Sized` is present..
|
||||
//
|
||||
// revisions: curr object_safe_for_dispatch
|
||||
|
||||
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||
|
||||
|
||||
trait Bar {
|
||||
fn bar(&self, x: &Self);
|
||||
}
|
||||
|
||||
trait Baz {
|
||||
fn bar(&self) -> Self;
|
||||
fn baz(&self) -> Self;
|
||||
}
|
||||
|
||||
trait Quux {
|
||||
fn get(&self, s: &Self) -> Self where Self : Sized;
|
||||
fn quux(&self, s: &Self) -> Self where Self : Sized;
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
//~^ ERROR E0038
|
||||
loop { }
|
||||
//[curr]~^ ERROR E0038
|
||||
t
|
||||
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||
}
|
||||
|
||||
fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
|
||||
//~^ ERROR E0038
|
||||
//[curr]~^ ERROR E0038
|
||||
t
|
||||
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||
}
|
||||
|
||||
fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
|
||||
@ -32,5 +39,4 @@ fn make_quux_explicit<T:Quux>(t: &T) -> &dyn Quux {
|
||||
t as &dyn Quux
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
|
@ -0,0 +1,12 @@
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/object-safety-no-static.rs:12:1
|
||||
|
|
||||
LL | fn foo() {}
|
||||
| --- associated function `foo` has no `self` parameter
|
||||
...
|
||||
LL | fn diverges() -> Box<dyn Foo> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -0,0 +1,15 @@
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/object-safety-no-static.rs:22:27
|
||||
|
|
||||
LL | fn foo() {}
|
||||
| --- associated function `foo` has no `self` parameter
|
||||
...
|
||||
LL | let b: Box<dyn Foo> = Box::new(Bar);
|
||||
| ^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<Bar>`
|
||||
= note: required by cast to type `std::boxed::Box<dyn Foo>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -1,14 +1,24 @@
|
||||
// Check that we correctly prevent users from making trait objects
|
||||
// from traits with static methods.
|
||||
//
|
||||
// revisions: curr object_safe_for_dispatch
|
||||
|
||||
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||
|
||||
trait Foo {
|
||||
fn foo();
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<dyn Foo + 'static> {
|
||||
//~^ ERROR E0038
|
||||
fn diverges() -> Box<dyn Foo> {
|
||||
//[curr]~^ ERROR E0038
|
||||
loop { }
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl Foo for Bar {}
|
||||
|
||||
fn main() {
|
||||
let b: Box<dyn Foo> = Box::new(Bar);
|
||||
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-sized-2.rs:10:1
|
||||
--> $DIR/object-safety-sized-2.rs:14:1
|
||||
|
|
||||
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
@ -0,0 +1,13 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-sized-2.rs:16:5
|
||||
|
|
||||
LL | t
|
||||
| ^ the trait `Bar` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
|
||||
= note: required by cast to type `&dyn Bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -1,5 +1,9 @@
|
||||
// Check that we correctly prevent users from making trait objects
|
||||
// from traits where `Self : Sized`.
|
||||
//
|
||||
// revisions: curr object_safe_for_dispatch
|
||||
|
||||
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||
|
||||
trait Bar
|
||||
where Self : Sized
|
||||
@ -8,8 +12,9 @@ trait Bar
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
//~^ ERROR E0038
|
||||
loop { }
|
||||
//[curr]~^ ERROR E0038
|
||||
t
|
||||
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-sized.rs:8:1
|
||||
--> $DIR/object-safety-sized.rs:12:1
|
||||
|
|
||||
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
@ -0,0 +1,13 @@
|
||||
error[E0038]: the trait `Bar` cannot be made into an object
|
||||
--> $DIR/object-safety-sized.rs:14:5
|
||||
|
|
||||
LL | t
|
||||
| ^ the trait `Bar` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
|
||||
= note: required by cast to type `&dyn Bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -1,13 +1,18 @@
|
||||
// Check that we correctly prevent users from making trait objects
|
||||
// from traits where `Self : Sized`.
|
||||
//
|
||||
// revisions: curr object_safe_for_dispatch
|
||||
|
||||
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||
|
||||
trait Bar : Sized {
|
||||
fn bar<T>(&self, t: T);
|
||||
}
|
||||
|
||||
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
//~^ ERROR E0038
|
||||
//[curr]~^ ERROR E0038
|
||||
t
|
||||
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -0,0 +1,23 @@
|
||||
// Check that we if we get ahold of an object unsafe trait
|
||||
// object with auto traits and lifetimes, we can downcast it
|
||||
//
|
||||
// check-pass
|
||||
|
||||
#![feature(object_safe_for_dispatch)]
|
||||
|
||||
trait Trait: Sized {}
|
||||
|
||||
fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait {
|
||||
t
|
||||
}
|
||||
|
||||
fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't))
|
||||
-> &'b (dyn Trait + 't)
|
||||
where
|
||||
'a: 'b,
|
||||
't: 'a + 'b,
|
||||
{
|
||||
t
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,69 @@
|
||||
// Check that we can manually implement an object
|
||||
// unsafe trait for its trait object
|
||||
//
|
||||
// run-pass
|
||||
|
||||
#![feature(object_safe_for_dispatch)]
|
||||
|
||||
trait Bad {
|
||||
fn stat() -> char {
|
||||
'A'
|
||||
}
|
||||
fn virt(&self) -> char {
|
||||
'B'
|
||||
}
|
||||
fn indirect(&self) -> char {
|
||||
Self::stat()
|
||||
}
|
||||
}
|
||||
|
||||
trait Good {
|
||||
fn good_virt(&self) -> char {
|
||||
panic!()
|
||||
}
|
||||
fn good_indirect(&self) -> char {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Bad for dyn Bad + 'a {
|
||||
fn stat() -> char {
|
||||
'C'
|
||||
}
|
||||
fn virt(&self) -> char {
|
||||
'D'
|
||||
}
|
||||
}
|
||||
|
||||
struct Struct {}
|
||||
|
||||
impl Bad for Struct {}
|
||||
|
||||
impl Good for Struct {}
|
||||
|
||||
fn main() {
|
||||
let s = Struct {};
|
||||
|
||||
let mut res = String::new();
|
||||
|
||||
// Directly call static
|
||||
res.push(Struct::stat()); // "A"
|
||||
res.push(<dyn Bad>::stat()); // "AC"
|
||||
|
||||
let good: &dyn Good = &s;
|
||||
|
||||
// These look similar enough...
|
||||
let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) };
|
||||
|
||||
// Call virtual
|
||||
res.push(s.virt()); // "ACB"
|
||||
res.push(bad.virt()); // "ACBD"
|
||||
|
||||
// Indirectly call static
|
||||
res.push(s.indirect()); // "ACBDA"
|
||||
res.push(bad.indirect()); // "ACBDAC"
|
||||
|
||||
if &res != "ACBDAC" {
|
||||
panic!();
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
// Check that we can statically dispatch methods for object
|
||||
// unsafe trait objects, directly and indirectly
|
||||
//
|
||||
// check-pass
|
||||
|
||||
#![feature(object_safe_for_dispatch)]
|
||||
|
||||
trait Statics {
|
||||
fn plain() {}
|
||||
fn generic<T>() {}
|
||||
}
|
||||
|
||||
trait Trait: Sized {}
|
||||
|
||||
impl<'a> Statics for dyn Trait + 'a {}
|
||||
|
||||
fn static_poly<T: Statics + ?Sized>() {
|
||||
T::plain();
|
||||
T::generic::<usize>();
|
||||
}
|
||||
|
||||
fn inferred_poly<T: Statics + ?Sized>(t: &T) {
|
||||
static_poly::<T>();
|
||||
T::plain();
|
||||
T::generic::<usize>();
|
||||
}
|
||||
|
||||
fn call(t: &dyn Trait) {
|
||||
static_poly::<dyn Trait>();
|
||||
inferred_poly(t);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
static_poly::<dyn Trait>();
|
||||
<dyn Trait>::plain();
|
||||
<dyn Trait>::generic::<usize>()
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/arbitrary-self-types-not-object-safe.rs:34:32
|
||||
|
|
||||
LL | fn foo(self: &Rc<Self>) -> usize;
|
||||
| --- method `foo`'s `self` parameter cannot be dispatched on
|
||||
...
|
||||
LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
|
||||
| ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
||||
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/arbitrary-self-types-not-object-safe.rs:34:13
|
||||
|
|
||||
LL | fn foo(self: &Rc<Self>) -> usize;
|
||||
| --- method `foo`'s `self` parameter cannot be dispatched on
|
||||
...
|
||||
LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
|
||||
| ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
|
||||
= note: required by cast to type `std::rc::Rc<dyn Foo>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -0,0 +1,15 @@
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/arbitrary-self-types-not-object-safe.rs:34:13
|
||||
|
|
||||
LL | fn foo(self: &Rc<Self>) -> usize;
|
||||
| --- method `foo`'s `self` parameter cannot be dispatched on
|
||||
...
|
||||
LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
|
||||
| ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
|
||||
= note: required by cast to type `std::rc::Rc<dyn Foo>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
@ -1,3 +1,6 @@
|
||||
// revisions: curr object_safe_for_dispatch
|
||||
|
||||
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||
#![feature(arbitrary_self_types)]
|
||||
|
||||
use std::rc::Rc;
|
||||
@ -29,8 +32,9 @@ impl Bar for usize {
|
||||
|
||||
fn make_foo() {
|
||||
let x = Rc::new(5usize) as Rc<dyn Foo>;
|
||||
//~^ ERROR E0038
|
||||
//~| ERROR E0038
|
||||
//[curr]~^ ERROR E0038
|
||||
//[curr]~| ERROR E0038
|
||||
//[object_safe_for_dispatch]~^^^ ERROR E0038
|
||||
}
|
||||
|
||||
fn make_bar() {
|
||||
|
@ -8,6 +8,7 @@ LL | let _: &dyn Tr = &St;
|
||||
| ^^^ the trait `Tr` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St`
|
||||
= note: required by cast to type `&dyn Tr`
|
||||
|
||||
error[E0038]: the trait `Tr` cannot be made into an object
|
||||
--> $DIR/trait-object-safety.rs:15:12
|
||||
|
@ -33,6 +33,7 @@ LL | (box 10 as Box<dyn bar>).dup();
|
||||
| ^^^^^^ the trait `bar` cannot be made into an object
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn bar>>` for `std::boxed::Box<{integer}>`
|
||||
= note: required by cast to type `std::boxed::Box<dyn bar>`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
18
src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs
Normal file
18
src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Check that we do not allow casts or coercions
|
||||
// to object unsafe trait objects inside a Box
|
||||
|
||||
#![feature(object_safe_for_dispatch)]
|
||||
|
||||
trait Trait: Sized {}
|
||||
|
||||
struct S;
|
||||
|
||||
impl Trait for S {}
|
||||
|
||||
fn takes_box(t: Box<dyn Trait>) {}
|
||||
|
||||
fn main() {
|
||||
Box::new(S) as Box<dyn Trait>; //~ ERROR E0038
|
||||
let t_box: Box<dyn Trait> = Box::new(S); //~ ERROR E0038
|
||||
takes_box(Box::new(S)); //~ ERROR E0038
|
||||
}
|
33
src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
Normal file
33
src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
Normal file
@ -0,0 +1,33 @@
|
||||
error[E0038]: the trait `Trait` cannot be made into an object
|
||||
--> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33
|
||||
|
|
||||
LL | let t_box: Box<dyn Trait> = Box::new(S);
|
||||
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Trait>>` for `std::boxed::Box<S>`
|
||||
= note: required by cast to type `std::boxed::Box<dyn Trait>`
|
||||
|
||||
error[E0038]: the trait `Trait` cannot be made into an object
|
||||
--> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15
|
||||
|
|
||||
LL | takes_box(Box::new(S));
|
||||
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Trait>>` for `std::boxed::Box<S>`
|
||||
= note: required by cast to type `std::boxed::Box<(dyn Trait + 'static)>`
|
||||
|
||||
error[E0038]: the trait `Trait` cannot be made into an object
|
||||
--> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5
|
||||
|
|
||||
LL | Box::new(S) as Box<dyn Trait>;
|
||||
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Trait>>` for `std::boxed::Box<S>`
|
||||
= note: required by cast to type `std::boxed::Box<dyn Trait>`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
18
src/test/ui/wf/wf-convert-unsafe-trait-obj.rs
Normal file
18
src/test/ui/wf/wf-convert-unsafe-trait-obj.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Check that we do not allow casts or coercions
|
||||
// to object unsafe trait objects by ref
|
||||
|
||||
#![feature(object_safe_for_dispatch)]
|
||||
|
||||
trait Trait: Sized {}
|
||||
|
||||
struct S;
|
||||
|
||||
impl Trait for S {}
|
||||
|
||||
fn takes_trait(t: &dyn Trait) {}
|
||||
|
||||
fn main() {
|
||||
&S as &dyn Trait; //~ ERROR E0038
|
||||
let t: &dyn Trait = &S; //~ ERROR E0038
|
||||
takes_trait(&S); //~ ERROR E0038
|
||||
}
|
33
src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
Normal file
33
src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
Normal file
@ -0,0 +1,33 @@
|
||||
error[E0038]: the trait `Trait` cannot be made into an object
|
||||
--> $DIR/wf-convert-unsafe-trait-obj.rs:16:25
|
||||
|
|
||||
LL | let t: &dyn Trait = &S;
|
||||
| ^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
error[E0038]: the trait `Trait` cannot be made into an object
|
||||
--> $DIR/wf-convert-unsafe-trait-obj.rs:17:17
|
||||
|
|
||||
LL | takes_trait(&S);
|
||||
| ^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
error[E0038]: the trait `Trait` cannot be made into an object
|
||||
--> $DIR/wf-convert-unsafe-trait-obj.rs:15:5
|
||||
|
|
||||
LL | &S as &dyn Trait;
|
||||
| ^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
29
src/test/ui/wf/wf-unsafe-trait-obj-match.rs
Normal file
29
src/test/ui/wf/wf-unsafe-trait-obj-match.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// Check that we do not allow coercions to object
|
||||
// unsafe trait objects in match arms
|
||||
|
||||
#![feature(object_safe_for_dispatch)]
|
||||
|
||||
trait Trait: Sized {}
|
||||
|
||||
struct S;
|
||||
|
||||
impl Trait for S {}
|
||||
|
||||
struct R;
|
||||
|
||||
impl Trait for R {}
|
||||
|
||||
fn opt() -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match opt() {
|
||||
Some(()) => &S,
|
||||
None => &R, //~ ERROR E0308
|
||||
}
|
||||
let t: &dyn Trait = match opt() { //~ ERROR E0038
|
||||
Some(()) => &S, //~ ERROR E0038
|
||||
None => &R,
|
||||
};
|
||||
}
|
38
src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
Normal file
38
src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
Normal file
@ -0,0 +1,38 @@
|
||||
error[E0308]: match arms have incompatible types
|
||||
--> $DIR/wf-unsafe-trait-obj-match.rs:23:17
|
||||
|
|
||||
LL | / match opt() {
|
||||
LL | | Some(()) => &S,
|
||||
| | -- this is found to be of type `&S`
|
||||
LL | | None => &R,
|
||||
| | ^^ expected struct `S`, found struct `R`
|
||||
LL | | }
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected type `&S`
|
||||
found type `&R`
|
||||
|
||||
error[E0038]: the trait `Trait` cannot be made into an object
|
||||
--> $DIR/wf-unsafe-trait-obj-match.rs:26:21
|
||||
|
|
||||
LL | Some(()) => &S,
|
||||
| ^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
error[E0038]: the trait `Trait` cannot be made into an object
|
||||
--> $DIR/wf-unsafe-trait-obj-match.rs:25:25
|
||||
|
|
||||
LL | let t: &dyn Trait = match opt() {
|
||||
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&R`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0038, E0308.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
Loading…
x
Reference in New Issue
Block a user