Skip to content

Commit 0bf018c

Browse files
committed
Auto merge of #43560 - QuietMisdreavus:ref-docs, r=steveklabnik
add docs for references as a primitive Just like #43529 did for function pointers, here is a new primitive page for references. This PR will pull in impls on references if it's a reference to a generic type parameter. Initially i was only able to pull in impls that were re-exported from another crate; crate-local impls got a different representation in the AST, and i had to change how types were resolved when cleaning it. (This is the change at the bottom of `librustdoc/clean/mod.rs`, in `resolve_type`.) I'm unsure the full ramifications of the change, but from what it looks like, it shouldn't impact anything major. Likewise, references to generic type parameters also get the `&'a [mut]` linked to the new page. cc @rust-lang/docs: Is this sufficient information? The listing of trait impls kinda feels redundant (especially if we can get the automated impl listing sorted again), but i still think it's useful to point out that you can use these in a generic context. Fixes #15654
2 parents 6e8452e + a2d5514 commit 0bf018c

File tree

3 files changed

+142
-19
lines changed

3 files changed

+142
-19
lines changed

src/librustdoc/clean/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,7 @@ pub enum PrimitiveType {
15471547
Array,
15481548
Tuple,
15491549
RawPointer,
1550+
Reference,
15501551
}
15511552

15521553
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
@@ -1581,6 +1582,7 @@ impl Type {
15811582
Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
15821583
Tuple(..) => Some(PrimitiveType::Tuple),
15831584
RawPointer(..) => Some(PrimitiveType::RawPointer),
1585+
BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
15841586
_ => None,
15851587
}
15861588
}
@@ -1633,6 +1635,7 @@ impl PrimitiveType {
16331635
"slice" => Some(PrimitiveType::Slice),
16341636
"tuple" => Some(PrimitiveType::Tuple),
16351637
"pointer" => Some(PrimitiveType::RawPointer),
1638+
"reference" => Some(PrimitiveType::Reference),
16361639
_ => None,
16371640
}
16381641
}
@@ -1661,6 +1664,7 @@ impl PrimitiveType {
16611664
Slice => "slice",
16621665
Tuple => "tuple",
16631666
RawPointer => "pointer",
1667+
Reference => "reference",
16641668
}
16651669
}
16661670

@@ -2556,6 +2560,7 @@ fn build_deref_target_impls(cx: &DocContext,
25562560
Array => tcx.lang_items.slice_impl(),
25572561
Tuple => None,
25582562
RawPointer => tcx.lang_items.const_ptr_impl(),
2563+
Reference => None,
25592564
};
25602565
if let Some(did) = did {
25612566
if !did.is_local() {
@@ -2777,6 +2782,9 @@ fn resolve_type(cx: &DocContext,
27772782
Def::SelfTy(..) if path.segments.len() == 1 => {
27782783
return Generic(keywords::SelfType.name().to_string());
27792784
}
2785+
Def::TyParam(..) if path.segments.len() == 1 => {
2786+
return Generic(format!("{:#}", path));
2787+
}
27802788
Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
27812789
_ => false,
27822790
};

src/librustdoc/html/format.rs

+17-19
Original file line numberDiff line numberDiff line change
@@ -665,50 +665,48 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
665665
_ => "".to_string(),
666666
};
667667
let m = MutableSpace(mutability);
668+
let amp = if f.alternate() {
669+
"&".to_string()
670+
} else {
671+
"&".to_string()
672+
};
668673
match **ty {
669674
clean::Slice(ref bt) => { // BorrowedRef{ ... Slice(T) } is &[T]
670675
match **bt {
671676
clean::Generic(_) => {
672677
if f.alternate() {
673678
primitive_link(f, PrimitiveType::Slice,
674-
&format!("&{}{}[{:#}]", lt, m, **bt))
679+
&format!("{}{}{}[{:#}]", amp, lt, m, **bt))
675680
} else {
676681
primitive_link(f, PrimitiveType::Slice,
677-
&format!("&{}{}[{}]", lt, m, **bt))
682+
&format!("{}{}{}[{}]", amp, lt, m, **bt))
678683
}
679684
}
680685
_ => {
686+
primitive_link(f, PrimitiveType::Slice,
687+
&format!("{}{}{}[", amp, lt, m))?;
681688
if f.alternate() {
682-
primitive_link(f, PrimitiveType::Slice,
683-
&format!("&{}{}[", lt, m))?;
684689
write!(f, "{:#}", **bt)?;
685690
} else {
686-
primitive_link(f, PrimitiveType::Slice,
687-
&format!("&{}{}[", lt, m))?;
688691
write!(f, "{}", **bt)?;
689692
}
690693
primitive_link(f, PrimitiveType::Slice, "]")
691694
}
692695
}
693696
}
694697
clean::ResolvedPath { typarams: Some(ref v), .. } if !v.is_empty() => {
695-
if f.alternate() {
696-
write!(f, "&{}{}", lt, m)?;
697-
} else {
698-
write!(f, "&{}{}", lt, m)?;
699-
}
700-
write!(f, "(")?;
698+
write!(f, "{}{}{}(", amp, lt, m)?;
701699
fmt_type(&ty, f, use_absolute)?;
702700
write!(f, ")")
703701
}
702+
clean::Generic(..) => {
703+
primitive_link(f, PrimitiveType::Reference,
704+
&format!("{}{}{}", amp, lt, m))?;
705+
fmt_type(&ty, f, use_absolute)
706+
}
704707
_ => {
705-
if f.alternate() {
706-
write!(f, "&{}{}", lt, m)?;
707-
fmt_type(&ty, f, use_absolute)
708-
} else {
709-
write!(f, "&{}{}", lt, m)?;
710-
fmt_type(&ty, f, use_absolute)
711-
}
708+
write!(f, "{}{}{}", amp, lt, m)?;
709+
fmt_type(&ty, f, use_absolute)
712710
}
713711
}
714712
}

src/libstd/primitive_docs.rs

+117
Original file line numberDiff line numberDiff line change
@@ -722,3 +722,120 @@ mod prim_isize { }
722722
///
723723
#[stable(feature = "rust1", since = "1.0.0")]
724724
mod prim_usize { }
725+
726+
#[doc(primitive = "reference")]
727+
//
728+
/// References, both shared and mutable.
729+
///
730+
/// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
731+
/// operators on a value, or by using a `ref` or `ref mut` pattern.
732+
///
733+
/// For those familiar with pointers, a reference is just a pointer that is assumed to not be null.
734+
/// In fact, `Option<&T>` has the same memory representation as a nullable pointer, and can be
735+
/// passed across FFI boundaries as such.
736+
///
737+
/// In most cases, references can be used much like the original value. Field access, method
738+
/// calling, and indexing work the same (save for mutability rules, of course). In addition, the
739+
/// comparison operators transparently defer to the referent's implementation, allowing references
740+
/// to be compared the same as owned values.
741+
///
742+
/// References have a lifetime attached to them, which represents the scope for which the borrow is
743+
/// valid. A lifetime is said to "outlive" another one if its representative scope is as long or
744+
/// longer than the other. The `'static` lifetime is the longest lifetime, which represents the
745+
/// total life of the program. For example, string literals have a `'static` lifetime because the
746+
/// text data is embedded into the binary of the program, rather than in an allocation that needs
747+
/// to be dynamically managed.
748+
///
749+
/// `&mut T` references can be freely coerced into `&T` references with the same referent type, and
750+
/// references with longer lifetimes can be freely coerced into references with shorter ones.
751+
///
752+
/// For more information on how to use references, see [the book's section on "References and
753+
/// Borrowing"][book-refs].
754+
///
755+
/// [book-refs]: ../book/second-edition/ch04-02-references-and-borrowing.html
756+
///
757+
/// The following traits are implemented for all `&T`, regardless of the type of its referent:
758+
///
759+
/// * [`Copy`]
760+
/// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!)
761+
/// * [`Deref`]
762+
/// * [`Borrow`]
763+
/// * [`Pointer`]
764+
///
765+
/// [`Copy`]: marker/trait.Copy.html
766+
/// [`Clone`]: clone/trait.Clone.html
767+
/// [`Deref`]: ops/trait.Deref.html
768+
/// [`Borrow`]: borrow/trait.Borrow.html
769+
/// [`Pointer`]: fmt/trait.Pointer.html
770+
///
771+
/// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating
772+
/// multiple simultaneous mutable borrows), plus the following, regardless of the type of its
773+
/// referent:
774+
///
775+
/// * [`DerefMut`]
776+
/// * [`BorrowMut`]
777+
///
778+
/// [`DerefMut`]: ops/trait.DerefMut.html
779+
/// [`BorrowMut`]: borrow/trait.BorrowMut.html
780+
///
781+
/// The following traits are implemented on `&T` references if the underlying `T` also implements
782+
/// that trait:
783+
///
784+
/// * All the traits in [`std::fmt`] except [`Pointer`] and [`fmt::Write`]
785+
/// * [`PartialOrd`]
786+
/// * [`Ord`]
787+
/// * [`PartialEq`]
788+
/// * [`Eq`]
789+
/// * [`AsRef`]
790+
/// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`)
791+
/// * [`Hash`]
792+
/// * [`ToSocketAddrs`]
793+
///
794+
/// [`std::fmt`]: fmt/index.html
795+
/// [`fmt::Write`]: fmt/trait.Write.html
796+
/// [`PartialOrd`]: cmp/trait.PartialOrd.html
797+
/// [`Ord`]: cmp/trait.Ord.html
798+
/// [`PartialEq`]: cmp/trait.PartialEq.html
799+
/// [`Eq`]: cmp/trait.Eq.html
800+
/// [`AsRef`]: convert/trait.AsRef.html
801+
/// [`Fn`]: ops/trait.Fn.html
802+
/// [`FnMut`]: ops/trait.FnMut.html
803+
/// [`FnOnce`]: ops/trait.FnOnce.html
804+
/// [`Hash`]: hash/trait.Hash.html
805+
/// [`ToSocketAddrs`]: net/trait.ToSocketAddrs.html
806+
///
807+
/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
808+
/// implements that trait:
809+
///
810+
/// * [`AsMut`]
811+
/// * [`FnMut`] \(in addition, `&mut T` references get [`FnOnce`] if `T: FnMut`)
812+
/// * [`fmt::Write`]
813+
/// * [`Iterator`]
814+
/// * [`DoubleEndedIterator`]
815+
/// * [`ExactSizeIterator`]
816+
/// * [`FusedIterator`]
817+
/// * [`TrustedLen`]
818+
/// * [`Send`] \(note that `&T` references only get `Send` if `T: Sync`)
819+
/// * [`io::Write`]
820+
/// * [`Read`]
821+
/// * [`Seek`]
822+
/// * [`BufRead`]
823+
///
824+
/// [`AsMut`]: convert/trait.AsMut.html
825+
/// [`Iterator`]: iter/trait.Iterator.html
826+
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
827+
/// [`ExactSizeIterator`]: iter/trait.ExactSizeIterator.html
828+
/// [`FusedIterator`]: iter/trait.FusedIterator.html
829+
/// [`TrustedLen`]: iter/trait.TrustedLen.html
830+
/// [`Send`]: marker/trait.Send.html
831+
/// [`io::Write`]: io/trait.Write.html
832+
/// [`Read`]: io/trait.Read.html
833+
/// [`Seek`]: io/trait.Seek.html
834+
/// [`BufRead`]: io/trait.BufRead.html
835+
///
836+
/// Note that due to method call deref coercion, simply calling a trait method will act like they
837+
/// work on references as well as they do on owned values! The implementations described here are
838+
/// meant for generic contexts, where the final type `T` is a type parameter or otherwise not
839+
/// locally known.
840+
#[stable(feature = "rust1", since = "1.0.0")]
841+
mod prim_ref { }

0 commit comments

Comments
 (0)