Skip to content

Commit 75296fc

Browse files
authored
Rollup merge of #130234 - lukas-code:ptr-cast-errors, r=WaffleLapkin
improve compile errors for invalid ptr-to-ptr casts with trait objects This is a follow-up to #120248 to improve some of its error messages. 1. Make the borrowcheck error for "type annotation requires that x must outlive y" actually point at the type annotation, i.e. the type `T` in a `x as T` cast. This makes the error more consistent with other errors caused by type annotation in other places, such as ```text error: lifetime may not live long enough --> src/lib.rs:4:12 | 3 | fn bar(a: &i32) { | - let's call the lifetime of this reference `'1` 4 | let b: &'static i32 = a; | ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` ``` 2. Don't say "cast" when we actually mean "coercion" and give borrowcheck errors from actual casts (which is currently just the check added in #120248) a higher priority than ones from coercions. This can improve the errors for ptr-to-ptr cast between trait objects because they are are lowered as an upcast "unsizing" coercion if possible (which may be the identity upcast) followed by the actual cast. 3. Bring back the old "casting X as Y is invalid" message for type mismatch in the principals and reword the "vtable kinds may not match" message to more accurately describe the pointer metadata and not refer to "vtables" if the metadata is unknown. fixes #130030 r? `@WaffleLapkin` but feel free to reassign
2 parents 363ae41 + b62e72c commit 75296fc

File tree

122 files changed

+552
-394
lines changed

Some content is hidden

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

122 files changed

+552
-394
lines changed

Diff for: compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,11 @@ impl<'tcx> BorrowExplanation<'tcx> {
333333
}
334334
}
335335

336-
if let ConstraintCategory::Cast { unsize_to: Some(unsize_ty) } = category {
336+
if let ConstraintCategory::Cast {
337+
is_implicit_coercion: true,
338+
unsize_to: Some(unsize_ty),
339+
} = category
340+
{
337341
self.add_object_lifetime_default_note(tcx, err, unsize_ty);
338342
}
339343
self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
@@ -740,7 +744,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
740744
// If we see an unsized cast, then if it is our data we should check
741745
// whether it is being cast to a trait object.
742746
Rvalue::Cast(
743-
CastKind::PointerCoercion(PointerCoercion::Unsize),
747+
CastKind::PointerCoercion(PointerCoercion::Unsize, _),
744748
operand,
745749
ty,
746750
) => {

Diff for: compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
4747
ConstraintCategory::Yield => "yielding this value ",
4848
ConstraintCategory::UseAsConst => "using this value as a constant ",
4949
ConstraintCategory::UseAsStatic => "using this value as a static ",
50-
ConstraintCategory::Cast { .. } => "cast ",
50+
ConstraintCategory::Cast { is_implicit_coercion: false, .. } => "cast ",
51+
ConstraintCategory::Cast { is_implicit_coercion: true, .. } => "coercion ",
5152
ConstraintCategory::CallArgument(_) => "argument ",
5253
ConstraintCategory::TypeAnnotation => "type annotation ",
5354
ConstraintCategory::ClosureBounds => "closure body ",

Diff for: compiler/rustc_borrowck/src/type_check/mod.rs

+44-27
Original file line numberDiff line numberDiff line change
@@ -1975,8 +1975,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
19751975
Rvalue::Cast(cast_kind, op, ty) => {
19761976
self.check_operand(op, location);
19771977

1978-
match cast_kind {
1979-
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
1978+
match *cast_kind {
1979+
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
1980+
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
19801981
let src_sig = op.ty(body, tcx).fn_sig(tcx);
19811982

19821983
// HACK: This shouldn't be necessary... We can remove this when we actually
@@ -2007,15 +2008,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20072008
self.prove_predicate(
20082009
ty::ClauseKind::WellFormed(src_ty.into()),
20092010
location.to_locations(),
2010-
ConstraintCategory::Cast { unsize_to: None },
2011+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
20112012
);
20122013

20132014
let src_ty = self.normalize(src_ty, location);
20142015
if let Err(terr) = self.sub_types(
20152016
src_ty,
20162017
*ty,
20172018
location.to_locations(),
2018-
ConstraintCategory::Cast { unsize_to: None },
2019+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
20192020
) {
20202021
span_mirbug!(
20212022
self,
@@ -2036,7 +2037,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20362037
self.prove_predicate(
20372038
ty::ClauseKind::WellFormed(src_ty.into()),
20382039
location.to_locations(),
2039-
ConstraintCategory::Cast { unsize_to: None },
2040+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
20402041
);
20412042

20422043
// The type that we see in the fcx is like
@@ -2049,7 +2050,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20492050
src_ty,
20502051
*ty,
20512052
location.to_locations(),
2052-
ConstraintCategory::Cast { unsize_to: None },
2053+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
20532054
) {
20542055
span_mirbug!(
20552056
self,
@@ -2062,19 +2063,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20622063
}
20632064
}
20642065

2065-
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(safety)) => {
2066+
CastKind::PointerCoercion(
2067+
PointerCoercion::ClosureFnPointer(safety),
2068+
coercion_source,
2069+
) => {
20662070
let sig = match op.ty(body, tcx).kind() {
20672071
ty::Closure(_, args) => args.as_closure().sig(),
20682072
_ => bug!(),
20692073
};
20702074
let ty_fn_ptr_from =
2071-
Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *safety));
2075+
Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, safety));
20722076

2077+
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
20732078
if let Err(terr) = self.sub_types(
20742079
ty_fn_ptr_from,
20752080
*ty,
20762081
location.to_locations(),
2077-
ConstraintCategory::Cast { unsize_to: None },
2082+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
20782083
) {
20792084
span_mirbug!(
20802085
self,
@@ -2087,7 +2092,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20872092
}
20882093
}
20892094

2090-
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
2095+
CastKind::PointerCoercion(
2096+
PointerCoercion::UnsafeFnPointer,
2097+
coercion_source,
2098+
) => {
20912099
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
20922100

20932101
// The type that we see in the fcx is like
@@ -2099,11 +2107,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20992107

21002108
let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
21012109

2110+
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
21022111
if let Err(terr) = self.sub_types(
21032112
ty_fn_ptr_from,
21042113
*ty,
21052114
location.to_locations(),
2106-
ConstraintCategory::Cast { unsize_to: None },
2115+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
21072116
) {
21082117
span_mirbug!(
21092118
self,
@@ -2116,30 +2125,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21162125
}
21172126
}
21182127

2119-
CastKind::PointerCoercion(PointerCoercion::Unsize) => {
2128+
CastKind::PointerCoercion(PointerCoercion::Unsize, coercion_source) => {
21202129
let &ty = ty;
21212130
let trait_ref = ty::TraitRef::new(
21222131
tcx,
21232132
tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)),
21242133
[op.ty(body, tcx), ty],
21252134
);
21262135

2136+
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
2137+
let unsize_to = tcx.fold_regions(ty, |r, _| {
2138+
if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r }
2139+
});
21272140
self.prove_trait_ref(
21282141
trait_ref,
21292142
location.to_locations(),
21302143
ConstraintCategory::Cast {
2131-
unsize_to: Some(tcx.fold_regions(ty, |r, _| {
2132-
if let ty::ReVar(_) = r.kind() {
2133-
tcx.lifetimes.re_erased
2134-
} else {
2135-
r
2136-
}
2137-
})),
2144+
is_implicit_coercion,
2145+
unsize_to: Some(unsize_to),
21382146
},
21392147
);
21402148
}
21412149

2142-
CastKind::DynStar => {
2150+
CastKind::PointerCoercion(PointerCoercion::DynStar, coercion_source) => {
21432151
// get the constraints from the target type (`dyn* Clone`)
21442152
//
21452153
// apply them to prove that the source type `Foo` implements `Clone` etc
@@ -2150,12 +2158,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21502158

21512159
let self_ty = op.ty(body, tcx);
21522160

2161+
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
21532162
self.prove_predicates(
21542163
existential_predicates
21552164
.iter()
21562165
.map(|predicate| predicate.with_self_ty(tcx, self_ty)),
21572166
location.to_locations(),
2158-
ConstraintCategory::Cast { unsize_to: None },
2167+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
21592168
);
21602169

21612170
let outlives_predicate = tcx.mk_predicate(Binder::dummy(
@@ -2166,11 +2175,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21662175
self.prove_predicate(
21672176
outlives_predicate,
21682177
location.to_locations(),
2169-
ConstraintCategory::Cast { unsize_to: None },
2178+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
21702179
);
21712180
}
21722181

2173-
CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
2182+
CastKind::PointerCoercion(
2183+
PointerCoercion::MutToConstPointer,
2184+
coercion_source,
2185+
) => {
21742186
let ty::RawPtr(ty_from, hir::Mutability::Mut) = op.ty(body, tcx).kind()
21752187
else {
21762188
span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
@@ -2180,11 +2192,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21802192
span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
21812193
return;
21822194
};
2195+
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
21832196
if let Err(terr) = self.sub_types(
21842197
*ty_from,
21852198
*ty_to,
21862199
location.to_locations(),
2187-
ConstraintCategory::Cast { unsize_to: None },
2200+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
21882201
) {
21892202
span_mirbug!(
21902203
self,
@@ -2197,7 +2210,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21972210
}
21982211
}
21992212

2200-
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
2213+
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => {
22012214
let ty_from = op.ty(body, tcx);
22022215

22032216
let opt_ty_elem_mut = match ty_from.kind() {
@@ -2242,11 +2255,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22422255
return;
22432256
}
22442257

2258+
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
22452259
if let Err(terr) = self.sub_types(
22462260
*ty_elem,
22472261
*ty_to,
22482262
location.to_locations(),
2249-
ConstraintCategory::Cast { unsize_to: None },
2263+
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
22502264
) {
22512265
span_mirbug!(
22522266
self,
@@ -2427,7 +2441,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
24272441
src_obj,
24282442
dst_obj,
24292443
location.to_locations(),
2430-
ConstraintCategory::Cast { unsize_to: None },
2444+
ConstraintCategory::Cast {
2445+
is_implicit_coercion: false,
2446+
unsize_to: None,
2447+
},
24312448
)
24322449
.unwrap();
24332450
}

Diff for: compiler/rustc_codegen_cranelift/src/base.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ fn codegen_stmt<'tcx>(
652652
lval.write_cvalue(fx, res);
653653
}
654654
Rvalue::Cast(
655-
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer),
655+
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
656656
ref operand,
657657
to_ty,
658658
) => {
@@ -677,7 +677,7 @@ fn codegen_stmt<'tcx>(
677677
}
678678
}
679679
Rvalue::Cast(
680-
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer),
680+
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _),
681681
ref operand,
682682
to_ty,
683683
) => {
@@ -688,6 +688,7 @@ fn codegen_stmt<'tcx>(
688688
Rvalue::Cast(
689689
CastKind::PointerCoercion(
690690
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
691+
_,
691692
),
692693
..,
693694
) => {
@@ -741,7 +742,7 @@ fn codegen_stmt<'tcx>(
741742
}
742743
}
743744
Rvalue::Cast(
744-
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)),
745+
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
745746
ref operand,
746747
_to_ty,
747748
) => {
@@ -763,14 +764,18 @@ fn codegen_stmt<'tcx>(
763764
}
764765
}
765766
Rvalue::Cast(
766-
CastKind::PointerCoercion(PointerCoercion::Unsize),
767+
CastKind::PointerCoercion(PointerCoercion::Unsize, _),
767768
ref operand,
768769
_to_ty,
769770
) => {
770771
let operand = codegen_operand(fx, operand);
771772
crate::unsize::coerce_unsized_into(fx, operand, lval);
772773
}
773-
Rvalue::Cast(CastKind::DynStar, ref operand, _) => {
774+
Rvalue::Cast(
775+
CastKind::PointerCoercion(PointerCoercion::DynStar, _),
776+
ref operand,
777+
_,
778+
) => {
774779
let operand = codegen_operand(fx, operand);
775780
crate::unsize::coerce_dyn_star(fx, operand, lval);
776781
}

Diff for: compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
3434
}
3535

3636
mir::Rvalue::Cast(
37-
mir::CastKind::PointerCoercion(PointerCoercion::Unsize),
37+
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _),
3838
ref source,
3939
_,
4040
) => {
@@ -465,7 +465,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
465465
let lladdr = bx.ptrtoint(llptr, llcast_ty);
466466
OperandValue::Immediate(lladdr)
467467
}
468-
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
468+
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _) => {
469469
match *operand.layout.ty.kind() {
470470
ty::FnDef(def_id, args) => {
471471
let instance = ty::Instance::resolve_for_fn_ptr(
@@ -481,7 +481,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
481481
_ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty),
482482
}
483483
}
484-
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_)) => {
484+
mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _) => {
485485
match *operand.layout.ty.kind() {
486486
ty::Closure(def_id, args) => {
487487
let instance = Instance::resolve_closure(
@@ -496,19 +496,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
496496
_ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty),
497497
}
498498
}
499-
mir::CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
499+
mir::CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _) => {
500500
// This is a no-op at the LLVM level.
501501
operand.val
502502
}
503-
mir::CastKind::PointerCoercion(PointerCoercion::Unsize) => {
503+
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _) => {
504504
assert!(bx.cx().is_backend_scalar_pair(cast));
505505
let (lldata, llextra) = operand.val.pointer_parts();
506506
let (lldata, llextra) =
507507
base::unsize_ptr(bx, lldata, operand.layout.ty, cast.ty, llextra);
508508
OperandValue::Pair(lldata, llextra)
509509
}
510510
mir::CastKind::PointerCoercion(
511-
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
511+
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer, _
512512
) => {
513513
bug!("{kind:?} is for borrowck, and should never appear in codegen");
514514
}
@@ -526,7 +526,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
526526
bug!("unexpected non-pair operand");
527527
}
528528
}
529-
mir::CastKind::DynStar => {
529+
mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
530530
let (lldata, llextra) = operand.val.pointer_parts();
531531
let (lldata, llextra) =
532532
base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);

0 commit comments

Comments
 (0)