Skip to content

Commit 1d5ea10

Browse files
committed
Require any function with a tait in its signature to actually constrain a hidden type
1 parent ccb160d commit 1d5ea10

File tree

106 files changed

+1210
-637
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+1210
-637
lines changed

Diff for: compiler/rustc_codegen_cranelift/example/issue-72793.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,23 @@
22

33
#![feature(type_alias_impl_trait)]
44

5-
trait T {
6-
type Item;
7-
}
5+
mod helper {
6+
pub trait T {
7+
type Item;
8+
}
89

9-
type Alias<'a> = impl T<Item = &'a ()>;
10+
pub type Alias<'a> = impl T<Item = &'a ()>;
1011

11-
struct S;
12-
impl<'a> T for &'a S {
13-
type Item = &'a ();
14-
}
12+
struct S;
13+
impl<'a> T for &'a S {
14+
type Item = &'a ();
15+
}
1516

16-
fn filter_positive<'a>() -> Alias<'a> {
17-
&S
17+
pub fn filter_positive<'a>() -> Alias<'a> {
18+
&S
19+
}
1820
}
21+
use helper::*;
1922

2023
fn with_positive(fun: impl Fn(Alias<'_>)) {
2124
fun(filter_positive());

Diff for: compiler/rustc_data_structures/src/obligation_forest/mod.rs

+16-11
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,6 @@ pub enum ProcessResult<O, E> {
146146
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
147147
struct ObligationTreeId(usize);
148148

149-
type ObligationTreeIdGenerator = impl Iterator<Item = ObligationTreeId>;
150-
151149
pub struct ObligationForest<O: ForestObligation> {
152150
/// The list of obligations. In between calls to [Self::process_obligations],
153151
/// this list only contains nodes in the `Pending` or `Waiting` state.
@@ -310,18 +308,25 @@ pub struct Error<O, E> {
310308
pub backtrace: Vec<O>,
311309
}
312310

313-
impl<O: ForestObligation> ObligationForest<O> {
314-
pub fn new() -> ObligationForest<O> {
315-
ObligationForest {
316-
nodes: vec![],
317-
done_cache: Default::default(),
318-
active_cache: Default::default(),
319-
reused_node_vec: vec![],
320-
obligation_tree_id_generator: (0..).map(ObligationTreeId),
321-
error_cache: Default::default(),
311+
mod helper {
312+
use super::*;
313+
pub type ObligationTreeIdGenerator = impl Iterator<Item = ObligationTreeId>;
314+
impl<O: ForestObligation> ObligationForest<O> {
315+
pub fn new() -> ObligationForest<O> {
316+
ObligationForest {
317+
nodes: vec![],
318+
done_cache: Default::default(),
319+
active_cache: Default::default(),
320+
reused_node_vec: vec![],
321+
obligation_tree_id_generator: (0..).map(ObligationTreeId),
322+
error_cache: Default::default(),
323+
}
322324
}
323325
}
326+
}
327+
use helper::*;
324328

329+
impl<O: ForestObligation> ObligationForest<O> {
325330
/// Returns the total number of nodes in the forest that have not
326331
/// yet been fully resolved.
327332
pub fn len(&self) -> usize {

Diff for: compiler/rustc_hir_analysis/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,10 @@ hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden
340340
hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
341341
.note = this item must mention the opaque type in its signature in order to be able to register hidden types
342342
343+
hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`, but has it in its signature
344+
.note = consider moving the opaque type's declaration and defining uses into a separate module
345+
.opaque = this opaque type is in the signature
346+
343347
hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
344348
345349
hir_analysis_too_large_static = extern static is too large for the current architecture

Diff for: compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_middle::hir::nested_filter;
77
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
88
use rustc_span::{sym, DUMMY_SP};
99

10-
use crate::errors::{TaitForwardCompat, TypeOf, UnconstrainedOpaqueType};
10+
use crate::errors::{TaitForwardCompat, TaitForwardCompat2, TypeOf, UnconstrainedOpaqueType};
1111

1212
pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) {
1313
if tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) {
@@ -151,13 +151,17 @@ impl TaitConstraintLocator<'_> {
151151
return;
152152
}
153153

154+
let opaques = self.tcx.opaque_types_defined_by(item_def_id);
155+
let opaque_type_must_be_defined = opaques.in_signature.contains(&self.def_id);
156+
let opaque_type_may_be_defined = opaques.in_body.contains(&self.def_id);
157+
154158
let mut constrained = false;
155159
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
156160
if opaque_type_key.def_id != self.def_id {
157161
continue;
158162
}
159163
constrained = true;
160-
if !self.tcx.opaque_types_defined_by(item_def_id).contains(&self.def_id) {
164+
if !opaque_type_must_be_defined && !opaque_type_may_be_defined {
161165
self.tcx.sess.emit_err(TaitForwardCompat {
162166
span: hidden_type.span,
163167
item_span: self
@@ -179,6 +183,16 @@ impl TaitConstraintLocator<'_> {
179183

180184
if !constrained {
181185
debug!("no constraints in typeck results");
186+
if opaque_type_must_be_defined {
187+
self.tcx.sess.emit_err(TaitForwardCompat2 {
188+
span: self
189+
.tcx
190+
.def_ident_span(item_def_id)
191+
.unwrap_or_else(|| self.tcx.def_span(item_def_id)),
192+
opaque_type_span: self.tcx.def_span(self.def_id),
193+
opaque_type: self.tcx.def_path_str(self.def_id),
194+
});
195+
}
182196
return;
183197
};
184198

Diff for: compiler/rustc_hir_analysis/src/errors.rs

+11
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,17 @@ pub struct TaitForwardCompat {
194194
pub item_span: Span,
195195
}
196196

197+
#[derive(Diagnostic)]
198+
#[diag(hir_analysis_tait_forward_compat2)]
199+
#[note]
200+
pub struct TaitForwardCompat2 {
201+
#[primary_span]
202+
pub span: Span,
203+
#[note(hir_analysis_opaque)]
204+
pub opaque_type_span: Span,
205+
pub opaque_type: String,
206+
}
207+
197208
pub struct MissingTypeParams {
198209
pub span: Span,
199210
pub def_span: Span,

Diff for: compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,10 @@ impl<T> Trait<T> for X {
289289
) =>
290290
{
291291
if tcx.is_type_alias_impl_trait(alias.def_id) {
292-
if !tcx
292+
let opaques = tcx
293293
.opaque_types_defined_by(body_owner_def_id.expect_local())
294-
.contains(&alias.def_id.expect_local())
294+
;
295+
if !opaques.in_body.contains(&alias.def_id.expect_local()) && !opaques.in_signature.contains(&alias.def_id.expect_local())
295296
{
296297
let sp = tcx
297298
.def_ident_span(body_owner_def_id)

Diff for: compiler/rustc_infer/src/infer/opaque_types.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,12 @@ impl<'tcx> InferCtxt<'tcx> {
387387
// Named `type Foo = impl Bar;`
388388
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
389389
if in_assoc_ty {
390-
self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
390+
self.tcx.opaque_types_defined_by(parent_def_id).in_body.contains(&def_id)
391+
|| self
392+
.tcx
393+
.opaque_types_defined_by(parent_def_id)
394+
.in_signature
395+
.contains(&def_id)
391396
} else {
392397
may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
393398
}

Diff for: compiler/rustc_middle/src/mir/terminator.rs

+46-37
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,6 @@ pub struct Terminator<'tcx> {
291291
pub kind: TerminatorKind<'tcx>,
292292
}
293293

294-
pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
295294
pub type SuccessorsMut<'a> =
296295
iter::Chain<std::option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
297296

@@ -317,47 +316,57 @@ impl<'tcx> TerminatorKind<'tcx> {
317316
pub fn if_(cond: Operand<'tcx>, t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
318317
TerminatorKind::SwitchInt { discr: cond, targets: SwitchTargets::static_if(0, f, t) }
319318
}
319+
}
320320

321-
pub fn successors(&self) -> Successors<'_> {
322-
use self::TerminatorKind::*;
323-
match *self {
324-
Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. }
325-
| Yield { resume: t, drop: Some(ref u), .. }
326-
| Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
327-
| Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
328-
| FalseUnwind { real_target: t, unwind: UnwindAction::Cleanup(ref u) }
329-
| InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => {
330-
Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
331-
}
332-
Goto { target: t }
333-
| Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
334-
| Call { target: Some(t), unwind: _, .. }
335-
| Yield { resume: t, drop: None, .. }
336-
| Drop { target: t, unwind: _, .. }
337-
| Assert { target: t, unwind: _, .. }
338-
| FalseUnwind { real_target: t, unwind: _ }
339-
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
340-
| InlineAsm { destination: Some(t), unwind: _, .. } => {
341-
Some(t).into_iter().chain((&[]).into_iter().copied())
342-
}
343-
UnwindResume
344-
| UnwindTerminate(_)
345-
| CoroutineDrop
346-
| Return
347-
| Unreachable
348-
| Call { target: None, unwind: _, .. }
349-
| InlineAsm { destination: None, unwind: _, .. } => {
350-
None.into_iter().chain((&[]).into_iter().copied())
351-
}
352-
SwitchInt { ref targets, .. } => {
353-
None.into_iter().chain(targets.targets.iter().copied())
321+
pub use helper::*;
322+
323+
mod helper {
324+
use super::*;
325+
pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
326+
impl<'tcx> TerminatorKind<'tcx> {
327+
pub fn successors(&self) -> Successors<'_> {
328+
use self::TerminatorKind::*;
329+
match *self {
330+
Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. }
331+
| Yield { resume: t, drop: Some(ref u), .. }
332+
| Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
333+
| Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
334+
| FalseUnwind { real_target: t, unwind: UnwindAction::Cleanup(ref u) }
335+
| InlineAsm {
336+
destination: Some(t), unwind: UnwindAction::Cleanup(ref u), ..
337+
} => Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied()),
338+
Goto { target: t }
339+
| Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
340+
| Call { target: Some(t), unwind: _, .. }
341+
| Yield { resume: t, drop: None, .. }
342+
| Drop { target: t, unwind: _, .. }
343+
| Assert { target: t, unwind: _, .. }
344+
| FalseUnwind { real_target: t, unwind: _ }
345+
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
346+
| InlineAsm { destination: Some(t), unwind: _, .. } => {
347+
Some(t).into_iter().chain((&[]).into_iter().copied())
348+
}
349+
UnwindResume
350+
| UnwindTerminate(_)
351+
| CoroutineDrop
352+
| Return
353+
| Unreachable
354+
| Call { target: None, unwind: _, .. }
355+
| InlineAsm { destination: None, unwind: _, .. } => {
356+
None.into_iter().chain((&[]).into_iter().copied())
357+
}
358+
SwitchInt { ref targets, .. } => {
359+
None.into_iter().chain(targets.targets.iter().copied())
360+
}
361+
FalseEdge { real_target, ref imaginary_target } => Some(real_target)
362+
.into_iter()
363+
.chain(slice::from_ref(imaginary_target).into_iter().copied()),
354364
}
355-
FalseEdge { real_target, ref imaginary_target } => Some(real_target)
356-
.into_iter()
357-
.chain(slice::from_ref(imaginary_target).into_iter().copied()),
358365
}
359366
}
367+
}
360368

369+
impl<'tcx> TerminatorKind<'tcx> {
361370
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
362371
use self::TerminatorKind::*;
363372
match *self {

Diff for: compiler/rustc_middle/src/query/erase.rs

+4
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ impl EraseType for Option<mir::DestructuredConstant<'_>> {
158158
type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
159159
}
160160

161+
impl EraseType for ty::OpaqueTypes<'_> {
162+
type Result = [u8; size_of::<ty::OpaqueTypes<'static>>()];
163+
}
164+
161165
impl EraseType for Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
162166
type Result = [u8; size_of::<Option<ty::EarlyBinder<ty::TraitRef<'static>>>>()];
163167
}

Diff for: compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ rustc_queries! {
341341

342342
query opaque_types_defined_by(
343343
key: LocalDefId
344-
) -> &'tcx ty::List<LocalDefId> {
344+
) -> ty::OpaqueTypes<'tcx> {
345345
desc {
346346
|tcx| "computing the opaque types defined by `{}`",
347347
tcx.def_path_str(key.to_def_id())

Diff for: compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub use adt::*;
3030
pub use assoc::*;
3131
pub use generic_args::*;
3232
pub use generics::*;
33+
pub use opaque_types::OpaqueTypes;
3334
use rustc_ast as ast;
3435
use rustc_ast::node_id::NodeMap;
3536
use rustc_attr as attr;

Diff for: compiler/rustc_middle/src/ty/opaque_types.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::ty::fold::{TypeFolder, TypeSuperFoldable};
33
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
44
use crate::ty::{GenericArg, GenericArgKind};
55
use rustc_data_structures::fx::FxHashMap;
6-
use rustc_span::def_id::DefId;
6+
use rustc_span::def_id::{DefId, LocalDefId};
77
use rustc_span::Span;
88

99
/// Converts generic params of a TypeFoldable from one
@@ -223,3 +223,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
223223
}
224224
}
225225
}
226+
227+
/// The opaque types defined by an item.
228+
#[derive(Copy, Clone, Debug, HashStable)]
229+
pub struct OpaqueTypes<'tcx> {
230+
/// Opaque types in the signature *must* be defined by the item itself.
231+
pub in_signature: &'tcx ty::List<LocalDefId>,
232+
/// Opaque types declared in the body are not required to be defined by
233+
/// the item itself, they could be defined by other nested items.
234+
pub in_body: &'tcx ty::List<LocalDefId>,
235+
}

Diff for: compiler/rustc_ty_utils/src/opaque_types.rs

+14-10
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
106106
let id = id.owner_id.def_id;
107107
if let DefKind::TyAlias = self.collector.tcx.def_kind(id) {
108108
let items = self.collector.tcx.opaque_types_defined_by(id);
109-
self.collector.opaques.extend(items);
109+
assert_eq!(&items.in_body[..], []);
110+
self.collector.opaques.extend(items.in_signature);
110111
}
111112
}
112113
#[instrument(level = "trace", skip(self))]
@@ -264,22 +265,20 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
264265
}
265266
}
266267

267-
fn opaque_types_defined_by<'tcx>(
268-
tcx: TyCtxt<'tcx>,
269-
item: LocalDefId,
270-
) -> &'tcx ty::List<LocalDefId> {
268+
fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> ty::OpaqueTypes<'tcx> {
271269
let kind = tcx.def_kind(item);
272270
trace!(?kind);
273-
let mut collector = OpaqueTypeCollector::new(tcx, item);
274-
super::sig_types::walk_types(tcx, item, &mut collector);
271+
let mut in_signature = OpaqueTypeCollector::new(tcx, item);
272+
let mut in_body = OpaqueTypeCollector::new(tcx, item);
273+
super::sig_types::walk_types(tcx, item, &mut in_signature);
275274
match kind {
276275
DefKind::AssocFn
277276
| DefKind::Fn
278277
| DefKind::Static(_)
279278
| DefKind::Const
280279
| DefKind::AssocConst
281280
| DefKind::AnonConst => {
282-
collector.collect_taits_declared_in_body();
281+
in_body.collect_taits_declared_in_body();
283282
}
284283
DefKind::OpaqueTy
285284
| DefKind::TyAlias
@@ -306,10 +305,15 @@ fn opaque_types_defined_by<'tcx>(
306305
// Closures and coroutines are type checked with their parent, so we need to allow all
307306
// opaques from the closure signature *and* from the parent body.
308307
DefKind::Closure | DefKind::Coroutine | DefKind::InlineConst => {
309-
collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item)));
308+
let nested = tcx.opaque_types_defined_by(tcx.local_parent(item));
309+
in_signature.opaques.extend(nested.in_signature);
310+
in_body.opaques.extend(nested.in_body);
310311
}
311312
}
312-
tcx.mk_local_def_ids(&collector.opaques)
313+
ty::OpaqueTypes {
314+
in_signature: tcx.mk_local_def_ids(&in_signature.opaques),
315+
in_body: tcx.mk_local_def_ids(&in_body.opaques),
316+
}
313317
}
314318

315319
pub(super) fn provide(providers: &mut Providers) {

0 commit comments

Comments
 (0)