Skip to content

Commit 314384b

Browse files
committed
Auto merge of rust-lang#120157 - matthiaskrgr:rollup-f0p3wkk, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - rust-lang#103730 (Added NonZeroXxx::from_mut(_unchecked)?) - rust-lang#113142 (optimize EscapeAscii's Display and CStr's Debug) - rust-lang#118799 (Stabilize single-field offset_of) - rust-lang#119613 (Expose Obligations created during type inference.) - rust-lang#119752 (Avoid ICEs in trait names without `dyn`) - rust-lang#120132 (Teach tidy about line/col information for malformed features) - rust-lang#120135 (SMIR: Make the remaining "private" fields actually private) - rust-lang#120148 (`single_use_lifetimes`: Don't suggest deleting lifetimes with bounds) - rust-lang#120150 (Stabilize `round_ties_even`) - rust-lang#120155 (Don't use `ReErased` to detect type test promotion failed) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 5378c1c + bb816e6 commit 314384b

File tree

69 files changed

+1032
-155
lines changed

Some content is hidden

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

69 files changed

+1032
-155
lines changed

compiler/rustc_borrowck/src/region_infer/mod.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_middle::mir::{
1818
};
1919
use rustc_middle::traits::ObligationCause;
2020
use rustc_middle::traits::ObligationCauseCode;
21-
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
21+
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
2222
use rustc_mir_dataflow::points::DenseLocationMap;
2323
use rustc_span::Span;
2424

@@ -1145,6 +1145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11451145
}
11461146

11471147
let ty = ty.fold_with(&mut OpaqueFolder { tcx });
1148+
let mut failed = false;
11481149

11491150
let ty = tcx.fold_regions(ty, |r, _depth| {
11501151
let r_vid = self.to_region_vid(r);
@@ -1160,15 +1161,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11601161
.filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
11611162
.find(|&u_r| self.eval_equal(u_r, r_vid))
11621163
.map(|u_r| ty::Region::new_var(tcx, u_r))
1163-
// In the case of a failure, use `ReErased`. We will eventually
1164-
// return `None` in this case.
1165-
.unwrap_or(tcx.lifetimes.re_erased)
1164+
// In case we could not find a named region to map to,
1165+
// we will return `None` below.
1166+
.unwrap_or_else(|| {
1167+
failed = true;
1168+
r
1169+
})
11661170
});
11671171

11681172
debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
11691173

11701174
// This will be true if we failed to promote some region.
1171-
if ty.has_erased_regions() {
1175+
if failed {
11721176
return None;
11731177
}
11741178

compiler/rustc_error_codes/src/error_codes/E0795.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro.
33
Erroneous code example:
44

55
```compile_fail,E0795
6-
#![feature(offset_of, offset_of_enum)]
6+
#![feature(offset_of_enum, offset_of_nested)]
77
88
let x = std::mem::offset_of!(Option<u8>, Some);
99
```
@@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option<u8>` can be found by specifying
1616
the field name `0`:
1717

1818
```
19-
#![feature(offset_of, offset_of_enum)]
19+
#![feature(offset_of_enum, offset_of_nested)]
2020
2121
let x: usize = std::mem::offset_of!(Option<u8>, Some.0);
2222
```

compiler/rustc_feature/src/unstable.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,9 @@ declare_features! (
549549
/// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
550550
(unstable, object_safe_for_dispatch, "1.40.0", Some(43561)),
551551
/// Allows using enums in offset_of!
552-
(unstable, offset_of_enum, "1.75.0", Some(106655)),
552+
(unstable, offset_of_enum, "1.75.0", Some(120141)),
553+
/// Allows using multiple nested field accesses in offset_of!
554+
(unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)),
553555
/// Allows using `#[optimize(X)]`.
554556
(unstable, optimize_attribute, "1.34.0", Some(54882)),
555557
/// Allows macro attributes on expressions, statements and non-inline modules.

compiler/rustc_hir_analysis/src/astconv/lint.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
7878
fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) -> bool {
7979
let tcx = self.tcx();
8080
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
81-
let (hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. })
82-
| hir::Node::TraitItem(hir::TraitItem {
83-
kind: hir::TraitItemKind::Fn(sig, _),
84-
generics,
85-
..
86-
})) = tcx.hir_node_by_def_id(parent_id)
87-
else {
88-
return false;
81+
let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) {
82+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => {
83+
(sig, generics, None)
84+
}
85+
hir::Node::TraitItem(hir::TraitItem {
86+
kind: hir::TraitItemKind::Fn(sig, _),
87+
generics,
88+
owner_id,
89+
..
90+
}) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))),
91+
_ => return false,
8992
};
9093
let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
9194
return false;
@@ -94,6 +97,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
9497
let is_object_safe = match self_ty.kind {
9598
hir::TyKind::TraitObject(objects, ..) => {
9699
objects.iter().all(|o| match o.trait_ref.path.res {
100+
Res::Def(DefKind::Trait, id) if Some(id) == owner => {
101+
// When we're dealing with a recursive trait, we don't want to downgrade
102+
// the error, so we consider them to be object safe always. (#119652)
103+
true
104+
}
97105
Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
98106
_ => false,
99107
})
@@ -122,7 +130,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
122130
],
123131
Applicability::MachineApplicable,
124132
);
125-
} else {
133+
} else if diag.is_error() {
126134
// We'll emit the object safety error already, with a structured suggestion.
127135
diag.downgrade_to_delayed_bug();
128136
}
@@ -148,8 +156,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
148156
}
149157
if !is_object_safe {
150158
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
151-
// We'll emit the object safety error already, with a structured suggestion.
152-
diag.downgrade_to_delayed_bug();
159+
if diag.is_error() {
160+
// We'll emit the object safety error already, with a structured suggestion.
161+
diag.downgrade_to_delayed_bug();
162+
}
153163
} else {
154164
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
155165
// There are more than one trait bound, we need surrounding parentheses.

compiler/rustc_hir_typeck/src/expr.rs

+12
Original file line numberDiff line numberDiff line change
@@ -3246,6 +3246,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32463246
) -> Ty<'tcx> {
32473247
let container = self.to_ty(container).normalized;
32483248

3249+
if let Some(ident_2) = fields.get(1)
3250+
&& !self.tcx.features().offset_of_nested
3251+
{
3252+
rustc_session::parse::feature_err(
3253+
&self.tcx.sess,
3254+
sym::offset_of_nested,
3255+
ident_2.span,
3256+
"only a single ident or integer is stable as the field in offset_of",
3257+
)
3258+
.emit();
3259+
}
3260+
32493261
let mut field_indices = Vec::with_capacity(fields.len());
32503262
let mut current_container = container;
32513263
let mut fields = fields.into_iter();

compiler/rustc_hir_typeck/src/lib.rs

+21-3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ use rustc_hir::{HirIdMap, Node};
6060
use rustc_hir_analysis::astconv::AstConv;
6161
use rustc_hir_analysis::check::check_abi;
6262
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
63+
use rustc_infer::traits::ObligationInspector;
6364
use rustc_middle::query::Providers;
6465
use rustc_middle::traits;
6566
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -139,7 +140,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDef
139140

140141
fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
141142
let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity();
142-
typeck_with_fallback(tcx, def_id, fallback)
143+
typeck_with_fallback(tcx, def_id, fallback, None)
143144
}
144145

145146
/// Used only to get `TypeckResults` for type inference during error recovery.
@@ -149,14 +150,28 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T
149150
let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id));
150151
Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used")
151152
};
152-
typeck_with_fallback(tcx, def_id, fallback)
153+
typeck_with_fallback(tcx, def_id, fallback, None)
153154
}
154155

155-
#[instrument(level = "debug", skip(tcx, fallback), ret)]
156+
/// Same as `typeck` but `inspect` is invoked on evaluation of each root obligation.
157+
/// Inspecting obligations only works with the new trait solver.
158+
/// This function is *only to be used* by external tools, it should not be
159+
/// called from within rustc. Note, this is not a query, and thus is not cached.
160+
pub fn inspect_typeck<'tcx>(
161+
tcx: TyCtxt<'tcx>,
162+
def_id: LocalDefId,
163+
inspect: ObligationInspector<'tcx>,
164+
) -> &'tcx ty::TypeckResults<'tcx> {
165+
let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity();
166+
typeck_with_fallback(tcx, def_id, fallback, Some(inspect))
167+
}
168+
169+
#[instrument(level = "debug", skip(tcx, fallback, inspector), ret)]
156170
fn typeck_with_fallback<'tcx>(
157171
tcx: TyCtxt<'tcx>,
158172
def_id: LocalDefId,
159173
fallback: impl Fn() -> Ty<'tcx> + 'tcx,
174+
inspector: Option<ObligationInspector<'tcx>>,
160175
) -> &'tcx ty::TypeckResults<'tcx> {
161176
// Closures' typeck results come from their outermost function,
162177
// as they are part of the same "inference environment".
@@ -178,6 +193,9 @@ fn typeck_with_fallback<'tcx>(
178193
let param_env = tcx.param_env(def_id);
179194

180195
let inh = Inherited::new(tcx, def_id);
196+
if let Some(inspector) = inspector {
197+
inh.infcx.attach_obligation_inspector(inspector);
198+
}
181199
let mut fcx = FnCtxt::new(&inh, param_env, def_id);
182200

183201
if let Some(hir::FnSig { header, decl, .. }) = fn_sig {

compiler/rustc_infer/src/infer/at.rs

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ impl<'tcx> InferCtxt<'tcx> {
9090
universe: self.universe.clone(),
9191
intercrate,
9292
next_trait_solver: self.next_trait_solver,
93+
obligation_inspector: self.obligation_inspector.clone(),
9394
}
9495
}
9596
}

compiler/rustc_infer/src/infer/mod.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
1313
use self::opaque_types::OpaqueTypeStorage;
1414
pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
1515

16-
use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt};
16+
use crate::traits::{
17+
self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt,
18+
};
1719

1820
use rustc_data_structures::fx::FxIndexMap;
1921
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -334,6 +336,8 @@ pub struct InferCtxt<'tcx> {
334336
pub intercrate: bool,
335337

336338
next_trait_solver: bool,
339+
340+
pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>,
337341
}
338342

339343
impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
@@ -708,6 +712,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
708712
universe: Cell::new(ty::UniverseIndex::ROOT),
709713
intercrate,
710714
next_trait_solver,
715+
obligation_inspector: Cell::new(None),
711716
}
712717
}
713718
}
@@ -1718,6 +1723,15 @@ impl<'tcx> InferCtxt<'tcx> {
17181723
}
17191724
}
17201725
}
1726+
1727+
/// Attach a callback to be invoked on each root obligation evaluated in the new trait solver.
1728+
pub fn attach_obligation_inspector(&self, inspector: ObligationInspector<'tcx>) {
1729+
debug_assert!(
1730+
self.obligation_inspector.get().is_none(),
1731+
"shouldn't override a set obligation inspector"
1732+
);
1733+
self.obligation_inspector.set(Some(inspector));
1734+
}
17211735
}
17221736

17231737
impl<'tcx> TypeErrCtxt<'_, 'tcx> {

compiler/rustc_infer/src/traits/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ use std::hash::{Hash, Hasher};
1313

1414
use hir::def_id::LocalDefId;
1515
use rustc_hir as hir;
16+
use rustc_middle::traits::query::NoSolution;
17+
use rustc_middle::traits::solve::Certainty;
1618
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1719
use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt};
1820
use rustc_span::Span;
1921

2022
pub use self::ImplSource::*;
2123
pub use self::SelectionError::*;
24+
use crate::infer::InferCtxt;
2225

2326
pub use self::engine::{TraitEngine, TraitEngineExt};
2427
pub use self::project::MismatchedProjectionTypes;
@@ -116,6 +119,11 @@ pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
116119

117120
pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
118121

122+
/// A callback that can be provided to `inspect_typeck`. Invoked on evaluation
123+
/// of root obligations.
124+
pub type ObligationInspector<'tcx> =
125+
fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
126+
119127
pub struct FulfillmentError<'tcx> {
120128
pub obligation: PredicateObligation<'tcx>,
121129
pub code: FulfillmentErrorCode<'tcx>,

compiler/rustc_resolve/src/late/diagnostics.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2567,8 +2567,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
25672567
debug!(?param.ident, ?param.ident.span, ?use_span);
25682568

25692569
let elidable = matches!(use_ctxt, LifetimeCtxt::Ref);
2570+
let deletion_span =
2571+
if param.bounds.is_empty() { deletion_span() } else { None };
25702572

2571-
let deletion_span = deletion_span();
25722573
self.r.lint_buffer.buffer_lint_with_diagnostic(
25732574
lint::builtin::SINGLE_USE_LIFETIMES,
25742575
param.id,

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@ symbols! {
11531153
offset,
11541154
offset_of,
11551155
offset_of_enum,
1156+
offset_of_nested,
11561157
ok_or_else,
11571158
omit_gdb_pretty_printer_section,
11581159
on,

0 commit comments

Comments
 (0)