diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 26c87f14cd737..8dedef627ce3f 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -952,7 +952,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); - check_type_alias_type_params_are_used(tcx, def_id); let ty = tcx.type_of(def_id).instantiate_identity(); let span = tcx.def_span(def_id); if tcx.type_alias_is_lazy(def_id) { @@ -966,8 +965,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), check_where_clauses(wfcx, def_id); Ok(()) })); - check_variances_for_type_defn(tcx, def_id); } else { + check_type_alias_type_params_are_used(tcx, def_id); res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| { // HACK: We sometimes incidentally check that const arguments have the correct // type as a side effect of the anon const desugaring. To make this "consistent" @@ -2017,12 +2016,6 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) } fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { - if tcx.type_alias_is_lazy(def_id) { - // Since we compute the variances for lazy type aliases and already reject bivariant - // parameters as unused, we can and should skip this check for lazy type aliases. - return; - } - let generics = tcx.generics_of(def_id); if generics.own_counts().types == 0 { return; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 32610619fe713..077d5d1096ee0 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2070,12 +2070,6 @@ pub(super) fn check_variances_for_type_defn<'tcx>(tcx: TyCtxt<'tcx>, def_id: Loc DefKind::Enum | DefKind::Struct | DefKind::Union => { // Ok } - DefKind::TyAlias => { - assert!( - tcx.type_alias_is_lazy(def_id), - "should not be computing variance of non-free type alias" - ); - } kind => span_bug!(tcx.def_span(def_id), "cannot compute the variances of {kind:?}"), } @@ -2227,7 +2221,6 @@ fn report_bivariance<'tcx>( errors::UnusedGenericParameterHelp::AdtNoPhantomData { param_name } } } - ItemKind::TyAlias(..) => errors::UnusedGenericParameterHelp::TyAlias { param_name }, item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"), }; @@ -2309,9 +2302,6 @@ impl<'tcx> IsProbablyCyclical<'tcx> { .visit_with(self) }) } - DefKind::TyAlias if self.tcx.type_alias_is_lazy(def_id) => { - self.tcx.type_of(def_id).instantiate_identity().skip_norm_wip().visit_with(self) - } _ => ControlFlow::Continue(()), } } @@ -2321,17 +2311,12 @@ impl<'tcx> TypeVisitor> for IsProbablyCyclical<'tcx> { type Result = ControlFlow<(), ()>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> { - let def_id = match ty.kind() { - ty::Adt(adt_def, _) => Some(adt_def.did()), - &ty::Alias(ty::AliasTy { kind: ty::Free { def_id }, .. }) => Some(def_id), - _ => None, - }; - if let Some(def_id) = def_id { - if def_id == self.item_def_id { + if let Some(adt_def) = ty.ty_adt_def() { + if adt_def.did() == self.item_def_id { return ControlFlow::Break(()); } - if self.seen.insert(def_id) { - self.visit_def(def_id)?; + if self.seen.insert(adt_def.did()) { + self.visit_def(adt_def.did())?; } } ty.super_visit_with(self) diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index a45856937a8e0..6410572ccb620 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -79,9 +79,6 @@ pub(crate) fn add_constraints_from_crate<'a, 'tcx>( } } DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id), - DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => { - constraint_cx.build_constraints_for_item(def_id) - } _ => {} } } @@ -107,15 +104,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let current_item = &CurrentItem { inferred_start }; let ty = tcx.type_of(def_id).instantiate_identity().skip_norm_wip(); - // The type as returned by `type_of` is the underlying type and generally not a free alias. - // Therefore we need to check the `DefKind` first. - if let DefKind::TyAlias = tcx.def_kind(def_id) - && tcx.type_alias_is_lazy(def_id) - { - self.add_constraints_from_ty(current_item, ty, self.covariant); - return; - } - match ty.kind() { ty::Adt(def, _) => { // Not entirely obvious: constraints on structs/enums do not @@ -216,14 +204,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// Adds constraints appropriate for an instance of `ty` appearing /// in a context with the generics defined in `generics` and /// ambient variance `variance` + #[instrument(level = "debug", skip(self, current))] fn add_constraints_from_ty( &mut self, current: &CurrentItem, ty: Ty<'tcx>, variance: VarianceTermPtr<'a>, ) { - debug!("add_constraints_from_ty(ty={:?}, variance={:?})", ty, variance); - match *ty.kind() { ty::Bool | ty::Char @@ -282,7 +269,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::Alias(ty::AliasTy { kind: ty::Free { def_id }, args, .. }) => { - self.add_constraints_from_args(current, def_id, args, variance); + // For performance reasons, we can't just call + // `expand_free_alias_tys` at the start of this function. + let ty = + self.tcx().type_of(def_id).instantiate(self.tcx(), args).skip_normalization(); + self.add_constraints_from_ty(current, ty, variance); } ty::Dynamic(data, r) => { diff --git a/compiler/rustc_hir_analysis/src/variance/dump.rs b/compiler/rustc_hir_analysis/src/variance/dump.rs index 2e17464736959..7963f5da0e870 100644 --- a/compiler/rustc_hir_analysis/src/variance/dump.rs +++ b/compiler/rustc_hir_analysis/src/variance/dump.rs @@ -38,18 +38,16 @@ pub(crate) fn variances(tcx: TyCtxt<'_>) { } match tcx.def_kind(id) { - DefKind::AssocFn | DefKind::Fn | DefKind::Enum | DefKind::Struct | DefKind::Union => {} - DefKind::TyAlias if tcx.type_alias_is_lazy(id) => {} + DefKind::AssocFn | DefKind::Fn | DefKind::Enum | DefKind::Struct | DefKind::Union => { + tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id.def_id)); + } kind => { let message = format!( "attr parsing didn't report an error for `#[{}]` on {kind:?}", rustc_span::sym::rustc_dump_variances, ); tcx.dcx().span_delayed_bug(tcx.def_span(id), message); - continue; } } - - tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id.def_id)); } } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 9c20ef1a73dcf..c4287a8d0bb10 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -52,11 +52,6 @@ pub(super) fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Va let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); } - DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => { - // These are inferred. - let crate_map = tcx.crate_variances(()); - return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); - } DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) { Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { return variance_of_opaque( diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs index 9c7680b921205..6faeab4217e37 100644 --- a/compiler/rustc_hir_analysis/src/variance/terms.rs +++ b/compiler/rustc_hir_analysis/src/variance/terms.rs @@ -99,9 +99,6 @@ pub(crate) fn determine_parameters_to_be_inferred<'a, 'tcx>( } } DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id), - DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => { - terms_cx.add_inferreds_for_item(def_id) - } _ => {} } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ece9dc52c292c..32fc4f86277bb 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1151,6 +1151,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Static { .. } | DefKind::Const { .. } | DefKind::ForeignMod + | DefKind::TyAlias | DefKind::Impl { .. } | DefKind::Trait | DefKind::TraitAlias @@ -1164,7 +1165,6 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Closure | DefKind::ExternCrate | DefKind::SyntheticCoroutineBody => false, - DefKind::TyAlias => tcx.type_alias_is_lazy(def_id), } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 321a486249620..05032b36f32c1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -928,7 +928,7 @@ impl<'tcx> TyCtxt<'tcx> { return Ty::new_error(self, guar); } - ty = self.type_of(def_id).instantiate(self, args).skip_norm_wip(); + ty = self.type_of(def_id).instantiate(self, args).skip_normalization(); depth += 1; } @@ -990,7 +990,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> { Some(expanded_ty) => *expanded_ty, None => { let generic_ty = self.tcx.type_of(def_id); - let concrete_ty = generic_ty.instantiate(self.tcx, args).skip_norm_wip(); + let concrete_ty = generic_ty.instantiate(self.tcx, args).skip_normalization(); let expanded_ty = self.fold_ty(concrete_ty); self.expanded_cache.insert((def_id, args), expanded_ty); expanded_ty @@ -1070,7 +1070,11 @@ impl<'tcx> TypeFolder> for FreeAliasTypeExpander<'tcx> { self.depth += 1; let ty = ensure_sufficient_stack(|| { - self.tcx.type_of(def_id).instantiate(self.tcx, args).skip_norm_wip().fold_with(self) + self.tcx + .type_of(def_id) + .instantiate(self.tcx, args) + .skip_normalization() + .fold_with(self) }); self.depth -= 1; ty diff --git a/tests/ui/lazy-type-alias/def-site-body-wf.rs b/tests/ui/lazy-type-alias/def-site-body-wf.rs new file mode 100644 index 0000000000000..8a92fa1a39239 --- /dev/null +++ b/tests/ui/lazy-type-alias/def-site-body-wf.rs @@ -0,0 +1,18 @@ +// Test that we check the body at the definition site for well-formedness. + +#![feature(lazy_type_alias)] + +// unsatisified trait bounds +type _A = ::Output; //~ ERROR cannot multiply `T` by `T` +type _B = Vec; //~ ERROR the size for values of type `str` cannot be known at compilation time + +// unsatisfied outlives-bounds +type _C<'a> = &'static &'a (); //~ ERROR reference has a longer lifetime than the data it references + +// diverging const exprs +type _D = [(); panic!()]; //~ ERROR evaluation panicked + +// dyn incompatibility +type _E = dyn Sized; //~ ERROR the trait `Sized` is not dyn compatible + +fn main() {} diff --git a/tests/ui/lazy-type-alias/def-site-body-wf.stderr b/tests/ui/lazy-type-alias/def-site-body-wf.stderr new file mode 100644 index 0000000000000..1f032752559cc --- /dev/null +++ b/tests/ui/lazy-type-alias/def-site-body-wf.stderr @@ -0,0 +1,54 @@ +error[E0277]: cannot multiply `T` by `T` + --> $DIR/def-site-body-wf.rs:6:14 + | +LL | type _A = ::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T` + | +help: consider restricting type parameter `T` with trait `Mul` + | +LL | type _A = ::Output; + | +++++++++++++++ + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/def-site-body-wf.rs:7:11 + | +LL | type _B = Vec; + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references + --> $DIR/def-site-body-wf.rs:10:1 + | +LL | type _C<'a> = &'static &'a (); + | ^^^^^^^^^^^ + | + = note: the pointer is valid for the static lifetime +note: but the referenced data is only valid for the lifetime `'a` as defined here + --> $DIR/def-site-body-wf.rs:10:9 + | +LL | type _C<'a> = &'static &'a (); + | ^^ + +error[E0080]: evaluation panicked: explicit panic + --> $DIR/def-site-body-wf.rs:13:16 + | +LL | type _D = [(); panic!()]; + | ^^^^^^^^ evaluation of `_D::{constant#0}` failed here + +error[E0038]: the trait `Sized` is not dyn compatible + --> $DIR/def-site-body-wf.rs:16:11 + | +LL | type _E = dyn Sized; + | ^^^^^^^^^ `Sized` is not dyn compatible + | + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0038, E0080, E0277, E0491. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr index e91946066bd08..dee809ebf7e81 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr @@ -23,7 +23,7 @@ LL | type Poly0 = Poly1<(T,)>; = note: in case this is a recursive type alias, consider using a struct, enum, or union instead error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:21:1 + --> $DIR/inherent-impls-overflow.rs:20:1 | LL | type Poly1 = Poly0<(T,)>; | ^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | type Poly1 = Poly0<(T,)>; = note: in case this is a recursive type alias, consider using a struct, enum, or union instead error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:26:1 + --> $DIR/inherent-impls-overflow.rs:24:1 | LL | impl Poly0<()> {} | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr index 62ed6e8e513d9..a592d3537ebde 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr @@ -24,38 +24,16 @@ LL | type Poly0 = Poly1<(T,)>; | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) -error: type parameter `T` is only used recursively - --> $DIR/inherent-impls-overflow.rs:17:24 - | -LL | type Poly0 = Poly1<(T,)>; - | - ^ - | | - | type parameter must be used non-recursively in the definition - | - = help: consider removing `T` or referring to it in the body of the type alias - = note: all type parameters must be used in a non-recursive way in order to constrain their variance - error[E0275]: overflow evaluating the requirement `Poly0<(T,)> == _` - --> $DIR/inherent-impls-overflow.rs:21:1 + --> $DIR/inherent-impls-overflow.rs:20:1 | LL | type Poly1 = Poly0<(T,)>; | ^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) -error: type parameter `T` is only used recursively - --> $DIR/inherent-impls-overflow.rs:21:24 - | -LL | type Poly1 = Poly0<(T,)>; - | - ^ - | | - | type parameter must be used non-recursively in the definition - | - = help: consider removing `T` or referring to it in the body of the type alias - = note: all type parameters must be used in a non-recursive way in order to constrain their variance - error[E0275]: overflow evaluating the requirement `Poly0<()> == _` - --> $DIR/inherent-impls-overflow.rs:26:1 + --> $DIR/inherent-impls-overflow.rs:24:1 | LL | impl Poly0<()> {} | ^^^^^^^^^^^^^^^^^ @@ -63,14 +41,14 @@ LL | impl Poly0<()> {} = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) error[E0275]: overflow evaluating the requirement `Poly0<()> == _` - --> $DIR/inherent-impls-overflow.rs:26:6 + --> $DIR/inherent-impls-overflow.rs:24:6 | LL | impl Poly0<()> {} | ^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0271, E0275. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs index b4a347cb098ca..be3cda4d53584 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs @@ -16,12 +16,10 @@ impl Loop {} type Poly0 = Poly1<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>` -//[next]~^^ ERROR type parameter `T` is only used recursively -//[next]~| ERROR overflow evaluating the requirement +//[next]~^^ ERROR overflow evaluating the requirement type Poly1 = Poly0<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` -//[next]~^^ ERROR type parameter `T` is only used recursively -//[next]~| ERROR overflow evaluating the requirement +//[next]~^^ ERROR overflow evaluating the requirement impl Poly0<()> {} //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs deleted file mode 100644 index c798e4e436824..0000000000000 --- a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Test that we check lazy type aliases for well-formedness. - -#![feature(lazy_type_alias)] -#![allow(incomplete_features)] - -type Alias = ::Output; //~ ERROR cannot multiply `T` by `T` - -fn main() {} diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr deleted file mode 100644 index d0d4d04e28a38..0000000000000 --- a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0277]: cannot multiply `T` by `T` - --> $DIR/unsatisfied-bounds-type-alias-body.rs:6:17 - | -LL | type Alias = ::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T` - | -help: consider restricting type parameter `T` with trait `Mul` - | -LL | type Alias = ::Output; - | +++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.next-fixed.stderr b/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.next-fixed.stderr new file mode 100644 index 0000000000000..f41371778a104 --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.next-fixed.stderr @@ -0,0 +1,19 @@ +error[E0080]: evaluation panicked: explicit panic + --> $DIR/unused-generic-arguments-not-wfchecked.rs:28:43 + | +LL | #[cfg(not(next_bugged))] type A2 = A<[(); panic!()]>; // FIXME: `panic!()` diverging + | ^^^^^^^^ evaluation of `A2::{constant#0}` failed here + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unused-generic-arguments-not-wfchecked.rs:31:37 + | +LL | #[cfg(not(next_bugged))] const _: A<[str]> = (); // FIXME: `str: Sized` unsatisfied + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0080, E0277. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.rs b/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.rs new file mode 100644 index 0000000000000..e048460cebae1 --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.rs @@ -0,0 +1,34 @@ +// We currently fail to wfcheck generic arguments that correspond to unused LTA generic parameters +// since we generally normalize types before wfchecking them, so we accidentally "expand them away" +// before we can check them. +// +// (We do still check predicates that reference unused parameters, of course.) +// +// FIXME(lazy_type_alias): I consider #100041 to be a stabilization-blocking concern for the checked +// version of LTA! The *entire premise* of checked_LTA is wfchecking; +// we can't have such obvious holes in it! +// +//@ revisions: current-bugged next-bugged next-fixed +// +//@[next-bugged] compile-flags: -Znext-solver +//@[next-fixed] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +// +//@[current-bugged] known-bug: #100041 +//@[current-bugged] check-pass +//@[next-bugged] known-bug: #100041 +//@[next-bugged] check-pass + +#![feature(lazy_type_alias)] + +type A = (); + +type A0 = A<[str]>; // FIXME: `str: Sized` unsatisfied +type A1<'r> = A<&'static &'r ()>; // FIXME: `'r: 'static` unsatisfied +#[cfg(not(next_bugged))] type A2 = A<[(); panic!()]>; // FIXME: `panic!()` diverging +//[next-fixed]~^ ERROR evaluation panicked + +#[cfg(not(next_bugged))] const _: A<[str]> = (); // FIXME: `str: Sized` unsatisfied +//[next-fixed]~^ ERROR the size for values of type `str` cannot be known at compilation time + +fn main() {} diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.fail.stderr b/tests/ui/lazy-type-alias/unused-generic-parameters.fail.stderr new file mode 100644 index 0000000000000..05e3881cb090c --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-parameters.fail.stderr @@ -0,0 +1,50 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/unused-generic-parameters.rs:24:22 + | +LL | #[cfg(fail)] fn a(_: A<'_>) {} + | ^^^^^ + | +note: lifetime parameter instantiated with the anonymous lifetime defined here + --> $DIR/unused-generic-parameters.rs:24:22 + | +LL | #[cfg(fail)] fn a(_: A<'_>) {} + | ^^^^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unused-generic-parameters.rs:28:22 + | +LL | #[cfg(fail)] fn b(_: B) {} + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound on the type alias `B` + --> $DIR/unused-generic-parameters.rs:26:8 + | +LL | type B = (); + | ^ required by this bound + +error[E0080]: evaluation panicked: explicit panic + --> $DIR/unused-generic-parameters.rs:34:26 + | +LL | #[cfg(fail)] fn c(_: C<{ panic!() }>) {} + | ^^^^^^^^ evaluation of `c::{constant#0}` failed here + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unused-generic-parameters.rs:28:22 + | +LL | #[cfg(fail)] fn b(_: B) {} + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound on the type alias `B` + --> $DIR/unused-generic-parameters.rs:26:8 + | +LL | type B = (); + | ^ required by this bound + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0277, E0478. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.rs b/tests/ui/lazy-type-alias/unused-generic-parameters.rs index 9d02de7a7212b..3482512671226 100644 --- a/tests/ui/lazy-type-alias/unused-generic-parameters.rs +++ b/tests/ui/lazy-type-alias/unused-generic-parameters.rs @@ -1,22 +1,36 @@ -// Check that we reject bivariant generic parameters as unused. -// Furthermore, check that we only emit a single diagnostic for unused type parameters: -// Previously, we would emit *two* errors, namely E0392 and E0091. +// Check that we accept unused generic parameters on lazy type aliases (for context, we reject +// unused type parameters on eager type aliases). +// +// As long as we check well-formedness before normalization there shouldn't be anything wrong with +// such parameters since we know that the corresponding arguments will get wfchecked regardless. +// +// FIXME(lazy_type_alias, #100041): At the time of writing however, that's not the case. I consider +// this to be stabilization-blocking concern for the strong / +// checked version of LTA! +// See also `unused-generic-arguments-not-wfchecked.rs`. +// +// (We *do* ofc still detect unsatisfied predicates even if they +// reference unused parameters) +// +// issue: +// +//@ revisions: pass fail +//@[pass] check-pass #![feature(lazy_type_alias)] -#![allow(incomplete_features)] -type A<'a> = (); -//~^ ERROR lifetime parameter `'a` is never used -//~| HELP consider removing `'a` +type A<'a: 'static> = (); +const _: A<'static> = (); +#[cfg(fail)] fn a(_: A<'_>) {} //[fail]~ ERROR lifetime bound not satisfied type B = (); -//~^ ERROR type parameter `T` is never used -//~| HELP consider removing `T` -//~| HELP if you intended `T` to be a const parameter +const _: B = (); +#[cfg(fail)] fn b(_: B) {} +//[fail]~^ ERROR the size for values of type `str` cannot be known at compilation time +//[fail]~| ERROR the size for values of type `str` cannot be known at compilation time -// Check that we don't emit the const param help message here: -type C = (); -//~^ ERROR type parameter `T` is never used -//~| HELP consider removing `T` +type C = (); +const _: C<{ 0 * 1 }> = (); +#[cfg(fail)] fn c(_: C<{ panic!() }>) {} //[fail]~ ERROR evaluation panicked fn main() {} diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.stderr b/tests/ui/lazy-type-alias/unused-generic-parameters.stderr deleted file mode 100644 index 484e21b0a03f9..0000000000000 --- a/tests/ui/lazy-type-alias/unused-generic-parameters.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0392]: lifetime parameter `'a` is never used - --> $DIR/unused-generic-parameters.rs:8:8 - | -LL | type A<'a> = (); - | ^^ unused lifetime parameter - | - = help: consider removing `'a` or referring to it in the body of the type alias - -error[E0392]: type parameter `T` is never used - --> $DIR/unused-generic-parameters.rs:12:8 - | -LL | type B = (); - | ^ unused type parameter - | - = help: consider removing `T` or referring to it in the body of the type alias - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead - -error[E0392]: type parameter `T` is never used - --> $DIR/unused-generic-parameters.rs:18:8 - | -LL | type C = (); - | ^ unused type parameter - | - = help: consider removing `T` or referring to it in the body of the type alias - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/lazy-type-alias/use-site-wf.rs b/tests/ui/lazy-type-alias/use-site-wf.rs new file mode 100644 index 0000000000000..a44ff3e3493d7 --- /dev/null +++ b/tests/ui/lazy-type-alias/use-site-wf.rs @@ -0,0 +1,16 @@ +// Test that we check usage sites of lazy type aliases, aka free alias types, for well-formedness. +// We check trailing where-clauses separately in `trailing-where-clause.rs`. + +#![feature(lazy_type_alias)] + +type B = T; + +fn b(_: B) {} +//~^ ERROR the trait bound `X: Copy` is not satisfied +//~| ERROR the trait bound `X: Copy` is not satisfied + +type A<'a: 'static> = &'a (); + +fn a<'r>(_: A<'r>) {} //~ ERROR lifetime bound not satisfied + +fn main() {} diff --git a/tests/ui/lazy-type-alias/use-site-wf.stderr b/tests/ui/lazy-type-alias/use-site-wf.stderr new file mode 100644 index 0000000000000..b473a2db055e4 --- /dev/null +++ b/tests/ui/lazy-type-alias/use-site-wf.stderr @@ -0,0 +1,50 @@ +error[E0277]: the trait bound `X: Copy` is not satisfied + --> $DIR/use-site-wf.rs:8:12 + | +LL | fn b(_: B) {} + | ^^^^ the trait `Copy` is not implemented for `X` + | +note: required by a bound on the type alias `B` + --> $DIR/use-site-wf.rs:6:11 + | +LL | type B = T; + | ^^^^ required by this bound +help: consider restricting type parameter `X` with trait `Copy` + | +LL | fn b(_: B) {} + | +++++++++++++++++++ + +error[E0478]: lifetime bound not satisfied + --> $DIR/use-site-wf.rs:14:13 + | +LL | fn a<'r>(_: A<'r>) {} + | ^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'r` as defined here + --> $DIR/use-site-wf.rs:14:6 + | +LL | fn a<'r>(_: A<'r>) {} + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0277]: the trait bound `X: Copy` is not satisfied + --> $DIR/use-site-wf.rs:8:12 + | +LL | fn b(_: B) {} + | ^^^^ the trait `Copy` is not implemented for `X` + | +note: required by a bound on the type alias `B` + --> $DIR/use-site-wf.rs:6:11 + | +LL | type B = T; + | ^^^^ required by this bound + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider restricting type parameter `X` with trait `Copy` + | +LL | fn b(_: B) {} + | +++++++++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0478. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias/variance-0.rs b/tests/ui/lazy-type-alias/variance-0.rs new file mode 100644 index 0000000000000..1cecdff2977b3 --- /dev/null +++ b/tests/ui/lazy-type-alias/variance-0.rs @@ -0,0 +1,61 @@ +// Ensure that we eagerly *expand* free alias types during variance computation. +// +// Since free alias types are always normalizable it's not unreasonable to expect that variance +// information "propagates through" free aliases unlike projections for example which constrain +// all of their generic arguments to be invariant[^1]. +// +// For context, we can't *normalize* types before trying to compute variances because we need +// variances for normalization in the first place, more specifically type relating. +// +// [^1]: Parent args: Traits are invariant over their params. Own args: Projections can be rigid. +// +// issue: +// +//@ check-pass + +// FIXME(lazy_type_alias): Revisit this before stabilization (it's not blocking tho): +// We might want to compute variances for free alias types again +// with a special rule. See `variance-1.rs` for details. + +#![feature(lazy_type_alias)] + +// `Co` is covariant over `'a` since we expand `A` to `&'a ()`. +struct Co<'a>(A<'a>); + +// `A` is *not* in a variance relation with its args since it's a type alias. +type A<'a> = &'a (); + +fn co<'a>(x: Co<'static>) { + let _: Co<'a> = x; // OK +} + +// `Contra` is contravariant over `'a` since we expand `B` to `fn(&'a ())`. +struct Contra<'a>(B<'a>); + +// (not in a variance relation) +type B<'a> = fn(&'a ()); + +fn contra<'a>(x: Contra<'a>) { + let _: Contra<'static> = x; // OK +} + +// `CoContra` is covariant over `T` and contravariant over `U` since we expand `C`. +struct CoContra(C); + +// (not in a variance relation) +type C = Option<(T, fn(U))>; + +fn co_contra<'a>(x: CoContra<&'static (), &'a ()>) -> CoContra<&'a (), &'static ()> { + x // OK +} + +// Check that we deeply expand: +struct Co2<'a>(D0<'a>); +type D0<'a> = D1<'a>; +type D1<'a> = D2<'a>; +type D2<'a> = D3<'a>; +type D3<'a> = &'a (); + +fn co2<'a>(x: Co2<'static>) -> Co2<'a> { x } // OK + +fn main() {} diff --git a/tests/ui/lazy-type-alias/variance-1.rs b/tests/ui/lazy-type-alias/variance-1.rs new file mode 100644 index 0000000000000..51480d271b439 --- /dev/null +++ b/tests/ui/lazy-type-alias/variance-1.rs @@ -0,0 +1,42 @@ +// Demonstrate that free alias types don't constrain their lifetime & type arguments if the corresp. +// lifetime & type parameters are unused in the lazy type alias (before normalization) since we +// eagerly expand them during variance computation unlike other alias types which constrain args to +// be invariant. + +// FIXME(lazy_type_alias): Revisit this before stabilization (altho it's not blocking): +// Do we want to compute variances for lazy type aliases & free alias types +// again and "force bivariant parameters to be invariant" if they're not +// constrained by a projection? +// This would make `struct WrapDiscard` below compile. + +#![feature(lazy_type_alias)] + +type Discard<'a, T> = (); + +// `'a` and `T` are bivariant & unconstrained => rejection +struct WrapDiscard<'a, T>(Discard<'a, T>); +//~^ ERROR lifetime parameter `'a` is never used +//~| ERROR type parameter `T` is never used + +type DiscardConstrained<'a, T, X> = X +where + X: Iterator; + +// `'a` and `T` are bivariant & constrained => acceptance +struct WrapDiscardConstrained<'a, T, X>(DiscardConstrained<'a, T, X>) +where + X: Iterator; + +type Co<'a> = std::vec::IntoIter<(&'a (), &'a ())>; + +// NOTE: If we end up switching back to computing variances for free alias types with the special +// rule explained in the FIXME above, then this function should still compile since +// LTA `DiscardConstrained` should be bivariant over `'a` and `T`, not invariant due to them +// being constrained by a projection. +fn bi<'r>( + x: WrapDiscardConstrained<'static, &'static (), Co<'static>>, +) -> WrapDiscardConstrained<'r, &'r (), Co<'r>> { + x +} + +fn main() {} diff --git a/tests/ui/lazy-type-alias/variance-1.stderr b/tests/ui/lazy-type-alias/variance-1.stderr new file mode 100644 index 0000000000000..5eb2f5d0673aa --- /dev/null +++ b/tests/ui/lazy-type-alias/variance-1.stderr @@ -0,0 +1,22 @@ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/variance-1.rs:17:20 + | +LL | struct WrapDiscard<'a, T>(Discard<'a, T>); + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-1.rs:17:24 + | +LL | struct WrapDiscard<'a, T>(Discard<'a, T>); + | ^ - `T` is named here, but is likely unused in the containing type + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/lazy-type-alias/variance.rs b/tests/ui/lazy-type-alias/variance.rs deleted file mode 100644 index dae2069502a20..0000000000000 --- a/tests/ui/lazy-type-alias/variance.rs +++ /dev/null @@ -1,38 +0,0 @@ -// This is a regression test for issue #114221. -// Check that we compute variances for lazy type aliases. - -//@ check-pass - -#![feature(lazy_type_alias)] -#![allow(incomplete_features)] - -// [+] `A` is covariant over `'a`. -struct A<'a>(Co<'a>); - -// [+] `Co` is covariant over `'a`. -type Co<'a> = &'a (); - -fn co<'a>(x: A<'static>) { - let _: A<'a> = x; -} - -// [-] `B` is contravariant over `'a`. -struct B<'a>(Contra<'a>); - -// [-] `Contra` is contravariant over `'a`. -type Contra<'a> = fn(&'a ()); - -fn contra<'a>(x: B<'a>) { - let _: B<'static> = x; -} - -struct C(CoContra); - -// [+, -] `CoContra` is covariant over `T` and contravariant over `U`. -type CoContra = Option<(T, fn(U))>; - -fn co_contra<'a>(x: C<&'static (), &'a ()>) -> C<&'a (), &'static ()> { - x -} - -fn main() {}