mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 02:03:53 +00:00
Auto merge of #40167 - frewsxcv:rollup, r=frewsxcv
Rollup of 6 pull requests - Successful merges: #39419, #39936, #39944, #39960, #40028, #40128 - Failed merges:
This commit is contained in:
commit
b671c32ddc
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -178,6 +178,43 @@ fn test_range_small() {
|
||||
assert_eq!(j, size - 2);
|
||||
}
|
||||
|
||||
#[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();
|
||||
|
@ -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)]
|
||||
|
@ -507,6 +507,56 @@ fn test_drain_range() {
|
||||
assert_eq!(v, &[(), ()]);
|
||||
}
|
||||
|
||||
#[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];
|
||||
|
@ -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 hir::map as hir_map;
|
||||
use hir;
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use infer;
|
||||
use super::{InferCtxt, TypeTrace, SubregionOrigin, RegionVariableOrigin, ValuePairs};
|
||||
use super::region_inference::{RegionResolutionError, ConcreteFailure, SubSupConflict,
|
||||
GenericBoundFailure, GenericKind};
|
||||
|
||||
use std::fmt;
|
||||
use hir;
|
||||
use hir::map as hir_map;
|
||||
use hir::def_id::DefId;
|
||||
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> {
|
432
src/librustc/infer/error_reporting/note.rs
Normal file
432
src/librustc/infer/error_reporting/note.rs
Normal file
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)?;
|
||||
|
@ -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<()> {
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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'
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user