]> git.lizzy.rs Git - rust.git/commitdiff
Check that TAIT generics are fully generic in mir typeck instead of wf-check, as...
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 16 Sep 2021 19:08:25 +0000 (19:08 +0000)
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 23 Sep 2021 13:35:16 +0000 (13:35 +0000)
33 files changed:
compiler/rustc_borrowck/src/region_infer/opaque_types.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/collect/type_of.rs
src/test/ui/type-alias-impl-trait/bound_reduction2.rs
src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs
src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
src/test/ui/type-alias-impl-trait/incomplete-inference.rs
src/test/ui/type-alias-impl-trait/incomplete-inference.stderr
src/test/ui/type-alias-impl-trait/issue-60371.rs
src/test/ui/type-alias-impl-trait/issue-60371.stderr
src/test/ui/type-alias-impl-trait/issue-60564.rs
src/test/ui/type-alias-impl-trait/issue-60564.stderr
src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
src/test/ui/type-alias-impl-trait/not_a_defining_use.rs
src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr

index d790e31105c8aa2f2ee20c82662dce9c1a473959..b35e76b96ad9194423b0a145e6d3bd8604d96df7 100644 (file)
@@ -1,5 +1,9 @@
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::vec_map::VecMap;
+use rustc_hir::OpaqueTyOrigin;
+use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
 use rustc_infer::infer::InferCtxt;
+use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 use rustc_trait_selection::opaque_types::InferCtxtExt;
@@ -50,13 +54,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(crate) fn infer_opaque_types(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
-        opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
+        opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
         span: Span,
     ) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
         opaque_ty_decls
             .into_iter()
-            .map(|(opaque_type_key, concrete_type)| {
+            .filter_map(|(opaque_type_key, decl)| {
                 let substs = opaque_type_key.substs;
+                let concrete_type = decl.concrete_ty;
                 debug!(?concrete_type, ?substs);
 
                 let mut subst_regions = vec![self.universal_regions.fr_static];
@@ -94,7 +99,13 @@ pub(crate) fn infer_opaque_types(
                     universal_concrete_type,
                     span,
                 );
-                (opaque_type_key, remapped_type)
+
+                check_opaque_type_parameter_valid(
+                    infcx.tcx,
+                    opaque_type_key,
+                    OpaqueTypeDecl { concrete_ty: remapped_type, ..decl },
+                )
+                .then_some((opaque_type_key, remapped_type))
             })
             .collect()
     }
@@ -119,3 +130,95 @@ pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
         })
     }
 }
+
+fn check_opaque_type_parameter_valid(
+    tcx: TyCtxt<'_>,
+    opaque_type_key: OpaqueTypeKey<'_>,
+    decl: OpaqueTypeDecl<'_>,
+) -> bool {
+    match decl.origin {
+        // No need to check return position impl trait (RPIT)
+        // because for type and const parameters they are correct
+        // by construction: we convert
+        //
+        // fn foo<P0..Pn>() -> impl Trait
+        //
+        // into
+        //
+        // type Foo<P0...Pn>
+        // fn foo<P0..Pn>() -> Foo<P0...Pn>.
+        //
+        // For lifetime parameters we convert
+        //
+        // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
+        //
+        // into
+        //
+        // type foo::<'p0..'pn>::Foo<'q0..'qm>
+        // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
+        //
+        // which would error here on all of the `'static` args.
+        OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true,
+        // Check these
+        OpaqueTyOrigin::TyAlias => {}
+    }
+    let span = decl.definition_span;
+    let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
+    let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
+    for (i, arg) in opaque_type_key.substs.iter().enumerate() {
+        let arg_is_param = match arg.unpack() {
+            GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
+            GenericArgKind::Lifetime(ty::ReStatic) => {
+                tcx.sess
+                    .struct_span_err(span, "non-defining opaque type use in defining scope")
+                    .span_label(
+                        tcx.def_span(opaque_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();
+                return false;
+            }
+            GenericArgKind::Lifetime(lt) => {
+                matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
+            }
+            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 = opaque_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();
+            return false;
+        }
+    }
+
+    for (_, indices) in seen_params {
+        if indices.len() > 1 {
+            let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
+            let spans: Vec<_> = indices
+                .into_iter()
+                .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
+                .collect();
+            tcx.sess
+                .struct_span_err(span, "non-defining opaque type use in defining scope")
+                .span_note(spans, &format!("{} used multiple times", descr))
+                .emit();
+            return false;
+        }
+    }
+    true
+}
index 5ccf380602554bfed8eb5c3b2b75b24f489861a8..3e536eb845f620eb50f72d0800f5e2795d45dd39 100644 (file)
@@ -14,6 +14,7 @@
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
+use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{
@@ -193,16 +194,17 @@ pub(crate) fn type_check<'mir, 'tcx>(
 
             opaque_type_values
                 .into_iter()
-                .filter_map(|(opaque_type_key, decl)| {
-                    let mut revealed_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
-                    if revealed_ty.has_infer_types_or_consts() {
+                .filter_map(|(opaque_type_key, mut decl)| {
+                    decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
+                    if decl.concrete_ty.has_infer_types_or_consts() {
                         infcx.tcx.sess.delay_span_bug(
                             body.span,
-                            &format!("could not resolve {:#?}", revealed_ty.kind()),
+                            &format!("could not resolve {:#?}", decl.concrete_ty.kind()),
                         );
-                        revealed_ty = infcx.tcx.ty_error();
+                        decl.concrete_ty = infcx.tcx.ty_error();
                     }
-                    let concrete_is_opaque = if let ty::Opaque(def_id, _) = revealed_ty.kind() {
+                    let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_ty.kind()
+                    {
                         *def_id == opaque_type_key.def_id
                     } else {
                         false
@@ -234,7 +236,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
                         );
                         None
                     } else {
-                        Some((opaque_type_key, revealed_ty))
+                        Some((opaque_type_key, decl))
                     }
                 })
                 .collect()
@@ -890,7 +892,7 @@ struct BorrowCheckContext<'a, 'tcx> {
 crate struct MirTypeckResults<'tcx> {
     crate constraints: MirTypeckRegionConstraints<'tcx>,
     crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-    crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
+    crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
 }
 
 /// A collection of region constraints that must be satisfied for the
index c01faae5d6a51c039f088df9aff6f0a7b5e782a7..028f6e89f18f127eac726cb7177d1ca8d72373ee 100644 (file)
@@ -1062,11 +1062,7 @@ fn fold_opaque_ty(
 /// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
 /// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
 /// For the above example, this function returns `true` for `f1` and `false` for `f2`.
-pub fn may_define_opaque_type(
-    tcx: TyCtxt<'_>,
-    def_id: LocalDefId,
-    opaque_hir_id: hir::HirId,
-) -> bool {
+fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
     let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
     // Named opaque types can be defined by any siblings or children of siblings.
index cb07fcf5fef5813fba8341be925567b9d55df4cc..01ec801228e2e8f0d35e3e931e94d83f4338b5cd 100644 (file)
@@ -2,7 +2,7 @@
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
 use rustc_ast as ast;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -12,7 +12,7 @@
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
 use rustc_middle::hir::map as hir_map;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
+use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
     self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
@@ -20,7 +20,6 @@
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
-use rustc_trait_selection::opaque_types::may_define_opaque_type;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
 
@@ -77,14 +76,14 @@ fn with_fcx<F>(&mut self, f: F)
 /// We do this check as a pre-pass before checking fn bodies because if these constraints are
 /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
 /// the types first.
+#[instrument(skip(tcx), level = "debug")]
 pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let item = tcx.hir().expect_item(hir_id);
 
     debug!(
-        "check_item_well_formed(it.def_id={:?}, it.name={})",
-        item.def_id,
-        tcx.def_path_str(def_id.to_def_id())
+        ?item.def_id,
+        item.name = ? tcx.def_path_str(def_id.to_def_id())
     );
 
     match item.kind {
@@ -557,8 +556,9 @@ fn check_type_defn<'tcx, F>(
     });
 }
 
+#[instrument(skip(tcx, item))]
 fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
-    debug!("check_trait: {:?}", item.def_id);
+    debug!(?item.def_id);
 
     let trait_def = tcx.trait_def(item.def_id);
     if trait_def.is_marker
@@ -712,13 +712,13 @@ fn check_impl<'tcx>(
 }
 
 /// Checks where-clauses and inline bounds that are declared on `def_id`.
+#[instrument(skip(fcx), level = "debug")]
 fn check_where_clauses<'tcx, 'fcx>(
     fcx: &FnCtxt<'fcx, 'tcx>,
     span: Span,
     def_id: DefId,
     return_ty: Option<(Ty<'tcx>, Span)>,
 ) {
-    debug!("check_where_clauses(def_id={:?}, return_ty={:?})", def_id, return_ty);
     let tcx = fcx.tcx;
 
     let predicates = tcx.predicates_of(def_id);
@@ -888,17 +888,15 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
 
     let predicates = predicates.instantiate_identity(tcx);
 
-    if let Some((mut return_ty, span)) = return_ty {
+    if let Some((return_ty, _)) = return_ty {
         if return_ty.has_infer_types_or_consts() {
             fcx.select_obligations_where_possible(false, |_| {});
-            return_ty = fcx.resolve_vars_if_possible(return_ty);
         }
-        check_opaque_types(fcx, def_id.expect_local(), span, return_ty);
     }
 
     let predicates = fcx.normalize_associated_types_in(span, predicates);
 
-    debug!("check_where_clauses: predicates={:?}", predicates.predicates);
+    debug!(?predicates.predicates);
     assert_eq!(predicates.predicates.len(), predicates.spans.len());
     let wf_obligations =
         iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| {
@@ -984,143 +982,6 @@ fn check_fn_or_method<'fcx, 'tcx>(
     check_where_clauses(fcx, span, def_id, Some((sig.output(), hir_decl.output.span())));
 }
 
-/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
-/// laid for "higher-order pattern unification".
-/// This ensures that inference is tractable.
-/// In particular, definitions of opaque types can only use other generics as arguments,
-/// and they cannot repeat an argument. Example:
-///
-/// ```rust
-/// type Foo<A, B> = impl Bar<A, B>;
-///
-/// // Okay -- `Foo` is applied to two distinct, generic types.
-/// fn a<T, U>() -> Foo<T, U> { .. }
-///
-/// // Not okay -- `Foo` is applied to `T` twice.
-/// fn b<T>() -> Foo<T, T> { .. }
-///
-/// // Not okay -- `Foo` is applied to a non-generic type.
-/// fn b<T>() -> Foo<T, u32> { .. }
-/// ```
-///
-fn check_opaque_types<'fcx, 'tcx>(
-    fcx: &FnCtxt<'fcx, 'tcx>,
-    fn_def_id: LocalDefId,
-    span: Span,
-    ty: Ty<'tcx>,
-) {
-    trace!("check_opaque_types(fn_def_id={:?}, ty={:?})", fn_def_id, ty);
-    let tcx = fcx.tcx;
-
-    ty.fold_with(&mut ty::fold::BottomUpFolder {
-        tcx,
-        ty_op: |ty| {
-            if let ty::Opaque(def_id, substs) = *ty.kind() {
-                trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
-                let generics = tcx.generics_of(def_id);
-
-                let opaque_hir_id = if let Some(local_id) = def_id.as_local() {
-                    tcx.hir().local_def_id_to_hir_id(local_id)
-                } else {
-                    // Opaque types from other crates won't have defining uses in this crate.
-                    return ty;
-                };
-                if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) =
-                    tcx.hir().expect_item(opaque_hir_id).kind
-                {
-                    // No need to check return position impl trait (RPIT)
-                    // because for type and const parameters they are correct
-                    // by construction: we convert
-                    //
-                    // fn foo<P0..Pn>() -> impl Trait
-                    //
-                    // into
-                    //
-                    // type Foo<P0...Pn>
-                    // fn foo<P0..Pn>() -> Foo<P0...Pn>.
-                    //
-                    // For lifetime parameters we convert
-                    //
-                    // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
-                    //
-                    // into
-                    //
-                    // type foo::<'p0..'pn>::Foo<'q0..'qm>
-                    // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
-                    //
-                    // which would error here on all of the `'static` args.
-                    return ty;
-                }
-                if !may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
-                    return ty;
-                }
-                trace!("check_opaque_types: may define, generics={:#?}", generics);
-                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(_)),
-
-                        GenericArgKind::Lifetime(region) if let ty::ReStatic = region => {
-                            tcx.sess
-                                .struct_span_err(
-                                    span,
-                                    "non-defining opaque type use in defining scope",
-                                )
-                                .span_label(
-                                    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();
-                            continue;
-                        }
-
-                        GenericArgKind::Lifetime(_) => true,
-
-                        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")
-                            .span_note(spans, &format!("{} used multiple times", descr))
-                            .emit();
-                    }
-                }
-            } // if let Opaque
-            ty
-        },
-        lt_op: |lt| lt,
-        ct_op: |ct| ct,
-    });
-}
-
 const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
      `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
      of the previous types except `Self`)";
@@ -1439,20 +1300,23 @@ fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
         hir_visit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
     }
 
+    #[instrument(skip(self, i), level = "debug")]
     fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
-        debug!("visit_item: {:?}", i);
+        trace!(?i);
         self.tcx.ensure().check_item_well_formed(i.def_id);
         hir_visit::walk_item(self, i);
     }
 
+    #[instrument(skip(self, trait_item), level = "debug")]
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        debug!("visit_trait_item: {:?}", trait_item);
+        trace!(?trait_item);
         self.tcx.ensure().check_trait_item_well_formed(trait_item.def_id);
         hir_visit::walk_trait_item(self, trait_item);
     }
 
+    #[instrument(skip(self, impl_item), level = "debug")]
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        debug!("visit_impl_item: {:?}", impl_item);
+        trace!(?impl_item);
         self.tcx.ensure().check_impl_item_well_formed(impl_item.def_id);
         hir_visit::walk_impl_item(self, impl_item);
     }
index 7f9afaae0eaa2675f8273aaf32af2ee7e9c5a53b..7a14d7f3d283d0afe0a412a4c49cd2bd447dfd8c 100644 (file)
@@ -1,4 +1,3 @@
-use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, ErrorReported, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -7,7 +6,7 @@
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{HirId, Node};
 use rustc_middle::hir::map::Map;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, SubstsRef};
+use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_span::symbol::Ident;
@@ -539,6 +538,25 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 }
 
 #[instrument(skip(tcx), level = "debug")]
+/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
+/// laid for "higher-order pattern unification".
+/// This ensures that inference is tractable.
+/// In particular, definitions of opaque types can only use other generics as arguments,
+/// and they cannot repeat an argument. Example:
+///
+/// ```rust
+/// type Foo<A, B> = impl Bar<A, B>;
+///
+/// // Okay -- `Foo` is applied to two distinct, generic types.
+/// fn a<T, U>() -> Foo<T, U> { .. }
+///
+/// // Not okay -- `Foo` is applied to `T` twice.
+/// fn b<T>() -> Foo<T, T> { .. }
+///
+/// // Not okay -- `Foo` is applied to a non-generic type.
+/// fn b<T>() -> Foo<T, u32> { .. }
+/// ```
+///
 fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
     use rustc_hir::{Expr, ImplItem, Item, TraitItem};
 
@@ -584,50 +602,8 @@ fn check(&mut self, def_id: LocalDefId) {
                 // FIXME(oli-obk): trace the actual span from inference to improve errors.
                 let span = self.tcx.def_span(def_id);
 
-                // 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 opaque_type_key.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!(
-                                    "defining opaque type use restricts opaque \
-                                     type by using the generic parameter `{}` twice",
-                                    arg,
-                                ),
-                            );
-                        }
-                    } 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 {} `{}`",
-                                param.name,
-                                param.kind.descr(),
-                                arg,
-                            ),
-                        );
-                    }
-                }
-
                 if let Some((prev_span, prev_ty)) = self.found {
-                    if *concrete_type != prev_ty {
+                    if *concrete_type != prev_ty && !(*concrete_type, prev_ty).references_error() {
                         debug!(?span);
                         // Found different concrete types for the opaque type.
                         let mut err = self.tcx.sess.struct_span_err(
index a15074c35936bb2d10cd04ac5d8b5cb27908c086..579067340e85cb72df1cb5775ab0d5df604afdf9 100644 (file)
@@ -7,6 +7,7 @@ trait TraitWithAssoc {
 }
 
 type Foo<V> = impl Trait<V>;
+//~^ ERROR could not find defining uses
 
 trait Trait<U> {}
 
@@ -14,5 +15,9 @@ impl<W> Trait<W> for () {}
 
 fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
     //~^ ERROR non-defining opaque type use in defining scope
+    //~| ERROR non-defining opaque type use in defining scope
+    //~| ERROR non-defining opaque type use in defining scope
+    //~| ERROR `T` is part of concrete type but not used in parameter list
+    //~| ERROR `T` is part of concrete type but not used in parameter list
     ()
 }
index c9d6a43b9094ace0c5ea08b930d92eca1f44439a..a77c0000f12e1a0571b4a3710747e7104226243f 100644 (file)
@@ -1,8 +1,34 @@
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+  --> $DIR/bound_reduction2.rs:16:60
+   |
+LL |   fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+   |  ____________________________________________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     ()
+LL | | }
+   | |_^
+
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+  --> $DIR/bound_reduction2.rs:16:60
+   |
+LL |   fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+   |  ____________________________________________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     ()
+LL | | }
+   | |_^
+
 error: non-defining opaque type use in defining scope
-  --> $DIR/bound_reduction2.rs:15:46
+  --> $DIR/bound_reduction2.rs:16:1
    |
 LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
-   |                                              ^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
   --> $DIR/bound_reduction2.rs:9:10
@@ -10,5 +36,35 @@ note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
 LL | type Foo<V> = impl Trait<V>;
    |          ^
 
-error: aborting due to previous error
+error: non-defining opaque type use in defining scope
+  --> $DIR/bound_reduction2.rs:16:1
+   |
+LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: used non-generic type `_` for generic parameter
+  --> $DIR/bound_reduction2.rs:9:10
+   |
+LL | type Foo<V> = impl Trait<V>;
+   |          ^
+
+error: non-defining opaque type use in defining scope
+  --> $DIR/bound_reduction2.rs:16:1
+   |
+LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: used non-generic type `_` for generic parameter
+  --> $DIR/bound_reduction2.rs:9:10
+   |
+LL | type Foo<V> = impl Trait<V>;
+   |          ^
+
+error: could not find defining uses
+  --> $DIR/bound_reduction2.rs:9:15
+   |
+LL | type Foo<V> = impl Trait<V>;
+   |               ^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
 
index 31f992976b1898ccd7cc71773c6b95669560a24a..885aae619d6a2bf5249b79df995508a4a63b336b 100644 (file)
@@ -3,6 +3,7 @@
 fn main() {}
 
 type Two<'a, 'b> = impl std::fmt::Debug;
+//~^ ERROR could not find defining uses
 
 fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
     //~^ ERROR non-defining opaque type use
index 08b26b8fc1307de927f4d60bccb3e2675ce23791..b99c6a51f4b1d24faa3cf2984eb3d9ff09da53ec 100644 (file)
@@ -1,5 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_lifetime_param.rs:7:26
+  --> $DIR/generic_duplicate_lifetime_param.rs:8:26
    |
 LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
    |                          ^^^^^^^^^^^
@@ -10,5 +10,11 @@ note: lifetime used multiple times
 LL | type Two<'a, 'b> = impl std::fmt::Debug;
    |          ^^  ^^
 
-error: aborting due to previous error
+error: could not find defining uses
+  --> $DIR/generic_duplicate_lifetime_param.rs:5:20
+   |
+LL | type Two<'a, 'b> = impl std::fmt::Debug;
+   |                    ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
index a4e40f516dcefd7bd9769f58d4cf479afc883a5f..33cd2f6ba07539da18608740f78f3efa94f4de54 100644 (file)
@@ -6,8 +6,11 @@ fn main() {}
 
 // test that unused generic parameters are ok
 type TwoTys<T, U> = impl Debug;
+//~^ ERROR could not find defining uses
 type TwoLifetimes<'a, 'b> = impl Debug;
+//~^ ERROR could not find defining uses
 type TwoConsts<const X: usize, const Y: usize> = impl Debug;
+//~^ ERROR could not find defining uses
 
 fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
     //~^ ERROR non-defining opaque type use in defining scope
index 641cce26d99446027b948a3fb02c4f15f641ac8d..52c60d1777e49131ecfc4b132c9096dd71b700bb 100644 (file)
@@ -1,5 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:12:30
+  --> $DIR/generic_duplicate_param_use.rs:15:30
    |
 LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
    |                              ^^^^^^^^^^^^
@@ -10,29 +10,47 @@ note: type used multiple times
 LL | type TwoTys<T, U> = impl Debug;
    |             ^  ^
 
+error: could not find defining uses
+  --> $DIR/generic_duplicate_param_use.rs:8:21
+   |
+LL | type TwoTys<T, U> = impl Debug;
+   |                     ^^^^^^^^^^
+
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:17:36
+  --> $DIR/generic_duplicate_param_use.rs:20:36
    |
 LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
    |                                    ^^^^^^^^^^^^^^^^^^^^
    |
 note: lifetime used multiple times
-  --> $DIR/generic_duplicate_param_use.rs:9:19
+  --> $DIR/generic_duplicate_param_use.rs:10:19
    |
 LL | type TwoLifetimes<'a, 'b> = impl Debug;
    |                   ^^  ^^
 
+error: could not find defining uses
+  --> $DIR/generic_duplicate_param_use.rs:10:29
+   |
+LL | type TwoLifetimes<'a, 'b> = impl Debug;
+   |                             ^^^^^^^^^^
+
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:22:50
+  --> $DIR/generic_duplicate_param_use.rs:25: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:10:22
+  --> $DIR/generic_duplicate_param_use.rs:12:22
    |
 LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
    |                      ^               ^
 
-error: aborting due to 3 previous errors
+error: could not find defining uses
+  --> $DIR/generic_duplicate_param_use.rs:12:50
+   |
+LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
+   |                                                  ^^^^^^^^^^
+
+error: aborting due to 6 previous errors
 
index a74731df69515f05d454255d9746e4fed54d9845..04fb57b39c052c3467fb45d3a7a3ab6cde829cc1 100644 (file)
@@ -6,6 +6,7 @@ fn main() {}
 
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
 
 fn one<T: Debug>(t: T) -> Two<T, T> {
     //~^ ERROR non-defining opaque type use in defining scope
index d87e8c5783b65e1020d8b275a000b90171239f26..fca9b70d1844173127303eb69e8b2ca171e5a9c3 100644 (file)
@@ -1,5 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use2.rs:10:27
+  --> $DIR/generic_duplicate_param_use2.rs:11:27
    |
 LL | fn one<T: Debug>(t: T) -> Two<T, T> {
    |                           ^^^^^^^^^
@@ -10,5 +10,17 @@ note: type used multiple times
 LL | type Two<T, U> = impl Debug;
    |          ^  ^
 
-error: aborting due to previous error
+error[E0277]: `T` doesn't implement `Debug`
+  --> $DIR/generic_duplicate_param_use2.rs:8:18
+   |
+LL | type Two<T, U> = impl Debug;
+   |                  ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | type Two<T: std::fmt::Debug, U> = impl Debug;
+   |           +++++++++++++++++
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
index 0597b8385d25255673bdc496fad0fd92b64f9fc5..1a755d3902612f125a17b5f5477634743baf941a 100644 (file)
@@ -6,6 +6,7 @@ fn main() {}
 
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
 
 fn one<T: Debug>(t: T) -> Two<T, T> {
     //~^ ERROR non-defining opaque type use in defining scope
@@ -17,5 +18,6 @@ fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
 }
 
 fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+    //~^ ERROR concrete type differs from previous defining opaque type use
     u
 }
index 711de855f0d10978edf72e5311010b57b21d8bb2..90b04c043a00ccb1d0fa28571d9e7ffaaa54fdee 100644 (file)
@@ -1,5 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use3.rs:10:27
+  --> $DIR/generic_duplicate_param_use3.rs:11:27
    |
 LL | fn one<T: Debug>(t: T) -> Two<T, T> {
    |                           ^^^^^^^^^
@@ -10,5 +10,29 @@ note: type used multiple times
 LL | type Two<T, U> = impl Debug;
    |          ^  ^
 
-error: aborting due to previous error
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/generic_duplicate_param_use3.rs:20:1
+   |
+LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `U`
+   |
+note: previous use here
+  --> $DIR/generic_duplicate_param_use3.rs:16:1
+   |
+LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` doesn't implement `Debug`
+  --> $DIR/generic_duplicate_param_use3.rs:8:18
+   |
+LL | type Two<T, U> = impl Debug;
+   |                  ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | type Two<T: std::fmt::Debug, U> = impl Debug;
+   |           +++++++++++++++++
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
index e77c94988f73e4fd7614b1dd76e6563e06282746..50d95c83d58e644600976228707615908d42cec6 100644 (file)
@@ -6,6 +6,7 @@ fn main() {}
 
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
+//~^ ERROR `U` doesn't implement `Debug`
 
 fn one<T: Debug>(t: T) -> Two<T, T> {
     //~^ ERROR non-defining opaque type use in defining scope
index fcf01f5164ae4aa770e52ada1ed7076194640d13..c4be2fa83f130fd068f7be5f14eddb4ac529ef93 100644 (file)
@@ -1,5 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use4.rs:10:27
+  --> $DIR/generic_duplicate_param_use4.rs:11:27
    |
 LL | fn one<T: Debug>(t: T) -> Two<T, T> {
    |                           ^^^^^^^^^
@@ -10,5 +10,17 @@ note: type used multiple times
 LL | type Two<T, U> = impl Debug;
    |          ^  ^
 
-error: aborting due to previous error
+error[E0277]: `U` doesn't implement `Debug`
+  --> $DIR/generic_duplicate_param_use4.rs:8:18
+   |
+LL | type Two<T, U> = impl Debug;
+   |                  ^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+help: consider restricting type parameter `U`
+   |
+LL | type Two<T, U: std::fmt::Debug> = impl Debug;
+   |              +++++++++++++++++
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
index 7ee5f7b068f451c4ad64786a5d81bda7c57f5342..cf43085877f4c7864eefd534a8cb071c130989a6 100644 (file)
@@ -5,8 +5,11 @@
 fn main() {}
 
 type OneTy<T> = impl Debug;
+//~^ ERROR could not find defining uses
 type OneLifetime<'a> = impl Debug;
+//~^ ERROR could not find defining uses
 type OneConst<const X: usize> = impl Debug;
+//~^ ERROR could not find defining uses
 
 // Not defining uses, because they doesn't define *all* possible generics.
 
index 5b42f10a6ee34a19ab01ddc65a2d27876212e2ff..3aa42a25484d1dcc169f6ed6423f5b4ded454225 100644 (file)
@@ -1,5 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:13:21
+  --> $DIR/generic_nondefining_use.rs:16:21
    |
 LL | fn concrete_ty() -> OneTy<u32> {
    |                     ^^^^^^^^^^
@@ -10,8 +10,14 @@ note: used non-generic type `u32` for generic parameter
 LL | type OneTy<T> = impl Debug;
    |            ^
 
+error: could not find defining uses
+  --> $DIR/generic_nondefining_use.rs:7:17
+   |
+LL | type OneTy<T> = impl Debug;
+   |                 ^^^^^^^^^^
+
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:18:27
+  --> $DIR/generic_nondefining_use.rs:21:27
    |
 LL | type OneLifetime<'a> = impl Debug;
    |                  -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
@@ -19,17 +25,29 @@ LL | type OneLifetime<'a> = impl Debug;
 LL | fn concrete_lifetime() -> OneLifetime<'static> {
    |                           ^^^^^^^^^^^^^^^^^^^^
 
+error: could not find defining uses
+  --> $DIR/generic_nondefining_use.rs:9:24
+   |
+LL | type OneLifetime<'a> = impl Debug;
+   |                        ^^^^^^^^^^
+
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:23:24
+  --> $DIR/generic_nondefining_use.rs:26:24
    |
 LL | fn concrete_const() -> OneConst<{ 123 }> {
    |                        ^^^^^^^^^^^^^^^^^
    |
 note: used non-generic constant `123_usize` for generic parameter
-  --> $DIR/generic_nondefining_use.rs:9:21
+  --> $DIR/generic_nondefining_use.rs:11:21
    |
 LL | type OneConst<const X: usize> = impl Debug;
    |                     ^
 
-error: aborting due to 3 previous errors
+error: could not find defining uses
+  --> $DIR/generic_nondefining_use.rs:11:33
+   |
+LL | type OneConst<const X: usize> = impl Debug;
+   |                                 ^^^^^^^^^^
+
+error: aborting due to 6 previous errors
 
index 955d1288a457d718689c5b5a44e209c701ee66d0..4c8bf2cfca11e75e9faee943e65c572560546444 100644 (file)
@@ -8,7 +8,6 @@ fn bar() -> Foo {
 }
 
 fn baz() -> Foo {
-    //~^ ERROR: concrete type differs from previous defining opaque type use
     Some(())
 }
 
index 53cdf9e5b385fc82f2209e64a6fc7dc007da30ab..0cdd4cc8dc3bac32435aa3e1debe2d2d70ca2f35 100644 (file)
@@ -4,18 +4,6 @@ error[E0282]: type annotations needed
 LL |     None
    |     ^^^^ cannot infer type for type parameter `T` declared on the enum `Option`
 
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/incomplete-inference.rs:10:1
-   |
-LL | fn baz() -> Foo {
-   | ^^^^^^^^^^^^^^^ expected `[type error]`, got `Option<()>`
-   |
-note: previous use here
-  --> $DIR/incomplete-inference.rs:5:1
-   |
-LL | fn bar() -> Foo {
-   | ^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0282`.
index 37a2f28ce074fed466fbb7dcb3f4b95ef7a0a7cd..9d2ba849c8667539ae6a40efbfb3505387ac0cbd 100644 (file)
@@ -11,6 +11,7 @@ impl Bug for &() {
 
     const FUN: fn() -> Self::Item = || ();
     //~^ ERROR the trait bound `(): Bug` is not satisfied
+    //~| ERROR non-defining opaque type use in defining scope
 }
 
 fn main() {}
index 1710e07644d647e3b698b4fe60fbf10997c44952..62ab7eb456010c8d166c7640c89ec19b532b55c3 100644 (file)
@@ -16,7 +16,16 @@ LL |     const FUN: fn() -> Self::Item = || ();
    = help: the following implementations were found:
              <&() as Bug>
 
-error: aborting due to 2 previous errors
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-60371.rs:12:37
+   |
+LL | impl Bug for &() {
+   |              - cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+...
+LL |     const FUN: fn() -> Self::Item = || ();
+   |                                     ^^^^^
+
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0277, E0658.
 For more information about an error, try `rustc --explain E0277`.
index 78def0d1136de8c5e7d0c0afde4b3a57ce2bbe2e..44dcec2c3da98f3ca47adaed7e089a8c88593ac1 100644 (file)
@@ -6,6 +6,7 @@ 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
index 66fa862ef9d7aa5e827a55eb8ed456a1d53f7baf..6b73fbef011ec8483e3b748637f32f905223ddfa 100644 (file)
@@ -1,5 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-60564.rs:19:34
+  --> $DIR/issue-60564.rs:20:34
    |
 LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
    |                                  ^^^^^^^^^^^^^^
@@ -10,5 +10,11 @@ note: used non-generic type `u8` for generic parameter
 LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
    |                         ^
 
-error: aborting due to previous error
+error: could not find defining uses
+  --> $DIR/issue-60564.rs:8:30
+   |
+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-2.rs b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
new file mode 100644 (file)
index 0000000..2e63540
--- /dev/null
@@ -0,0 +1,14 @@
+// Regression test for issue #68368
+// Ensures that we don't ICE when emitting an error
+// for a non-defining use when lifetimes are involved
+
+#![feature(type_alias_impl_trait)]
+trait Trait<T> {}
+type Alias<'a, U> = impl Trait<U>;
+//~^ ERROR could not find defining uses
+fn f<'a>() -> Alias<'a, ()> {}
+//~^ ERROR non-defining opaque type use in defining scope
+
+fn main() {}
+
+impl<X> Trait<X> for () {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/src/test/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
new file mode 100644 (file)
index 0000000..721f99a
--- /dev/null
@@ -0,0 +1,20 @@
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-68368-non-defining-use-2.rs:9:15
+   |
+LL | fn f<'a>() -> Alias<'a, ()> {}
+   |               ^^^^^^^^^^^^^
+   |
+note: used non-generic type `()` for generic parameter
+  --> $DIR/issue-68368-non-defining-use-2.rs:7:16
+   |
+LL | type Alias<'a, U> = impl Trait<U>;
+   |                ^
+
+error: could not find defining uses
+  --> $DIR/issue-68368-non-defining-use-2.rs:7:21
+   |
+LL | type Alias<'a, U> = impl Trait<U>;
+   |                     ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
index 3b6decbe9c65e5cf5e5d75123246fc66ebd33a01..3addd8dcc4fb3486e5aa91f515a011eb9ab166b8 100644 (file)
@@ -5,6 +5,7 @@
 #![feature(type_alias_impl_trait)]
 trait Trait<T> {}
 type Alias<'a, U> = impl Trait<U>;
+//~^ ERROR could not find defining uses
 fn f<'a>() -> Alias<'a, ()> {}
 //~^ ERROR non-defining opaque type use in defining scope
 
index c2fa54f50f881214050a05d210964a8c152bd080..f5b8fccf65d167779a5cc91b7185a6dd153bfec6 100644 (file)
@@ -1,5 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-68368-non-defining-use.rs:8:15
+  --> $DIR/issue-68368-non-defining-use.rs:9:15
    |
 LL | fn f<'a>() -> Alias<'a, ()> {}
    |               ^^^^^^^^^^^^^
@@ -10,5 +10,11 @@ note: used non-generic type `()` for generic parameter
 LL | type Alias<'a, U> = impl Trait<U>;
    |                ^
 
-error: aborting due to previous error
+error: could not find defining uses
+  --> $DIR/issue-68368-non-defining-use.rs:7:21
+   |
+LL | type Alias<'a, U> = impl Trait<U>;
+   |                     ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
index bcd9aeff6b451a839dc74293e2505bcbb2d4f834..11a922443e64a33c2083c6786b8e05553f6a7566 100644 (file)
@@ -11,7 +11,6 @@ fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>)
 }
 
 fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
-    //~^ ERROR concrete type differs from previous defining opaque type
     (a, b)
     //~^ ERROR mismatched types
 }
index 3d943b77af57da8a7586a1d5a5ba97514ae8886c..bbe709dccab4eb6e9404d4b5cba860ad4a7a2592 100644 (file)
@@ -1,11 +1,10 @@
 error[E0308]: mismatched types
-  --> $DIR/multiple-def-uses-in-one-fn3.rs:15:9
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
    |
 LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
    |      -                    - found type parameter
    |      |
    |      expected type parameter
-LL |
 LL |     (a, b)
    |         ^ expected type parameter `A`, found type parameter `B`
    |
@@ -14,18 +13,6 @@ LL |     (a, b)
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/multiple-def-uses-in-one-fn3.rs:13:1
-   |
-LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `[type error]`
-   |
-note: previous use here
-  --> $DIR/multiple-def-uses-in-one-fn3.rs:9:1
-   |
-LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0308`.
index f29b980dfd0e578e0177ea2a574c3d18ff6b1c2d..107cd394579355d2d05b010c4615a592f13b1f35 100644 (file)
@@ -5,6 +5,7 @@
 fn main() {}
 
 type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
 
 fn two<T: Debug>(t: T) -> Two<T, u32> {
     //~^ ERROR non-defining opaque type use in defining scope
@@ -26,6 +27,7 @@ impl Bar for u32 {
 }
 
 fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
+    //~^ ERROR concrete type differs from previous
     (t, <U as Bar>::FOO)
 }
 
index 2fa236b373a40e482f9b5249ee24a8e3215d590a..08e49845521c6ab18e3d7dd92a2fe77f8519df4e 100644 (file)
@@ -1,5 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/not_a_defining_use.rs:9:27
+  --> $DIR/not_a_defining_use.rs:10:27
    |
 LL | fn two<T: Debug>(t: T) -> Two<T, u32> {
    |                           ^^^^^^^^^^^
@@ -10,5 +10,30 @@ note: used non-generic type `u32` for generic parameter
 LL | type Two<T, U> = impl Debug;
    |             ^
 
-error: aborting due to previous error
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/not_a_defining_use.rs:29:1
+   |
+LL | fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
+   |
+note: previous use here
+  --> $DIR/not_a_defining_use.rs:15:1
+   |
+LL | fn three<T: Debug, U>(t: T) -> Two<T, U> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` doesn't implement `Debug`
+  --> $DIR/not_a_defining_use.rs:7:18
+   |
+LL | type Two<T, U> = impl Debug;
+   |                  ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = note: required because of the requirements on the impl of `Debug` for `(T, i8)`
+help: consider restricting type parameter `T`
+   |
+LL | type Two<T: std::fmt::Debug, U> = impl Debug;
+   |           +++++++++++++++++
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0277`.