diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index f3d37a6be7b48..810737587912b 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,11 +1,8 @@ -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::vec_map::VecMap; use rustc_hir::def_id::DefId; use rustc_hir::OpaqueTyOrigin; use rustc_infer::infer::InferCtxt; -use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable}; -use rustc_span::Span; use rustc_trait_selection::opaque_types::InferCtxtExt; use super::RegionInferenceContext; @@ -107,21 +104,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { let opaque_type_key = OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs }; - let remapped_type = infcx.infer_opaque_definition_from_instantiation( + let ty = infcx.infer_opaque_definition_from_instantiation( opaque_type_key, universal_concrete_type, origin, ); - let ty = if check_opaque_type_parameter_valid( - infcx.tcx, - opaque_type_key, - origin, - concrete_type.span, - ) { - remapped_type - } else { - infcx.tcx.ty_error() - }; // Sometimes two opaque types are the same only after we remap the generic parameters // back to the opaque type definition. E.g. we may have `OpaqueType` mapped to `(X, Y)` // and `OpaqueType` mapped to `(Y, X)`, and those are the same, but we only know that @@ -184,95 +171,3 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) } } - -fn check_opaque_type_parameter_valid( - tcx: TyCtxt<'_>, - opaque_type_key: OpaqueTypeKey<'_>, - origin: OpaqueTyOrigin, - span: Span, -) -> bool { - match 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() -> impl Trait - // - // into - // - // type Foo - // fn foo() -> Foo. - // - // For lifetime parameters we convert - // - // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> - // - // into - // - // type foo::<'p0..'pn>::Foo<'q0..'qm> - // fn foo() -> 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 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(lt) if lt.is_static() => { - 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` 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 -} diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 74f5185d67236..238c6d9999075 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -82,6 +82,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { )); debug!(?definition_ty); + if !check_opaque_type_parameter_valid( + self.tcx, + opaque_type_key, + origin, + instantiated_ty.span, + ) { + return self.tcx.ty_error(); + } + // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs` // on stable and we'd break that. if let OpaqueTyOrigin::TyAlias = origin { @@ -148,6 +157,98 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } +fn check_opaque_type_parameter_valid( + tcx: TyCtxt<'_>, + opaque_type_key: OpaqueTypeKey<'_>, + origin: OpaqueTyOrigin, + span: Span, +) -> bool { + match 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() -> impl Trait + // + // into + // + // type Foo + // fn foo() -> Foo. + // + // For lifetime parameters we convert + // + // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> + // + // into + // + // type foo::<'p0..'pn>::Foo<'q0..'qm> + // fn foo() -> 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 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(lt) if lt.is_static() => { + 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` 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 +} + struct ReverseMapper<'tcx> { tcx: TyCtxt<'tcx>, 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 cf46add124cb3..093c1c231861f 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 @@ -15,7 +15,6 @@ type TwoConsts = impl Debug; fn one_ty(t: T) -> TwoTys { t //~^ ERROR non-defining opaque type use in defining scope - //~| ERROR `U` doesn't implement `Debug` } fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { 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 d661196e1bf19..b2edcc5526a4a 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,14 +1,3 @@ -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use.rs:16:5 - | -LL | t - | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | -help: consider restricting type parameter `U` - | -LL | type TwoTys = impl Debug; - | +++++++++++++++++ - error: non-defining opaque type use in defining scope --> $DIR/generic_duplicate_param_use.rs:16:5 | @@ -22,7 +11,7 @@ LL | type TwoTys = impl Debug; | ^ ^ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:22:5 + --> $DIR/generic_duplicate_param_use.rs:21:5 | LL | t | ^ @@ -34,7 +23,7 @@ LL | type TwoLifetimes<'a, 'b> = impl Debug; | ^^ ^^ error: non-defining opaque type use in defining scope - --> $DIR/generic_duplicate_param_use.rs:27:5 + --> $DIR/generic_duplicate_param_use.rs:26:5 | LL | t | ^ @@ -45,6 +34,5 @@ note: constant used multiple times LL | type TwoConsts = impl Debug; | ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. 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 48d8dff2b9392..4fc7679311a2e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -19,14 +19,6 @@ where fn iter_bits(self, n: u8) -> Self::BitsIter { (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) //~^ ERROR non-defining opaque type use in defining scope - //~| ERROR type mismatch resolving - //~| ERROR type mismatch resolving `>::Error == E` - //~| ERROR no implementation for `T >> T` - //~| ERROR no implementation for `T & T` - //~| ERROR the trait bound `T: From` - //~| ERROR the trait bound `T: Copy` is not satisfied - //~| ERROR `E` doesn't implement `Debug` - //~| ERROR the trait bound `u8: From` is not satisfied } } 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 4ef53973a7c74..bbc93657be32f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr @@ -1,132 +1,3 @@ -error[E0271]: type mismatch resolving `<[closure@$DIR/issue-60564.rs:20:28: 20:100] as FnOnce<(u8,)>>::Output == I` - --> $DIR/issue-60564.rs:20:9 - | -LL | type IterBitsIter = impl std::iter::Iterator; - | - this type parameter -... -LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found type parameter `I` - | - = note: expected type `u8` - found type parameter `I` - = note: required because of the requirements on the impl of `Iterator` for `Map>, [closure@$DIR/issue-60564.rs:20:28: 20:100]>` - -error[E0271]: type mismatch resolving `>::Error == E` - --> $DIR/issue-60564.rs:20:9 - | -LL | type IterBitsIter = impl std::iter::Iterator; - | - this type parameter -... -LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `E`, found enum `Infallible` - | - = note: expected type parameter `E` - found enum `Infallible` -note: required by a bound in `` - --> $DIR/issue-60564.rs:15:37 - | -LL | + std::convert::TryInto, - | ^^^^^^^^^ required by this bound in `` - -error[E0277]: no implementation for `T >> T` - --> $DIR/issue-60564.rs:20:9 - | -LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T >> T` - | -note: required by a bound in `` - --> $DIR/issue-60564.rs:12:8 - | -LL | T: std::ops::Shr - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `` -help: consider restricting type parameter `T` - | -LL | type IterBitsIter = impl std::iter::Iterator; - | +++++++++++++++ - -error[E0277]: no implementation for `T & T` - --> $DIR/issue-60564.rs:20:9 - | -LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T & T` - | -note: required by a bound in `` - --> $DIR/issue-60564.rs:13:11 - | -LL | + std::ops::BitAnd - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `` -help: consider restricting type parameter `T` - | -LL | type IterBitsIter = impl std::iter::Iterator; - | ++++++++++++++++++ - -error[E0277]: the trait bound `T: From` is not satisfied - --> $DIR/issue-60564.rs:20:9 - | -LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From` is not implemented for `T` - | -note: required by a bound in `` - --> $DIR/issue-60564.rs:14:11 - | -LL | + std::convert::From - | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `` -help: consider restricting type parameter `T` - | -LL | type IterBitsIter, E, I> = impl std::iter::Iterator; - | ++++++++++++++++++++++++ - -error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-60564.rs:20:9 - | -LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` - | -note: required by a bound in `` - --> $DIR/issue-60564.rs:10:9 - | -LL | impl IterBits for T - | ^^^^ required by this bound in `` -help: consider restricting type parameter `T` - | -LL | type IterBitsIter = impl std::iter::Iterator; - | +++++++++++++++++++ - -error[E0277]: `E` doesn't implement `Debug` - --> $DIR/issue-60564.rs:20:9 - | -LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `E` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | -note: required by a bound in `` - --> $DIR/issue-60564.rs:16:8 - | -LL | E: std::fmt::Debug, - | ^^^^^^^^^^^^^^^ required by this bound in `` -help: consider restricting type parameter `E` - | -LL | type IterBitsIter = impl std::iter::Iterator; - | +++++++++++++++++ - -error[E0277]: the trait bound `u8: From` is not satisfied - --> $DIR/issue-60564.rs:20:9 - | -LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From` is not implemented for `u8` - | - = note: required because of the requirements on the impl of `Into` for `T` - = note: required because of the requirements on the impl of `TryFrom` for `u8` - = note: required because of the requirements on the impl of `TryInto` for `T` -note: required by a bound in `` - --> $DIR/issue-60564.rs:15:11 - | -LL | + std::convert::TryInto, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `` -help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement - | -LL | type IterBitsIter = impl std::iter::Iterator where u8: From; - | +++++++++++++++++ - error: non-defining opaque type use in defining scope --> $DIR/issue-60564.rs:20:9 | @@ -139,7 +10,5 @@ note: used non-generic type `u8` for generic parameter LL | type IterBitsIter = impl std::iter::Iterator; | ^ -error: aborting due to 9 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. 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 bffff8787e4a2..b50462bf237bb 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 @@ -8,7 +8,6 @@ type Alias<'a, U> = impl Trait; fn f<'a>() -> Alias<'a, ()> {} //~^ ERROR non-defining opaque type use in defining scope -//~| ERROR the trait bound `(): Trait` is not satisfied 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 b79d638ad9951..8059621b61a09 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,3 @@ -error[E0277]: the trait bound `(): Trait` is not satisfied - --> $DIR/issue-68368-non-defining-use.rs:9:29 - | -LL | fn f<'a>() -> Alias<'a, ()> {} - | ^^ the trait `Trait` is not implemented for `()` - | -help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement - | -LL | type Alias<'a, U> = impl Trait where (): Trait; - | ++++++++++++++++++ - error: non-defining opaque type use in defining scope --> $DIR/issue-68368-non-defining-use.rs:9:29 | @@ -21,6 +10,5 @@ note: used non-generic type `()` for generic parameter LL | type Alias<'a, U> = impl Trait; | ^ -error: aborting due to 2 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/issue-69136-inner-lifetime-resolve-error.rs b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs index b0de8bf6aa4f2..428454bc04844 100644 --- a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs +++ b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs @@ -19,6 +19,5 @@ type Return = impl WithAssoc; fn my_fun() -> Return<()> {} //~^ ERROR non-defining opaque type use in defining scope -//~| ERROR non-defining opaque type use in defining scope fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr index d038fbbe1b40a..7b50c8af26e5f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr @@ -26,18 +26,6 @@ note: used non-generic type `()` for generic parameter LL | type Return = impl WithAssoc; | ^ -error: non-defining opaque type use in defining scope - --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27 - | -LL | fn my_fun() -> Return<()> {} - | ^^ - | -note: used non-generic type `()` for generic parameter - --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13 - | -LL | type Return = impl WithAssoc; - | ^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0261`.