Skip to content

Commit

Permalink
Rollup merge of rust-lang#63796 - estebank:opaque_future, r=Centril
Browse files Browse the repository at this point in the history
Tweak E0308 on opaque types

```
error[E0308]: if and else have incompatible types
  --> file.rs:21:9
   |
18 | /     if true {
19 | |         thing_one()
   | |         ----------- expected because of this
20 | |     } else {
21 | |         thing_two()
   | |         ^^^^^^^^^^^ expected opaque type, found a different opaque type
22 | |     }.await
   | |_____- if and else have incompatible types
   |
   = note: expected type `impl std::future::Future` (opaque type)
              found type `impl std::future::Future` (opaque type)
   = note: distinct uses of `impl Trait` result in different opaque types
   = help: if both futures resolve to the same type, consider `await`ing on both of them
```

r? @Centril
CC rust-lang#63167
  • Loading branch information
Centril authored Aug 22, 2019
2 parents 6c1cdb7 + a710c61 commit aa9490b
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1650,7 +1650,7 @@ impl<'tcx> ObligationCause<'tcx> {
hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types",
_ => "match arms have compatible types",
},
IfExpression { .. } => "if and else have compatible types",
IfExpression { .. } => "if and else have incompatible types",
IfExpressionWithNoElse => "if missing an else returns ()",
MainFunctionType => "`main` function has the correct type",
StartFunctionType => "`start` function has the correct type",
Expand Down
22 changes: 17 additions & 5 deletions src/librustc/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,20 +247,32 @@ impl<'tcx> ty::TyS<'tcx> {
}

impl<'tcx> TyCtxt<'tcx> {
pub fn note_and_explain_type_err(self,
db: &mut DiagnosticBuilder<'_>,
err: &TypeError<'tcx>,
sp: Span) {
pub fn note_and_explain_type_err(
self,
db: &mut DiagnosticBuilder<'_>,
err: &TypeError<'tcx>,
sp: Span,
) {
use self::TypeError::*;

match err.clone() {
match err {
Sorts(values) => {
let expected_str = values.expected.sort_string(self);
let found_str = values.found.sort_string(self);
if expected_str == found_str && expected_str == "closure" {
db.note("no two closures, even if identical, have the same type");
db.help("consider boxing your closure and/or using it as a trait object");
}
if expected_str == found_str && expected_str == "opaque type" { // Issue #63167
db.note("distinct uses of `impl Trait` result in different opaque types");
let e_str = values.expected.to_string();
let f_str = values.found.to_string();
if &e_str == &f_str && &e_str == "impl std::future::Future" {
// FIXME: use non-string based check.
db.help("if both `Future`s have the same `Output` type, consider \
`.await`ing on both of them");
}
}
if let (ty::Infer(ty::IntVar(_)), ty::Float(_)) =
(&values.found.sty, &values.expected.sty) // Issue #53280
{
Expand Down
24 changes: 24 additions & 0 deletions src/test/ui/suggestions/opaque-type-error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// edition:2018
use core::future::Future;

async fn base_thing() -> Result<(), ()> {
Ok(())
}

fn thing_one() -> impl Future<Output = Result<(), ()>> {
base_thing()
}

fn thing_two() -> impl Future<Output = Result<(), ()>> {
base_thing()
}

async fn thing() -> Result<(), ()> {
if true {
thing_one()
} else {
thing_two() //~ ERROR if and else have incompatible types
}.await
}

fn main() {}
20 changes: 20 additions & 0 deletions src/test/ui/suggestions/opaque-type-error.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0308]: if and else have incompatible types
--> $DIR/opaque-type-error.rs:20:9
|
LL | / if true {
LL | | thing_one()
| | ----------- expected because of this
LL | | } else {
LL | | thing_two()
| | ^^^^^^^^^^^ expected opaque type, found a different opaque type
LL | | }.await
| |_____- if and else have incompatible types
|
= note: expected type `impl std::future::Future` (opaque type)
found type `impl std::future::Future` (opaque type)
= note: distinct uses of `impl Trait` result in different opaque types
= help: if both `Future`s have the same `Output` type, consider `.await`ing on both of them

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

0 comments on commit aa9490b

Please sign in to comment.