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

Get rid of the Scalar and ScalarPair variants of ConstValue... #55260

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
edf94c5
Update function names in comments
oli-obk Oct 19, 2018
856eaed
Simplify `ConstValue`
oli-obk Oct 21, 2018
fe4e950
Make the HashStable impl of Allocation safer for future changes of th…
oli-obk Oct 21, 2018
04fc561
The `Hash` and `Eq` impls of `ConstValue` were inherently broken
oli-obk Oct 21, 2018
b11b3cb
Fixup a bunch of things for "simplify const value"
oli-obk Oct 21, 2018
3aecb0d
Fix some simd intrinsics
oli-obk Oct 21, 2018
8d42376
Fix an ICE that can occur while errors are already being emitted
oli-obk Oct 21, 2018
847f5b9
Const prop is only interested in immediate constants right now
oli-obk Oct 21, 2018
e52644c
Update a few tests with their improved diagnostic messages
oli-obk Oct 21, 2018
8246dd4
Alignment check facepalm
oli-obk Oct 21, 2018
5620d68
Enums can produce scalar pairs with undefs in one of the elements
oli-obk Oct 21, 2018
fc6472c
Hide a constructor function that is unused outside this module
oli-obk Oct 22, 2018
336094f
Use a more appropriate parameter environment
oli-obk Oct 22, 2018
b4ba332
Don't resolve `impl Trait` in function def constants to the concrete …
oli-obk Oct 22, 2018
dfc5d26
Constants carry their type with them
oli-obk Oct 22, 2018
c50d77d
Alignment of `const_field` results must be of the field's type
oli-obk Oct 22, 2018
1d14a84
Add a debugging aid
oli-obk Oct 22, 2018
9fbce39
Change some useless `ParamEnv::empty` to `reveal_all`
oli-obk Oct 22, 2018
1f2fcee
Improve debugging output of layout computation failure
oli-obk Oct 22, 2018
e3bbe6d
Shrink allocations to fit the type at hand
oli-obk Oct 22, 2018
6ff70da
Resize `Allocation`s when doing field accesses into them
oli-obk Oct 22, 2018
7b526d8
Read the slice length from the correct place in the fat pointer
oli-obk Oct 22, 2018
9df63e9
Global Allocations don't have an `extra` value
oli-obk Oct 22, 2018
a7a92e2
Rebase fallout
oli-obk Oct 22, 2018
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
64 changes: 56 additions & 8 deletions src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ use middle::region;
use std::iter;
use std::io;
use std::ops::{Deref, DerefMut};
use std::hash::Hash;
use std::cmp;
use std::hash::{Hash, Hasher};
use syntax::ast::Mutability;
use rustc_serialize::{Encoder, Decodable, Encodable};
use rustc_data_structures::sorted_map::SortedMap;
Expand Down Expand Up @@ -217,9 +218,56 @@ impl<'tcx, Tag> Pointer<Tag> {
}


#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct AllocId(pub u64);

impl Eq for AllocId {}

impl Hash for AllocId {
fn hash<H: Hasher>(&self, state: &mut H) {
ty::tls::with(|tcx| {
let alloc_type = tcx.alloc_map.lock().get(*self);
match alloc_type {
Some(alloc_type) => alloc_type.hash(state),
None => self.0.hash(state),
}
})
}
}

impl PartialEq for AllocId {
fn eq(&self, other: &Self) -> bool {
ty::tls::with(|tcx| {
let (s, o) = {
let map = tcx.alloc_map.lock();
(map.get(*self), map.get(*other))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, wait, what? That doesn't seem right to me.

Certainly, ptr comparison in miri should compare the actual IDs, the the content that's stored behind these IDs. What is the type of s and o here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only applies to AllocIds that refer to global allocations. Comparing by id is inherently wrong. We never ran into any trouble, because we never used a ConstValue containing an AllocId in comparisons that mattered. Now that everything is ByRef, pattern match exhaustiveness checks failed because they couldn't figure out that two const patterns are the same if their AllocId differs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only applies to AllocIds that refer to global allocations.

It is still grossly wrong in the context of the miri engine. Ptr equality wants to compare the IDs, not the allocations they point to, and the IDs should be newtyped to not mix them up with other integers.

pattern match exhaustiveness checks failed because they couldn't figure out that two const patterns are the same if their AllocId differs.

Then it shouldn't use the same equality as the miri engine. If you want to overwrite equality and hashing for ConstValue, I can support that, but doing it for a type used inside the engine makes me really nervous.

};
s == o
})
}
}

impl Ord for AllocId {
fn cmp(&self, other: &Self) -> cmp::Ordering {
match self.partial_cmp(other) {
Some(ord) => ord,
None => self.0.cmp(&other.0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it okay to fall back to comparing the integers here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This happens only for non-interned allocations

}
}
}

impl PartialOrd for AllocId {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
ty::tls::with(|tcx| {
let (s, o) = {
let map = tcx.alloc_map.lock();
(map.get(*self)?, map.get(*other)?)
};
s.partial_cmp(&o)
})
}
}

impl ::rustc_serialize::UseSpecializedEncodable for AllocId {}
impl ::rustc_serialize::UseSpecializedDecodable for AllocId {}

Expand Down Expand Up @@ -427,7 +475,7 @@ impl fmt::Display for AllocId {
}
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable)]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
pub enum AllocType<'tcx, M> {
/// The alloc id is used as a function pointer
Function(Instance<'tcx>),
Expand All @@ -440,7 +488,7 @@ pub enum AllocType<'tcx, M> {

pub struct AllocMap<'tcx, M> {
/// Lets you know what an AllocId refers to
id_to_type: FxHashMap<AllocId, AllocType<'tcx, M>>,
id_to_type: FxHashMap<u64, AllocType<'tcx, M>>,
Copy link
Member

@RalfJung RalfJung Oct 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we lose the newtype protection for not mixing up IDs.

I don't understand the purpose of this entire commit, at all. It also suffers from an astute lack of comments :)


/// Used to ensure that functions and statics only get one associated AllocId
type_interner: FxHashMap<AllocType<'tcx, M>, AllocId>,
Expand Down Expand Up @@ -479,7 +527,7 @@ impl<'tcx, M: fmt::Debug + Eq + Hash + Clone> AllocMap<'tcx, M> {
}
let id = self.reserve();
debug!("creating alloc_type {:?} with id {}", alloc_type, id);
self.id_to_type.insert(id, alloc_type.clone());
self.id_to_type.insert(id.0, alloc_type.clone());
self.type_interner.insert(alloc_type, id);
id
}
Expand All @@ -492,7 +540,7 @@ impl<'tcx, M: fmt::Debug + Eq + Hash + Clone> AllocMap<'tcx, M> {
}

pub fn get(&self, id: AllocId) -> Option<AllocType<'tcx, M>> {
self.id_to_type.get(&id).cloned()
self.id_to_type.get(&id.0).cloned()
}

pub fn unwrap_memory(&self, id: AllocId) -> M {
Expand All @@ -513,13 +561,13 @@ impl<'tcx, M: fmt::Debug + Eq + Hash + Clone> AllocMap<'tcx, M> {
}

pub fn set_id_memory(&mut self, id: AllocId, mem: M) {
if let Some(old) = self.id_to_type.insert(id, AllocType::Memory(mem)) {
if let Some(old) = self.id_to_type.insert(id.0, AllocType::Memory(mem)) {
bug!("tried to set allocation id {}, but it was already existing as {:#?}", id, old);
}
}

pub fn set_id_same_memory(&mut self, id: AllocId, mem: M) {
self.id_to_type.insert_same(id, AllocType::Memory(mem));
self.id_to_type.insert_same(id.0, AllocType::Memory(mem));
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ use util::ppaux;

use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct Instance<'tcx> {
pub def: InstanceDef<'tcx>,
pub substs: &'tcx Substs<'tcx>,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum InstanceDef<'tcx> {
Item(DefId),
Intrinsic(DefId),
Expand Down