Don't report bivariance error when nesting a struct with field errors into another struct

This commit is contained in:
Michael Goulet 2024-10-15 14:58:41 -04:00
parent a0c2aba29a
commit 68885216b6
3 changed files with 72 additions and 10 deletions

View File

@ -1875,24 +1875,15 @@ fn check_variances_for_type_defn<'tcx>(
item: &'tcx hir::Item<'tcx>,
hir_generics: &hir::Generics<'tcx>,
) {
let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
match item.kind {
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
for field in tcx.adt_def(item.owner_id).all_fields() {
if field.ty(tcx, identity_args).references_error() {
return;
}
}
// Ok
}
ItemKind::TyAlias(..) => {
assert!(
tcx.type_alias_is_lazy(item.owner_id),
"should not be computing variance of non-weak type alias"
);
if tcx.type_of(item.owner_id).skip_binder().references_error() {
return;
}
}
kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"),
}
@ -1955,6 +1946,15 @@ fn check_variances_for_type_defn<'tcx>(
continue;
}
// Look for `ErrorGuaranteed` deeply within this type.
if let ControlFlow::Break(ErrorGuaranteed { .. }) = tcx
.type_of(item.owner_id)
.instantiate_identity()
.visit_with(&mut HasErrorDeep { tcx, seen: Default::default() })
{
continue;
}
match hir_param.name {
hir::ParamName::Error => {}
_ => {
@ -1965,6 +1965,46 @@ fn check_variances_for_type_defn<'tcx>(
}
}
/// Look for `ErrorGuaranteed` deeply within structs' (unsubstituted) fields.
struct HasErrorDeep<'tcx> {
tcx: TyCtxt<'tcx>,
seen: FxHashSet<DefId>,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasErrorDeep<'tcx> {
type Result = ControlFlow<ErrorGuaranteed>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
match *ty.kind() {
ty::Adt(def, _) => {
if self.seen.insert(def.did()) {
for field in def.all_fields() {
self.tcx.type_of(field.did).instantiate_identity().visit_with(self)?;
}
}
}
ty::Error(guar) => return ControlFlow::Break(guar),
_ => {}
}
ty.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
if let Err(guar) = r.error_reported() {
ControlFlow::Break(guar)
} else {
ControlFlow::Continue(())
}
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
if let Err(guar) = c.error_reported() {
ControlFlow::Break(guar)
} else {
ControlFlow::Continue(())
}
}
}
fn report_bivariance<'tcx>(
tcx: TyCtxt<'tcx>,
param: &'tcx hir::GenericParam<'tcx>,

View File

@ -0,0 +1,13 @@
// Make sure we don't report bivariance errors when nesting structs w/ unresolved
// fields into *other* structs.
struct Hello<'a> {
missing: Missing<'a>,
//~^ ERROR cannot find type `Missing` in this scope
}
struct Other<'a> {
hello: Hello<'a>,
}
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0412]: cannot find type `Missing` in this scope
--> $DIR/type-resolve-error-two-structs-deep.rs:5:14
|
LL | missing: Missing<'a>,
| ^^^^^^^ not found in this scope
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0412`.