Skip to content

Commit 3fc4a95

Browse files
authored
Unrolled build for rust-lang#115196
Rollup merge of rust-lang#115196 - chenyukang:yukang-fix-86094, r=estebank Suggest adding `return` if the for semi which can coerce to the fn return type Fixes rust-lang#86094 r? `@estebank`
2 parents 99592fd + 25d38c4 commit 3fc4a95

File tree

7 files changed

+230
-12
lines changed

7 files changed

+230
-12
lines changed

compiler/rustc_errors/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ pub enum StashKey {
507507
CallAssocMethod,
508508
TraitMissingMethod,
509509
OpaqueHiddenTypeMismatch,
510+
MaybeForgetReturn,
510511
}
511512

512513
fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+5
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
564564

565565
if !errors.is_empty() {
566566
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
567+
let errors_causecode = errors
568+
.iter()
569+
.map(|e| (e.obligation.cause.span, e.root_obligation.cause.code().clone()))
570+
.collect::<Vec<_>>();
567571
self.err_ctxt().report_fulfillment_errors(errors);
572+
self.collect_unused_stmts_for_coerce_return_ty(errors_causecode);
568573
}
569574
}
570575

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+55-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
use rustc_ast as ast;
1212
use rustc_data_structures::fx::FxIndexSet;
1313
use rustc_errors::{
14-
pluralize, Applicability, Diagnostic, DiagnosticId, ErrorGuaranteed, MultiSpan,
14+
pluralize, Applicability, Diagnostic, DiagnosticId, ErrorGuaranteed, MultiSpan, StashKey,
1515
};
1616
use rustc_hir as hir;
1717
use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -27,6 +27,7 @@ use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
2727
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
2828
use rustc_infer::infer::TypeTrace;
2929
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
30+
use rustc_middle::traits::ObligationCauseCode::ExprBindingObligation;
3031
use rustc_middle::ty::adjustment::AllowTwoPhase;
3132
use rustc_middle::ty::visit::TypeVisitableExt;
3233
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
@@ -1375,7 +1376,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13751376
}
13761377
_ => bug!("unexpected type: {:?}", ty.normalized),
13771378
},
1378-
Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
1379+
Res::Def(
1380+
DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy,
1381+
_,
1382+
)
13791383
| Res::SelfTyParam { .. }
13801384
| Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() {
13811385
Some(adt) if !adt.is_enum() => {
@@ -1845,6 +1849,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18451849
}
18461850
}
18471851

1852+
pub(super) fn collect_unused_stmts_for_coerce_return_ty(
1853+
&self,
1854+
errors_causecode: Vec<(Span, ObligationCauseCode<'tcx>)>,
1855+
) {
1856+
for (span, code) in errors_causecode {
1857+
let Some(mut diag) =
1858+
self.tcx.sess.diagnostic().steal_diagnostic(span, StashKey::MaybeForgetReturn)
1859+
else {
1860+
continue;
1861+
};
1862+
1863+
if let Some(fn_sig) = self.body_fn_sig()
1864+
&& let ExprBindingObligation(_, _, hir_id, ..) = code
1865+
&& !fn_sig.output().is_unit()
1866+
{
1867+
let mut block_num = 0;
1868+
let mut found_semi = false;
1869+
for (_, node) in self.tcx.hir().parent_iter(hir_id) {
1870+
match node {
1871+
hir::Node::Stmt(stmt) => if let hir::StmtKind::Semi(ref expr) = stmt.kind {
1872+
let expr_ty = self.typeck_results.borrow().expr_ty(expr);
1873+
let return_ty = fn_sig.output();
1874+
if !matches!(expr.kind, hir::ExprKind::Ret(..)) &&
1875+
self.can_coerce(expr_ty, return_ty) {
1876+
found_semi = true;
1877+
}
1878+
},
1879+
hir::Node::Block(_block) => if found_semi {
1880+
block_num += 1;
1881+
}
1882+
hir::Node::Item(item) => if let hir::ItemKind::Fn(..) = item.kind {
1883+
break;
1884+
}
1885+
_ => {}
1886+
}
1887+
}
1888+
if block_num > 1 && found_semi {
1889+
diag.span_suggestion_verbose(
1890+
span.shrink_to_lo(),
1891+
"you might have meant to return this to infer its type parameters",
1892+
"return ",
1893+
Applicability::MaybeIncorrect,
1894+
);
1895+
}
1896+
}
1897+
diag.emit();
1898+
}
1899+
}
1900+
18481901
/// Given a vector of fulfillment errors, try to adjust the spans of the
18491902
/// errors to more accurately point at the cause of the failure.
18501903
///

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::traits::{
1717
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
1818
use rustc_errors::{
1919
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
20-
MultiSpan, Style,
20+
MultiSpan, StashKey, Style,
2121
};
2222
use rustc_hir as hir;
2323
use rustc_hir::def::{DefKind, Namespace, Res};
@@ -2049,14 +2049,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
20492049
// begin with in those cases.
20502050
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
20512051
if let None = self.tainted_by_errors() {
2052-
self.emit_inference_failure_err(
2052+
let err = self.emit_inference_failure_err(
20532053
obligation.cause.body_id,
20542054
span,
20552055
trait_ref.self_ty().skip_binder().into(),
20562056
ErrorCode::E0282,
20572057
false,
2058-
)
2059-
.emit();
2058+
);
2059+
err.stash(span, StashKey::MaybeForgetReturn);
20602060
}
20612061
return;
20622062
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
struct MyError;
2+
3+
fn foo(x: bool) -> Result<(), MyError> {
4+
if x {
5+
Err(MyError);
6+
//~^ ERROR type annotations needed
7+
}
8+
9+
Ok(())
10+
}
11+
12+
fn bar(x: bool) -> Result<(), MyError> {
13+
if x {
14+
Ok(());
15+
//~^ ERROR type annotations needed
16+
}
17+
18+
Ok(())
19+
}
20+
21+
fn baz(x: bool) -> Result<(), MyError> {
22+
//~^ ERROR mismatched types
23+
if x {
24+
1;
25+
}
26+
27+
Err(MyError);
28+
}
29+
30+
fn error() -> Result<(), MyError> {
31+
Err(MyError)
32+
}
33+
34+
fn bak(x: bool) -> Result<(), MyError> {
35+
if x {
36+
//~^ ERROR mismatched types
37+
error();
38+
} else {
39+
//~^ ERROR mismatched types
40+
error();
41+
}
42+
}
43+
44+
fn bad(x: bool) -> Result<(), MyError> {
45+
Err(MyError); //~ ERROR type annotations needed
46+
Ok(())
47+
}
48+
49+
fn with_closure<F, A, B>(_: F) -> i32
50+
where
51+
F: FnOnce(A, B),
52+
{
53+
0
54+
}
55+
56+
fn a() -> i32 {
57+
with_closure(|x: u32, y| {}); //~ ERROR type annotations needed
58+
0
59+
}
60+
61+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/issue-86094-suggest-add-return-to-coerce-ret-ty.rs:5:9
3+
|
4+
LL | Err(MyError);
5+
| ^^^ cannot infer type of the type parameter `T` declared on the enum `Result`
6+
|
7+
help: consider specifying the generic arguments
8+
|
9+
LL | Err::<T, MyError>(MyError);
10+
| ++++++++++++++
11+
help: you might have meant to return this to infer its type parameters
12+
|
13+
LL | return Err(MyError);
14+
| ++++++
15+
16+
error[E0282]: type annotations needed
17+
--> $DIR/issue-86094-suggest-add-return-to-coerce-ret-ty.rs:14:9
18+
|
19+
LL | Ok(());
20+
| ^^ cannot infer type of the type parameter `E` declared on the enum `Result`
21+
|
22+
help: consider specifying the generic arguments
23+
|
24+
LL | Ok::<(), E>(());
25+
| +++++++++
26+
help: you might have meant to return this to infer its type parameters
27+
|
28+
LL | return Ok(());
29+
| ++++++
30+
31+
error[E0308]: mismatched types
32+
--> $DIR/issue-86094-suggest-add-return-to-coerce-ret-ty.rs:21:20
33+
|
34+
LL | fn baz(x: bool) -> Result<(), MyError> {
35+
| --- ^^^^^^^^^^^^^^^^^^^ expected `Result<(), MyError>`, found `()`
36+
| |
37+
| implicitly returns `()` as its body has no tail or `return` expression
38+
...
39+
LL | Err(MyError);
40+
| - help: remove this semicolon to return this value
41+
|
42+
= note: expected enum `Result<(), MyError>`
43+
found unit type `()`
44+
45+
error[E0308]: mismatched types
46+
--> $DIR/issue-86094-suggest-add-return-to-coerce-ret-ty.rs:35:10
47+
|
48+
LL | if x {
49+
| __________^
50+
LL | |
51+
LL | | error();
52+
| | - help: remove this semicolon to return this value
53+
LL | | } else {
54+
| |_____^ expected `Result<(), MyError>`, found `()`
55+
|
56+
= note: expected enum `Result<(), MyError>`
57+
found unit type `()`
58+
59+
error[E0308]: mismatched types
60+
--> $DIR/issue-86094-suggest-add-return-to-coerce-ret-ty.rs:38:12
61+
|
62+
LL | } else {
63+
| ____________^
64+
LL | |
65+
LL | | error();
66+
| | - help: remove this semicolon to return this value
67+
LL | | }
68+
| |_____^ expected `Result<(), MyError>`, found `()`
69+
|
70+
= note: expected enum `Result<(), MyError>`
71+
found unit type `()`
72+
73+
error[E0282]: type annotations needed
74+
--> $DIR/issue-86094-suggest-add-return-to-coerce-ret-ty.rs:45:5
75+
|
76+
LL | Err(MyError);
77+
| ^^^ cannot infer type of the type parameter `T` declared on the enum `Result`
78+
|
79+
help: consider specifying the generic arguments
80+
|
81+
LL | Err::<T, MyError>(MyError);
82+
| ++++++++++++++
83+
84+
error[E0282]: type annotations needed
85+
--> $DIR/issue-86094-suggest-add-return-to-coerce-ret-ty.rs:57:27
86+
|
87+
LL | with_closure(|x: u32, y| {});
88+
| ^
89+
|
90+
help: consider giving this closure parameter an explicit type
91+
|
92+
LL | with_closure(|x: u32, y: /* Type */| {});
93+
| ++++++++++++
94+
95+
error: aborting due to 7 previous errors
96+
97+
Some errors have detailed explanations: E0282, E0308.
98+
For more information about an error, try `rustc --explain E0282`.

tests/ui/traits/new-solver/specialization-unconstrained.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@ LL | #![feature(specialization)]
88
= help: consider using `min_specialization` instead, which is more stable and complete
99
= note: `#[warn(incomplete_features)]` on by default
1010

11-
error[E0282]: type annotations needed
12-
--> $DIR/specialization-unconstrained.rs:14:22
13-
|
14-
LL | default type Id = T;
15-
| ^ cannot infer type for associated type `<T as Default>::Id`
16-
1711
error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id == ()`
1812
--> $DIR/specialization-unconstrained.rs:20:5
1913
|
@@ -26,6 +20,12 @@ note: required by a bound in `test`
2620
LL | fn test<T: Default<Id = U>, U>() {}
2721
| ^^^^^^ required by this bound in `test`
2822

23+
error[E0282]: type annotations needed
24+
--> $DIR/specialization-unconstrained.rs:14:22
25+
|
26+
LL | default type Id = T;
27+
| ^ cannot infer type for associated type `<T as Default>::Id`
28+
2929
error: aborting due to 2 previous errors; 1 warning emitted
3030

3131
Some errors have detailed explanations: E0282, E0284.

0 commit comments

Comments
 (0)