Skip to content

Commit b6612f4

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

File tree

90 files changed

+837
-478
lines changed

Some content is hidden

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

90 files changed

+837
-478
lines changed

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 {

compiler/rustc_hir_analysis/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,10 @@ hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden
312312
hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
313313
.note = this item must mention the opaque type in its signature in order to be able to register hidden types
314314
315+
hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`, but has it in its signature
316+
.note = consider moving the opaque type's declaration and defining uses into a separate module
317+
.opaque = this opaque type is in the signature
318+
315319
hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
316320
317321
hir_analysis_too_large_static = extern static is too large for the current architecture

compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs

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

9-
use crate::errors::{TaitForwardCompat, UnconstrainedOpaqueType};
9+
use crate::errors::{TaitForwardCompat, TaitForwardCompat2, UnconstrainedOpaqueType};
1010

1111
/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
1212
/// laid for "higher-order pattern unification".
@@ -138,13 +138,17 @@ impl TaitConstraintLocator<'_> {
138138
return;
139139
}
140140

141+
let opaques = self.tcx.opaque_types_defined_by(item_def_id);
142+
let opaque_type_must_be_defined = opaques.in_signature.contains(&self.def_id);
143+
let opaque_type_may_be_defined = opaques.in_body.contains(&self.def_id);
144+
141145
let mut constrained = false;
142146
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
143147
if opaque_type_key.def_id != self.def_id {
144148
continue;
145149
}
146150
constrained = true;
147-
if !self.tcx.opaque_types_defined_by(item_def_id).contains(&self.def_id) {
151+
if !opaque_type_must_be_defined && !opaque_type_may_be_defined {
148152
self.tcx.sess.emit_err(TaitForwardCompat {
149153
span: hidden_type.span,
150154
item_span: self
@@ -166,6 +170,16 @@ impl TaitConstraintLocator<'_> {
166170

167171
if !constrained {
168172
debug!("no constraints in typeck results");
173+
if opaque_type_must_be_defined {
174+
self.tcx.sess.emit_err(TaitForwardCompat2 {
175+
span: self
176+
.tcx
177+
.def_ident_span(item_def_id)
178+
.unwrap_or_else(|| self.tcx.def_span(item_def_id)),
179+
opaque_type_span: self.tcx.def_span(self.def_id),
180+
opaque_type: self.tcx.def_path_str(self.def_id),
181+
});
182+
}
169183
return;
170184
};
171185

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,

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)

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
}

compiler/rustc_middle/src/mir/terminator.rs

+46-37
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,6 @@ pub struct Terminator<'tcx> {
284284
pub kind: TerminatorKind<'tcx>,
285285
}
286286

287-
pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
288287
pub type SuccessorsMut<'a> =
289288
iter::Chain<std::option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
290289

@@ -310,47 +309,57 @@ impl<'tcx> TerminatorKind<'tcx> {
310309
pub fn if_(cond: Operand<'tcx>, t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
311310
TerminatorKind::SwitchInt { discr: cond, targets: SwitchTargets::static_if(0, f, t) }
312311
}
312+
}
313313

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

362+
impl<'tcx> TerminatorKind<'tcx> {
354363
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
355364
use self::TerminatorKind::*;
356365
match *self {

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
}

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 [LocalDefId] {
344+
) -> ty::OpaqueTypes<'tcx> {
345345
desc {
346346
|tcx| "computing the opaque types defined by `{}`",
347347
tcx.def_path_str(key.to_def_id())

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;

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 [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 [LocalDefId],
235+
}

compiler/rustc_ty_utils/src/opaque_types.rs

+16-11
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
118118
let id = id.owner_id.def_id;
119119
if let DefKind::TyAlias = self.collector.tcx.def_kind(id) {
120120
let items = self.collector.tcx.opaque_types_defined_by(id);
121-
self.collector.opaques.extend(items);
121+
assert_eq!(items.in_body, []);
122+
self.collector.opaques.extend(items.in_signature);
122123
}
123124
}
124125
#[instrument(level = "trace", skip(self))]
@@ -269,38 +270,39 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
269270
}
270271
}
271272

272-
fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [LocalDefId] {
273+
fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> ty::OpaqueTypes<'tcx> {
273274
let kind = tcx.def_kind(item);
274275
trace!(?kind);
275-
let mut collector = OpaqueTypeCollector::new(tcx, item);
276+
let mut in_signature = OpaqueTypeCollector::new(tcx, item);
277+
let mut in_body = OpaqueTypeCollector::new(tcx, item);
276278
match kind {
277279
// Walk over the signature of the function-like to find the opaques.
278280
DefKind::AssocFn | DefKind::Fn => {
279281
let ty_sig = tcx.fn_sig(item).instantiate_identity();
280282
let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
281283
// Walk over the inputs and outputs manually in order to get good spans for them.
282-
collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
284+
in_signature.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
283285
for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
284-
collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
286+
in_signature.visit_spanned(hir.span, ty.map_bound(|x| *x));
285287
}
286-
collector.collect_body_and_predicate_taits();
288+
in_body.collect_body_and_predicate_taits();
287289
}
288290
// Walk over the type of the item to find opaques.
289291
DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
290292
let span = match tcx.hir().get_by_def_id(item).ty() {
291293
Some(ty) => ty.span,
292294
_ => tcx.def_span(item),
293295
};
294-
collector.visit_spanned(span, tcx.type_of(item).instantiate_identity());
295-
collector.collect_body_and_predicate_taits();
296+
in_signature.visit_spanned(span, tcx.type_of(item).instantiate_identity());
297+
in_body.collect_body_and_predicate_taits();
296298
}
297299
// We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
298300
DefKind::TyAlias | DefKind::AssocTy => {
299-
tcx.type_of(item).instantiate_identity().visit_with(&mut collector);
301+
tcx.type_of(item).instantiate_identity().visit_with(&mut in_signature);
300302
}
301303
DefKind::OpaqueTy => {
302304
for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() {
303-
collector.visit_spanned(span, pred);
305+
in_signature.visit_spanned(span, pred);
304306
}
305307
}
306308
DefKind::Mod
@@ -327,7 +329,10 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
327329
return tcx.opaque_types_defined_by(tcx.local_parent(item));
328330
}
329331
}
330-
tcx.arena.alloc_from_iter(collector.opaques)
332+
ty::OpaqueTypes {
333+
in_signature: tcx.arena.alloc_from_iter(in_signature.opaques),
334+
in_body: tcx.arena.alloc_from_iter(in_body.opaques),
335+
}
331336
}
332337

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

0 commit comments

Comments
 (0)