RFC 2027: "first draft" of implementation
These are a squashed series of commits.
This commit is contained in:
parent
d28a9c38fe
commit
ef5acdeceb
59 changed files with 847 additions and 105 deletions
|
@ -1146,10 +1146,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
let span = cause.span(self.tcx);
|
let span = cause.span(self.tcx);
|
||||||
|
|
||||||
diag.span_label(span, terr.to_string());
|
// Ignore msg for object safe coercion
|
||||||
if let Some((sp, msg)) = secondary_span {
|
// since E0038 message will be printed
|
||||||
diag.span_label(sp, msg);
|
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 {
|
if let Some((expected, found)) = expected_found {
|
||||||
match (terr, is_simple_error, expected == found) {
|
match (terr, is_simple_error, expected == found) {
|
||||||
|
@ -1169,6 +1176,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
&sort_string(values.found),
|
&sort_string(values.found),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
(TypeError::ObjectUnsafeCoercion(_), ..) => {
|
||||||
|
diag.note_unsuccessfull_coercion(found, expected);
|
||||||
|
}
|
||||||
(_, false, _) => {
|
(_, false, _) => {
|
||||||
if let Some(exp_found) = exp_found {
|
if let Some(exp_found) = exp_found {
|
||||||
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
|
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 span = trace.cause.span(self.tcx);
|
||||||
let failure_code = trace.cause.as_failure_code(terr);
|
let failure_code = trace.cause.as_failure_code(terr);
|
||||||
let mut diag = match failure_code {
|
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) => {
|
FailureCode::Error0317(failure_str) => {
|
||||||
struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
|
struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
|
||||||
}
|
}
|
||||||
|
@ -1628,6 +1642,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FailureCode {
|
enum FailureCode {
|
||||||
|
Error0038(DefId),
|
||||||
Error0317(&'static str),
|
Error0317(&'static str),
|
||||||
Error0580(&'static str),
|
Error0580(&'static str),
|
||||||
Error0308(&'static str),
|
Error0308(&'static str),
|
||||||
|
@ -1666,6 +1681,7 @@ impl<'tcx> ObligationCause<'tcx> {
|
||||||
TypeError::IntrinsicCast => {
|
TypeError::IntrinsicCast => {
|
||||||
Error0308("cannot coerce intrinsics to function pointers")
|
Error0308("cannot coerce intrinsics to function pointers")
|
||||||
}
|
}
|
||||||
|
TypeError::ObjectUnsafeCoercion(did) => Error0038(did.clone()),
|
||||||
_ => Error0308("mismatched types"),
|
_ => Error0308("mismatched types"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -790,15 +790,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
ty::Predicate::ObjectSafe(trait_def_id) => {
|
ty::Predicate::ObjectSafe(trait_def_id) => {
|
||||||
let violations = self.tcx.object_safety_violations(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,
|
span,
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
violations,
|
violations,
|
||||||
) {
|
)
|
||||||
err
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
|
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
|
||||||
|
@ -934,11 +930,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
TraitNotObjectSafe(did) => {
|
TraitNotObjectSafe(did) => {
|
||||||
let violations = self.tcx.object_safety_violations(did);
|
let violations = self.tcx.object_safety_violations(did);
|
||||||
if let Some(err) = self.tcx.report_object_safety_error(span, did, violations) {
|
self.tcx.report_object_safety_error(span, did, violations)
|
||||||
err
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// already reported in the query
|
// already reported in the query
|
||||||
|
@ -1493,11 +1485,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
violations: Vec<ObjectSafetyViolation>,
|
violations: Vec<ObjectSafetyViolation>,
|
||||||
) -> Option<DiagnosticBuilder<'tcx>> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
if self.sess.trait_methods_not_found.borrow().contains(&span) {
|
|
||||||
// Avoid emitting error caused by non-existing method (#58734)
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let trait_str = self.def_path_str(trait_def_id);
|
let trait_str = self.def_path_str(trait_def_id);
|
||||||
let span = self.sess.source_map().def_span(span);
|
let span = self.sess.source_map().def_span(span);
|
||||||
let mut err = struct_span_err!(
|
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 `{}`",
|
err.note(&format!("required for the cast to the object type `{}`",
|
||||||
self.ty_to_string(object_ty)));
|
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 => {
|
ObligationCauseCode::RepeatVec => {
|
||||||
err.note("the `Copy` trait is required because the \
|
err.note("the `Copy` trait is required because the \
|
||||||
repeated element will be copied");
|
repeated element will be copied");
|
||||||
|
|
|
@ -188,6 +188,9 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
/// Obligation incurred due to an object cast.
|
/// Obligation incurred due to an object cast.
|
||||||
ObjectCastObligation(/* Object type */ Ty<'tcx>),
|
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:
|
// Various cases where expressions must be sized/copy/etc:
|
||||||
/// L = X implies that L is Sized
|
/// L = X implies that L is Sized
|
||||||
AssignmentLhsSized,
|
AssignmentLhsSized,
|
||||||
|
|
|
@ -2246,7 +2246,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(principal) = data.principal() {
|
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 {
|
} else {
|
||||||
// Only auto-trait bounds exist.
|
// Only auto-trait bounds exist.
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -481,6 +481,10 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
||||||
.and_then(|r| Some(super::ObjectTypeBound(ty, r)))
|
.and_then(|r| Some(super::ObjectTypeBound(ty, r)))
|
||||||
),
|
),
|
||||||
super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
|
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::AssignmentLhsSized => Some(super::AssignmentLhsSized),
|
||||||
super::TupleInitializerSized => Some(super::TupleInitializerSized),
|
super::TupleInitializerSized => Some(super::TupleInitializerSized),
|
||||||
super::StructInitializerSized => Some(super::StructInitializerSized),
|
super::StructInitializerSized => Some(super::StructInitializerSized),
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub enum TypeError<'tcx> {
|
||||||
ProjectionMismatched(ExpectedFound<DefId>),
|
ProjectionMismatched(ExpectedFound<DefId>),
|
||||||
ProjectionBoundsLength(ExpectedFound<usize>),
|
ProjectionBoundsLength(ExpectedFound<usize>),
|
||||||
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
|
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
|
||||||
|
ObjectUnsafeCoercion(DefId),
|
||||||
ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
|
ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
|
||||||
|
|
||||||
IntrinsicCast,
|
IntrinsicCast,
|
||||||
|
@ -179,6 +179,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
||||||
IntrinsicCast => {
|
IntrinsicCast => {
|
||||||
write!(f, "cannot coerce intrinsics to function pointers")
|
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),
|
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
|
||||||
ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
|
ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
|
||||||
IntrinsicCast => IntrinsicCast,
|
IntrinsicCast => IntrinsicCast,
|
||||||
|
ObjectUnsafeCoercion(ref x) => return tcx.lift(x).map(ObjectUnsafeCoercion),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1356,6 +1357,7 @@ EnumTypeFoldableImpl! {
|
||||||
(ty::error::TypeError::ExistentialMismatch)(x),
|
(ty::error::TypeError::ExistentialMismatch)(x),
|
||||||
(ty::error::TypeError::ConstMismatch)(x),
|
(ty::error::TypeError::ConstMismatch)(x),
|
||||||
(ty::error::TypeError::IntrinsicCast),
|
(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
|
// obligations that don't refer to Self and
|
||||||
// checking those
|
// checking those
|
||||||
|
|
||||||
let cause = self.cause(traits::MiscObligation);
|
let defer_to_coercion =
|
||||||
let component_traits =
|
self.infcx.tcx.features().object_safe_for_dispatch;
|
||||||
data.auto_traits().chain(data.principal_def_id());
|
|
||||||
self.out.extend(
|
if !defer_to_coercion {
|
||||||
component_traits.map(|did| traits::Obligation::new(
|
let cause = self.cause(traits::MiscObligation);
|
||||||
cause.clone(),
|
let component_traits =
|
||||||
param_env,
|
data.auto_traits().chain(data.principal_def_id());
|
||||||
ty::Predicate::ObjectSafe(did)
|
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
|
// Inference variables are the complicated case, since we don't
|
||||||
|
|
|
@ -152,6 +152,32 @@ impl Diagnostic {
|
||||||
self.note_expected_found_extra(label, expected, found, &"", &"")
|
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,
|
pub fn note_expected_found_extra(&mut self,
|
||||||
label: &dyn fmt::Display,
|
label: &dyn fmt::Display,
|
||||||
expected: DiagnosticStyledString,
|
expected: DiagnosticStyledString,
|
||||||
|
|
|
@ -209,6 +209,11 @@ impl<'a> DiagnosticBuilder<'a> {
|
||||||
found_extra: &dyn fmt::Display,
|
found_extra: &dyn fmt::Display,
|
||||||
) -> &mut Self);
|
) -> &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 note(&mut self, msg: &str) -> &mut Self);
|
||||||
forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
|
forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
|
||||||
sp: S,
|
sp: S,
|
||||||
|
|
|
@ -1275,8 +1275,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
span,
|
span,
|
||||||
item.trait_ref().def_id(),
|
item.trait_ref().def_id(),
|
||||||
object_safety_violations
|
object_safety_violations
|
||||||
)
|
).emit();
|
||||||
.map(|mut err| err.emit());
|
|
||||||
return tcx.types.err;
|
return tcx.types.err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,21 +428,36 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
self.report_cast_to_unsized_type(fcx);
|
self.report_cast_to_unsized_type(fcx);
|
||||||
} else if self.expr_ty.references_error() || self.cast_ty.references_error() {
|
} else if self.expr_ty.references_error() || self.cast_ty.references_error() {
|
||||||
// No sense in giving duplicate error messages
|
// 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 {
|
} else {
|
||||||
match self.do_check(fcx) {
|
match self.try_coercion_cast(fcx) {
|
||||||
Ok(k) => {
|
Ok(()) => {
|
||||||
debug!(" -> {:?}", k);
|
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
|
/// 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
|
/// can return Ok and create type errors in the fcx rather than returning
|
||||||
/// directly. coercion-cast is handled in check instead of here.
|
/// 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 {
|
fn try_coercion_cast(
|
||||||
fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No).is_ok()
|
&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::{
|
use rustc::ty::adjustment::{
|
||||||
Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast
|
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::fold::TypeFoldable;
|
||||||
use rustc::ty::error::TypeError;
|
use rustc::ty::error::TypeError;
|
||||||
use rustc::ty::relate::RelateResult;
|
use rustc::ty::relate::RelateResult;
|
||||||
|
use rustc::ty::subst::SubstsRef;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use syntax::feature_gate;
|
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
|
// a "spurious" type variable, and we don't want to have that
|
||||||
// type variable in memory if the coercion fails.
|
// type variable in memory if the coercion fails.
|
||||||
let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b));
|
let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b));
|
||||||
if unsize.is_ok() {
|
match unsize {
|
||||||
debug!("coerce: unsize successful");
|
Ok(_) => {
|
||||||
return unsize;
|
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");
|
debug!("coerce: unsize failed");
|
||||||
|
|
||||||
|
@ -539,7 +547,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
let mut selcx = traits::SelectionContext::new(self);
|
let mut selcx = traits::SelectionContext::new(self);
|
||||||
|
|
||||||
// Create an obligation for `Source: CoerceUnsized<Target>`.
|
// 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.
|
// Use a FIFO queue for this custom fulfillment procedure.
|
||||||
//
|
//
|
||||||
|
@ -566,14 +578,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
let obligation = queue.remove(0);
|
let obligation = queue.remove(0);
|
||||||
debug!("coerce_unsized resolve step: {:?}", obligation);
|
debug!("coerce_unsized resolve step: {:?}", obligation);
|
||||||
let trait_ref = match obligation.predicate {
|
let trait_ref = match obligation.predicate {
|
||||||
ty::Predicate::Trait(ref t) if traits.contains(&t.def_id()) => {
|
ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
|
||||||
if unsize_did == t.def_id() {
|
if unsize_did == tr.def_id() {
|
||||||
if let ty::Tuple(..) = &t.skip_binder().input_types().nth(1).unwrap().kind {
|
let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind;
|
||||||
|
if let ty::Tuple(..) = sty {
|
||||||
debug!("coerce_unsized: found unsized tuple coercion");
|
debug!("coerce_unsized: found unsized tuple coercion");
|
||||||
has_unsized_tuple_coercion = true;
|
has_unsized_tuple_coercion = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.clone()
|
tr.clone()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
coercion.obligations.push(obligation);
|
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 {
|
for component_def_id in component_def_ids {
|
||||||
if !tcx.is_object_safe(component_def_id) {
|
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`.
|
// 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 {
|
} else {
|
||||||
let mut supertrait_def_ids =
|
let mut supertrait_def_ids =
|
||||||
traits::supertrait_def_ids(tcx, component_def_id);
|
traits::supertrait_def_ids(tcx, component_def_id);
|
||||||
|
|
|
@ -528,6 +528,9 @@ declare_features! (
|
||||||
/// Enable accurate caller location reporting during panic (RFC 2091).
|
/// Enable accurate caller location reporting during panic (RFC 2091).
|
||||||
(active, track_caller, "1.40.0", Some(47809), None),
|
(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
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
@ -459,6 +459,7 @@ symbols! {
|
||||||
no_std,
|
no_std,
|
||||||
not,
|
not,
|
||||||
note,
|
note,
|
||||||
|
object_safe_for_dispatch,
|
||||||
Ok,
|
Ok,
|
||||||
omit_gdb_pretty_printer_section,
|
omit_gdb_pretty_printer_section,
|
||||||
on,
|
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
|
| ^^^^^^^^^^ 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 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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ LL | let _ = x
|
||||||
|
|
|
|
||||||
= note: the trait cannot require that `Self : Sized`
|
= 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 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
|
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: 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 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
|
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
|
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) { }
|
LL | fn take_param<T:Foo>(foo: &T) { }
|
||||||
| ---------- --- required by this bound in `take_param`
|
| ---------- --- 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}>`
|
= 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
|
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;
|
LL | let z = &x as &dyn Foo;
|
||||||
| ^^^^^^^^ the trait `Foo` cannot be made into an object
|
| ^^^^^^^^ 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`
|
= note: the trait cannot require that `Self : Sized`
|
||||||
|
|
||||||
error[E0038]: the trait `Foo` cannot be made into an object
|
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;
|
LL | let z = &x as &dyn Foo;
|
||||||
| ^^ the trait `Foo` cannot be made into an object
|
| ^^ the trait `Foo` cannot be made into an object
|
||||||
|
|
|
|
||||||
= note: the trait cannot require that `Self : Sized`
|
= 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 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
|
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.
|
// 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)]
|
#![feature(box_syntax)]
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
@ -15,15 +18,17 @@ fn take_param<T:Foo>(foo: &T) { }
|
||||||
|
|
||||||
fn a() {
|
fn a() {
|
||||||
let x: Box<_> = box 3;
|
let x: Box<_> = box 3;
|
||||||
take_param(&x); //~ ERROR E0277
|
take_param(&x); //[curr]~ ERROR E0277
|
||||||
|
//[object_safe_for_dispatch]~^ ERROR E0277
|
||||||
}
|
}
|
||||||
|
|
||||||
fn b() {
|
fn b() {
|
||||||
let x: Box<_> = box 3;
|
let x: Box<_> = box 3;
|
||||||
let y = &x;
|
let y = &x;
|
||||||
let z = &x as &dyn Foo;
|
let z = &x as &dyn Foo;
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
//~| ERROR E0038
|
//[curr]~| ERROR E0038
|
||||||
|
//[object_safe_for_dispatch]~^^^ ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0038]: the trait `Bar` cannot be made into an object
|
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;
|
LL | const X: usize;
|
||||||
| - the trait cannot contain associated consts like `X`
|
| - 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
|
// Check that we correctly prevent users from making trait objects
|
||||||
// from traits with associated consts.
|
// from traits with associated consts.
|
||||||
|
//
|
||||||
|
// revisions: curr object_safe_for_dispatch
|
||||||
|
|
||||||
|
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||||
|
|
||||||
trait Bar {
|
trait Bar {
|
||||||
const X: usize;
|
const X: usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
t
|
t
|
||||||
|
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0038]: 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:14:1
|
--> $DIR/object-safety-generics.rs:18:1
|
||||||
|
|
|
|
||||||
LL | fn bar<T>(&self, t: T);
|
LL | fn bar<T>(&self, t: T);
|
||||||
| --- method `bar` has generic type parameters
|
| --- 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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
||||||
|
|
||||||
error[E0038]: 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);
|
LL | fn bar<T>(&self, t: T);
|
||||||
| --- method `bar` has generic type parameters
|
| --- 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
|
// Check that we correctly prevent users from making trait objects
|
||||||
// from traits with generic methods, unless `where Self : Sized` is
|
// from traits with generic methods, unless `where Self : Sized` is
|
||||||
// present.
|
// present.
|
||||||
|
// revisions: curr object_safe_for_dispatch
|
||||||
|
|
||||||
|
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||||
|
|
||||||
|
|
||||||
trait Bar {
|
trait Bar {
|
||||||
fn bar<T>(&self, t: T);
|
fn bar<T>(&self, t: T);
|
||||||
|
@ -12,13 +16,15 @@ trait Quux {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
t
|
t
|
||||||
|
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
|
fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
t as &dyn Bar
|
t as &dyn Bar
|
||||||
|
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
|
fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0038]: the trait `Bar` cannot be made into an object
|
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);
|
LL | fn bar(&self, x: &Self);
|
||||||
| --- method `bar` references the `Self` type in its parameters or return type
|
| --- 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
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
||||||
|
|
||||||
error[E0038]: the trait `Baz` 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;
|
LL | fn baz(&self) -> Self;
|
||||||
| --- method `bar` references the `Self` type in its parameters or return type
|
| --- method `baz` references the `Self` type in its parameters or return type
|
||||||
...
|
...
|
||||||
LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
|
LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
// Check that we correctly prevent users from making trait objects
|
||||||
// form traits that make use of `Self` in an argument or return
|
// form traits that make use of `Self` in an argument or return
|
||||||
// position, unless `where Self : Sized` is present..
|
// 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 {
|
trait Bar {
|
||||||
fn bar(&self, x: &Self);
|
fn bar(&self, x: &Self);
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Baz {
|
trait Baz {
|
||||||
fn bar(&self) -> Self;
|
fn baz(&self) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Quux {
|
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 {
|
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
loop { }
|
t
|
||||||
|
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
|
fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
t
|
t
|
||||||
|
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_quux<T:Quux>(t: &T) -> &dyn Quux {
|
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
|
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
|
// Check that we correctly prevent users from making trait objects
|
||||||
// from traits with static methods.
|
// from traits with static methods.
|
||||||
|
//
|
||||||
|
// revisions: curr object_safe_for_dispatch
|
||||||
|
|
||||||
|
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
fn foo();
|
fn foo() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<dyn Foo + 'static> {
|
fn diverges() -> Box<dyn Foo> {
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
loop { }
|
loop { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Bar;
|
||||||
|
|
||||||
|
impl Foo for Bar {}
|
||||||
|
|
||||||
fn main() {
|
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
|
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 {
|
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
// Check that we correctly prevent users from making trait objects
|
||||||
// from traits where `Self : Sized`.
|
// from traits where `Self : Sized`.
|
||||||
|
//
|
||||||
|
// revisions: curr object_safe_for_dispatch
|
||||||
|
|
||||||
|
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
|
||||||
|
|
||||||
trait Bar
|
trait Bar
|
||||||
where Self : Sized
|
where Self : Sized
|
||||||
|
@ -8,8 +12,9 @@ trait Bar
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
loop { }
|
t
|
||||||
|
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0038]: the trait `Bar` cannot be made into an object
|
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 {
|
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
// Check that we correctly prevent users from making trait objects
|
||||||
// from traits where `Self : Sized`.
|
// 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 {
|
trait Bar : Sized {
|
||||||
fn bar<T>(&self, t: T);
|
fn bar<T>(&self, t: T);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
t
|
t
|
||||||
|
//[object_safe_for_dispatch]~^ ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
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)]
|
#![feature(arbitrary_self_types)]
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -29,8 +32,9 @@ impl Bar for usize {
|
||||||
|
|
||||||
fn make_foo() {
|
fn make_foo() {
|
||||||
let x = Rc::new(5usize) as Rc<dyn Foo>;
|
let x = Rc::new(5usize) as Rc<dyn Foo>;
|
||||||
//~^ ERROR E0038
|
//[curr]~^ ERROR E0038
|
||||||
//~| ERROR E0038
|
//[curr]~| ERROR E0038
|
||||||
|
//[object_safe_for_dispatch]~^^^ ERROR E0038
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_bar() {
|
fn make_bar() {
|
||||||
|
|
|
@ -8,6 +8,7 @@ LL | let _: &dyn Tr = &St;
|
||||||
| ^^^ the trait `Tr` cannot be made into an object
|
| ^^^ 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 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
|
error[E0038]: the trait `Tr` cannot be made into an object
|
||||||
--> $DIR/trait-object-safety.rs:15:12
|
--> $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
|
| ^^^^^^ 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 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
|
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…
Add table
Add a link
Reference in a new issue