From 96f5584b808cd08c3c8208db4fee04d2c2b71d79 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Sun, 19 Apr 2020 16:52:15 -0700
Subject: [PATCH 1/2] Expand "recursive opaque type" diagnostic

Fix #70968, partially address #66523.
---
 src/librustc_hir/hir.rs                       |  12 ++
 .../traits/error_reporting/suggestions.rs     |   4 +-
 src/librustc_typeck/check/mod.rs              | 195 ++++++++++++++++--
 .../ui/impl-trait/binding-without-value.rs    |   9 +
 .../impl-trait/binding-without-value.stderr   |  16 ++
 .../issues/infinite-impl-trait-issue-38064.rs |   4 +-
 .../infinite-impl-trait-issue-38064.stderr    |  24 ++-
 .../recursive-impl-trait-type-direct.stderr   |   9 +-
 .../recursive-impl-trait-type-indirect.stderr | 153 ++++++++------
 ...e-impl-trait-type-through-non-recursive.rs |   8 +-
 ...pl-trait-type-through-non-recursive.stderr |  44 ++--
 src/test/ui/impl-trait/where-allowed-2.rs     |   3 +-
 src/test/ui/impl-trait/where-allowed-2.stderr |   8 +-
 13 files changed, 374 insertions(+), 115 deletions(-)
 create mode 100644 src/test/ui/impl-trait/binding-without-value.rs
 create mode 100644 src/test/ui/impl-trait/binding-without-value.stderr

diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 634ab32a28542..bed2044c70855 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -2726,6 +2726,18 @@ impl Node<'_> {
         }
     }
 
+    pub fn body_id(&self) -> Option<BodyId> {
+        match self {
+            Node::TraitItem(TraitItem {
+                kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
+                ..
+            })
+            | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
+            | Node::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
+            _ => None,
+        }
+    }
+
     pub fn generics(&self) -> Option<&Generics<'_>> {
         match self {
             Node::TraitItem(TraitItem { generics, .. })
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index 8796cfb52165d..edff67929f6d0 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -1992,8 +1992,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 /// Collect all the returned expressions within the input expression.
 /// Used to point at the return spans when we want to suggest some change to them.
 #[derive(Default)]
-struct ReturnsVisitor<'v> {
-    returns: Vec<&'v hir::Expr<'v>>,
+pub struct ReturnsVisitor<'v> {
+    pub returns: Vec<&'v hir::Expr<'v>>,
     in_block_tail: bool,
 }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a409e20953da1..d4db32abe2a16 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -138,6 +138,7 @@ use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::opaque_types::{InferCtxtExt as _, OpaqueTypeDecl};
 use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
+use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
@@ -1711,6 +1712,181 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId,
     }
 }
 
+/// Given a `DefId` for an opaque type in return position, find its parent item's return
+/// expressions.
+fn get_owner_return_paths(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> Option<(hir::HirId, ReturnsVisitor<'tcx>)> {
+    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let id = tcx.hir().get_parent_item(hir_id);
+    tcx.hir()
+        .find(id)
+        .map(|n| (id, n))
+        .and_then(|(hir_id, node)| node.body_id().map(|b| (hir_id, b)))
+        .map(|(hir_id, body_id)| {
+            let body = tcx.hir().body(body_id);
+            let mut visitor = ReturnsVisitor::default();
+            visitor.visit_body(body);
+            (hir_id, visitor)
+        })
+}
+
+/// Emit an error for recursive opaque types.
+///
+/// If this is a return `impl Trait`, find the item's return expressions and point at them. For
+/// direct recursion this is enough, but for indirect recursion also point at the last intermediary
+/// `impl Trait`.
+///
+/// If all the return expressions evaluate to `!`, then we explain that the error will go away
+/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
+fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
+    let mut err =
+        struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type to a concrete type");
+
+    let mut label = false;
+    if let Some((hir_id, visitor)) = get_owner_return_paths(tcx, def_id) {
+        let tables = tcx.typeck_tables_of(tcx.hir().local_def_id(hir_id));
+        if visitor
+            .returns
+            .iter()
+            .filter_map(|expr| tables.node_type_opt(expr.hir_id))
+            .map(|ty| tcx.infer_ctxt().enter(|infcx| infcx.resolve_vars_if_possible(&ty)))
+            .all(|ty| matches!(ty.kind, ty::Never))
+        {
+            let spans = visitor
+                .returns
+                .iter()
+                .filter(|expr| tables.node_type_opt(expr.hir_id).is_some())
+                .map(|expr| expr.span)
+                .collect::<Vec<Span>>();
+            let span_len = spans.len();
+            if span_len == 1 {
+                err.span_label(spans[0], "this returned value is of `!` type");
+            } else {
+                let mut multispan: MultiSpan = spans.clone().into();
+                for span in spans {
+                    multispan
+                        .push_span_label(span, "this returned value is of `!` type".to_string());
+                }
+                err.span_note(multispan, "these returned values have a concrete \"never\" type");
+            }
+            err.help("this error will resolve once the item's body returns a concrete type");
+        } else {
+            let mut seen = FxHashSet::default();
+            seen.insert(span);
+            err.span_label(span, "recursive opaque type");
+            label = true;
+            for (sp, ty) in visitor
+                .returns
+                .iter()
+                .filter_map(|e| tables.node_type_opt(e.hir_id).map(|t| (e.span, t)))
+                .filter(|(_, ty)| !matches!(ty.kind, ty::Never))
+                .map(|(sp, ty)| {
+                    (sp, tcx.infer_ctxt().enter(|infcx| infcx.resolve_vars_if_possible(&ty)))
+                })
+            {
+                struct VisitTypes(Vec<DefId>);
+                impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes {
+                    fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+                        match t.kind {
+                            ty::Opaque(def, _) => {
+                                self.0.push(def);
+                                false
+                            }
+                            _ => t.super_visit_with(self),
+                        }
+                    }
+                }
+                let mut visitor = VisitTypes(vec![]);
+                ty.visit_with(&mut visitor);
+                for def_id in visitor.0 {
+                    let ty_span = tcx.def_span(def_id);
+                    if !seen.contains(&ty_span) {
+                        err.span_label(ty_span, &format!("returning this opaque type `{}`", ty));
+                        seen.insert(ty_span);
+                    }
+                    err.span_label(sp, &format!("returning here with type `{}`", ty));
+                }
+            }
+        }
+    }
+    if !label {
+        err.span_label(span, "cannot resolve to a concrete type");
+    }
+    err.emit();
+}
+
+/// Emit an error for recursive opaque types in a `let` binding.
+fn binding_opaque_type_cycle_error(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+    span: Span,
+    partially_expanded_type: Ty<'tcx>,
+) {
+    let mut err =
+        struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type to a concrete type");
+    err.span_label(span, "cannot resolve to a concrete type");
+    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let mut prev_hir_id = hir_id;
+    let mut hir_id = tcx.hir().get_parent_node(hir_id);
+    while let Some(node) = tcx.hir().find(hir_id) {
+        match node {
+            hir::Node::Local(hir::Local {
+                pat,
+                init: None,
+                ty: Some(ty),
+                source: hir::LocalSource::Normal,
+                ..
+            }) => {
+                err.span_label(pat.span, "this binding might not have a concrete type");
+                err.span_suggestion_verbose(
+                    ty.span.shrink_to_hi(),
+                    "set the binding to a value for a concrete type to be resolved",
+                    " = /* value */".to_string(),
+                    Applicability::HasPlaceholders,
+                );
+            }
+            hir::Node::Local(hir::Local {
+                init: Some(expr),
+                source: hir::LocalSource::Normal,
+                ..
+            }) => {
+                let hir_id = tcx.hir().as_local_hir_id(def_id);
+                let tables =
+                    tcx.typeck_tables_of(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id)));
+                let ty = tables.node_type_opt(expr.hir_id);
+                if let Some(ty) =
+                    tcx.infer_ctxt().enter(|infcx| infcx.resolve_vars_if_possible(&ty))
+                {
+                    err.span_label(
+                        expr.span,
+                        &format!(
+                            "this is of type `{}`, which doesn't constrain \
+                                `{}` enough to arrive to a concrete type",
+                            ty, partially_expanded_type
+                        ),
+                    );
+                }
+            }
+            _ => {}
+        }
+        if prev_hir_id == hir_id {
+            break;
+        }
+        prev_hir_id = hir_id;
+        hir_id = tcx.hir().get_parent_node(hir_id);
+    }
+    err.emit();
+}
+
+fn async_opaque_type_cycle_error(tcx: TyCtxt<'tcx>, span: Span) {
+    struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
+        .span_label(span, "recursive `async fn`")
+        .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
+        .emit();
+}
+
 /// Checks that an opaque type does not contain cycles.
 fn check_opaque_for_cycles<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -1721,21 +1897,12 @@ fn check_opaque_for_cycles<'tcx>(
 ) {
     if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs)
     {
-        if let hir::OpaqueTyOrigin::AsyncFn = origin {
-            struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing",)
-                .span_label(span, "recursive `async fn`")
-                .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
-                .emit();
-        } else {
-            let mut err =
-                struct_span_err!(tcx.sess, span, E0720, "opaque type expands to a recursive type",);
-            err.span_label(span, "expands to a recursive type");
-            if let ty::Opaque(..) = partially_expanded_type.kind {
-                err.note("type resolves to itself");
-            } else {
-                err.note(&format!("expanded type is `{}`", partially_expanded_type));
+        match origin {
+            hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span),
+            hir::OpaqueTyOrigin::Binding => {
+                binding_opaque_type_cycle_error(tcx, def_id, span, partially_expanded_type)
             }
-            err.emit();
+            _ => opaque_type_cycle_error(tcx, def_id, span),
         }
     }
 }
diff --git a/src/test/ui/impl-trait/binding-without-value.rs b/src/test/ui/impl-trait/binding-without-value.rs
new file mode 100644
index 0000000000000..6a97f28ff552b
--- /dev/null
+++ b/src/test/ui/impl-trait/binding-without-value.rs
@@ -0,0 +1,9 @@
+#![allow(incomplete_features)]
+#![feature(impl_trait_in_bindings)]
+
+fn foo() {
+    let _ : impl Copy;
+    //~^ ERROR cannot resolve opaque type
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/binding-without-value.stderr b/src/test/ui/impl-trait/binding-without-value.stderr
new file mode 100644
index 0000000000000..1898af5b63eeb
--- /dev/null
+++ b/src/test/ui/impl-trait/binding-without-value.stderr
@@ -0,0 +1,16 @@
+error[E0720]: cannot resolve opaque type to a concrete type
+  --> $DIR/binding-without-value.rs:5:13
+   |
+LL |     let _ : impl Copy;
+   |         -   ^^^^^^^^^ cannot resolve to a concrete type
+   |         |
+   |         this binding might not have a concrete type
+   |
+help: set the binding to a value for a concrete type to be resolved
+   |
+LL |     let _ : impl Copy = /* value */;
+   |                       ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs
index 150a8015cbc75..451ddb3cce0e0 100644
--- a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs
+++ b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs
@@ -5,13 +5,13 @@
 
 trait Quux {}
 
-fn foo() -> impl Quux { //~ opaque type expands to a recursive type
+fn foo() -> impl Quux { //~ ERROR cannot resolve opaque type
     struct Foo<T>(T);
     impl<T> Quux for Foo<T> {}
     Foo(bar())
 }
 
-fn bar() -> impl Quux { //~ opaque type expands to a recursive type
+fn bar() -> impl Quux { //~ ERROR cannot resolve opaque type
     struct Bar<T>(T);
     impl<T> Quux for Bar<T> {}
     Bar(foo())
diff --git a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
index d10001e8a8e53..a38fb7cb56e9d 100644
--- a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
+++ b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
@@ -1,18 +1,26 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/infinite-impl-trait-issue-38064.rs:8:13
    |
 LL | fn foo() -> impl Quux {
-   |             ^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `foo::Foo<bar::Bar<impl Quux>>`
+   |             ^^^^^^^^^ recursive opaque type
+...
+LL |     Foo(bar())
+   |     ---------- returning here with type `foo::Foo<impl Quux>`
+...
+LL | fn bar() -> impl Quux {
+   |             --------- returning this opaque type `foo::Foo<impl Quux>`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/infinite-impl-trait-issue-38064.rs:14:13
    |
+LL | fn foo() -> impl Quux {
+   |             --------- returning this opaque type `bar::Bar<impl Quux>`
+...
 LL | fn bar() -> impl Quux {
-   |             ^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `bar::Bar<foo::Foo<impl Quux>>`
+   |             ^^^^^^^^^ recursive opaque type
+...
+LL |     Bar(foo())
+   |     ---------- returning here with type `bar::Bar<impl Quux>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
index 5a95e2969d1b0..5149d42370c75 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
@@ -1,10 +1,11 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-direct.rs:5:14
    |
 LL | fn test() -> impl Sized {
-   |              ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |              ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     test()
+   |     ------ returning here with type `impl Sized`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index 6573b00870c5b..0bf362e9a6d4a 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -1,114 +1,147 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:7:22
    |
 LL | fn option(i: i32) -> impl Sized {
-   |                      ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `std::option::Option<(impl Sized, i32)>`
+   |                      ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     if i < 0 { None } else { Some((option(i - 1), i)) }
+   |                ----          ------------------------ returning here with type `std::option::Option<(impl Sized, i32)>`
+   |                |
+   |                returning here with type `std::option::Option<(impl Sized, i32)>`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:12:15
    |
 LL | fn tuple() -> impl Sized {
-   |               ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `(impl Sized,)`
+   |               ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     (tuple(),)
+   |     ---------- returning here with type `(impl Sized,)`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:17:15
    |
 LL | fn array() -> impl Sized {
-   |               ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[impl Sized; 1]`
+   |               ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     [array()]
+   |     --------- returning here with type `[impl Sized; 1]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:22:13
    |
 LL | fn ptr() -> impl Sized {
-   |             ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `*const impl Sized`
+   |             ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     &ptr() as *const _
+   |     ------------------ returning here with type `*const impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:27:16
    |
 LL | fn fn_ptr() -> impl Sized {
-   |                ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `fn() -> impl Sized`
+   |                ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     fn_ptr as fn() -> _
+   |     ------------------- returning here with type `fn() -> impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:32:25
    |
-LL | fn closure_capture() -> impl Sized {
-   |                         ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 37:6 x:impl Sized]`
+LL |   fn closure_capture() -> impl Sized {
+   |                           ^^^^^^^^^^ recursive opaque type
+...
+LL | /     move || {
+LL | |         x;
+LL | |     }
+   | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 37:6 x:impl Sized]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:40:29
    |
-LL | fn closure_ref_capture() -> impl Sized {
-   |                             ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 45:6 x:impl Sized]`
+LL |   fn closure_ref_capture() -> impl Sized {
+   |                               ^^^^^^^^^^ recursive opaque type
+...
+LL | /     move || {
+LL | |         &x;
+LL | |     }
+   | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 45:6 x:impl Sized]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:48:21
    |
 LL | fn closure_sig() -> impl Sized {
-   |                     ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:21]`
+   |                     ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     || closure_sig()
+   |     ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:21]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:53:23
    |
 LL | fn generator_sig() -> impl Sized {
-   |                       ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:23]`
+   |                       ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     || generator_sig()
+   |     ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:23]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:58:27
    |
-LL | fn generator_capture() -> impl Sized {
-   |                           ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 x:impl Sized {()}]`
+LL |   fn generator_capture() -> impl Sized {
+   |                             ^^^^^^^^^^ recursive opaque type
+...
+LL | /     move || {
+LL | |         yield;
+LL | |         x;
+LL | |     }
+   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 x:impl Sized {()}]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:67:35
    |
 LL | fn substs_change<T: 'static>() -> impl Sized {
-   |                                   ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `(impl Sized,)`
+   |                                   ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     (substs_change::<&T>(),)
+   |     ------------------------ returning here with type `(impl Sized,)`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:72:24
    |
-LL | fn generator_hold() -> impl Sized {
-   |                        ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]`
+LL |   fn generator_hold() -> impl Sized {
+   |                          ^^^^^^^^^^ recursive opaque type
+LL |
+LL | /     move || {
+LL | |         let x = generator_hold();
+LL | |         yield;
+LL | |         x;
+LL | |     }
+   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:86:26
    |
 LL | fn mutual_recursion() -> impl Sync {
-   |                          ^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |                          ^^^^^^^^^ recursive opaque type
+LL |
+LL |     mutual_recursion_b()
+   |     -------------------- returning here with type `impl Sized`
+...
+LL | fn mutual_recursion_b() -> impl Sized {
+   |                            ---------- returning this opaque type `impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-indirect.rs:91:28
    |
+LL | fn mutual_recursion() -> impl Sync {
+   |                          --------- returning this opaque type `impl std::marker::Sync`
+...
 LL | fn mutual_recursion_b() -> impl Sized {
-   |                            ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |                            ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     mutual_recursion()
+   |     ------------------ returning here with type `impl std::marker::Sync`
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs
index cfd9c0ec5b45b..818e40365394d 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs
@@ -4,21 +4,21 @@
 
 fn id<T>(t: T) -> impl Sized { t }
 
-fn recursive_id() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+fn recursive_id() -> impl Sized { //~ ERROR cannot resolve opaque type
     id(recursive_id2())
 }
 
-fn recursive_id2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+fn recursive_id2() -> impl Sized { //~ ERROR cannot resolve opaque type
     id(recursive_id())
 }
 
 fn wrap<T>(t: T) -> impl Sized { (t,) }
 
-fn recursive_wrap() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+fn recursive_wrap() -> impl Sized { //~ ERROR cannot resolve opaque type
     wrap(recursive_wrap2())
 }
 
-fn recursive_wrap2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+fn recursive_wrap2() -> impl Sized { //~ ERROR cannot resolve opaque type
     wrap(recursive_wrap())
 }
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
index 73c12f6137d24..65e0b8882c425 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
@@ -1,34 +1,46 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:7:22
    |
+LL | fn id<T>(t: T) -> impl Sized { t }
+   |                   ---------- returning this opaque type `impl Sized`
+LL | 
 LL | fn recursive_id() -> impl Sized {
-   |                      ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |                      ^^^^^^^^^^ recursive opaque type
+LL |     id(recursive_id2())
+   |     ------------------- returning here with type `impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:11:23
    |
+LL | fn id<T>(t: T) -> impl Sized { t }
+   |                   ---------- returning this opaque type `impl Sized`
+...
 LL | fn recursive_id2() -> impl Sized {
-   |                       ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |                       ^^^^^^^^^^ recursive opaque type
+LL |     id(recursive_id())
+   |     ------------------ returning here with type `impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:17:24
    |
+LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
+   |                     ---------- returning this opaque type `impl Sized`
+LL | 
 LL | fn recursive_wrap() -> impl Sized {
-   |                        ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `((impl Sized,),)`
+   |                        ^^^^^^^^^^ recursive opaque type
+LL |     wrap(recursive_wrap2())
+   |     ----------------------- returning here with type `impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:21:25
    |
+LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
+   |                     ---------- returning this opaque type `impl Sized`
+...
 LL | fn recursive_wrap2() -> impl Sized {
-   |                         ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `((impl Sized,),)`
+   |                         ^^^^^^^^^^ recursive opaque type
+LL |     wrap(recursive_wrap())
+   |     ---------------------- returning here with type `impl Sized`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/impl-trait/where-allowed-2.rs b/src/test/ui/impl-trait/where-allowed-2.rs
index f7744ef1b3eae..462508f306ef3 100644
--- a/src/test/ui/impl-trait/where-allowed-2.rs
+++ b/src/test/ui/impl-trait/where-allowed-2.rs
@@ -3,7 +3,6 @@
 use std::fmt::Debug;
 
 // Disallowed
-fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
-//~^ ERROR opaque type expands to a recursive type
+fn in_adt_in_return() -> Vec<impl Debug> { panic!() } //~ ERROR cannot resolve opaque type
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/where-allowed-2.stderr b/src/test/ui/impl-trait/where-allowed-2.stderr
index 1de15014c1f8d..6c0e0a4c9a38b 100644
--- a/src/test/ui/impl-trait/where-allowed-2.stderr
+++ b/src/test/ui/impl-trait/where-allowed-2.stderr
@@ -1,10 +1,12 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type to a concrete type
   --> $DIR/where-allowed-2.rs:6:30
    |
 LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
-   |                              ^^^^^^^^^^ expands to a recursive type
+   |                              ^^^^^^^^^^    -------- this returned value is of `!` type
+   |                              |
+   |                              cannot resolve to a concrete type
    |
-   = note: type resolves to itself
+   = help: this error will resolve once the item's body returns a concrete type
 
 error: aborting due to previous error
 

From 8f12485335f506f4c9633305f323e55cdc3c8c2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Mon, 15 Jun 2020 12:11:28 -0700
Subject: [PATCH 2/2] review comments

---
 src/librustc_typeck/check/mod.rs              | 22 +++++----------
 .../impl-trait/binding-without-value.stderr   |  4 +--
 .../infinite-impl-trait-issue-38064.stderr    |  4 +--
 .../recursive-impl-trait-type-direct.stderr   |  2 +-
 .../recursive-impl-trait-type-indirect.stderr | 28 +++++++++----------
 ...pl-trait-type-through-non-recursive.stderr |  8 +++---
 src/test/ui/impl-trait/where-allowed-2.stderr |  4 +--
 7 files changed, 32 insertions(+), 40 deletions(-)

diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index d4db32abe2a16..1fff8fff9c03a 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1741,8 +1741,7 @@ fn get_owner_return_paths(
 /// If all the return expressions evaluate to `!`, then we explain that the error will go away
 /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
 fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
-    let mut err =
-        struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type to a concrete type");
+    let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
 
     let mut label = false;
     if let Some((hir_id, visitor)) = get_owner_return_paths(tcx, def_id) {
@@ -1751,7 +1750,6 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
             .returns
             .iter()
             .filter_map(|expr| tables.node_type_opt(expr.hir_id))
-            .map(|ty| tcx.infer_ctxt().enter(|infcx| infcx.resolve_vars_if_possible(&ty)))
             .all(|ty| matches!(ty.kind, ty::Never))
         {
             let spans = visitor
@@ -1782,9 +1780,6 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
                 .iter()
                 .filter_map(|e| tables.node_type_opt(e.hir_id).map(|t| (e.span, t)))
                 .filter(|(_, ty)| !matches!(ty.kind, ty::Never))
-                .map(|(sp, ty)| {
-                    (sp, tcx.infer_ctxt().enter(|infcx| infcx.resolve_vars_if_possible(&ty)))
-                })
             {
                 struct VisitTypes(Vec<DefId>);
                 impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes {
@@ -1812,7 +1807,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
         }
     }
     if !label {
-        err.span_label(span, "cannot resolve to a concrete type");
+        err.span_label(span, "cannot resolve opaque type");
     }
     err.emit();
 }
@@ -1824,9 +1819,9 @@ fn binding_opaque_type_cycle_error(
     span: Span,
     partially_expanded_type: Ty<'tcx>,
 ) {
-    let mut err =
-        struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type to a concrete type");
-    err.span_label(span, "cannot resolve to a concrete type");
+    let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
+    err.span_label(span, "cannot resolve opaque type");
+    // Find the the owner that declared this `impl Trait` type.
     let hir_id = tcx.hir().as_local_hir_id(def_id);
     let mut prev_hir_id = hir_id;
     let mut hir_id = tcx.hir().get_parent_node(hir_id);
@@ -1855,15 +1850,12 @@ fn binding_opaque_type_cycle_error(
                 let hir_id = tcx.hir().as_local_hir_id(def_id);
                 let tables =
                     tcx.typeck_tables_of(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id)));
-                let ty = tables.node_type_opt(expr.hir_id);
-                if let Some(ty) =
-                    tcx.infer_ctxt().enter(|infcx| infcx.resolve_vars_if_possible(&ty))
-                {
+                if let Some(ty) = tables.node_type_opt(expr.hir_id) {
                     err.span_label(
                         expr.span,
                         &format!(
                             "this is of type `{}`, which doesn't constrain \
-                                `{}` enough to arrive to a concrete type",
+                             `{}` enough to arrive to a concrete type",
                             ty, partially_expanded_type
                         ),
                     );
diff --git a/src/test/ui/impl-trait/binding-without-value.stderr b/src/test/ui/impl-trait/binding-without-value.stderr
index 1898af5b63eeb..0d2faeaf85d10 100644
--- a/src/test/ui/impl-trait/binding-without-value.stderr
+++ b/src/test/ui/impl-trait/binding-without-value.stderr
@@ -1,8 +1,8 @@
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/binding-without-value.rs:5:13
    |
 LL |     let _ : impl Copy;
-   |         -   ^^^^^^^^^ cannot resolve to a concrete type
+   |         -   ^^^^^^^^^ cannot resolve opaque type
    |         |
    |         this binding might not have a concrete type
    |
diff --git a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
index a38fb7cb56e9d..c538b77098a2d 100644
--- a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
+++ b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
@@ -1,4 +1,4 @@
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/infinite-impl-trait-issue-38064.rs:8:13
    |
 LL | fn foo() -> impl Quux {
@@ -10,7 +10,7 @@ LL |     Foo(bar())
 LL | fn bar() -> impl Quux {
    |             --------- returning this opaque type `foo::Foo<impl Quux>`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/infinite-impl-trait-issue-38064.rs:14:13
    |
 LL | fn foo() -> impl Quux {
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
index 5149d42370c75..5a3027ec751a9 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
@@ -1,4 +1,4 @@
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-direct.rs:5:14
    |
 LL | fn test() -> impl Sized {
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index 0bf362e9a6d4a..75ff9e078cc2c 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -1,4 +1,4 @@
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:7:22
    |
 LL | fn option(i: i32) -> impl Sized {
@@ -9,7 +9,7 @@ LL |     if i < 0 { None } else { Some((option(i - 1), i)) }
    |                |
    |                returning here with type `std::option::Option<(impl Sized, i32)>`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:12:15
    |
 LL | fn tuple() -> impl Sized {
@@ -18,7 +18,7 @@ LL |
 LL |     (tuple(),)
    |     ---------- returning here with type `(impl Sized,)`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:17:15
    |
 LL | fn array() -> impl Sized {
@@ -27,7 +27,7 @@ LL |
 LL |     [array()]
    |     --------- returning here with type `[impl Sized; 1]`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:22:13
    |
 LL | fn ptr() -> impl Sized {
@@ -36,7 +36,7 @@ LL |
 LL |     &ptr() as *const _
    |     ------------------ returning here with type `*const impl Sized`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:27:16
    |
 LL | fn fn_ptr() -> impl Sized {
@@ -45,7 +45,7 @@ LL |
 LL |     fn_ptr as fn() -> _
    |     ------------------- returning here with type `fn() -> impl Sized`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:32:25
    |
 LL |   fn closure_capture() -> impl Sized {
@@ -56,7 +56,7 @@ LL | |         x;
 LL | |     }
    | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 37:6 x:impl Sized]`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:40:29
    |
 LL |   fn closure_ref_capture() -> impl Sized {
@@ -67,7 +67,7 @@ LL | |         &x;
 LL | |     }
    | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 45:6 x:impl Sized]`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:48:21
    |
 LL | fn closure_sig() -> impl Sized {
@@ -76,7 +76,7 @@ LL |
 LL |     || closure_sig()
    |     ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:21]`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:53:23
    |
 LL | fn generator_sig() -> impl Sized {
@@ -85,7 +85,7 @@ LL |
 LL |     || generator_sig()
    |     ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:23]`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:58:27
    |
 LL |   fn generator_capture() -> impl Sized {
@@ -97,7 +97,7 @@ LL | |         x;
 LL | |     }
    | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 x:impl Sized {()}]`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:67:35
    |
 LL | fn substs_change<T: 'static>() -> impl Sized {
@@ -106,7 +106,7 @@ LL |
 LL |     (substs_change::<&T>(),)
    |     ------------------------ returning here with type `(impl Sized,)`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:72:24
    |
 LL |   fn generator_hold() -> impl Sized {
@@ -119,7 +119,7 @@ LL | |         x;
 LL | |     }
    | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:86:26
    |
 LL | fn mutual_recursion() -> impl Sync {
@@ -131,7 +131,7 @@ LL |     mutual_recursion_b()
 LL | fn mutual_recursion_b() -> impl Sized {
    |                            ---------- returning this opaque type `impl Sized`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:91:28
    |
 LL | fn mutual_recursion() -> impl Sync {
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
index 65e0b8882c425..fbc58837a8e94 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
@@ -1,4 +1,4 @@
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:7:22
    |
 LL | fn id<T>(t: T) -> impl Sized { t }
@@ -9,7 +9,7 @@ LL | fn recursive_id() -> impl Sized {
 LL |     id(recursive_id2())
    |     ------------------- returning here with type `impl Sized`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:11:23
    |
 LL | fn id<T>(t: T) -> impl Sized { t }
@@ -20,7 +20,7 @@ LL | fn recursive_id2() -> impl Sized {
 LL |     id(recursive_id())
    |     ------------------ returning here with type `impl Sized`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:17:24
    |
 LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
@@ -31,7 +31,7 @@ LL | fn recursive_wrap() -> impl Sized {
 LL |     wrap(recursive_wrap2())
    |     ----------------------- returning here with type `impl Sized`
 
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:21:25
    |
 LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
diff --git a/src/test/ui/impl-trait/where-allowed-2.stderr b/src/test/ui/impl-trait/where-allowed-2.stderr
index 6c0e0a4c9a38b..b8e06725cbcdd 100644
--- a/src/test/ui/impl-trait/where-allowed-2.stderr
+++ b/src/test/ui/impl-trait/where-allowed-2.stderr
@@ -1,10 +1,10 @@
-error[E0720]: cannot resolve opaque type to a concrete type
+error[E0720]: cannot resolve opaque type
   --> $DIR/where-allowed-2.rs:6:30
    |
 LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
    |                              ^^^^^^^^^^    -------- this returned value is of `!` type
    |                              |
-   |                              cannot resolve to a concrete type
+   |                              cannot resolve opaque type
    |
    = help: this error will resolve once the item's body returns a concrete type