Skip to content
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

Fully destructure constants into patterns #70743

Merged
merged 21 commits into from
Sep 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b54f122
Merge tuple and struct pattern generation.
oli-obk Apr 3, 2020
34c62e0
Add a query for dereferencing constants of reference type
oli-obk Jul 1, 2020
b2532a8
Implement destructuring for all aggregates and for references
oli-obk Jul 1, 2020
3795886
Split check for `PartialEq` impl into a method
oli-obk Sep 20, 2020
aba5ea1
Lint on function pointers used in patterns
oli-obk Sep 20, 2020
adf98ab
Use precise errors during const to pat conversion instead of a catch-…
oli-obk Sep 20, 2020
f7eceef
Document future incompat lints
oli-obk Sep 21, 2020
f12583a
Pacify tidy
oli-obk Sep 21, 2020
1b1b6ea
Remove the "lift constant to reference" logic
oli-obk Sep 23, 2020
d486486
Talk about unpredictable instead of "not deterministic"
oli-obk Sep 23, 2020
177d0ce
Deduplicate errors in const to pat conversion
oli-obk Sep 23, 2020
9a7e66a
Make sure we don't hide errors just because a lint has been emitted
oli-obk Sep 23, 2020
6a33de0
Name function correctly
oli-obk Sep 23, 2020
0174231
Make sure we report a future incompat error in all cases
oli-obk Sep 23, 2020
da21764
Make sure we keep emitting a hard error
oli-obk Sep 23, 2020
9aa1c09
Update documentation tests
oli-obk Sep 23, 2020
2bc54d4
Don't talk about determinism
oli-obk Sep 24, 2020
e4928d7
Use correct type in diagnostics again
oli-obk Sep 24, 2020
9550ca6
Deduplicate the "needs partialeq derive" message creation sites
oli-obk Sep 24, 2020
fc9f294
Document `FallbackToConstRef` and make sure we don't accidentally use it
oli-obk Sep 24, 2020
daf976f
Revert a test change to make sure it's still testing the original issue
oli-obk Sep 24, 2020
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
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,14 @@ rustc_queries! {
desc { "destructure constant" }
}

/// Dereference a constant reference or raw pointer and turn the result into a constant
/// again.
query deref_const(
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
) -> &'tcx ty::Const<'tcx> {
desc { "deref constant" }
}

query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
desc { "get a &core::panic::Location referring to a span" }
}
Expand Down
41 changes: 40 additions & 1 deletion compiler/rustc_mir/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

use std::convert::TryFrom;

use rustc_hir::Mutability;
use rustc_middle::mir;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};

use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx};
use crate::interpret::{
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, MemPlaceMeta, Scalar,
};

mod error;
mod eval_queries;
Expand Down Expand Up @@ -67,3 +70,39 @@ pub(crate) fn destructure_const<'tcx>(

mir::DestructuredConst { variant, fields }
}

pub(crate) fn deref_const<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
val: &'tcx ty::Const<'tcx>,
) -> &'tcx ty::Const<'tcx> {
trace!("deref_const: {:?}", val);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
let op = ecx.const_to_op(val, None).unwrap();
let mplace = ecx.deref_operand(op).unwrap();
if let Scalar::Ptr(ptr) = mplace.ptr {
assert_eq!(
ecx.memory.get_raw(ptr.alloc_id).unwrap().mutability,
Mutability::Not,
"deref_const cannot be used with mutable allocations as \
that could allow pattern matching to observe mutable statics",
);
}

let ty = match mplace.meta {
MemPlaceMeta::None => mplace.layout.ty,
MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
// In case of unsized types, figure out the real type behind.
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
ty::Str => bug!("there's no sized equivalent of a `str`"),
ty::Slice(elem_ty) => tcx.mk_array(elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
_ => bug!(
"type {} should not have metadata, but had {:?}",
mplace.layout.ty,
mplace.meta
),
},
};

tcx.mk_const(ty::Const { val: ty::ConstKind::Value(op_to_const(&ecx, mplace.into())), ty })
}
4 changes: 4 additions & 0 deletions compiler/rustc_mir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,8 @@ pub fn provide(providers: &mut Providers) {
let (param_env, value) = param_env_and_value.into_parts();
const_eval::destructure_const(tcx, param_env, value)
};
providers.deref_const = |tcx, param_env_and_value| {
let (param_env, value) = param_env_and_value.into_parts();
const_eval::deref_const(tcx, param_env, value)
};
}
Loading