diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 65df056fd424b..c5db2a8a7807b 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -38,6 +38,7 @@ pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch}; pub use self::select::{MethodMatchedData}; // intentionally don't export variants pub use self::specialize::{OverlapError, specialization_graph, specializes, translate_substs}; +pub use self::specialize::{SpecializesCache}; pub use self::util::elaborate_predicates; pub use self::util::supertraits; pub use self::util::Supertraits; diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index d43d2de1f1fbc..b2d14dab9a0b0 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -20,6 +20,7 @@ use super::{SelectionContext, FulfillmentContext}; use super::util::{fresh_type_vars_for_impl, impl_trait_ref_and_oblig}; +use rustc_data_structures::fnv::FnvHashMap; use hir::def_id::DefId; use infer::{InferCtxt, TypeOrigin}; use middle::region; @@ -111,6 +112,10 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl1_def_id: DefId, impl2_def_id: DefId) -> bool { + if let Some(r) = tcx.specializes_cache.borrow().check(impl1_def_id, impl2_def_id) { + return r; + } + // The feature gate should prevent introducing new specializations, but not // taking advantage of upstream ones. if !tcx.sess.features.borrow().specialization && @@ -146,7 +151,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .unwrap() .subst(tcx, &penv.free_substs); - tcx.normalizing_infer_ctxt(ProjectionMode::Topmost).enter(|mut infcx| { + let result = tcx.normalizing_infer_ctxt(ProjectionMode::Topmost).enter(|mut infcx| { // Normalize the trait reference, adding any obligations // that arise into the impl1 assumptions. let Normalized { value: impl1_trait_ref, obligations: normalization_obligations } = { @@ -167,7 +172,10 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Attempt to prove that impl2 applies, given all of the above. fulfill_implication(&infcx, impl1_trait_ref, impl2_def_id).is_ok() - }) + }); + + tcx.specializes_cache.borrow_mut().insert(impl1_def_id, impl2_def_id, result); + result } /// Attempt to fulfill all obligations of `target_impl` after unification with @@ -225,3 +233,23 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, } }) } + +pub struct SpecializesCache { + map: FnvHashMap<(DefId, DefId), bool> +} + +impl SpecializesCache { + pub fn new() -> Self { + SpecializesCache { + map: FnvHashMap() + } + } + + pub fn check(&self, a: DefId, b: DefId) -> Option { + self.map.get(&(a, b)).cloned() + } + + pub fn insert(&mut self, a: DefId, b: DefId, result: bool) { + self.map.insert((a, b), result); + } +} diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 39fe744c67d01..aa50266977795 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -291,6 +291,8 @@ impl<'a, 'gcx, 'tcx> Deref for TyCtxt<'a, 'gcx, 'tcx> { pub struct GlobalCtxt<'tcx> { global_interners: CtxtInterners<'tcx>, + pub specializes_cache: RefCell, + pub dep_graph: DepGraph, /// Common types, pre-interned for your convenience. @@ -637,6 +639,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let dep_graph = map.dep_graph.clone(); let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone()); tls::enter_global(GlobalCtxt { + specializes_cache: RefCell::new(traits::SpecializesCache::new()), global_interners: interners, dep_graph: dep_graph.clone(), types: common_types, diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index cdbad685008f2..b5d8192b4dd2c 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -391,6 +391,7 @@ fn you_know_nothing(jon_snow: &mut i32) { // but it is already borrowed }; } +``` In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it cannot be borrowed by the `starks` closure at the same time. To fix this issue, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ce83c4a258ce9..3fbcdaf650eeb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -795,7 +795,17 @@ impl Clean for hir::Lifetime { impl Clean for hir::LifetimeDef { fn clean(&self, _: &DocContext) -> Lifetime { - Lifetime(self.lifetime.name.to_string()) + if self.bounds.len() > 0 { + let mut s = format!("{}: {}", + self.lifetime.name.to_string(), + self.bounds[0].name.to_string()); + for bound in self.bounds.iter().skip(1) { + s.push_str(&format!(" + {}", bound.name.to_string())); + } + Lifetime(s) + } else { + Lifetime(self.lifetime.name.to_string()) + } } } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index d256e939afcfc..a52a914fea680 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -640,6 +640,10 @@ span.since { margin-right: 5px; } +:target > code { + background: #FDFFD3; +} + /* Media Queries */ @media (max-width: 700px) { diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 6c61d6b914c56..abfa65580646d 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -67,8 +67,7 @@ struct Context<'a, 'b:'a> { name_positions: HashMap, - /// Updated as arguments are consumed or methods are entered - nest_level: usize, + /// Updated as arguments are consumed next_arg: usize, } @@ -164,9 +163,7 @@ impl<'a, 'b> Context<'a, 'b> { let pos = match arg.position { parse::ArgumentNext => { let i = self.next_arg; - if self.check_positional_ok() { - self.next_arg += 1; - } + self.next_arg += 1; Exact(i) } parse::ArgumentIs(i) => Exact(i), @@ -189,25 +186,13 @@ impl<'a, 'b> Context<'a, 'b> { self.verify_arg_type(Named(s.to_string()), Unsigned); } parse::CountIsNextParam => { - if self.check_positional_ok() { - let next_arg = self.next_arg; - self.verify_arg_type(Exact(next_arg), Unsigned); - self.next_arg += 1; - } + let next_arg = self.next_arg; + self.verify_arg_type(Exact(next_arg), Unsigned); + self.next_arg += 1; } } } - fn check_positional_ok(&mut self) -> bool { - if self.nest_level != 0 { - self.ecx.span_err(self.fmtsp, "cannot use implicit positional \ - arguments nested inside methods"); - false - } else { - true - } - } - fn describe_num_args(&self) -> String { match self.args.len() { 0 => "no arguments given".to_string(), @@ -655,7 +640,6 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, name_positions: HashMap::new(), name_types: HashMap::new(), name_ordering: name_ordering, - nest_level: 0, next_arg: 0, literal: String::new(), pieces: Vec::new(),