Skip to content

Commit

Permalink
data_structures: Add a reference wrapper for pointer-indexed maps/sets
Browse files Browse the repository at this point in the history
Use `ptr::eq` for comparing pointers
  • Loading branch information
petrochenkov committed Jul 20, 2018
1 parent 414a86e commit 2eb83ee
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/liballoc/collections/btree/node.rs
Expand Up @@ -103,7 +103,7 @@ impl<K, V> LeafNode<K, V> {
}

fn is_shared_root(&self) -> bool {
self as *const _ == &EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V>
ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/lint/mod.rs
Expand Up @@ -39,7 +39,7 @@ use hir::intravisit;
use hir;
use lint::builtin::BuiltinLintDiagnostics;
use session::{Session, DiagnosticMessageId};
use std::hash;
use std::{hash, ptr};
use syntax::ast;
use syntax::codemap::MultiSpan;
use syntax::edition::Edition;
Expand Down Expand Up @@ -354,7 +354,7 @@ pub struct LintId {

impl PartialEq for LintId {
fn eq(&self, other: &LintId) -> bool {
(self.lint as *const Lint) == (other.lint as *const Lint)
ptr::eq(self.lint, other.lint)
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/librustc/ty/mod.rs
Expand Up @@ -47,7 +47,7 @@ use std::ops::Deref;
use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter};
use std::slice;
use std::vec::IntoIter;
use std::mem;
use std::{mem, ptr};
use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
use syntax::attr;
use syntax::ext::hygiene::Mark;
Expand Down Expand Up @@ -527,8 +527,7 @@ impl<'tcx> PartialOrd for TyS<'tcx> {
impl<'tcx> PartialEq for TyS<'tcx> {
#[inline]
fn eq(&self, other: &TyS<'tcx>) -> bool {
// (self as *const _) == (other as *const _)
(self as *const TyS<'tcx>) == (other as *const TyS<'tcx>)
ptr::eq(self, other)
}
}
impl<'tcx> Eq for TyS<'tcx> {}
Expand Down Expand Up @@ -678,7 +677,7 @@ impl<T> PartialOrd for Slice<T> where T: PartialOrd {
impl<T: PartialEq> PartialEq for Slice<T> {
#[inline]
fn eq(&self, other: &Slice<T>) -> bool {
(self as *const _) == (other as *const _)
ptr::eq(self, other)
}
}
impl<T: Eq> Eq for Slice<T> {}
Expand Down Expand Up @@ -1730,7 +1729,7 @@ impl Ord for AdtDef {
impl PartialEq for AdtDef {
// AdtDef are always interned and this is part of TyS equality
#[inline]
fn eq(&self, other: &Self) -> bool { self as *const _ == other as *const _ }
fn eq(&self, other: &Self) -> bool { ptr::eq(self, other) }
}

impl Eq for AdtDef {}
Expand Down
9 changes: 5 additions & 4 deletions src/librustc/ty/query/job.rs
Expand Up @@ -11,6 +11,7 @@
#![allow(warnings)]

use std::mem;
use rustc_data_structures::ptr_key::PtrKey;
use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
use rustc_data_structures::OnDrop;
use syntax_pos::Span;
Expand All @@ -20,7 +21,7 @@ use ty::query::plumbing::CycleError;
use ty::context::TyCtxt;
use errors::Diagnostic;
use std::process;
use std::fmt;
use std::{fmt, ptr};
use std::collections::HashSet;
#[cfg(parallel_queries)]
use {
Expand Down Expand Up @@ -124,7 +125,7 @@ impl<'tcx> QueryJob<'tcx> {
while let Some(job) = current_job {
cycle.insert(0, job.info.clone());

if &*job as *const _ == self as *const _ {
if ptr::eq(&*job, self) {
// This is the end of the cycle
// The span entry we included was for the usage
// of the cycle itself, and not part of the cycle
Expand Down Expand Up @@ -282,7 +283,7 @@ where
fn cycle_check<'tcx>(query: Lrc<QueryJob<'tcx>>,
span: Span,
stack: &mut Vec<(Span, Lrc<QueryJob<'tcx>>)>,
visited: &mut HashSet<*const QueryJob<'tcx>>
visited: &mut HashSet<PtrKey<'tcx, QueryJob<'tcx>>>
) -> Option<Option<Waiter<'tcx>>> {
if visited.contains(&query.as_ptr()) {
return if let Some(p) = stack.iter().position(|q| q.1.as_ptr() == query.as_ptr()) {
Expand Down Expand Up @@ -321,7 +322,7 @@ fn cycle_check<'tcx>(query: Lrc<QueryJob<'tcx>>,
#[cfg(parallel_queries)]
fn connected_to_root<'tcx>(
query: Lrc<QueryJob<'tcx>>,
visited: &mut HashSet<*const QueryJob<'tcx>>
visited: &mut HashSet<PtrKey<'tcx, QueryJob<'tcx>>>
) -> bool {
// We already visited this or we're deliberately ignoring it
if visited.contains(&query.as_ptr()) {
Expand Down
21 changes: 11 additions & 10 deletions src/librustc_data_structures/lib.rs
Expand Up @@ -56,29 +56,30 @@ extern crate rustc_cratesio_shim;

pub use rustc_serialize::hex::ToHex;

pub mod array_vec;
pub mod accumulate_vec;
pub mod small_vec;
pub mod array_vec;
pub mod base_n;
pub mod bitslice;
pub mod bitvec;
pub mod flock;
pub mod fx;
pub mod graph;
pub mod indexed_set;
pub mod indexed_vec;
pub mod obligation_forest;
pub mod owning_ref;
pub mod ptr_key;
pub mod sip128;
pub mod small_vec;
pub mod snapshot_map;
pub use ena::snapshot_vec;
pub mod sorted_map;
pub mod stable_hasher;
pub mod transitive_relation;
pub use ena::unify;
pub mod fx;
pub mod tuple_slice;
pub mod graph;
pub mod flock;
pub mod sync;
pub mod owning_ref;
pub mod tiny_list;
pub mod sorted_map;
pub mod transitive_relation;
pub mod tuple_slice;
pub use ena::unify;
pub mod work_queue;

pub struct OnDrop<F: Fn()>(pub F);
Expand Down
45 changes: 45 additions & 0 deletions src/librustc_data_structures/ptr_key.rs
@@ -0,0 +1,45 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::{hash, ptr};
use std::ops::Deref;

/// A wrapper around reference that compares and hashes like a pointer.
/// Can be used as a key in sets/maps indexed by pointers to avoid `unsafe`.
#[derive(Debug)]
pub struct PtrKey<'a, T: 'a>(pub &'a T);

impl<'a, T> Clone for PtrKey<'a, T> {
fn clone(&self) -> Self { *self }
}

impl<'a, T> Copy for PtrKey<'a, T> {}

impl<'a, T> PartialEq for PtrKey<'a, T> {
fn eq(&self, rhs: &Self) -> bool {
ptr::eq(self.0, rhs.0)
}
}

impl<'a, T> Eq for PtrKey<'a, T> {}

impl<'a, T> hash::Hash for PtrKey<'a, T> {
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
(self.0 as *const T).hash(hasher)
}
}

impl<'a, T> Deref for PtrKey<'a, T> {
type Target = T;

fn deref(&self) -> &Self::Target {
self.0
}
}
16 changes: 8 additions & 8 deletions src/librustc_resolve/resolve_imports.rs
Expand Up @@ -17,6 +17,7 @@ use Resolver;
use {names_to_string, module_to_string};
use {resolve_error, ResolutionError};

use rustc_data_structures::ptr_key::PtrKey;
use rustc::ty;
use rustc::lint::builtin::BuiltinLintDiagnostics;
use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
Expand All @@ -33,7 +34,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::Span;

use std::cell::{Cell, RefCell};
use std::mem;
use std::{mem, ptr};

/// Contains data for specific types of import directives.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -105,8 +106,8 @@ impl<'a> ImportDirective<'a> {
/// Records information about the resolution of a name in a namespace of a module.
pub struct NameResolution<'a> {
/// Single imports that may define the name in the namespace.
/// Import directives are arena-allocated, so it's ok to use pointers as keys, they are stable.
single_imports: FxHashSet<*const ImportDirective<'a>>,
/// Import directives are arena-allocated, so it's ok to use pointers as keys.
single_imports: FxHashSet<PtrKey<'a, ImportDirective<'a>>>,
/// The least shadowable known binding for this name, or None if there are no known bindings.
pub binding: Option<&'a NameBinding<'a>>,
shadowed_glob: Option<&'a NameBinding<'a>>,
Expand Down Expand Up @@ -192,7 +193,6 @@ impl<'a> Resolver<'a> {
// Check if one of single imports can still define the name,
// if it can then our result is not determined and can be invalidated.
for single_import in &resolution.single_imports {
let single_import = unsafe { &**single_import };
if !self.is_accessible(single_import.vis.get()) {
continue;
}
Expand Down Expand Up @@ -291,7 +291,7 @@ impl<'a> Resolver<'a> {
SingleImport { target, type_ns_only, .. } => {
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
resolution.single_imports.insert(directive);
resolution.single_imports.insert(PtrKey(directive));
});
}
// We don't add prelude imports to the globs since they only affect lexical scopes,
Expand Down Expand Up @@ -398,7 +398,7 @@ impl<'a> Resolver<'a> {
_ if old_binding.is_some() => return t,
None => return t,
Some(binding) => match old_binding {
Some(old_binding) if old_binding as *const _ == binding as *const _ => return t,
Some(old_binding) if ptr::eq(old_binding, binding) => return t,
_ => (binding, t),
}
}
Expand Down Expand Up @@ -583,7 +583,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
Err(Undetermined) => indeterminate = true,
Err(Determined) => {
this.update_resolution(parent, target, ns, |_, resolution| {
resolution.single_imports.remove(&(directive as *const _));
resolution.single_imports.remove(&PtrKey(directive));
});
}
Ok(binding) if !binding.is_importable() => {
Expand Down Expand Up @@ -916,7 +916,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {

let mut reexports = Vec::new();
let mut exported_macro_names = FxHashMap();
if module as *const _ == self.graph_root as *const _ {
if ptr::eq(module, self.graph_root) {
let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
for export in macro_exports.into_iter().rev() {
if let Some(later_span) = exported_macro_names.insert(export.ident.modern(),
Expand Down

0 comments on commit 2eb83ee

Please sign in to comment.