Skip to content

Commit 0ed4e6c

Browse files
committed
Expand free alias types during variance computation
1 parent 2bd7a97 commit 0ed4e6c

22 files changed

Lines changed: 316 additions & 167 deletions

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
951951
tcx.ensure_ok().generics_of(def_id);
952952
tcx.ensure_ok().type_of(def_id);
953953
tcx.ensure_ok().predicates_of(def_id);
954-
check_type_alias_type_params_are_used(tcx, def_id);
955954
let ty = tcx.type_of(def_id).instantiate_identity();
956955
let span = tcx.def_span(def_id);
957956
if tcx.type_alias_is_lazy(def_id) {
@@ -965,8 +964,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
965964
check_where_clauses(wfcx, def_id);
966965
Ok(())
967966
}));
968-
check_variances_for_type_defn(tcx, def_id);
969967
} else {
968+
check_type_alias_type_params_are_used(tcx, def_id);
970969
res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
971970
// HACK: We sometimes incidentally check that const arguments have the correct
972971
// type as a side effect of the anon const desugaring. To make this "consistent"
@@ -2013,12 +2012,6 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
20132012
}
20142013

20152014
fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
2016-
if tcx.type_alias_is_lazy(def_id) {
2017-
// Since we compute the variances for lazy type aliases and already reject bivariant
2018-
// parameters as unused, we can and should skip this check for lazy type aliases.
2019-
return;
2020-
}
2021-
20222015
let generics = tcx.generics_of(def_id);
20232016
if generics.own_counts().types == 0 {
20242017
return;

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,12 +2006,6 @@ pub(super) fn check_variances_for_type_defn<'tcx>(tcx: TyCtxt<'tcx>, def_id: Loc
20062006
DefKind::Enum | DefKind::Struct | DefKind::Union => {
20072007
// Ok
20082008
}
2009-
DefKind::TyAlias => {
2010-
assert!(
2011-
tcx.type_alias_is_lazy(def_id),
2012-
"should not be computing variance of non-free type alias"
2013-
);
2014-
}
20152009
kind => span_bug!(tcx.def_span(def_id), "cannot compute the variances of {kind:?}"),
20162010
}
20172011

@@ -2158,7 +2152,6 @@ fn report_bivariance<'tcx>(
21582152
errors::UnusedGenericParameterHelp::AdtNoPhantomData { param_name }
21592153
}
21602154
}
2161-
ItemKind::TyAlias(..) => errors::UnusedGenericParameterHelp::TyAlias { param_name },
21622155
item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"),
21632156
};
21642157

@@ -2236,9 +2229,6 @@ impl<'tcx> IsProbablyCyclical<'tcx> {
22362229
self.tcx.type_of(field.did).instantiate_identity().visit_with(self)
22372230
})
22382231
}
2239-
DefKind::TyAlias if self.tcx.type_alias_is_lazy(def_id) => {
2240-
self.tcx.type_of(def_id).instantiate_identity().visit_with(self)
2241-
}
22422232
_ => ControlFlow::Continue(()),
22432233
}
22442234
}
@@ -2248,17 +2238,12 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsProbablyCyclical<'tcx> {
22482238
type Result = ControlFlow<(), ()>;
22492239

22502240
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
2251-
let def_id = match ty.kind() {
2252-
ty::Adt(adt_def, _) => Some(adt_def.did()),
2253-
ty::Alias(ty::Free, alias_ty) => Some(alias_ty.def_id),
2254-
_ => None,
2255-
};
2256-
if let Some(def_id) = def_id {
2257-
if def_id == self.item_def_id {
2241+
if let Some(adt_def) = ty.ty_adt_def() {
2242+
if adt_def.did() == self.item_def_id {
22582243
return ControlFlow::Break(());
22592244
}
2260-
if self.seen.insert(def_id) {
2261-
self.visit_def(def_id)?;
2245+
if self.seen.insert(adt_def.did()) {
2246+
self.visit_def(adt_def.did())?;
22622247
}
22632248
}
22642249
ty.super_visit_with(self)

compiler/rustc_hir_analysis/src/variance/constraints.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ pub(crate) fn add_constraints_from_crate<'a, 'tcx>(
7979
}
8080
}
8181
DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
82-
DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => {
83-
constraint_cx.build_constraints_for_item(def_id)
84-
}
8582
_ => {}
8683
}
8784
}
@@ -107,15 +104,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
107104
let current_item = &CurrentItem { inferred_start };
108105
let ty = tcx.type_of(def_id).instantiate_identity();
109106

110-
// The type as returned by `type_of` is the underlying type and generally not a free alias.
111-
// Therefore we need to check the `DefKind` first.
112-
if let DefKind::TyAlias = tcx.def_kind(def_id)
113-
&& tcx.type_alias_is_lazy(def_id)
114-
{
115-
self.add_constraints_from_ty(current_item, ty, self.covariant);
116-
return;
117-
}
118-
119107
match ty.kind() {
120108
ty::Adt(def, _) => {
121109
// Not entirely obvious: constraints on structs/enums do not
@@ -216,14 +204,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
216204
/// Adds constraints appropriate for an instance of `ty` appearing
217205
/// in a context with the generics defined in `generics` and
218206
/// ambient variance `variance`
207+
#[instrument(level = "debug", skip(self, current))]
219208
fn add_constraints_from_ty(
220209
&mut self,
221210
current: &CurrentItem,
222211
ty: Ty<'tcx>,
223212
variance: VarianceTermPtr<'a>,
224213
) {
225-
debug!("add_constraints_from_ty(ty={:?}, variance={:?})", ty, variance);
226-
227214
match *ty.kind() {
228215
ty::Bool
229216
| ty::Char
@@ -273,12 +260,15 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
273260
self.add_constraints_from_args(current, def.did(), args, variance);
274261
}
275262

276-
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, ref data) => {
277-
self.add_constraints_from_invariant_args(current, data.args, variance);
263+
ty::Alias(ty::Free, alias_ty) => {
264+
// For performance reasons, we can't just call
265+
// `expand_free_alias_tys` at the start of this function.
266+
let ty = self.tcx().type_of(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args);
267+
self.add_constraints_from_ty(current, ty, variance);
278268
}
279269

280-
ty::Alias(ty::Free, ref data) => {
281-
self.add_constraints_from_args(current, data.def_id, data.args, variance);
270+
ty::Alias(_, ref alias_ty) => {
271+
self.add_constraints_from_invariant_args(current, alias_ty.args, variance);
282272
}
283273

284274
ty::Dynamic(data, r) => {

compiler/rustc_hir_analysis/src/variance/dump.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,16 @@ pub(crate) fn variances(tcx: TyCtxt<'_>) {
3838
}
3939

4040
match tcx.def_kind(id) {
41-
DefKind::AssocFn | DefKind::Fn | DefKind::Enum | DefKind::Struct | DefKind::Union => {}
42-
DefKind::TyAlias if tcx.type_alias_is_lazy(id) => {}
41+
DefKind::AssocFn | DefKind::Fn | DefKind::Enum | DefKind::Struct | DefKind::Union => {
42+
tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id.def_id));
43+
}
4344
kind => {
4445
let message = format!(
4546
"attr parsing didn't report an error for `#[{}]` on {kind:?}",
4647
rustc_span::sym::rustc_dump_variances,
4748
);
4849
tcx.dcx().span_delayed_bug(tcx.def_span(id), message);
49-
continue;
5050
}
5151
}
52-
53-
tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id.def_id));
5452
}
5553
}

compiler/rustc_hir_analysis/src/variance/mod.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,6 @@ pub(super) fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Va
5151
let crate_map = tcx.crate_variances(());
5252
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
5353
}
54-
DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => {
55-
// These are inferred.
56-
let crate_map = tcx.crate_variances(());
57-
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
58-
}
5954
DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
6055
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
6156
return variance_of_opaque(

compiler/rustc_hir_analysis/src/variance/terms.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,6 @@ pub(crate) fn determine_parameters_to_be_inferred<'a, 'tcx>(
9999
}
100100
}
101101
DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id),
102-
DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => {
103-
terms_cx.add_inferreds_for_item(def_id)
104-
}
105102
_ => {}
106103
}
107104
}

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
11471147
| DefKind::Static { .. }
11481148
| DefKind::Const { .. }
11491149
| DefKind::ForeignMod
1150+
| DefKind::TyAlias
11501151
| DefKind::Impl { .. }
11511152
| DefKind::Trait
11521153
| DefKind::TraitAlias
@@ -1160,7 +1161,6 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
11601161
| DefKind::Closure
11611162
| DefKind::ExternCrate
11621163
| DefKind::SyntheticCoroutineBody => false,
1163-
DefKind::TyAlias => tcx.type_alias_is_lazy(def_id),
11641164
}
11651165
}
11661166

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Test that we check the body at the definition site for well-formedness.
2+
3+
#![feature(lazy_type_alias)]
4+
5+
// unsatisified trait bounds
6+
type _A<T> = <T as std::ops::Mul>::Output; //~ ERROR cannot multiply `T` by `T`
7+
type _B = Vec<str>; //~ ERROR the size for values of type `str` cannot be known at compilation time
8+
9+
// unsatisfied outlives-bounds
10+
type _C<'a> = &'static &'a (); //~ ERROR reference has a longer lifetime than the data it references
11+
12+
// diverging const exprs
13+
type _D = [(); panic!()]; //~ ERROR evaluation panicked
14+
15+
// dyn incompatibility
16+
type _E = dyn Sized; //~ ERROR the trait `Sized` is not dyn compatible
17+
18+
fn main() {}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
error[E0277]: cannot multiply `T` by `T`
2+
--> $DIR/def-site-body-wf.rs:6:14
3+
|
4+
LL | type _A<T> = <T as std::ops::Mul>::Output;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T`
6+
|
7+
help: consider restricting type parameter `T` with trait `Mul`
8+
|
9+
LL | type _A<T: std::ops::Mul> = <T as std::ops::Mul>::Output;
10+
| +++++++++++++++
11+
12+
error[E0277]: the size for values of type `str` cannot be known at compilation time
13+
--> $DIR/def-site-body-wf.rs:7:11
14+
|
15+
LL | type _B = Vec<str>;
16+
| ^^^^^^^^ doesn't have a size known at compile-time
17+
|
18+
= help: the trait `Sized` is not implemented for `str`
19+
note: required by an implicit `Sized` bound in `Vec`
20+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
21+
22+
error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references
23+
--> $DIR/def-site-body-wf.rs:10:1
24+
|
25+
LL | type _C<'a> = &'static &'a ();
26+
| ^^^^^^^^^^^
27+
|
28+
= note: the pointer is valid for the static lifetime
29+
note: but the referenced data is only valid for the lifetime `'a` as defined here
30+
--> $DIR/def-site-body-wf.rs:10:9
31+
|
32+
LL | type _C<'a> = &'static &'a ();
33+
| ^^
34+
35+
error[E0080]: evaluation panicked: explicit panic
36+
--> $DIR/def-site-body-wf.rs:13:16
37+
|
38+
LL | type _D = [(); panic!()];
39+
| ^^^^^^^^ evaluation of `_D::{constant#0}` failed here
40+
41+
error[E0038]: the trait `Sized` is not dyn compatible
42+
--> $DIR/def-site-body-wf.rs:16:11
43+
|
44+
LL | type _E = dyn Sized;
45+
| ^^^^^^^^^ `Sized` is not dyn compatible
46+
|
47+
= note: the trait is not dyn compatible because it requires `Self: Sized`
48+
= note: for a trait to be dyn compatible it needs to allow building a vtable
49+
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
50+
51+
error: aborting due to 5 previous errors
52+
53+
Some errors have detailed explanations: E0038, E0080, E0277, E0491.
54+
For more information about an error, try `rustc --explain E0038`.

tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ LL | type Poly0<T> = Poly1<(T,)>;
2323
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
2424

2525
error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
26-
--> $DIR/inherent-impls-overflow.rs:21:1
26+
--> $DIR/inherent-impls-overflow.rs:20:1
2727
|
2828
LL | type Poly1<T> = Poly0<(T,)>;
2929
| ^^^^^^^^^^^^^
3030
|
3131
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
3232

3333
error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
34-
--> $DIR/inherent-impls-overflow.rs:26:1
34+
--> $DIR/inherent-impls-overflow.rs:24:1
3535
|
3636
LL | impl Poly0<()> {}
3737
| ^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)