diff options
| -rw-r--r-- | src/libcollections/range.rs | 28 | ||||
| -rw-r--r-- | src/libcollections/string.rs | 9 | ||||
| -rw-r--r-- | src/libcollectionstest/btree/map.rs | 37 | ||||
| -rw-r--r-- | src/libcollectionstest/lib.rs | 1 | ||||
| -rw-r--r-- | src/libcollectionstest/vec.rs | 50 | ||||
| -rw-r--r-- | src/librustc/infer/error_reporting/mod.rs (renamed from src/librustc/infer/error_reporting.rs) | 470 | ||||
| -rw-r--r-- | src/librustc/infer/error_reporting/note.rs | 432 | ||||
| -rw-r--r-- | src/librustc/infer/mod.rs | 10 | ||||
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustdoc/html/format.rs | 116 | ||||
| -rw-r--r-- | src/librustdoc/html/highlight.rs | 6 | ||||
| -rw-r--r-- | src/librustdoc/html/render.rs | 64 | ||||
| -rw-r--r-- | src/librustdoc/html/static/main.js | 2 | ||||
| -rw-r--r-- | src/librustdoc/html/static/rustdoc.css | 8 | ||||
| -rw-r--r-- | src/libstd/ffi/c_str.rs | 14 | ||||
| -rw-r--r-- | src/test/rustdoc/assoc-consts.rs | 8 | ||||
| -rw-r--r-- | src/test/rustdoc/issue-28478.rs | 3 | ||||
| -rw-r--r-- | src/test/rustdoc/issue-33302.rs | 30 |
18 files changed, 759 insertions, 531 deletions
diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs index 1df4ace3777..e4b94a1d70e 100644 --- a/src/libcollections/range.rs +++ b/src/libcollections/range.rs @@ -14,7 +14,7 @@ //! Range syntax. -use core::ops::{RangeFull, Range, RangeTo, RangeFrom}; +use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive}; use Bound::{self, Excluded, Included, Unbounded}; /// **RangeArgument** is implemented by Rust's built-in range types, produced @@ -105,6 +105,32 @@ impl<T> RangeArgument<T> for Range<T> { } } +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl<T> RangeArgument<T> for RangeInclusive<T> { + fn start(&self) -> Bound<&T> { + match *self { + RangeInclusive::Empty{ ref at } => Included(at), + RangeInclusive::NonEmpty { ref start, .. } => Included(start), + } + } + fn end(&self) -> Bound<&T> { + match *self { + RangeInclusive::Empty{ ref at } => Excluded(at), + RangeInclusive::NonEmpty { ref end, .. } => Included(end), + } + } +} + +#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] +impl<T> RangeArgument<T> for RangeToInclusive<T> { + fn start(&self) -> Bound<&T> { + Unbounded + } + fn end(&self) -> Bound<&T> { + Included(&self.end) + } +} + impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) { fn start(&self) -> Bound<&T> { match *self { diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 6839b698a56..4b37aef860d 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1483,6 +1483,15 @@ impl FromIterator<char> for String { } } +#[stable(feature = "string_from_iter_by_ref", since = "1.17.0")] +impl<'a> FromIterator<&'a char> for String { + fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> String { + let mut buf = String::new(); + buf.extend(iter); + buf + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a> FromIterator<&'a str> for String { fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> String { diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs index f33923f9963..2c899d96940 100644 --- a/src/libcollectionstest/btree/map.rs +++ b/src/libcollectionstest/btree/map.rs @@ -179,6 +179,43 @@ fn test_range_small() { } #[test] +fn test_range_inclusive() { + let size = 500; + + let map: BTreeMap<_, _> = (0...size).map(|i| (i, i)).collect(); + + fn check<'a, L, R>(lhs: L, rhs: R) + where L: IntoIterator<Item=(&'a i32, &'a i32)>, + R: IntoIterator<Item=(&'a i32, &'a i32)>, + { + let lhs: Vec<_> = lhs.into_iter().collect(); + let rhs: Vec<_> = rhs.into_iter().collect(); + assert_eq!(lhs, rhs); + } + + check(map.range(size + 1...size + 1), vec![]); + check(map.range(size...size), vec![(&size, &size)]); + check(map.range(size...size + 1), vec![(&size, &size)]); + check(map.range(0...0), vec![(&0, &0)]); + check(map.range(0...size - 1), map.range(..size)); + check(map.range(-1...-1), vec![]); + check(map.range(-1...size), map.range(..)); + check(map.range(...size), map.range(..)); + check(map.range(...200), map.range(..201)); + check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]); + check(map.range(-1...0), vec![(&0, &0)]); + check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]); +} + +#[test] +fn test_range_inclusive_max_value() { + let max = ::std::usize::MAX; + let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect(); + + assert_eq!(map.range(max...max).collect::<Vec<_>>(), &[(&max, &0)]); +} + +#[test] fn test_range_equal_empty_cases() { let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect(); assert_eq!(map.range((Included(2), Excluded(2))).next(), None); diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 57e3c2df059..849d2401691 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -14,6 +14,7 @@ #![feature(binary_heap_peek_mut_pop)] #![feature(box_syntax)] #![feature(btree_range)] +#![feature(inclusive_range_syntax)] #![feature(collection_placement)] #![feature(collections)] #![feature(collections_bound)] diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index edeedf1d40b..06d70800d39 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -508,6 +508,56 @@ fn test_drain_range() { } #[test] +fn test_drain_inclusive_range() { + let mut v = vec!['a', 'b', 'c', 'd', 'e']; + for _ in v.drain(1...3) { + } + assert_eq!(v, &['a', 'e']); + + let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect(); + for _ in v.drain(1...5) { + } + assert_eq!(v, &["0".to_string()]); + + let mut v: Vec<String> = (0...5).map(|x| x.to_string()).collect(); + for _ in v.drain(0...5) { + } + assert_eq!(v, Vec::<String>::new()); + + let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect(); + for _ in v.drain(0...3) { + } + assert_eq!(v, &["4".to_string(), "5".to_string()]); + + let mut v: Vec<_> = (0...1).map(|x| x.to_string()).collect(); + for _ in v.drain(...0) { + } + assert_eq!(v, &["1".to_string()]); +} + +#[test] +fn test_drain_max_vec_size() { + let mut v = Vec::<()>::with_capacity(usize::max_value()); + unsafe { v.set_len(usize::max_value()); } + for _ in v.drain(usize::max_value() - 1..) { + } + assert_eq!(v.len(), usize::max_value() - 1); + + let mut v = Vec::<()>::with_capacity(usize::max_value()); + unsafe { v.set_len(usize::max_value()); } + for _ in v.drain(usize::max_value() - 1...usize::max_value() - 1) { + } + assert_eq!(v.len(), usize::max_value() - 1); +} + +#[test] +#[should_panic] +fn test_drain_inclusive_out_of_bounds() { + let mut v = vec![1, 2, 3, 4, 5]; + v.drain(5...5); +} + +#[test] fn test_into_boxed_slice() { let xs = vec![1, 2, 3]; let ys = xs.into_boxed_slice(); diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting/mod.rs index f48ff87689f..21139c8dde2 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -55,32 +55,25 @@ //! ported to this system, and which relies on string concatenation at the //! time of error detection. -use super::InferCtxt; -use super::TypeTrace; -use super::SubregionOrigin; -use super::RegionVariableOrigin; -use super::ValuePairs; -use super::region_inference::RegionResolutionError; -use super::region_inference::ConcreteFailure; -use super::region_inference::SubSupConflict; -use super::region_inference::GenericBoundFailure; -use super::region_inference::GenericKind; +use infer; +use super::{InferCtxt, TypeTrace, SubregionOrigin, RegionVariableOrigin, ValuePairs}; +use super::region_inference::{RegionResolutionError, ConcreteFailure, SubSupConflict, + GenericBoundFailure, GenericKind}; -use hir::map as hir_map; +use std::fmt; use hir; - +use hir::map as hir_map; use hir::def_id::DefId; -use infer; use middle::region; use traits::{ObligationCause, ObligationCauseCode}; use ty::{self, TyCtxt, TypeFoldable}; use ty::{Region, Issue32330}; use ty::error::TypeError; - -use std::fmt; use syntax_pos::{Pos, Span}; use errors::DiagnosticBuilder; +mod note; + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn note_and_explain_region(self, err: &mut DiagnosticBuilder, @@ -584,289 +577,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.emit(); } - fn report_concrete_failure(&self, - origin: SubregionOrigin<'tcx>, - sub: &'tcx Region, - sup: &'tcx Region) - -> DiagnosticBuilder<'tcx> { - match origin { - infer::Subtype(trace) => { - let terr = TypeError::RegionsDoesNotOutlive(sup, sub); - self.report_and_explain_type_error(trace, &terr) - } - infer::Reborrow(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0312, - "lifetime of reference outlives \ - lifetime of borrowed content..."); - self.tcx.note_and_explain_region(&mut err, - "...the reference is valid for ", - sub, - "..."); - self.tcx.note_and_explain_region(&mut err, - "...but the borrowed content is only valid for ", - sup, - ""); - err - } - infer::ReborrowUpvar(span, ref upvar_id) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0313, - "lifetime of borrowed pointer outlives \ - lifetime of captured variable `{}`...", - self.tcx.local_var_name_str(upvar_id.var_id)); - self.tcx.note_and_explain_region(&mut err, - "...the borrowed pointer is valid for ", - sub, - "..."); - self.tcx.note_and_explain_region(&mut err, - &format!("...but `{}` is only valid for ", - self.tcx.local_var_name_str(upvar_id.var_id)), - sup, - ""); - err - } - infer::InfStackClosure(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0314, - "closure outlives stack frame"); - self.tcx.note_and_explain_region(&mut err, - "...the closure must be valid for ", - sub, - "..."); - self.tcx.note_and_explain_region(&mut err, - "...but the closure's stack frame is only valid for ", - sup, - ""); - err - } - infer::InvokeClosure(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0315, - "cannot invoke closure outside of its lifetime"); - self.tcx.note_and_explain_region(&mut err, - "the closure is only valid for ", - sup, - ""); - err - } - infer::DerefPointer(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0473, - "dereference of reference outside its lifetime"); - self.tcx.note_and_explain_region(&mut err, - "the reference is only valid for ", - sup, - ""); - err - } - infer::FreeVariable(span, id) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0474, - "captured variable `{}` does not outlive the enclosing closure", - self.tcx.local_var_name_str(id)); - self.tcx.note_and_explain_region(&mut err, - "captured variable is valid for ", - sup, - ""); - self.tcx.note_and_explain_region(&mut err, - "closure is valid for ", - sub, - ""); - err - } - infer::IndexSlice(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0475, - "index of slice outside its lifetime"); - self.tcx.note_and_explain_region(&mut err, - "the slice is only valid for ", - sup, - ""); - err - } - infer::RelateObjectBound(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0476, - "lifetime of the source pointer does not outlive \ - lifetime bound of the object type"); - self.tcx.note_and_explain_region(&mut err, - "object type is valid for ", - sub, - ""); - self.tcx.note_and_explain_region(&mut err, - "source pointer is only valid for ", - sup, - ""); - err - } - infer::RelateParamBound(span, ty) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0477, - "the type `{}` does not fulfill the required lifetime", - self.ty_to_string(ty)); - self.tcx.note_and_explain_region(&mut err, - "type must outlive ", - sub, - ""); - err - } - infer::RelateRegionParamBound(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0478, - "lifetime bound not satisfied"); - self.tcx.note_and_explain_region(&mut err, - "lifetime parameter instantiated with ", - sup, - ""); - self.tcx.note_and_explain_region(&mut err, - "but lifetime parameter must outlive ", - sub, - ""); - err - } - infer::RelateDefaultParamBound(span, ty) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0479, - "the type `{}` (provided as the value of \ - a type parameter) is not valid at this point", - self.ty_to_string(ty)); - self.tcx.note_and_explain_region(&mut err, - "type must outlive ", - sub, - ""); - err - } - infer::CallRcvr(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0480, - "lifetime of method receiver does not outlive \ - the method call"); - self.tcx.note_and_explain_region(&mut err, - "the receiver is only valid for ", - sup, - ""); - err - } - infer::CallArg(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0481, - "lifetime of function argument does not outlive \ - the function call"); - self.tcx.note_and_explain_region(&mut err, - "the function argument is only valid for ", - sup, - ""); - err - } - infer::CallReturn(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0482, - "lifetime of return value does not outlive \ - the function call"); - self.tcx.note_and_explain_region(&mut err, - "the return value is only valid for ", - sup, - ""); - err - } - infer::Operand(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0483, - "lifetime of operand does not outlive \ - the operation"); - self.tcx.note_and_explain_region(&mut err, - "the operand is only valid for ", - sup, - ""); - err - } - infer::AddrOf(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0484, - "reference is not valid at the time of borrow"); - self.tcx.note_and_explain_region(&mut err, - "the borrow is only valid for ", - sup, - ""); - err - } - infer::AutoBorrow(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0485, - "automatically reference is not valid \ - at the time of borrow"); - self.tcx.note_and_explain_region(&mut err, - "the automatic borrow is only valid for ", - sup, - ""); - err - } - infer::ExprTypeIsNotInScope(t, span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0486, - "type of expression contains references \ - that are not valid during the expression: `{}`", - self.ty_to_string(t)); - self.tcx.note_and_explain_region(&mut err, - "type is only valid for ", - sup, - ""); - err - } - infer::SafeDestructor(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0487, - "unsafe use of destructor: destructor might be called \ - while references are dead"); - // FIXME (22171): terms "super/subregion" are suboptimal - self.tcx.note_and_explain_region(&mut err, - "superregion: ", - sup, - ""); - self.tcx.note_and_explain_region(&mut err, - "subregion: ", - sub, - ""); - err - } - infer::BindingTypeIsNotValidAtDecl(span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0488, - "lifetime of variable does not enclose its declaration"); - self.tcx.note_and_explain_region(&mut err, - "the variable is only valid for ", - sup, - ""); - err - } - infer::ParameterInScope(_, span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0489, - "type/lifetime parameter not in scope here"); - self.tcx.note_and_explain_region(&mut err, - "the parameter is only valid for ", - sub, - ""); - err - } - infer::DataBorrowed(ty, span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0490, - "a value of type `{}` is borrowed for too long", - self.ty_to_string(ty)); - self.tcx.note_and_explain_region(&mut err, "the type is valid for ", sub, ""); - self.tcx.note_and_explain_region(&mut err, "but the borrow lasts for ", sup, ""); - err - } - infer::ReferenceOutlivesReferent(ty, span) => { - let mut err = struct_span_err!(self.tcx.sess, span, E0491, - "in type `{}`, reference has a longer lifetime \ - than the data it references", - self.ty_to_string(ty)); - self.tcx.note_and_explain_region(&mut err, - "the pointer is valid for ", - sub, - ""); - self.tcx.note_and_explain_region(&mut err, - "but the referenced data is only valid for ", - sup, - ""); - err - } - infer::CompareImplMethodObligation { span, - item_name, - impl_item_def_id, - trait_item_def_id, - lint_id } => { - self.report_extra_impl_obligation(span, - item_name, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", sup, sub), - lint_id) - } - } - } - fn report_sub_sup_conflict(&self, var_origin: RegionVariableOrigin, sub_origin: SubregionOrigin<'tcx>, @@ -939,170 +649,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { due to conflicting requirements", var_description) } - - fn note_region_origin(&self, err: &mut DiagnosticBuilder, origin: &SubregionOrigin<'tcx>) { - match *origin { - infer::Subtype(ref trace) => { - if let Some((expected, found)) = self.values_str(&trace.values) { - // FIXME: do we want a "the" here? - err.span_note( - trace.cause.span, - &format!("...so that {} (expected {}, found {})", - trace.cause.as_requirement_str(), expected, found)); - } else { - // FIXME: this really should be handled at some earlier stage. Our - // handling of region checking when type errors are present is - // *terrible*. - - err.span_note( - trace.cause.span, - &format!("...so that {}", - trace.cause.as_requirement_str())); - } - } - infer::Reborrow(span) => { - err.span_note( - span, - "...so that reference does not outlive \ - borrowed content"); - } - infer::ReborrowUpvar(span, ref upvar_id) => { - err.span_note( - span, - &format!( - "...so that closure can access `{}`", - self.tcx.local_var_name_str(upvar_id.var_id) - .to_string())); - } - infer::InfStackClosure(span) => { - err.span_note( - span, - "...so that closure does not outlive its stack frame"); - } - infer::InvokeClosure(span) => { - err.span_note( - span, - "...so that closure is not invoked outside its lifetime"); - } - infer::DerefPointer(span) => { - err.span_note( - span, - "...so that pointer is not dereferenced \ - outside its lifetime"); - } - infer::FreeVariable(span, id) => { - err.span_note( - span, - &format!("...so that captured variable `{}` \ - does not outlive the enclosing closure", - self.tcx.local_var_name_str(id))); - } - infer::IndexSlice(span) => { - err.span_note( - span, - "...so that slice is not indexed outside the lifetime"); - } - infer::RelateObjectBound(span) => { - err.span_note( - span, - "...so that it can be closed over into an object"); - } - infer::CallRcvr(span) => { - err.span_note( - span, - "...so that method receiver is valid for the method call"); - } - infer::CallArg(span) => { - err.span_note( - span, - "...so that argument is valid for the call"); - } - infer::CallReturn(span) => { - err.span_note( - span, - "...so that return value is valid for the call"); - } - infer::Operand(span) => { - err.span_note( - span, - "...so that operand is valid for operation"); - } - infer::AddrOf(span) => { - err.span_note( - span, - "...so that reference is valid \ - at the time of borrow"); - } - infer::AutoBorrow(span) => { - err.span_note( - span, - "...so that auto-reference is valid \ - at the time of borrow"); - } - infer::ExprTypeIsNotInScope(t, span) => { - err.span_note( - span, - &format!("...so type `{}` of expression is valid during the \ - expression", - self.ty_to_string(t))); - } - infer::BindingTypeIsNotValidAtDecl(span) => { - err.span_note( - span, - "...so that variable is valid at time of its declaration"); - } - infer::ParameterInScope(_, span) => { - err.span_note( - span, - "...so that a type/lifetime parameter is in scope here"); - } - infer::DataBorrowed(ty, span) => { - err.span_note( - span, - &format!("...so that the type `{}` is not borrowed for too long", - self.ty_to_string(ty))); - } - infer::ReferenceOutlivesReferent(ty, span) => { - err.span_note( - span, - &format!("...so that the reference type `{}` \ - does not outlive the data it points at", - self.ty_to_string(ty))); - } - infer::RelateParamBound(span, t) => { - err.span_note( - span, - &format!("...so that the type `{}` \ - will meet its required lifetime bounds", - self.ty_to_string(t))); - } - infer::RelateDefaultParamBound(span, t) => { - err.span_note( - span, - &format!("...so that type parameter \ - instantiated with `{}`, \ - will meet its declared lifetime bounds", - self.ty_to_string(t))); - } - infer::RelateRegionParamBound(span) => { - err.span_note( - span, - "...so that the declared lifetime parameter bounds \ - are satisfied"); - } - infer::SafeDestructor(span) => { - err.span_note( - span, - "...so that references are valid when the destructor \ - runs"); - } - infer::CompareImplMethodObligation { span, .. } => { - err.span_note( - span, - "...so that the definition in impl matches the definition from the trait"); - } - } - } } impl<'tcx> ObligationCause<'tcx> { diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs new file mode 100644 index 00000000000..8f8b2603dad --- /dev/null +++ b/src/librustc/infer/error_reporting/note.rs @@ -0,0 +1,432 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use infer::{self, InferCtxt, SubregionOrigin}; +use ty::Region; +use ty::error::TypeError; +use errors::DiagnosticBuilder; + +impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { + pub(super) fn note_region_origin(&self, + err: &mut DiagnosticBuilder, + origin: &SubregionOrigin<'tcx>) { + match *origin { + infer::Subtype(ref trace) => { + if let Some((expected, found)) = self.values_str(&trace.values) { + // FIXME: do we want a "the" here? + err.span_note(trace.cause.span, + &format!("...so that {} (expected {}, found {})", + trace.cause.as_requirement_str(), + expected, + found)); + } else { + // FIXME: this really should be handled at some earlier stage. Our + // handling of region checking when type errors are present is + // *terrible*. + + err.span_note(trace.cause.span, + &format!("...so that {}", trace.cause.as_requirement_str())); + } + } + infer::Reborrow(span) => { + err.span_note(span, + "...so that reference does not outlive borrowed content"); + } + infer::ReborrowUpvar(span, ref upvar_id) => { + err.span_note(span, + &format!("...so that closure can access `{}`", + self.tcx + .local_var_name_str(upvar_id.var_id) + .to_string())); + } + infer::InfStackClosure(span) => { + err.span_note(span, "...so that closure does not outlive its stack frame"); + } + infer::InvokeClosure(span) => { + err.span_note(span, + "...so that closure is not invoked outside its lifetime"); + } + infer::DerefPointer(span) => { + err.span_note(span, + "...so that pointer is not dereferenced outside its lifetime"); + } + infer::FreeVariable(span, id) => { + err.span_note(span, + &format!("...so that captured variable `{}` does not outlive the \ + enclosing closure", + self.tcx.local_var_name_str(id))); + } + infer::IndexSlice(span) => { + err.span_note(span, "...so that slice is not indexed outside the lifetime"); + } + infer::RelateObjectBound(span) => { + err.span_note(span, "...so that it can be closed over into an object"); + } + infer::CallRcvr(span) => { + err.span_note(span, + "...so that method receiver is valid for the method call"); + } + infer::CallArg(span) => { + err.span_note(span, "...so that argument is valid for the call"); + } + infer::CallReturn(span) => { + err.span_note(span, "...so that return value is valid for the call"); + } + infer::Operand(span) => { + err.span_note(span, "...so that operand is valid for operation"); + } + infer::AddrOf(span) => { + err.span_note(span, "...so that reference is valid at the time of borrow"); + } + infer::AutoBorrow(span) => { + err.span_note(span, + "...so that auto-reference is valid at the time of borrow"); + } + infer::ExprTypeIsNotInScope(t, span) => { + err.span_note(span, + &format!("...so type `{}` of expression is valid during the \ + expression", + self.ty_to_string(t))); + } + infer::BindingTypeIsNotValidAtDecl(span) => { + err.span_note(span, + "...so that variable is valid at time of its declaration"); + } + infer::ParameterInScope(_, span) => { + err.span_note(span, + "...so that a type/lifetime parameter is in scope here"); + } + infer::DataBorrowed(ty, span) => { + err.span_note(span, + &format!("...so that the type `{}` is not borrowed for too long", + self.ty_to_string(ty))); + } + infer::ReferenceOutlivesReferent(ty, span) => { + err.span_note(span, + &format!("...so that the reference type `{}` does not outlive the \ + data it points at", + self.ty_to_string(ty))); + } + infer::RelateParamBound(span, t) => { + err.span_note(span, + &format!("...so that the type `{}` will meet its required \ + lifetime bounds", + self.ty_to_string(t))); + } + infer::RelateDefaultParamBound(span, t) => { + err.span_note(span, + &format!("...so that type parameter instantiated with `{}`, will \ + meet its declared lifetime bounds", + self.ty_to_string(t))); + } + infer::RelateRegionParamBound(span) => { + err.span_note(span, + "...so that the declared lifetime parameter bounds are satisfied"); + } + infer::SafeDestructor(span) => { + err.span_note(span, + "...so that references are valid when the destructor runs"); + } + infer::CompareImplMethodObligation { span, .. } => { + err.span_note(span, + "...so that the definition in impl matches the definition from the \ + trait"); + } + } + } + + pub(super) fn report_concrete_failure(&self, + origin: SubregionOrigin<'tcx>, + sub: &'tcx Region, + sup: &'tcx Region) + -> DiagnosticBuilder<'tcx> { + match origin { + infer::Subtype(trace) => { + let terr = TypeError::RegionsDoesNotOutlive(sup, sub); + self.report_and_explain_type_error(trace, &terr) + } + infer::Reborrow(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0312, + "lifetime of reference outlives lifetime of \ + borrowed content..."); + self.tcx.note_and_explain_region(&mut err, + "...the reference is valid for ", + sub, + "..."); + self.tcx.note_and_explain_region(&mut err, + "...but the borrowed content is only valid for ", + sup, + ""); + err + } + infer::ReborrowUpvar(span, ref upvar_id) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0313, + "lifetime of borrowed pointer outlives lifetime \ + of captured variable `{}`...", + self.tcx.local_var_name_str(upvar_id.var_id)); + self.tcx.note_and_explain_region(&mut err, + "...the borrowed pointer is valid for ", + sub, + "..."); + self.tcx + .note_and_explain_region(&mut err, + &format!("...but `{}` is only valid for ", + self.tcx + .local_var_name_str(upvar_id.var_id)), + sup, + ""); + err + } + infer::InfStackClosure(span) => { + let mut err = + struct_span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame"); + self.tcx.note_and_explain_region(&mut err, + "...the closure must be valid for ", + sub, + "..."); + self.tcx.note_and_explain_region(&mut err, + "...but the closure's stack frame is only valid \ + for ", + sup, + ""); + err + } + infer::InvokeClosure(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0315, + "cannot invoke closure outside of its lifetime"); + self.tcx + .note_and_explain_region(&mut err, "the closure is only valid for ", sup, ""); + err + } + infer::DerefPointer(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0473, + "dereference of reference outside its lifetime"); + self.tcx + .note_and_explain_region(&mut err, "the reference is only valid for ", sup, ""); + err + } + infer::FreeVariable(span, id) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0474, + "captured variable `{}` does not outlive the \ + enclosing closure", + self.tcx.local_var_name_str(id)); + self.tcx + .note_and_explain_region(&mut err, "captured variable is valid for ", sup, ""); + self.tcx.note_and_explain_region(&mut err, "closure is valid for ", sub, ""); + err + } + infer::IndexSlice(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0475, + "index of slice outside its lifetime"); + self.tcx.note_and_explain_region(&mut err, "the slice is only valid for ", sup, ""); + err + } + infer::RelateObjectBound(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0476, + "lifetime of the source pointer does not outlive \ + lifetime bound of the object type"); + self.tcx.note_and_explain_region(&mut err, "object type is valid for ", sub, ""); + self.tcx.note_and_explain_region(&mut err, + "source pointer is only valid for ", + sup, + ""); + err + } + infer::RelateParamBound(span, ty) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0477, + "the type `{}` does not fulfill the required \ + lifetime", + self.ty_to_string(ty)); + self.tcx.note_and_explain_region(&mut err, "type must outlive ", sub, ""); + err + } + infer::RelateRegionParamBound(span) => { + let mut err = + struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); + self.tcx.note_and_explain_region(&mut err, + "lifetime parameter instantiated with ", + sup, + ""); + self.tcx.note_and_explain_region(&mut err, + "but lifetime parameter must outlive ", + sub, + ""); + err + } + infer::RelateDefaultParamBound(span, ty) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0479, + "the type `{}` (provided as the value of a type \ + parameter) is not valid at this point", + self.ty_to_string(ty)); + self.tcx.note_and_explain_region(&mut err, "type must outlive ", sub, ""); + err + } + infer::CallRcvr(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0480, + "lifetime of method receiver does not outlive the \ + method call"); + self.tcx + .note_and_explain_region(&mut err, "the receiver is only valid for ", sup, ""); + err + } + infer::CallArg(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0481, + "lifetime of function argument does not outlive \ + the function call"); + self.tcx.note_and_explain_region(&mut err, + "the function argument is only valid for ", + sup, + ""); + err + } + infer::CallReturn(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0482, + "lifetime of return value does not outlive the \ + function call"); + self.tcx.note_and_explain_region(&mut err, + "the return value is only valid for ", + sup, + ""); + err + } + infer::Operand(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0483, + "lifetime of operand does not outlive the \ + operation"); + self.tcx + .note_and_explain_region(&mut err, "the operand is only valid for ", sup, ""); + err + } + infer::AddrOf(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0484, + "reference is not valid at the time of borrow"); + self.tcx + .note_and_explain_region(&mut err, "the borrow is only valid for ", sup, ""); + err + } + infer::AutoBorrow(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0485, + "automatically reference is not valid at the time \ + of borrow"); + self.tcx.note_and_explain_region(&mut err, + "the automatic borrow is only valid for ", + sup, + ""); + err + } + infer::ExprTypeIsNotInScope(t, span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0486, + "type of expression contains references that are \ + not valid during the expression: `{}`", + self.ty_to_string(t)); + self.tcx.note_and_explain_region(&mut err, "type is only valid for ", sup, ""); + err + } + infer::SafeDestructor(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0487, + "unsafe use of destructor: destructor might be \ + called while references are dead"); + // FIXME (22171): terms "super/subregion" are suboptimal + self.tcx.note_and_explain_region(&mut err, "superregion: ", sup, ""); + self.tcx.note_and_explain_region(&mut err, "subregion: ", sub, ""); + err + } + infer::BindingTypeIsNotValidAtDecl(span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0488, + "lifetime of variable does not enclose its \ + declaration"); + self.tcx + .note_and_explain_region(&mut err, "the variable is only valid for ", sup, ""); + err + } + infer::ParameterInScope(_, span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0489, + "type/lifetime parameter not in scope here"); + self.tcx + .note_and_explain_region(&mut err, "the parameter is only valid for ", sub, ""); + err + } + infer::DataBorrowed(ty, span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0490, + "a value of type `{}` is borrowed for too long", + self.ty_to_string(ty)); + self.tcx.note_and_explain_region(&mut err, "the type is valid for ", sub, ""); + self.tcx.note_and_explain_region(&mut err, "but the borrow lasts for ", sup, ""); + err + } + infer::ReferenceOutlivesReferent(ty, span) => { + let mut err = struct_span_err!(self.tcx.sess, + span, + E0491, + "in type `{}`, reference has a longer lifetime \ + than the data it references", + self.ty_to_string(ty)); + self.tcx.note_and_explain_region(&mut err, "the pointer is valid for ", sub, ""); + self.tcx.note_and_explain_region(&mut err, + "but the referenced data is only valid for ", + sup, + ""); + err + } + infer::CompareImplMethodObligation { span, + item_name, + impl_item_def_id, + trait_item_def_id, + lint_id } => { + self.report_extra_impl_obligation(span, + item_name, + impl_item_def_id, + trait_item_def_id, + &format!("`{}: {}`", sup, sub), + lint_id) + } + } + } +} diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index a929060cf98..b07ef4dfd44 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -210,7 +210,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// region that each late-bound region was replaced with. pub type SkolemizationMap<'tcx> = FxHashMap<ty::BoundRegion, &'tcx ty::Region>; -/// See `error_reporting.rs` for more details +/// See `error_reporting` module for more details #[derive(Clone, Debug)] pub enum ValuePairs<'tcx> { Types(ExpectedFound<Ty<'tcx>>), @@ -221,7 +221,7 @@ pub enum ValuePairs<'tcx> { /// The trace designates the path through inference that we took to /// encounter an error or subtyping constraint. /// -/// See `error_reporting.rs` for more details. +/// See `error_reporting` module for more details. #[derive(Clone)] pub struct TypeTrace<'tcx> { cause: ObligationCause<'tcx>, @@ -230,7 +230,7 @@ pub struct TypeTrace<'tcx> { /// The origin of a `r1 <= r2` constraint. /// -/// See `error_reporting.rs` for more details +/// See `error_reporting` module for more details #[derive(Clone, Debug)] pub enum SubregionOrigin<'tcx> { // Arose from a subtyping relation @@ -348,7 +348,7 @@ pub enum LateBoundRegionConversionTime { /// Reasons to create a region inference variable /// -/// See `error_reporting.rs` for more details +/// See `error_reporting` module for more details #[derive(Clone, Debug)] pub enum RegionVariableOrigin { // Region variables created for ill-categorized reasons, @@ -1295,7 +1295,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // this infcx was in use. This is totally hokey but // otherwise we have a hard time separating legit region // errors from silly ones. - self.report_region_errors(&errors); // see error_reporting.rs + self.report_region_errors(&errors); // see error_reporting module } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 73b82fbad5d..1294296840e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1476,7 +1476,7 @@ pub struct PolyTrait { /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly /// it does not preserve mutability or boxes. -#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq)] pub enum Type { /// structs/enums/traits (most that'd be an hir::TyPath) ResolvedPath { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6f8c6aa7094..23507dc889b 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -90,6 +90,16 @@ impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { } } +impl<'a, T: fmt::Debug> fmt::Debug for CommaSep<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for (i, item) in self.0.iter().enumerate() { + if i != 0 { write!(f, ", ")?; } + fmt::Debug::fmt(item, f)?; + } + Ok(()) + } +} + impl<'a> fmt::Display for TyParamBounds<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let &TyParamBounds(bounds) = self; @@ -165,7 +175,7 @@ impl<'a> fmt::Display for WhereClause<'a> { if f.alternate() { clause.push_str(" where "); } else { - clause.push_str(" <span class='where fmt-newline'>where "); + clause.push_str(" <span class=\"where fmt-newline\">where "); } for (i, pred) in gens.where_predicates.iter().enumerate() { if i > 0 { @@ -449,8 +459,8 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path, } else { root.push_str(&seg.name); root.push_str("/"); - write!(w, "<a class='mod' - href='{}index.html'>{}</a>::", + write!(w, "<a class=\"mod\" + href=\"{}index.html\">{}</a>::", root, seg.name)?; } @@ -491,7 +501,7 @@ fn primitive_link(f: &mut fmt::Formatter, Some(&def_id) if def_id.is_local() => { let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len()); let len = if len == 0 {0} else {len - 1}; - write!(f, "<a class='primitive' href='{}primitive.{}.html'>", + write!(f, "<a class=\"primitive\" href=\"{}primitive.{}.html\">", repeat("../").take(len).collect::<String>(), prim.to_url_str())?; needs_termination = true; @@ -508,7 +518,7 @@ fn primitive_link(f: &mut fmt::Formatter, (.., render::Unknown) => None, }; if let Some((cname, root)) = loc { - write!(f, "<a class='primitive' href='{}{}/primitive.{}.html'>", + write!(f, "<a class=\"primitive\" href=\"{}{}/primitive.{}.html\">", root, cname, prim.to_url_str())?; @@ -550,7 +560,7 @@ impl<'a> fmt::Display for HRef<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match href(self.did) { Some((url, shortty, fqp)) => if !f.alternate() { - write!(f, "<a class='{}' href='{}' title='{} {}'>{}</a>", + write!(f, "<a class=\"{}\" href=\"{}\" title=\"{} {}\">{}</a>", shortty, url, shortty, fqp.join("::"), self.text) } else { write!(f, "{}", self.text) @@ -560,7 +570,8 @@ impl<'a> fmt::Display for HRef<'a> { } } -fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt::Result { +fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool, + is_not_debug: bool) -> fmt::Result { match *t { clean::Generic(ref name) => { f.write_str(name) @@ -571,7 +582,8 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: tybounds(f, typarams) } clean::Infer => write!(f, "_"), - clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()), + clean::Primitive(prim) if is_not_debug => primitive_link(f, prim, prim.as_str()), + clean::Primitive(prim) => write!(f, "{}", prim.as_str()), clean::BareFunction(ref decl) => { if f.alternate() { write!(f, "{}{}fn{:#}{:#}", @@ -589,26 +601,30 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } clean::Tuple(ref typs) => { match &typs[..] { - &[] => primitive_link(f, PrimitiveType::Tuple, "()"), - &[ref one] => { + &[] if is_not_debug => primitive_link(f, PrimitiveType::Tuple, "()"), + &[] => write!(f, "()"), + &[ref one] if is_not_debug => { primitive_link(f, PrimitiveType::Tuple, "(")?; //carry f.alternate() into this display w/o branching manually fmt::Display::fmt(one, f)?; primitive_link(f, PrimitiveType::Tuple, ",)") } - many => { + &[ref one] => write!(f, "({:?},)", one), + many if is_not_debug => { primitive_link(f, PrimitiveType::Tuple, "(")?; fmt::Display::fmt(&CommaSep(&many), f)?; primitive_link(f, PrimitiveType::Tuple, ")") } + many => write!(f, "({:?})", &CommaSep(&many)), } } - clean::Vector(ref t) => { + clean::Vector(ref t) if is_not_debug => { primitive_link(f, PrimitiveType::Slice, &format!("["))?; fmt::Display::fmt(t, f)?; primitive_link(f, PrimitiveType::Slice, &format!("]")) } - clean::FixedVector(ref t, ref s) => { + clean::Vector(ref t) => write!(f, "[{:?}]", t), + clean::FixedVector(ref t, ref s) if is_not_debug => { primitive_link(f, PrimitiveType::Array, "[")?; fmt::Display::fmt(t, f)?; if f.alternate() { @@ -619,10 +635,17 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: &format!("; {}]", Escape(s))) } } + clean::FixedVector(ref t, ref s) => { + if f.alternate() { + write!(f, "[{:?}; {}]", t, s) + } else { + write!(f, "[{:?}; {}]", t, Escape(s)) + } + } clean::Never => f.write_str("!"), clean::RawPointer(m, ref t) => { match **t { - clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { + clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} if is_not_debug => { if f.alternate() { primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{}{:#}", RawMutableSpace(m), t)) @@ -631,11 +654,21 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: &format!("*{}{}", RawMutableSpace(m), t)) } } - _ => { + clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { + if f.alternate() { + write!(f, "*{}{:#?}", RawMutableSpace(m), t) + } else { + write!(f, "*{}{:?}", RawMutableSpace(m), t) + } + } + _ if is_not_debug => { primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{}", RawMutableSpace(m)))?; fmt::Display::fmt(t, f) } + _ => { + write!(f, "*{}{:?}", RawMutableSpace(m), t) + } } } clean::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty} => { @@ -647,15 +680,23 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: match **ty { clean::Vector(ref bt) => { // BorrowedRef{ ... Vector(T) } is &[T] match **bt { - clean::Generic(_) => + clean::Generic(_) if is_not_debug => { if f.alternate() { primitive_link(f, PrimitiveType::Slice, &format!("&{}{}[{:#}]", lt, m, **bt)) } else { primitive_link(f, PrimitiveType::Slice, &format!("&{}{}[{}]", lt, m, **bt)) - }, - _ => { + } + } + clean::Generic(_) => { + if f.alternate() { + write!(f, "&{}{}[{:#?}]", lt, m, **bt) + } else { + write!(f, "&{}{}[{:?}]", lt, m, **bt) + } + } + _ if is_not_debug => { if f.alternate() { primitive_link(f, PrimitiveType::Slice, &format!("&{}{}[", lt, m))?; @@ -667,15 +708,26 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } primitive_link(f, PrimitiveType::Slice, "]") } + _ => { + if f.alternate() { + write!(f, "&{}{}[{:#?}]", lt, m, **bt) + } else { + write!(f, "&{}{}[{:?}]", lt, m, **bt) + } + } } } _ => { if f.alternate() { write!(f, "&{}{}", lt, m)?; - fmt_type(&ty, f, use_absolute) + fmt_type(&ty, f, use_absolute, is_not_debug) } else { - write!(f, "&{}{}", lt, m)?; - fmt_type(&ty, f, use_absolute) + if is_not_debug { + write!(f, "&{}{}", lt, m)?; + } else { + write!(f, "&{}{}", lt, m)?; + } + fmt_type(&ty, f, use_absolute, is_not_debug) } } } @@ -723,9 +775,17 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } clean::QPath { ref name, ref self_type, ref trait_ } => { if f.alternate() { - write!(f, "<{:#} as {:#}>::{}", self_type, trait_, name) + if is_not_debug { + write!(f, "<{:#} as {:#}>::{}", self_type, trait_, name) + } else { + write!(f, "<{:#?} as {:#?}>::{}", self_type, trait_, name) + } } else { - write!(f, "<{} as {}>::{}", self_type, trait_, name) + if is_not_debug { + write!(f, "<{} as {}>::{}", self_type, trait_, name) + } else { + write!(f, "<{:?} as {:?}>::{}", self_type, trait_, name) + } } } clean::Unique(..) => { @@ -736,7 +796,13 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: impl fmt::Display for clean::Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt_type(self, f, false) + fmt_type(self, f, false, true) + } +} + +impl fmt::Debug for clean::Type { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt_type(self, f, false, false) } } @@ -777,7 +843,7 @@ fn fmt_impl(i: &clean::Impl, plain.push_str(" for "); } - fmt_type(&i.for_, f, use_absolute)?; + fmt_type(&i.for_, f, use_absolute, true)?; plain.push_str(&format!("{:#}", i.for_)); fmt::Display::fmt(&WhereClause(&i.generics, plain.len() + 1), f)?; diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 2c15dd92323..0dafc4225a3 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -144,12 +144,12 @@ impl<U: Write> Writer for U { -> io::Result<()> { match klass { Class::None => write!(self, "{}", text), - klass => write!(self, "<span class='{}'>{}</span>", klass.rustdoc_class(), text), + klass => write!(self, "<span class=\"{}\">{}</span>", klass.rustdoc_class(), text), } } fn enter_span(&mut self, klass: Class) -> io::Result<()> { - write!(self, "<span class='{}'>", klass.rustdoc_class()) + write!(self, "<span class=\"{}\">", klass.rustdoc_class()) } fn exit_span(&mut self) -> io::Result<()> { @@ -363,7 +363,7 @@ fn write_header(class: Option<&str>, if let Some(id) = id { write!(out, "id='{}' ", id)?; } - write!(out, "class='rust {}'>\n", class.unwrap_or("")) + write!(out, "class=\"rust {}\">\n", class.unwrap_or("")) } fn write_footer(out: &mut Write) -> io::Result<()> { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index bb39c8c4f22..44f71d89529 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1547,7 +1547,7 @@ impl<'a> fmt::Display for Item<'a> { component)?; } } - write!(fmt, "<a class='{}' href=''>{}</a>", + write!(fmt, "<a class=\"{}\" href=''>{}</a>", self.item.type_(), self.item.name.as_ref().unwrap())?; write!(fmt, "</span>")?; // in-band @@ -1654,9 +1654,35 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin Ok(()) } +fn md_render_assoc_item(item: &clean::Item) -> String { + match item.inner { + clean::AssociatedConstItem(ref ty, ref default) => { + if let Some(default) = default.as_ref() { + format!("```\n{}: {:?} = {}\n```\n\n", item.name.as_ref().unwrap(), ty, default) + } else { + format!("```\n{}: {:?}\n```\n\n", item.name.as_ref().unwrap(), ty) + } + } + _ => String::new(), + } +} + +fn get_doc_value(item: &clean::Item) -> Option<&str> { + let x = item.doc_value(); + if x.is_none() { + match item.inner { + clean::AssociatedConstItem(_, _) => Some(""), + _ => None, + } + } else { + x + } +} + fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result { - if let Some(s) = item.doc_value() { - write!(w, "<div class='docblock'>{}</div>", Markdown(s))?; + if let Some(s) = get_doc_value(item) { + write!(w, "<div class='docblock'>{}</div>", + Markdown(&format!("{}{}", md_render_assoc_item(item), s)))?; } Ok(()) } @@ -1817,7 +1843,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, let doc_value = myitem.doc_value().unwrap_or(""); write!(w, " <tr class='{stab} module-item'> - <td><a class='{class}' href='{href}' + <td><a class=\"{class}\" href=\"{href}\" title='{title_type} {title}'>{name}</a>{unsafety_flag}</td> <td class='docblock-short'> {stab_docs} {docs} @@ -2215,16 +2241,12 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink) -> String { fn assoc_const(w: &mut fmt::Formatter, it: &clean::Item, ty: &clean::Type, - default: Option<&String>, + _default: Option<&String>, link: AssocItemLink) -> fmt::Result { - write!(w, "const <a href='{}' class='constant'>{}</a>", + write!(w, "const <a href='{}' class=\"constant\"><b>{}</b></a>: {}", naive_assoc_href(it, link), - it.name.as_ref().unwrap())?; - - write!(w, ": {}", ty)?; - if let Some(default) = default { - write!(w, " = {}", Escape(default))?; - } + it.name.as_ref().unwrap(), + ty)?; Ok(()) } @@ -2232,7 +2254,7 @@ fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item, bounds: &Vec<clean::TyParamBound>, default: Option<&clean::Type>, link: AssocItemLink) -> fmt::Result { - write!(w, "type <a href='{}' class='type'>{}</a>", + write!(w, "type <a href='{}' class=\"type\">{}</a>", naive_assoc_href(it, link), it.name.as_ref().unwrap())?; if !bounds.is_empty() { @@ -2375,7 +2397,7 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, let ns_id = derive_id(format!("{}.{}", field.name.as_ref().unwrap(), ItemType::StructField.name_space())); - write!(w, "<span id='{id}' class='{item_type}'> + write!(w, "<span id='{id}' class=\"{item_type}\"> <span id='{ns_id}' class='invisible'> <code>{name}: {ty}</code> </span></span>", @@ -2417,7 +2439,7 @@ fn item_union(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, if fields.peek().is_some() { write!(w, "<h2 class='fields'>Fields</h2>")?; for (field, ty) in fields { - write!(w, "<span id='{shortty}.{name}' class='{shortty}'><code>{name}: {ty}</code> + write!(w, "<span id='{shortty}.{name}' class=\"{shortty}\"><code>{name}: {ty}</code> </span>", shortty = ItemType::StructField, name = field.name.as_ref().unwrap(), @@ -2902,7 +2924,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi if render_method_item { let id = derive_id(format!("{}.{}", item_type, name)); let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); - write!(w, "<h4 id='{}' class='{}'>", id, item_type)?; + write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?; write!(w, "<span id='{}' class='invisible'>", ns_id)?; write!(w, "<code>")?; render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?; @@ -2914,7 +2936,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi clean::TypedefItem(ref tydef, _) => { let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name)); let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); - write!(w, "<h4 id='{}' class='{}'>", id, item_type)?; + write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?; write!(w, "<span id='{}' class='invisible'><code>", ns_id)?; assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?; write!(w, "</code></span></h4>\n")?; @@ -2922,7 +2944,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi clean::AssociatedConstItem(ref ty, ref default) => { let id = derive_id(format!("{}.{}", item_type, name)); let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); - write!(w, "<h4 id='{}' class='{}'>", id, item_type)?; + write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?; write!(w, "<span id='{}' class='invisible'><code>", ns_id)?; assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?; write!(w, "</code></span></h4>\n")?; @@ -2930,7 +2952,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi clean::ConstantItem(ref c) => { let id = derive_id(format!("{}.{}", item_type, name)); let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); - write!(w, "<h4 id='{}' class='{}'>", id, item_type)?; + write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?; write!(w, "<span id='{}' class='invisible'><code>", ns_id)?; assoc_const(w, item, &c.type_, Some(&c.expr), link.anchor(&id))?; write!(w, "</code></span></h4>\n")?; @@ -2938,7 +2960,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi clean::AssociatedTypeItem(ref bounds, ref default) => { let id = derive_id(format!("{}.{}", item_type, name)); let ns_id = derive_id(format!("{}.{}", name, item_type.name_space())); - write!(w, "<h4 id='{}' class='{}'>", id, item_type)?; + write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?; write!(w, "<span id='{}' class='invisible'><code>", ns_id)?; assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?; write!(w, "</code></span></h4>\n")?; @@ -2956,7 +2978,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi // We need the stability of the item from the trait // because impls can't have a stability. document_stability(w, cx, it)?; - if item.doc_value().is_some() { + if get_doc_value(item).is_some() { document_full(w, item)?; } else { // In case the item isn't documented, diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index c12e1e7d608..20028586227 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -979,7 +979,7 @@ .html("[<span class='inner'></span>]"); toggle.children(".inner").text(labelForToggleButton(false)); - $(".method").each(function() { + $(".method, .impl-items > .associatedconstant").each(function() { if ($(this).next().is(".docblock") || ($(this).next().is(".stability") && $(this).next().next().is(".docblock"))) { $(this).children().last().after(toggle.clone()); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 681d2354056..b0bf69b0181 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -89,7 +89,7 @@ h2 { h3 { font-size: 1.3em; } -h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { +h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { font-weight: 500; margin: 20px 0 15px 0; padding-bottom: 6px; @@ -99,10 +99,10 @@ h1.fqn { margin-top: 0; position: relative; } -h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { +h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) { border-bottom: 1px solid; } -h3.impl, h3.method, h4.method, h3.type, h4.type { +h3.impl, h3.method, h4.method, h3.type, h4.type, h4.associatedconstant { font-weight: 600; margin-top: 10px; margin-bottom: 10px; @@ -382,7 +382,7 @@ h4 > code, h3 > code, .invisible > code { .content .impl-items .docblock, .content .impl-items .stability { margin-left: 40px; } -.content .impl-items .method, .content .impl-items > .type { +.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant { margin-left: 20px; } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index dc3855367ae..bc678fcb838 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -455,6 +455,20 @@ impl From<NulError> for io::Error { } } +#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] +impl Error for FromBytesWithNulError { + fn description(&self) -> &str { + "data provided is not null terminated or contains an interior nul byte" + } +} + +#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] +impl fmt::Display for FromBytesWithNulError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} + impl IntoStringError { /// Consumes this error, returning original `CString` which generated the /// error. diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index 8d3f9b59bb2..d4119f5d351 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -13,14 +13,16 @@ pub trait Foo { // @has assoc_consts/trait.Foo.html '//*[@class="rust trait"]' \ // 'const FOO: usize;' - // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO' - const FOO: usize; + // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize' + // @has - '//*[@class="docblock"]' 'FOO: usize = 12' + const FOO: usize = 12; } pub struct Bar; impl Bar { // @has assoc_consts/struct.Bar.html '//*[@id="associatedconstant.BAR"]' \ - // 'const BAR: usize = 3' + // 'const BAR: usize' + // @has - '//*[@class="docblock"]' 'BAR: usize = 3' pub const BAR: usize = 3; } diff --git a/src/test/rustdoc/issue-28478.rs b/src/test/rustdoc/issue-28478.rs index 0db92a491ed..493c08693e9 100644 --- a/src/test/rustdoc/issue-28478.rs +++ b/src/test/rustdoc/issue-28478.rs @@ -16,7 +16,8 @@ pub trait Bar { // @has - '//*[@id="associatedtype.Bar"]' 'type Bar = ()' // @has - '//*[@href="#associatedtype.Bar"]' 'Bar' type Bar = (); - // @has - '//*[@id="associatedconstant.Baz"]' 'const Baz: usize = 7' + // @has - '//*[@id="associatedconstant.Baz"]' 'const Baz: usize' + // @has - '//*[@class="docblock"]' 'Baz: usize = 7' // @has - '//*[@href="#associatedconstant.Baz"]' 'Baz' const Baz: usize = 7; // @has - '//*[@id="tymethod.bar"]' 'fn bar' diff --git a/src/test/rustdoc/issue-33302.rs b/src/test/rustdoc/issue-33302.rs index c6da6b0575b..a34ee908ef2 100644 --- a/src/test/rustdoc/issue-33302.rs +++ b/src/test/rustdoc/issue-33302.rs @@ -28,18 +28,40 @@ macro_rules! make { fn ignore(_: &X) {} const C: X; // @has issue_33302/trait.T.html \ - // '//*[@class="rust trait"]' 'const D: i32 = 4 * 4;' - // @has - '//*[@id="associatedconstant.D"]' 'const D: i32 = 4 * 4' + // '//*[@class="rust trait"]' 'const D: i32' + // @has - '//*[@class="docblock"]' 'D: i32 = 4 * 4' + // @has - '//*[@id="associatedconstant.D"]' 'const D: i32' const D: i32 = ($n * $n); } // @has issue_33302/struct.S.html \ // '//h3[@class="impl"]' 'impl T<[i32; 16]> for S' - // @has - '//*[@id="associatedconstant.C"]' 'const C: [i32; 16] = [0; 4 * 4]' - // @has - '//*[@id="associatedconstant.D"]' 'const D: i32 = 4 * 4' + // @has - '//*[@id="associatedconstant.C"]' 'const C: [i32; 16]' + // @has - '//*[@id="associatedconstant.D"]' 'const D: i32' + // @has - '//*[@class="docblock"]' 'C: [i32; 16] = [0; 4 * 4]' impl T<[i32; ($n * $n)]> for S { const C: [i32; ($n * $n)] = [0; ($n * $n)]; } + + // @has issue_33302/struct.S.html \ + // '//h3[@class="impl"]' 'impl T<[i32; 16]> for S' + // @has - '//*[@id="associatedconstant.C-1"]' 'const C: (i32,)' + // @has - '//*[@id="associatedconstant.D-1"]' 'const D: i32' + // @has - '//*[@class="docblock"]' 'C: (i32,) = (4,)' + impl T<(i32,)> for S { + const C: (i32,) = ($n,); + } + + // @has issue_33302/struct.S.html \ + // '//h3[@class="impl"]' 'impl T<(i32, i32)> for S' + // @has - '//*[@id="associatedconstant.C-2"]' 'const C: (i32, i32)' + // @has - '//*[@id="associatedconstant.D-2"]' 'const D: i32' + // @has - '//*[@class="docblock"]' 'C: (i32, i32) = (4, 4)' + // @has - '//*[@class="docblock"]' 'D: i32 = 4 / 4' + impl T<(i32, i32)> for S { + const C: (i32, i32) = ($n, $n); + const D: i32 = ($n / $n); + } } } |
