about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_middle/ty/mod.rs48
-rw-r--r--src/librustc_typeck/check/wfcheck.rs108
-rw-r--r--src/librustc_typeck/collect/type_of.rs140
-rw-r--r--src/test/ui/type-alias-impl-trait/bound_reduction2.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/bound_reduction2.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs22
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr47
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs3
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr23
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr17
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs26
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr41
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.stderr31
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/not_a_defining_use.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr19
21 files changed, 276 insertions, 311 deletions
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 901365ef691..9b182333907 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -1077,48 +1077,42 @@ impl<'tcx> Generics {
         false
     }
 
+    pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
+        if let Some(index) = param_index.checked_sub(self.parent_count) {
+            &self.params[index]
+        } else {
+            tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
+                .param_at(param_index, tcx)
+        }
+    }
+
     pub fn region_param(
         &'tcx self,
         param: &EarlyBoundRegion,
         tcx: TyCtxt<'tcx>,
     ) -> &'tcx GenericParamDef {
-        if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
-            let param = &self.params[index as usize];
-            match param.kind {
-                GenericParamDefKind::Lifetime => param,
-                _ => bug!("expected lifetime parameter, but found another generic parameter"),
-            }
-        } else {
-            tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
-                .region_param(param, tcx)
+        let param = self.param_at(param.index as usize, tcx);
+        match param.kind {
+            GenericParamDefKind::Lifetime => param,
+            _ => bug!("expected lifetime parameter, but found another generic parameter"),
         }
     }
 
     /// Returns the `GenericParamDef` associated with this `ParamTy`.
     pub fn type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
-        if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
-            let param = &self.params[index as usize];
-            match param.kind {
-                GenericParamDefKind::Type { .. } => param,
-                _ => bug!("expected type parameter, but found another generic parameter"),
-            }
-        } else {
-            tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
-                .type_param(param, tcx)
+        let param = self.param_at(param.index as usize, tcx);
+        match param.kind {
+            GenericParamDefKind::Type { .. } => param,
+            _ => bug!("expected type parameter, but found another generic parameter"),
         }
     }
 
     /// Returns the `ConstParameterDef` associated with this `ParamConst`.
     pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef {
-        if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
-            let param = &self.params[index as usize];
-            match param.kind {
-                GenericParamDefKind::Const => param,
-                _ => bug!("expected const parameter, but found another generic parameter"),
-            }
-        } else {
-            tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
-                .const_param(param, tcx)
+        let param = self.param_at(param.index as usize, tcx);
+        match param.kind {
+            GenericParamDefKind::Const => param,
+            _ => bug!("expected const parameter, but found another generic parameter"),
         }
     }
 }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 30a53cbc397..b0ff17ad56d 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -9,7 +9,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 use rustc_hir::lang_items;
 use rustc_hir::ItemKind;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
     self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
@@ -864,87 +864,77 @@ fn check_opaque_types<'fcx, 'tcx>(
                 trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
                 let generics = tcx.generics_of(def_id);
                 // Only check named `impl Trait` types defined in this crate.
+                // FIXME(eddyb) is  `generics.parent.is_none()` correct? It seems
+                // potentially risky wrt associated types in `impl`s.
                 if generics.parent.is_none() && def_id.is_local() {
                     let opaque_hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
                     if may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
                         trace!("check_opaque_types: may define, generics={:#?}", generics);
-                        let mut seen: FxHashMap<_, Vec<_>> = FxHashMap::default();
-                        for (subst, param) in substs.iter().zip(&generics.params) {
-                            match subst.unpack() {
-                                ty::subst::GenericArgKind::Type(ty) => match ty.kind {
-                                    ty::Param(..) => {}
-                                    // Prevent `fn foo() -> Foo<u32>` from being defining.
-                                    _ => {
-                                        tcx.sess
-                                            .struct_span_err(
-                                                span,
-                                                "non-defining opaque type use \
-                                                 in defining scope",
-                                            )
-                                            .span_note(
-                                                tcx.def_span(param.def_id),
-                                                &format!(
-                                                    "used non-generic type {} for \
-                                                     generic parameter",
-                                                    ty,
-                                                ),
-                                            )
-                                            .emit();
-                                    }
-                                },
+                        let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
+                        for (i, &arg) in substs.iter().enumerate() {
+                            let arg_is_param = match arg.unpack() {
+                                GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
 
-                                ty::subst::GenericArgKind::Lifetime(region) => {
-                                    let param_span = tcx.def_span(param.def_id);
+                                GenericArgKind::Lifetime(region) => {
                                     if let ty::ReStatic = region {
                                         tcx.sess
                                             .struct_span_err(
                                                 span,
-                                                "non-defining opaque type use \
-                                                 in defining scope",
+                                                "non-defining opaque type use in defining scope",
                                             )
                                             .span_label(
-                                                param_span,
+                                                tcx.def_span(generics.param_at(i, tcx).def_id),
                                                 "cannot use static lifetime; use a bound lifetime \
                                                  instead or remove the lifetime parameter from the \
                                                  opaque type",
                                             )
                                             .emit();
-                                    } else {
-                                        seen.entry(region).or_default().push(param_span);
+                                        continue;
                                     }
+
+                                    true
                                 }
 
-                                ty::subst::GenericArgKind::Const(ct) => match ct.val {
-                                    ty::ConstKind::Param(_) => {}
-                                    _ => {
-                                        tcx.sess
-                                            .struct_span_err(
-                                                span,
-                                                "non-defining opaque type use \
-                                                 in defining scope",
-                                            )
-                                            .span_note(
-                                                tcx.def_span(param.def_id),
-                                                &format!(
-                                                    "used non-generic const {} for \
-                                                     generic parameter",
-                                                    ty,
-                                                ),
-                                            )
-                                            .emit();
-                                    }
-                                },
-                            } // match subst
-                        } // for (subst, param)
-                        for (_, spans) in seen {
-                            if spans.len() > 1 {
+                                GenericArgKind::Const(ct) => {
+                                    matches!(ct.val, ty::ConstKind::Param(_))
+                                }
+                            };
+
+                            if arg_is_param {
+                                seen_params.entry(arg).or_default().push(i);
+                            } else {
+                                // Prevent `fn foo() -> Foo<u32>` from being defining.
+                                let opaque_param = generics.param_at(i, tcx);
+                                tcx.sess
+                                    .struct_span_err(
+                                        span,
+                                        "non-defining opaque type use in defining scope",
+                                    )
+                                    .span_note(
+                                        tcx.def_span(opaque_param.def_id),
+                                        &format!(
+                                            "used non-generic {} `{}` for generic parameter",
+                                            opaque_param.kind.descr(),
+                                            arg,
+                                        ),
+                                    )
+                                    .emit();
+                            }
+                        } // for (arg, param)
+
+                        for (_, indices) in seen_params {
+                            if indices.len() > 1 {
+                                let descr = generics.param_at(indices[0], tcx).kind.descr();
+                                let spans: Vec<_> = indices
+                                    .into_iter()
+                                    .map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
+                                    .collect();
                                 tcx.sess
                                     .struct_span_err(
                                         span,
-                                        "non-defining opaque type use \
-                                         in defining scope",
+                                        "non-defining opaque type use in defining scope",
                                     )
-                                    .span_note(spans, "lifetime used multiple times")
+                                    .span_note(spans, &format!("{} used multiple times", descr))
                                     .emit();
                             }
                         }
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index e6099b98dc8..d45c8270068 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, Applicability, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -7,7 +7,7 @@ use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::Node;
 use rustc_middle::hir::map::Map;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
+use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
 use rustc_session::parse::feature_err;
@@ -369,13 +369,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     struct ConstraintLocator<'tcx> {
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        // (first found type span, actual type, mapping from the opaque type's generic
-        // parameters to the concrete type's generic parameters)
-        //
-        // The mapping is an index for each use site of a generic parameter in the concrete type
-        //
-        // The indices index into the generic parameters on the opaque type.
-        found: Option<(Span, Ty<'tcx>, Vec<usize>)>,
+        // (first found type span, actual type)
+        found: Option<(Span, Ty<'tcx>)>,
     }
 
     impl ConstraintLocator<'_> {
@@ -407,83 +402,51 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 
                 // FIXME(oli-obk): trace the actual span from inference to improve errors.
                 let span = self.tcx.def_span(def_id);
-                // used to quickly look up the position of a generic parameter
-                let mut index_map: FxHashMap<ty::ParamTy, usize> = FxHashMap::default();
-                // Skipping binder is ok, since we only use this to find generic parameters and
-                // their positions.
-                for (idx, subst) in substs.iter().enumerate() {
-                    if let GenericArgKind::Type(ty) = subst.unpack() {
-                        if let ty::Param(p) = ty.kind {
-                            if index_map.insert(p, idx).is_some() {
-                                // There was already an entry for `p`, meaning a generic parameter
-                                // was used twice.
-                                self.tcx.sess.span_err(
-                                    span,
-                                    &format!(
-                                        "defining opaque type use restricts opaque \
-                                         type by using the generic parameter `{}` twice",
-                                        p,
-                                    ),
-                                );
-                                return;
-                            }
-                        } else {
+
+                // HACK(eddyb) this check shouldn't be needed, as `wfcheck`
+                // performs the same checks, in theory, but I've kept it here
+                // using `delay_span_bug`, just in case `wfcheck` slips up.
+                let opaque_generics = self.tcx.generics_of(self.def_id);
+                let mut used_params: FxHashSet<_> = FxHashSet::default();
+                for (i, arg) in substs.iter().enumerate() {
+                    let arg_is_param = match arg.unpack() {
+                        GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
+                        GenericArgKind::Lifetime(lt) => {
+                            matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
+                        }
+                        GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
+                    };
+
+                    if arg_is_param {
+                        if !used_params.insert(arg) {
+                            // There was already an entry for `arg`, meaning a generic parameter
+                            // was used twice.
                             self.tcx.sess.delay_span_bug(
                                 span,
                                 &format!(
-                                    "non-defining opaque ty use in defining scope: {:?}, {:?}",
-                                    concrete_type, substs,
+                                    "defining opaque type use restricts opaque \
+                                     type by using the generic parameter `{}` twice",
+                                    arg,
                                 ),
                             );
                         }
-                    }
-                }
-                // Compute the index within the opaque type for each generic parameter used in
-                // the concrete type.
-                let indices = concrete_type
-                    .subst(self.tcx, substs)
-                    .walk()
-                    .filter_map(|t| match &t.kind {
-                        ty::Param(p) => Some(*index_map.get(p).unwrap()),
-                        _ => None,
-                    })
-                    .collect();
-                let is_param = |ty: Ty<'_>| match ty.kind {
-                    ty::Param(_) => true,
-                    _ => false,
-                };
-                let bad_substs: Vec<_> = substs
-                    .iter()
-                    .enumerate()
-                    .filter_map(|(i, k)| {
-                        if let GenericArgKind::Type(ty) = k.unpack() { Some((i, ty)) } else { None }
-                    })
-                    .filter(|(_, ty)| !is_param(ty))
-                    .collect();
-                if !bad_substs.is_empty() {
-                    let identity_substs = InternalSubsts::identity_for_item(self.tcx, self.def_id);
-                    for (i, bad_subst) in bad_substs {
-                        self.tcx.sess.span_err(
+                    } else {
+                        let param = opaque_generics.param_at(i, self.tcx);
+                        self.tcx.sess.delay_span_bug(
                             span,
                             &format!(
                                 "defining opaque type use does not fully define opaque type: \
-                            generic parameter `{}` is specified as concrete type `{}`",
-                                identity_substs.type_at(i),
-                                bad_subst
+                                 generic parameter `{}` is specified as concrete {} `{}`",
+                                param.name,
+                                param.kind.descr(),
+                                arg,
                             ),
                         );
                     }
-                } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found {
-                    let mut ty = concrete_type.walk().fuse();
-                    let mut p_ty = prev_ty.walk().fuse();
-                    let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) {
-                        // Type parameters are equal to any other type parameter for the purpose of
-                        // concrete type equality, as it is possible to obtain the same type just
-                        // by passing matching parameters to a function.
-                        (ty::Param(_), ty::Param(_)) => true,
-                        _ => t == p,
-                    });
-                    if !iter_eq || ty.next().is_some() || p_ty.next().is_some() {
+                }
+
+                if let Some((prev_span, prev_ty)) = self.found {
+                    if *concrete_type != prev_ty {
                         debug!("find_opaque_ty_constraints: span={:?}", span);
                         // Found different concrete types for the opaque type.
                         let mut err = self.tcx.sess.struct_span_err(
@@ -496,34 +459,9 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         );
                         err.span_note(prev_span, "previous use here");
                         err.emit();
-                    } else if indices != *prev_indices {
-                        // Found "same" concrete types, but the generic parameter order differs.
-                        let mut err = self.tcx.sess.struct_span_err(
-                            span,
-                            "concrete type's generic parameters differ from previous defining use",
-                        );
-                        use std::fmt::Write;
-                        let mut s = String::new();
-                        write!(s, "expected [").unwrap();
-                        let list = |s: &mut String, indices: &Vec<usize>| {
-                            let mut indices = indices.iter().cloned();
-                            if let Some(first) = indices.next() {
-                                write!(s, "`{}`", substs[first]).unwrap();
-                                for i in indices {
-                                    write!(s, ", `{}`", substs[i]).unwrap();
-                                }
-                            }
-                        };
-                        list(&mut s, prev_indices);
-                        write!(s, "], got [").unwrap();
-                        list(&mut s, &indices);
-                        write!(s, "]").unwrap();
-                        err.span_label(span, s);
-                        err.span_note(prev_span, "previous use here");
-                        err.emit();
                     }
                 } else {
-                    self.found = Some((span, concrete_type, indices));
+                    self.found = Some((span, concrete_type));
                 }
             } else {
                 debug!(
@@ -606,7 +544,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     }
 
     match locator.found {
-        Some((_, ty, _)) => ty,
+        Some((_, ty)) => ty,
         None => {
             let span = tcx.def_span(def_id);
             tcx.sess.span_err(span, "could not find defining uses");
diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs
index 1becb1e83a5..0a4cc9b7fe8 100644
--- a/src/test/ui/type-alias-impl-trait/bound_reduction2.rs
+++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.rs
@@ -8,13 +8,12 @@ trait TraitWithAssoc {
 }
 
 type Foo<V> = impl Trait<V>;
-//~^ ERROR could not find defining uses
-//~| ERROR the trait bound `T: TraitWithAssoc` is not satisfied
+//~^ ERROR the trait bound `T: TraitWithAssoc` is not satisfied
 
 trait Trait<U> {}
 
 impl<W> Trait<W> for () {}
 
-fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR does not fully define
+fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
     ()
 }
diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
index aff558569ea..b871f79aa1d 100644
--- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
+++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
@@ -9,20 +9,6 @@ help: consider further restricting this bound
 LL | fn foo_desugared<T: TraitWithAssoc + TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
    |                                    ^^^^^^^^^^^^^^^^
 
-error: defining opaque type use does not fully define opaque type: generic parameter `V` is specified as concrete type `<T as TraitWithAssoc>::Assoc`
-  --> $DIR/bound_reduction2.rs:18:1
-   |
-LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
-LL | |     ()
-LL | | }
-   | |_^
-
-error: could not find defining uses
-  --> $DIR/bound_reduction2.rs:10:1
-   |
-LL | type Foo<V> = impl Trait<V>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
index 165e320be5e..4503607a836 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
@@ -1,14 +1,26 @@
-#![feature(type_alias_impl_trait)]
+#![feature(type_alias_impl_trait, const_generics)]
+#![allow(incomplete_features)]
 
 use std::fmt::Debug;
 
 fn main() {}
 
 // test that unused generic parameters are ok
-type Two<T, U> = impl Debug;
-//~^ could not find defining uses
+type TwoTys<T, U> = impl Debug;
+type TwoLifetimes<'a, 'b> = impl Debug;
+type TwoConsts<const X: usize, const Y: usize> = impl Debug;
 
-fn one<T: Debug>(t: T) -> Two<T, T> {
-//~^ ERROR defining opaque type use restricts opaque type
+fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
+//~^ ERROR non-defining opaque type use in defining scope
+    t
+}
+
+fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
+//~^ ERROR non-defining opaque type use in defining scope
+    t
+}
+
+fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
+//~^ ERROR non-defining opaque type use in defining scope
     t
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
index e1794034e20..b4757e2763d 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
@@ -1,17 +1,38 @@
-error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
-  --> $DIR/generic_duplicate_param_use.rs:11:1
-   |
-LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
-LL | |
-LL | |     t
-LL | | }
-   | |_^
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_duplicate_param_use.rs:13:30
+   |
+LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
+   |                              ^^^^^^^^^^^^
+   |
+note: type used multiple times
+  --> $DIR/generic_duplicate_param_use.rs:9:13
+   |
+LL | type TwoTys<T, U> = impl Debug;
+   |             ^  ^
 
-error: could not find defining uses
-  --> $DIR/generic_duplicate_param_use.rs:8:1
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_duplicate_param_use.rs:18:36
+   |
+LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
+   |                                    ^^^^^^^^^^^^^^^^^^^^
+   |
+note: lifetime used multiple times
+  --> $DIR/generic_duplicate_param_use.rs:10:19
+   |
+LL | type TwoLifetimes<'a, 'b> = impl Debug;
+   |                   ^^  ^^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_duplicate_param_use.rs:23:50
+   |
+LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
+   |                                                  ^^^^^^^^^^^^^^^
+   |
+note: constant used multiple times
+  --> $DIR/generic_duplicate_param_use.rs:11:22
    |
-LL | type Two<T, U> = impl Debug;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
+   |                      ^               ^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
index 0adce817c5c..2b98d8fc63a 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
@@ -8,10 +8,10 @@ fn main() {}
 type Two<T, U> = impl Debug;
 
 fn one<T: Debug>(t: T) -> Two<T, T> {
-//~^ defining opaque type use restricts opaque type
     t
 }
 
 fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+//~^ ERROR concrete type differs from previous defining opaque type use
     t
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
index a9a51fa0b4b..8170c671f68 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
@@ -1,8 +1,16 @@
-error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/generic_duplicate_param_use2.rs:14:1
+   |
+LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+LL | |
+LL | |     t
+LL | | }
+   | |_^ expected `U`, got `T`
+   |
+note: previous use here
   --> $DIR/generic_duplicate_param_use2.rs:10:1
    |
 LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
-LL | |
 LL | |     t
 LL | | }
    | |_^
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
index 8d3e7f9f424..d9133fd11f7 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
@@ -8,15 +8,14 @@ fn main() {}
 type Two<T, U> = impl Debug;
 
 fn one<T: Debug>(t: T) -> Two<T, T> {
-//~^ defining opaque type use restricts opaque type
     t
 }
 
 fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+//~^ ERROR concrete type differs from previous defining opaque type use
     t
 }
 
 fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
-//~^ concrete type's generic parameters differ from previous defining use
     u
 }
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
index 04dcdc295f9..86dd3368400 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
@@ -1,28 +1,19 @@
-error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
-  --> $DIR/generic_duplicate_param_use3.rs:10:1
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/generic_duplicate_param_use3.rs:14:1
    |
-LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
+LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
 LL | |
 LL | |     t
 LL | | }
-   | |_^
-
-error: concrete type's generic parameters differ from previous defining use
-  --> $DIR/generic_duplicate_param_use3.rs:19:1
-   |
-LL | / fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
-LL | |
-LL | |     u
-LL | | }
-   | |_^ expected [`T`], got [`U`]
+   | |_^ expected `U`, got `T`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use3.rs:15:1
+  --> $DIR/generic_duplicate_param_use3.rs:10:1
    |
-LL | / fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
 LL | |     t
 LL | | }
    | |_^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
index 65f7d7f485d..40388c3b6c8 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
@@ -8,7 +8,7 @@ fn main() {}
 type Two<T, U> = impl Debug;
 
 fn one<T: Debug>(t: T) -> Two<T, T> {
-//~^ ERROR defining opaque type use restricts opaque type
+//~^ ERROR non-defining opaque type use in defining scope
     t
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
index 082177b8212..fcf01f5164a 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
@@ -1,11 +1,14 @@
-error: defining opaque type use restricts opaque type by using the generic parameter `T` twice
-  --> $DIR/generic_duplicate_param_use4.rs:10:1
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_duplicate_param_use4.rs:10:27
    |
-LL | / fn one<T: Debug>(t: T) -> Two<T, T> {
-LL | |
-LL | |     t
-LL | | }
-   | |_^
+LL | fn one<T: Debug>(t: T) -> Two<T, T> {
+   |                           ^^^^^^^^^
+   |
+note: type used multiple times
+  --> $DIR/generic_duplicate_param_use4.rs:8:10
+   |
+LL | type Two<T, U> = impl Debug;
+   |          ^  ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs
index 60106eba175..b1782120f84 100644
--- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs
@@ -1,13 +1,27 @@
-#![feature(type_alias_impl_trait)]
+#![feature(type_alias_impl_trait, const_generics)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
 
 fn main() {}
 
-type Cmp<T> = impl 'static;
-//~^ ERROR could not find defining uses
-//~^^ ERROR: at least one trait must be specified
+type OneTy<T> = impl Debug;
+type OneLifetime<'a> = impl Debug;
+type OneConst<const X: usize> = impl Debug;
 
+// Not defining uses, because they doesn't define *all* possible generics.
 
-// not a defining use, because it doesn't define *all* possible generics
-fn cmp() -> Cmp<u32> { //~ ERROR defining opaque type use does not fully define
+fn concrete_ty() -> OneTy<u32> {
+//~^ ERROR non-defining opaque type use in defining scope
     5u32
 }
+
+fn concrete_lifetime() -> OneLifetime<'static> {
+//~^ ERROR non-defining opaque type use in defining scope
+    6u32
+}
+
+fn concrete_const() -> OneConst<{123}> {
+//~^ ERROR non-defining opaque type use in defining scope
+    7u32
+}
diff --git a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
index b952aaa79cc..b0ffc4a5ef6 100644
--- a/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
@@ -1,22 +1,35 @@
-error: at least one trait must be specified
-  --> $DIR/generic_nondefining_use.rs:5:15
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_nondefining_use.rs:14:21
    |
-LL | type Cmp<T> = impl 'static;
-   |               ^^^^^^^^^^^^
+LL | fn concrete_ty() -> OneTy<u32> {
+   |                     ^^^^^^^^^^
+   |
+note: used non-generic type `u32` for generic parameter
+  --> $DIR/generic_nondefining_use.rs:8:12
+   |
+LL | type OneTy<T> = impl Debug;
+   |            ^
 
-error: defining opaque type use does not fully define opaque type: generic parameter `T` is specified as concrete type `u32`
-  --> $DIR/generic_nondefining_use.rs:11:1
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_nondefining_use.rs:19:27
    |
-LL | / fn cmp() -> Cmp<u32> {
-LL | |     5u32
-LL | | }
-   | |_^
+LL | type OneLifetime<'a> = impl Debug;
+   |                  -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+...
+LL | fn concrete_lifetime() -> OneLifetime<'static> {
+   |                           ^^^^^^^^^^^^^^^^^^^^
 
-error: could not find defining uses
-  --> $DIR/generic_nondefining_use.rs:5:1
+error: non-defining opaque type use in defining scope
+  --> $DIR/generic_nondefining_use.rs:24:24
+   |
+LL | fn concrete_const() -> OneConst<{123}> {
+   |                        ^^^^^^^^^^^^^^^
+   |
+note: used non-generic constant `123usize` for generic parameter
+  --> $DIR/generic_nondefining_use.rs:10:21
    |
-LL | type Cmp<T> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | type OneConst<const X: usize> = impl Debug;
+   |                     ^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs
index 73acc92172b..4eb7f7836d8 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs
@@ -6,7 +6,6 @@ trait IterBits {
 }
 
 type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-//~^ ERROR could not find defining uses
 
 impl<T: Copy, E> IterBits for T
 where
@@ -18,7 +17,8 @@ where
 {
     type BitsIter = IterBitsIter<T, E, u8>;
     fn iter_bits(self, n: u8) -> Self::BitsIter {
-    //~^ ERROR defining opaque type use does not fully define opaque type
+    //~^ ERROR non-defining opaque type use in defining scope
+    //~| ERROR non-defining opaque type use in defining scope
         (0u8..n)
             .rev()
             .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
index 9de3e759e15..55984609437 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
@@ -1,19 +1,26 @@
-error: defining opaque type use does not fully define opaque type: generic parameter `I` is specified as concrete type `u8`
-  --> $DIR/issue-60564.rs:20:5
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-60564.rs:19:34
    |
-LL | /     fn iter_bits(self, n: u8) -> Self::BitsIter {
-LL | |
-LL | |         (0u8..n)
-LL | |             .rev()
-LL | |             .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
-LL | |     }
-   | |_____^
+LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
+   |                                  ^^^^^^^^^^^^^^
+   |
+note: used non-generic type `_` for generic parameter
+  --> $DIR/issue-60564.rs:8:22
+   |
+LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
+   |                      ^
 
-error: could not find defining uses
-  --> $DIR/issue-60564.rs:8:1
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-60564.rs:19:34
+   |
+LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
+   |                                  ^^^^^^^^^^^^^^
+   |
+note: used non-generic type `u8` for generic parameter
+  --> $DIR/issue-60564.rs:8:25
    |
 LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
index d00f8d7a901..3b6decbe9c6 100644
--- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
@@ -4,9 +4,9 @@
 
 #![feature(type_alias_impl_trait)]
 trait Trait<T> {}
-type Alias<'a, U> = impl Trait<U>; //~ ERROR could not find defining uses
+type Alias<'a, U> = impl Trait<U>;
 fn f<'a>() -> Alias<'a, ()> {}
-//~^ ERROR defining opaque type use does not fully define opaque type: generic parameter `U`
+//~^ ERROR non-defining opaque type use in defining scope
 
 fn main() {}
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
index b585942406f..c2fa54f50f8 100644
--- a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
@@ -1,14 +1,14 @@
-error: defining opaque type use does not fully define opaque type: generic parameter `U` is specified as concrete type `()`
-  --> $DIR/issue-68368-non-defining-use.rs:8:1
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-68368-non-defining-use.rs:8:15
    |
 LL | fn f<'a>() -> Alias<'a, ()> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/issue-68368-non-defining-use.rs:7:1
+   |               ^^^^^^^^^^^^^
+   |
+note: used non-generic type `()` for generic parameter
+  --> $DIR/issue-68368-non-defining-use.rs:7:16
    |
 LL | type Alias<'a, U> = impl Trait<U>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                ^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs
index ca00e582d34..02485b24e7b 100644
--- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs
+++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.rs
@@ -7,7 +7,6 @@ fn main() {}
 type Two<T, U> = impl Debug;
 
 fn two<T: Debug>(t: T) -> Two<T, u32> {
-    //~^ ERROR defining opaque type use does not fully define opaque type
     (t, 4i8)
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
index d68f1bd30a0..cce861b76c9 100644
--- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
+++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
@@ -1,14 +1,5 @@
-error: defining opaque type use does not fully define opaque type: generic parameter `U` is specified as concrete type `u32`
-  --> $DIR/not_a_defining_use.rs:9:1
-   |
-LL | / fn two<T: Debug>(t: T) -> Two<T, u32> {
-LL | |
-LL | |     (t, 4i8)
-LL | | }
-   | |_^
-
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/not_a_defining_use.rs:30:1
+  --> $DIR/not_a_defining_use.rs:29:1
    |
 LL | / fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
 LL | |     (t, <U as Bar>::FOO)
@@ -16,12 +7,12 @@ LL | | }
    | |_^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
    |
 note: previous use here
-  --> $DIR/not_a_defining_use.rs:14:1
+  --> $DIR/not_a_defining_use.rs:9:1
    |
-LL | / fn three<T: Debug, U>(t: T) -> Two<T, U> {
-LL | |     (t, 5i8)
+LL | / fn two<T: Debug>(t: T) -> Two<T, u32> {
+LL | |     (t, 4i8)
 LL | | }
    | |_^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error