Don't report bivariance error when nesting a struct with field errors into another struct
This commit is contained in:
parent
a0c2aba29a
commit
68885216b6
@ -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>,
|
||||
|
13
tests/ui/variance/type-resolve-error-two-structs-deep.rs
Normal file
13
tests/ui/variance/type-resolve-error-two-structs-deep.rs
Normal 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() {}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user