Skip to content

Commit 0bc2001

Browse files
committed
Require any function with a tait in its signature to actually constrain a hidden type
1 parent 39e7bf6 commit 0bc2001

File tree

116 files changed

+1514
-698
lines changed

Some content is hidden

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

116 files changed

+1514
-698
lines changed

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());

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
@@ -460,6 +460,10 @@ hir_analysis_static_specialize = cannot specialize on `'static` lifetime
460460
hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
461461
.note = this item must mention the opaque type in its signature in order to be able to register hidden types
462462
463+
hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`, but has it in its signature
464+
.note = consider moving the opaque type's declaration and defining uses into a separate module
465+
.opaque = this opaque type is in the signature
466+
463467
hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
464468
465469
hir_analysis_too_large_static = extern static is too large for the current architecture

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

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

11-
use crate::errors::{TaitForwardCompat, TypeOf, UnconstrainedOpaqueType};
11+
use crate::errors::{TaitForwardCompat, TaitForwardCompat2, TypeOf, UnconstrainedOpaqueType};
1212

1313
pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
1414
let mut res = Ok(());
@@ -229,13 +229,14 @@ impl TaitConstraintLocator<'_> {
229229
return;
230230
}
231231

232+
let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
233+
232234
let mut constrained = false;
233235
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
234236
if opaque_type_key.def_id != self.def_id {
235237
continue;
236238
}
237239
constrained = true;
238-
let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
239240

240241
if !opaque_types_defined_by.contains(&self.def_id) {
241242
self.tcx.dcx().emit_err(TaitForwardCompat {
@@ -259,6 +260,16 @@ impl TaitConstraintLocator<'_> {
259260

260261
if !constrained {
261262
debug!("no constraints in typeck results");
263+
if opaque_types_defined_by.contains(&self.def_id) {
264+
self.tcx.dcx().emit_err(TaitForwardCompat2 {
265+
span: self
266+
.tcx
267+
.def_ident_span(item_def_id)
268+
.unwrap_or_else(|| self.tcx.def_span(item_def_id)),
269+
opaque_type_span: self.tcx.def_span(self.def_id),
270+
opaque_type: self.tcx.def_path_str(self.def_id),
271+
});
272+
}
262273
return;
263274
};
264275

compiler/rustc_hir_analysis/src/errors.rs

+11
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,17 @@ pub struct TaitForwardCompat {
390390
pub item_span: Span,
391391
}
392392

393+
#[derive(Diagnostic)]
394+
#[diag(hir_analysis_tait_forward_compat2)]
395+
#[note]
396+
pub struct TaitForwardCompat2 {
397+
#[primary_span]
398+
pub span: Span,
399+
#[note(hir_analysis_opaque)]
400+
pub opaque_type_span: Span,
401+
pub opaque_type: String,
402+
}
403+
393404
pub struct MissingTypeParams {
394405
pub span: Span,
395406
pub def_span: Span,

compiler/rustc_middle/src/mir/terminator.rs

+81-70
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,6 @@ pub struct Terminator<'tcx> {
377377
pub kind: TerminatorKind<'tcx>,
378378
}
379379

380-
pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
381-
pub type SuccessorsMut<'a> = impl DoubleEndedIterator<Item = &'a mut BasicBlock> + 'a;
382-
383380
impl<'tcx> Terminator<'tcx> {
384381
#[inline]
385382
pub fn successors(&self) -> Successors<'_> {
@@ -407,81 +404,95 @@ impl<'tcx> TerminatorKind<'tcx> {
407404
pub fn if_(cond: Operand<'tcx>, t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
408405
TerminatorKind::SwitchInt { discr: cond, targets: SwitchTargets::static_if(0, f, t) }
409406
}
407+
}
410408

411-
#[inline]
412-
pub fn successors(&self) -> Successors<'_> {
413-
use self::TerminatorKind::*;
414-
match *self {
415-
Call { target: Some(ref t), unwind: UnwindAction::Cleanup(u), .. }
416-
| Yield { resume: ref t, drop: Some(u), .. }
417-
| Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
418-
| Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
419-
| FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => {
420-
slice::from_ref(t).into_iter().copied().chain(Some(u))
421-
}
422-
Goto { target: ref t }
423-
| Call { target: None, unwind: UnwindAction::Cleanup(ref t), .. }
424-
| Call { target: Some(ref t), unwind: _, .. }
425-
| Yield { resume: ref t, drop: None, .. }
426-
| Drop { target: ref t, unwind: _, .. }
427-
| Assert { target: ref t, unwind: _, .. }
428-
| FalseUnwind { real_target: ref t, unwind: _ } => {
429-
slice::from_ref(t).into_iter().copied().chain(None)
430-
}
431-
UnwindResume
432-
| UnwindTerminate(_)
433-
| CoroutineDrop
434-
| Return
435-
| Unreachable
436-
| Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None),
437-
InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => {
438-
targets.iter().copied().chain(Some(u))
439-
}
440-
InlineAsm { ref targets, unwind: _, .. } => targets.iter().copied().chain(None),
441-
SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None),
442-
FalseEdge { ref real_target, imaginary_target } => {
443-
slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target))
409+
pub use helper::*;
410+
411+
mod helper {
412+
use super::*;
413+
pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
414+
pub type SuccessorsMut<'a> = impl DoubleEndedIterator<Item = &'a mut BasicBlock> + 'a;
415+
impl<'tcx> TerminatorKind<'tcx> {
416+
#[inline]
417+
pub fn successors(&self) -> Successors<'_> {
418+
use self::TerminatorKind::*;
419+
match *self {
420+
Call { target: Some(ref t), unwind: UnwindAction::Cleanup(u), .. }
421+
| Yield { resume: ref t, drop: Some(u), .. }
422+
| Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
423+
| Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
424+
| FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => {
425+
slice::from_ref(t).into_iter().copied().chain(Some(u))
426+
}
427+
Goto { target: ref t }
428+
| Call { target: None, unwind: UnwindAction::Cleanup(ref t), .. }
429+
| Call { target: Some(ref t), unwind: _, .. }
430+
| Yield { resume: ref t, drop: None, .. }
431+
| Drop { target: ref t, unwind: _, .. }
432+
| Assert { target: ref t, unwind: _, .. }
433+
| FalseUnwind { real_target: ref t, unwind: _ } => {
434+
slice::from_ref(t).into_iter().copied().chain(None)
435+
}
436+
UnwindResume
437+
| UnwindTerminate(_)
438+
| CoroutineDrop
439+
| Return
440+
| Unreachable
441+
| Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None),
442+
InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => {
443+
targets.iter().copied().chain(Some(u))
444+
}
445+
InlineAsm { ref targets, unwind: _, .. } => targets.iter().copied().chain(None),
446+
SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None),
447+
FalseEdge { ref real_target, imaginary_target } => {
448+
slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target))
449+
}
444450
}
445451
}
446-
}
447452

448-
#[inline]
449-
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
450-
use self::TerminatorKind::*;
451-
match *self {
452-
Call { target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), .. }
453-
| Yield { resume: ref mut t, drop: Some(ref mut u), .. }
454-
| Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
455-
| Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
456-
| FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) } => {
457-
slice::from_mut(t).into_iter().chain(Some(u))
458-
}
459-
Goto { target: ref mut t }
460-
| Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
461-
| Call { target: Some(ref mut t), unwind: _, .. }
462-
| Yield { resume: ref mut t, drop: None, .. }
463-
| Drop { target: ref mut t, unwind: _, .. }
464-
| Assert { target: ref mut t, unwind: _, .. }
465-
| FalseUnwind { real_target: ref mut t, unwind: _ } => {
466-
slice::from_mut(t).into_iter().chain(None)
467-
}
468-
UnwindResume
469-
| UnwindTerminate(_)
470-
| CoroutineDrop
471-
| Return
472-
| Unreachable
473-
| Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
474-
InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => {
475-
targets.iter_mut().chain(Some(u))
476-
}
477-
InlineAsm { ref mut targets, unwind: _, .. } => targets.iter_mut().chain(None),
478-
SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None),
479-
FalseEdge { ref mut real_target, ref mut imaginary_target } => {
480-
slice::from_mut(real_target).into_iter().chain(Some(imaginary_target))
453+
#[inline]
454+
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
455+
use self::TerminatorKind::*;
456+
match *self {
457+
Call {
458+
target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), ..
459+
}
460+
| Yield { resume: ref mut t, drop: Some(ref mut u), .. }
461+
| Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
462+
| Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
463+
| FalseUnwind {
464+
real_target: ref mut t,
465+
unwind: UnwindAction::Cleanup(ref mut u),
466+
} => slice::from_mut(t).into_iter().chain(Some(u)),
467+
Goto { target: ref mut t }
468+
| Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
469+
| Call { target: Some(ref mut t), unwind: _, .. }
470+
| Yield { resume: ref mut t, drop: None, .. }
471+
| Drop { target: ref mut t, unwind: _, .. }
472+
| Assert { target: ref mut t, unwind: _, .. }
473+
| FalseUnwind { real_target: ref mut t, unwind: _ } => {
474+
slice::from_mut(t).into_iter().chain(None)
475+
}
476+
UnwindResume
477+
| UnwindTerminate(_)
478+
| CoroutineDrop
479+
| Return
480+
| Unreachable
481+
| Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
482+
InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => {
483+
targets.iter_mut().chain(Some(u))
484+
}
485+
InlineAsm { ref mut targets, unwind: _, .. } => targets.iter_mut().chain(None),
486+
SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None),
487+
FalseEdge { ref mut real_target, ref mut imaginary_target } => {
488+
slice::from_mut(real_target).into_iter().chain(Some(imaginary_target))
489+
}
481490
}
482491
}
483492
}
493+
}
484494

495+
impl<'tcx> TerminatorKind<'tcx> {
485496
#[inline]
486497
pub fn unwind(&self) -> Option<&UnwindAction> {
487498
match *self {

library/std/src/backtrace.rs

+32-28
Original file line numberDiff line numberDiff line change
@@ -428,39 +428,43 @@ impl fmt::Display for Backtrace {
428428
}
429429
}
430430

431-
type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe;
432-
433-
fn lazy_resolve(mut capture: Capture) -> LazyResolve {
434-
move || {
435-
// Use the global backtrace lock to synchronize this as it's a
436-
// requirement of the `backtrace` crate, and then actually resolve
437-
// everything.
438-
let _lock = lock();
439-
for frame in capture.frames.iter_mut() {
440-
let symbols = &mut frame.symbols;
441-
let frame = match &frame.frame {
442-
RawFrame::Actual(frame) => frame,
443-
#[cfg(test)]
444-
RawFrame::Fake => unimplemented!(),
445-
};
446-
unsafe {
447-
backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
448-
symbols.push(BacktraceSymbol {
449-
name: symbol.name().map(|m| m.as_bytes().to_vec()),
450-
filename: symbol.filename_raw().map(|b| match b {
451-
BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()),
452-
BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
453-
}),
454-
lineno: symbol.lineno(),
455-
colno: symbol.colno(),
431+
mod helper {
432+
use super::*;
433+
pub(super) type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe;
434+
435+
pub(super) fn lazy_resolve(mut capture: Capture) -> LazyResolve {
436+
move || {
437+
// Use the global backtrace lock to synchronize this as it's a
438+
// requirement of the `backtrace` crate, and then actually resolve
439+
// everything.
440+
let _lock = lock();
441+
for frame in capture.frames.iter_mut() {
442+
let symbols = &mut frame.symbols;
443+
let frame = match &frame.frame {
444+
RawFrame::Actual(frame) => frame,
445+
#[cfg(test)]
446+
RawFrame::Fake => unimplemented!(),
447+
};
448+
unsafe {
449+
backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
450+
symbols.push(BacktraceSymbol {
451+
name: symbol.name().map(|m| m.as_bytes().to_vec()),
452+
filename: symbol.filename_raw().map(|b| match b {
453+
BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()),
454+
BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
455+
}),
456+
lineno: symbol.lineno(),
457+
colno: symbol.colno(),
458+
});
456459
});
457-
});
460+
}
458461
}
459-
}
460462

461-
capture
463+
capture
464+
}
462465
}
463466
}
467+
use helper::*;
464468

465469
impl RawFrame {
466470
fn ip(&self) -> *mut c_void {

0 commit comments

Comments
 (0)