Skip to content

Commit 4a8c5b2

Browse files
committed
Auto merge of #57545 - bovinebuddha:object_safe_for_dispatch, r=nikomatsakis
Object safe for dispatch cc #43561
2 parents f466f52 + ef5acde commit 4a8c5b2

File tree

58 files changed

+847
-89
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+847
-89
lines changed

src/librustc/infer/error_reporting/mod.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -1146,10 +1146,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11461146

11471147
let span = cause.span(self.tcx);
11481148

1149-
diag.span_label(span, terr.to_string());
1150-
if let Some((sp, msg)) = secondary_span {
1151-
diag.span_label(sp, msg);
1152-
}
1149+
// Ignore msg for object safe coercion
1150+
// since E0038 message will be printed
1151+
match terr {
1152+
TypeError::ObjectUnsafeCoercion(_) => {}
1153+
_ => {
1154+
diag.span_label(span, terr.to_string());
1155+
if let Some((sp, msg)) = secondary_span {
1156+
diag.span_label(sp, msg);
1157+
}
1158+
}
1159+
};
11531160

11541161
if let Some((expected, found)) = expected_found {
11551162
match (terr, is_simple_error, expected == found) {
@@ -1169,6 +1176,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11691176
&sort_string(values.found),
11701177
);
11711178
}
1179+
(TypeError::ObjectUnsafeCoercion(_), ..) => {
1180+
diag.note_unsuccessfull_coercion(found, expected);
1181+
}
11721182
(_, false, _) => {
11731183
if let Some(exp_found) = exp_found {
11741184
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
@@ -1267,6 +1277,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12671277
let span = trace.cause.span(self.tcx);
12681278
let failure_code = trace.cause.as_failure_code(terr);
12691279
let mut diag = match failure_code {
1280+
FailureCode::Error0038(did) => {
1281+
let violations = self.tcx.object_safety_violations(did);
1282+
self.tcx.report_object_safety_error(span, did, violations)
1283+
}
12701284
FailureCode::Error0317(failure_str) => {
12711285
struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
12721286
}
@@ -1628,6 +1642,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16281642
}
16291643

16301644
enum FailureCode {
1645+
Error0038(DefId),
16311646
Error0317(&'static str),
16321647
Error0580(&'static str),
16331648
Error0308(&'static str),
@@ -1666,6 +1681,7 @@ impl<'tcx> ObligationCause<'tcx> {
16661681
TypeError::IntrinsicCast => {
16671682
Error0308("cannot coerce intrinsics to function pointers")
16681683
}
1684+
TypeError::ObjectUnsafeCoercion(did) => Error0038(did.clone()),
16691685
_ => Error0308("mismatched types"),
16701686
},
16711687
}

src/librustc/traits/error_reporting.rs

+15-17
Original file line numberDiff line numberDiff line change
@@ -793,15 +793,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
793793

794794
ty::Predicate::ObjectSafe(trait_def_id) => {
795795
let violations = self.tcx.object_safety_violations(trait_def_id);
796-
if let Some(err) = self.tcx.report_object_safety_error(
796+
self.tcx.report_object_safety_error(
797797
span,
798798
trait_def_id,
799799
violations,
800-
) {
801-
err
802-
} else {
803-
return;
804-
}
800+
)
805801
}
806802

807803
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
@@ -937,11 +933,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
937933

938934
TraitNotObjectSafe(did) => {
939935
let violations = self.tcx.object_safety_violations(did);
940-
if let Some(err) = self.tcx.report_object_safety_error(span, did, violations) {
941-
err
942-
} else {
943-
return;
944-
}
936+
self.tcx.report_object_safety_error(span, did, violations)
945937
}
946938

947939
// already reported in the query
@@ -1665,11 +1657,7 @@ impl<'tcx> TyCtxt<'tcx> {
16651657
span: Span,
16661658
trait_def_id: DefId,
16671659
violations: Vec<ObjectSafetyViolation>,
1668-
) -> Option<DiagnosticBuilder<'tcx>> {
1669-
if self.sess.trait_methods_not_found.borrow().contains(&span) {
1670-
// Avoid emitting error caused by non-existing method (#58734)
1671-
return None;
1672-
}
1660+
) -> DiagnosticBuilder<'tcx> {
16731661
let trait_str = self.def_path_str(trait_def_id);
16741662
let span = self.sess.source_map().def_span(span);
16751663
let mut err = struct_span_err!(
@@ -1687,7 +1675,13 @@ impl<'tcx> TyCtxt<'tcx> {
16871675
};
16881676
}
16891677
}
1690-
Some(err)
1678+
1679+
if self.sess.trait_methods_not_found.borrow().contains(&span) {
1680+
// Avoid emitting error caused by non-existing method (#58734)
1681+
err.cancel();
1682+
}
1683+
1684+
err
16911685
}
16921686
}
16931687

@@ -2098,6 +2092,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
20982092
err.note(&format!("required for the cast to the object type `{}`",
20992093
self.ty_to_string(object_ty)));
21002094
}
2095+
ObligationCauseCode::Coercion { source: _, target } => {
2096+
err.note(&format!("required by cast to type `{}`",
2097+
self.ty_to_string(target)));
2098+
}
21012099
ObligationCauseCode::RepeatVec => {
21022100
err.note("the `Copy` trait is required because the \
21032101
repeated element will be copied");

src/librustc/traits/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ pub enum ObligationCauseCode<'tcx> {
188188
/// Obligation incurred due to an object cast.
189189
ObjectCastObligation(/* Object type */ Ty<'tcx>),
190190

191+
/// Obligation incurred due to a coercion.
192+
Coercion { source: Ty<'tcx>, target: Ty<'tcx> },
193+
191194
// Various cases where expressions must be sized/copy/etc:
192195
/// L = X implies that L is Sized
193196
AssignmentLhsSized,

src/librustc/traits/select.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -2246,7 +2246,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
22462246
}
22472247

22482248
if let Some(principal) = data.principal() {
2249-
principal.with_self_ty(self.tcx(), self_ty)
2249+
if !self.infcx.tcx.features().object_safe_for_dispatch {
2250+
principal.with_self_ty(self.tcx(), self_ty)
2251+
} else if self.tcx().is_object_safe(principal.def_id()) {
2252+
principal.with_self_ty(self.tcx(), self_ty)
2253+
} else {
2254+
return;
2255+
}
22502256
} else {
22512257
// Only auto-trait bounds exist.
22522258
return;

src/librustc/traits/structural_impls.rs

+4
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,10 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
481481
.and_then(|r| Some(super::ObjectTypeBound(ty, r)))
482482
),
483483
super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
484+
super::Coercion { source, target } => Some(super::Coercion {
485+
source: tcx.lift(&source)?,
486+
target: tcx.lift(&target)?,
487+
}),
484488
super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
485489
super::TupleInitializerSized => Some(super::TupleInitializerSized),
486490
super::StructInitializerSized => Some(super::StructInitializerSized),

src/librustc/ty/error.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub enum TypeError<'tcx> {
4545
ProjectionMismatched(ExpectedFound<DefId>),
4646
ProjectionBoundsLength(ExpectedFound<usize>),
4747
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
48-
48+
ObjectUnsafeCoercion(DefId),
4949
ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
5050

5151
IntrinsicCast,
@@ -178,6 +178,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
178178
IntrinsicCast => {
179179
write!(f, "cannot coerce intrinsics to function pointers")
180180
}
181+
ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"),
181182
}
182183
}
183184
}

src/librustc/ty/structural_impls.rs

+2
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
749749
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
750750
ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
751751
IntrinsicCast => IntrinsicCast,
752+
ObjectUnsafeCoercion(ref x) => return tcx.lift(x).map(ObjectUnsafeCoercion),
752753
})
753754
}
754755
}
@@ -1350,6 +1351,7 @@ EnumTypeFoldableImpl! {
13501351
(ty::error::TypeError::ExistentialMismatch)(x),
13511352
(ty::error::TypeError::ConstMismatch)(x),
13521353
(ty::error::TypeError::IntrinsicCast),
1354+
(ty::error::TypeError::ObjectUnsafeCoercion)(x),
13531355
}
13541356
}
13551357

src/librustc/ty/wf.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -380,16 +380,21 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
380380
// obligations that don't refer to Self and
381381
// checking those
382382

383-
let cause = self.cause(traits::MiscObligation);
384-
let component_traits =
385-
data.auto_traits().chain(data.principal_def_id());
386-
self.out.extend(
387-
component_traits.map(|did| traits::Obligation::new(
388-
cause.clone(),
389-
param_env,
390-
ty::Predicate::ObjectSafe(did)
391-
))
392-
);
383+
let defer_to_coercion =
384+
self.infcx.tcx.features().object_safe_for_dispatch;
385+
386+
if !defer_to_coercion {
387+
let cause = self.cause(traits::MiscObligation);
388+
let component_traits =
389+
data.auto_traits().chain(data.principal_def_id());
390+
self.out.extend(
391+
component_traits.map(|did| traits::Obligation::new(
392+
cause.clone(),
393+
param_env,
394+
ty::Predicate::ObjectSafe(did)
395+
))
396+
);
397+
}
393398
}
394399

395400
// Inference variables are the complicated case, since we don't

src/librustc_errors/diagnostic.rs

+26
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,32 @@ impl Diagnostic {
152152
self.note_expected_found_extra(label, expected, found, &"", &"")
153153
}
154154

155+
pub fn note_unsuccessfull_coercion(&mut self,
156+
expected: DiagnosticStyledString,
157+
found: DiagnosticStyledString)
158+
-> &mut Self
159+
{
160+
let mut msg: Vec<_> =
161+
vec![(format!("required when trying to coerce from type `"),
162+
Style::NoStyle)];
163+
msg.extend(expected.0.iter()
164+
.map(|x| match *x {
165+
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
166+
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
167+
}));
168+
msg.push((format!("` to type '"), Style::NoStyle));
169+
msg.extend(found.0.iter()
170+
.map(|x| match *x {
171+
StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
172+
StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
173+
}));
174+
msg.push((format!("`"), Style::NoStyle));
175+
176+
// For now, just attach these as notes
177+
self.highlighted_note(msg);
178+
self
179+
}
180+
155181
pub fn note_expected_found_extra(&mut self,
156182
label: &dyn fmt::Display,
157183
expected: DiagnosticStyledString,

src/librustc_errors/diagnostic_builder.rs

+5
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,11 @@ impl<'a> DiagnosticBuilder<'a> {
209209
found_extra: &dyn fmt::Display,
210210
) -> &mut Self);
211211

212+
forward!(pub fn note_unsuccessfull_coercion(&mut self,
213+
expected: DiagnosticStyledString,
214+
found: DiagnosticStyledString,
215+
) -> &mut Self);
216+
212217
forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
213218
forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
214219
sp: S,

src/librustc_typeck/astconv.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1274,8 +1274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12741274
span,
12751275
item.trait_ref().def_id(),
12761276
object_safety_violations
1277-
)
1278-
.map(|mut err| err.emit());
1277+
).emit();
12791278
return tcx.types.err;
12801279
}
12811280
}

src/librustc_typeck/check/cast.rs

+32-11
Original file line numberDiff line numberDiff line change
@@ -428,21 +428,36 @@ impl<'a, 'tcx> CastCheck<'tcx> {
428428
self.report_cast_to_unsized_type(fcx);
429429
} else if self.expr_ty.references_error() || self.cast_ty.references_error() {
430430
// No sense in giving duplicate error messages
431-
} else if self.try_coercion_cast(fcx) {
432-
self.trivial_cast_lint(fcx);
433-
debug!(" -> CoercionCast");
434-
fcx.tables.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id);
435-
436431
} else {
437-
match self.do_check(fcx) {
438-
Ok(k) => {
439-
debug!(" -> {:?}", k);
432+
match self.try_coercion_cast(fcx) {
433+
Ok(()) => {
434+
self.trivial_cast_lint(fcx);
435+
debug!(" -> CoercionCast");
436+
fcx.tables.borrow_mut()
437+
.set_coercion_cast(self.expr.hir_id.local_id);
438+
}
439+
Err(ty::error::TypeError::ObjectUnsafeCoercion(did)) => {
440+
self.report_object_unsafe_cast(&fcx, did);
441+
}
442+
Err(_) => {
443+
match self.do_check(fcx) {
444+
Ok(k) => {
445+
debug!(" -> {:?}", k);
446+
}
447+
Err(e) => self.report_cast_error(fcx, e),
448+
};
440449
}
441-
Err(e) => self.report_cast_error(fcx, e),
442450
};
443451
}
444452
}
445453

454+
fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) {
455+
let violations = fcx.tcx.object_safety_violations(did);
456+
let mut err = fcx.tcx.report_object_safety_error(self.cast_span, did, violations);
457+
err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty)));
458+
err.emit();
459+
}
460+
446461
/// Checks a cast, and report an error if one exists. In some cases, this
447462
/// can return Ok and create type errors in the fcx rather than returning
448463
/// directly. coercion-cast is handled in check instead of here.
@@ -646,8 +661,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
646661
}
647662
}
648663

649-
fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> bool {
650-
fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No).is_ok()
664+
fn try_coercion_cast(
665+
&self,
666+
fcx: &FnCtxt<'a, 'tcx>,
667+
) -> Result<(), ty::error::TypeError<'_>> {
668+
match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) {
669+
Ok(_) => Ok(()),
670+
Err(err) => Err(err),
671+
}
651672
}
652673
}
653674

0 commit comments

Comments
 (0)