Skip to content

Commit dfc6d7a

Browse files
authored
Rollup merge of #97818 - compiler-errors:rpit-error-spanned, r=oli-obk
Point at return expression for RPIT-related error Certainly this needs some diagnostic refining, but I wanted to show that it was possible first and foremost. Not sure if this is the right approach. Open to feedback. Fixes #80583
2 parents 25b8449 + 52409c4 commit dfc6d7a

File tree

14 files changed

+97
-5
lines changed

14 files changed

+97
-5
lines changed

compiler/rustc_infer/src/infer/opaque_types.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use hir::{HirId, OpaqueTyOrigin};
55
use rustc_data_structures::sync::Lrc;
66
use rustc_data_structures::vec_map::VecMap;
77
use rustc_hir as hir;
8-
use rustc_middle::traits::ObligationCause;
8+
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
99
use rustc_middle::ty::fold::BottomUpFolder;
1010
use rustc_middle::ty::subst::{GenericArgKind, Subst};
1111
use rustc_middle::ty::{
@@ -46,6 +46,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
4646
value: T,
4747
body_id: HirId,
4848
span: Span,
49+
code: ObligationCauseCode<'tcx>,
4950
param_env: ty::ParamEnv<'tcx>,
5051
) -> InferOk<'tcx, T> {
5152
if !value.has_opaque_types() {
@@ -68,10 +69,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
6869
) =>
6970
{
7071
let span = if span.is_dummy() { self.tcx.def_span(def_id) } else { span };
71-
let cause = ObligationCause::misc(span, body_id);
72+
let cause = ObligationCause::new(span, body_id, code.clone());
73+
// FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
74+
// for opaque types, and then use that kind to fix the spans for type errors
75+
// that we see later on.
7276
let ty_var = self.next_ty_var(TypeVariableOrigin {
7377
kind: TypeVariableOriginKind::TypeInference,
74-
span: cause.span,
78+
span,
7579
});
7680
obligations.extend(
7781
self.handle_opaque_type(ty, ty_var, true, &cause, param_env)

compiler/rustc_middle/src/traits/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,9 @@ pub enum ObligationCauseCode<'tcx> {
387387
/// Return type of this function
388388
ReturnType,
389389

390+
/// Opaque return type of this function
391+
OpaqueReturnType(Option<(Ty<'tcx>, Span)>),
392+
390393
/// Block implicit return
391394
BlockTailExpression(hir::HirId),
392395

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2661,6 +2661,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
26612661
err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
26622662
}
26632663
}
2664+
ObligationCauseCode::OpaqueReturnType(expr_info) => {
2665+
if let Some((expr_ty, expr_span)) = expr_info {
2666+
let expr_ty = self.resolve_vars_if_possible(expr_ty);
2667+
err.span_label(
2668+
expr_span,
2669+
format!("return type was inferred to be `{expr_ty}` here"),
2670+
);
2671+
}
2672+
}
26642673
}
26652674
}
26662675

compiler/rustc_trait_selection/src/traits/project.rs

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use rustc_hir::def::DefKind;
2828
use rustc_hir::def_id::DefId;
2929
use rustc_hir::lang_items::LangItem;
3030
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
31+
use rustc_infer::traits::ObligationCauseCode;
3132
use rustc_middle::traits::select::OverflowError;
3233
use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder, TypeSuperFoldable};
3334
use rustc_middle::ty::subst::Subst;
@@ -261,6 +262,7 @@ fn project_and_unify_type<'cx, 'tcx>(
261262
actual,
262263
obligation.cause.body_id,
263264
obligation.cause.span,
265+
ObligationCauseCode::MiscObligation,
264266
obligation.param_env,
265267
);
266268
obligations.extend(new);

compiler/rustc_typeck/src/check/check.rs

+5
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,13 @@ pub(super) fn check_fn<'a, 'tcx>(
101101
declared_ret_ty,
102102
body.value.hir_id,
103103
DUMMY_SP,
104+
traits::ObligationCauseCode::OpaqueReturnType(None),
104105
param_env,
105106
));
107+
// If we replaced declared_ret_ty with infer vars, then we must be infering
108+
// an opaque type, so set a flag so we can improve diagnostics.
109+
fcx.return_type_has_opaque = ret_ty != declared_ret_ty;
110+
106111
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
107112
fcx.ret_type_span = Some(decl.output.span());
108113

compiler/rustc_typeck/src/check/closure.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
1010
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1111
use rustc_infer::infer::LateBoundRegionConversionTime;
1212
use rustc_infer::infer::{InferOk, InferResult};
13+
use rustc_infer::traits::ObligationCauseCode;
1314
use rustc_middle::ty::fold::TypeFoldable;
1415
use rustc_middle::ty::subst::InternalSubsts;
1516
use rustc_middle::ty::{self, Ty};
@@ -645,8 +646,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
645646
}
646647

647648
fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
648-
let InferOk { value, obligations } =
649-
self.replace_opaque_types_with_inference_vars(ty, body_id, span, self.param_env);
649+
let InferOk { value, obligations } = self.replace_opaque_types_with_inference_vars(
650+
ty,
651+
body_id,
652+
span,
653+
ObligationCauseCode::MiscObligation,
654+
self.param_env,
655+
);
650656
self.register_predicates(obligations);
651657
value
652658
}

compiler/rustc_typeck/src/check/expr.rs

+32
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use rustc_hir::{ExprKind, HirId, QPath};
3939
use rustc_infer::infer;
4040
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
4141
use rustc_infer::infer::InferOk;
42+
use rustc_infer::traits::ObligationCause;
4243
use rustc_middle::middle::stability;
4344
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
4445
use rustc_middle::ty::error::TypeError::FieldMisMatch;
@@ -839,6 +840,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
839840
return_expr,
840841
return_expr_ty,
841842
);
843+
844+
if self.return_type_has_opaque {
845+
// Point any obligations that were registered due to opaque type
846+
// inference at the return expression.
847+
self.select_obligations_where_possible(false, |errors| {
848+
self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty);
849+
});
850+
}
851+
}
852+
853+
fn point_at_return_for_opaque_ty_error(
854+
&self,
855+
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
856+
span: Span,
857+
return_expr_ty: Ty<'tcx>,
858+
) {
859+
// Don't point at the whole block if it's empty
860+
if span == self.tcx.hir().span(self.body_id) {
861+
return;
862+
}
863+
for err in errors {
864+
let cause = &mut err.obligation.cause;
865+
if let ObligationCauseCode::OpaqueReturnType(None) = cause.code() {
866+
let new_cause = ObligationCause::new(
867+
cause.span,
868+
cause.body_id,
869+
ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, span))),
870+
);
871+
*cause = new_cause;
872+
}
873+
}
842874
}
843875

844876
pub(crate) fn check_lhs_assignable(

compiler/rustc_typeck/src/check/fn_ctxt/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ pub struct FnCtxt<'a, 'tcx> {
115115
/// either given explicitly or inferred from, say, an `Fn*` trait
116116
/// bound. Used for diagnostic purposes only.
117117
pub(super) return_type_pre_known: bool,
118+
119+
/// True if the return type has an Opaque type
120+
pub(super) return_type_has_opaque: bool,
118121
}
119122

120123
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -141,6 +144,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
141144
}),
142145
inh,
143146
return_type_pre_known: true,
147+
return_type_has_opaque: false,
144148
}
145149
}
146150

src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ LL | fn bar() -> impl Bar {
66
...
77
LL | fn baz() -> impl Bar<Item = i32> {
88
| ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32`
9+
LL |
10+
LL | bar()
11+
| ----- return type was inferred to be `impl Bar` here
912
|
1013
= note: expected associated type `<impl Bar as Foo>::Item`
1114
found type `i32`

src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied
33
|
44
LL | fn rawr() -> impl Trait {
55
| ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>`
6+
LL |
7+
LL | Uwu::<10, 12>
8+
| ------------- return type was inferred to be `Uwu<10_u32, 12_u32>` here
69
|
710
= help: the trait `Trait` is implemented for `Uwu<N>`
811

@@ -11,6 +14,9 @@ error[E0277]: the trait bound `u32: Traitor<N>` is not satisfied
1114
|
1215
LL | fn uwu<const N: u8>() -> impl Traitor<N> {
1316
| ^^^^^^^^^^^^^^^ the trait `Traitor<N>` is not implemented for `u32`
17+
LL |
18+
LL | 1_u32
19+
| ----- return type was inferred to be `u32` here
1420
|
1521
= help: the following other types implement trait `Traitor<N, M>`:
1622
<u32 as Traitor<N, 2_u8>>
@@ -21,6 +27,9 @@ error[E0277]: the trait bound `u64: Traitor` is not satisfied
2127
|
2228
LL | fn owo() -> impl Traitor {
2329
| ^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u64`
30+
LL |
31+
LL | 1_u64
32+
| ----- return type was inferred to be `u64` here
2433
|
2534
= help: the following other types implement trait `Traitor<N, M>`:
2635
<u32 as Traitor<N, 2_u8>>

src/test/ui/impl-trait/bound-normalization-fail.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as imp
33
|
44
LL | fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc`
6+
LL |
7+
LL | Foo(())
8+
| ------- return type was inferred to be `Foo<()>` here
69
|
710
note: expected this to be `()`
811
--> $DIR/bound-normalization-fail.rs:14:19
@@ -27,6 +30,9 @@ error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lif
2730
|
2831
LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
2932
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc`
33+
...
34+
LL | Foo(())
35+
| ------- return type was inferred to be `Foo<()>` here
3036
|
3137
note: expected this to be `()`
3238
--> $DIR/bound-normalization-fail.rs:14:19

src/test/ui/issues-71798.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ error[E0277]: `u32` is not a future
99
|
1010
LL | fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future
12+
LL |
13+
LL | *x
14+
| -- return type was inferred to be `u32` here
1215
|
1316
= help: the trait `Future` is not implemented for `u32`
1417
= note: u32 must be a future or must implement `IntoFuture` to be awaited

src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
33
|
44
LL | fn foo() -> impl Foo<FooX> {
55
| ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
6+
...
7+
LL | ()
8+
| -- return type was inferred to be `()` here
69
|
710
= help: the trait `Foo<()>` is implemented for `()`
811

src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
33
|
44
LL | fn foo() -> impl Foo<FooX> {
55
| ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
6+
LL |
7+
LL | ()
8+
| -- return type was inferred to be `()` here
69
|
710
= help: the following other types implement trait `Foo<A>`:
811
<() as Foo<()>>

0 commit comments

Comments
 (0)