Skip to content

Commit 733e444

Browse files
committed
Prevent defining opaque types in nested items
1 parent d715644 commit 733e444

File tree

6 files changed

+129
-14
lines changed

6 files changed

+129
-14
lines changed

compiler/rustc_hir_analysis/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ hir_analysis_trait_object_declared_with_no_traits =
7272
hir_analysis_opaque_type_constrained_but_not_in_sig = opaque type constrained without being represented in the signature
7373
.item_label = this item must mention the opaque type in its signature or where bounds
7474
75+
hir_analysis_opaque_type_constrained_but_not_in_sibling = opaque type constrained in nested item
76+
.item_label = this item is not a sibling of the opaque type
77+
7578
hir_analysis_missing_type_params =
7679
the type {$parameterCount ->
7780
[one] parameter

compiler/rustc_hir_analysis/src/collect/type_of.rs

+61-11
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ use rustc_span::{sym, Span, DUMMY_SP};
2222

2323
use super::ItemCtxt;
2424
use super::{bad_placeholder, is_suggestable_infer_ty};
25-
use crate::errors::{OpaqueTypeConstrainedButNotInSig, UnconstrainedOpaqueType};
25+
use crate::errors::{
26+
OpaqueTypeConstrainedButNotInSig, OpaqueTypeConstrainedInNonSibling, UnconstrainedOpaqueType,
27+
};
2628

2729
/// Computes the relevant generic parameter for a potential generic const argument.
2830
///
@@ -640,13 +642,20 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
640642
let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
641643
debug!(?concrete_opaque_types);
642644
if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
643-
if let Err(item_def_id) =
645+
if let Err((item_def_id, sibling)) =
644646
may_define_opaque_type(self.tcx, item_def_id, self.def_id, concrete_type.span)
645647
{
646-
self.tcx.sess.emit_err(OpaqueTypeConstrainedButNotInSig {
647-
span: concrete_type.span,
648-
item_span: self.tcx.def_span(item_def_id),
649-
});
648+
if sibling {
649+
self.tcx.sess.emit_err(OpaqueTypeConstrainedButNotInSig {
650+
span: concrete_type.span,
651+
item_span: self.tcx.def_span(item_def_id),
652+
});
653+
} else {
654+
self.tcx.sess.emit_err(OpaqueTypeConstrainedInNonSibling {
655+
span: concrete_type.span,
656+
item_span: self.tcx.def_span(item_def_id),
657+
});
658+
}
650659
}
651660
debug!(?concrete_type, "found constraint");
652661
if let Some(prev) = &mut self.found {
@@ -766,8 +775,27 @@ fn may_define_opaque_type<'tcx>(
766775
def_id: LocalDefId,
767776
opaque_def_id: LocalDefId,
768777
span: Span,
769-
) -> Result<(), LocalDefId> {
770-
if tcx.is_descendant_of(opaque_def_id.to_def_id(), def_id.to_def_id()) {
778+
) -> Result<(), (LocalDefId, bool)> {
779+
let mut parent = tcx.local_parent(opaque_def_id);
780+
loop {
781+
trace!(?parent);
782+
match tcx.def_kind(parent) {
783+
DefKind::AssocTy | DefKind::TyAlias => {
784+
parent = tcx.local_parent(parent);
785+
break;
786+
}
787+
// Skip nested opaque types
788+
DefKind::OpaqueTy => {
789+
parent = tcx.local_parent(parent);
790+
}
791+
def_kind => {
792+
trace!(?def_kind);
793+
return Err((def_id, false));
794+
}
795+
}
796+
}
797+
trace!(?parent);
798+
if parent == def_id {
771799
// If the opaque type is defined in the body of a function, that function
772800
// may constrain the opaque type since it can't mention it in bounds.
773801
return Ok(());
@@ -777,9 +805,31 @@ fn may_define_opaque_type<'tcx>(
777805
return may_define_opaque_type(tcx, tcx.local_parent(def_id), opaque_def_id, span);
778806
}
779807

808+
let mut item_parent = tcx.local_parent(def_id);
809+
while item_parent != parent {
810+
trace!(?item_parent);
811+
match tcx.def_kind(item_parent) {
812+
// Skip impls, to allow methods to constrain opaque types from the surrounding module.
813+
DefKind::Impl { .. } | DefKind::Trait => {
814+
item_parent = tcx.local_parent(item_parent);
815+
}
816+
// Skip modules, to allow constraining opaque types in child modules
817+
DefKind::Mod => {
818+
item_parent = tcx.local_parent(item_parent);
819+
}
820+
def_kind => {
821+
trace!(?def_kind);
822+
break;
823+
}
824+
}
825+
}
826+
827+
if item_parent != parent {
828+
return Err((def_id, false));
829+
}
830+
780831
let param_env = tcx.param_env(def_id);
781832

782-
trace!(parent = ?tcx.parent(opaque_def_id.to_def_id()));
783833
fn has_tait<'tcx>(
784834
val: impl TypeVisitable<TyCtxt<'tcx>>,
785835
opaque_def_id: LocalDefId,
@@ -874,7 +924,7 @@ fn may_define_opaque_type<'tcx>(
874924
let tait_in_where_bounds =
875925
has_tait(tcx.predicates_of(def_id.to_def_id()).predicates, opaque_def_id, tcx, param_env);
876926
if tcx.features().type_alias_impl_trait_in_where_bounds {
877-
if tait_in_where_bounds { Ok(()) } else { Err(def_id) }
927+
if tait_in_where_bounds { Ok(()) } else { Err((def_id, true)) }
878928
} else {
879929
if tait_in_where_bounds {
880930
feature_err(
@@ -885,7 +935,7 @@ fn may_define_opaque_type<'tcx>(
885935
)
886936
.emit();
887937
}
888-
Err(def_id)
938+
Err((def_id, true))
889939
}
890940
}
891941

compiler/rustc_hir_analysis/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,14 @@ pub struct OpaqueTypeConstrainedButNotInSig {
184184
#[label(hir_analysis_item_label)]
185185
pub item_span: Span,
186186
}
187+
#[derive(Diagnostic)]
188+
#[diag(hir_analysis_opaque_type_constrained_but_not_in_sibling)]
189+
pub struct OpaqueTypeConstrainedInNonSibling {
190+
#[primary_span]
191+
pub span: Span,
192+
#[label(hir_analysis_item_label)]
193+
pub item_span: Span,
194+
}
187195

188196
pub struct MissingTypeParams {
189197
pub span: Span,

tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,7 @@ where
104104
// Type in const path
105105
const {
106106
pub struct Foo;
107-
fn foo() -> Type5 {
108-
Foo
109-
}
107+
let _: Type5 = Foo;
110108
};
111109

112110
// Type in impl path
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#![feature(type_alias_impl_trait)]
2+
3+
fn main() {}
4+
5+
type Foo = impl std::fmt::Display;
6+
7+
fn bar() {
8+
pub fn foo() -> Foo {
9+
"foo"
10+
//~^ ERROR: opaque type constrained in nested item
11+
}
12+
}
13+
14+
fn baz() -> Foo {
15+
pub fn foo() -> Foo {
16+
"foo"
17+
//~^ ERROR: opaque type constrained in nested item
18+
}
19+
"baz"
20+
}
21+
22+
struct Bak {
23+
x: [u8; {
24+
fn blob() -> Foo {
25+
"blob"
26+
//~^ ERROR: opaque type constrained in nested item
27+
}
28+
5
29+
}],
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: opaque type constrained in nested item
2+
--> $DIR/defining-use-item-child.rs:9:9
3+
|
4+
LL | pub fn foo() -> Foo {
5+
| ------------------- this item is not a sibling of the opaque type
6+
LL | "foo"
7+
| ^^^^^
8+
9+
error: opaque type constrained in nested item
10+
--> $DIR/defining-use-item-child.rs:16:9
11+
|
12+
LL | pub fn foo() -> Foo {
13+
| ------------------- this item is not a sibling of the opaque type
14+
LL | "foo"
15+
| ^^^^^
16+
17+
error: opaque type constrained in nested item
18+
--> $DIR/defining-use-item-child.rs:25:13
19+
|
20+
LL | fn blob() -> Foo {
21+
| ---------------- this item is not a sibling of the opaque type
22+
LL | "blob"
23+
| ^^^^^^
24+
25+
error: aborting due to 3 previous errors
26+

0 commit comments

Comments
 (0)