Skip to content

Commit fa6be71

Browse files
authored
Unrolled build for rust-lang#127976
Rollup merge of rust-lang#127976 - fmease:lta-cyclic-bivariant-param-better-err, r=compiler-errors Lazy type aliases: Diagostics: Detect bivariant ty params that are only used recursively Follow-up to errs's rust-lang#127871. Extends the logic to cover LTAs, too, not just ADTs. This change only takes effect with the next-gen solver enabled as cycle errors like the one we have here are fatal in the old solver. That's my explanation anyways. r? compiler-errors
2 parents 0cd01aa + 756459e commit fa6be71

File tree

3 files changed

+50
-50
lines changed

3 files changed

+50
-50
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+37-36
Original file line numberDiff line numberDiff line change
@@ -1922,39 +1922,31 @@ fn report_bivariance<'tcx>(
19221922
);
19231923

19241924
if !usage_spans.is_empty() {
1925-
// First, check if the ADT is (probably) cyclical. We say probably here, since
1926-
// we're not actually looking into substitutions, just walking through fields.
1927-
// And we only recurse into the fields of ADTs, and not the hidden types of
1928-
// opaques or anything else fancy.
1925+
// First, check if the ADT/LTA is (probably) cyclical. We say probably here, since we're
1926+
// not actually looking into substitutions, just walking through fields / the "RHS".
1927+
// We don't recurse into the hidden types of opaques or anything else fancy.
19291928
let item_def_id = item.owner_id.to_def_id();
1930-
let is_probably_cyclical = if matches!(
1931-
tcx.def_kind(item_def_id),
1932-
DefKind::Struct | DefKind::Union | DefKind::Enum
1933-
) {
1934-
IsProbablyCyclical { tcx, adt_def_id: item_def_id, seen: Default::default() }
1935-
.visit_all_fields(tcx.adt_def(item_def_id))
1936-
.is_break()
1937-
} else {
1938-
false
1939-
};
1940-
// If the ADT is cyclical, then if at least one usage of the type parameter or
1941-
// the `Self` alias is present in the, then it's probably a cyclical struct, and
1942-
// we should call those parameter usages recursive rather than just saying they're
1943-
// unused...
1929+
let is_probably_cyclical =
1930+
IsProbablyCyclical { tcx, item_def_id, seen: Default::default() }
1931+
.visit_def(item_def_id)
1932+
.is_break();
1933+
// If the ADT/LTA is cyclical, then if at least one usage of the type parameter or
1934+
// the `Self` alias is present in the, then it's probably a cyclical struct/ type
1935+
// alias, and we should call those parameter usages recursive rather than just saying
1936+
// they're unused...
19441937
//
19451938
// We currently report *all* of the parameter usages, since computing the exact
19461939
// subset is very involved, and the fact we're mentioning recursion at all is
19471940
// likely to guide the user in the right direction.
19481941
if is_probably_cyclical {
1949-
let diag = tcx.dcx().create_err(errors::RecursiveGenericParameter {
1942+
return tcx.dcx().emit_err(errors::RecursiveGenericParameter {
19501943
spans: usage_spans,
19511944
param_span: param.span,
19521945
param_name,
19531946
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
19541947
help,
19551948
note: (),
19561949
});
1957-
return diag.emit();
19581950
}
19591951
}
19601952

@@ -1974,42 +1966,51 @@ fn report_bivariance<'tcx>(
19741966
diag.emit()
19751967
}
19761968

1977-
/// Detects cases where an ADT is trivially cyclical -- we want to detect this so
1978-
/// /we only mention that its parameters are used cyclically if the ADT is truly
1969+
/// Detects cases where an ADT/LTA is trivially cyclical -- we want to detect this so
1970+
/// we only mention that its parameters are used cyclically if the ADT/LTA is truly
19791971
/// cyclical.
19801972
///
19811973
/// Notably, we don't consider substitutions here, so this may have false positives.
19821974
struct IsProbablyCyclical<'tcx> {
19831975
tcx: TyCtxt<'tcx>,
1984-
adt_def_id: DefId,
1976+
item_def_id: DefId,
19851977
seen: FxHashSet<DefId>,
19861978
}
19871979

19881980
impl<'tcx> IsProbablyCyclical<'tcx> {
1989-
fn visit_all_fields(&mut self, adt_def: ty::AdtDef<'tcx>) -> ControlFlow<(), ()> {
1990-
for field in adt_def.all_fields() {
1991-
self.tcx.type_of(field.did).instantiate_identity().visit_with(self)?;
1981+
fn visit_def(&mut self, def_id: DefId) -> ControlFlow<(), ()> {
1982+
match self.tcx.def_kind(def_id) {
1983+
DefKind::Struct | DefKind::Enum | DefKind::Union => {
1984+
self.tcx.adt_def(def_id).all_fields().try_for_each(|field| {
1985+
self.tcx.type_of(field.did).instantiate_identity().visit_with(self)
1986+
})
1987+
}
1988+
DefKind::TyAlias if self.tcx.type_alias_is_lazy(def_id) => {
1989+
self.tcx.type_of(def_id).instantiate_identity().visit_with(self)
1990+
}
1991+
_ => ControlFlow::Continue(()),
19921992
}
1993-
1994-
ControlFlow::Continue(())
19951993
}
19961994
}
19971995

19981996
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsProbablyCyclical<'tcx> {
19991997
type Result = ControlFlow<(), ()>;
20001998

2001-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
2002-
if let Some(adt_def) = t.ty_adt_def() {
2003-
if adt_def.did() == self.adt_def_id {
1999+
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
2000+
let def_id = match ty.kind() {
2001+
ty::Adt(adt_def, _) => Some(adt_def.did()),
2002+
ty::Alias(ty::Weak, alias_ty) => Some(alias_ty.def_id),
2003+
_ => None,
2004+
};
2005+
if let Some(def_id) = def_id {
2006+
if def_id == self.item_def_id {
20042007
return ControlFlow::Break(());
20052008
}
2006-
2007-
if self.seen.insert(adt_def.did()) {
2008-
self.visit_all_fields(adt_def)?;
2009+
if self.seen.insert(def_id) {
2010+
self.visit_def(def_id)?;
20092011
}
20102012
}
2011-
2012-
t.super_visit_with(self)
2013+
ty.super_visit_with(self)
20132014
}
20142015
}
20152016

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

+11-12
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,27 @@ error[E0275]: overflow evaluating the requirement `Loop == _`
44
LL | impl Loop {}
55
| ^^^^
66

7-
error[E0392]: type parameter `T` is never used
8-
--> $DIR/inherent-impls-overflow.rs:14:12
7+
error: type parameter `T` is only used recursively
8+
--> $DIR/inherent-impls-overflow.rs:14:24
99
|
1010
LL | type Poly0<T> = Poly1<(T,)>;
11-
| ^ - `T` is named here, but is likely unused in the containing type
11+
| - ^
1212
| |
13-
| unused type parameter
13+
| type parameter must be used non-recursively in the definition
1414
|
1515
= help: consider removing `T` or referring to it in the body of the type alias
16-
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
16+
= note: all type parameters must be used in a non-recursive way in order to constrain their variance
1717

18-
error[E0392]: type parameter `T` is never used
19-
--> $DIR/inherent-impls-overflow.rs:17:12
18+
error: type parameter `T` is only used recursively
19+
--> $DIR/inherent-impls-overflow.rs:17:24
2020
|
2121
LL | type Poly1<T> = Poly0<(T,)>;
22-
| ^ - `T` is named here, but is likely unused in the containing type
22+
| - ^
2323
| |
24-
| unused type parameter
24+
| type parameter must be used non-recursively in the definition
2525
|
2626
= help: consider removing `T` or referring to it in the body of the type alias
27-
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
27+
= note: all type parameters must be used in a non-recursive way in order to constrain their variance
2828

2929
error[E0275]: overflow evaluating the requirement `Poly0<()> == _`
3030
--> $DIR/inherent-impls-overflow.rs:21:6
@@ -36,5 +36,4 @@ LL | impl Poly0<()> {}
3636

3737
error: aborting due to 4 previous errors
3838

39-
Some errors have detailed explanations: E0275, E0392.
40-
For more information about an error, try `rustc --explain E0275`.
39+
For more information about this error, try `rustc --explain E0275`.

tests/ui/lazy-type-alias/inherent-impls-overflow.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ impl Loop {}
1313

1414
type Poly0<T> = Poly1<(T,)>;
1515
//[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
16-
//[next]~^^ ERROR type parameter `T` is never used
16+
//[next]~^^ ERROR type parameter `T` is only used recursively
1717
type Poly1<T> = Poly0<(T,)>;
1818
//[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
19-
//[next]~^^ ERROR type parameter `T` is never used
19+
//[next]~^^ ERROR type parameter `T` is only used recursively
2020

2121
impl Poly0<()> {}
2222
//[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`

0 commit comments

Comments
 (0)