Skip to content

Commit 3bca723

Browse files
committed
Auto merge of #89028 - Aaron1011:coercion-cause, r=nagisa
Propagate coercion cause into `try_coerce` Currently, `coerce_inner` discards its `ObligationCause` when calling `try_coerce`. This interfers with other diagnostc improvements I'm working on, since we will lose the original span by the time the actual coercion occurs. Additionally, we now use the span of the trailing expression (rather than the span of the entire function) when performing a coercion in `check_return_expr`. This currently has no visible effect on any of the unit tests, but will unblock future diagnostic improvements.
2 parents 10967a1 + 31cdd8c commit 3bca723

16 files changed

+52
-23
lines changed

Diff for: compiler/rustc_typeck/src/check/cast.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
362362
),
363363
self.cast_ty,
364364
AllowTwoPhase::No,
365+
None,
365366
)
366367
.is_ok()
367368
{
@@ -379,6 +380,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
379380
),
380381
self.cast_ty,
381382
AllowTwoPhase::No,
383+
None,
382384
)
383385
.is_ok()
384386
{
@@ -394,6 +396,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
394396
fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }),
395397
self.cast_ty,
396398
AllowTwoPhase::No,
399+
None,
397400
)
398401
.is_ok()
399402
{
@@ -409,6 +412,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
409412
),
410413
self.cast_ty,
411414
AllowTwoPhase::No,
415+
None,
412416
)
413417
.is_ok()
414418
{
@@ -666,6 +670,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
666670
self.expr_ty,
667671
fcx.tcx.mk_fn_ptr(f),
668672
AllowTwoPhase::No,
673+
None,
669674
);
670675
if let Err(TypeError::IntrinsicCast) = res {
671676
return Err(CastError::IllegalCast);
@@ -829,7 +834,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
829834

830835
// Coerce to a raw pointer so that we generate AddressOf in MIR.
831836
let array_ptr_type = fcx.tcx.mk_ptr(m_expr);
832-
fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No)
837+
fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
833838
.unwrap_or_else(|_| {
834839
bug!(
835840
"could not cast from reference to array to pointer to array ({:?} to {:?})",
@@ -861,7 +866,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
861866
}
862867

863868
fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'_>> {
864-
match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) {
869+
match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
865870
Ok(_) => Ok(()),
866871
Err(err) => Err(err),
867872
}

Diff for: compiler/rustc_typeck/src/check/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ pub(super) fn check_fn<'a, 'tcx>(
214214
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
215215
} else {
216216
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
217-
fcx.check_return_expr(&body.value);
217+
fcx.check_return_expr(&body.value, false);
218218
}
219219
fcx.in_tail_expr = false;
220220

Diff for: compiler/rustc_typeck/src/check/coercion.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -935,11 +935,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
935935
expr_ty: Ty<'tcx>,
936936
target: Ty<'tcx>,
937937
allow_two_phase: AllowTwoPhase,
938+
cause: Option<ObligationCause<'tcx>>,
938939
) -> RelateResult<'tcx, Ty<'tcx>> {
939940
let source = self.resolve_vars_with_obligations(expr_ty);
940941
debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
941942

942-
let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
943+
let cause =
944+
cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable));
943945
let coerce = Coerce::new(self, cause, allow_two_phase);
944946
let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
945947

@@ -1363,7 +1365,13 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
13631365
// Special-case the first expression we are coercing.
13641366
// To be honest, I'm not entirely sure why we do this.
13651367
// We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
1366-
fcx.try_coerce(expression, expression_ty, self.expected_ty, AllowTwoPhase::No)
1368+
fcx.try_coerce(
1369+
expression,
1370+
expression_ty,
1371+
self.expected_ty,
1372+
AllowTwoPhase::No,
1373+
Some(cause.clone()),
1374+
)
13671375
} else {
13681376
match self.expressions {
13691377
Expressions::Dynamic(ref exprs) => fcx.try_find_coercion_lub(

Diff for: compiler/rustc_typeck/src/check/demand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
134134
) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
135135
let expected = self.resolve_vars_with_obligations(expected);
136136

137-
let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase) {
137+
let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) {
138138
Ok(ty) => return (ty, None),
139139
Err(e) => e,
140140
};

Diff for: compiler/rustc_typeck/src/check/expr.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
765765
if self.ret_coercion_span.get().is_none() {
766766
self.ret_coercion_span.set(Some(e.span));
767767
}
768-
self.check_return_expr(e);
768+
self.check_return_expr(e, true);
769769
} else {
770770
let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
771771
if self.ret_coercion_span.get().is_none() {
@@ -794,16 +794,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
794794
self.tcx.types.never
795795
}
796796

797-
pub(super) fn check_return_expr(&self, return_expr: &'tcx hir::Expr<'tcx>) {
797+
/// `explicit_return` is `true` if we're checkng an explicit `return expr`,
798+
/// and `false` if we're checking a trailing expression.
799+
pub(super) fn check_return_expr(
800+
&self,
801+
return_expr: &'tcx hir::Expr<'tcx>,
802+
explicit_return: bool,
803+
) {
798804
let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
799805
span_bug!(return_expr.span, "check_return_expr called outside fn body")
800806
});
801807

802808
let ret_ty = ret_coercion.borrow().expected_ty();
803809
let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty);
810+
let mut span = return_expr.span;
811+
// Use the span of the trailing expression for our cause,
812+
// not the span of the entire function
813+
if !explicit_return {
814+
if let ExprKind::Block(body, _) = return_expr.kind {
815+
if let Some(last_expr) = body.expr {
816+
span = last_expr.span;
817+
}
818+
}
819+
}
804820
ret_coercion.borrow_mut().coerce(
805821
self,
806-
&self.cause(return_expr.span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),
822+
&self.cause(span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),
807823
return_expr,
808824
return_expr_ty,
809825
);

Diff for: src/test/ui/issues/issue-55796.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/iss
1515
LL | Box::new(self.out_edges(u).map(|e| e.target()))
1616
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1717
= note: but, the lifetime must be valid for the static lifetime...
18-
note: ...so that the expression is assignable
18+
note: ...so that the types are compatible
1919
--> $DIR/issue-55796.rs:18:9
2020
|
2121
LL | Box::new(self.out_edges(u).map(|e| e.target()))
@@ -40,7 +40,7 @@ note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/iss
4040
LL | Box::new(self.in_edges(u).map(|e| e.target()))
4141
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4242
= note: but, the lifetime must be valid for the static lifetime...
43-
note: ...so that the expression is assignable
43+
note: ...so that the types are compatible
4444
--> $DIR/issue-55796.rs:23:9
4545
|
4646
LL | Box::new(self.in_edges(u).map(|e| e.target()))

Diff for: src/test/ui/issues/issue-75777.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ LL | Box::new(move |_| fut)
1717
= note: expected `(Pin<Box<dyn Future<Output = A> + Send>>,)`
1818
found `(Pin<Box<(dyn Future<Output = A> + Send + 'a)>>,)`
1919
= note: but, the lifetime must be valid for the static lifetime...
20-
note: ...so that the expression is assignable
20+
note: ...so that the types are compatible
2121
--> $DIR/issue-75777.rs:13:5
2222
|
2323
LL | Box::new(move |_| fut)

Diff for: src/test/ui/nll/issue-55394.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ note: but, the lifetime must be valid for the lifetime `'_` as defined on the im
1919
|
2020
LL | impl Foo<'_> {
2121
| ^^
22-
note: ...so that the expression is assignable
22+
note: ...so that the types are compatible
2323
--> $DIR/issue-55394.rs:9:9
2424
|
2525
LL | Foo { bar }

Diff for: src/test/ui/nll/type-alias-free-regions.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ note: but, the lifetime must be valid for the lifetime `'a` as defined on the im
2121
|
2222
LL | impl<'a> FromBox<'a> for C<'a> {
2323
| ^^
24-
note: ...so that the expression is assignable
24+
note: ...so that the types are compatible
2525
--> $DIR/type-alias-free-regions.rs:17:9
2626
|
2727
LL | C { f: b }
@@ -52,7 +52,7 @@ note: but, the lifetime must be valid for the lifetime `'a` as defined on the im
5252
|
5353
LL | impl<'a> FromTuple<'a> for C<'a> {
5454
| ^^
55-
note: ...so that the expression is assignable
55+
note: ...so that the types are compatible
5656
--> $DIR/type-alias-free-regions.rs:27:9
5757
|
5858
LL | C { f: Box::new(b.0) }

Diff for: src/test/ui/object-lifetime/object-lifetime-default-elision.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
1919
|
2020
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
2121
| ^^
22-
note: ...so that the expression is assignable
22+
note: ...so that the types are compatible
2323
--> $DIR/object-lifetime-default-elision.rs:71:5
2424
|
2525
LL | ss
@@ -48,7 +48,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
4848
|
4949
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
5050
| ^^
51-
note: ...so that the expression is assignable
51+
note: ...so that the types are compatible
5252
--> $DIR/object-lifetime-default-elision.rs:71:5
5353
|
5454
LL | ss

Diff for: src/test/ui/regions/region-object-lifetime-in-coercion.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
6969
|
7070
LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
7171
| ^^
72-
note: ...so that the expression is assignable
72+
note: ...so that the types are compatible
7373
--> $DIR/region-object-lifetime-in-coercion.rs:23:5
7474
|
7575
LL | Box::new(v)

Diff for: src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ note: but, the lifetime must be valid for the lifetime `'c` as defined on the fu
1919
|
2020
LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
2121
| ^^
22-
note: ...so that the expression is assignable
22+
note: ...so that the types are compatible
2323
--> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
2424
|
2525
LL | box v as Box<dyn SomeTrait + 'a>

Diff for: src/test/ui/regions/regions-creating-enums4.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
2121
|
2222
LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
2323
| ^^
24-
note: ...so that the expression is assignable
24+
note: ...so that the types are compatible
2525
--> $DIR/regions-creating-enums4.rs:7:5
2626
|
2727
LL | Ast::Add(x, y)

Diff for: src/test/ui/regions/regions-ret-borrowed-1.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on th
99
|
1010
LL | with(|o| o)
1111
| ^^^^^
12-
note: ...so that the expression is assignable
12+
note: ...so that the types are compatible
1313
--> $DIR/regions-ret-borrowed-1.rs:10:14
1414
|
1515
LL | with(|o| o)

Diff for: src/test/ui/regions/regions-ret-borrowed.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on th
99
|
1010
LL | with(|o| o)
1111
| ^^^^^
12-
note: ...so that the expression is assignable
12+
note: ...so that the types are compatible
1313
--> $DIR/regions-ret-borrowed.rs:13:14
1414
|
1515
LL | with(|o| o)

Diff for: src/test/ui/regions/regions-trait-object-subtyping.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
3636
|
3737
LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
3838
| ^^
39-
note: ...so that the expression is assignable
39+
note: ...so that the types are compatible
4040
--> $DIR/regions-trait-object-subtyping.rs:15:5
4141
|
4242
LL | x

0 commit comments

Comments
 (0)