Skip to content

Commit 702987f

Browse files
committed
Auto merge of #130732 - matthiaskrgr:rollup-ke1j314, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #129550 (Add str.as_str() for easy Deref to string slices) - #130344 (Handle unsized consts with type `str` in v0 symbol mangling) - #130659 (Support `char::encode_utf16` in const scenarios.) - #130705 (No longer mark RTN as incomplete) - #130712 (Don't call `ty::Const::normalize` in error reporting) - #130713 (Mark `u8::make_ascii_uppercase` and `u8::make_ascii_lowercase` as const.) - #130714 (Introduce `structurally_normalize_const`, use it in `rustc_hir_typeck`) - #130715 (Replace calls to `ty::Const::{try_}eval` in mir build/pattern analysis) - #130723 (Add test for `available_parallelism()`) - #130726 (tests: Remove spuriously failing vec-tryinto-array codegen test) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 66b0b29 + 693269b commit 702987f

File tree

120 files changed

+522
-800
lines changed

Some content is hidden

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

120 files changed

+522
-800
lines changed

Diff for: compiler/rustc_feature/src/unstable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ declare_features! (
578578
/// be used to describe E or vise-versa.
579579
(unstable, result_ffi_guarantees, "1.80.0", Some(110503)),
580580
/// Allows bounding the return type of AFIT/RPITIT.
581-
(incomplete, return_type_notation, "1.70.0", Some(109417)),
581+
(unstable, return_type_notation, "1.70.0", Some(109417)),
582582
/// Allows `extern "rust-cold"`.
583583
(unstable, rust_cold_cc, "1.63.0", Some(97544)),
584584
/// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics

Diff for: compiler/rustc_hir/src/hir.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -1668,10 +1668,17 @@ pub enum ArrayLen<'hir> {
16681668
}
16691669

16701670
impl ArrayLen<'_> {
1671-
pub fn hir_id(&self) -> HirId {
1671+
pub fn span(self) -> Span {
1672+
match self {
1673+
ArrayLen::Infer(arg) => arg.span,
1674+
ArrayLen::Body(body) => body.span(),
1675+
}
1676+
}
1677+
1678+
pub fn hir_id(self) -> HirId {
16721679
match self {
1673-
ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(ConstArg { hir_id, .. }) => {
1674-
*hir_id
1680+
ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(&ConstArg { hir_id, .. }) => {
1681+
hir_id
16751682
}
16761683
}
16771684
}

Diff for: compiler/rustc_hir_typeck/src/expr.rs

+35-31
Original file line numberDiff line numberDiff line change
@@ -1491,8 +1491,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14911491
expr: &'tcx hir::Expr<'tcx>,
14921492
) -> Ty<'tcx> {
14931493
let tcx = self.tcx;
1494-
let count = self.lower_array_length(count);
1495-
if let Some(count) = count.try_eval_target_usize(tcx, self.param_env) {
1494+
let count_span = count.span();
1495+
let count = self.try_structurally_resolve_const(count_span, self.lower_array_length(count));
1496+
1497+
if let Some(count) = count.try_to_target_usize(tcx) {
14961498
self.suggest_array_len(expr, count);
14971499
}
14981500

@@ -1520,19 +1522,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15201522
return Ty::new_error(tcx, guar);
15211523
}
15221524

1523-
self.check_repeat_element_needs_copy_bound(element, count, element_ty);
1525+
// If the length is 0, we don't create any elements, so we don't copy any.
1526+
// If the length is 1, we don't copy that one element, we move it. Only check
1527+
// for `Copy` if the length is larger, or unevaluated.
1528+
// FIXME(min_const_generic_exprs): We could perhaps defer this check so that
1529+
// we don't require `<?0t as Tr>::CONST` doesn't unnecessarily require `Copy`.
1530+
if count.try_to_target_usize(tcx).is_none_or(|x| x > 1) {
1531+
self.enforce_repeat_element_needs_copy_bound(element, element_ty);
1532+
}
15241533

15251534
let ty = Ty::new_array_with_const_len(tcx, t, count);
1526-
15271535
self.register_wf_obligation(ty.into(), expr.span, ObligationCauseCode::WellFormed(None));
1528-
15291536
ty
15301537
}
15311538

1532-
fn check_repeat_element_needs_copy_bound(
1539+
/// Requires that `element_ty` is `Copy` (unless it's a const expression itself).
1540+
fn enforce_repeat_element_needs_copy_bound(
15331541
&self,
15341542
element: &hir::Expr<'_>,
1535-
count: ty::Const<'tcx>,
15361543
element_ty: Ty<'tcx>,
15371544
) {
15381545
let tcx = self.tcx;
@@ -1565,27 +1572,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15651572
_ => traits::IsConstable::No,
15661573
};
15671574

1568-
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
1569-
// don't copy that one element, we move it. Only check for Copy if the length is larger.
1570-
if count.try_eval_target_usize(tcx, self.param_env).is_none_or(|len| len > 1) {
1571-
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
1572-
let code = traits::ObligationCauseCode::RepeatElementCopy {
1573-
is_constable,
1574-
elt_type: element_ty,
1575-
elt_span: element.span,
1576-
elt_stmt_span: self
1577-
.tcx
1578-
.hir()
1579-
.parent_iter(element.hir_id)
1580-
.find_map(|(_, node)| match node {
1581-
hir::Node::Item(it) => Some(it.span),
1582-
hir::Node::Stmt(stmt) => Some(stmt.span),
1583-
_ => None,
1584-
})
1585-
.expect("array repeat expressions must be inside an item or statement"),
1586-
};
1587-
self.require_type_meets(element_ty, element.span, code, lang_item);
1588-
}
1575+
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
1576+
let code = traits::ObligationCauseCode::RepeatElementCopy {
1577+
is_constable,
1578+
elt_type: element_ty,
1579+
elt_span: element.span,
1580+
elt_stmt_span: self
1581+
.tcx
1582+
.hir()
1583+
.parent_iter(element.hir_id)
1584+
.find_map(|(_, node)| match node {
1585+
hir::Node::Item(it) => Some(it.span),
1586+
hir::Node::Stmt(stmt) => Some(stmt.span),
1587+
_ => None,
1588+
})
1589+
.expect("array repeat expressions must be inside an item or statement"),
1590+
};
1591+
self.require_type_meets(element_ty, element.span, code, lang_item);
15891592
}
15901593

15911594
fn check_expr_tuple(
@@ -2800,9 +2803,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
28002803
len: ty::Const<'tcx>,
28012804
) {
28022805
err.span_label(field.span, "unknown field");
2803-
if let (Some(len), Ok(user_index)) =
2804-
(len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
2805-
{
2806+
if let (Some(len), Ok(user_index)) = (
2807+
self.try_structurally_resolve_const(base.span, len).try_to_target_usize(self.tcx),
2808+
field.as_str().parse::<u64>(),
2809+
) {
28062810
let help = "instead of using tuple indexing, use array indexing";
28072811
let applicability = if len < user_index {
28082812
Applicability::MachineApplicable

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14701470
}
14711471
}
14721472

1473+
#[instrument(level = "debug", skip(self, sp), ret)]
1474+
pub fn try_structurally_resolve_const(&self, sp: Span, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
1475+
// FIXME(min_const_generic_exprs): We could process obligations here if `ct` is a var.
1476+
1477+
if self.next_trait_solver()
1478+
&& let ty::ConstKind::Unevaluated(..) = ct.kind()
1479+
{
1480+
// We need to use a separate variable here as otherwise the temporary for
1481+
// `self.fulfillment_cx.borrow_mut()` is alive in the `Err` branch, resulting
1482+
// in a reentrant borrow, causing an ICE.
1483+
let result = self
1484+
.at(&self.misc(sp), self.param_env)
1485+
.structurally_normalize_const(ct, &mut **self.fulfillment_cx.borrow_mut());
1486+
match result {
1487+
Ok(normalized_ct) => normalized_ct,
1488+
Err(errors) => {
1489+
let guar = self.err_ctxt().report_fulfillment_errors(errors);
1490+
return ty::Const::new_error(self.tcx, guar);
1491+
}
1492+
}
1493+
} else if self.tcx.features().generic_const_exprs {
1494+
ct.normalize(self.tcx, self.param_env)
1495+
} else {
1496+
ct
1497+
}
1498+
}
1499+
14731500
/// Resolves `ty` by a single level if `ty` is a type variable.
14741501
///
14751502
/// When the new solver is enabled, this will also attempt to normalize

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1502,7 +1502,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15021502
// Create an dummy type `&[_]` so that both &[] and `&Vec<T>` can coerce to it.
15031503
let dummy_ty = if let ty::Array(elem_ty, size) = peeled.kind()
15041504
&& let ty::Infer(_) = elem_ty.kind()
1505-
&& size.try_eval_target_usize(self.tcx, self.param_env) == Some(0)
1505+
&& self
1506+
.try_structurally_resolve_const(provided_expr.span, *size)
1507+
.try_to_target_usize(self.tcx)
1508+
== Some(0)
15061509
{
15071510
let slice = Ty::new_slice(self.tcx, *elem_ty);
15081511
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, slice)

Diff for: compiler/rustc_hir_typeck/src/intrinsicck.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
101101
}
102102
}
103103
Ok(SizeSkeleton::Generic(size)) => {
104-
if let Some(size) = size.try_eval_target_usize(tcx, self.param_env) {
104+
if let Some(size) =
105+
self.try_structurally_resolve_const(span, size).try_to_target_usize(tcx)
106+
{
105107
format!("{size} bytes")
106108
} else {
107109
format!("generic size {size}")

Diff for: compiler/rustc_hir_typeck/src/method/suggest.rs

+1-14
Original file line numberDiff line numberDiff line change
@@ -1721,20 +1721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17211721
}
17221722
}
17231723

1724-
if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() {
1725-
let msg = "remove this method call";
1726-
let mut fallback_span = true;
1727-
if let SelfSource::MethodCall(expr) = source {
1728-
let call_expr = self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id));
1729-
if let Some(span) = call_expr.span.trim_start(expr.span) {
1730-
err.span_suggestion(span, msg, "", Applicability::MachineApplicable);
1731-
fallback_span = false;
1732-
}
1733-
}
1734-
if fallback_span {
1735-
err.span_label(span, msg);
1736-
}
1737-
} else if let Some(similar_candidate) = similar_candidate {
1724+
if let Some(similar_candidate) = similar_candidate {
17381725
// Don't emit a suggestion if we found an actual method
17391726
// that had unsatisfied trait bounds
17401727
if unsatisfied_predicates.is_empty()

Diff for: compiler/rustc_hir_typeck/src/pat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2412,7 +2412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24122412
len: ty::Const<'tcx>,
24132413
min_len: u64,
24142414
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
2415-
let len = len.try_eval_target_usize(self.tcx, self.param_env);
2415+
let len = self.try_structurally_resolve_const(span, len).try_to_target_usize(self.tcx);
24162416

24172417
let guar = if let Some(len) = len {
24182418
// Now we know the length...

Diff for: compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5757
this.in_scope(region_scope, lint_level, |this| this.as_rvalue(block, scope, value))
5858
}
5959
ExprKind::Repeat { value, count } => {
60-
if Some(0) == count.try_eval_target_usize(this.tcx, this.param_env) {
60+
if Some(0) == count.try_to_target_usize(this.tcx) {
6161
this.build_zero_repeat(block, value, scope, source_info)
6262
} else {
6363
let value_operand = unpack!(

Diff for: compiler/rustc_mir_build/src/build/matches/match_pair.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4242
let tcx = self.tcx;
4343
let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
4444
match place_resolved.ty(&self.local_decls, tcx).ty.kind() {
45-
ty::Array(_, length) => (length.eval_target_usize(tcx, self.param_env), true),
45+
ty::Array(_, length) => (
46+
length
47+
.try_to_target_usize(tcx)
48+
.expect("expected len of array pat to be definite"),
49+
true,
50+
),
4651
_ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
4752
}
4853
} else {

Diff for: compiler/rustc_mir_build/src/thir/pattern/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
441441
ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
442442
// Fixed-length array, `[T; len]`.
443443
ty::Array(_, len) => {
444-
let len = len.eval_target_usize(self.tcx, self.param_env);
444+
let len = len
445+
.try_to_target_usize(self.tcx)
446+
.expect("expected len of array pat to be definite");
445447
assert!(len >= prefix.len() as u64 + suffix.len() as u64);
446448
PatKind::Array { prefix, slice, suffix }
447449
}

Diff for: compiler/rustc_pattern_analysis/src/rustc.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
352352
ty::Array(sub_ty, len) => {
353353
// We treat arrays of a constant but unknown length like slices.
354354
ConstructorSet::Slice {
355-
array_len: len.try_eval_target_usize(cx.tcx, cx.param_env).map(|l| l as usize),
355+
array_len: len.try_to_target_usize(cx.tcx).map(|l| l as usize),
356356
subtype_is_empty: cx.is_uninhabited(*sub_ty),
357357
}
358358
}
@@ -685,9 +685,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
685685
}
686686
PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
687687
let array_len = match ty.kind() {
688-
ty::Array(_, length) => {
689-
Some(length.eval_target_usize(cx.tcx, cx.param_env) as usize)
690-
}
688+
ty::Array(_, length) => Some(
689+
length
690+
.try_to_target_usize(cx.tcx)
691+
.expect("expected len of array pat to be definite")
692+
as usize,
693+
),
691694
ty::Slice(_) => None,
692695
_ => span_bug!(pat.span, "bad ty {} for slice pattern", ty.inner()),
693696
};

Diff for: compiler/rustc_symbol_mangling/src/v0.rs

+27-32
Original file line numberDiff line numberDiff line change
@@ -607,45 +607,40 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
607607
let _ = write!(self.out, "{bits:x}_");
608608
}
609609

610+
// Handle `str` as partial support for unsized constants
611+
ty::Str => {
612+
let tcx = self.tcx();
613+
// HACK(jaic1): hide the `str` type behind a reference
614+
// for the following transformation from valtree to raw bytes
615+
let ref_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, ct_ty);
616+
let slice = valtree.try_to_raw_bytes(tcx, ref_ty).unwrap_or_else(|| {
617+
bug!("expected to get raw bytes from valtree {:?} for type {:}", valtree, ct_ty)
618+
});
619+
let s = std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter");
620+
621+
// "e" for str as a basic type
622+
self.push("e");
623+
624+
// FIXME(eddyb) use a specialized hex-encoding loop.
625+
for byte in s.bytes() {
626+
let _ = write!(self.out, "{byte:02x}");
627+
}
628+
629+
self.push("_");
630+
}
631+
610632
// FIXME(valtrees): Remove the special case for `str`
611633
// here and fully support unsized constants.
612-
ty::Ref(_, inner_ty, mutbl) => {
634+
ty::Ref(_, _, mutbl) => {
613635
self.push(match mutbl {
614636
hir::Mutability::Not => "R",
615637
hir::Mutability::Mut => "Q",
616638
});
617639

618-
match inner_ty.kind() {
619-
ty::Str if mutbl.is_not() => {
620-
let slice =
621-
valtree.try_to_raw_bytes(self.tcx(), ct_ty).unwrap_or_else(|| {
622-
bug!(
623-
"expected to get raw bytes from valtree {:?} for type {:}",
624-
valtree,
625-
ct_ty
626-
)
627-
});
628-
let s =
629-
std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter");
630-
631-
self.push("e");
632-
633-
// FIXME(eddyb) use a specialized hex-encoding loop.
634-
for byte in s.bytes() {
635-
let _ = write!(self.out, "{byte:02x}");
636-
}
637-
638-
self.push("_");
639-
}
640-
_ => {
641-
let pointee_ty = ct_ty
642-
.builtin_deref(true)
643-
.expect("tried to dereference on non-ptr type");
644-
let dereferenced_const =
645-
ty::Const::new_value(self.tcx, valtree, pointee_ty);
646-
dereferenced_const.print(self)?;
647-
}
648-
}
640+
let pointee_ty =
641+
ct_ty.builtin_deref(true).expect("tried to dereference on non-ptr type");
642+
let dereferenced_const = ty::Const::new_value(self.tcx, valtree, pointee_ty);
643+
dereferenced_const.print(self)?;
649644
}
650645

651646
ty::Array(..) | ty::Tuple(..) | ty::Adt(..) | ty::Slice(_) => {

0 commit comments

Comments
 (0)