Skip to content

Rollup of 7 pull requests #127906

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
72e2255
cleanup: remove support for 3DNow! cpu features
durin42 Jul 17, 2024
a47ca19
rewrite extern-fn-with-extern-types to rmake
Oneirical Jul 8, 2024
a795d89
rewrite and rename issue-25581
Oneirical Jul 8, 2024
d6a3f65
rewrite extern-fn-struct-passing-abi to rmake
Oneirical Jul 8, 2024
98454ec
rewrite longjmp-across-rust to rmake
Oneirical Jul 8, 2024
205bfe7
rewrite static-extern-type to rmake
Oneirical Jul 8, 2024
bde9178
rewrite extern-fn-explicit-align to rmake
Oneirical Jul 8, 2024
f7d67d6
rewrite extern-fn-with-packed-struct to rmake
Oneirical Jul 8, 2024
c68d25b
rewrite extern-fn-mangle to rmake
Oneirical Jul 8, 2024
d83ada3
rewrite and rename issue-85401-static-mir
Oneirical Jul 16, 2024
890ef11
rewrite missing-crate-dependency to rmake
Oneirical Jul 16, 2024
3ba62f0
rewrite unstable-flag-required to rmake
Oneirical Jul 16, 2024
7f3f34d
Mark myself as on leave
oli-obk Jul 18, 2024
487802d
Remove `TrailingToken`.
nnethercote Jul 16, 2024
69157bd
Add missing GHA group for building `llvm-bitcode-linker`
Kobzol Jul 18, 2024
fa74a9e
valtree construction: keep track of which type was valtree-incompatible
RalfJung Jul 13, 2024
e613bc9
const_to_pat: cleanup leftovers from when we had to deal with non-str…
RalfJung Jul 13, 2024
86ce911
pattern lowering: make sure we never call user-defined PartialEq inst…
RalfJung Jul 13, 2024
67c99d6
avoid creating an Instance only to immediately disassemble it again
RalfJung Jul 13, 2024
303a2db
remove saw_const_match_error; check if pattern contains an Error instead
RalfJung Jul 15, 2024
78fe5f7
Rollup merge of #127491 - Oneirical:bulletproof-test, r=jieyouxu
tgross35 Jul 18, 2024
a2178df
Rollup merge of #127687 - RalfJung:pattern-cleanup, r=oli-obk,lcnr
tgross35 Jul 18, 2024
d817c0f
Rollup merge of #127822 - Oneirical:amazon-rainfortest, r=jieyouxu
tgross35 Jul 18, 2024
e2e0681
Rollup merge of #127842 - nnethercote:rm-TrailingToken, r=petrochenkov
tgross35 Jul 18, 2024
e4bc3d5
Rollup merge of #127864 - durin42:farewell-3dnow, r=nikic
tgross35 Jul 18, 2024
73eba8e
Rollup merge of #127899 - oli-obk:leave, r=lqd
tgross35 Jul 18, 2024
16d2b61
Rollup merge of #127901 - Kobzol:llvm-bitcode-linker-gha-group, r=onu…
tgross35 Jul 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4411,6 +4411,7 @@ dependencies = [
name = "rustc_mir_build"
version = "0.0.0"
dependencies = [
"either",
"itertools",
"rustc_apfloat",
"rustc_arena",
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn eval_unevaluated_mir_constant_to_valtree(
&self,
constant: &mir::ConstOperand<'tcx>,
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
) -> Result<Result<ty::ValTree<'tcx>, Ty<'tcx>>, ErrorHandled> {
let uv = match self.monomorphize(constant.const_) {
mir::Const::Unevaluated(uv, _) => uv.shrink(),
mir::Const::Ty(_, c) => match c.kind() {
// A constant that came from a const generic but was then used as an argument to old-style
// simd_shuffle (passing as argument instead of as a generic param).
rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Some(valtree)),
rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Ok(valtree)),
other => span_bug!(constant.span, "{other:#?}"),
},
// We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
Expand All @@ -70,6 +70,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let val = self
.eval_unevaluated_mir_constant_to_valtree(constant)
.ok()
.map(|x| x.ok())
.flatten()
.map(|val| {
let field_ty = ty.builtin_index().unwrap();
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_const_eval/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ pub(crate) use valtrees::{eval_to_valtree, valtree_to_const_value};
// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
const VALTREE_MAX_NODES: usize = 100000;

pub(crate) enum ValTreeCreationError {
pub(crate) enum ValTreeCreationError<'tcx> {
NodesOverflow,
/// Values of this type, or this particular value, are not supported as valtrees.
NonSupportedType,
NonSupportedType(Ty<'tcx>),
}
pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError<'tcx>>;

impl From<InterpErrorInfo<'_>> for ValTreeCreationError {
fn from(err: InterpErrorInfo<'_>) -> Self {
impl<'tcx> From<InterpErrorInfo<'tcx>> for ValTreeCreationError<'tcx> {
fn from(err: InterpErrorInfo<'tcx>) -> Self {
ty::tls::with(|tcx| {
bug!(
"Unexpected Undefined Behavior error during valtree construction: {}",
Expand Down
16 changes: 8 additions & 8 deletions compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,21 @@ fn const_to_valtree_inner<'tcx>(
// We could allow wide raw pointers where both sides are integers in the future,
// but for now we reject them.
if matches!(val.layout.abi, Abi::ScalarPair(..)) {
return Err(ValTreeCreationError::NonSupportedType);
return Err(ValTreeCreationError::NonSupportedType(ty));
}
let val = val.to_scalar();
// We are in the CTFE machine, so ptr-to-int casts will fail.
// This can only be `Ok` if `val` already is an integer.
let Ok(val) = val.try_to_scalar_int() else {
return Err(ValTreeCreationError::NonSupportedType);
return Err(ValTreeCreationError::NonSupportedType(ty));
};
// It's just a ScalarInt!
Ok(ty::ValTree::Leaf(val))
}

// Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
// agree with runtime equality tests.
ty::FnPtr(_) => Err(ValTreeCreationError::NonSupportedType),
ty::FnPtr(_) => Err(ValTreeCreationError::NonSupportedType(ty)),

ty::Ref(_, _, _) => {
let derefd_place = ecx.deref_pointer(place)?;
Expand All @@ -148,15 +148,15 @@ fn const_to_valtree_inner<'tcx>(
// resolving their backing type, even if we can do that at const eval time. We may
// hypothetically be able to allow `dyn StructuralPartialEq` trait objects in the future,
// but it is unclear if this is useful.
ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType),
ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType(ty)),

ty::Tuple(elem_tys) => {
branches(ecx, place, elem_tys.len(), None, num_nodes)
}

ty::Adt(def, _) => {
if def.is_union() {
return Err(ValTreeCreationError::NonSupportedType);
return Err(ValTreeCreationError::NonSupportedType(ty));
} else if def.variants().is_empty() {
bug!("uninhabited types should have errored and never gotten converted to valtree")
}
Expand All @@ -180,7 +180,7 @@ fn const_to_valtree_inner<'tcx>(
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType),
| ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType(ty)),
}
}

Expand Down Expand Up @@ -251,7 +251,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes);

match valtree_result {
Ok(valtree) => Ok(Some(valtree)),
Ok(valtree) => Ok(Ok(valtree)),
Err(err) => {
let did = cid.instance.def_id();
let global_const_id = cid.display(tcx);
Expand All @@ -262,7 +262,7 @@ pub(crate) fn eval_to_valtree<'tcx>(
tcx.dcx().emit_err(MaxNumNodesInConstErr { span, global_const_id });
Err(handled.into())
}
ValTreeCreationError::NonSupportedType => Ok(None),
ValTreeCreationError::NonSupportedType(ty) => Ok(Err(ty)),
}
}
}
Expand Down
17 changes: 8 additions & 9 deletions compiler/rustc_error_codes/src/error_codes/E0158.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
An associated `const`, `const` parameter or `static` has been referenced
in a pattern.
A generic parameter or `static` has been referenced in a pattern.

Erroneous code example:

Expand All @@ -15,25 +14,25 @@ trait Bar {

fn test<A: Bar>(arg: Foo) {
match arg {
A::X => println!("A::X"), // error: E0158: associated consts cannot be
// referenced in patterns
A::X => println!("A::X"), // error: E0158: constant pattern depends
// on a generic parameter
Foo::Two => println!("Two")
}
}
```

Associated `const`s cannot be referenced in patterns because it is impossible
Generic parameters cannot be referenced in patterns because it is impossible
for the compiler to prove exhaustiveness (that some pattern will always match).
Take the above example, because Rust does type checking in the *generic*
method, not the *monomorphized* specific instance. So because `Bar` could have
theoretically infinite implementations, there's no way to always be sure that
theoretically arbitrary implementations, there's no way to always be sure that
`A::X` is `Foo::One`. So this code must be rejected. Even if code can be
proven exhaustive by a programmer, the compiler cannot currently prove this.

The same holds true of `const` parameters and `static`s.
The same holds true of `static`s.

If you want to match against an associated `const`, `const` parameter or
`static` consider using a guard instead:
If you want to match against a `const` that depends on a generic parameter or a
`static`, consider using a guard instead:

```
trait Trait {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1427,17 +1427,17 @@ impl<'tcx> InferCtxt<'tcx> {
span: Span,
) -> Result<ty::Const<'tcx>, ErrorHandled> {
match self.const_eval_resolve(param_env, unevaluated, span) {
Ok(Some(val)) => Ok(ty::Const::new_value(
Ok(Ok(val)) => Ok(ty::Const::new_value(
self.tcx,
val,
self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args),
)),
Ok(None) => {
Ok(Err(bad_ty)) => {
let tcx = self.tcx;
let def_id = unevaluated.def;
span_bug!(
tcx.def_span(def_id),
"unable to construct a constant value for the unevaluated constant {:?}",
"unable to construct a valtree for the unevaluated constant {:?}: type {bad_ty} is not valtree-compatible",
unevaluated
);
}
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,11 @@ TrivialTypeTraversalImpls! { ErrorHandled }
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>;
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
/// `Ok(None)` indicates the constant was fine, but the valtree couldn't be constructed.
/// This is needed in `thir::pattern::lower_inline_const`.
pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
/// `Ok(Err(ty))` indicates the constant was fine, but the valtree couldn't be constructed
/// because the value containts something of type `ty` that is not valtree-compatible.
/// The caller can then show an appropriate error; the query does not have the
/// necssary context to give good user-facing errors for this case.
pub type EvalToValTreeResult<'tcx> = Result<Result<ValTree<'tcx>, Ty<'tcx>>, ErrorHandled>;

#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(InterpErrorInfo<'_>, 8);
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,10 @@ impl EraseType for Result<mir::ConstValue<'_>, mir::interpret::ErrorHandled> {
type Result = [u8; size_of::<Result<mir::ConstValue<'static>, mir::interpret::ErrorHandled>>()];
}

impl EraseType for Result<Option<ty::ValTree<'_>>, mir::interpret::ErrorHandled> {
type Result =
[u8; size_of::<Result<Option<ty::ValTree<'static>>, mir::interpret::ErrorHandled>>()];
impl EraseType for Result<Result<ty::ValTree<'_>, Ty<'_>>, mir::interpret::ErrorHandled> {
type Result = [u8; size_of::<
Result<Result<ty::ValTree<'static>, Ty<'static>>, mir::interpret::ErrorHandled>,
>()];
}

impl EraseType for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
Expand Down
11 changes: 4 additions & 7 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,16 +783,13 @@ pub enum PatKind<'tcx> {
},

/// One of the following:
/// * `&str` (represented as a valtree), which will be handled as a string pattern and thus
/// exhaustiveness checking will detect if you use the same string twice in different
/// patterns.
/// * `&str`/`&[u8]` (represented as a valtree), which will be handled as a string/slice pattern
/// and thus exhaustiveness checking will detect if you use the same string/slice twice in
/// different patterns.
/// * integer, bool, char or float (represented as a valtree), which will be handled by
/// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
/// much simpler.
/// * Opaque constants (represented as `mir::ConstValue`), that must not be matched
/// structurally. So anything that does not derive `PartialEq` and `Eq`.
///
/// These are always compared with the matched place using (the semantics of) `PartialEq`.
/// * `String`, if `string_deref_patterns` is enabled.
Constant {
value: mir::Const<'tcx>,
},
Expand Down
53 changes: 38 additions & 15 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::middle::resolve_bound_vars as rbv;
use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar};
use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use either::Either;
use rustc_data_structures::intern::Interned;
use rustc_error_messages::MultiSpan;
use rustc_hir as hir;
Expand Down Expand Up @@ -312,14 +313,16 @@ impl<'tcx> Const<'tcx> {
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
}

/// Returns the evaluated constant
/// Returns the evaluated constant as a valtree;
/// if that fails due to a valtree-incompatible type, indicate which type that is
/// by returning `Err(Left(bad_type))`.
#[inline]
pub fn eval(
pub fn eval_valtree(
self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
span: Span,
) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
) -> Result<(Ty<'tcx>, ValTree<'tcx>), Either<Ty<'tcx>, ErrorHandled>> {
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
match self.kind() {
ConstKind::Unevaluated(unevaluated) => {
Expand All @@ -328,27 +331,47 @@ impl<'tcx> Const<'tcx> {
let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env);
// try to resolve e.g. associated constants to their definition on an impl, and then
// evaluate the const.
let Some(c) = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?
else {
// This can happen when we run on ill-typed code.
let e = tcx.dcx().span_delayed_bug(
span,
"`ty::Const::eval` called on a non-valtree-compatible type",
);
return Err(e.into());
};
Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span) {
Ok(Ok(c)) => {
Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
}
Ok(Err(bad_ty)) => Err(Either::Left(bad_ty)),
Err(err) => Err(Either::Right(err.into())),
}
}
ConstKind::Value(ty, val) => Ok((ty, val)),
ConstKind::Error(g) => Err(g.into()),
ConstKind::Error(g) => Err(Either::Right(g.into())),
ConstKind::Param(_)
| ConstKind::Infer(_)
| ConstKind::Bound(_, _)
| ConstKind::Placeholder(_)
| ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric(span)),
| ConstKind::Expr(_) => Err(Either::Right(ErrorHandled::TooGeneric(span))),
}
}

/// Returns the evaluated constant
#[inline]
pub fn eval(
self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
span: Span,
) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
self.eval_valtree(tcx, param_env, span).map_err(|err| {
match err {
Either::Right(err) => err,
Either::Left(_bad_ty) => {
// This can happen when we run on ill-typed code.
let e = tcx.dcx().span_delayed_bug(
span,
"`ty::Const::eval` called on a non-valtree-compatible type",
);
e.into()
}
}
})
}

/// Normalizes the constant to a value or an error if possible.
#[inline]
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"

[dependencies]
# tidy-alphabetical-start
either = "1.5.0"
itertools = "0.12"
rustc_apfloat = "0.2.0"
rustc_arena = { path = "../rustc_arena" }
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_mir_build/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ mir_build_already_borrowed = cannot borrow value as mutable because it is also b

mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable

mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns

mir_build_bindings_with_variant_name =
pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
.suggestion = to match on the variant, qualify the path
Expand Down
Loading
Loading