RFC 2027: "first draft" of implementation

These are a squashed series of commits.
This commit is contained in:
Mathias Blikstad 2019-01-08 22:14:04 +01:00 committed by Niko Matsakis
parent d28a9c38fe
commit ef5acdeceb
59 changed files with 847 additions and 105 deletions

View File

@ -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"),
},
}

View File

@ -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");

View File

@ -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,

View File

@ -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;

View File

@ -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),

View File

@ -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"),
}
}
}

View File

@ -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),
}
}

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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),
}
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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
// -------------------------------------------------------------------------

View File

@ -459,6 +459,7 @@ symbols! {
no_std,
not,
note,
object_safe_for_dispatch,
Ok,
omit_gdb_pretty_printer_section,
on,

View 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() {}

View File

@ -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`.

View File

@ -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`.

View File

@ -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() {}

View File

@ -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`.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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`.

View File

@ -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() { }

View File

@ -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`

View File

@ -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`.

View File

@ -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() {

View File

@ -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

View File

@ -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`.

View File

@ -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 {

View File

@ -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

View File

@ -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`.

View File

@ -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() {}

View File

@ -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`.

View File

@ -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`.

View File

@ -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
}

View File

@ -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

View File

@ -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`.

View File

@ -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() {

View File

@ -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

View File

@ -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`.

View File

@ -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() {

View File

@ -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() {}

View File

@ -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!();
}
}

View File

@ -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>()
}

View File

@ -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`.

View File

@ -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`.

View File

@ -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() {

View File

@ -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

View File

@ -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

View 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
}

View 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`.

View 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
}

View 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`.

View 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,
};
}

View 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`.