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>,
|
item: &'tcx hir::Item<'tcx>,
|
||||||
hir_generics: &hir::Generics<'tcx>,
|
hir_generics: &hir::Generics<'tcx>,
|
||||||
) {
|
) {
|
||||||
let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
|
|
||||||
|
|
||||||
match item.kind {
|
match item.kind {
|
||||||
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
|
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
|
||||||
for field in tcx.adt_def(item.owner_id).all_fields() {
|
// Ok
|
||||||
if field.ty(tcx, identity_args).references_error() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ItemKind::TyAlias(..) => {
|
ItemKind::TyAlias(..) => {
|
||||||
assert!(
|
assert!(
|
||||||
tcx.type_alias_is_lazy(item.owner_id),
|
tcx.type_alias_is_lazy(item.owner_id),
|
||||||
"should not be computing variance of non-weak type alias"
|
"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:?}"),
|
kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"),
|
||||||
}
|
}
|
||||||
@ -1955,6 +1946,15 @@ fn check_variances_for_type_defn<'tcx>(
|
|||||||
continue;
|
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 {
|
match hir_param.name {
|
||||||
hir::ParamName::Error => {}
|
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>(
|
fn report_bivariance<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param: &'tcx hir::GenericParam<'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