Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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"
Expand Down Expand Up @@ -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;
Expand Down
23 changes: 4 additions & 19 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:?}"),
}

Expand Down Expand Up @@ -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:?}"),
};

Expand Down Expand Up @@ -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(()),
}
}
Expand All @@ -2321,17 +2311,12 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> 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)
Expand Down
21 changes: 6 additions & 15 deletions compiler/rustc_hir_analysis/src/variance/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
_ => {}
}
}
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 =
Copy link
Copy Markdown
Member

@BoxyUwU BoxyUwU May 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does variance computation have a mechanism to avoid infinite recursion? I'm wondering whether we need to be concerned about sth like type Foo = (Foo,);. I realise that item wfcks do eventually check for diverging free aliases (or atleast ought to 😌) but I'm unsure about query orderings and whether that's always checked before computing variances

View changes since the review

self.tcx().type_of(def_id).instantiate(self.tcx(), args).skip_normalization();
self.add_constraints_from_ty(current, ty, variance);
}

ty::Dynamic(data, r) => {
Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_hir_analysis/src/variance/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
5 changes: 0 additions & 5 deletions compiler/rustc_hir_analysis/src/variance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_hir_analysis/src/variance/terms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
_ => {}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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),
}
}

Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1070,7 +1070,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> 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
Expand Down
18 changes: 18 additions & 0 deletions tests/ui/lazy-type-alias/def-site-body-wf.rs
Original file line number Diff line number Diff line change
@@ -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<T> = <T as std::ops::Mul>::Output; //~ ERROR cannot multiply `T` by `T`
type _B = Vec<str>; //~ 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() {}
54 changes: 54 additions & 0 deletions tests/ui/lazy-type-alias/def-site-body-wf.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
error[E0277]: cannot multiply `T` by `T`
--> $DIR/def-site-body-wf.rs:6:14
|
LL | type _A<T> = <T as std::ops::Mul>::Output;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T`
|
help: consider restricting type parameter `T` with trait `Mul`
|
LL | type _A<T: std::ops::Mul> = <T as std::ops::Mul>::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<str>;
| ^^^^^^^^ 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 <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>

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`.
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ LL | type Poly0<T> = 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<T> = 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<()> {}
| ^^^^^^^^^^^^^^^^^
Expand Down
30 changes: 4 additions & 26 deletions tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,53 +24,31 @@ LL | type Poly0<T> = 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<T> = 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<T> = 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<T> = 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<()> {}
| ^^^^^^^^^^^^^^^^^
|
= 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`.
6 changes: 2 additions & 4 deletions tests/ui/lazy-type-alias/inherent-impls-overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ impl Loop {}

type Poly0<T> = 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<T> = 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<(((((((...,),),),),),),)>`
Expand Down
Loading
Loading