Skip to content

Commit dc75933

Browse files
authored
Auto merge of #36491 - Manishearth:rollup, r=Manishearth
Rollup of 9 pull requests - Successful merges: #36384, #36405, #36425, #36429, #36438, #36454, #36459, #36461, #36463 - Failed merges: #36444
2 parents e2c64d1 + ec08128 commit dc75933

Some content is hidden

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

62 files changed

+1399
-977
lines changed

Diff for: src/libcore/clone.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,23 @@ pub trait Clone : Sized {
113113
}
114114
}
115115

116-
// FIXME(aburka): this method is used solely by #[derive] to
117-
// assert that every component of a type implements Clone.
116+
// FIXME(aburka): these structs are used solely by #[derive] to
117+
// assert that every component of a type implements Clone or Copy.
118118
//
119-
// This should never be called by user code.
119+
// These structs should never appear in user code.
120+
#[doc(hidden)]
121+
#[allow(missing_debug_implementations)]
122+
#[unstable(feature = "derive_clone_copy",
123+
reason = "deriving hack, should not be public",
124+
issue = "0")]
125+
pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData<T> }
126+
#[doc(hidden)]
127+
#[allow(missing_debug_implementations)]
128+
#[unstable(feature = "derive_clone_copy",
129+
reason = "deriving hack, should not be public",
130+
issue = "0")]
131+
pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }
132+
#[cfg(stage0)]
120133
#[doc(hidden)]
121134
#[inline(always)]
122135
#[unstable(feature = "derive_clone_copy",

Diff for: src/libcore/cmp.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
129129
/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has
130130
/// no extra methods, it is only informing the compiler that this is an
131131
/// equivalence relation rather than a partial equivalence relation. Note that
132-
/// the `derive` strategy requires all fields are `PartialEq`, which isn't
132+
/// the `derive` strategy requires all fields are `Eq`, which isn't
133133
/// always desired.
134134
///
135135
/// ## How can I implement `Eq`?
@@ -165,6 +165,17 @@ pub trait Eq: PartialEq<Self> {
165165
fn assert_receiver_is_total_eq(&self) {}
166166
}
167167

168+
// FIXME: this struct is used solely by #[derive] to
169+
// assert that every component of a type implements Eq.
170+
//
171+
// This struct should never appear in user code.
172+
#[doc(hidden)]
173+
#[allow(missing_debug_implementations)]
174+
#[unstable(feature = "derive_eq",
175+
reason = "deriving hack, should not be public",
176+
issue = "0")]
177+
pub struct AssertParamIsEq<T: Eq + ?Sized> { _field: ::marker::PhantomData<T> }
178+
168179
/// An `Ordering` is the result of a comparison between two values.
169180
///
170181
/// # Examples

Diff for: src/libcore/slice.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -520,8 +520,8 @@ impl<T> ops::Index<usize> for [T] {
520520
type Output = T;
521521

522522
fn index(&self, index: usize) -> &T {
523-
assert!(index < self.len());
524-
unsafe { self.get_unchecked(index) }
523+
// NB built-in indexing
524+
&(*self)[index]
525525
}
526526
}
527527

@@ -530,8 +530,8 @@ impl<T> ops::Index<usize> for [T] {
530530
impl<T> ops::IndexMut<usize> for [T] {
531531
#[inline]
532532
fn index_mut(&mut self, index: usize) -> &mut T {
533-
assert!(index < self.len());
534-
unsafe { self.get_unchecked_mut(index) }
533+
// NB built-in indexing
534+
&mut (*self)[index]
535535
}
536536
}
537537

Diff for: src/librustc/infer/mod.rs

+27
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,33 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
830830
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
831831
}
832832

833+
// Clear the "obligations in snapshot" flag, invoke the closure,
834+
// then restore the flag to its original value. This flag is a
835+
// debugging measure designed to detect cases where we start a
836+
// snapshot, create type variables, register obligations involving
837+
// those type variables in the fulfillment cx, and then have to
838+
// unroll the snapshot, leaving "dangling type variables" behind.
839+
// In such cases, the flag will be set by the fulfillment cx, and
840+
// an assertion will fail when rolling the snapshot back. Very
841+
// useful, much better than grovelling through megabytes of
842+
// RUST_LOG output.
843+
//
844+
// HOWEVER, in some cases the flag is wrong. In particular, we
845+
// sometimes create a "mini-fulfilment-cx" in which we enroll
846+
// obligations. As long as this fulfillment cx is fully drained
847+
// before we return, this is not a problem, as there won't be any
848+
// escaping obligations in the main cx. In those cases, you can
849+
// use this function.
850+
pub fn save_and_restore_obligations_in_snapshot_flag<F, R>(&self, func: F) -> R
851+
where F: FnOnce(&Self) -> R
852+
{
853+
let flag = self.obligations_in_snapshot.get();
854+
self.obligations_in_snapshot.set(false);
855+
let result = func(self);
856+
self.obligations_in_snapshot.set(flag);
857+
result
858+
}
859+
833860
fn start_snapshot(&self) -> CombinedSnapshot {
834861
debug!("start_snapshot()");
835862

Diff for: src/librustc/middle/cstore.rs

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use std::rc::Rc;
3939
use std::path::PathBuf;
4040
use syntax::ast;
4141
use syntax::attr;
42+
use syntax::ext::base::LoadedMacro;
4243
use syntax::ptr::P;
4344
use syntax::parse::token::InternedString;
4445
use syntax_pos::Span;
@@ -492,6 +493,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
492493
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
493494
}
494495

496+
pub trait MacroLoader {
497+
fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro>;
498+
}
495499

496500
/// Metadata encoding and decoding can make use of thread-local encoding and
497501
/// decoding contexts. These allow implementers of serialize::Encodable and

Diff for: src/librustc/session/mod.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use util::nodemap::{NodeMap, FnvHashMap};
2121
use util::common::duration_to_secs_str;
2222
use mir::transform as mir_pass;
2323

24-
use syntax::ast::{NodeId, Name};
24+
use syntax::ast::NodeId;
2525
use errors::{self, DiagnosticBuilder};
2626
use errors::emitter::{Emitter, EmitterWriter};
2727
use syntax::json::JsonEmitter;
@@ -39,7 +39,7 @@ use llvm;
3939

4040
use std::path::{Path, PathBuf};
4141
use std::cell::{self, Cell, RefCell};
42-
use std::collections::{HashMap, HashSet};
42+
use std::collections::HashMap;
4343
use std::env;
4444
use std::ffi::CString;
4545
use std::rc::Rc;
@@ -96,10 +96,6 @@ pub struct Session {
9696
pub injected_allocator: Cell<Option<ast::CrateNum>>,
9797
pub injected_panic_runtime: Cell<Option<ast::CrateNum>>,
9898

99-
/// Names of all bang-style macros and syntax extensions
100-
/// available in this crate
101-
pub available_macros: RefCell<HashSet<Name>>,
102-
10399
/// Map from imported macro spans (which consist of
104100
/// the localized span for the macro body) to the
105101
/// macro name and defintion span in the source crate.
@@ -552,7 +548,6 @@ pub fn build_session_(sopts: config::Options,
552548
next_node_id: Cell::new(1),
553549
injected_allocator: Cell::new(None),
554550
injected_panic_runtime: Cell::new(None),
555-
available_macros: RefCell::new(HashSet::new()),
556551
imported_macro_spans: RefCell::new(HashMap::new()),
557552
incr_comp_session: RefCell::new(IncrCompSession::NotInitialized),
558553
perf_stats: PerfStats {

Diff for: src/librustc/traits/specialize/mod.rs

+24-22
Original file line numberDiff line numberDiff line change
@@ -203,32 +203,34 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
203203
// attempt to prove all of the predicates for impl2 given those for impl1
204204
// (which are packed up in penv)
205205

206-
let mut fulfill_cx = FulfillmentContext::new();
207-
for oblig in obligations.into_iter() {
208-
fulfill_cx.register_predicate_obligation(&infcx, oblig);
209-
}
210-
match fulfill_cx.select_all_or_error(infcx) {
211-
Err(errors) => {
212-
// no dice!
213-
debug!("fulfill_implication: for impls on {:?} and {:?}, could not fulfill: {:?} given \
214-
{:?}",
215-
source_trait_ref,
216-
target_trait_ref,
217-
errors,
218-
infcx.parameter_environment.caller_bounds);
219-
Err(())
206+
infcx.save_and_restore_obligations_in_snapshot_flag(|infcx| {
207+
let mut fulfill_cx = FulfillmentContext::new();
208+
for oblig in obligations.into_iter() {
209+
fulfill_cx.register_predicate_obligation(&infcx, oblig);
220210
}
211+
match fulfill_cx.select_all_or_error(infcx) {
212+
Err(errors) => {
213+
// no dice!
214+
debug!("fulfill_implication: for impls on {:?} and {:?}, \
215+
could not fulfill: {:?} given {:?}",
216+
source_trait_ref,
217+
target_trait_ref,
218+
errors,
219+
infcx.parameter_environment.caller_bounds);
220+
Err(())
221+
}
221222

222-
Ok(()) => {
223-
debug!("fulfill_implication: an impl for {:?} specializes {:?}",
224-
source_trait_ref,
225-
target_trait_ref);
223+
Ok(()) => {
224+
debug!("fulfill_implication: an impl for {:?} specializes {:?}",
225+
source_trait_ref,
226+
target_trait_ref);
226227

227-
// Now resolve the *substitution* we built for the target earlier, replacing
228-
// the inference variables inside with whatever we got from fulfillment.
229-
Ok(infcx.resolve_type_vars_if_possible(&target_substs))
228+
// Now resolve the *substitution* we built for the target earlier, replacing
229+
// the inference variables inside with whatever we got from fulfillment.
230+
Ok(infcx.resolve_type_vars_if_possible(&target_substs))
231+
}
230232
}
231-
}
233+
})
232234
}
233235

234236
pub struct SpecializesCache {

Diff for: src/librustc/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1303,7 +1303,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
13031303
}
13041304

13051305
pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> {
1306-
obj.projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
1306+
obj.projection_bounds.sort_by_key(|b| b.sort_key(self));
13071307
self.mk_ty(TyTrait(box obj))
13081308
}
13091309

Diff for: src/librustc/ty/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -1018,10 +1018,6 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
10181018
pub fn item_name(&self) -> Name {
10191019
self.0.projection_ty.item_name // safe to skip the binder to access a name
10201020
}
1021-
1022-
pub fn sort_key(&self) -> (DefId, Name) {
1023-
self.0.projection_ty.sort_key()
1024-
}
10251021
}
10261022

10271023
pub trait ToPolyTraitRef<'tcx> {

Diff for: src/librustc/ty/sty.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::mem;
2323
use std::ops;
2424
use syntax::abi;
2525
use syntax::ast::{self, Name};
26-
use syntax::parse::token::keywords;
26+
use syntax::parse::token::{keywords, InternedString};
2727

2828
use serialize::{Decodable, Decoder, Encodable, Encoder};
2929

@@ -440,12 +440,6 @@ pub struct ProjectionTy<'tcx> {
440440
pub item_name: Name,
441441
}
442442

443-
impl<'tcx> ProjectionTy<'tcx> {
444-
pub fn sort_key(&self) -> (DefId, Name) {
445-
(self.trait_ref.def_id, self.item_name)
446-
}
447-
}
448-
449443
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
450444
pub struct BareFnTy<'tcx> {
451445
pub unsafety: hir::Unsafety,
@@ -738,8 +732,17 @@ impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
738732
self.0.item_name // safe to skip the binder to access a name
739733
}
740734

741-
pub fn sort_key(&self) -> (DefId, Name) {
742-
(self.0.trait_ref.def_id, self.0.item_name)
735+
pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) {
736+
// We want something here that is stable across crate boundaries.
737+
// The DefId isn't but the `deterministic_hash` of the corresponding
738+
// DefPath is.
739+
let trait_def = tcx.lookup_trait_def(self.0.trait_ref.def_id);
740+
let def_path_hash = trait_def.def_path_hash;
741+
742+
// An `ast::Name` is also not stable (it's just an index into an
743+
// interning table), so map to the corresponding `InternedString`.
744+
let item_name = self.0.item_name.as_str();
745+
(def_path_hash, item_name)
743746
}
744747

745748
pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,

Diff for: src/librustc/ty/trait_def.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,20 @@ pub struct TraitDef<'tcx> {
7070
pub specialization_graph: RefCell<traits::specialization_graph::Graph>,
7171

7272
/// Various flags
73-
pub flags: Cell<TraitFlags>
73+
pub flags: Cell<TraitFlags>,
74+
75+
/// The ICH of this trait's DefPath, cached here so it doesn't have to be
76+
/// recomputed all the time.
77+
pub def_path_hash: u64,
7478
}
7579

7680
impl<'a, 'gcx, 'tcx> TraitDef<'tcx> {
7781
pub fn new(unsafety: hir::Unsafety,
7882
paren_sugar: bool,
7983
generics: &'tcx ty::Generics<'tcx>,
8084
trait_ref: ty::TraitRef<'tcx>,
81-
associated_type_names: Vec<Name>)
85+
associated_type_names: Vec<Name>,
86+
def_path_hash: u64)
8287
-> TraitDef<'tcx> {
8388
TraitDef {
8489
paren_sugar: paren_sugar,
@@ -90,6 +95,7 @@ impl<'a, 'gcx, 'tcx> TraitDef<'tcx> {
9095
blanket_impls: RefCell::new(vec![]),
9196
flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS),
9297
specialization_graph: RefCell::new(traits::specialization_graph::Graph::new()),
98+
def_path_hash: def_path_hash,
9399
}
94100
}
95101

Diff for: src/librustc/ty/util.rs

+5-34
Original file line numberDiff line numberDiff line change
@@ -411,15 +411,11 @@ impl<'a, 'gcx, 'tcx> TypeIdHasher<'a, 'gcx, 'tcx> {
411411
}
412412

413413
fn def_id(&mut self, did: DefId) {
414-
// Hash the crate identification information.
415-
let name = self.tcx.crate_name(did.krate);
416-
let disambiguator = self.tcx.crate_disambiguator(did.krate);
417-
self.hash((name, disambiguator));
418-
419-
// Hash the item path within that crate.
420-
// FIXME(#35379) This should use a deterministic
421-
// DefPath hashing mechanism, not the DefIndex.
422-
self.hash(did.index);
414+
// Hash the DefPath corresponding to the DefId, which is independent
415+
// of compiler internal state.
416+
let tcx = self.tcx;
417+
let def_path = tcx.def_path(did);
418+
def_path.deterministic_hash_to(tcx, &mut self.state);
423419
}
424420
}
425421

@@ -445,33 +441,8 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> {
445441
self.hash(f.sig.variadic());
446442
}
447443
TyTrait(ref data) => {
448-
// Trait objects have a list of projection bounds
449-
// that are not guaranteed to be sorted in an order
450-
// that gets preserved across crates, so we need
451-
// to sort them again by the name, in string form.
452-
453-
// Hash the whole principal trait ref.
454444
self.def_id(data.principal.def_id());
455-
data.principal.visit_with(self);
456-
457-
// Hash region and builtin bounds.
458-
data.region_bound.visit_with(self);
459445
self.hash(data.builtin_bounds);
460-
461-
// Only projection bounds are left, sort and hash them.
462-
let mut projection_bounds: Vec<_> = data.projection_bounds
463-
.iter()
464-
.map(|b| (b.item_name().as_str(), b))
465-
.collect();
466-
projection_bounds.sort_by_key(|&(ref name, _)| name.clone());
467-
for (name, bound) in projection_bounds {
468-
self.def_id(bound.0.trait_ref.def_id);
469-
self.hash(name);
470-
bound.visit_with(self);
471-
}
472-
473-
// Bypass super_visit_with, we've visited everything.
474-
return false;
475446
}
476447
TyTuple(tys) => {
477448
self.hash(tys.len());

0 commit comments

Comments
 (0)