diff --git a/COPYRIGHT b/COPYRIGHT index abe8998030871..19559fa2950ea 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -197,28 +197,6 @@ their own copyright notices and license terms: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* Hoedown, the markdown parser, under src/rt/hoedown, is - licensed as follows. - - Copyright (c) 2008, Natacha Porté - Copyright (c) 2011, Vicent Martí - Copyright (c) 2013, Devin Torres and the Hoedown authors - - Permission to use, copy, modify, and distribute this - software for any purpose with or without fee is hereby - granted, provided that the above copyright notice and - this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR - DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE - INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR - ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA - OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * libbacktrace, under src/libbacktrace: Copyright (C) 2012-2014 Free Software Foundation, Inc. diff --git a/cargo b/cargo index 4729175045b41..c416fb60b11ec 160000 --- a/cargo +++ b/cargo @@ -1 +1 @@ -Subproject commit 4729175045b41b688ab903120860866ce7a22ba9 +Subproject commit c416fb60b11ecfd2a1ba0fb8567c9a92590b5d28 diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index d04f414250ade..e3808248e22fe 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -325,8 +325,10 @@ impl str { /// Returns a subslice of `str`. /// - /// This is the non-panicking alternative to indexing the `str`. Returns `None` whenever - /// equivalent indexing operation would panic. + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// [`None`]: option/enum.Option.html#variant.None /// /// # Examples /// @@ -346,8 +348,10 @@ impl str { /// Returns a mutable subslice of `str`. /// - /// This is the non-panicking alternative to indexing the `str`. Returns `None` whenever - /// equivalent indexing operation would panic. + /// This is the non-panicking alternative to indexing the `str`. Returns + /// [`None`] whenever equivalent indexing operation would panic. + /// + /// [`None`]: option/enum.Option.html#variant.None /// /// # Examples /// @@ -570,7 +574,7 @@ impl str { core_str::StrExt::split_at_mut(self, mid) } - /// Returns an iterator over the `char`s of a string slice. + /// Returns an iterator over the [`char`]s of a string slice. /// /// As a string slice consists of valid UTF-8, we can iterate through a /// string slice by [`char`]. This method returns such an iterator. @@ -1657,13 +1661,13 @@ impl str { /// Parses this string slice into another type. /// - /// Because `parse()` is so general, it can cause problems with type - /// inference. As such, `parse()` is one of the few times you'll see + /// Because `parse` is so general, it can cause problems with type + /// inference. As such, `parse` is one of the few times you'll see /// the syntax affectionately known as the 'turbofish': `::<>`. This /// helps the inference algorithm understand specifically which type /// you're trying to parse into. /// - /// `parse()` can parse any type that implements the [`FromStr`] trait. + /// `parse` can parse any type that implements the [`FromStr`] trait. /// /// [`FromStr`]: str/trait.FromStr.html /// @@ -1746,7 +1750,7 @@ impl str { /// /// `replacen` creates a new [`String`], and copies the data from this string slice into it. /// While doing so, it attempts to find matches of a pattern. If it finds any, it - /// replaces them with the replacement string slice at most `N` times. + /// replaces them with the replacement string slice at most `count` times. /// /// [`String`]: string/struct.String.html /// @@ -1892,7 +1896,9 @@ impl str { return s; } - /// Escapes each char in `s` with `char::escape_debug`. + /// Escapes each char in `s` with [`char::escape_debug`]. + /// + /// [`char::escape_debug`]: primitive.char.html#method.escape_debug #[unstable(feature = "str_escape", reason = "return type may change to be an iterator", issue = "27791")] @@ -1900,7 +1906,9 @@ impl str { self.chars().flat_map(|c| c.escape_debug()).collect() } - /// Escapes each char in `s` with `char::escape_default`. + /// Escapes each char in `s` with [`char::escape_default`]. + /// + /// [`char::escape_default`]: primitive.char.html#method.escape_default #[unstable(feature = "str_escape", reason = "return type may change to be an iterator", issue = "27791")] @@ -1908,7 +1916,9 @@ impl str { self.chars().flat_map(|c| c.escape_default()).collect() } - /// Escapes each char in `s` with `char::escape_unicode`. + /// Escapes each char in `s` with [`char::escape_unicode`]. + /// + /// [`char::escape_unicode`]: primitive.char.html#method.escape_unicode #[unstable(feature = "str_escape", reason = "return type may change to be an iterator", issue = "27791")] @@ -1916,9 +1926,10 @@ impl str { self.chars().flat_map(|c| c.escape_unicode()).collect() } - /// Converts a `Box` into a [`String`] without copying or allocating. + /// Converts a [`Box`] into a [`String`] without copying or allocating. /// /// [`String`]: string/struct.String.html + /// [`Box`]: boxed/struct.Box.html /// /// # Examples /// diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 5aea2bcaa4f5c..59d04ea8c771c 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -57,17 +57,13 @@ pub enum DepNode { // Represents different phases in the compiler. CollectLanguageItems, - CheckStaticRecursion, ResolveLifetimes, RegionResolveCrate, - CheckLoops, PluginRegistrar, StabilityIndex, CollectItem(D), CollectItemSig(D), Coherence, - EffectCheck, - Liveness, Resolve, EntryPoint, CheckEntryFn, @@ -216,15 +212,11 @@ impl DepNode { MirKrate => Some(MirKrate), TypeckBodiesKrate => Some(TypeckBodiesKrate), CollectLanguageItems => Some(CollectLanguageItems), - CheckStaticRecursion => Some(CheckStaticRecursion), ResolveLifetimes => Some(ResolveLifetimes), RegionResolveCrate => Some(RegionResolveCrate), - CheckLoops => Some(CheckLoops), PluginRegistrar => Some(PluginRegistrar), StabilityIndex => Some(StabilityIndex), Coherence => Some(Coherence), - EffectCheck => Some(EffectCheck), - Liveness => Some(Liveness), Resolve => Some(Resolve), EntryPoint => Some(EntryPoint), CheckEntryFn => Some(CheckEntryFn), diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index d7aa36b24f942..cfafec00ae20d 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -442,6 +442,27 @@ impl<'hir> Map<'hir> { self.local_def_id(self.body_owner(id)) } + /// Given a body owner's id, returns the `BodyId` associated with it. + pub fn body_owned_by(&self, id: NodeId) -> BodyId { + if let Some(entry) = self.find_entry(id) { + if let Some(body_id) = entry.associated_body() { + // For item-like things and closures, the associated + // body has its own distinct id, and that is returned + // by `associated_body`. + body_id + } else { + // For some expressions, the expression is its own body. + if let EntryExpr(_, expr) = entry { + BodyId { node_id: expr.id } + } else { + span_bug!(self.span(id), "id `{}` has no associated body", id); + } + } + } else { + bug!("no entry for id `{}`", id) + } + } + pub fn ty_param_owner(&self, id: NodeId) -> NodeId { match self.get(id) { NodeItem(&Item { node: ItemTrait(..), .. }) => id, diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 5ef30550f1155..3a6367c353c1e 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -13,8 +13,10 @@ use hir::def_id::DefId; use ich::{self, CachingCodemapView}; use session::config::DebugInfoLevel::NoDebugInfo; use ty; +use util::nodemap::NodeMap; use std::hash as std_hash; +use std::collections::{HashMap, HashSet}; use syntax::ast; use syntax::attr; @@ -296,3 +298,53 @@ impl<'a, 'tcx> HashStable> for Span { } } } + +pub fn hash_stable_hashmap<'a, 'tcx, K, V, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher, + map: &HashMap, + extract_stable_key: F) + where K: Eq + std_hash::Hash, + V: HashStable>, + R: std_hash::BuildHasher, + SK: HashStable> + Ord + Clone, + F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK, + W: StableHasherResult, +{ + let mut keys: Vec<_> = map.keys() + .map(|k| (extract_stable_key(hcx, k), k)) + .collect(); + keys.sort_unstable_by_key(|&(ref stable_key, _)| stable_key.clone()); + keys.len().hash_stable(hcx, hasher); + for (stable_key, key) in keys { + stable_key.hash_stable(hcx, hasher); + map[key].hash_stable(hcx, hasher); + } +} + +pub fn hash_stable_hashset<'a, 'tcx, K, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher, + set: &HashSet, + extract_stable_key: F) + where K: Eq + std_hash::Hash, + R: std_hash::BuildHasher, + SK: HashStable> + Ord + Clone, + F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK, + W: StableHasherResult, +{ + let mut keys: Vec<_> = set.iter() + .map(|k| extract_stable_key(hcx, k)) + .collect(); + keys.sort_unstable(); + keys.hash_stable(hcx, hasher); +} + +pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher, + map: &NodeMap) + where V: HashStable>, + W: StableHasherResult, +{ + hash_stable_hashmap(hcx, hasher, map, |hcx, node_id| { + hcx.tcx.hir.definitions().node_to_hir_id(*node_id).local_id + }); +} diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 401f7e1921ab4..3ff8ffb35054a 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -22,7 +22,8 @@ impl_stable_hash_for!(struct mir::SourceInfo { span, scope }); impl_stable_hash_for!(enum mir::Mutability { Mut, Not }); impl_stable_hash_for!(enum mir::BorrowKind { Shared, Unique, Mut }); impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer }); -impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, ty, name, source_info }); +impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { mutability, ty, name, source_info, +is_user_variable}); impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref }); impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup }); impl_stable_hash_for!(struct mir::Terminator<'tcx> { source_info, kind }); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 7b6f3af2a11ec..46d1e7ef0c7c4 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -11,31 +11,22 @@ //! This module contains `HashStable` implementations for various data types //! from rustc::ty in no particular order. -use ich::StableHashingContext; +use ich::{self, StableHashingContext, NodeIdHashingMode}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use std::hash as std_hash; use std::mem; +use syntax_pos::symbol::InternedString; use ty; - -impl<'a, 'tcx> HashStable> for ty::Ty<'tcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'tcx>, - hasher: &mut StableHasher) { - let type_hash = hcx.tcx().type_id_hash(*self); - type_hash.hash_stable(hcx, hasher); - } -} - impl_stable_hash_for!(struct ty::ItemSubsts<'tcx> { substs }); -impl<'a, 'tcx, T> HashStable> for ty::Slice +impl<'a, 'tcx, T> HashStable> for &'tcx ty::Slice where T: HashStable> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'tcx>, hasher: &mut StableHasher) { - (&**self).hash_stable(hcx, hasher); + (&self[..]).hash_stable(hcx, hasher); } } @@ -67,9 +58,13 @@ impl<'a, 'tcx> HashStable> for ty::Region { index.hash_stable(hcx, hasher); name.hash_stable(hcx, hasher); } + ty::ReScope(code_extent) => { + code_extent.hash_stable(hcx, hasher); + } + ty::ReFree(ref free_region) => { + free_region.hash_stable(hcx, hasher); + } ty::ReLateBound(..) | - ty::ReFree(..) | - ty::ReScope(..) | ty::ReVar(..) | ty::ReSkolemized(..) => { bug!("TypeIdHasher: unexpected region {:?}", *self) @@ -127,7 +122,6 @@ impl_stable_hash_for!(enum ty::BorrowKind { MutBorrow }); - impl<'a, 'tcx> HashStable> for ty::UpvarCapture<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a, 'tcx>, @@ -223,7 +217,6 @@ impl<'a, 'tcx> HashStable> for ty::Predicate<'tcx } } - impl<'a, 'tcx> HashStable> for ty::AdtFlags { fn hash_stable(&self, _: &mut StableHashingContext<'a, 'tcx>, @@ -280,9 +273,14 @@ for ::middle::const_val::ConstVal<'tcx> { def_id.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); } - ConstVal::Struct(ref _name_value_map) => { - // BTreeMap>), - panic!("Ordering still unstable") + ConstVal::Struct(ref name_value_map) => { + let mut values: Vec<(InternedString, &ConstVal)> = + name_value_map.iter() + .map(|(name, val)| (name.as_str(), val)) + .collect(); + + values.sort_unstable_by_key(|&(ref name, _)| name.clone()); + values.hash_stable(hcx, hasher); } ConstVal::Tuple(ref value) => { value.hash_stable(hcx, hasher); @@ -303,7 +301,6 @@ for ::middle::const_val::ConstVal<'tcx> { impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs }); - impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> { parent, predicates @@ -413,3 +410,265 @@ impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData { impl_stable_hash_for!(struct ty::DebruijnIndex { depth }); + +impl_stable_hash_for!(enum ty::cast::CastKind { + CoercionCast, + PtrPtrCast, + PtrAddrCast, + AddrPtrCast, + NumericCast, + EnumCast, + PrimIntCast, + U8CharCast, + ArrayPtrCast, + FnPtrPtrCast, + FnPtrAddrCast +}); + +impl<'a, 'tcx> HashStable> for ::middle::region::CodeExtent +{ + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + hcx.tcx().region_maps.code_extent_data(*self).hash_stable(hcx, hasher); + }); + } +} + +impl<'a, 'tcx> HashStable> for ::middle::region::CodeExtentData +{ + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + use middle::region::CodeExtentData; + + mem::discriminant(self).hash_stable(hcx, hasher); + match *self { + CodeExtentData::Misc(node_id) | + CodeExtentData::DestructionScope(node_id) => { + node_id.hash_stable(hcx, hasher); + } + CodeExtentData::CallSiteScope { fn_id, body_id } | + CodeExtentData::ParameterScope { fn_id, body_id } => { + fn_id.hash_stable(hcx, hasher); + body_id.hash_stable(hcx, hasher); + } + CodeExtentData::Remainder(block_remainder) => { + block_remainder.hash_stable(hcx, hasher); + } + } + } +} + +impl_stable_hash_for!(struct ::middle::region::BlockRemainder { + block, + first_statement_index +}); + +impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo { + custom_kind +}); + +impl_stable_hash_for!(struct ty::FreeRegion { + scope, + bound_region +}); + +impl_stable_hash_for!(enum ty::BoundRegion { + BrAnon(index), + BrNamed(def_id, name), + BrFresh(index), + BrEnv +}); + +impl<'a, 'tcx> HashStable> for ty::TypeVariants<'tcx> +{ + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + use ty::TypeVariants::*; + + mem::discriminant(self).hash_stable(hcx, hasher); + match *self { + TyBool | + TyChar | + TyStr | + TyNever => { + // Nothing more to hash. + } + TyInt(int_ty) => { + int_ty.hash_stable(hcx, hasher); + } + TyUint(uint_ty) => { + uint_ty.hash_stable(hcx, hasher); + } + TyFloat(float_ty) => { + float_ty.hash_stable(hcx, hasher); + } + TyAdt(adt_def, substs) => { + adt_def.hash_stable(hcx, hasher); + substs.hash_stable(hcx, hasher); + } + TyArray(inner_ty, len) => { + inner_ty.hash_stable(hcx, hasher); + len.hash_stable(hcx, hasher); + } + TySlice(inner_ty) => { + inner_ty.hash_stable(hcx, hasher); + } + TyRawPtr(pointee_ty) => { + pointee_ty.hash_stable(hcx, hasher); + } + TyRef(region, pointee_ty) => { + region.hash_stable(hcx, hasher); + pointee_ty.hash_stable(hcx, hasher); + } + TyFnDef(def_id, substs, ref sig) => { + def_id.hash_stable(hcx, hasher); + substs.hash_stable(hcx, hasher); + sig.hash_stable(hcx, hasher); + } + TyFnPtr(ref sig) => { + sig.hash_stable(hcx, hasher); + } + TyDynamic(ref existential_predicates, region) => { + existential_predicates.hash_stable(hcx, hasher); + region.hash_stable(hcx, hasher); + } + TyClosure(def_id, closure_substs) => { + def_id.hash_stable(hcx, hasher); + closure_substs.hash_stable(hcx, hasher); + } + TyTuple(inner_tys, from_diverging_type_var) => { + inner_tys.hash_stable(hcx, hasher); + from_diverging_type_var.hash_stable(hcx, hasher); + } + TyProjection(ref projection_ty) => { + projection_ty.hash_stable(hcx, hasher); + } + TyAnon(def_id, substs) => { + def_id.hash_stable(hcx, hasher); + substs.hash_stable(hcx, hasher); + } + TyParam(param_ty) => { + param_ty.hash_stable(hcx, hasher); + } + + TyError | + TyInfer(..) => { + bug!("ty::TypeVariants::hash_stable() - Unexpected variant.") + } + } + } +} + +impl_stable_hash_for!(struct ty::ParamTy { + idx, + name +}); + +impl_stable_hash_for!(struct ty::TypeAndMut<'tcx> { + ty, + mutbl +}); + +impl<'a, 'tcx> HashStable> for ty::ExistentialPredicate<'tcx> +{ + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + mem::discriminant(self).hash_stable(hcx, hasher); + match *self { + ty::ExistentialPredicate::Trait(ref trait_ref) => { + trait_ref.hash_stable(hcx, hasher); + } + ty::ExistentialPredicate::Projection(ref projection) => { + projection.hash_stable(hcx, hasher); + } + ty::ExistentialPredicate::AutoTrait(def_id) => { + def_id.hash_stable(hcx, hasher); + } + } + } +} + +impl_stable_hash_for!(struct ty::ExistentialTraitRef<'tcx> { + def_id, + substs +}); + +impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> { + trait_ref, + item_name, + ty +}); + + +impl<'a, 'tcx> HashStable> for ty::TypeckTables<'tcx> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + let ty::TypeckTables { + ref type_relative_path_defs, + ref node_types, + ref item_substs, + ref adjustments, + ref method_map, + ref upvar_capture_map, + ref closure_tys, + ref closure_kinds, + ref liberated_fn_sigs, + ref fru_field_types, + + ref cast_kinds, + + // FIXME(#41184): This is still ignored at the moment. + lints: _, + ref used_trait_imports, + tainted_by_errors, + ref free_region_map, + } = *self; + + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + ich::hash_stable_nodemap(hcx, hasher, type_relative_path_defs); + ich::hash_stable_nodemap(hcx, hasher, node_types); + ich::hash_stable_nodemap(hcx, hasher, item_substs); + ich::hash_stable_nodemap(hcx, hasher, adjustments); + + ich::hash_stable_hashmap(hcx, hasher, method_map, |hcx, method_call| { + let ty::MethodCall { + expr_id, + autoderef + } = *method_call; + + let def_id = hcx.tcx().hir.local_def_id(expr_id); + (hcx.def_path_hash(def_id), autoderef) + }); + + ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| { + let ty::UpvarId { + var_id, + closure_expr_id + } = *up_var_id; + + let var_def_id = hcx.tcx().hir.local_def_id(var_id); + let closure_def_id = hcx.tcx().hir.local_def_id(closure_expr_id); + (hcx.def_path_hash(var_def_id), hcx.def_path_hash(closure_def_id)) + }); + + ich::hash_stable_nodemap(hcx, hasher, closure_tys); + ich::hash_stable_nodemap(hcx, hasher, closure_kinds); + ich::hash_stable_nodemap(hcx, hasher, liberated_fn_sigs); + ich::hash_stable_nodemap(hcx, hasher, fru_field_types); + ich::hash_stable_nodemap(hcx, hasher, cast_kinds); + + ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| { + hcx.def_path_hash(*def_id) + }); + + tainted_by_errors.hash_stable(hcx, hasher); + free_region_map.hash_stable(hcx, hasher); + }) + } +} diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index f932c90a331e1..d70ed051ac410 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -12,8 +12,8 @@ pub use self::fingerprint::Fingerprint; pub use self::caching_codemap_view::CachingCodemapView; -pub use self::hcx::{StableHashingContext, NodeIdHashingMode}; - +pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap, + hash_stable_hashset, hash_stable_nodemap}; mod fingerprint; mod caching_codemap_view; mod hcx; diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 9fa2bc8a2a7a9..dcbe50de2e9b2 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -70,7 +70,7 @@ use ty::{self, TyCtxt, TypeFoldable}; use ty::{Region, Issue32330}; use ty::error::TypeError; use syntax_pos::{Pos, Span}; -use errors::DiagnosticBuilder; +use errors::{DiagnosticBuilder, DiagnosticStyledString}; mod note; @@ -365,6 +365,262 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } + /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value` + /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and + /// populate `other_value` with `other_ty`. + /// + /// ```text + /// Foo> + /// ^^^^--------^ this is highlighted + /// | | + /// | this type argument is exactly the same as the other type, not highlighted + /// this is highlighted + /// Bar + /// -------- this type is the same as a type argument in the other type, not highlighted + /// ``` + fn highlight_outer(&self, + mut value: &mut DiagnosticStyledString, + mut other_value: &mut DiagnosticStyledString, + name: String, + sub: &ty::subst::Substs<'tcx>, + pos: usize, + other_ty: &ty::Ty<'tcx>) { + // `value` and `other_value` hold two incomplete type representation for display. + // `name` is the path of both types being compared. `sub` + value.push_highlighted(name); + let len = sub.len(); + if len > 0 { + value.push_highlighted("<"); + } + + // Output the lifetimes fot the first type + let lifetimes = sub.regions().map(|lifetime| { + let s = format!("{}", lifetime); + if s.is_empty() { + "'_".to_string() + } else { + s + } + }).collect::>().join(", "); + if !lifetimes.is_empty() { + if sub.regions().count() < len { + value.push_normal(lifetimes + &", "); + } else { + value.push_normal(lifetimes); + } + } + + // Highlight all the type arguments that aren't at `pos` and compare the type argument at + // `pos` and `other_ty`. + for (i, type_arg) in sub.types().enumerate() { + if i == pos { + let values = self.cmp(type_arg, other_ty); + value.0.extend((values.0).0); + other_value.0.extend((values.1).0); + } else { + value.push_highlighted(format!("{}", type_arg)); + } + + if len > 0 && i != len - 1 { + value.push_normal(", "); + } + //self.push_comma(&mut value, &mut other_value, len, i); + } + if len > 0 { + value.push_highlighted(">"); + } + } + + /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`, + /// as that is the difference to the other type. + /// + /// For the following code: + /// + /// ```norun + /// let x: Foo> = foo::>(); + /// ``` + /// + /// The type error output will behave in the following way: + /// + /// ```text + /// Foo> + /// ^^^^--------^ this is highlighted + /// | | + /// | this type argument is exactly the same as the other type, not highlighted + /// this is highlighted + /// Bar + /// -------- this type is the same as a type argument in the other type, not highlighted + /// ``` + fn cmp_type_arg(&self, + mut t1_out: &mut DiagnosticStyledString, + mut t2_out: &mut DiagnosticStyledString, + path: String, + sub: &ty::subst::Substs<'tcx>, + other_path: String, + other_ty: &ty::Ty<'tcx>) -> Option<()> { + for (i, ta) in sub.types().enumerate() { + if &ta == other_ty { + self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty); + return Some(()); + } + if let &ty::TyAdt(def, _) = &ta.sty { + let path_ = self.tcx.item_path_str(def.did.clone()); + if path_ == other_path { + self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty); + return Some(()); + } + } + } + None + } + + /// Add a `,` to the type representation only if it is appropriate. + fn push_comma(&self, + value: &mut DiagnosticStyledString, + other_value: &mut DiagnosticStyledString, + len: usize, + pos: usize) { + if len > 0 && pos != len - 1 { + value.push_normal(", "); + other_value.push_normal(", "); + } + } + + /// Compare two given types, eliding parts that are the same between them and highlighting + /// relevant differences, and return two representation of those types for highlighted printing. + fn cmp(&self, t1: ty::Ty<'tcx>, t2: ty::Ty<'tcx>) + -> (DiagnosticStyledString, DiagnosticStyledString) + { + match (&t1.sty, &t2.sty) { + (&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => { + let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); + let path1 = self.tcx.item_path_str(def1.did.clone()); + let path2 = self.tcx.item_path_str(def2.did.clone()); + if def1.did == def2.did { + // Easy case. Replace same types with `_` to shorten the output and highlight + // the differing ones. + // let x: Foo = y::>(); + // Foo + // Foo + // --- ^ type argument elided + // | + // highlighted in output + values.0.push_normal(path1); + values.1.push_normal(path2); + + // Only draw `<...>` if there're lifetime/type arguments. + let len = sub1.len(); + if len > 0 { + values.0.push_normal("<"); + values.1.push_normal("<"); + } + + fn lifetime_display(lifetime: &Region) -> String { + let s = format!("{}", lifetime); + if s.is_empty() { + "'_".to_string() + } else { + s + } + } + // At one point we'd like to elide all lifetimes here, they are irrelevant for + // all diagnostics that use this output + // + // Foo<'x, '_, Bar> + // Foo<'y, '_, Qux> + // ^^ ^^ --- type arguments are not elided + // | | + // | elided as they were the same + // not elided, they were different, but irrelevant + let lifetimes = sub1.regions().zip(sub2.regions()); + for (i, lifetimes) in lifetimes.enumerate() { + let l1 = lifetime_display(lifetimes.0); + let l2 = lifetime_display(lifetimes.1); + if l1 == l2 { + values.0.push_normal("'_"); + values.1.push_normal("'_"); + } else { + values.0.push_highlighted(l1); + values.1.push_highlighted(l2); + } + self.push_comma(&mut values.0, &mut values.1, len, i); + } + + // We're comparing two types with the same path, so we compare the type + // arguments for both. If they are the same, do not highlight and elide from the + // output. + // Foo<_, Bar> + // Foo<_, Qux> + // ^ elided type as this type argument was the same in both sides + let type_arguments = sub1.types().zip(sub2.types()); + let regions_len = sub1.regions().collect::>().len(); + for (i, (ta1, ta2)) in type_arguments.enumerate() { + let i = i + regions_len; + if ta1 == ta2 { + values.0.push_normal("_"); + values.1.push_normal("_"); + } else { + let (x1, x2) = self.cmp(ta1, ta2); + (values.0).0.extend(x1.0); + (values.1).0.extend(x2.0); + } + self.push_comma(&mut values.0, &mut values.1, len, i); + } + + // Close the type argument bracket. + // Only draw `<...>` if there're lifetime/type arguments. + if len > 0 { + values.0.push_normal(">"); + values.1.push_normal(">"); + } + values + } else { + // Check for case: + // let x: Foo = foo::>(); + // Foo + // ------- this type argument is exactly the same as the other type + // Bar + if self.cmp_type_arg(&mut values.0, + &mut values.1, + path1.clone(), + sub1, + path2.clone(), + &t2).is_some() { + return values; + } + // Check for case: + // let x: Bar = y:>>(); + // Bar + // Foo> + // ------- this type argument is exactly the same as the other type + if self.cmp_type_arg(&mut values.1, + &mut values.0, + path2, + sub2, + path1, + &t1).is_some() { + return values; + } + + // We couldn't find anything in common, highlight everything. + // let x: Bar = y::>(); + (DiagnosticStyledString::highlighted(format!("{}", t1)), + DiagnosticStyledString::highlighted(format!("{}", t2))) + } + } + _ => { + if t1 == t2 { + // The two types are the same, elide and don't highlight. + (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_")) + } else { + // We couldn't find anything in common, highlight everything. + (DiagnosticStyledString::highlighted(format!("{}", t1)), + DiagnosticStyledString::highlighted(format!("{}", t2))) + } + } + } + } + pub fn note_type_err(&self, diag: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>, @@ -397,14 +653,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some((expected, found)) = expected_found { match (terr, is_simple_error, expected == found) { - (&TypeError::Sorts(ref values), false, true) => { + (&TypeError::Sorts(ref values), false, true) => { diag.note_expected_found_extra( - &"type", &expected, &found, + &"type", expected, found, &format!(" ({})", values.expected.sort_string(self.tcx)), &format!(" ({})", values.found.sort_string(self.tcx))); } (_, false, _) => { - diag.note_expected_found(&"type", &expected, &found); + diag.note_expected_found(&"type", expected, found); } _ => (), } @@ -472,26 +728,40 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { diag } - /// Returns a string of the form "expected `{}`, found `{}`". - fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<(String, String)> { + fn values_str(&self, values: &ValuePairs<'tcx>) + -> Option<(DiagnosticStyledString, DiagnosticStyledString)> + { match *values { - infer::Types(ref exp_found) => self.expected_found_str(exp_found), + infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found), infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found), infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found), } } + fn expected_found_str_ty(&self, + exp_found: &ty::error::ExpectedFound>) + -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { + let exp_found = self.resolve_type_vars_if_possible(exp_found); + if exp_found.references_error() { + return None; + } + + Some(self.cmp(exp_found.expected, exp_found.found)) + } + + /// Returns a string of the form "expected `{}`, found `{}`". fn expected_found_str>( &self, exp_found: &ty::error::ExpectedFound) - -> Option<(String, String)> + -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { let exp_found = self.resolve_type_vars_if_possible(exp_found); if exp_found.references_error() { return None; } - Some((format!("{}", exp_found.expected), format!("{}", exp_found.found))) + Some((DiagnosticStyledString::highlighted(format!("{}", exp_found.expected)), + DiagnosticStyledString::highlighted(format!("{}", exp_found.found)))) } fn report_generic_bound_failure(&self, diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index 8f8b2603dad84..8b753e0d22be7 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -20,6 +20,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match *origin { infer::Subtype(ref trace) => { if let Some((expected, found)) = self.values_str(&trace.values) { + let expected = expected.content(); + let found = found.content(); // FIXME: do we want a "the" here? err.span_note(trace.cause.span, &format!("...so that {} (expected {}, found {})", diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 3b002fd4dfc1a..1f96330d51da5 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -42,6 +42,7 @@ #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(discriminant_value)] +#![feature(sort_unstable)] extern crate arena; extern crate core; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 694321812836b..81cf24e58dda4 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -27,6 +27,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::map as hir_map; use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData}; use hir::svh::Svh; +use ich; use middle::lang_items; use ty::{self, TyCtxt}; use session::Session; @@ -161,6 +162,20 @@ pub struct ExternCrate { pub path_len: usize, } +pub struct EncodedMetadata { + pub raw_data: Vec, + pub hashes: Vec, +} + +/// The hash for some metadata that (when saving) will be exported +/// from this crate, or which (when importing) was exported by an +/// upstream crate. +#[derive(Debug, RustcEncodable, RustcDecodable, Copy, Clone)] +pub struct EncodedMetadataHash { + pub def_index: DefIndex, + pub hash: ich::Fingerprint, +} + /// A store of Rust crates, through with their metadata /// can be accessed. pub trait CrateStore { @@ -258,7 +273,8 @@ pub trait CrateStore { fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &LinkMeta, - reachable: &NodeSet) -> Vec; + reachable: &NodeSet) + -> EncodedMetadata; fn metadata_encoding_version(&self) -> &[u8]; } @@ -417,7 +433,10 @@ impl CrateStore for DummyCrateStore { fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &LinkMeta, - reachable: &NodeSet) -> Vec { vec![] } + reachable: &NodeSet) + -> EncodedMetadata { + bug!("encode_metadata") + } fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 5af8e7e52d888..d2b8ed8c29707 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -12,7 +12,6 @@ //! `unsafe`. use self::RootUnsafeContext::*; -use dep_graph::DepNode; use ty::{self, Ty, TyCtxt}; use ty::MethodCall; use lint; @@ -241,8 +240,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let _task = tcx.dep_graph.in_task(DepNode::EffectCheck); - let mut visitor = EffectCheckVisitor { tcx: tcx, tables: &ty::TypeckTables::empty(), diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs index cdb081ab40098..a8eb6a1074383 100644 --- a/src/librustc/middle/free_region.rs +++ b/src/librustc/middle/free_region.rs @@ -180,3 +180,7 @@ fn lub() { map.relate_free_regions(frs[1], frs[2]); assert_eq!(map.lub_free_regions(frs[0], frs[1]), ty::ReFree(frs[2])); } + +impl_stable_hash_for!(struct FreeRegionMap { + relation +}); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 7cae08efc0de0..b7da8480c1cef 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -109,7 +109,6 @@ use self::LoopKind::*; use self::LiveNodeKind::*; use self::VarKind::*; -use dep_graph::DepNode; use hir::def::*; use ty::{self, TyCtxt, ParameterEnvironment}; use traits::{self, Reveal}; @@ -196,7 +195,6 @@ impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> { } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let _task = tcx.dep_graph.in_task(DepNode::Liveness); tcx.hir.krate().visit_all_item_likes(&mut IrMaps::new(tcx).as_deep_visitor()); tcx.sess.abort_if_errors(); } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index aea4684e526ce..9ff64b295b765 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -197,10 +197,10 @@ impl<'tcx> Mir<'tcx> { pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { (self.arg_count+1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); - if self.local_decls[local].source_info.is_none() { - Some(local) - } else { + if self.local_decls[local].is_user_variable { None + } else { + Some(local) } }) } @@ -210,10 +210,10 @@ impl<'tcx> Mir<'tcx> { pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { (self.arg_count+1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); - if self.local_decls[local].source_info.is_none() { - None - } else { + if self.local_decls[local].is_user_variable { Some(local) + } else { + None } }) } @@ -370,6 +370,9 @@ pub struct LocalDecl<'tcx> { /// Temporaries and the return pointer are always mutable. pub mutability: Mutability, + /// True if this corresponds to a user-declared local variable. + pub is_user_variable: bool, + /// Type of this local. pub ty: Ty<'tcx>, @@ -379,24 +382,23 @@ pub struct LocalDecl<'tcx> { /// to generate better debuginfo. pub name: Option, - /// For user-declared variables, stores their source information. - /// - /// For temporaries, this is `None`. - /// - /// This is the primary way to differentiate between user-declared - /// variables and compiler-generated temporaries. - pub source_info: Option, + /// Source info of the local. + pub source_info: SourceInfo, } impl<'tcx> LocalDecl<'tcx> { /// Create a new `LocalDecl` for a temporary. #[inline] - pub fn new_temp(ty: Ty<'tcx>) -> Self { + pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self { LocalDecl { mutability: Mutability::Mut, ty: ty, name: None, - source_info: None, + source_info: SourceInfo { + span: span, + scope: ARGUMENT_VISIBILITY_SCOPE + }, + is_user_variable: false } } @@ -404,12 +406,16 @@ impl<'tcx> LocalDecl<'tcx> { /// /// This must be inserted into the `local_decls` list as the first local. #[inline] - pub fn new_return_pointer(return_ty: Ty) -> LocalDecl { + pub fn new_return_pointer(return_ty: Ty, span: Span) -> LocalDecl { LocalDecl { mutability: Mutability::Mut, ty: return_ty, - source_info: None, + source_info: SourceInfo { + span: span, + scope: ARGUMENT_VISIBILITY_SCOPE + }, name: None, // FIXME maybe we do want some name here? + is_user_variable: false } } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 733ad36de90e3..83963de8b0014 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -630,12 +630,11 @@ macro_rules! make_mir_visitor { ref $($mutability)* ty, name: _, ref $($mutability)* source_info, + is_user_variable: _, } = *local_decl; self.visit_ty(ty); - if let Some(ref $($mutability)* info) = *source_info { - self.visit_source_info(info); - } + self.visit_source_info(source_info); } fn super_visibility_scope(&mut self, diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 823bdc9e092ac..868ccad8a3a90 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -429,6 +429,8 @@ define_maps! { <'tcx> pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (), + pub borrowck: BorrowCheck(DefId) -> (), + /// Gets a complete map from all types to their inherent impls. /// Not meant to be used directly outside of coherence. /// (Defined only for LOCAL_CRATE) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a2c356c20db09..bbeb1f1fe5f12 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -452,6 +452,23 @@ impl<'tcx> Hash for TyS<'tcx> { } } +impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + let ty::TyS { + ref sty, + + // The other fields just provide fast access to information that is + // also contained in `sty`, so no need to hash them. + flags: _, + region_depth: _, + } = *self; + + sty.hash_stable(hcx, hasher); + } +} + pub type Ty<'tcx> = &'tcx TyS<'tcx>; impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {} @@ -2224,7 +2241,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// `DefId` is really just an interned def-path). /// /// Note that if `id` is not local to this crate, the result will - // be a non-local `DefPath`. + /// be a non-local `DefPath`. pub fn def_path(self, id: DefId) -> hir_map::DefPath { if id.is_local() { self.hir.def_path(id) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index fd8191303a9a6..c650ffe302762 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -13,7 +13,7 @@ use hir::def_id::{DefId, LOCAL_CRATE}; use hir::map::DefPathData; use infer::InferCtxt; -// use hir::map as hir_map; +use ich::{StableHashingContext, NodeIdHashingMode}; use traits::{self, Reveal}; use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable}; use ty::ParameterEnvironment; @@ -25,8 +25,8 @@ use util::nodemap::FxHashMap; use middle::lang_items; use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; -use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult}; - +use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, + HashStable}; use std::cell::RefCell; use std::cmp; use std::hash::Hash; @@ -187,6 +187,22 @@ impl<'tcx> ParameterEnvironment<'tcx> { } } +impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { + /// Creates a hash of the type `Ty` which will be the same no matter what crate + /// context it's calculated within. This is used by the `type_id` intrinsic. + pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 { + let mut hasher = StableHasher::new(); + let mut hcx = StableHashingContext::new(self); + + hcx.while_hashing_spans(false, |hcx| { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + ty.hash_stable(hcx, &mut hasher); + }); + }); + hasher.finish() + } +} + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn has_error_field(self, ty: Ty<'tcx>) -> bool { match ty.sty { @@ -339,14 +355,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .collect() } - /// Creates a hash of the type `Ty` which will be the same no matter what crate - /// context it's calculated within. This is used by the `type_id` intrinsic. - pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 { - let mut hasher = TypeIdHasher::new(self); - hasher.visit_ty(ty); - hasher.finish() - } - /// Calculate the destructor of a given type. pub fn calculate_dtor( self, diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index 713e656666271..ca313622a3afd 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -307,12 +307,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { data } - fn create_drop_flag(&mut self, index: MovePathIndex) { + fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) { let tcx = self.tcx; let patch = &mut self.patch; debug!("create_drop_flag({:?})", self.mir.span); self.drop_flags.entry(index).or_insert_with(|| { - patch.new_temp(tcx.types.bool) + patch.new_temp(tcx.types.bool, span) }); } @@ -374,7 +374,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { debug!("collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}", child, location, path, (maybe_live, maybe_dead)); if maybe_live && maybe_dead { - self.create_drop_flag(child) + self.create_drop_flag(child, terminator.source_info.span) } }); } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 0915c57b588eb..142286bd834d0 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -22,7 +22,6 @@ pub use self::mir::elaborate_drops::ElaborateDrops; use self::InteriorKind::*; -use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; use rustc::hir::map::blocks::FnLikeNode; use rustc::cfg; @@ -37,12 +36,13 @@ use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::ImmutabilityBlame; use rustc::middle::region; use rustc::ty::{self, TyCtxt}; +use rustc::ty::maps::Providers; use std::fmt; use std::rc::Rc; use std::hash::{Hash, Hasher}; use syntax::ast; -use syntax_pos::{MultiSpan, Span}; +use syntax_pos::{DUMMY_SP, MultiSpan, Span}; use errors::DiagnosticBuilder; use rustc::hir; @@ -62,16 +62,16 @@ pub struct LoanDataFlowOperator; pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>; pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - tcx.dep_graph.with_task(DepNode::BorrowCheckKrate, tcx, (), check_crate_task); - - fn check_crate_task<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (): ()) { - tcx.visit_all_bodies_in_krate(|body_owner_def_id, body_id| { - tcx.dep_graph.with_task(DepNode::BorrowCheck(body_owner_def_id), - tcx, - body_id, - borrowck_fn); - }); - } + tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| { + ty::queries::borrowck::get(tcx, DUMMY_SP, body_owner_def_id); + }); +} + +pub fn provide(providers: &mut Providers) { + *providers = Providers { + borrowck, + ..*providers + }; } /// Collection of conclusions determined via borrow checker analyses. @@ -81,11 +81,11 @@ pub struct AnalysisData<'a, 'tcx: 'a> { pub move_data: move_data::FlowedMoveData<'a, 'tcx>, } -fn borrowck_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, body_id: hir::BodyId) { - debug!("borrowck_fn(body_id={:?})", body_id); +fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { + debug!("borrowck(body_owner_def_id={:?})", owner_def_id); - let owner_id = tcx.hir.body_owner(body_id); - let owner_def_id = tcx.hir.local_def_id(owner_id); + let owner_id = tcx.hir.as_local_node_id(owner_def_id).unwrap(); + let body_id = tcx.hir.body_owned_by(owner_id); let attributes = tcx.get_attrs(owner_def_id); let tables = tcx.item_tables(owner_def_id); diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index d3b22884a3d8c..a1d3357faf566 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -51,4 +51,6 @@ mod borrowck; pub mod graphviz; +pub use borrowck::provide; + __build_diagnostic_array! { librustc_borrowck, DIAGNOSTICS } diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index adb2219722602..848e5a076bb9a 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -40,6 +40,12 @@ unsafe impl Array for [T; 8] { const LEN: usize = 8; } +unsafe impl Array for [T; 32] { + type Element = T; + type PartialStorage = [ManuallyDrop; 32]; + const LEN: usize = 32; +} + pub struct ArrayVec { count: usize, values: A::PartialStorage diff --git a/src/librustc_data_structures/blake2b.rs b/src/librustc_data_structures/blake2b.rs index 9d97a83f693c3..bdef9fefd41e4 100644 --- a/src/librustc_data_structures/blake2b.rs +++ b/src/librustc_data_structures/blake2b.rs @@ -29,16 +29,23 @@ pub struct Blake2bCtx { t: [u64; 2], c: usize, outlen: u16, - finalized: bool + finalized: bool, + + #[cfg(debug_assertions)] + fnv_hash: u64, } +#[cfg(debug_assertions)] impl ::std::fmt::Debug for Blake2bCtx { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - try!(write!(fmt, "hash: ")); - for v in &self.h { - try!(write!(fmt, "{:x}", v)); - } - Ok(()) + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(fmt, "{:x}", self.fnv_hash) + } +} + +#[cfg(not(debug_assertions))] +impl ::std::fmt::Debug for Blake2bCtx { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(fmt, "Enable debug_assertions() for more info.") } } @@ -157,6 +164,9 @@ fn blake2b_new(outlen: usize, key: &[u8]) -> Blake2bCtx { c: 0, outlen: outlen as u16, finalized: false, + + #[cfg(debug_assertions)] + fnv_hash: 0xcbf29ce484222325, }; ctx.h[0] ^= 0x01010000 ^ ((key.len() << 8) as u64) ^ (outlen as u64); @@ -194,6 +204,16 @@ fn blake2b_update(ctx: &mut Blake2bCtx, mut data: &[u8]) { checked_mem_copy(data, &mut ctx.b[ctx.c .. ], bytes_to_copy); ctx.c += bytes_to_copy; } + + #[cfg(debug_assertions)] + { + // compute additional FNV hash for simpler to read debug output + const MAGIC_PRIME: u64 = 0x00000100000001b3; + + for &byte in data { + ctx.fnv_hash = (ctx.fnv_hash ^ byte as u64).wrapping_mul(MAGIC_PRIME); + } + } } fn blake2b_final(ctx: &mut Blake2bCtx) diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 72c533a74618b..00c46d992bfd5 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -40,6 +40,7 @@ #![feature(discriminant_value)] #![feature(specialization)] #![feature(manually_drop)] +#![feature(struct_field_attributes)] #![cfg_attr(unix, feature(libc))] #![cfg_attr(test, feature(test))] diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index dc412a0763ef7..95f063976d491 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -40,13 +40,18 @@ fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize { /// This hasher currently always uses the stable Blake2b algorithm /// and allows for variable output lengths through its type /// parameter. -#[derive(Debug)] pub struct StableHasher { state: Blake2bHasher, bytes_hashed: u64, width: PhantomData, } +impl ::std::fmt::Debug for StableHasher { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{:?}", self.state) + } +} + pub trait StableHasherResult: Sized { fn finish(hasher: StableHasher) -> Self; } diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index 2bce7faf08cec..2631108aeb5fa 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -9,11 +9,14 @@ // except according to those terms. use bitvec::BitMatrix; +use stable_hasher::{HashStable, StableHasher, StableHasherResult}; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; use std::cell::RefCell; use std::fmt::Debug; use std::mem; + + #[derive(Clone)] pub struct TransitiveRelation { // List of elements. This is used to map from a T to a usize. We @@ -334,6 +337,49 @@ impl Decodable for TransitiveRelation } } +impl HashStable for TransitiveRelation + where T: HashStable + PartialEq + Debug +{ + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { + // We are assuming here that the relation graph has been built in a + // deterministic way and we can just hash it the way it is. + let TransitiveRelation { + ref elements, + ref edges, + // "closure" is just a copy of the data above + closure: _ + } = *self; + + elements.hash_stable(hcx, hasher); + edges.hash_stable(hcx, hasher); + } +} + +impl HashStable for Edge { + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { + let Edge { + ref source, + ref target, + } = *self; + + source.hash_stable(hcx, hasher); + target.hash_stable(hcx, hasher); + } +} + +impl HashStable for Index { + fn hash_stable(&self, + hcx: &mut CTX, + hasher: &mut StableHasher) { + let Index(idx) = *self; + idx.hash_stable(hcx, hasher); + } +} + #[test] fn test_one_step() { let mut relation = TransitiveRelation::new(); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index bdb05d06b0b10..20ae561431b54 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -35,7 +35,7 @@ use rustc_typeck as typeck; use rustc_privacy; use rustc_plugin::registry::Registry; use rustc_plugin as plugin; -use rustc_passes::{ast_validation, no_asm, loops, consts, rvalues, +use rustc_passes::{ast_validation, no_asm, loops, consts, static_recursion, hir_stats, mir_stats}; use rustc_const_eval::check_match; use super::Compilation; @@ -891,6 +891,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut local_providers = ty::maps::Providers::default(); mir::provide(&mut local_providers); rustc_privacy::provide(&mut local_providers); + borrowck::provide(&mut local_providers); typeck::provide(&mut local_providers); ty::provide(&mut local_providers); reachable::provide(&mut local_providers); @@ -957,10 +958,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, "liveness checking", || middle::liveness::check_crate(tcx)); - time(time_passes, - "rvalue checking", - || rvalues::check_crate(tcx)); - time(time_passes, "MIR dump", || mir::mir_map::build_mir_for_crate(tcx)); @@ -976,8 +973,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // in stage 4 below. passes.push_hook(box mir::transform::dump_mir::DumpMir); passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("initial")); - passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants); passes.push_pass(box mir::transform::type_check::TypeckMir); + passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants); passes.push_pass( box mir::transform::simplify_branches::SimplifyBranches::new("initial")); passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("qualify-consts")); @@ -1083,6 +1080,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "serialize dep graph", || rustc_incremental::save_dep_graph(tcx, &incremental_hashes_map, + &translation.metadata.hashes, translation.link.crate_hash)); translation } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 1b77ead92deb6..9715ace3e2e2e 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -35,6 +35,46 @@ pub struct SubDiagnostic { pub render_span: Option, } +#[derive(PartialEq, Eq)] +pub struct DiagnosticStyledString(pub Vec); + +impl DiagnosticStyledString { + pub fn new() -> DiagnosticStyledString { + DiagnosticStyledString(vec![]) + } + pub fn push_normal>(&mut self, t: S) { + self.0.push(StringPart::Normal(t.into())); + } + pub fn push_highlighted>(&mut self, t: S) { + self.0.push(StringPart::Highlighted(t.into())); + } + pub fn normal>(t: S) -> DiagnosticStyledString { + DiagnosticStyledString(vec![StringPart::Normal(t.into())]) + } + + pub fn highlighted>(t: S) -> DiagnosticStyledString { + DiagnosticStyledString(vec![StringPart::Highlighted(t.into())]) + } + + pub fn content(&self) -> String { + self.0.iter().map(|x| x.content()).collect::() + } +} + +#[derive(PartialEq, Eq)] +pub enum StringPart { + Normal(String), + Highlighted(String), +} + +impl StringPart { + pub fn content(&self) -> String { + match self { + &StringPart::Normal(ref s) | & StringPart::Highlighted(ref s) => s.to_owned() + } + } +} + impl Diagnostic { pub fn new(level: Level, message: &str) -> Self { Diagnostic::new_with_code(level, None, message) @@ -81,8 +121,8 @@ impl Diagnostic { pub fn note_expected_found(&mut self, label: &fmt::Display, - expected: &fmt::Display, - found: &fmt::Display) + expected: DiagnosticStyledString, + found: DiagnosticStyledString) -> &mut Self { self.note_expected_found_extra(label, expected, found, &"", &"") @@ -90,21 +130,29 @@ impl Diagnostic { pub fn note_expected_found_extra(&mut self, label: &fmt::Display, - expected: &fmt::Display, - found: &fmt::Display, + expected: DiagnosticStyledString, + found: DiagnosticStyledString, expected_extra: &fmt::Display, found_extra: &fmt::Display) -> &mut Self { + let mut msg: Vec<_> = vec![(format!("expected {} `", label), Style::NoStyle)]; + msg.extend(expected.0.iter() + .map(|x| match *x { + StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), + StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), + })); + msg.push((format!("`{}\n", expected_extra), Style::NoStyle)); + msg.push((format!(" found {} `", label), Style::NoStyle)); + msg.extend(found.0.iter() + .map(|x| match *x { + StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), + StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), + })); + msg.push((format!("`{}", found_extra), Style::NoStyle)); + // For now, just attach these as notes - self.highlighted_note(vec![ - (format!("expected {} `", label), Style::NoStyle), - (format!("{}", expected), Style::Highlight), - (format!("`{}\n", expected_extra), Style::NoStyle), - (format!(" found {} `", label), Style::NoStyle), - (format!("{}", found), Style::Highlight), - (format!("`{}", found_extra), Style::NoStyle), - ]); + self.highlighted_note(msg); self } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 7dfea6b8951b0..7b27f13951b61 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -9,6 +9,8 @@ // except according to those terms. use Diagnostic; +use DiagnosticStyledString; + use Level; use Handler; use std::fmt::{self, Debug}; @@ -115,14 +117,14 @@ impl<'a> DiagnosticBuilder<'a> { forward!(pub fn note_expected_found(&mut self, label: &fmt::Display, - expected: &fmt::Display, - found: &fmt::Display) + expected: DiagnosticStyledString, + found: DiagnosticStyledString) -> &mut Self); forward!(pub fn note_expected_found_extra(&mut self, label: &fmt::Display, - expected: &fmt::Display, - found: &fmt::Display, + expected: DiagnosticStyledString, + found: DiagnosticStyledString, expected_extra: &fmt::Display, found_extra: &fmt::Display) -> &mut Self); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 2efdaa57fba36..da29e354a7014 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -203,7 +203,7 @@ impl error::Error for ExplicitBug { } } -pub use diagnostic::{Diagnostic, SubDiagnostic}; +pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString, StringPart}; pub use diagnostic_builder::DiagnosticBuilder; /// A handler deals with errors; certain errors diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs index d900907395656..8a1af5dd08d74 100644 --- a/src/librustc_incremental/persist/data.rs +++ b/src/librustc_incremental/persist/data.rs @@ -13,6 +13,7 @@ use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId}; use rustc::hir::def_id::DefIndex; use rustc::ich::Fingerprint; +use rustc::middle::cstore::EncodedMetadataHash; use std::sync::Arc; use rustc_data_structures::fx::FxHashMap; @@ -98,7 +99,7 @@ pub struct SerializedMetadataHashes { /// where `X` refers to some item in this crate. That `X` will be /// a `DefPathIndex` that gets retracted to the current `DefId` /// (matching the one found in this structure). - pub hashes: Vec, + pub hashes: Vec, /// For each DefIndex (as it occurs in SerializedMetadataHash), this /// map stores the DefPathIndex (as it occurs in DefIdDirectory), so @@ -112,14 +113,3 @@ pub struct SerializedMetadataHashes { /// the DefIndex. pub index_map: FxHashMap } - -/// The hash for some metadata that (when saving) will be exported -/// from this crate, or which (when importing) was exported by an -/// upstream crate. -#[derive(Debug, RustcEncodable, RustcDecodable)] -pub struct SerializedMetadataHash { - pub def_index: DefIndex, - - /// the hash itself, computed by `calculate_item_hash` - pub hash: Fingerprint, -} diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index d931f64d579e1..af5c1f05bd1fc 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -215,9 +215,11 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> { } } -pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - prev_metadata_hashes: &FxHashMap, - current_metadata_hashes: &FxHashMap) { +pub fn check_dirty_clean_metadata<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + prev_metadata_hashes: &FxHashMap, + current_metadata_hashes: &FxHashMap) +{ if !tcx.sess.opts.debugging_opts.query_dep_graph { return; } @@ -230,7 +232,7 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, current_metadata_hashes: current_metadata_hashes, checked_attrs: FxHashSet(), }; - krate.visit_all_item_likes(&mut dirty_clean_visitor); + intravisit::walk_crate(&mut dirty_clean_visitor, krate); let mut all_attrs = FindAllAttrs { tcx: tcx, @@ -246,30 +248,58 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }); } -pub struct DirtyCleanMetadataVisitor<'a, 'tcx:'a, 'm> { +pub struct DirtyCleanMetadataVisitor<'a, 'tcx: 'a, 'm> { tcx: TyCtxt<'a, 'tcx, 'tcx>, prev_metadata_hashes: &'m FxHashMap, current_metadata_hashes: &'m FxHashMap, checked_attrs: FxHashSet, } -impl<'a, 'tcx, 'm> ItemLikeVisitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { +impl<'a, 'tcx, 'm> intravisit::Visitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { + + fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { + intravisit::NestedVisitorMap::All(&self.tcx.hir) + } + fn visit_item(&mut self, item: &'tcx hir::Item) { self.check_item(item.id, item.span); + intravisit::walk_item(self, item); + } - if let hir::ItemEnum(ref def, _) = item.node { - for v in &def.variants { - self.check_item(v.node.data.id(), v.span); - } + fn visit_variant_data(&mut self, + variant_data: &'tcx hir::VariantData, + _: ast::Name, + _: &'tcx hir::Generics, + _parent_id: ast::NodeId, + span: Span) { + if self.tcx.hir.find(variant_data.id()).is_some() { + // VariantData that represent structs or tuples don't have a + // separate entry in the HIR map and checking them would error, + // so only check if this is an enum or union variant. + self.check_item(variant_data.id(), span); } + + intravisit::walk_struct_def(self, variant_data); } - fn visit_trait_item(&mut self, item: &hir::TraitItem) { + fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { self.check_item(item.id, item.span); + intravisit::walk_trait_item(self, item); } - fn visit_impl_item(&mut self, item: &hir::ImplItem) { + fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { self.check_item(item.id, item.span); + intravisit::walk_impl_item(self, item); + } + + fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem) { + self.check_item(i.id, i.span); + intravisit::walk_foreign_item(self, i); + } + + fn visit_struct_field(&mut self, s: &'tcx hir::StructField) { + self.check_item(s.id, s.span); + intravisit::walk_struct_field(self, s); } } @@ -281,13 +311,15 @@ impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { for attr in self.tcx.get_attrs(def_id).iter() { if attr.check_name(ATTR_DIRTY_METADATA) { if check_config(self.tcx, attr) { - self.checked_attrs.insert(attr.id); - self.assert_state(false, def_id, item_span); + if self.checked_attrs.insert(attr.id) { + self.assert_state(false, def_id, item_span); + } } } else if attr.check_name(ATTR_CLEAN_METADATA) { if check_config(self.tcx, attr) { - self.checked_attrs.insert(attr.id); - self.assert_state(true, def_id, item_span); + if self.checked_attrs.insert(attr.id) { + self.assert_state(true, def_id, item_span); + } } } } diff --git a/src/librustc_incremental/persist/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs index fe8cf72996e15..e769641a4cadf 100644 --- a/src/librustc_incremental/persist/preds/mod.rs +++ b/src/librustc_incremental/persist/preds/mod.rs @@ -44,16 +44,18 @@ impl<'q> Predecessors<'q> { pub fn new(query: &'q DepGraphQuery, hcx: &mut HashContext) -> Self { let tcx = hcx.tcx; - let collect_for_metadata = tcx.sess.opts.debugging_opts.incremental_cc || - tcx.sess.opts.debugging_opts.query_dep_graph; - // Find the set of "start nodes". These are nodes that we will // possibly query later. let is_output = |node: &DepNode| -> bool { match *node { DepNode::WorkProduct(_) => true, - DepNode::MetaData(ref def_id) => collect_for_metadata && def_id.is_local(), - + DepNode::MetaData(ref def_id) => { + // We do *not* create dep-nodes for the current crate's + // metadata anymore, just for metadata that we import/read + // from other crates. + debug_assert!(!def_id.is_local()); + false + } // if -Z query-dep-graph is passed, save more extended data // to enable better unit testing DepNode::TypeckTables(_) | @@ -75,6 +77,22 @@ impl<'q> Predecessors<'q> { .or_insert_with(|| hcx.hash(input).unwrap()); } + if tcx.sess.opts.debugging_opts.query_dep_graph { + // Not all inputs might have been reachable from an output node, + // but we still want their hash for our unit tests. + let hir_nodes = query.graph.all_nodes().iter().filter_map(|node| { + match node.data { + DepNode::Hir(_) => Some(&node.data), + _ => None, + } + }); + + for node in hir_nodes { + hashes.entry(node) + .or_insert_with(|| hcx.hash(node).unwrap()); + } + } + let bootstrap_outputs: Vec<&'q DepNode> = (0 .. graph.len_nodes()) .map(NodeIndex) diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 1591503865e81..1864009fbdf21 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -12,13 +12,12 @@ use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; use rustc::hir::svh::Svh; use rustc::ich::Fingerprint; +use rustc::middle::cstore::EncodedMetadataHash; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::graph::{NodeIndex, INCOMING}; use rustc_serialize::Encodable as RustcEncodable; use rustc_serialize::opaque::Encoder; -use std::hash::Hash; use std::io::{self, Cursor, Write}; use std::fs::{self, File}; use std::path::PathBuf; @@ -32,10 +31,10 @@ use super::fs::*; use super::dirty_clean; use super::file_format; use super::work_product; -use calculate_svh::IchHasher; pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, incremental_hashes_map: &IncrementalHashesMap, + metadata_hashes: &[EncodedMetadataHash], svh: Svh) { debug!("save_dep_graph()"); let _ignore = tcx.dep_graph.in_ignore(); @@ -56,16 +55,16 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let preds = Predecessors::new(&query, &mut hcx); let mut current_metadata_hashes = FxHashMap(); + // IMPORTANT: We are saving the metadata hashes *before* the dep-graph, + // since metadata-encoding might add new entries to the + // DefIdDirectory (which is saved in the dep-graph file). if sess.opts.debugging_opts.incremental_cc || sess.opts.debugging_opts.query_dep_graph { - // IMPORTANT: We are saving the metadata hashes *before* the dep-graph, - // since metadata-encoding might add new entries to the - // DefIdDirectory (which is saved in the dep-graph file). save_in(sess, metadata_hash_export_path(sess), |e| encode_metadata_hashes(tcx, svh, - &preds, + metadata_hashes, &mut builder, &mut current_metadata_hashes, e)); @@ -241,80 +240,16 @@ pub fn encode_dep_graph(preds: &Predecessors, pub fn encode_metadata_hashes(tcx: TyCtxt, svh: Svh, - preds: &Predecessors, + metadata_hashes: &[EncodedMetadataHash], builder: &mut DefIdDirectoryBuilder, current_metadata_hashes: &mut FxHashMap, encoder: &mut Encoder) -> io::Result<()> { - // For each `MetaData(X)` node where `X` is local, accumulate a - // hash. These are the metadata items we export. Downstream - // crates will want to see a hash that tells them whether we might - // have changed the metadata for a given item since they last - // compiled. - // - // (I initially wrote this with an iterator, but it seemed harder to read.) let mut serialized_hashes = SerializedMetadataHashes { - hashes: vec![], + hashes: metadata_hashes.to_vec(), index_map: FxHashMap() }; - for (index, target) in preds.reduced_graph.all_nodes().iter().enumerate() { - let index = NodeIndex(index); - let def_id = match *target.data { - DepNode::MetaData(def_id) if def_id.is_local() => def_id, - _ => continue, - }; - - // To create the hash for each item `X`, we don't hash the raw - // bytes of the metadata (though in principle we - // could). Instead, we walk the predecessors of `MetaData(X)` - // from the dep-graph. This corresponds to all the inputs that - // were read to construct the metadata. To create the hash for - // the metadata, we hash (the hash of) all of those inputs. - debug!("save: computing metadata hash for {:?}", def_id); - - // Create a vector containing a pair of (source-id, hash). - // The source-id is stored as a `DepNode`, where the u64 - // is the det. hash of the def-path. This is convenient - // because we can sort this to get a stable ordering across - // compilations, even if the def-ids themselves have changed. - let mut hashes: Vec<(DepNode, Fingerprint)> = - preds.reduced_graph - .depth_traverse(index, INCOMING) - .map(|index| preds.reduced_graph.node_data(index)) - .filter(|dep_node| HashContext::is_hashable(dep_node)) - .map(|dep_node| { - let hash_dep_node = dep_node.map_def(|&def_id| Some(tcx.def_path_hash(def_id))) - .unwrap(); - let hash = preds.hashes[dep_node]; - (hash_dep_node, hash) - }) - .collect(); - - hashes.sort(); - let mut state = IchHasher::new(); - hashes.hash(&mut state); - let hash = state.finish(); - - debug!("save: metadata hash for {:?} is {}", def_id, hash); - - if tcx.sess.opts.debugging_opts.incremental_dump_hash { - println!("metadata hash for {:?} is {}", def_id, hash); - for pred_index in preds.reduced_graph.depth_traverse(index, INCOMING) { - let dep_node = preds.reduced_graph.node_data(pred_index); - if HashContext::is_hashable(&dep_node) { - println!("metadata hash for {:?} depends on {:?} with hash {}", - def_id, dep_node, preds.hashes[dep_node]); - } - } - } - - serialized_hashes.hashes.push(SerializedMetadataHash { - def_index: def_id.index, - hash: hash, - }); - } - if tcx.sess.opts.debugging_opts.query_dep_graph { for serialized_hash in &serialized_hashes.hashes { let def_id = DefId::local(serialized_hash.def_index); diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 459132eb9c613..d9008ce555cc1 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -10,14 +10,12 @@ use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; -use encoder::EncodeContext; +use index_builder::EntryBuilder; use schema::*; use rustc::hir; use rustc::ty; -use rustc_serialize::Encodable; - #[derive(RustcEncodable, RustcDecodable)] pub struct Ast<'tcx> { pub body: Lazy, @@ -26,7 +24,14 @@ pub struct Ast<'tcx> { pub rvalue_promotable_to_static: bool, } -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { +impl_stable_hash_for!(struct Ast<'tcx> { + body, + tables, + nested_bodies, + rvalue_promotable_to_static +}); + +impl<'a, 'b, 'tcx> EntryBuilder<'a, 'b, 'tcx> { pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy> { let body = self.tcx.hir.body(body_id); let lazy_body = self.lazy(body); @@ -34,15 +39,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tables = self.tcx.body_tables(body_id); let lazy_tables = self.lazy(tables); - let nested_pos = self.position(); - let nested_count = { - let mut visitor = NestedBodyEncodingVisitor { - ecx: self, - count: 0, - }; - visitor.visit_body(body); - visitor.count + let mut visitor = NestedBodyCollector { + tcx: self.tcx, + bodies_found: Vec::new(), }; + visitor.visit_body(body); + let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found); let rvalue_promotable_to_static = self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id]; @@ -50,27 +52,25 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy(&Ast { body: lazy_body, tables: lazy_tables, - nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count), + nested_bodies: lazy_nested_bodies, rvalue_promotable_to_static: rvalue_promotable_to_static }) } } -struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> { - ecx: &'a mut EncodeContext<'b, 'tcx>, - count: usize, +struct NestedBodyCollector<'a, 'tcx: 'a> { + tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, + bodies_found: Vec<&'tcx hir::Body>, } -impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> { +impl<'a, 'tcx: 'a> Visitor<'tcx> for NestedBodyCollector<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::None } fn visit_nested_body(&mut self, body: hir::BodyId) { - let body = self.ecx.tcx.hir.body(body); - body.encode(self.ecx).unwrap(); - self.count += 1; - + let body = self.tcx.hir.body(body); + self.bodies_found.push(body); self.visit_body(body); } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 37984e4c3718f..3239dfb937b5e 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -14,8 +14,9 @@ use locator; use schema; use rustc::dep_graph::DepTrackingMapConfig; -use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternCrate}; -use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro}; +use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, + ExternCrate, NativeLibrary, LinkMeta, + LinkagePreference, LoadedMacro, EncodedMetadata}; use rustc::hir::def::{self, Def}; use rustc::middle::lang_items; use rustc::session::Session; @@ -498,7 +499,8 @@ impl CrateStore for cstore::CStore { fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &LinkMeta, - reachable: &NodeSet) -> Vec + reachable: &NodeSet) + -> EncodedMetadata { encoder::encode_metadata(tcx, self, link_meta, reachable) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 38d774992a551..ffe68094c6afc 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -12,7 +12,8 @@ use cstore; use index::Index; use schema::*; -use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary}; +use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary, + EncodedMetadata, EncodedMetadataHash}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId}; use rustc::hir::map::definitions::DefPathTable; use rustc::middle::dependency_format::Linkage; @@ -42,7 +43,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc::hir::intravisit; -use super::index_builder::{FromId, IndexBuilder, Untracked}; +use super::index_builder::{FromId, IndexBuilder, Untracked, EntryBuilder}; pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder<'a>, @@ -54,6 +55,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> { lazy_state: LazyState, type_shorthands: FxHashMap, usize>, predicate_shorthands: FxHashMap, usize>, + + pub metadata_hashes: Vec, } macro_rules! encoder_methods { @@ -172,7 +175,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }) } - fn lazy_seq(&mut self, iter: I) -> LazySeq + pub fn lazy_seq(&mut self, iter: I) -> LazySeq where I: IntoIterator, T: Encodable { @@ -184,7 +187,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }) } - fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq + pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq where I: IntoIterator, T: 'b + Encodable { @@ -233,15 +236,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { Ok(()) } +} +impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq { + debug!("EntryBuilder::encode_item_variances({:?})", def_id); let tcx = self.tcx; - self.lazy_seq(tcx.item_variances(def_id).iter().cloned()) + self.lazy_seq_from_slice(&tcx.item_variances(def_id)) } fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { let tcx = self.tcx; - self.lazy(&tcx.item_type(def_id)) + let ty = tcx.item_type(def_id); + debug!("EntryBuilder::encode_item_type({:?}) => {:?}", def_id, ty); + self.lazy(&ty) } /// Encode data for the given variant of the given ADT. The @@ -256,6 +264,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def = tcx.lookup_adt_def(enum_did); let variant = &def.variants[index]; let def_id = variant.did; + debug!("EntryBuilder::encode_enum_variant_info({:?})", def_id); let data = VariantData { ctor_kind: variant.ctor_kind, @@ -302,10 +311,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { -> Entry<'tcx> { let tcx = self.tcx; let def_id = tcx.hir.local_def_id(id); + debug!("EntryBuilder::encode_info_for_mod({:?})", def_id); let data = ModData { reexports: match tcx.export_map.get(&id) { - Some(exports) if *vis == hir::Public => self.lazy_seq_ref(exports), + Some(exports) if *vis == hir::Public => { + self.lazy_seq_from_slice(exports.as_slice()) + } _ => LazySeq::empty(), }, }; @@ -339,14 +351,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { for (variant_index, variant) in def.variants.iter().enumerate() { for (field_index, field) in variant.fields.iter().enumerate() { self.record(field.did, - EncodeContext::encode_field, + EntryBuilder::encode_field, (adt_def_id, Untracked((variant_index, field_index)))); } } } } -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { +impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { /// Encode data for the given field of the given variant of the /// given ADT. The indices of the variant/field are untracked: /// this is ok because we will have to lookup the adt-def by its @@ -363,6 +375,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let field = &variant.fields[field_index]; let def_id = field.did; + debug!("EntryBuilder::encode_field({:?})", def_id); + let variant_id = tcx.hir.as_local_node_id(variant.did).unwrap(); let variant_data = tcx.hir.expect_variant_data(variant_id); @@ -387,6 +401,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> { + debug!("EntryBuilder::encode_struct_ctor({:?})", def_id); let tcx = self.tcx; let variant = tcx.lookup_adt_def(adt_def_id).struct_variant(); @@ -429,16 +444,19 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_generics(&mut self, def_id: DefId) -> Lazy { + debug!("EntryBuilder::encode_generics({:?})", def_id); let tcx = self.tcx; self.lazy(tcx.item_generics(def_id)) } fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { + debug!("EntryBuilder::encode_predicates({:?})", def_id); let tcx = self.tcx; self.lazy(&tcx.item_predicates(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { + debug!("EntryBuilder::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); @@ -521,6 +539,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { + debug!("EntryBuilder::encode_info_for_impl_item({:?})", def_id); let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.hir.expect_impl_item(node_id); let impl_item = self.tcx.associated_item(def_id); @@ -607,11 +626,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_mir(&mut self, def_id: DefId) -> Option>> { + debug!("EntryBuilder::encode_mir({:?})", def_id); self.tcx.maps.mir.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow())) } // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq { + debug!("EntryBuilder::encode_inherent_implementations({:?})", def_id); match self.tcx.maps.inherent_impls.borrow().get(&def_id) { None => LazySeq::empty(), Some(implementations) => { @@ -624,18 +645,19 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_stability(&mut self, def_id: DefId) -> Option> { + debug!("EntryBuilder::encode_stability({:?})", def_id); self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) } fn encode_deprecation(&mut self, def_id: DefId) -> Option> { + debug!("EntryBuilder::encode_deprecation({:?})", def_id); self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) } fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { let tcx = self.tcx; - debug!("encoding info for item at {}", - tcx.sess.codemap().span_to_string(item.span)); + debug!("EntryBuilder::encode_info_for_item({:?})", def_id); let kind = match item.node { hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic, @@ -907,7 +929,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let def = self.tcx.lookup_adt_def(def_id); for (i, variant) in def.variants.iter().enumerate() { self.record(variant.did, - EncodeContext::encode_enum_variant_info, + EntryBuilder::encode_enum_variant_info, (def_id, Untracked(i))); } } @@ -918,7 +940,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { if !struct_def.is_struct() { let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id()); self.record(ctor_def_id, - EncodeContext::encode_struct_ctor, + EntryBuilder::encode_struct_ctor, (def_id, ctor_def_id)); } } @@ -928,14 +950,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { hir::ItemImpl(..) => { for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { self.record(trait_item_def_id, - EncodeContext::encode_info_for_impl_item, + EntryBuilder::encode_info_for_impl_item, trait_item_def_id); } } hir::ItemTrait(..) => { for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { self.record(item_def_id, - EncodeContext::encode_info_for_trait_item, + EntryBuilder::encode_info_for_trait_item, item_def_id); } } @@ -943,13 +965,13 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { } } -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { +impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { fn encode_info_for_foreign_item(&mut self, (def_id, nitem): (DefId, &hir::ForeignItem)) -> Entry<'tcx> { let tcx = self.tcx; - debug!("writing foreign item {}", tcx.node_path_str(nitem.id)); + debug!("EntryBuilder::encode_info_for_foreign_item({:?})", def_id); let kind = match nitem.node { hir::ForeignItemFn(_, ref names, _) => { @@ -1002,7 +1024,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { match item.node { hir::ItemExternCrate(_) | hir::ItemUse(..) => (), // ignore these - _ => self.index.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)), + _ => self.index.record(def_id, EntryBuilder::encode_info_for_item, (def_id, item)), } self.index.encode_addl_info_for_item(item); } @@ -1010,7 +1032,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { intravisit::walk_foreign_item(self, ni); let def_id = self.index.tcx.hir.local_def_id(ni.id); self.index.record(def_id, - EncodeContext::encode_info_for_foreign_item, + EntryBuilder::encode_info_for_foreign_item, (def_id, ni)); } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { @@ -1023,7 +1045,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { } fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { let def_id = self.index.tcx.hir.local_def_id(macro_def.id); - self.index.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def); + self.index.record(def_id, EntryBuilder::encode_info_for_macro_def, macro_def); } } @@ -1032,14 +1054,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { for ty_param in &generics.ty_params { let def_id = self.tcx.hir.local_def_id(ty_param.id); let has_default = Untracked(ty_param.default.is_some()); - self.record(def_id, EncodeContext::encode_info_for_ty_param, (def_id, has_default)); + self.record(def_id, EntryBuilder::encode_info_for_ty_param, (def_id, has_default)); } } fn encode_info_for_ty(&mut self, ty: &hir::Ty) { if let hir::TyImplTrait(_) = ty.node { let def_id = self.tcx.hir.local_def_id(ty.id); - self.record(def_id, EncodeContext::encode_info_for_anon_ty, def_id); + self.record(def_id, EntryBuilder::encode_info_for_anon_ty, def_id); } } @@ -1047,17 +1069,18 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { match expr.node { hir::ExprClosure(..) => { let def_id = self.tcx.hir.local_def_id(expr.id); - self.record(def_id, EncodeContext::encode_info_for_closure, def_id); + self.record(def_id, EntryBuilder::encode_info_for_closure, def_id); } _ => {} } } } -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { +impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { fn encode_info_for_ty_param(&mut self, (def_id, Untracked(has_default)): (DefId, Untracked)) -> Entry<'tcx> { + debug!("EntryBuilder::encode_info_for_ty_param({:?})", def_id); let tcx = self.tcx; Entry { kind: EntryKind::Type, @@ -1084,6 +1107,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> { + debug!("EntryBuilder::encode_info_for_anon_ty({:?})", def_id); let tcx = self.tcx; Entry { kind: EntryKind::Type, @@ -1106,6 +1130,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { + debug!("EntryBuilder::encode_info_for_closure({:?})", def_id); let tcx = self.tcx; let data = ClosureData { @@ -1133,11 +1158,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { + // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because + // we really on the HashStable specialization for [Attribute] + // to properly filter things out. + self.lazy_seq_from_slice(attrs) + } +} + +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_items(&mut self) -> Index { let krate = self.tcx.hir.krate(); let mut index = IndexBuilder::new(self); index.record(DefId::local(CRATE_DEF_INDEX), - EncodeContext::encode_info_for_mod, + EntryBuilder::encode_info_for_mod, FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); let mut visitor = EncodeVisitor { index: index }; krate.visit_all_item_likes(&mut visitor.as_deep_visitor()); @@ -1147,10 +1181,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { visitor.index.into_items() } - fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { - self.lazy_seq_ref(attrs) - } - fn encode_crate_deps(&mut self) -> LazySeq { fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc)> { // Pull the cnums and name,vers,hash out of cstore @@ -1298,7 +1328,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { None => LazySeq::empty(), } } +} +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_crate_root(&mut self) -> Lazy { let mut i = self.position(); let crate_deps = self.encode_crate_deps(); @@ -1431,14 +1463,15 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cstore: &cstore::CStore, link_meta: &LinkMeta, exported_symbols: &NodeSet) - -> Vec { + -> EncodedMetadata +{ let mut cursor = Cursor::new(vec![]); cursor.write_all(METADATA_HEADER).unwrap(); // Will be filed with the root position after encoding everything. cursor.write_all(&[0, 0, 0, 0]).unwrap(); - let root = { + let (root, metadata_hashes) = { let mut ecx = EncodeContext { opaque: opaque::Encoder::new(&mut cursor), tcx: tcx, @@ -1448,6 +1481,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), + metadata_hashes: Vec::new(), }; // Encode the rustc version string in a predictable location. @@ -1455,7 +1489,8 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Encode all the entries and extra information in the crate, // culminating in the `CrateRoot` which points to all of it. - ecx.encode_crate_root() + let root = ecx.encode_crate_root(); + (root, ecx.metadata_hashes) }; let mut result = cursor.into_inner(); @@ -1467,7 +1502,10 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result[header + 2] = (pos >> 8) as u8; result[header + 3] = (pos >> 0) as u8; - result + EncodedMetadata { + raw_data: result, + hashes: metadata_hashes, + } } pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions { diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index a811f72bc956c..01f948866b850 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -59,14 +59,19 @@ use encoder::EncodeContext; use index::Index; use schema::*; -use rustc::dep_graph::DepNode; use rustc::hir; use rustc::hir::def_id::DefId; +use rustc::ich::{StableHashingContext, Fingerprint}; +use rustc::middle::cstore::EncodedMetadataHash; use rustc::ty::TyCtxt; use syntax::ast; use std::ops::{Deref, DerefMut}; +use rustc_data_structures::accumulate_vec::AccumulateVec; +use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; +use rustc_serialize::Encodable; + /// Builder that can encode new items, adding them into the index. /// Item encoding cannot be nested. pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> { @@ -112,16 +117,45 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { /// holds, and that it is therefore not gaining "secret" access to /// bits of HIR or other state that would not be trackd by the /// content system. - pub fn record(&mut self, - id: DefId, - op: fn(&mut EncodeContext<'b, 'tcx>, DATA) -> Entry<'tcx>, - data: DATA) + pub fn record<'x, DATA>(&'x mut self, + id: DefId, + op: fn(&mut EntryBuilder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>, + data: DATA) where DATA: DepGraphRead { - let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id)); - data.read(self.tcx); - let entry = op(&mut self.ecx, data); - self.items.record(id, self.ecx.lazy(&entry)); + assert!(id.is_local()); + let tcx: TyCtxt<'b, 'tcx, 'tcx> = self.ecx.tcx; + + // We don't track this since we are explicitly computing the incr. comp. + // hashes anyway. In theory we could do some tracking here and use it to + // avoid rehashing things (and instead cache the hashes) but it's + // unclear whether that would be a win since hashing is cheap enough. + let _task = tcx.dep_graph.in_ignore(); + + let compute_ich = (tcx.sess.opts.debugging_opts.query_dep_graph || + tcx.sess.opts.debugging_opts.incremental_cc) && + tcx.sess.opts.build_dep_graph(); + + let ecx: &'x mut EncodeContext<'b, 'tcx> = &mut *self.ecx; + let mut entry_builder = EntryBuilder { + tcx: tcx, + ecx: ecx, + hcx: if compute_ich { + Some((StableHashingContext::new(tcx), StableHasher::new())) + } else { + None + } + }; + + let entry = op(&mut entry_builder, data); + + if let Some((ref mut hcx, ref mut hasher)) = entry_builder.hcx { + entry.hash_stable(hcx, hasher); + } + + let entry = entry_builder.ecx.lazy(&entry); + entry_builder.finish(id); + self.items.record(id, entry); } pub fn into_items(self) -> Index { @@ -223,3 +257,91 @@ impl DepGraphRead for FromId { tcx.hir.read(self.0); } } + +pub struct EntryBuilder<'a, 'b: 'a, 'tcx: 'b> { + pub tcx: TyCtxt<'b, 'tcx, 'tcx>, + ecx: &'a mut EncodeContext<'b, 'tcx>, + hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher)>, +} + +impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { + + pub fn finish(self, def_id: DefId) { + if let Some((_, hasher)) = self.hcx { + let hash = hasher.finish(); + self.ecx.metadata_hashes.push(EncodedMetadataHash { + def_index: def_id.index, + hash: hash, + }); + } + } + + pub fn lazy(&mut self, value: &T) -> Lazy + where T: Encodable + HashStable> + { + if let Some((ref mut hcx, ref mut hasher)) = self.hcx { + value.hash_stable(hcx, hasher); + debug!("metadata-hash: {:?}", hasher); + } + self.ecx.lazy(value) + } + + pub fn lazy_seq(&mut self, iter: I) -> LazySeq + where I: IntoIterator, + T: Encodable + HashStable> + { + if let Some((ref mut hcx, ref mut hasher)) = self.hcx { + let iter = iter.into_iter(); + let (lower_bound, upper_bound) = iter.size_hint(); + + if upper_bound == Some(lower_bound) { + lower_bound.hash_stable(hcx, hasher); + let mut num_items_hashed = 0; + let ret = self.ecx.lazy_seq(iter.inspect(|item| { + item.hash_stable(hcx, hasher); + num_items_hashed += 1; + })); + + // Sometimes items in a sequence are filtered out without being + // hashed (e.g. for &[ast::Attribute]) and this code path cannot + // handle that correctly, so we want to make sure we didn't hit + // it by accident. + if lower_bound != num_items_hashed { + bug!("Hashed a different number of items ({}) than expected ({})", + num_items_hashed, + lower_bound); + } + debug!("metadata-hash: {:?}", hasher); + ret + } else { + // Collect into a vec so we know the length of the sequence + let items: AccumulateVec<[T; 32]> = iter.collect(); + items.hash_stable(hcx, hasher); + debug!("metadata-hash: {:?}", hasher); + self.ecx.lazy_seq(items) + } + } else { + self.ecx.lazy_seq(iter) + } + } + + pub fn lazy_seq_from_slice(&mut self, slice: &[T]) -> LazySeq + where T: Encodable + HashStable> + { + if let Some((ref mut hcx, ref mut hasher)) = self.hcx { + slice.hash_stable(hcx, hasher); + debug!("metadata-hash: {:?}", hasher); + } + self.ecx.lazy_seq_ref(slice.iter()) + } + + pub fn lazy_seq_ref_from_slice(&mut self, slice: &[&T]) -> LazySeq + where T: Encodable + HashStable> + { + if let Some((ref mut hcx, ref mut hasher)) = self.hcx { + slice.hash_stable(hcx, hasher); + debug!("metadata-hash: {:?}", hasher); + } + self.ecx.lazy_seq_ref(slice.iter().map(|x| *x)) + } +} diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 2fbdb8c0de676..b9e142ac65072 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -27,6 +27,7 @@ #![feature(rustc_private)] #![feature(specialization)] #![feature(staged_api)] +#![feature(discriminant_value)] #[macro_use] extern crate log; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index abb482a50ebc2..53d6a9ec10df2 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -14,6 +14,7 @@ use index; use rustc::hir; use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId}; +use rustc::ich::StableHashingContext; use rustc::middle::const_val::ConstVal; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; use rustc::middle::lang_items; @@ -27,6 +28,10 @@ use syntax::symbol::Symbol; use syntax_pos::{self, Span}; use std::marker::PhantomData; +use std::mem; + +use rustc_data_structures::stable_hasher::{StableHasher, HashStable, + StableHasherResult}; pub fn rustc_version() -> String { format!("rustc {}", @@ -100,6 +105,15 @@ impl Clone for Lazy { impl serialize::UseSpecializedEncodable for Lazy {} impl serialize::UseSpecializedDecodable for Lazy {} +impl HashStable for Lazy { + fn hash_stable(&self, + _: &mut CTX, + _: &mut StableHasher) { + // There's nothing to do. Whatever got encoded within this Lazy<> + // wrapper has already been hashed. + } +} + /// A sequence of type T referred to by its absolute position /// in the metadata and length, and which can be decoded lazily. /// The sequence is a single node for the purposes of `Lazy`. @@ -148,6 +162,15 @@ impl Clone for LazySeq { impl serialize::UseSpecializedEncodable for LazySeq {} impl serialize::UseSpecializedDecodable for LazySeq {} +impl HashStable for LazySeq { + fn hash_stable(&self, + _: &mut CTX, + _: &mut StableHasher) { + // There's nothing to do. Whatever got encoded within this Lazy<> + // wrapper has already been hashed. + } +} + /// Encoding / decoding state for `Lazy` and `LazySeq`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum LazyState { @@ -219,6 +242,23 @@ pub struct Entry<'tcx> { pub mir: Option>>, } +impl_stable_hash_for!(struct Entry<'tcx> { + kind, + visibility, + span, + attributes, + children, + stability, + deprecation, + ty, + inherent_impls, + variances, + generics, + predicates, + ast, + mir +}); + #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub enum EntryKind<'tcx> { Const(u8), @@ -246,22 +286,91 @@ pub enum EntryKind<'tcx> { AssociatedConst(AssociatedContainer, u8), } +impl<'a, 'tcx> HashStable> for EntryKind<'tcx> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'tcx>, + hasher: &mut StableHasher) { + mem::discriminant(self).hash_stable(hcx, hasher); + match *self { + EntryKind::ImmStatic | + EntryKind::MutStatic | + EntryKind::ForeignImmStatic | + EntryKind::ForeignMutStatic | + EntryKind::ForeignMod | + EntryKind::Field | + EntryKind::Type => { + // Nothing else to hash here. + } + EntryKind::Const(qualif) => { + qualif.hash_stable(hcx, hasher); + } + EntryKind::Enum(ref repr_options) => { + repr_options.hash_stable(hcx, hasher); + } + EntryKind::Variant(ref variant_data) => { + variant_data.hash_stable(hcx, hasher); + } + EntryKind::Struct(ref variant_data, ref repr_options) | + EntryKind::Union(ref variant_data, ref repr_options) => { + variant_data.hash_stable(hcx, hasher); + repr_options.hash_stable(hcx, hasher); + } + EntryKind::Fn(ref fn_data) | + EntryKind::ForeignFn(ref fn_data) => { + fn_data.hash_stable(hcx, hasher); + } + EntryKind::Mod(ref mod_data) => { + mod_data.hash_stable(hcx, hasher); + } + EntryKind::MacroDef(ref macro_def) => { + macro_def.hash_stable(hcx, hasher); + } + EntryKind::Closure(closure_data) => { + closure_data.hash_stable(hcx, hasher); + } + EntryKind::Trait(ref trait_data) => { + trait_data.hash_stable(hcx, hasher); + } + EntryKind::DefaultImpl(ref impl_data) | + EntryKind::Impl(ref impl_data) => { + impl_data.hash_stable(hcx, hasher); + } + EntryKind::Method(ref method_data) => { + method_data.hash_stable(hcx, hasher); + } + EntryKind::AssociatedType(associated_container) => { + associated_container.hash_stable(hcx, hasher); + } + EntryKind::AssociatedConst(associated_container, qualif) => { + associated_container.hash_stable(hcx, hasher); + qualif.hash_stable(hcx, hasher); + } + } + } +} + #[derive(RustcEncodable, RustcDecodable)] pub struct ModData { pub reexports: LazySeq, } +impl_stable_hash_for!(struct ModData { reexports }); + #[derive(RustcEncodable, RustcDecodable)] pub struct MacroDef { pub body: String, } +impl_stable_hash_for!(struct MacroDef { body }); + #[derive(RustcEncodable, RustcDecodable)] pub struct FnData { pub constness: hir::Constness, pub arg_names: LazySeq, } +impl_stable_hash_for!(struct FnData { constness, arg_names }); + #[derive(RustcEncodable, RustcDecodable)] pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, @@ -273,6 +382,13 @@ pub struct VariantData<'tcx> { pub struct_ctor: Option, } +impl_stable_hash_for!(struct VariantData<'tcx> { + ctor_kind, + discr, + evaluated_discr, + struct_ctor +}); + #[derive(RustcEncodable, RustcDecodable)] pub struct TraitData<'tcx> { pub unsafety: hir::Unsafety, @@ -281,6 +397,13 @@ pub struct TraitData<'tcx> { pub super_predicates: Lazy>, } +impl_stable_hash_for!(struct TraitData<'tcx> { + unsafety, + paren_sugar, + has_default_impl, + super_predicates +}); + #[derive(RustcEncodable, RustcDecodable)] pub struct ImplData<'tcx> { pub polarity: hir::ImplPolarity, @@ -291,6 +414,14 @@ pub struct ImplData<'tcx> { pub trait_ref: Option>>, } +impl_stable_hash_for!(struct ImplData<'tcx> { + polarity, + parent_impl, + coerce_unsized_info, + trait_ref +}); + + /// Describes whether the container of an associated item /// is a trait or an impl and whether, in a trait, it has /// a default, or an in impl, whether it's marked "default". @@ -302,6 +433,13 @@ pub enum AssociatedContainer { ImplFinal, } +impl_stable_hash_for!(enum ::schema::AssociatedContainer { + TraitRequired, + TraitWithDefault, + ImplDefault, + ImplFinal +}); + impl AssociatedContainer { pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer { match *self { @@ -335,9 +473,11 @@ pub struct MethodData { pub container: AssociatedContainer, pub has_self: bool, } +impl_stable_hash_for!(struct MethodData { fn_data, container, has_self }); #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { pub kind: ty::ClosureKind, pub ty: Lazy>, } +impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty }); diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index 1cd9a1b25bade..df2841a668269 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -62,7 +62,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let idx = unpack!(block = this.as_operand(block, None, index)); // bounds check: - let (len, lt) = (this.temp(usize_ty.clone()), this.temp(bool_ty)); + let (len, lt) = (this.temp(usize_ty.clone(), expr_span), + this.temp(bool_ty, expr_span)); this.cfg.push_assign(block, source_info, // len = len(slice) &len, Rvalue::Len(slice.clone())); this.cfg.push_assign(block, source_info, // lt = idx < len diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 6694107a8d485..fb547332c5f58 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -82,7 +82,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let bool_ty = this.hir.bool_ty(); let minval = this.minval_literal(expr_span, expr.ty); - let is_min = this.temp(bool_ty); + let is_min = this.temp(bool_ty, expr_span); this.cfg.push_assign(block, source_info, &is_min, Rvalue::BinaryOp(BinOp::Eq, arg.clone(), minval)); @@ -95,7 +95,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } ExprKind::Box { value, value_extents } => { let value = this.hir.mirror(value); - let result = this.temp(expr.ty); + let result = this.temp(expr.ty, expr_span); // to start, malloc some memory of suitable type (thus far, uninitialized): this.cfg.push_assign(block, source_info, &result, Rvalue::Box(value.ty)); this.in_scope(value_extents, block, |this| { @@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let bool_ty = self.hir.bool_ty(); if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() { let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty], false); - let result_value = self.temp(result_tup); + let result_value = self.temp(result_tup, span); self.cfg.push_assign(block, source_info, &result_value, Rvalue::CheckedBinaryOp(op, @@ -301,7 +301,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; // Check for / 0 - let is_zero = self.temp(bool_ty); + let is_zero = self.temp(bool_ty, span); let zero = self.zero_literal(span, ty); self.cfg.push_assign(block, source_info, &is_zero, Rvalue::BinaryOp(BinOp::Eq, rhs.clone(), zero)); @@ -315,9 +315,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let neg_1 = self.neg_1_literal(span, ty); let min = self.minval_literal(span, ty); - let is_neg_1 = self.temp(bool_ty); - let is_min = self.temp(bool_ty); - let of = self.temp(bool_ty); + let is_neg_1 = self.temp(bool_ty, span); + let is_min = self.temp(bool_ty, span); + let of = self.temp(bool_ty, span); // this does (rhs == -1) & (lhs == MIN). It could short-circuit instead diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 42d9ab4d2bf27..e4598b4143871 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -44,8 +44,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } let expr_ty = expr.ty.clone(); - let temp = this.temp(expr_ty.clone()); let expr_span = expr.span; + let temp = this.temp(expr_ty.clone(), expr_span); let source_info = this.source_info(expr_span); if expr.temp_lifetime_was_shrunk && this.hir.needs_drop(expr_ty) { diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 7336da654c184..c03432312b0ab 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -138,7 +138,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } _ => { let expr_ty = expr.ty; - let temp = this.temp(expr.ty.clone()); + let temp = this.temp(expr.ty.clone(), expr_span); unpack!(block = this.into(&temp, block, expr)); unpack!(block = this.build_drop(block, expr_span, temp, expr_ty)); block.unit() diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 705eb1f56608e..ddeec1fe6d0ba 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -710,7 +710,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { mutability: mutability, ty: var_ty.clone(), name: Some(name), - source_info: Some(source_info), + source_info: source_info, + is_user_variable: true, }); self.var_indices.insert(var_id, var); diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index f4fdf8ade900a..5fece4d6a5d23 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -210,7 +210,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { debug!("num_enum_variants: {}, tested variants: {:?}, variants: {:?}", num_enum_variants, values, variants); let discr_ty = adt_def.repr.discr_type().to_ty(tcx); - let discr = self.temp(discr_ty); + let discr = self.temp(discr_ty, test.span); self.cfg.push_assign(block, source_info, &discr, Rvalue::Discriminant(lvalue.clone())); assert_eq!(values.len() + 1, targets.len()); @@ -270,7 +270,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let ty::TyRef(region, mt) = ty.sty { if let ty::TyArray(_, _) = mt.ty.sty { ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8)); - let val_slice = self.temp(ty); + let val_slice = self.temp(ty, test.span); self.cfg.push_assign(block, source_info, &val_slice, Rvalue::Cast(CastKind::Unsize, val, ty)); val = Operand::Consume(val_slice); @@ -285,7 +285,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value: value.clone() }); - let slice = self.temp(ty); + let slice = self.temp(ty, test.span); self.cfg.push_assign(block, source_info, &slice, Rvalue::Cast(CastKind::Unsize, array, ty)); Operand::Consume(slice) @@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty]); let bool_ty = self.hir.bool_ty(); - let eq_result = self.temp(bool_ty); + let eq_result = self.temp(bool_ty, test.span); let eq_block = self.cfg.start_new_block(); let cleanup = self.diverge_cleanup(); self.cfg.terminate(block, source_info, TerminatorKind::Call { @@ -349,7 +349,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { TestKind::Len { len, op } => { let (usize_ty, bool_ty) = (self.hir.usize_ty(), self.hir.bool_ty()); - let (actual, result) = (self.temp(usize_ty), self.temp(bool_ty)); + let (actual, result) = (self.temp(usize_ty, test.span), + self.temp(bool_ty, test.span)); // actual = len(lvalue) self.cfg.push_assign(block, source_info, @@ -383,7 +384,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { left: Operand<'tcx>, right: Operand<'tcx>) -> BasicBlock { let bool_ty = self.hir.bool_ty(); - let result = self.temp(bool_ty); + let result = self.temp(bool_ty, span); // result = op(left, right) let source_info = self.source_info(span); diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 99aa5cb0fa86e..35a8b245f2bb6 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -27,8 +27,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// /// NB: **No cleanup is scheduled for this temporary.** You should /// call `schedule_drop` once the temporary is initialized. - pub fn temp(&mut self, ty: Ty<'tcx>) -> Lvalue<'tcx> { - let temp = self.local_decls.push(LocalDecl::new_temp(ty)); + pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Lvalue<'tcx> { + let temp = self.local_decls.push(LocalDecl::new_temp(ty, span)); let lvalue = Lvalue::Local(temp); debug!("temp: created temp {:?} with type {:?}", lvalue, self.local_decls[temp].ty); @@ -106,7 +106,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value: u64) -> Lvalue<'tcx> { let usize_ty = self.hir.usize_ty(); - let temp = self.temp(usize_ty); + let temp = self.temp(usize_ty, source_info.span); self.cfg.push_assign_constant( block, source_info, &temp, Constant { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index db03a1c68f715..ef3fa23500b34 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -249,7 +249,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { visibility_scopes: IndexVec::new(), visibility_scope: ARGUMENT_VISIBILITY_SCOPE, breakable_scopes: vec![], - local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty), 1), + local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty, + span), 1), var_indices: NodeMap(), unit_temp: None, cached_resume_block: None, @@ -304,8 +305,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.local_decls.push(LocalDecl { mutability: Mutability::Not, ty: ty, - source_info: None, + source_info: SourceInfo { + scope: ARGUMENT_VISIBILITY_SCOPE, + span: pattern.map_or(self.fn_span, |pat| pat.span) + }, name: name, + is_user_variable: false, }); } @@ -341,7 +346,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Some(ref tmp) => tmp.clone(), None => { let ty = self.hir.unit_ty(); - let tmp = self.temp(ty); + let fn_span = self.fn_span; + let tmp = self.temp(ty, fn_span); self.unit_temp = Some(tmp.clone()); tmp } diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index eb16812af9b02..bb07081fe433b 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -244,6 +244,39 @@ let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; ``` "##, +E0161: r##" +A value was moved. However, its size was not known at compile time, and only +values of a known size can be moved. + +Erroneous code example: + +```compile_fail +#![feature(box_syntax)] + +fn main() { + let array: &[isize] = &[1, 2, 3]; + let _x: Box<[isize]> = box *array; + // error: cannot move a value of type [isize]: the size of [isize] cannot + // be statically determined +} +``` + +In Rust, you can only move a value when its size is known at compile time. + +To work around this restriction, consider "hiding" the value behind a reference: +either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move +it around as usual. Example: + +``` +#![feature(box_syntax)] + +fn main() { + let array: &[isize] = &[1, 2, 3]; + let _x: Box<&[isize]> = box array; // ok! +} +``` +"##, + E0396: r##" The value behind a raw pointer can't be determined at compile-time (or even link-time), which means it can't be used in a constant diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 63d20be88feee..0cec84d16a81c 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -137,16 +137,20 @@ enum CallKind { Direct(DefId), } -fn temp_decl(mutability: Mutability, ty: Ty) -> LocalDecl { - LocalDecl { mutability, ty, name: None, source_info: None } +fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl { + LocalDecl { + mutability, ty, name: None, + source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span }, + is_user_variable: false + } } -fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>) +fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span) -> IndexVec> { - iter::once(temp_decl(Mutability::Mut, sig.output())) + iter::once(temp_decl(Mutability::Mut, sig.output(), span)) .chain(sig.inputs().iter().map( - |ity| temp_decl(Mutability::Not, ity))) + |ity| temp_decl(Mutability::Not, ity, span))) .collect() } @@ -188,7 +192,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, ), IndexVec::new(), sig.output(), - local_decls_for_sig(&sig), + local_decls_for_sig(&sig, span), sig.inputs().len(), vec![], span @@ -297,7 +301,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, debug!("build_call_shim: sig={:?}", sig); - let mut local_decls = local_decls_for_sig(&sig); + let mut local_decls = local_decls_for_sig(&sig, span); let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE }; let rcvr_arg = Local::new(1+0); @@ -317,7 +321,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, tcx.mk_ref(re_erased, ty::TypeAndMut { ty: sig.inputs()[0], mutbl: hir::Mutability::MutMutable - }) + }), + span )); statements.push(Statement { source_info: source_info, @@ -442,7 +447,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, debug!("build_ctor: def_id={:?} sig={:?} fields={:?}", def_id, sig, fields); - let local_decls = local_decls_for_sig(&sig); + let local_decls = local_decls_for_sig(&sig, span); let source_info = SourceInfo { span: span, diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 80a9c06f11b28..ac2bdaad24f76 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -461,11 +461,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { for loc in callee_mir.vars_and_temps_iter() { let mut local = callee_mir.local_decls[loc].clone(); - if let Some(ref mut source_info) = local.source_info { - source_info.scope = scope_map[source_info.scope]; - - source_info.span = callsite.location.span; - } + local.source_info.scope = scope_map[local.source_info.scope]; + local.source_info.span = callsite.location.span; let idx = caller_mir.local_decls.push(local); local_map.push(idx); @@ -506,7 +503,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let ty = dest.ty(caller_mir, self.tcx); - let temp = LocalDecl::new_temp(ty); + let temp = LocalDecl::new_temp(ty, callsite.location.span); let tmp = caller_mir.local_decls.push(temp); let tmp = Lvalue::Local(tmp); @@ -590,7 +587,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { arg.deref()); let ty = arg.ty(caller_mir, self.tcx); - let ref_tmp = LocalDecl::new_temp(ty); + let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span); let ref_tmp = caller_mir.local_decls.push(ref_tmp); let ref_tmp = Lvalue::Local(ref_tmp); @@ -611,7 +608,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Consume(ref_tmp), ptr_ty); - let cast_tmp = LocalDecl::new_temp(ptr_ty); + let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span); let cast_tmp = caller_mir.local_decls.push(cast_tmp); let cast_tmp = Lvalue::Local(cast_tmp); @@ -645,7 +642,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let ty = arg.ty(caller_mir, tcx); - let arg_tmp = LocalDecl::new_temp(ty); + let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span); let arg_tmp = caller_mir.local_decls.push(arg_tmp); let arg_tmp = Lvalue::Local(arg_tmp); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 57cf4b1e8b02b..ed9a0d3809f24 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -208,7 +208,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let no_stmts = self.source[loc.block].statements.len(); let new_temp = self.promoted.local_decls.push( - LocalDecl::new_temp(self.source.local_decls[temp].ty)); + LocalDecl::new_temp(self.source.local_decls[temp].ty, + self.source.local_decls[temp].source_info.span)); debug!("promote({:?} @ {:?}/{:?}, {:?})", temp, loc, no_stmts, self.keep_original); @@ -379,7 +380,8 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, }; // Declare return pointer local - let initial_locals = iter::once(LocalDecl::new_return_pointer(ty)).collect(); + let initial_locals = iter::once(LocalDecl::new_return_pointer(ty, span)) + .collect(); let mut promoter = Promoter { promoted: Mir::new( diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 8eabe92fb98c0..1313b24fa74f5 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -881,7 +881,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Avoid a generic error for other uses of arguments. if self.qualif.intersects(Qualif::FN_ARGUMENT) { let decl = &self.mir.local_decls[index]; - span_err!(self.tcx.sess, decl.source_info.unwrap().span, E0022, + span_err!(self.tcx.sess, decl.source_info.span, E0022, "arguments of constant functions can only \ be immutable by-value bindings"); return; diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 3d604affbfea9..bfb08de56d8bb 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -24,6 +24,7 @@ use std::fmt; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::Idx; fn mirbug(tcx: TyCtxt, span: Span, msg: &str) { @@ -87,6 +88,11 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.sanitize_type(rvalue, rval_ty); } + fn visit_local_decl(&mut self, local_decl: &LocalDecl<'tcx>) { + self.super_local_decl(local_decl); + self.sanitize_type(local_decl, local_decl.ty); + } + fn visit_mir(&mut self, mir: &Mir<'tcx>) { self.sanitize_type(&"return type", mir.return_ty); for local_decl in &mir.local_decls { @@ -317,6 +323,7 @@ pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { fulfillment_cx: traits::FulfillmentContext<'tcx>, last_span: Span, body_id: ast::NodeId, + reported_errors: FxHashSet<(Ty<'tcx>, Span)>, } impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { @@ -326,6 +333,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { fulfillment_cx: traits::FulfillmentContext::new(), last_span: DUMMY_SP, body_id: body_id, + reported_errors: FxHashSet(), } } @@ -641,9 +649,43 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn typeck_mir(&mut self, mir: &Mir<'tcx>) { + fn check_local(&mut self, mir: &Mir<'gcx>, local: Local, local_decl: &LocalDecl<'gcx>) { + match mir.local_kind(local) { + LocalKind::ReturnPointer | LocalKind::Arg => { + // return values of normal functions are required to be + // sized by typeck, but return values of ADT constructors are + // not because we don't include a `Self: Sized` bounds on them. + // + // Unbound parts of arguments were never required to be Sized + // - maybe we should make that a warning. + return + } + LocalKind::Var | LocalKind::Temp => {} + } + + let span = local_decl.source_info.span; + let ty = local_decl.ty; + if !ty.is_sized(self.tcx().global_tcx(), self.infcx.param_env(), span) { + // in current MIR construction, all non-control-flow rvalue + // expressions evaluate through `as_temp` or `into` a return + // slot or local, so to find all unsized rvalues it is enough + // to check all temps, return slots and locals. + if let None = self.reported_errors.replace((ty, span)) { + span_err!(self.tcx().sess, span, E0161, + "cannot move a value of type {0}: the size of {0} \ + cannot be statically determined", ty); + } + } + } + + fn typeck_mir(&mut self, mir: &Mir<'gcx>) { self.last_span = mir.span; debug!("run_on_mir: {:?}", mir.span); + + for (local, local_decl) in mir.local_decls.iter_enumerated() { + self.check_local(mir, local, local_decl); + } + for block in mir.basic_blocks() { for stmt in &block.statements { if stmt.source_info.span != DUMMY_SP { @@ -698,16 +740,18 @@ impl TypeckMir { impl<'tcx> MirPass<'tcx> for TypeckMir { fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) { - debug!("run_pass: {}", tcx.node_path_str(src.item_id())); + let item_id = src.item_id(); + let def_id = tcx.hir.local_def_id(item_id); + debug!("run_pass: {}", tcx.item_path_str(def_id)); if tcx.sess.err_count() > 0 { // compiling a broken program can obviously result in a // broken MIR, so try not to report duplicate errors. return; } - let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id()); + let param_env = ty::ParameterEnvironment::for_item(tcx, item_id); tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| { - let mut checker = TypeChecker::new(&infcx, src.item_id()); + let mut checker = TypeChecker::new(&infcx, item_id); { let mut verifier = TypeVerifier::new(&mut checker, mir); verifier.visit_mir(mir); diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index ccbc6700d89c1..04a1fc891cf1e 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -686,7 +686,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> } fn new_temp(&mut self, ty: Ty<'tcx>) -> Local { - self.elaborator.patch().new_temp(ty) + self.elaborator.patch().new_temp(ty, self.source_info.span) } fn terminator_loc(&mut self, bb: BasicBlock) -> Location { diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 19f240da73059..7898d93c22e3b 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -11,6 +11,7 @@ use rustc::ty::Ty; use rustc::mir::*; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use syntax_pos::Span; /// This struct represents a patch to MIR, which can add /// new statements and basic blocks and patch over block @@ -92,10 +93,10 @@ impl<'tcx> MirPatch<'tcx> { } } - pub fn new_temp(&mut self, ty: Ty<'tcx>) -> Local { + pub fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local { let index = self.next_local; self.next_local += 1; - self.new_locals.push(LocalDecl::new_temp(ty)); + self.new_locals.push(LocalDecl::new_temp(ty, span)); Local::new(index as usize) } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index ef2bf6e543420..b202e1495104e 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -196,8 +196,8 @@ fn write_scope_tree(tcx: TyCtxt, // User variable types (including the user's name in a comment). for local in mir.vars_iter() { let var = &mir.local_decls[local]; - let (name, source_info) = if var.source_info.unwrap().scope == child { - (var.name.unwrap(), var.source_info.unwrap()) + let (name, source_info) = if var.source_info.scope == child { + (var.name.unwrap(), var.source_info) } else { // Not a variable or not declared in this scope. continue; diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 5f06eadb84a92..036a52d5a3db3 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -82,39 +82,6 @@ extern { ``` "##, -E0161: r##" -A value was moved. However, its size was not known at compile time, and only -values of a known size can be moved. - -Erroneous code example: - -```compile_fail -#![feature(box_syntax)] - -fn main() { - let array: &[isize] = &[1, 2, 3]; - let _x: Box<[isize]> = box *array; - // error: cannot move a value of type [isize]: the size of [isize] cannot - // be statically determined -} -``` - -In Rust, you can only move a value when its size is known at compile time. - -To work around this restriction, consider "hiding" the value behind a reference: -either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move -it around as usual. Example: - -``` -#![feature(box_syntax)] - -fn main() { - let array: &[isize] = &[1, 2, 3]; - let _x: Box<&[isize]> = box array; // ok! -} -``` -"##, - E0265: r##" This error indicates that a static or constant references itself. All statics and constants need to resolve to a value in an acyclic manner. diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 7a465f0ec4239..22566c813d86a 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -47,5 +47,4 @@ pub mod hir_stats; pub mod loops; pub mod mir_stats; pub mod no_asm; -pub mod rvalues; pub mod static_recursion; diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 421181c68c4cd..2ea235af10378 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -11,7 +11,6 @@ use self::Context::*; use rustc::session::Session; -use rustc::dep_graph::DepNode; use rustc::hir::map::Map; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir; @@ -50,7 +49,6 @@ struct CheckLoopVisitor<'a, 'hir: 'a> { } pub fn check_crate(sess: &Session, map: &Map) { - let _task = map.dep_graph.in_task(DepNode::CheckLoops); let krate = map.krate(); krate.visit_all_item_likes(&mut CheckLoopVisitor { sess: sess, diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs deleted file mode 100644 index c367e71fcd246..0000000000000 --- a/src/librustc_passes/rvalues.rs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2014 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Checks that all rvalues in a crate have statically known size. check_crate -// is the public starting point. - -use rustc::dep_graph::DepNode; -use rustc::middle::expr_use_visitor as euv; -use rustc::middle::mem_categorization as mc; -use rustc::ty::{self, TyCtxt}; -use rustc::traits::Reveal; - -use rustc::hir; -use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; -use syntax::ast; -use syntax_pos::Span; - -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let mut rvcx = RvalueContext { tcx: tcx }; - tcx.visit_all_item_likes_in_krate(DepNode::RvalueCheck, &mut rvcx.as_deep_visitor()); -} - -struct RvalueContext<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, -} - -impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_nested_body(&mut self, body_id: hir::BodyId) { - let body = self.tcx.hir.body(body_id); - self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| { - let mut delegate = RvalueContextDelegate { - tcx: infcx.tcx, - param_env: &infcx.parameter_environment - }; - euv::ExprUseVisitor::new(&mut delegate, &infcx).consume_body(body); - }); - self.visit_body(body); - } -} - -struct RvalueContextDelegate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx>, - param_env: &'a ty::ParameterEnvironment<'gcx>, -} - -impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'gcx, 'tcx> { - fn consume(&mut self, - _: ast::NodeId, - span: Span, - cmt: mc::cmt<'tcx>, - _: euv::ConsumeMode) { - debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty); - let ty = self.tcx.lift_to_global(&cmt.ty).unwrap(); - if !ty.is_sized(self.tcx.global_tcx(), self.param_env, span) { - span_err!(self.tcx.sess, span, E0161, - "cannot move a value of type {0}: the size of {0} cannot be statically determined", - ty); - } - } - - fn matched_pat(&mut self, - _matched_pat: &hir::Pat, - _cmt: mc::cmt, - _mode: euv::MatchMode) {} - - fn consume_pat(&mut self, - _consume_pat: &hir::Pat, - _cmt: mc::cmt, - _mode: euv::ConsumeMode) { - } - - fn borrow(&mut self, - _borrow_id: ast::NodeId, - _borrow_span: Span, - _cmt: mc::cmt, - _loan_region: &'tcx ty::Region, - _bk: ty::BorrowKind, - _loan_cause: euv::LoanCause) { - } - - fn decl_without_init(&mut self, - _id: ast::NodeId, - _span: Span) { - } - - fn mutate(&mut self, - _assignment_id: ast::NodeId, - _assignment_span: Span, - _assignee_cmt: mc::cmt, - _mode: euv::MutateMode) { - } -} diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index fc05471ead30b..d0bf49b7b337d 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -11,7 +11,6 @@ // This compiler pass detects constants that refer to themselves // recursively. -use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; use rustc::session::{CompileResult, Session}; use rustc::hir::def::{Def, CtorKind}; @@ -88,8 +87,6 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> { } pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) -> CompileResult { - let _task = hir_map.dep_graph.in_task(DepNode::CheckStaticRecursion); - let mut visitor = CheckCrateVisitor { sess: sess, hir_map: hir_map, diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 7be80a757ca01..c4fdc46d030c9 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -283,7 +283,7 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> { Layout::Vector { .. } => { Some(Reg { - kind: RegKind::Integer, + kind: RegKind::Vector, size: self.size(ccx) }) } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 66380079a8b29..0ffa7a79408e1 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -443,7 +443,10 @@ fn archive_config<'a>(sess: &'a Session, } fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, out_filename: &Path) { - let result = fs::File::create(out_filename).and_then(|mut f| f.write_all(&trans.metadata)); + let result = fs::File::create(out_filename).and_then(|mut f| { + f.write_all(&trans.metadata.raw_data) + }); + if let Err(e) = result { sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 574b345218be9..f76e816bcf0c9 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -36,6 +36,7 @@ use llvm::{Linkage, ValueRef, Vector, get_param}; use llvm; use rustc::hir::def_id::LOCAL_CRATE; use middle::lang_items::StartFnLangItem; +use middle::cstore::EncodedMetadata; use rustc::ty::{self, Ty, TyCtxt}; use rustc::dep_graph::{AssertDepGraphSafe, DepNode, WorkProduct}; use rustc::hir::map as hir_map; @@ -724,7 +725,8 @@ fn contains_null(s: &str) -> bool { } fn write_metadata(cx: &SharedCrateContext, - exported_symbols: &NodeSet) -> Vec { + exported_symbols: &NodeSet) + -> EncodedMetadata { use flate; #[derive(PartialEq, Eq, PartialOrd, Ord)] @@ -748,7 +750,10 @@ fn write_metadata(cx: &SharedCrateContext, }).max().unwrap(); if kind == MetadataKind::None { - return Vec::new(); + return EncodedMetadata { + raw_data: vec![], + hashes: vec![], + }; } let cstore = &cx.tcx().sess.cstore; @@ -761,7 +766,7 @@ fn write_metadata(cx: &SharedCrateContext, assert!(kind == MetadataKind::Compressed); let mut compressed = cstore.metadata_encoding_version().to_vec(); - compressed.extend_from_slice(&flate::deflate_bytes(&metadata)); + compressed.extend_from_slice(&flate::deflate_bytes(&metadata.raw_data)); let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed); let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false); diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs index cbe170d85834c..2daebf5cf3d6b 100644 --- a/src/librustc_trans/cabi_x86_64.rs +++ b/src/librustc_trans/cabi_x86_64.rs @@ -173,14 +173,15 @@ fn reg_component(cls: &[Class], i: &mut usize, size: u64) -> Option { Class::Sse => { let vec_len = 1 + cls[*i+1..].iter().take_while(|&&c| c == Class::SseUp).count(); *i += vec_len; - Some(match size { - 4 => Reg::f32(), - 8 => Reg::f64(), - _ => { - Reg { - kind: RegKind::Vector, - size: Size::from_bytes(vec_len as u64 * 8) - } + Some(if vec_len == 1 { + match size { + 4 => Reg::f32(), + _ => Reg::f64() + } + } else { + Reg { + kind: RegKind::Vector, + size: Size::from_bytes(vec_len as u64 * 8) } }) } diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs index c6f8ba7b6dc78..3d074c31c8a32 100644 --- a/src/librustc_trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/debuginfo/create_scope_map.rs @@ -65,7 +65,7 @@ pub fn create_mir_scopes(ccx: &CrateContext, mir: &Mir, debug_context: &Function let mut has_variables = BitVector::new(mir.visibility_scopes.len()); for var in mir.vars_iter() { let decl = &mir.local_decls[var]; - has_variables.insert(decl.source_info.unwrap().scope.index()); + has_variables.insert(decl.source_info.scope.index()); } // Instantiate all scopes. diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 5c3b17c889760..628d46f8e7059 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -168,7 +168,7 @@ pub struct CrateTranslation { pub modules: Vec, pub metadata_module: ModuleTranslation, pub link: middle::cstore::LinkMeta, - pub metadata: Vec, + pub metadata: middle::cstore::EncodedMetadata, pub exported_symbols: back::symbol_export::ExportedSymbols, pub no_builtins: bool, pub windows_subsystem: Option, diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index f4c9a136ace3c..c51e1fb002803 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -255,8 +255,7 @@ pub fn trans_mir<'a, 'tcx: 'a>( if let Some(name) = decl.name { // User variable - let source_info = decl.source_info.unwrap(); - let debug_scope = mircx.scopes[source_info.scope]; + let debug_scope = mircx.scopes[decl.source_info.scope]; let dbg = debug_scope.is_valid() && bcx.sess().opts.debuginfo == FullDebugInfo; if !lvalue_locals.contains(local.index()) && !dbg { @@ -268,7 +267,7 @@ pub fn trans_mir<'a, 'tcx: 'a>( assert!(!ty.has_erasable_regions()); let lvalue = LvalueRef::alloca(&bcx, ty, &name.as_str()); if dbg { - let (scope, span) = mircx.debug_loc(source_info); + let (scope, span) = mircx.debug_loc(decl.source_info); declare_local(&bcx, &mircx.debug_context, name, ty, scope, VariableAccess::DirectVariable { alloca: lvalue.llval }, VariableKind::LocalVariable, span); diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 052340a0f253a..61ff8daddf0a6 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -406,7 +406,7 @@ mod prim_slice { } /// /// This documentation describes a number of methods and trait implementations /// on the `str` type. For technical reasons, there is additional, separate -/// documentation in [the `std::str` module](str/index.html) as well. +/// documentation in the [`std::str`](str/index.html) module as well. /// /// # Examples /// @@ -425,7 +425,7 @@ mod prim_slice { } /// # Representation /// /// A `&str` is made up of two components: a pointer to some bytes, and a -/// length. You can look at these with the [`.as_ptr`] and [`len`] methods: +/// length. You can look at these with the [`as_ptr`] and [`len`] methods: /// /// ``` /// use std::slice; @@ -452,11 +452,11 @@ mod prim_slice { } /// assert_eq!(s, Ok(story)); /// ``` /// -/// [`.as_ptr`]: #method.as_ptr +/// [`as_ptr`]: #method.as_ptr /// [`len`]: #method.len /// /// Note: This example shows the internals of `&str`. `unsafe` should not be -/// used to get a string slice under normal circumstances. Use `.as_slice()` +/// used to get a string slice under normal circumstances. Use `as_slice` /// instead. #[stable(feature = "rust1", since = "1.0.0")] mod prim_str { } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 58be43526fd9d..3b928ea93c78a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2552,10 +2552,10 @@ impl<'a> Parser<'a> { } token::Literal(token::Float(n), _suf) => { self.bump(); - let prev_span = self.prev_span; let fstr = n.as_str(); - let mut err = self.diagnostic().struct_span_err(prev_span, + let mut err = self.diagnostic().struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n)); + err.span_label(self.prev_span, &"unexpected token"); if fstr.chars().all(|x| "0123456789.".contains(x)) { let float = match fstr.parse::().ok() { Some(f) => f, @@ -2573,7 +2573,7 @@ impl<'a> Parser<'a> { word(&mut s.s, fstr.splitn(2, ".").last().unwrap()) }); err.span_suggestion( - prev_span, + lo.to(self.prev_span), "try parenthesizing the first index", sugg); } diff --git a/src/test/compile-fail/issue-41139.rs b/src/test/compile-fail/issue-41139.rs new file mode 100644 index 0000000000000..15ca151c49a79 --- /dev/null +++ b/src/test/compile-fail/issue-41139.rs @@ -0,0 +1,18 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Trait {} + +fn get_function<'a>() -> &'a Fn() -> Trait { panic!("") } + +fn main() { + let t : &Trait = &get_function()(); + //~^ ERROR cannot move a value of type Trait + 'static +} diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 048ccb529a24f..37c6ef58f5e56 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -38,8 +38,13 @@ enum EnumVisibility { A } #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -pub enum EnumVisibility { A } +pub enum EnumVisibility { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + A +} @@ -56,7 +61,10 @@ enum EnumChangeNameCStyleVariant { #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeNameCStyleVariant { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] Variant1, + #[rustc_metadata_clean(cfg="cfail3")] Variant2Changed, } @@ -259,10 +267,13 @@ enum EnumChangeFieldTypeTupleStyleVariant { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeFieldTypeTupleStyleVariant { - Variant1(u32, u64), + Variant1(u32, + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + u64), } @@ -277,11 +288,16 @@ enum EnumChangeFieldTypeStructStyleVariant { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeFieldTypeStructStyleVariant { Variant1, - Variant2 { a: u32, b: u64 }, + Variant2 { + a: u32, + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + b: u64 + }, } @@ -312,10 +328,16 @@ enum EnumChangeOrderTupleStyleVariant { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumChangeOrderTupleStyleVariant { - Variant1(u64, u32), + Variant1( + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + u64, + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + u32), } @@ -611,11 +633,23 @@ enum EnumSwapUsageTypeParameters { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumSwapUsageTypeParameters { - Variant1 { a: B }, - Variant2 { a: A }, + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + Variant1 { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + a: B + }, + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + Variant2 { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + a: A + }, } @@ -630,11 +664,23 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { - Variant1 { a: &'b u32 }, - Variant2 { b: &'a u32 }, + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + Variant1 { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + a: &'b u32 + }, + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + Variant2 { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + b: &'a u32 + }, } @@ -653,10 +699,16 @@ mod change_field_type_indirectly_tuple_style { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum TupleStyle { - Variant1(FieldType) + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + Variant1( + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + FieldType + ) } } @@ -671,10 +723,16 @@ mod change_field_type_indirectly_struct_style { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] enum StructStyle { - Variant1 { a: FieldType } + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + Variant1 { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + a: FieldType + } } } diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs index 03e621fedbeb4..1d26e6c07d15b 100644 --- a/src/test/incremental/hashes/extern_mods.rs +++ b/src/test/incremental/hashes/extern_mods.rs @@ -53,9 +53,11 @@ extern { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn change_parameter_name(d: i64) -> i32; } @@ -70,9 +72,11 @@ extern { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn change_parameter_type(c: i32) -> i32; } @@ -87,9 +91,11 @@ extern { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn change_return_type(c: i32) -> i8; } @@ -104,9 +110,11 @@ extern { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn add_parameter(c: i32, d: i32) -> i32; } @@ -121,9 +129,11 @@ extern { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn add_return_type(c: i32) -> i32; } @@ -138,9 +148,11 @@ extern { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn make_function_variadic(c: i32, ...); } @@ -155,9 +167,11 @@ extern "C" { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern "rust-call" { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn change_calling_convention(c: i32); } @@ -172,9 +186,11 @@ extern { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn make_function_public(c: i32); } @@ -246,9 +262,11 @@ mod indirectly_change_parameter_type { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn indirectly_change_parameter_type(c: c_int); } } @@ -264,9 +282,11 @@ mod indirectly_change_return_type { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] extern { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] pub fn indirectly_change_return_type() -> c_int; } } diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 93d94cd1a19c4..2fe3f0d5d1fe0 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -50,7 +50,7 @@ fn add_return_type() {} #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] // The type doesn't change, so metadata is the same #[rustc_metadata_clean(cfg="cfail3")] fn add_return_type() -> () {} @@ -154,7 +154,7 @@ fn lifetime_parameter() {} #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +// #[rustc_metadata_dirty(cfg="cfail2")] -- Unused lifetime params don't show up in the type? #[rustc_metadata_clean(cfg="cfail3")] fn lifetime_parameter<'a>() {} @@ -315,16 +315,16 @@ fn return_impl_trait() -> impl Clone { #[cfg(cfail1)] fn change_return_impl_trait() -> impl Clone { - 0 + 0u32 } #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] // The actual type is the same, so: clean #[rustc_metadata_clean(cfg="cfail3")] fn change_return_impl_trait() -> impl Copy { - 0 + 0u32 } diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index fd9ac61046e3a..899aefa24a033 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -107,7 +107,7 @@ impl Foo { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -126,7 +126,7 @@ impl Foo { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl Foo { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -171,7 +171,7 @@ impl Foo { impl Foo { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_method_to_impl1(&self) { } @@ -219,9 +219,7 @@ impl Foo { #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_dirty(label="HirBody", cfg="cfail2")] #[rustc_clean(label="HirBody", cfg="cfail3")] - // At the moment we explicitly ignore argument names in metadata, since they - // are not used in downstream crates (except in rustdoc) - #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_method_parameter_name(&self, b: i64) { } } @@ -287,9 +285,7 @@ impl Foo { #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_dirty(label="HirBody", cfg="cfail2")] #[rustc_clean(label="HirBody", cfg="cfail3")] - // At the moment we explicitly ignore argument names in metadata, since they - // are not used in downstream crates (except in rustdoc) - #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn change_method_parameter_order(&self, b: i64, a: i64) { } } @@ -373,7 +369,7 @@ impl Foo { impl Foo { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] // Apparently unused lifetimes don't show up in the type. #[rustc_metadata_clean(cfg="cfail3")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -544,7 +540,7 @@ impl Bar { impl Bar { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_impl_parameter(&self) { } } @@ -565,7 +561,7 @@ impl Bar { impl Bar { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub fn add_trait_bound_to_impl_parameter(&self) { } } diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index 2d79987823f20..17a5dc1678367 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -62,9 +62,13 @@ struct TupleStructFieldType(i32); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct TupleStructFieldType(u32); +struct TupleStructFieldType( + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + u32 +); // Tuple Struct Add Field ------------------------------------------------------ @@ -77,7 +81,13 @@ struct TupleStructAddField(i32); #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct TupleStructAddField(i32, u32); +struct TupleStructAddField( + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + i32, + #[rustc_metadata_clean(cfg="cfail3")] + u32 +); // Tuple Struct Field Visibility ----------------------------------------------- @@ -101,9 +111,13 @@ struct RecordStructFieldType { x: f32 } #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct RecordStructFieldType { x: u64 } +struct RecordStructFieldType { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + x: u64 +} // Record Struct Field Name ---------------------------------------------------- @@ -129,7 +143,12 @@ struct RecordStructAddField { x: f32 } #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct RecordStructAddField { x: f32, y: () } +struct RecordStructAddField { + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + x: f32, + #[rustc_metadata_clean(cfg="cfail3")] + y: () } // Record Struct Field Visibility ---------------------------------------------- @@ -142,7 +161,11 @@ struct RecordStructFieldVisibility { x: f32 } #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct RecordStructFieldVisibility { pub x: f32 } +struct RecordStructFieldVisibility { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + pub x: f32 +} // Add Lifetime Parameter ------------------------------------------------------ @@ -168,7 +191,14 @@ struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64); #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct AddLifetimeParameterBound<'a, 'b: 'a>(&'a f32, &'b f64); +struct AddLifetimeParameterBound<'a, 'b: 'a>( + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + &'a f32, + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + &'b f64 +); #[cfg(cfail1)] struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); @@ -178,7 +208,13 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64) +struct AddLifetimeParameterBoundWhereClause<'a, 'b>( + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + &'a f32, + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + &'b f64) where 'b: 'a; @@ -192,7 +228,16 @@ struct AddTypeParameter(T1, T1); #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct AddTypeParameter(T1, T2); +struct AddTypeParameter( + // The field contains the parent's Generics, so it's dirty even though its + // type hasn't changed. + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + T1, + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + T2 +); // Add Type Parameter Bound ---------------------------------------------------- @@ -205,7 +250,11 @@ struct AddTypeParameterBound(T); #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct AddTypeParameterBound(T); +struct AddTypeParameterBound( + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + T +); #[cfg(cfail1)] @@ -216,7 +265,11 @@ struct AddTypeParameterBoundWhereClause(T); #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] -struct AddTypeParameterBoundWhereClause(T) where T: Sync; +struct AddTypeParameterBoundWhereClause( + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + T +) where T: Sync; // Empty struct ---------------------------------------------------------------- @@ -234,6 +287,7 @@ struct Visibility; #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub struct Visibility; @@ -252,9 +306,13 @@ mod tuple_struct_change_field_type_indirectly { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] - struct TupleStruct(FieldType); + struct TupleStruct( + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + FieldType + ); } @@ -267,9 +325,11 @@ mod record_struct_change_field_type_indirectly { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] struct RecordStruct { + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] _x: FieldType } } diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 94698506ec53f..61a2be054a51a 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -100,7 +100,7 @@ trait TraitAddReturnType { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddReturnType { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -121,7 +121,7 @@ trait TraitChangeReturnType { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeReturnType { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -142,7 +142,7 @@ trait TraitAddParameterToMethod { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddParameterToMethod { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -164,7 +164,7 @@ trait TraitChangeMethodParameterName { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeMethodParameterName { // FIXME(#38501) This should preferably always be clean. @@ -194,7 +194,7 @@ trait TraitChangeMethodParameterType { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeMethodParameterType { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -215,7 +215,7 @@ trait TraitChangeMethodParameterTypeRef { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeMethodParameterTypeRef { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -236,7 +236,7 @@ trait TraitChangeMethodParametersOrder { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeMethodParametersOrder { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -257,9 +257,13 @@ trait TraitAddMethodDefaultImplementation { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddMethodDefaultImplementation { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method() { } } @@ -293,7 +297,7 @@ trait TraitChangeModeSelfRefToMut { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeModeSelfRefToMut { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -335,7 +339,7 @@ trait TraitChangeModeSelfOwnToRef { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeModeSelfOwnToRef { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -356,7 +360,7 @@ trait TraitAddUnsafeModifier { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddUnsafeModifier { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -377,7 +381,7 @@ trait TraitAddExternModifier { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddExternModifier { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -398,7 +402,7 @@ trait TraitChangeExternCToRustIntrinsic { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeExternCToRustIntrinsic { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -419,7 +423,7 @@ trait TraitAddTypeParameterToMethod { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddTypeParameterToMethod { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -440,12 +444,12 @@ trait TraitAddLifetimeParameterToMethod { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddLifetimeParameterToMethod { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] // Unused lifetimes don't seem to show up in type? #[rustc_metadata_clean(cfg="cfail3")] fn method<'a>(); } @@ -465,7 +469,7 @@ trait TraitAddTraitBoundToMethodTypeParameter { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddTraitBoundToMethodTypeParameter { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -486,7 +490,7 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddBuiltinBoundToMethodTypeParameter { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -507,7 +511,7 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -528,7 +532,7 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddSecondTraitBoundToMethodTypeParameter { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -549,7 +553,7 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -570,7 +574,7 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -585,7 +589,12 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { // Add associated type ------------------------------------------------------------ #[cfg(cfail1)] trait TraitAddAssociatedType { - fn mathod(); + + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method(); } #[cfg(not(cfail1))] @@ -596,7 +605,7 @@ trait TraitAddAssociatedType { trait TraitAddAssociatedType { type Associated; - fn mathod(); + fn method(); } @@ -606,9 +615,12 @@ trait TraitAddAssociatedType { trait TraitAddTraitBoundToAssociatedType { type Associated; - fn mathod(); + fn method(); } + +// Apparently the type bound contributes to the predicates of the trait, but +// does not change the associated item itself. #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] @@ -617,11 +629,11 @@ trait TraitAddTraitBoundToAssociatedType { trait TraitAddTraitBoundToAssociatedType { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] type Associated: ReferencedTrait0; - fn mathod(); + fn method(); } @@ -631,7 +643,7 @@ trait TraitAddTraitBoundToAssociatedType { trait TraitAddLifetimeBoundToAssociatedType<'a> { type Associated; - fn mathod(); + fn method(); } #[cfg(not(cfail1))] @@ -642,11 +654,11 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { trait TraitAddLifetimeBoundToAssociatedType<'a> { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] type Associated: 'a; - fn mathod(); + fn method(); } @@ -656,18 +668,22 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { trait TraitAddDefaultToAssociatedType { type Associated; - fn mathod(); + fn method(); } #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddDefaultToAssociatedType { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] type Associated = ReferenceType0; - fn mathod(); + fn method(); } @@ -675,7 +691,7 @@ trait TraitAddDefaultToAssociatedType { // Add associated constant -------------------------------------------------------- #[cfg(cfail1)] trait TraitAddAssociatedConstant { - fn mathod(); + fn method(); } #[cfg(not(cfail1))] @@ -686,7 +702,7 @@ trait TraitAddAssociatedConstant { trait TraitAddAssociatedConstant { const Value: u32; - fn mathod(); + fn method(); } @@ -696,18 +712,26 @@ trait TraitAddAssociatedConstant { trait TraitAddInitializerToAssociatedConstant { const Value: u32; - fn mathod(); + fn method(); } #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitAddInitializerToAssociatedConstant { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] const Value: u32 = 1; - fn mathod(); + #[rustc_clean(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method(); } @@ -717,13 +741,13 @@ trait TraitAddInitializerToAssociatedConstant { trait TraitChangeTypeOfAssociatedConstant { const Value: u32; - fn mathod(); + fn method(); } #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeTypeOfAssociatedConstant { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -732,7 +756,11 @@ trait TraitChangeTypeOfAssociatedConstant { #[rustc_metadata_clean(cfg="cfail3")] const Value: f64; - fn mathod(); + #[rustc_clean(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_clean(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method(); } @@ -1111,9 +1139,6 @@ trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send + Sync { } - -// EDIT: Some more cases ---------------------------------------------------------- - // Change return type of method indirectly by modifying a use statement------------ mod change_return_type_of_method_indirectly_use { #[cfg(cfail1)] @@ -1123,7 +1148,7 @@ mod change_return_type_of_method_indirectly_use { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeReturnType { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -1145,7 +1170,7 @@ mod change_method_parameter_type_indirectly_by_use { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeArgType { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -1167,7 +1192,7 @@ mod change_method_parameter_type_bound_indirectly_by_use { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeBoundOfMethodTypeParameter { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -1190,7 +1215,7 @@ mod change_method_parameter_type_bound_indirectly_by_use_where { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] trait TraitChangeBoundOfMethodTypeParameterWhere { #[rustc_dirty(label="Hir", cfg="cfail2")] diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index 30e376f04fb87..06c8eb6a878f0 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -120,7 +120,7 @@ impl ChangeMethodBodyTraitInlined for Foo { #[rustc_metadata_clean(cfg="cfail3")] #[inline] fn method_name() { - () + panic!() } } @@ -144,7 +144,7 @@ pub trait ChangeMethodSelfnessTrait { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl ChangeMethodSelfnessTrait for Foo { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -176,16 +176,14 @@ pub trait RemoveMethodSelfnessTrait { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl RemoveMethodSelfnessTrait for Foo { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] - fn method_name() { - () - } + fn method_name() {} } // Change Method Selfmutness ----------------------------------------------------------- @@ -208,16 +206,14 @@ pub trait ChangeMethodSelfmutnessTrait { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl ChangeMethodSelfmutnessTrait for Foo { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] #[rustc_metadata_dirty(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] - fn method_name(&mut self) { - () - } + fn method_name(&mut self) {} } // Change item kind ----------------------------------------------------------- @@ -317,16 +313,20 @@ impl ChangeHasValueTrait for Foo { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] pub trait ChangeHasValueTrait { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] fn method_name() { } } #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl ChangeHasValueTrait for Foo { fn method_name() { } @@ -346,32 +346,16 @@ impl AddDefaultTrait for Foo { #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl AddDefaultTrait for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] default fn method_name() { } } -// Remove default - -pub trait RemoveDefaultTrait { - fn method_name(); -} - -#[cfg(cfail1)] -impl RemoveDefaultTrait for Foo { - default fn method_name() { } -} - -#[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] -#[rustc_metadata_clean(cfg="cfail3")] -impl RemoveDefaultTrait for Foo { - fn method_name() { } -} - // Add arguments #[cfg(cfail1)] @@ -392,7 +376,7 @@ pub trait AddArgumentTrait { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl AddArgumentTrait for Foo { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -422,7 +406,7 @@ pub trait ChangeArgumentTypeTrait { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] impl ChangeArgumentTypeTrait for Foo { #[rustc_dirty(label="Hir", cfg="cfail2")] @@ -504,7 +488,7 @@ impl AddLifetimeBoundToImplParameter for T { impl AddLifetimeBoundToImplParameter for T { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn id(self) -> Self { self } } @@ -529,7 +513,7 @@ impl AddTraitBoundToImplParameter for T { impl AddTraitBoundToImplParameter for T { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] fn id(self) -> Self { self } } diff --git a/src/test/incremental/unchecked_dirty_clean_metadata.rs b/src/test/incremental/unchecked_dirty_clean_metadata.rs index 4017b4d4ba9ae..917c2c9dbce4f 100644 --- a/src/test/incremental/unchecked_dirty_clean_metadata.rs +++ b/src/test/incremental/unchecked_dirty_clean_metadata.rs @@ -33,13 +33,3 @@ fn main() { } } -struct _Struct { - #[rustc_metadata_dirty(cfg="cfail2")] - //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute - _field1: i32, - - #[rustc_metadata_clean(cfg="cfail2")] - //[cfail2]~^ ERROR found unchecked #[rustc_dirty]/#[rustc_clean] attribute - _field2: i32, -} - diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.c b/src/test/run-make/extern-fn-struct-passing-abi/test.c index 4253767ee76a9..4e09928edc6d1 100644 --- a/src/test/run-make/extern-fn-struct-passing-abi/test.c +++ b/src/test/run-make/extern-fn-struct-passing-abi/test.c @@ -38,6 +38,11 @@ struct Huge { int32_t e; }; +struct FloatPoint { + double x; + double y; +}; + // System V x86_64 ABI: // a, b, c, d, e should be in registers // s should be byval pointer @@ -258,3 +263,17 @@ struct Huge huge_struct(struct Huge s) { return s; } + +// System V x86_64 ABI: +// p should be in registers +// return should be in registers +// +// Win64 ABI: +// p should be a byval pointer +// return should be in a hidden sret pointer +struct FloatPoint float_point(struct FloatPoint p) { + assert(p.x == 5.); + assert(p.y == -3.); + + return p; +} diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.rs b/src/test/run-make/extern-fn-struct-passing-abi/test.rs index b91362b8edccb..ff845a644b114 100644 --- a/src/test/run-make/extern-fn-struct-passing-abi/test.rs +++ b/src/test/run-make/extern-fn-struct-passing-abi/test.rs @@ -46,6 +46,13 @@ struct Huge { e: i32 } +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +struct FloatPoint { + x: f64, + y: f64 +} + #[link(name = "test", kind = "static")] extern { fn byval_rect(a: i32, b: i32, c: i32, d: i32, e: i32, s: Rect); @@ -72,6 +79,8 @@ extern { fn sret_split_struct(a: i32, b: i32, s: Rect) -> BiggerRect; fn huge_struct(s: Huge) -> Huge; + + fn float_point(p: FloatPoint) -> FloatPoint; } fn main() { @@ -79,6 +88,7 @@ fn main() { let t = BiggerRect { s: s, a: 27834, b: 7657 }; let u = FloatRect { a: 3489, b: 3490, c: 8. }; let v = Huge { a: 5647, b: 5648, c: 5649, d: 5650, e: 5651 }; + let p = FloatPoint { x: 5., y: -3. }; unsafe { byval_rect(1, 2, 3, 4, 5, s); @@ -94,5 +104,6 @@ fn main() { assert_eq!(split_ret_byval_struct(1, 2, s), s); assert_eq!(sret_byval_struct(1, 2, 3, 4, s), t); assert_eq!(sret_split_struct(1, 2, s), t); + assert_eq!(float_point(p), p); } } diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr index 6f42a9f679a6a..6956a043cc694 100644 --- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types 16 | x.push(y); | ^ lifetime mismatch | - = note: expected type `Ref<'a, i32>` - found type `Ref<'_, i32>` + = note: expected type `Ref<'a, _>` + found type `Ref<'_, _>` note: the anonymous lifetime #2 defined on the body at 15:51... --> $DIR/ex2a-push-one-existing-name.rs:15:52 | diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr index edc1c2362de57..990ae65ba9854 100644 --- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types 16 | x.push(y); | ^ lifetime mismatch | - = note: expected type `Ref<'_, i32>` - found type `Ref<'_, i32>` + = note: expected type `Ref<'_, _>` + found type `Ref<'_, _>` note: the anonymous lifetime #3 defined on the body at 15:43... --> $DIR/ex2b-push-no-existing-names.rs:15:44 | diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr index 755b71d4a1d9e..82f6c71ec1c2e 100644 --- a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr +++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr @@ -27,7 +27,7 @@ note: but, the lifetime must be valid for the lifetime 'b as defined on the body 17 | | x.push(z); 18 | | } | |_^ ...ending here -note: ...so that expression is assignable (expected Ref<'b, i32>, found Ref<'_, i32>) +note: ...so that expression is assignable (expected Ref<'b, _>, found Ref<'_, _>) --> $DIR/ex2c-push-inference-variable.rs:17:12 | 17 | x.push(z); diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs new file mode 100644 index 0000000000000..c448ad955fab4 --- /dev/null +++ b/src/test/ui/mismatched_types/abridged.rs @@ -0,0 +1,61 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Bar { + Qux, + Zar, +} + +struct Foo { + bar: usize, +} + +struct X { + x: T1, + y: T2, +} + +fn a() -> Foo { + Some(Foo { bar: 1 }) +} + +fn a2() -> Foo { + Ok(Foo { bar: 1}) +} + +fn b() -> Option { + Foo { bar: 1 } +} + +fn c() -> Result { + Foo { bar: 1 } +} + +fn d() -> X, String> { + X { + x: X { + x: "".to_string(), + y: 2, + }, + y: 3, + } +} + +fn e() -> X, String> { + X { + x: X { + x: "".to_string(), + y: 2, + }, + y: "".to_string(), + } +} + +fn main() {} diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr new file mode 100644 index 0000000000000..c67c6113d17c5 --- /dev/null +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -0,0 +1,70 @@ +error[E0308]: mismatched types + --> $DIR/abridged.rs:26:5 + | +26 | Some(Foo { bar: 1 }) + | ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option` + | + = note: expected type `Foo` + found type `std::option::Option` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:30:5 + | +30 | Ok(Foo { bar: 1}) + | ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result` + | + = note: expected type `Foo` + found type `std::result::Result` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:34:5 + | +34 | Foo { bar: 1 } + | ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo` + | + = note: expected type `std::option::Option` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:38:5 + | +38 | Foo { bar: 1 } + | ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo` + | + = note: expected type `std::result::Result` + found type `Foo` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:42:5 + | +42 | X { + | _____^ starting here... +43 | | x: X { +44 | | x: "".to_string(), +45 | | y: 2, +46 | | }, +47 | | y: 3, +48 | | } + | |_____^ ...ending here: expected struct `std::string::String`, found integral variable + | + = note: expected type `X, std::string::String>` + found type `X, {integer}>` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:52:5 + | +52 | X { + | _____^ starting here... +53 | | x: X { +54 | | x: "".to_string(), +55 | | y: 2, +56 | | }, +57 | | y: "".to_string(), +58 | | } + | |_____^ ...ending here: expected struct `std::string::String`, found integral variable + | + = note: expected type `X, _>` + found type `X, _>` + +error: aborting due to 6 previous errors + diff --git a/src/test/parse-fail/tuple-float-index.rs b/src/test/ui/suggestions/tuple-float-index.rs similarity index 75% rename from src/test/parse-fail/tuple-float-index.rs rename to src/test/ui/suggestions/tuple-float-index.rs index 57ad89ad37404..8bfbd0e74db22 100644 --- a/src/test/parse-fail/tuple-float-index.rs +++ b/src/test/ui/suggestions/tuple-float-index.rs @@ -11,7 +11,5 @@ // compile-flags: -Z parse-only fn main () { - (1, (2, 3)).1.1; //~ ERROR unexpected token - //~^ HELP try parenthesizing the first index - //~| SUGGESTION ((1, (2, 3)).1).1 + (1, (2, 3)).1.1; } diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr new file mode 100644 index 0000000000000..abe04dc1aa210 --- /dev/null +++ b/src/test/ui/suggestions/tuple-float-index.stderr @@ -0,0 +1,11 @@ +error: unexpected token: `1.1` + --> $DIR/tuple-float-index.rs:14:17 + | +14 | (1, (2, 3)).1.1; + | ^^^ unexpected token + | +help: try parenthesizing the first index + | ((1, (2, 3)).1).1; + +error: aborting due to previous error + diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2865fa6a79253..7fb296c19f6ed 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1589,8 +1589,14 @@ actual:\n\ } fn dump_output(&self, out: &str, err: &str) { - self.dump_output_file(out, "out"); - self.dump_output_file(err, "err"); + let revision = if let Some(r) = self.revision { + format!("{}.", r) + } else { + String::new() + }; + + self.dump_output_file(out, &format!("{}out", revision)); + self.dump_output_file(err, &format!("{}err", revision)); self.maybe_dump_to_stdout(out, err); } diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index dee37341051ed..17f8b62117ad4 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -82,11 +82,9 @@ fn filter_dirs(path: &Path) -> bool { "src/llvm", "src/libbacktrace", "src/compiler-rt", - "src/rt/hoedown", "src/rustllvm", "src/rust-installer", "src/liblibc", - "src/tools/cargo", "src/vendor", ]; skip.iter().any(|p| path.ends_with(p))