Skip to content

Commit ee7feb6

Browse files
committed
Auto merge of #158884 - JonathanBrouwer:rollup-wuMjcbX, r=<try>
Rollup of 7 pull requests try-job: dist-various-1 try-job: test-various try-job: x86_64-gnu-aux try-job: x86_64-gnu-llvm-21-3 try-job: x86_64-msvc-1 try-job: aarch64-apple try-job: x86_64-mingw-1 try-job: i686-msvc-2
2 parents 36714a9 + c9db118 commit ee7feb6

37 files changed

Lines changed: 576 additions & 70 deletions

compiler/rustc_abi/src/lib.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ even other Rust compilers, such as rust-analyzer!
3636
3737
*/
3838

39+
use std::cmp::min;
3940
use std::fmt;
4041
#[cfg(feature = "nightly")]
4142
use std::iter::Step;
@@ -1060,14 +1061,8 @@ impl Align {
10601061
/// Either `1 << (pointer_bits - 1)` or [`Align::MAX`], whichever is smaller.
10611062
#[inline]
10621063
pub fn max_for_target(tdl: &TargetDataLayout) -> Align {
1063-
let pointer_bits = tdl.pointer_size().bits();
1064-
if let Ok(pointer_bits) = u8::try_from(pointer_bits)
1065-
&& pointer_bits <= Align::MAX.pow2
1066-
{
1067-
Align { pow2: pointer_bits - 1 }
1068-
} else {
1069-
Align::MAX
1070-
}
1064+
let pointer_bits = u8::try_from(tdl.pointer_size().bits()).unwrap();
1065+
min(Align { pow2: pointer_bits - 1 }, Align::MAX)
10711066
}
10721067

10731068
#[inline]

compiler/rustc_const_eval/src/const_eval/valtrees.rs

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_abi::{BackendRepr, FieldIdx, VariantIdx};
2+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
23
use rustc_data_structures::stack::ensure_sufficient_stack;
34
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError};
45
use rustc_middle::traits::ObligationCause;
@@ -17,13 +18,15 @@ use crate::interpret::{
1718
intern_const_alloc_recursive,
1819
};
1920

20-
#[instrument(skip(ecx), level = "debug")]
21+
#[instrument(skip(ecx, visited, settled), level = "debug")]
2122
fn branches<'tcx>(
2223
ecx: &CompileTimeInterpCx<'tcx>,
2324
place: &MPlaceTy<'tcx>,
2425
field_count: usize,
2526
variant: Option<VariantIdx>,
2627
num_nodes: &mut usize,
28+
visited: &mut FxHashSet<MPlaceTy<'tcx>>,
29+
settled: &mut FxHashMap<MPlaceTy<'tcx>, EvalToValTreeResult<'tcx>>,
2730
) -> EvalToValTreeResult<'tcx> {
2831
let place = match variant {
2932
Some(variant) => ecx.project_downcast(place, variant).unwrap(),
@@ -45,7 +48,7 @@ fn branches<'tcx>(
4548

4649
for i in 0..field_count {
4750
let field = ecx.project_field(&place, FieldIdx::from_usize(i)).unwrap();
48-
let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?;
51+
let valtree = const_to_valtree_inner(ecx, &field, num_nodes, visited, settled)?;
4952
branches.push(ty::Const::new_value(*ecx.tcx, valtree, field.layout.ty));
5053
}
5154

@@ -57,39 +60,53 @@ fn branches<'tcx>(
5760
Ok(ty::ValTree::from_branches(*ecx.tcx, branches))
5861
}
5962

60-
#[instrument(skip(ecx), level = "debug")]
63+
#[instrument(skip(ecx, visited, settled), level = "debug")]
6164
fn slice_branches<'tcx>(
6265
ecx: &CompileTimeInterpCx<'tcx>,
6366
place: &MPlaceTy<'tcx>,
6467
num_nodes: &mut usize,
68+
visited: &mut FxHashSet<MPlaceTy<'tcx>>,
69+
settled: &mut FxHashMap<MPlaceTy<'tcx>, EvalToValTreeResult<'tcx>>,
6570
) -> EvalToValTreeResult<'tcx> {
6671
let n = place.len(ecx).unwrap_or_else(|_| panic!("expected to use len of place {place:?}"));
6772

6873
let mut elems = Vec::with_capacity(n as usize);
6974
for i in 0..n {
7075
let place_elem = ecx.project_index(place, i).unwrap();
71-
let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?;
76+
let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes, visited, settled)?;
7277
elems.push(ty::Const::new_value(*ecx.tcx, valtree, place_elem.layout.ty));
7378
}
7479

7580
Ok(ty::ValTree::from_branches(*ecx.tcx, elems))
7681
}
7782

78-
#[instrument(skip(ecx), level = "debug")]
83+
#[instrument(skip(ecx, visited, settled), level = "debug")]
7984
fn const_to_valtree_inner<'tcx>(
8085
ecx: &CompileTimeInterpCx<'tcx>,
8186
place: &MPlaceTy<'tcx>,
8287
num_nodes: &mut usize,
88+
visited: &mut FxHashSet<MPlaceTy<'tcx>>,
89+
settled: &mut FxHashMap<MPlaceTy<'tcx>, EvalToValTreeResult<'tcx>>,
8390
) -> EvalToValTreeResult<'tcx> {
8491
let tcx = *ecx.tcx;
8592
let ty = place.layout.ty;
8693
debug!("ty kind: {:?}", ty.kind());
8794

95+
if let Some(&result) = settled.get(place) {
96+
return result;
97+
}
98+
99+
if visited.contains(place) {
100+
return Err(ValTreeCreationError::CyclicConst);
101+
}
102+
88103
if *num_nodes >= VALTREE_MAX_NODES {
89104
return Err(ValTreeCreationError::NodesOverflow);
90105
}
91106

92-
match ty.kind() {
107+
visited.insert(place.clone());
108+
109+
let result = ensure_sufficient_stack(|| match ty.kind() {
93110
ty::FnDef(..) => {
94111
*num_nodes += 1;
95112
Ok(ty::ValTree::zst(tcx))
@@ -108,7 +125,7 @@ fn const_to_valtree_inner<'tcx>(
108125
// Since the returned valtree does not contain the type or layout, we can just
109126
// switch to the base type.
110127
place.layout = ecx.layout_of(*base).unwrap();
111-
ensure_sufficient_stack(|| const_to_valtree_inner(ecx, &place, num_nodes))
128+
const_to_valtree_inner(ecx, &place, num_nodes, visited, settled)
112129
}
113130

114131
ty::RawPtr(_, _) => {
@@ -120,16 +137,16 @@ fn const_to_valtree_inner<'tcx>(
120137
// We could allow wide raw pointers where both sides are integers in the future,
121138
// but for now we reject them.
122139
if matches!(val.layout.backend_repr, BackendRepr::ScalarPair(..)) {
123-
return Err(ValTreeCreationError::NonSupportedType(ty));
140+
Err(ValTreeCreationError::NonSupportedType(ty))
141+
} else {
142+
let val = val.to_scalar();
143+
// We are in the CTFE machine, so ptr-to-int casts will fail.
144+
// This can only be `Ok` if `val` already is an integer.
145+
match val.try_to_scalar_int() {
146+
Ok(val) => Ok(ty::ValTree::from_scalar_int(tcx, val)),
147+
Err(_) => Err(ValTreeCreationError::NonSupportedType(ty)),
148+
}
124149
}
125-
let val = val.to_scalar();
126-
// We are in the CTFE machine, so ptr-to-int casts will fail.
127-
// This can only be `Ok` if `val` already is an integer.
128-
let Ok(val) = val.try_to_scalar_int() else {
129-
return Err(ValTreeCreationError::NonSupportedType(ty));
130-
};
131-
// It's just a ScalarInt!
132-
Ok(ty::ValTree::from_scalar_int(tcx, val))
133150
}
134151

135152
// Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
@@ -138,33 +155,39 @@ fn const_to_valtree_inner<'tcx>(
138155

139156
ty::Ref(_, _, _) => {
140157
let derefd_place = ecx.deref_pointer(place).report_err()?;
141-
const_to_valtree_inner(ecx, &derefd_place, num_nodes)
158+
const_to_valtree_inner(ecx, &derefd_place, num_nodes, visited, settled)
142159
}
143160

144-
ty::Str | ty::Slice(_) | ty::Array(_, _) => slice_branches(ecx, place, num_nodes),
161+
ty::Str | ty::Slice(_) | ty::Array(_, _) => {
162+
slice_branches(ecx, place, num_nodes, visited, settled)
163+
}
145164
// Trait objects are not allowed in type level constants, as we have no concept for
146165
// resolving their backing type, even if we can do that at const eval time. We may
147166
// hypothetically be able to allow `dyn StructuralPartialEq` trait objects in the future,
148167
// but it is unclear if this is useful.
149168
ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType(ty)),
150169

151-
ty::Tuple(elem_tys) => branches(ecx, place, elem_tys.len(), None, num_nodes),
170+
ty::Tuple(elem_tys) => {
171+
branches(ecx, place, elem_tys.len(), None, num_nodes, visited, settled)
172+
}
152173

153174
ty::Adt(def, _) => {
154175
if def.is_union() {
155-
return Err(ValTreeCreationError::NonSupportedType(ty));
176+
Err(ValTreeCreationError::NonSupportedType(ty))
156177
} else if def.variants().is_empty() {
157178
bug!("uninhabited types should have errored and never gotten converted to valtree")
179+
} else {
180+
let variant = ecx.read_discriminant(place).report_err()?;
181+
branches(
182+
ecx,
183+
place,
184+
def.variant(variant).fields.len(),
185+
def.is_enum().then_some(variant),
186+
num_nodes,
187+
visited,
188+
settled,
189+
)
158190
}
159-
160-
let variant = ecx.read_discriminant(place).report_err()?;
161-
branches(
162-
ecx,
163-
place,
164-
def.variant(variant).fields.len(),
165-
def.is_enum().then_some(variant),
166-
num_nodes,
167-
)
168191
}
169192

170193
// FIXME(oli-obk): we could look behind opaque types
@@ -186,7 +209,11 @@ fn const_to_valtree_inner<'tcx>(
186209
| ty::Coroutine(..)
187210
| ty::CoroutineWitness(..)
188211
| ty::UnsafeBinder(_) => Err(ValTreeCreationError::NonSupportedType(ty)),
189-
}
212+
});
213+
214+
visited.remove(place);
215+
settled.insert(place.clone(), result);
216+
result
190217
}
191218

192219
/// Valtrees don't store the `MemPlaceMeta` that all dynamically sized values have in the interpreter.
@@ -257,7 +284,9 @@ pub(crate) fn eval_to_valtree<'tcx>(
257284
debug!(?place);
258285

259286
let mut num_nodes = 0;
260-
const_to_valtree_inner(&ecx, &place, &mut num_nodes)
287+
let mut visited = FxHashSet::default();
288+
let mut settled = FxHashMap::default();
289+
const_to_valtree_inner(&ecx, &place, &mut num_nodes, &mut visited, &mut settled)
261290
}
262291

263292
/// Converts a `ValTree` to a `ConstValue`, which is needed after mir

compiler/rustc_middle/src/error.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,15 @@ pub(crate) struct InvalidConstInValtree {
144144
pub global_const_id: String,
145145
}
146146

147+
#[derive(Diagnostic)]
148+
#[diag("constant {$global_const_id} cannot be used as pattern")]
149+
#[note("constants whose type references itself cannot be used as patterns")]
150+
pub(crate) struct CyclicConstInValtree {
151+
#[primary_span]
152+
pub span: Span,
153+
pub global_const_id: String,
154+
}
155+
147156
#[derive(Diagnostic)]
148157
#[diag("internal compiler error: reentrant incremental verify failure, suppressing message")]
149158
pub(crate) struct Reentrant;

compiler/rustc_middle/src/mir/interpret/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ pub enum ValTreeCreationError<'tcx> {
105105
InvalidConst,
106106
/// Values of this type, or this particular value, are not supported as valtrees.
107107
NonSupportedType(Ty<'tcx>),
108+
/// Trying to valtree this constant would cause the valtree to have cycles.
109+
CyclicConst,
108110
/// The error has already been handled by const evaluation.
109111
ErrorHandled(ErrorHandled),
110112
}

compiler/rustc_middle/src/mir/interpret/queries.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,13 @@ impl<'tcx> TyCtxt<'tcx> {
232232
});
233233
Err(ReportedErrorInfo::allowed_in_infallible(handled).into())
234234
}
235+
ValTreeCreationError::CyclicConst => {
236+
let handled = self.dcx().emit_err(error::CyclicConstInValtree {
237+
span,
238+
global_const_id: cid.display(self),
239+
});
240+
Err(ReportedErrorInfo::allowed_in_infallible(handled).into())
241+
}
235242
ValTreeCreationError::ErrorHandled(handled) => Err(handled),
236243
}
237244
}

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,23 @@ impl<'tcx> TypingEnv<'tcx> {
11281128
Self::new(tcx.param_env(def_id), TypingMode::non_body_analysis())
11291129
}
11301130

1131+
/// Ideally we just use `TypingMode::PostTypeckUntilBorrowck`.
1132+
/// But that's not compatible with the old solver yet.
1133+
///
1134+
/// FIXME: this should not be needed in the long term.
1135+
pub fn post_typeck_until_borrowck_for_mir_build(
1136+
tcx: TyCtxt<'tcx>,
1137+
def_id: LocalDefId,
1138+
) -> TypingEnv<'tcx> {
1139+
if tcx.use_typing_mode_post_typeck_until_borrowck() {
1140+
TypingEnv::new(tcx.param_env(def_id.to_def_id()), ty::TypingMode::borrowck(tcx, def_id))
1141+
} else {
1142+
// FIXME(#132279): We're in a body, we should use a typing
1143+
// mode which reveals the opaque types defined by that body.
1144+
TypingEnv::non_body_analysis(tcx, def_id)
1145+
}
1146+
}
1147+
11311148
pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey<DefId>) -> TypingEnv<'tcx> {
11321149
TypingEnv::new(tcx.param_env_normalized_for_post_analysis(def_id), TypingMode::PostAnalysis)
11331150
}

compiler/rustc_mir_build/src/builder/mod.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,15 @@ fn construct_fn<'tcx>(
505505
);
506506
}
507507

508-
// FIXME(#132279): This should be able to reveal opaque
509-
// types defined during HIR typeck.
510-
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
508+
let typing_mode = if tcx.use_typing_mode_post_typeck_until_borrowck() {
509+
TypingMode::borrowck(tcx, fn_def)
510+
} else {
511+
// FIXME(#132279): This should be able to reveal opaque
512+
// types defined during HIR typeck.
513+
TypingMode::non_body_analysis()
514+
};
515+
516+
let infcx = tcx.infer_ctxt().build(typing_mode);
511517
let mut builder = Builder::new(
512518
thir,
513519
infcx,
@@ -587,9 +593,15 @@ fn construct_const<'a, 'tcx>(
587593
_ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
588594
};
589595

590-
// FIXME(#132279): We likely want to be able to use the hidden types of
591-
// opaques used by this function here.
592-
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
596+
let typing_mode = if tcx.use_typing_mode_post_typeck_until_borrowck() {
597+
TypingMode::borrowck(tcx, def)
598+
} else {
599+
// FIXME(#132279): This should be able to reveal opaque
600+
// types defined during HIR typeck.
601+
TypingMode::non_body_analysis()
602+
};
603+
604+
let infcx = tcx.infer_ctxt().build(typing_mode);
593605
let mut builder =
594606
Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None);
595607

compiler/rustc_mir_build/src/builder/scope.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -968,8 +968,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
968968
tcx: self.tcx,
969969
typeck_results,
970970
module: self.tcx.parent_module(self.hir_id).to_def_id(),
971-
// FIXME(#132279): We're in a body, should handle opaques.
972-
typing_env: rustc_middle::ty::TypingEnv::non_body_analysis(self.tcx, self.def_id),
971+
typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(
972+
self.tcx,
973+
self.def_id,
974+
),
973975
dropless_arena: &dropless_arena,
974976
match_lint_level: self.hir_id,
975977
whole_match_span: Some(rustc_span::Span::default()),

compiler/rustc_mir_build/src/check_tail_calls.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ pub(crate) fn check_tail_calls(tcx: TyCtxt<'_>, def: LocalDefId) -> Result<(), E
2727
tcx,
2828
thir,
2929
found_errors: Ok(()),
30-
// FIXME(#132279): we're clearly in a body here.
31-
typing_env: ty::TypingEnv::non_body_analysis(tcx, def),
30+
typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def),
3231
is_closure,
3332
caller_def_id: def,
3433
};

compiler/rustc_mir_build/src/check_unsafety.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,8 +1093,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
10931093
body_target_features,
10941094
assignment_info: None,
10951095
in_union_destructure: false,
1096-
// FIXME(#132279): we're clearly in a body here.
1097-
typing_env: ty::TypingEnv::non_body_analysis(tcx, def),
1096+
typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def),
10981097
inside_adt: false,
10991098
warnings: &mut warnings,
11001099
suggest_unsafe_block: true,

0 commit comments

Comments
 (0)