Skip to content

Commit 21548b4

Browse files
committed
add typevisitor for rejecting fields with nested type alias impl types
1 parent cba8b4c commit 21548b4

18 files changed

+245
-115
lines changed

compiler/rustc_typeck/src/check/check.rs

+124-73
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_attr as attr;
77
use rustc_errors::{Applicability, ErrorReported};
88
use rustc_hir as hir;
99
use rustc_hir::def_id::{DefId, LocalDefId};
10-
use rustc_hir::intravisit::Visitor;
10+
use rustc_hir::intravisit::{self, Visitor};
1111
use rustc_hir::lang_items::LangItem;
1212
use rustc_hir::{def::DefKind, def::Res, ItemKind, Node, PathSegment};
1313
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -437,40 +437,82 @@ fn check_fields_for_opaque_types(
437437
def_id: LocalDefId,
438438
span: Span,
439439
) {
440-
fn find_span_of_field_def_and_ty_alias(
440+
struct TyAliasFinder<'tcx> {
441+
tcx: TyCtxt<'tcx>,
442+
ty_alias_span: Option<Span>,
443+
ty_alias_ident: Option<Ident>,
444+
field_ty_span: Option<Span>,
445+
}
446+
447+
impl TyAliasFinder<'_> {
448+
fn new(tcx: TyCtxt<'tcx>) -> TyAliasFinder<'_> {
449+
TyAliasFinder { tcx, ty_alias_span: None, ty_alias_ident: None, field_ty_span: None }
450+
}
451+
452+
fn get_collected_information(&self) -> (Option<Span>, Option<Ident>, Option<Span>) {
453+
(self.field_ty_span, self.ty_alias_ident, self.ty_alias_span)
454+
}
455+
}
456+
457+
impl<'tcx> intravisit::Visitor<'tcx> for TyAliasFinder<'tcx> {
458+
type Map = intravisit::ErasedMap<'tcx>;
459+
460+
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
461+
intravisit::NestedVisitorMap::None
462+
}
463+
464+
fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) {
465+
if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = t.kind {
466+
if let Res::Def(DefKind::TyAlias, ty_alias_def_id) = path.res {
467+
let span = path.span;
468+
if let Some(ty_alias_local_id) = ty_alias_def_id.as_local() {
469+
let ty_alias_hir_id =
470+
self.tcx.hir().local_def_id_to_hir_id(ty_alias_local_id);
471+
let node = self.tcx.hir().get(ty_alias_hir_id);
472+
match node {
473+
hir::Node::Item(hir::Item {
474+
ident, kind, span: ty_alias_span, ..
475+
}) => match kind {
476+
hir::ItemKind::TyAlias(_, _) => {
477+
self.ty_alias_span = Some(*ty_alias_span);
478+
self.ty_alias_ident = Some(*ident);
479+
self.field_ty_span = Some(span);
480+
return;
481+
}
482+
_ => bug!("expected an item of kind TyAlias"),
483+
},
484+
_ => {
485+
self.field_ty_span = Some(span);
486+
return;
487+
}
488+
}
489+
}
490+
}
491+
}
492+
intravisit::walk_ty(self, t);
493+
}
494+
}
495+
496+
fn find_ty_alias_information(
441497
tcx: TyCtxt<'tcx>,
442498
field_def: &ty::FieldDef,
443-
) -> (Option<Span>, Option<Span>) {
499+
) -> (Option<Span>, Option<Span>, Option<Ident>, Option<Span>) {
444500
let field_def_def_id = field_def.did;
445501
if let Some(field_def_local_id) = field_def_def_id.as_local() {
446502
let field_def_hir_id = tcx.hir().local_def_id_to_hir_id(field_def_local_id);
447503
if let hir::Node::Field(hir::FieldDef {
448504
span: field_def_span, ty: field_def_ty, ..
449505
}) = tcx.hir().get(field_def_hir_id)
450506
{
451-
if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = field_def_ty.kind {
452-
if let Res::Def(DefKind::TyAlias, ty_alias_def_id) = path.res {
453-
if let Some(ty_alias_local_id) = ty_alias_def_id.as_local() {
454-
let ty_alias_hir_id =
455-
tcx.hir().local_def_id_to_hir_id(ty_alias_local_id);
456-
let node = tcx.hir().get(ty_alias_hir_id);
457-
match node {
458-
hir::Node::Item(hir::Item {
459-
kind, span: ty_alias_span, ..
460-
}) => match kind {
461-
hir::ItemKind::TyAlias(_, _) => {
462-
return (Some(*field_def_span), Some(*ty_alias_span));
463-
}
464-
_ => bug!("expected an item of kind TyAlias"),
465-
},
466-
_ => return (Some(*field_def_span), None),
467-
}
468-
}
469-
}
470-
}
507+
let mut type_alias_finder = TyAliasFinder::new(tcx);
508+
type_alias_finder.visit_ty(field_def_ty);
509+
510+
let (field_ty_span, ty_alias_ident, ty_alias_span) =
511+
type_alias_finder.get_collected_information();
512+
return (Some(*field_def_span), field_ty_span, ty_alias_ident, ty_alias_span);
471513
}
472514
}
473-
(None, None)
515+
(None, None, None, None)
474516
}
475517

476518
debug!("check_fields_of_opaque_types(adt_def: {:?}, span: {:?})", adt_def, span);
@@ -484,59 +526,68 @@ fn check_fields_for_opaque_types(
484526
debug!("field_def: {:?}", field_def);
485527

486528
let field_ty = field_def.ty(tcx, substs);
487-
match field_ty.kind() {
488-
ty::Opaque(..) => {
489-
use ty::AdtKind::*;
490-
let adt_kind = match adt_def.adt_kind() {
491-
Struct => "struct",
492-
Enum => "enum",
493-
Union => "union",
494-
};
495-
496-
let mut diag;
497-
match find_span_of_field_def_and_ty_alias(tcx, field_def) {
498-
(Some(field_def_span), Some(ty_alias_span)) => {
499-
diag = tcx.sess.struct_span_err(
500-
span,
501-
&format!(
502-
"type alias impl traits are not allowed as field types in {}s",
503-
adt_kind
504-
),
505-
);
506-
diag.span_label(
507-
field_def_span,
508-
"this field contains a type alias impl trait",
509-
);
510-
diag.span_label(ty_alias_span, "type alias defined here");
511-
}
512-
(Some(field_def_span), None) => {
513-
diag = tcx.sess.struct_span_err(
514-
span,
515-
&format!(
516-
"type alias impl traits are not allowed as field types in {}s",
517-
adt_kind
518-
),
519-
);
529+
if field_ty.has_opaque_types() {
530+
use ty::AdtKind::*;
531+
let adt_kind = match adt_def.adt_kind() {
532+
Struct => "struct",
533+
Enum => "enum",
534+
Union => "union",
535+
};
520536

521-
diag.span_label(
522-
field_def_span,
523-
"this field contains a type alias impl trait",
524-
);
525-
}
526-
_ => {
527-
diag = tcx.sess.struct_span_err(
528-
span,
529-
&format!(
530-
"type alias impl traits are not allowed as field types in {}s",
531-
adt_kind
532-
),
533-
);
534-
}
537+
let mut diag;
538+
match find_ty_alias_information(tcx, field_def) {
539+
(
540+
Some(field_def_span),
541+
Some(field_ty_span),
542+
Some(ty_alias_ident),
543+
Some(ty_alias_span),
544+
) => {
545+
diag = tcx.sess.struct_span_err(
546+
span,
547+
&format!(
548+
"type aliases of `impl Trait` are not allowed as field types in {}s",
549+
adt_kind
550+
),
551+
);
552+
let field_def_span_msg = format!(
553+
"this field contains a type alias `{}` of an `impl Trait`",
554+
ty_alias_ident
555+
);
556+
557+
let field_ty_span_msg =
558+
"this type is a type alias of an `impl Trait`".to_string();
559+
560+
diag.span_label(field_def_span, field_def_span_msg);
561+
diag.span_label(field_ty_span, field_ty_span_msg);
562+
diag.span_label(ty_alias_span, "type alias defined here");
535563
}
564+
(Some(field_def_span), Some(field_ty_span), None, None) => {
565+
diag = tcx.sess.struct_span_err(
566+
span,
567+
&format!(
568+
"type aliases of `impl Trait` are not allowed as field types in {}s",
569+
adt_kind
570+
),
571+
);
536572

537-
diag.emit();
573+
diag.span_label(
574+
field_def_span,
575+
"this field contains a type alias of an `impl trait`",
576+
);
577+
diag.span_label(field_ty_span, "this type is a type alias of an `impl trait`");
578+
}
579+
_ => {
580+
diag = tcx.sess.struct_span_err(
581+
span,
582+
&format!(
583+
"type alias impl traits are not allowed as field types in {}s",
584+
adt_kind
585+
),
586+
);
587+
}
538588
}
539-
_ => {}
589+
590+
diag.emit();
540591
}
541592
});
542593
}

src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ type Foo = impl Debug;
66
//~^ ERROR could not find defining uses
77

88
struct Bar(Foo);
9-
//~^ ERROR type alias impl traits are not allowed as field types in structs
9+
//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs
1010
fn define() -> Bar {
1111
Bar(42) //~ ERROR mismatched types
1212
}

src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr

+3-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ error: could not find defining uses
6060
LL | type Foo = impl Debug;
6161
| ^^^^^^^^^^
6262

63-
error: type alias impl traits are not allowed as field types in structs
63+
error: type aliases of `impl Trait` are not allowed as field types in structs
6464
--> $DIR/feature-gate-type_alias_impl_trait.rs:8:1
6565
|
6666
LL | type Foo = impl Debug;
@@ -69,7 +69,8 @@ LL | type Foo = impl Debug;
6969
LL | struct Bar(Foo);
7070
| ^^^^^^^^^^^---^^
7171
| |
72-
| this field contains a type alias impl trait
72+
| this field contains a type alias `Foo` of an `impl Trait`
73+
| this type is a type alias of an `impl Trait`
7374

7475
error: could not find defining uses
7576
--> $DIR/feature-gate-type_alias_impl_trait.rs:20:13

src/test/ui/impl-trait/reject-opaque_types-in-fields.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ type ImplCopy = impl Copy;
44
//~^ ERROR could not find defining uses
55

66
enum Wrapper {
7-
//~^ ERROR type alias impl traits are not allowed as field types in enums
7+
//~^ ERROR type aliases of `impl Trait` are not allowed as field types in enums
88
First(ImplCopy),
99
Second
1010
}
@@ -13,7 +13,7 @@ type X = impl Iterator<Item = u64> + Unpin;
1313
//~^ ERROR could not find defining uses
1414

1515
struct Foo(X);
16-
//~^ ERROR type alias impl traits are not allowed as field types in structs
16+
//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs
1717

1818
impl Foo {
1919
fn new(z: Vec<u64>) -> Self {
@@ -22,8 +22,11 @@ impl Foo {
2222
}
2323
}
2424

25+
struct FooNested(Vec<X>);
26+
//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs
27+
2528
struct Bar {a : X}
26-
//~^ ERROR type alias impl traits are not allowed as field types in structs
29+
//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs
2730

2831
impl Bar {
2932
fn new(z: Vec<u64>) -> Self {
@@ -33,7 +36,7 @@ impl Bar {
3336
}
3437

3538
union MyUnion {
36-
//~^ ERROR type alias impl traits are not allowed as field types in unions
39+
//~^ ERROR type aliases of `impl Trait` are not allowed as field types in unions
3740
a: X,
3841
//~^ ERROR unions may not contain fields that need dropping
3942
}

0 commit comments

Comments
 (0)