Auto merge of #88165 - GuillaumeGomez:rollup-4o0v2ps, r=GuillaumeGomez
Rollup of 8 pull requests Successful merges: - #86123 (Preserve more spans in internal `rustc_queries!` macro) - #87874 (Add TcpStream type to TcpListener::incoming docs) - #88034 (rustc_privacy: Replace `HirId`s and `DefId`s with `LocalDefId`s where possible) - #88050 (Remove `HashStable` impls for `FileName` and `RealFileName`) - #88093 ([rustdoc] Wrap code blocks in `<code>` tag) - #88146 (Add tests for some `feature(const_evaluatable_checked)` incr comp issues) - #88153 (Update .mailmap) - #88159 (Use a trait instead of the now disallowed missing trait there) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
6d64f7f695
21 changed files with 641 additions and 408 deletions
1
.mailmap
1
.mailmap
|
@ -113,6 +113,7 @@ Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com>
|
||||||
Heather <heather@cynede.net> <Cynede@Gentoo.org>
|
Heather <heather@cynede.net> <Cynede@Gentoo.org>
|
||||||
Heather <heather@cynede.net> <Heather@cynede.net>
|
Heather <heather@cynede.net> <Heather@cynede.net>
|
||||||
Herman J. Radtke III <herman@hermanradtke.com> Herman J. Radtke III <hermanradtke@gmail.com>
|
Herman J. Radtke III <herman@hermanradtke.com> Herman J. Radtke III <hermanradtke@gmail.com>
|
||||||
|
Hirochika Matsumoto <git@hkmatsumoto.com> <matsujika@gmail.com>
|
||||||
Ian Jackson <ijackson@chiark.greenend.org.uk> <ian.jackson@citrix.com>
|
Ian Jackson <ijackson@chiark.greenend.org.uk> <ian.jackson@citrix.com>
|
||||||
Ian Jackson <ijackson@chiark.greenend.org.uk> <ijackson+github@slimy.greenend.org.uk>
|
Ian Jackson <ijackson@chiark.greenend.org.uk> <ijackson+github@slimy.greenend.org.uk>
|
||||||
Ian Jackson <ijackson@chiark.greenend.org.uk> <iwj@xenproject.org>
|
Ian Jackson <ijackson@chiark.greenend.org.uk> <iwj@xenproject.org>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Delimiter, TokenTree};
|
use proc_macro2::{Delimiter, TokenTree};
|
||||||
use quote::quote;
|
use quote::{quote, quote_spanned};
|
||||||
use syn::parse::{Parse, ParseStream, Result};
|
use syn::parse::{Parse, ParseStream, Result};
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
|
@ -42,19 +42,19 @@ enum QueryModifier {
|
||||||
LoadCached(Ident, Ident, Block),
|
LoadCached(Ident, Ident, Block),
|
||||||
|
|
||||||
/// A cycle error for this query aborting the compilation with a fatal error.
|
/// A cycle error for this query aborting the compilation with a fatal error.
|
||||||
FatalCycle,
|
FatalCycle(Ident),
|
||||||
|
|
||||||
/// A cycle error results in a delay_bug call
|
/// A cycle error results in a delay_bug call
|
||||||
CycleDelayBug,
|
CycleDelayBug(Ident),
|
||||||
|
|
||||||
/// Don't hash the result, instead just mark a query red if it runs
|
/// Don't hash the result, instead just mark a query red if it runs
|
||||||
NoHash,
|
NoHash(Ident),
|
||||||
|
|
||||||
/// Generate a dep node based on the dependencies of the query
|
/// Generate a dep node based on the dependencies of the query
|
||||||
Anon,
|
Anon(Ident),
|
||||||
|
|
||||||
/// Always evaluate the query, ignoring its dependencies
|
/// Always evaluate the query, ignoring its dependencies
|
||||||
EvalAlways,
|
EvalAlways(Ident),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for QueryModifier {
|
impl Parse for QueryModifier {
|
||||||
|
@ -111,15 +111,15 @@ impl Parse for QueryModifier {
|
||||||
let ty = args.parse()?;
|
let ty = args.parse()?;
|
||||||
Ok(QueryModifier::Storage(ty))
|
Ok(QueryModifier::Storage(ty))
|
||||||
} else if modifier == "fatal_cycle" {
|
} else if modifier == "fatal_cycle" {
|
||||||
Ok(QueryModifier::FatalCycle)
|
Ok(QueryModifier::FatalCycle(modifier))
|
||||||
} else if modifier == "cycle_delay_bug" {
|
} else if modifier == "cycle_delay_bug" {
|
||||||
Ok(QueryModifier::CycleDelayBug)
|
Ok(QueryModifier::CycleDelayBug(modifier))
|
||||||
} else if modifier == "no_hash" {
|
} else if modifier == "no_hash" {
|
||||||
Ok(QueryModifier::NoHash)
|
Ok(QueryModifier::NoHash(modifier))
|
||||||
} else if modifier == "anon" {
|
} else if modifier == "anon" {
|
||||||
Ok(QueryModifier::Anon)
|
Ok(QueryModifier::Anon(modifier))
|
||||||
} else if modifier == "eval_always" {
|
} else if modifier == "eval_always" {
|
||||||
Ok(QueryModifier::EvalAlways)
|
Ok(QueryModifier::EvalAlways(modifier))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::new(modifier.span(), "unknown query modifier"))
|
Err(Error::new(modifier.span(), "unknown query modifier"))
|
||||||
}
|
}
|
||||||
|
@ -203,19 +203,19 @@ struct QueryModifiers {
|
||||||
load_cached: Option<(Ident, Ident, Block)>,
|
load_cached: Option<(Ident, Ident, Block)>,
|
||||||
|
|
||||||
/// A cycle error for this query aborting the compilation with a fatal error.
|
/// A cycle error for this query aborting the compilation with a fatal error.
|
||||||
fatal_cycle: bool,
|
fatal_cycle: Option<Ident>,
|
||||||
|
|
||||||
/// A cycle error results in a delay_bug call
|
/// A cycle error results in a delay_bug call
|
||||||
cycle_delay_bug: bool,
|
cycle_delay_bug: Option<Ident>,
|
||||||
|
|
||||||
/// Don't hash the result, instead just mark a query red if it runs
|
/// Don't hash the result, instead just mark a query red if it runs
|
||||||
no_hash: bool,
|
no_hash: Option<Ident>,
|
||||||
|
|
||||||
/// Generate a dep node based on the dependencies of the query
|
/// Generate a dep node based on the dependencies of the query
|
||||||
anon: bool,
|
anon: Option<Ident>,
|
||||||
|
|
||||||
// Always evaluate the query, ignoring its dependencies
|
// Always evaluate the query, ignoring its dependencies
|
||||||
eval_always: bool,
|
eval_always: Option<Ident>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process query modifiers into a struct, erroring on duplicates
|
/// Process query modifiers into a struct, erroring on duplicates
|
||||||
|
@ -224,11 +224,11 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
|
||||||
let mut storage = None;
|
let mut storage = None;
|
||||||
let mut cache = None;
|
let mut cache = None;
|
||||||
let mut desc = None;
|
let mut desc = None;
|
||||||
let mut fatal_cycle = false;
|
let mut fatal_cycle = None;
|
||||||
let mut cycle_delay_bug = false;
|
let mut cycle_delay_bug = None;
|
||||||
let mut no_hash = false;
|
let mut no_hash = None;
|
||||||
let mut anon = false;
|
let mut anon = None;
|
||||||
let mut eval_always = false;
|
let mut eval_always = None;
|
||||||
for modifier in query.modifiers.0.drain(..) {
|
for modifier in query.modifiers.0.drain(..) {
|
||||||
match modifier {
|
match modifier {
|
||||||
QueryModifier::LoadCached(tcx, id, block) => {
|
QueryModifier::LoadCached(tcx, id, block) => {
|
||||||
|
@ -289,35 +289,35 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
|
||||||
}
|
}
|
||||||
desc = Some((tcx, list));
|
desc = Some((tcx, list));
|
||||||
}
|
}
|
||||||
QueryModifier::FatalCycle => {
|
QueryModifier::FatalCycle(ident) => {
|
||||||
if fatal_cycle {
|
if fatal_cycle.is_some() {
|
||||||
panic!("duplicate modifier `fatal_cycle` for query `{}`", query.name);
|
panic!("duplicate modifier `fatal_cycle` for query `{}`", query.name);
|
||||||
}
|
}
|
||||||
fatal_cycle = true;
|
fatal_cycle = Some(ident);
|
||||||
}
|
}
|
||||||
QueryModifier::CycleDelayBug => {
|
QueryModifier::CycleDelayBug(ident) => {
|
||||||
if cycle_delay_bug {
|
if cycle_delay_bug.is_some() {
|
||||||
panic!("duplicate modifier `cycle_delay_bug` for query `{}`", query.name);
|
panic!("duplicate modifier `cycle_delay_bug` for query `{}`", query.name);
|
||||||
}
|
}
|
||||||
cycle_delay_bug = true;
|
cycle_delay_bug = Some(ident);
|
||||||
}
|
}
|
||||||
QueryModifier::NoHash => {
|
QueryModifier::NoHash(ident) => {
|
||||||
if no_hash {
|
if no_hash.is_some() {
|
||||||
panic!("duplicate modifier `no_hash` for query `{}`", query.name);
|
panic!("duplicate modifier `no_hash` for query `{}`", query.name);
|
||||||
}
|
}
|
||||||
no_hash = true;
|
no_hash = Some(ident);
|
||||||
}
|
}
|
||||||
QueryModifier::Anon => {
|
QueryModifier::Anon(ident) => {
|
||||||
if anon {
|
if anon.is_some() {
|
||||||
panic!("duplicate modifier `anon` for query `{}`", query.name);
|
panic!("duplicate modifier `anon` for query `{}`", query.name);
|
||||||
}
|
}
|
||||||
anon = true;
|
anon = Some(ident);
|
||||||
}
|
}
|
||||||
QueryModifier::EvalAlways => {
|
QueryModifier::EvalAlways(ident) => {
|
||||||
if eval_always {
|
if eval_always.is_some() {
|
||||||
panic!("duplicate modifier `eval_always` for query `{}`", query.name);
|
panic!("duplicate modifier `eval_always` for query `{}`", query.name);
|
||||||
}
|
}
|
||||||
eval_always = true;
|
eval_always = Some(ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,31 +454,39 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||||
let mut attributes = Vec::new();
|
let mut attributes = Vec::new();
|
||||||
|
|
||||||
// Pass on the fatal_cycle modifier
|
// Pass on the fatal_cycle modifier
|
||||||
if modifiers.fatal_cycle {
|
if let Some(fatal_cycle) = &modifiers.fatal_cycle {
|
||||||
attributes.push(quote! { fatal_cycle });
|
attributes.push(quote! { #fatal_cycle });
|
||||||
};
|
};
|
||||||
// Pass on the storage modifier
|
// Pass on the storage modifier
|
||||||
if let Some(ref ty) = modifiers.storage {
|
if let Some(ref ty) = modifiers.storage {
|
||||||
attributes.push(quote! { storage(#ty) });
|
let span = ty.span();
|
||||||
|
attributes.push(quote_spanned! {span=> storage(#ty) });
|
||||||
};
|
};
|
||||||
// Pass on the cycle_delay_bug modifier
|
// Pass on the cycle_delay_bug modifier
|
||||||
if modifiers.cycle_delay_bug {
|
if let Some(cycle_delay_bug) = &modifiers.cycle_delay_bug {
|
||||||
attributes.push(quote! { cycle_delay_bug });
|
attributes.push(quote! { #cycle_delay_bug });
|
||||||
};
|
};
|
||||||
// Pass on the no_hash modifier
|
// Pass on the no_hash modifier
|
||||||
if modifiers.no_hash {
|
if let Some(no_hash) = &modifiers.no_hash {
|
||||||
attributes.push(quote! { no_hash });
|
attributes.push(quote! { #no_hash });
|
||||||
};
|
};
|
||||||
// Pass on the anon modifier
|
// Pass on the anon modifier
|
||||||
if modifiers.anon {
|
if let Some(anon) = &modifiers.anon {
|
||||||
attributes.push(quote! { anon });
|
attributes.push(quote! { #anon });
|
||||||
};
|
};
|
||||||
// Pass on the eval_always modifier
|
// Pass on the eval_always modifier
|
||||||
if modifiers.eval_always {
|
if let Some(eval_always) = &modifiers.eval_always {
|
||||||
attributes.push(quote! { eval_always });
|
attributes.push(quote! { #eval_always });
|
||||||
};
|
};
|
||||||
|
|
||||||
let attribute_stream = quote! {#(#attributes),*};
|
// This uses the span of the query definition for the commas,
|
||||||
|
// which can be important if we later encounter any ambiguity
|
||||||
|
// errors with any of the numerous macro_rules! macros that
|
||||||
|
// we use. Using the call-site span would result in a span pointing
|
||||||
|
// at the entire `rustc_queries!` invocation, which wouldn't
|
||||||
|
// be very useful.
|
||||||
|
let span = name.span();
|
||||||
|
let attribute_stream = quote_spanned! {span=> #(#attributes),*};
|
||||||
let doc_comments = query.doc_comments.iter();
|
let doc_comments = query.doc_comments.iter();
|
||||||
// Add the query to the group
|
// Add the query to the group
|
||||||
query_stream.extend(quote! {
|
query_stream.extend(quote! {
|
||||||
|
|
|
@ -11,7 +11,8 @@ use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::struct_span_err;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet};
|
||||||
|
use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||||
use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind};
|
use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
|
@ -354,9 +355,8 @@ trait VisibilityLike: Sized {
|
||||||
|
|
||||||
// Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
|
// Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
|
||||||
// associated types for which we can't determine visibility precisely.
|
// associated types for which we can't determine visibility precisely.
|
||||||
fn of_impl(hir_id: hir::HirId, tcx: TyCtxt<'_>, access_levels: &AccessLevels) -> Self {
|
fn of_impl(def_id: LocalDefId, tcx: TyCtxt<'_>, access_levels: &AccessLevels) -> Self {
|
||||||
let mut find = FindMin { tcx, access_levels, min: Self::MAX };
|
let mut find = FindMin { tcx, access_levels, min: Self::MAX };
|
||||||
let def_id = tcx.hir().local_def_id(hir_id);
|
|
||||||
find.visit(tcx.type_of(def_id));
|
find.visit(tcx.type_of(def_id));
|
||||||
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
|
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
|
||||||
find.visit_trait(trait_ref);
|
find.visit_trait(trait_ref);
|
||||||
|
@ -424,7 +424,7 @@ struct EmbargoVisitor<'tcx> {
|
||||||
|
|
||||||
struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
|
struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
|
||||||
access_level: Option<AccessLevel>,
|
access_level: Option<AccessLevel>,
|
||||||
item_def_id: DefId,
|
item_def_id: LocalDefId,
|
||||||
ev: &'a mut EmbargoVisitor<'tcx>,
|
ev: &'a mut EmbargoVisitor<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,12 +448,12 @@ impl EmbargoVisitor<'tcx> {
|
||||||
|
|
||||||
fn reach(
|
fn reach(
|
||||||
&mut self,
|
&mut self,
|
||||||
item_id: hir::HirId,
|
def_id: LocalDefId,
|
||||||
access_level: Option<AccessLevel>,
|
access_level: Option<AccessLevel>,
|
||||||
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
||||||
ReachEverythingInTheInterfaceVisitor {
|
ReachEverythingInTheInterfaceVisitor {
|
||||||
access_level: cmp::min(access_level, Some(AccessLevel::Reachable)),
|
access_level: cmp::min(access_level, Some(AccessLevel::Reachable)),
|
||||||
item_def_id: self.tcx.hir().local_def_id(item_id).to_def_id(),
|
item_def_id: def_id,
|
||||||
ev: self,
|
ev: self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -536,10 +536,10 @@ impl EmbargoVisitor<'tcx> {
|
||||||
| hir::ItemKind::Union(ref struct_def, _) = item.kind
|
| hir::ItemKind::Union(ref struct_def, _) = item.kind
|
||||||
{
|
{
|
||||||
for field in struct_def.fields() {
|
for field in struct_def.fields() {
|
||||||
let field_vis =
|
let def_id = self.tcx.hir().local_def_id(field.hir_id);
|
||||||
self.tcx.visibility(self.tcx.hir().local_def_id(field.hir_id));
|
let field_vis = self.tcx.visibility(def_id);
|
||||||
if field_vis.is_accessible_from(module.to_def_id(), self.tcx) {
|
if field_vis.is_accessible_from(module.to_def_id(), self.tcx) {
|
||||||
self.reach(field.hir_id, level).ty();
|
self.reach(def_id, level).ty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -638,7 +638,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||||
let inherited_item_level = match item.kind {
|
let inherited_item_level = match item.kind {
|
||||||
hir::ItemKind::Impl { .. } => {
|
hir::ItemKind::Impl { .. } => {
|
||||||
Option::<AccessLevel>::of_impl(item.hir_id(), self.tcx, &self.access_levels)
|
Option::<AccessLevel>::of_impl(item.def_id, self.tcx, &self.access_levels)
|
||||||
}
|
}
|
||||||
// Foreign modules inherit level from parents.
|
// Foreign modules inherit level from parents.
|
||||||
hir::ItemKind::ForeignMod { .. } => self.prev_level,
|
hir::ItemKind::ForeignMod { .. } => self.prev_level,
|
||||||
|
@ -750,7 +750,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||||
// reachable if they are returned via `impl Trait`, even from private functions.
|
// reachable if they are returned via `impl Trait`, even from private functions.
|
||||||
let exist_level =
|
let exist_level =
|
||||||
cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait));
|
cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait));
|
||||||
self.reach(item.hir_id(), exist_level).generics().predicates().ty();
|
self.reach(item.def_id, exist_level).generics().predicates().ty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Visit everything.
|
// Visit everything.
|
||||||
|
@ -759,15 +759,15 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||||
| hir::ItemKind::Fn(..)
|
| hir::ItemKind::Fn(..)
|
||||||
| hir::ItemKind::TyAlias(..) => {
|
| hir::ItemKind::TyAlias(..) => {
|
||||||
if item_level.is_some() {
|
if item_level.is_some() {
|
||||||
self.reach(item.hir_id(), item_level).generics().predicates().ty();
|
self.reach(item.def_id, item_level).generics().predicates().ty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::Trait(.., trait_item_refs) => {
|
hir::ItemKind::Trait(.., trait_item_refs) => {
|
||||||
if item_level.is_some() {
|
if item_level.is_some() {
|
||||||
self.reach(item.hir_id(), item_level).generics().predicates();
|
self.reach(item.def_id, item_level).generics().predicates();
|
||||||
|
|
||||||
for trait_item_ref in trait_item_refs {
|
for trait_item_ref in trait_item_refs {
|
||||||
let mut reach = self.reach(trait_item_ref.id.hir_id(), item_level);
|
let mut reach = self.reach(trait_item_ref.id.def_id, item_level);
|
||||||
reach.generics().predicates();
|
reach.generics().predicates();
|
||||||
|
|
||||||
if trait_item_ref.kind == AssocItemKind::Type
|
if trait_item_ref.kind == AssocItemKind::Type
|
||||||
|
@ -782,18 +782,18 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
hir::ItemKind::TraitAlias(..) => {
|
hir::ItemKind::TraitAlias(..) => {
|
||||||
if item_level.is_some() {
|
if item_level.is_some() {
|
||||||
self.reach(item.hir_id(), item_level).generics().predicates();
|
self.reach(item.def_id, item_level).generics().predicates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Visit everything except for private impl items.
|
// Visit everything except for private impl items.
|
||||||
hir::ItemKind::Impl(ref impl_) => {
|
hir::ItemKind::Impl(ref impl_) => {
|
||||||
if item_level.is_some() {
|
if item_level.is_some() {
|
||||||
self.reach(item.hir_id(), item_level).generics().predicates().ty().trait_ref();
|
self.reach(item.def_id, item_level).generics().predicates().ty().trait_ref();
|
||||||
|
|
||||||
for impl_item_ref in impl_.items {
|
for impl_item_ref in impl_.items {
|
||||||
let impl_item_level = self.get(impl_item_ref.id.def_id);
|
let impl_item_level = self.get(impl_item_ref.id.def_id);
|
||||||
if impl_item_level.is_some() {
|
if impl_item_level.is_some() {
|
||||||
self.reach(impl_item_ref.id.hir_id(), impl_item_level)
|
self.reach(impl_item_ref.id.def_id, impl_item_level)
|
||||||
.generics()
|
.generics()
|
||||||
.predicates()
|
.predicates()
|
||||||
.ty();
|
.ty();
|
||||||
|
@ -805,13 +805,14 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||||
// Visit everything, but enum variants have their own levels.
|
// Visit everything, but enum variants have their own levels.
|
||||||
hir::ItemKind::Enum(ref def, _) => {
|
hir::ItemKind::Enum(ref def, _) => {
|
||||||
if item_level.is_some() {
|
if item_level.is_some() {
|
||||||
self.reach(item.hir_id(), item_level).generics().predicates();
|
self.reach(item.def_id, item_level).generics().predicates();
|
||||||
}
|
}
|
||||||
for variant in def.variants {
|
for variant in def.variants {
|
||||||
let variant_level = self.get(self.tcx.hir().local_def_id(variant.id));
|
let variant_level = self.get(self.tcx.hir().local_def_id(variant.id));
|
||||||
if variant_level.is_some() {
|
if variant_level.is_some() {
|
||||||
for field in variant.data.fields() {
|
for field in variant.data.fields() {
|
||||||
self.reach(field.hir_id, variant_level).ty();
|
self.reach(self.tcx.hir().local_def_id(field.hir_id), variant_level)
|
||||||
|
.ty();
|
||||||
}
|
}
|
||||||
// Corner case: if the variant is reachable, but its
|
// Corner case: if the variant is reachable, but its
|
||||||
// enum is not, make the enum reachable as well.
|
// enum is not, make the enum reachable as well.
|
||||||
|
@ -824,7 +825,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||||
for foreign_item in items {
|
for foreign_item in items {
|
||||||
let foreign_item_level = self.get(foreign_item.id.def_id);
|
let foreign_item_level = self.get(foreign_item.id.def_id);
|
||||||
if foreign_item_level.is_some() {
|
if foreign_item_level.is_some() {
|
||||||
self.reach(foreign_item.id.hir_id(), foreign_item_level)
|
self.reach(foreign_item.id.def_id, foreign_item_level)
|
||||||
.generics()
|
.generics()
|
||||||
.predicates()
|
.predicates()
|
||||||
.ty();
|
.ty();
|
||||||
|
@ -834,11 +835,12 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||||
// Visit everything except for private fields.
|
// Visit everything except for private fields.
|
||||||
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
|
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
|
||||||
if item_level.is_some() {
|
if item_level.is_some() {
|
||||||
self.reach(item.hir_id(), item_level).generics().predicates();
|
self.reach(item.def_id, item_level).generics().predicates();
|
||||||
for field in struct_def.fields() {
|
for field in struct_def.fields() {
|
||||||
let field_level = self.get(self.tcx.hir().local_def_id(field.hir_id));
|
let def_id = self.tcx.hir().local_def_id(field.hir_id);
|
||||||
|
let field_level = self.get(def_id);
|
||||||
if field_level.is_some() {
|
if field_level.is_some() {
|
||||||
self.reach(field.hir_id, field_level).ty();
|
self.reach(def_id, field_level).ty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -992,7 +994,7 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
||||||
struct NamePrivacyVisitor<'tcx> {
|
struct NamePrivacyVisitor<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
|
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
|
||||||
current_item: Option<hir::HirId>,
|
current_item: LocalDefId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> NamePrivacyVisitor<'tcx> {
|
impl<'tcx> NamePrivacyVisitor<'tcx> {
|
||||||
|
@ -1014,11 +1016,15 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
|
||||||
field: &'tcx ty::FieldDef,
|
field: &'tcx ty::FieldDef,
|
||||||
in_update_syntax: bool,
|
in_update_syntax: bool,
|
||||||
) {
|
) {
|
||||||
|
if def.is_enum() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// definition of the field
|
// definition of the field
|
||||||
let ident = Ident::new(kw::Empty, use_ctxt);
|
let ident = Ident::new(kw::Empty, use_ctxt);
|
||||||
let current_hir = self.current_item.unwrap();
|
let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.current_item);
|
||||||
let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did, current_hir).1;
|
let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did, hir_id).1;
|
||||||
if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
|
if !field.vis.is_accessible_from(def_id, self.tcx) {
|
||||||
let label = if in_update_syntax {
|
let label = if in_update_syntax {
|
||||||
format!("field `{}` is private", field.ident)
|
format!("field `{}` is private", field.ident)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1063,7 +1069,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||||
let orig_current_item = self.current_item.replace(item.hir_id());
|
let orig_current_item = mem::replace(&mut self.current_item, item.def_id);
|
||||||
intravisit::walk_item(self, item);
|
intravisit::walk_item(self, item);
|
||||||
self.current_item = orig_current_item;
|
self.current_item = orig_current_item;
|
||||||
}
|
}
|
||||||
|
@ -1763,9 +1769,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
item_id: hir::HirId,
|
item_def_id: LocalDefId,
|
||||||
item_def_id: DefId,
|
|
||||||
span: Span,
|
|
||||||
/// The visitor checks that each component type is at least this visible.
|
/// The visitor checks that each component type is at least this visible.
|
||||||
required_visibility: ty::Visibility,
|
required_visibility: ty::Visibility,
|
||||||
has_pub_restricted: bool,
|
has_pub_restricted: bool,
|
||||||
|
@ -1820,8 +1824,8 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
||||||
if self.leaks_private_dep(def_id) {
|
if self.leaks_private_dep(def_id) {
|
||||||
self.tcx.struct_span_lint_hir(
|
self.tcx.struct_span_lint_hir(
|
||||||
lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
|
lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
|
||||||
self.item_id,
|
self.tcx.hir().local_def_id_to_hir_id(self.item_def_id),
|
||||||
self.span,
|
self.tcx.def_span(self.item_def_id.to_def_id()),
|
||||||
|lint| {
|
|lint| {
|
||||||
lint.build(&format!(
|
lint.build(&format!(
|
||||||
"{} `{}` from private dependency '{}' in public \
|
"{} `{}` from private dependency '{}' in public \
|
||||||
|
@ -1856,15 +1860,16 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr);
|
let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr);
|
||||||
|
let span = self.tcx.def_span(self.item_def_id.to_def_id());
|
||||||
if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
|
if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
|
||||||
let mut err = if kind == "trait" {
|
let mut err = if kind == "trait" {
|
||||||
struct_span_err!(self.tcx.sess, self.span, E0445, "{}", make_msg())
|
struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg())
|
||||||
} else {
|
} else {
|
||||||
struct_span_err!(self.tcx.sess, self.span, E0446, "{}", make_msg())
|
struct_span_err!(self.tcx.sess, span, E0446, "{}", make_msg())
|
||||||
};
|
};
|
||||||
let vis_span =
|
let vis_span =
|
||||||
self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id));
|
self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id));
|
||||||
err.span_label(self.span, format!("can't leak {} {}", vis_descr, kind));
|
err.span_label(span, format!("can't leak {} {}", vis_descr, kind));
|
||||||
err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr));
|
err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr));
|
||||||
err.emit();
|
err.emit();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1872,7 +1877,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
||||||
self.tcx.struct_span_lint_hir(
|
self.tcx.struct_span_lint_hir(
|
||||||
lint::builtin::PRIVATE_IN_PUBLIC,
|
lint::builtin::PRIVATE_IN_PUBLIC,
|
||||||
hir_id,
|
hir_id,
|
||||||
self.span,
|
span,
|
||||||
|lint| lint.build(&format!("{} (error {})", make_msg(), err_code)).emit(),
|
|lint| lint.build(&format!("{} (error {})", make_msg(), err_code)).emit(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1915,35 +1920,33 @@ impl DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
||||||
struct PrivateItemsInPublicInterfacesVisitor<'tcx> {
|
struct PrivateItemsInPublicInterfacesVisitor<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
has_pub_restricted: bool,
|
has_pub_restricted: bool,
|
||||||
old_error_set_ancestry: HirIdSet,
|
old_error_set_ancestry: LocalDefIdSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PrivateItemsInPublicInterfacesVisitor<'tcx> {
|
impl<'tcx> PrivateItemsInPublicInterfacesVisitor<'tcx> {
|
||||||
fn check(
|
fn check(
|
||||||
&self,
|
&self,
|
||||||
item_id: hir::HirId,
|
def_id: LocalDefId,
|
||||||
required_visibility: ty::Visibility,
|
required_visibility: ty::Visibility,
|
||||||
) -> SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
) -> SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
||||||
SearchInterfaceForPrivateItemsVisitor {
|
SearchInterfaceForPrivateItemsVisitor {
|
||||||
tcx: self.tcx,
|
tcx: self.tcx,
|
||||||
item_id,
|
item_def_id: def_id,
|
||||||
item_def_id: self.tcx.hir().local_def_id(item_id).to_def_id(),
|
|
||||||
span: self.tcx.hir().span(item_id),
|
|
||||||
required_visibility,
|
required_visibility,
|
||||||
has_pub_restricted: self.has_pub_restricted,
|
has_pub_restricted: self.has_pub_restricted,
|
||||||
has_old_errors: self.old_error_set_ancestry.contains(&item_id),
|
has_old_errors: self.old_error_set_ancestry.contains(&def_id),
|
||||||
in_assoc_ty: false,
|
in_assoc_ty: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_assoc_item(
|
fn check_assoc_item(
|
||||||
&self,
|
&self,
|
||||||
hir_id: hir::HirId,
|
def_id: LocalDefId,
|
||||||
assoc_item_kind: AssocItemKind,
|
assoc_item_kind: AssocItemKind,
|
||||||
defaultness: hir::Defaultness,
|
defaultness: hir::Defaultness,
|
||||||
vis: ty::Visibility,
|
vis: ty::Visibility,
|
||||||
) {
|
) {
|
||||||
let mut check = self.check(hir_id, vis);
|
let mut check = self.check(def_id, vis);
|
||||||
|
|
||||||
let (check_ty, is_assoc_ty) = match assoc_item_kind {
|
let (check_ty, is_assoc_ty) = match assoc_item_kind {
|
||||||
AssocItemKind::Const | AssocItemKind::Fn { .. } => (true, false),
|
AssocItemKind::Const | AssocItemKind::Fn { .. } => (true, false),
|
||||||
|
@ -1982,38 +1985,38 @@ impl<'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'tcx> {
|
||||||
| hir::ItemKind::Static(..)
|
| hir::ItemKind::Static(..)
|
||||||
| hir::ItemKind::Fn(..)
|
| hir::ItemKind::Fn(..)
|
||||||
| hir::ItemKind::TyAlias(..) => {
|
| hir::ItemKind::TyAlias(..) => {
|
||||||
self.check(item.hir_id(), item_visibility).generics().predicates().ty();
|
self.check(item.def_id, item_visibility).generics().predicates().ty();
|
||||||
}
|
}
|
||||||
hir::ItemKind::OpaqueTy(..) => {
|
hir::ItemKind::OpaqueTy(..) => {
|
||||||
// `ty()` for opaque types is the underlying type,
|
// `ty()` for opaque types is the underlying type,
|
||||||
// it's not a part of interface, so we skip it.
|
// it's not a part of interface, so we skip it.
|
||||||
self.check(item.hir_id(), item_visibility).generics().bounds();
|
self.check(item.def_id, item_visibility).generics().bounds();
|
||||||
}
|
}
|
||||||
hir::ItemKind::Trait(.., trait_item_refs) => {
|
hir::ItemKind::Trait(.., trait_item_refs) => {
|
||||||
self.check(item.hir_id(), item_visibility).generics().predicates();
|
self.check(item.def_id, item_visibility).generics().predicates();
|
||||||
|
|
||||||
for trait_item_ref in trait_item_refs {
|
for trait_item_ref in trait_item_refs {
|
||||||
self.check_assoc_item(
|
self.check_assoc_item(
|
||||||
trait_item_ref.id.hir_id(),
|
trait_item_ref.id.def_id,
|
||||||
trait_item_ref.kind,
|
trait_item_ref.kind,
|
||||||
trait_item_ref.defaultness,
|
trait_item_ref.defaultness,
|
||||||
item_visibility,
|
item_visibility,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let AssocItemKind::Type = trait_item_ref.kind {
|
if let AssocItemKind::Type = trait_item_ref.kind {
|
||||||
self.check(trait_item_ref.id.hir_id(), item_visibility).bounds();
|
self.check(trait_item_ref.id.def_id, item_visibility).bounds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::TraitAlias(..) => {
|
hir::ItemKind::TraitAlias(..) => {
|
||||||
self.check(item.hir_id(), item_visibility).generics().predicates();
|
self.check(item.def_id, item_visibility).generics().predicates();
|
||||||
}
|
}
|
||||||
hir::ItemKind::Enum(ref def, _) => {
|
hir::ItemKind::Enum(ref def, _) => {
|
||||||
self.check(item.hir_id(), item_visibility).generics().predicates();
|
self.check(item.def_id, item_visibility).generics().predicates();
|
||||||
|
|
||||||
for variant in def.variants {
|
for variant in def.variants {
|
||||||
for field in variant.data.fields() {
|
for field in variant.data.fields() {
|
||||||
self.check(field.hir_id, item_visibility).ty();
|
self.check(self.tcx.hir().local_def_id(field.hir_id), item_visibility).ty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2021,16 +2024,17 @@ impl<'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'tcx> {
|
||||||
hir::ItemKind::ForeignMod { items, .. } => {
|
hir::ItemKind::ForeignMod { items, .. } => {
|
||||||
for foreign_item in items {
|
for foreign_item in items {
|
||||||
let vis = tcx.visibility(foreign_item.id.def_id);
|
let vis = tcx.visibility(foreign_item.id.def_id);
|
||||||
self.check(foreign_item.id.hir_id(), vis).generics().predicates().ty();
|
self.check(foreign_item.id.def_id, vis).generics().predicates().ty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Subitems of structs and unions have their own publicity.
|
// Subitems of structs and unions have their own publicity.
|
||||||
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
|
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
|
||||||
self.check(item.hir_id(), item_visibility).generics().predicates();
|
self.check(item.def_id, item_visibility).generics().predicates();
|
||||||
|
|
||||||
for field in struct_def.fields() {
|
for field in struct_def.fields() {
|
||||||
let field_visibility = tcx.visibility(tcx.hir().local_def_id(field.hir_id));
|
let def_id = tcx.hir().local_def_id(field.hir_id);
|
||||||
self.check(field.hir_id, min(item_visibility, field_visibility, tcx)).ty();
|
let field_visibility = tcx.visibility(def_id);
|
||||||
|
self.check(def_id, min(item_visibility, field_visibility, tcx)).ty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// An inherent impl is public when its type is public
|
// An inherent impl is public when its type is public
|
||||||
|
@ -2038,8 +2042,8 @@ impl<'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'tcx> {
|
||||||
// A trait impl is public when both its type and its trait are public
|
// A trait impl is public when both its type and its trait are public
|
||||||
// Subitems of trait impls have inherited publicity.
|
// Subitems of trait impls have inherited publicity.
|
||||||
hir::ItemKind::Impl(ref impl_) => {
|
hir::ItemKind::Impl(ref impl_) => {
|
||||||
let impl_vis = ty::Visibility::of_impl(item.hir_id(), tcx, &Default::default());
|
let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default());
|
||||||
self.check(item.hir_id(), impl_vis).generics().predicates();
|
self.check(item.def_id, impl_vis).generics().predicates();
|
||||||
for impl_item_ref in impl_.items {
|
for impl_item_ref in impl_.items {
|
||||||
let impl_item_vis = if impl_.of_trait.is_none() {
|
let impl_item_vis = if impl_.of_trait.is_none() {
|
||||||
min(tcx.visibility(impl_item_ref.id.def_id), impl_vis, tcx)
|
min(tcx.visibility(impl_item_ref.id.def_id), impl_vis, tcx)
|
||||||
|
@ -2047,7 +2051,7 @@ impl<'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'tcx> {
|
||||||
impl_vis
|
impl_vis
|
||||||
};
|
};
|
||||||
self.check_assoc_item(
|
self.check_assoc_item(
|
||||||
impl_item_ref.id.hir_id(),
|
impl_item_ref.id.def_id,
|
||||||
impl_item_ref.kind,
|
impl_item_ref.kind,
|
||||||
impl_item_ref.defaultness,
|
impl_item_ref.defaultness,
|
||||||
impl_item_vis,
|
impl_item_vis,
|
||||||
|
@ -2119,7 +2123,8 @@ fn visibility(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Visibility {
|
||||||
|
|
||||||
fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||||
// Check privacy of names not checked in previous compilation stages.
|
// Check privacy of names not checked in previous compilation stages.
|
||||||
let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None, current_item: None };
|
let mut visitor =
|
||||||
|
NamePrivacyVisitor { tcx, maybe_typeck_results: None, current_item: module_def_id };
|
||||||
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
||||||
|
|
||||||
intravisit::walk_mod(&mut visitor, module, hir_id);
|
intravisit::walk_mod(&mut visitor, module, hir_id);
|
||||||
|
@ -2188,7 +2193,15 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for private types and traits in public interfaces.
|
// Check for private types and traits in public interfaces.
|
||||||
let mut visitor =
|
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
|
||||||
PrivateItemsInPublicInterfacesVisitor { tcx, has_pub_restricted, old_error_set_ancestry };
|
tcx,
|
||||||
|
has_pub_restricted,
|
||||||
|
// Only definition IDs are ever searched in `old_error_set_ancestry`,
|
||||||
|
// so we can filter away all non-definition IDs at this point.
|
||||||
|
old_error_set_ancestry: old_error_set_ancestry
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|hir_id| tcx.hir().opt_local_def_id(hir_id))
|
||||||
|
.collect(),
|
||||||
|
};
|
||||||
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
|
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,7 +157,7 @@ scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);
|
||||||
// FIXME: We should use this enum or something like it to get rid of the
|
// FIXME: We should use this enum or something like it to get rid of the
|
||||||
// use of magic `/rust/1.x/...` paths across the board.
|
// use of magic `/rust/1.x/...` paths across the board.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd)]
|
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd)]
|
||||||
#[derive(HashStable_Generic, Decodable)]
|
#[derive(Decodable)]
|
||||||
pub enum RealFileName {
|
pub enum RealFileName {
|
||||||
LocalPath(PathBuf),
|
LocalPath(PathBuf),
|
||||||
/// For remapped paths (namely paths into libstd that have been mapped
|
/// For remapped paths (namely paths into libstd that have been mapped
|
||||||
|
@ -269,7 +269,7 @@ impl RealFileName {
|
||||||
|
|
||||||
/// Differentiates between real files and common virtual files.
|
/// Differentiates between real files and common virtual files.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
|
||||||
#[derive(HashStable_Generic, Decodable, Encodable)]
|
#[derive(Decodable, Encodable)]
|
||||||
pub enum FileName {
|
pub enum FileName {
|
||||||
Real(RealFileName),
|
Real(RealFileName),
|
||||||
/// Call to `quote!`.
|
/// Call to `quote!`.
|
||||||
|
|
|
@ -767,17 +767,24 @@ impl TcpListener {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use std::net::TcpListener;
|
/// use std::net::{TcpListener, TcpStream};
|
||||||
///
|
///
|
||||||
/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
|
/// fn handle_connection(stream: TcpStream) {
|
||||||
|
/// //...
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// for stream in listener.incoming() {
|
/// fn main() -> std::io::Result<()> {
|
||||||
/// match stream {
|
/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
|
||||||
/// Ok(stream) => {
|
///
|
||||||
/// println!("new client!");
|
/// for stream in listener.incoming() {
|
||||||
|
/// match stream {
|
||||||
|
/// Ok(stream) => {
|
||||||
|
/// handle_connection(stream);
|
||||||
|
/// }
|
||||||
|
/// Err(e) => { /* connection failed */ }
|
||||||
/// }
|
/// }
|
||||||
/// Err(e) => { /* connection failed */ }
|
|
||||||
/// }
|
/// }
|
||||||
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -65,10 +65,11 @@ fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option<Buf
|
||||||
out.push_buffer(extra);
|
out.push_buffer(extra);
|
||||||
}
|
}
|
||||||
if let Some(class) = class {
|
if let Some(class) = class {
|
||||||
writeln!(out, "<pre class=\"rust {}\">", class);
|
write!(out, "<pre class=\"rust {}\">", class);
|
||||||
} else {
|
} else {
|
||||||
writeln!(out, "<pre class=\"rust\">");
|
write!(out, "<pre class=\"rust\">");
|
||||||
}
|
}
|
||||||
|
write!(out, "<code>");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the given `src` source code into HTML by adding classes for highlighting.
|
/// Convert the given `src` source code into HTML by adding classes for highlighting.
|
||||||
|
@ -101,7 +102,7 @@ fn write_code(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_footer(out: &mut Buffer, playground_button: Option<&str>) {
|
fn write_footer(out: &mut Buffer, playground_button: Option<&str>) {
|
||||||
writeln!(out, "</pre>{}</div>", playground_button.unwrap_or_default());
|
writeln!(out, "</code></pre>{}</div>", playground_button.unwrap_or_default());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How a span of text is classified. Mostly corresponds to token kinds.
|
/// How a span of text is classified. Mostly corresponds to token kinds.
|
||||||
|
|
|
@ -234,7 +234,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||||
return Some(Event::Html(
|
return Some(Event::Html(
|
||||||
format!(
|
format!(
|
||||||
"<div class=\"example-wrap\">\
|
"<div class=\"example-wrap\">\
|
||||||
<pre class=\"language-{}\">{}</pre>\
|
<pre class=\"language-{}\"><code>{}</code></pre>\
|
||||||
</div>",
|
</div>",
|
||||||
lang,
|
lang,
|
||||||
Escape(&text),
|
Escape(&text),
|
||||||
|
|
|
@ -454,24 +454,25 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
|
||||||
+ name.as_str().len()
|
+ name.as_str().len()
|
||||||
+ generics_len;
|
+ generics_len;
|
||||||
|
|
||||||
w.write_str("<pre class=\"rust fn\">");
|
wrap_item(w, "fn", |w| {
|
||||||
render_attributes_in_pre(w, it, "");
|
render_attributes_in_pre(w, it, "");
|
||||||
w.reserve(header_len);
|
w.reserve(header_len);
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{vis}{constness}{asyncness}{unsafety}{abi}fn \
|
"{vis}{constness}{asyncness}{unsafety}{abi}fn \
|
||||||
{name}{generics}{decl}{notable_traits}{where_clause}</pre>",
|
{name}{generics}{decl}{notable_traits}{where_clause}",
|
||||||
vis = vis,
|
vis = vis,
|
||||||
constness = constness,
|
constness = constness,
|
||||||
asyncness = asyncness,
|
asyncness = asyncness,
|
||||||
unsafety = unsafety,
|
unsafety = unsafety,
|
||||||
abi = abi,
|
abi = abi,
|
||||||
name = name,
|
name = name,
|
||||||
generics = f.generics.print(cx),
|
generics = f.generics.print(cx),
|
||||||
where_clause = print_where_clause(&f.generics, cx, 0, true),
|
where_clause = print_where_clause(&f.generics, cx, 0, true),
|
||||||
decl = f.decl.full_print(header_len, 0, f.header.asyncness, cx),
|
decl = f.decl.full_print(header_len, 0, f.header.asyncness, cx),
|
||||||
notable_traits = notable_traits_decl(&f.decl, cx),
|
notable_traits = notable_traits_decl(&f.decl, cx),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
document(w, cx, it, None)
|
document(w, cx, it, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,108 +488,111 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
|
||||||
|
|
||||||
// Output the trait definition
|
// Output the trait definition
|
||||||
wrap_into_docblock(w, |w| {
|
wrap_into_docblock(w, |w| {
|
||||||
w.write_str("<pre class=\"rust trait\">");
|
wrap_item(w, "trait", |w| {
|
||||||
render_attributes_in_pre(w, it, "");
|
render_attributes_in_pre(w, it, "");
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{}{}{}trait {}{}{}",
|
"{}{}{}trait {}{}{}",
|
||||||
it.visibility.print_with_space(it.def_id, cx),
|
it.visibility.print_with_space(it.def_id, cx),
|
||||||
t.unsafety.print_with_space(),
|
t.unsafety.print_with_space(),
|
||||||
if t.is_auto { "auto " } else { "" },
|
if t.is_auto { "auto " } else { "" },
|
||||||
it.name.as_ref().unwrap(),
|
it.name.as_ref().unwrap(),
|
||||||
t.generics.print(cx),
|
t.generics.print(cx),
|
||||||
bounds
|
bounds
|
||||||
);
|
);
|
||||||
|
|
||||||
if !t.generics.where_predicates.is_empty() {
|
if !t.generics.where_predicates.is_empty() {
|
||||||
write!(w, "{}", print_where_clause(&t.generics, cx, 0, true));
|
write!(w, "{}", print_where_clause(&t.generics, cx, 0, true));
|
||||||
} else {
|
} else {
|
||||||
w.write_str(" ");
|
w.write_str(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.items.is_empty() {
|
if t.items.is_empty() {
|
||||||
w.write_str("{ }");
|
w.write_str("{ }");
|
||||||
} else {
|
} else {
|
||||||
// FIXME: we should be using a derived_id for the Anchors here
|
// FIXME: we should be using a derived_id for the Anchors here
|
||||||
w.write_str("{\n");
|
w.write_str("{\n");
|
||||||
let mut toggle = false;
|
let mut toggle = false;
|
||||||
|
|
||||||
// If there are too many associated types, hide _everything_
|
// If there are too many associated types, hide _everything_
|
||||||
if should_hide_fields(count_types) {
|
if should_hide_fields(count_types) {
|
||||||
toggle = true;
|
toggle = true;
|
||||||
toggle_open(
|
toggle_open(
|
||||||
w,
|
w,
|
||||||
format_args!("{} associated items", count_types + count_consts + count_methods),
|
format_args!(
|
||||||
);
|
"{} associated items",
|
||||||
}
|
count_types + count_consts + count_methods
|
||||||
for t in &types {
|
),
|
||||||
render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
|
);
|
||||||
w.write_str(";\n");
|
|
||||||
}
|
|
||||||
// If there are too many associated constants, hide everything after them
|
|
||||||
// We also do this if the types + consts is large because otherwise we could
|
|
||||||
// render a bunch of types and _then_ a bunch of consts just because both were
|
|
||||||
// _just_ under the limit
|
|
||||||
if !toggle && should_hide_fields(count_types + count_consts) {
|
|
||||||
toggle = true;
|
|
||||||
toggle_open(
|
|
||||||
w,
|
|
||||||
format_args!(
|
|
||||||
"{} associated constant{} and {} method{}",
|
|
||||||
count_consts,
|
|
||||||
pluralize(count_consts),
|
|
||||||
count_methods,
|
|
||||||
pluralize(count_methods),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if !types.is_empty() && !consts.is_empty() {
|
|
||||||
w.write_str("\n");
|
|
||||||
}
|
|
||||||
for t in &consts {
|
|
||||||
render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
|
|
||||||
w.write_str(";\n");
|
|
||||||
}
|
|
||||||
if !toggle && should_hide_fields(count_methods) {
|
|
||||||
toggle = true;
|
|
||||||
toggle_open(w, format_args!("{} methods", count_methods));
|
|
||||||
}
|
|
||||||
if !consts.is_empty() && !required.is_empty() {
|
|
||||||
w.write_str("\n");
|
|
||||||
}
|
|
||||||
for (pos, m) in required.iter().enumerate() {
|
|
||||||
render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait, cx);
|
|
||||||
w.write_str(";\n");
|
|
||||||
|
|
||||||
if pos < required.len() - 1 {
|
|
||||||
w.write_str("<div class=\"item-spacer\"></div>");
|
|
||||||
}
|
}
|
||||||
}
|
for t in &types {
|
||||||
if !required.is_empty() && !provided.is_empty() {
|
render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
|
||||||
w.write_str("\n");
|
w.write_str(";\n");
|
||||||
}
|
}
|
||||||
for (pos, m) in provided.iter().enumerate() {
|
// If there are too many associated constants, hide everything after them
|
||||||
render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait, cx);
|
// We also do this if the types + consts is large because otherwise we could
|
||||||
match *m.kind {
|
// render a bunch of types and _then_ a bunch of consts just because both were
|
||||||
clean::MethodItem(ref inner, _)
|
// _just_ under the limit
|
||||||
if !inner.generics.where_predicates.is_empty() =>
|
if !toggle && should_hide_fields(count_types + count_consts) {
|
||||||
{
|
toggle = true;
|
||||||
w.write_str(",\n { ... }\n");
|
toggle_open(
|
||||||
}
|
w,
|
||||||
_ => {
|
format_args!(
|
||||||
w.write_str(" { ... }\n");
|
"{} associated constant{} and {} method{}",
|
||||||
|
count_consts,
|
||||||
|
pluralize(count_consts),
|
||||||
|
count_methods,
|
||||||
|
pluralize(count_methods),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if !types.is_empty() && !consts.is_empty() {
|
||||||
|
w.write_str("\n");
|
||||||
|
}
|
||||||
|
for t in &consts {
|
||||||
|
render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait, cx);
|
||||||
|
w.write_str(";\n");
|
||||||
|
}
|
||||||
|
if !toggle && should_hide_fields(count_methods) {
|
||||||
|
toggle = true;
|
||||||
|
toggle_open(w, format_args!("{} methods", count_methods));
|
||||||
|
}
|
||||||
|
if !consts.is_empty() && !required.is_empty() {
|
||||||
|
w.write_str("\n");
|
||||||
|
}
|
||||||
|
for (pos, m) in required.iter().enumerate() {
|
||||||
|
render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait, cx);
|
||||||
|
w.write_str(";\n");
|
||||||
|
|
||||||
|
if pos < required.len() - 1 {
|
||||||
|
w.write_str("<div class=\"item-spacer\"></div>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pos < provided.len() - 1 {
|
if !required.is_empty() && !provided.is_empty() {
|
||||||
w.write_str("<div class=\"item-spacer\"></div>");
|
w.write_str("\n");
|
||||||
}
|
}
|
||||||
|
for (pos, m) in provided.iter().enumerate() {
|
||||||
|
render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait, cx);
|
||||||
|
match *m.kind {
|
||||||
|
clean::MethodItem(ref inner, _)
|
||||||
|
if !inner.generics.where_predicates.is_empty() =>
|
||||||
|
{
|
||||||
|
w.write_str(",\n { ... }\n");
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
w.write_str(" { ... }\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pos < provided.len() - 1 {
|
||||||
|
w.write_str("<div class=\"item-spacer\"></div>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if toggle {
|
||||||
|
toggle_close(w);
|
||||||
|
}
|
||||||
|
w.write_str("}");
|
||||||
}
|
}
|
||||||
if toggle {
|
});
|
||||||
toggle_close(w);
|
|
||||||
}
|
|
||||||
w.write_str("}");
|
|
||||||
}
|
|
||||||
w.write_str("</pre>")
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Trait documentation
|
// Trait documentation
|
||||||
|
@ -811,16 +815,17 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
|
fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
|
||||||
w.write_str("<pre class=\"rust trait-alias\">");
|
wrap_item(w, "trait-alias", |w| {
|
||||||
render_attributes_in_pre(w, it, "");
|
render_attributes_in_pre(w, it, "");
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"trait {}{}{} = {};</pre>",
|
"trait {}{}{} = {};",
|
||||||
it.name.as_ref().unwrap(),
|
it.name.as_ref().unwrap(),
|
||||||
t.generics.print(cx),
|
t.generics.print(cx),
|
||||||
print_where_clause(&t.generics, cx, 0, true),
|
print_where_clause(&t.generics, cx, 0, true),
|
||||||
bounds(&t.bounds, true, cx)
|
bounds(&t.bounds, true, cx)
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
document(w, cx, it, None);
|
document(w, cx, it, None);
|
||||||
|
|
||||||
|
@ -832,16 +837,17 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
|
fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
|
||||||
w.write_str("<pre class=\"rust opaque\">");
|
wrap_item(w, "opaque", |w| {
|
||||||
render_attributes_in_pre(w, it, "");
|
render_attributes_in_pre(w, it, "");
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"type {}{}{where_clause} = impl {bounds};</pre>",
|
"type {}{}{where_clause} = impl {bounds};",
|
||||||
it.name.as_ref().unwrap(),
|
it.name.as_ref().unwrap(),
|
||||||
t.generics.print(cx),
|
t.generics.print(cx),
|
||||||
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
||||||
bounds = bounds(&t.bounds, false, cx),
|
bounds = bounds(&t.bounds, false, cx),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
document(w, cx, it, None);
|
document(w, cx, it, None);
|
||||||
|
|
||||||
|
@ -859,19 +865,20 @@ fn item_typedef(
|
||||||
t: &clean::Typedef,
|
t: &clean::Typedef,
|
||||||
is_associated: bool,
|
is_associated: bool,
|
||||||
) {
|
) {
|
||||||
w.write_str("<pre class=\"rust typedef\">");
|
wrap_item(w, "typedef", |w| {
|
||||||
render_attributes_in_pre(w, it, "");
|
render_attributes_in_pre(w, it, "");
|
||||||
if !is_associated {
|
if !is_associated {
|
||||||
write!(w, "{}", it.visibility.print_with_space(it.def_id, cx));
|
write!(w, "{}", it.visibility.print_with_space(it.def_id, cx));
|
||||||
}
|
}
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"type {}{}{where_clause} = {type_};</pre>",
|
"type {}{}{where_clause} = {type_};",
|
||||||
it.name.as_ref().unwrap(),
|
it.name.as_ref().unwrap(),
|
||||||
t.generics.print(cx),
|
t.generics.print(cx),
|
||||||
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
||||||
type_ = t.type_.print(cx),
|
type_ = t.type_.print(cx),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
document(w, cx, it, None);
|
document(w, cx, it, None);
|
||||||
|
|
||||||
|
@ -885,10 +892,10 @@ fn item_typedef(
|
||||||
|
|
||||||
fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
|
fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
|
||||||
wrap_into_docblock(w, |w| {
|
wrap_into_docblock(w, |w| {
|
||||||
w.write_str("<pre class=\"rust union\">");
|
wrap_item(w, "union", |w| {
|
||||||
render_attributes_in_pre(w, it, "");
|
render_attributes_in_pre(w, it, "");
|
||||||
render_union(w, it, Some(&s.generics), &s.fields, "", cx);
|
render_union(w, it, Some(&s.generics), &s.fields, "", cx);
|
||||||
w.write_str("</pre>")
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
document(w, cx, it, None);
|
document(w, cx, it, None);
|
||||||
|
@ -934,59 +941,68 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
|
||||||
|
|
||||||
fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
|
fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
|
||||||
wrap_into_docblock(w, |w| {
|
wrap_into_docblock(w, |w| {
|
||||||
w.write_str("<pre class=\"rust enum\">");
|
wrap_item(w, "enum", |w| {
|
||||||
render_attributes_in_pre(w, it, "");
|
render_attributes_in_pre(w, it, "");
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{}enum {}{}{}",
|
"{}enum {}{}{}",
|
||||||
it.visibility.print_with_space(it.def_id, cx),
|
it.visibility.print_with_space(it.def_id, cx),
|
||||||
it.name.as_ref().unwrap(),
|
it.name.as_ref().unwrap(),
|
||||||
e.generics.print(cx),
|
e.generics.print(cx),
|
||||||
print_where_clause(&e.generics, cx, 0, true),
|
print_where_clause(&e.generics, cx, 0, true),
|
||||||
);
|
);
|
||||||
if e.variants.is_empty() && !e.variants_stripped {
|
if e.variants.is_empty() && !e.variants_stripped {
|
||||||
w.write_str(" {}");
|
w.write_str(" {}");
|
||||||
} else {
|
} else {
|
||||||
w.write_str(" {\n");
|
w.write_str(" {\n");
|
||||||
let count_variants = e.variants.len();
|
let count_variants = e.variants.len();
|
||||||
let toggle = should_hide_fields(count_variants);
|
let toggle = should_hide_fields(count_variants);
|
||||||
if toggle {
|
if toggle {
|
||||||
toggle_open(w, format_args!("{} variants", count_variants));
|
toggle_open(w, format_args!("{} variants", count_variants));
|
||||||
}
|
}
|
||||||
for v in &e.variants {
|
for v in &e.variants {
|
||||||
w.write_str(" ");
|
w.write_str(" ");
|
||||||
let name = v.name.as_ref().unwrap();
|
let name = v.name.as_ref().unwrap();
|
||||||
match *v.kind {
|
match *v.kind {
|
||||||
clean::VariantItem(ref var) => match var {
|
clean::VariantItem(ref var) => match var {
|
||||||
clean::Variant::CLike => write!(w, "{}", name),
|
clean::Variant::CLike => write!(w, "{}", name),
|
||||||
clean::Variant::Tuple(ref tys) => {
|
clean::Variant::Tuple(ref tys) => {
|
||||||
write!(w, "{}(", name);
|
write!(w, "{}(", name);
|
||||||
for (i, ty) in tys.iter().enumerate() {
|
for (i, ty) in tys.iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
w.write_str(", ")
|
w.write_str(", ")
|
||||||
}
|
}
|
||||||
write!(w, "{}", ty.print(cx));
|
write!(w, "{}", ty.print(cx));
|
||||||
}
|
}
|
||||||
w.write_str(")");
|
w.write_str(")");
|
||||||
}
|
}
|
||||||
clean::Variant::Struct(ref s) => {
|
clean::Variant::Struct(ref s) => {
|
||||||
render_struct(w, v, None, s.struct_type, &s.fields, " ", false, cx);
|
render_struct(
|
||||||
}
|
w,
|
||||||
},
|
v,
|
||||||
_ => unreachable!(),
|
None,
|
||||||
|
s.struct_type,
|
||||||
|
&s.fields,
|
||||||
|
" ",
|
||||||
|
false,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
w.write_str(",\n");
|
||||||
}
|
}
|
||||||
w.write_str(",\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.variants_stripped {
|
if e.variants_stripped {
|
||||||
w.write_str(" // some variants omitted\n");
|
w.write_str(" // some variants omitted\n");
|
||||||
|
}
|
||||||
|
if toggle {
|
||||||
|
toggle_close(w);
|
||||||
|
}
|
||||||
|
w.write_str("}");
|
||||||
}
|
}
|
||||||
if toggle {
|
});
|
||||||
toggle_close(w);
|
|
||||||
}
|
|
||||||
w.write_str("}");
|
|
||||||
}
|
|
||||||
w.write_str("</pre>")
|
|
||||||
});
|
});
|
||||||
|
|
||||||
document(w, cx, it, None);
|
document(w, cx, it, None);
|
||||||
|
@ -1090,27 +1106,27 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean
|
||||||
let name = it.name.as_ref().expect("proc-macros always have names");
|
let name = it.name.as_ref().expect("proc-macros always have names");
|
||||||
match m.kind {
|
match m.kind {
|
||||||
MacroKind::Bang => {
|
MacroKind::Bang => {
|
||||||
w.push_str("<pre class=\"rust macro\">");
|
wrap_item(w, "macro", |w| {
|
||||||
write!(w, "{}!() {{ /* proc-macro */ }}", name);
|
write!(w, "{}!() {{ /* proc-macro */ }}", name);
|
||||||
w.push_str("</pre>");
|
});
|
||||||
}
|
}
|
||||||
MacroKind::Attr => {
|
MacroKind::Attr => {
|
||||||
w.push_str("<pre class=\"rust attr\">");
|
wrap_item(w, "attr", |w| {
|
||||||
write!(w, "#[{}]", name);
|
write!(w, "#[{}]", name);
|
||||||
w.push_str("</pre>");
|
});
|
||||||
}
|
}
|
||||||
MacroKind::Derive => {
|
MacroKind::Derive => {
|
||||||
w.push_str("<pre class=\"rust derive\">");
|
wrap_item(w, "derive", |w| {
|
||||||
write!(w, "#[derive({})]", name);
|
write!(w, "#[derive({})]", name);
|
||||||
if !m.helpers.is_empty() {
|
if !m.helpers.is_empty() {
|
||||||
w.push_str("\n{\n");
|
w.push_str("\n{\n");
|
||||||
w.push_str(" // Attributes available to this derive:\n");
|
w.push_str(" // Attributes available to this derive:\n");
|
||||||
for attr in &m.helpers {
|
for attr in &m.helpers {
|
||||||
writeln!(w, " #[{}]", attr);
|
writeln!(w, " #[{}]", attr);
|
||||||
|
}
|
||||||
|
w.push_str("}\n");
|
||||||
}
|
}
|
||||||
w.push_str("}\n");
|
});
|
||||||
}
|
|
||||||
w.push_str("</pre>");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document(w, cx, it, None)
|
document(w, cx, it, None)
|
||||||
|
@ -1122,49 +1138,49 @@ fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
|
fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
|
||||||
w.write_str("<pre class=\"rust const\">");
|
wrap_item(w, "const", |w| {
|
||||||
render_attributes_in_code(w, it);
|
render_attributes_in_code(w, it);
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{vis}const {name}: {typ}",
|
"{vis}const {name}: {typ}",
|
||||||
vis = it.visibility.print_with_space(it.def_id, cx),
|
vis = it.visibility.print_with_space(it.def_id, cx),
|
||||||
name = it.name.as_ref().unwrap(),
|
name = it.name.as_ref().unwrap(),
|
||||||
typ = c.type_.print(cx),
|
typ = c.type_.print(cx),
|
||||||
);
|
);
|
||||||
|
|
||||||
let value = c.value(cx.tcx());
|
let value = c.value(cx.tcx());
|
||||||
let is_literal = c.is_literal(cx.tcx());
|
let is_literal = c.is_literal(cx.tcx());
|
||||||
let expr = c.expr(cx.tcx());
|
let expr = c.expr(cx.tcx());
|
||||||
if value.is_some() || is_literal {
|
if value.is_some() || is_literal {
|
||||||
write!(w, " = {expr};", expr = Escape(&expr));
|
write!(w, " = {expr};", expr = Escape(&expr));
|
||||||
} else {
|
} else {
|
||||||
w.write_str(";");
|
w.write_str(";");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_literal {
|
if !is_literal {
|
||||||
if let Some(value) = &value {
|
if let Some(value) = &value {
|
||||||
let value_lowercase = value.to_lowercase();
|
let value_lowercase = value.to_lowercase();
|
||||||
let expr_lowercase = expr.to_lowercase();
|
let expr_lowercase = expr.to_lowercase();
|
||||||
|
|
||||||
if value_lowercase != expr_lowercase
|
if value_lowercase != expr_lowercase
|
||||||
&& value_lowercase.trim_end_matches("i32") != expr_lowercase
|
&& value_lowercase.trim_end_matches("i32") != expr_lowercase
|
||||||
{
|
{
|
||||||
write!(w, " // {value}", value = Escape(value));
|
write!(w, " // {value}", value = Escape(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
w.write_str("</pre>");
|
|
||||||
document(w, cx, it, None)
|
document(w, cx, it, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
|
fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
|
||||||
wrap_into_docblock(w, |w| {
|
wrap_into_docblock(w, |w| {
|
||||||
w.write_str("<pre class=\"rust struct\">");
|
wrap_item(w, "struct", |w| {
|
||||||
render_attributes_in_code(w, it);
|
render_attributes_in_code(w, it);
|
||||||
render_struct(w, it, Some(&s.generics), s.struct_type, &s.fields, "", true, cx);
|
render_struct(w, it, Some(&s.generics), s.struct_type, &s.fields, "", true, cx);
|
||||||
w.write_str("</pre>")
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
document(w, cx, it, None);
|
document(w, cx, it, None);
|
||||||
|
@ -1213,28 +1229,31 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) {
|
fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) {
|
||||||
w.write_str("<pre class=\"rust static\">");
|
wrap_item(w, "static", |w| {
|
||||||
render_attributes_in_code(w, it);
|
render_attributes_in_code(w, it);
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{vis}static {mutability}{name}: {typ}</pre>",
|
"{vis}static {mutability}{name}: {typ}",
|
||||||
vis = it.visibility.print_with_space(it.def_id, cx),
|
vis = it.visibility.print_with_space(it.def_id, cx),
|
||||||
mutability = s.mutability.print_with_space(),
|
mutability = s.mutability.print_with_space(),
|
||||||
name = it.name.as_ref().unwrap(),
|
name = it.name.as_ref().unwrap(),
|
||||||
typ = s.type_.print(cx)
|
typ = s.type_.print(cx)
|
||||||
);
|
);
|
||||||
|
});
|
||||||
document(w, cx, it, None)
|
document(w, cx, it, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
|
fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
|
||||||
w.write_str("<pre class=\"rust foreigntype\">extern {\n");
|
wrap_item(w, "foreigntype", |w| {
|
||||||
render_attributes_in_code(w, it);
|
w.write_str("extern {\n");
|
||||||
write!(
|
render_attributes_in_code(w, it);
|
||||||
w,
|
write!(
|
||||||
" {}type {};\n}}</pre>",
|
w,
|
||||||
it.visibility.print_with_space(it.def_id, cx),
|
" {}type {};\n}}",
|
||||||
it.name.as_ref().unwrap(),
|
it.visibility.print_with_space(it.def_id, cx),
|
||||||
);
|
it.name.as_ref().unwrap(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
document(w, cx, it, None);
|
document(w, cx, it, None);
|
||||||
|
|
||||||
|
@ -1321,6 +1340,15 @@ where
|
||||||
w.write_str("</div>")
|
w.write_str("</div>")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wrap_item<F>(w: &mut Buffer, item_name: &str, f: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut Buffer),
|
||||||
|
{
|
||||||
|
w.write_fmt(format_args!("<pre class=\"rust {}\"><code>", item_name));
|
||||||
|
f(w);
|
||||||
|
w.write_str("</code></pre>");
|
||||||
|
}
|
||||||
|
|
||||||
fn render_stability_since(
|
fn render_stability_since(
|
||||||
w: &mut Buffer,
|
w: &mut Buffer,
|
||||||
item: &clean::Item,
|
item: &clean::Item,
|
||||||
|
|
|
@ -249,7 +249,6 @@ code, pre, a.test-arrow, .code-header {
|
||||||
}
|
}
|
||||||
.docblock pre code, .docblock-short pre code {
|
.docblock pre code, .docblock-short pre code {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
padding-right: 1ex;
|
|
||||||
}
|
}
|
||||||
pre {
|
pre {
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
// revisions: cfail
|
||||||
|
#![feature(const_generics, const_evaluatable_checked)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
// regression test for #77650
|
||||||
|
fn c<T, const N: std::num::NonZeroUsize>()
|
||||||
|
where
|
||||||
|
[T; N.get()]: Sized,
|
||||||
|
{
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
<[T; N.get()]>::try_from(())
|
||||||
|
//~^ error: the trait bound
|
||||||
|
//~^^ error: mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,35 @@
|
||||||
|
error[E0277]: the trait bound `[T; _]: From<()>` is not satisfied
|
||||||
|
--> $DIR/hash-tyvid-regression-1.rs:9:5
|
||||||
|
|
|
||||||
|
LL | <[T; N.get()]>::try_from(())
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `[T; _]`
|
||||||
|
|
|
||||||
|
= note: required because of the requirements on the impl of `Into<[T; _]>` for `()`
|
||||||
|
= note: required because of the requirements on the impl of `TryFrom<()>` for `[T; _]`
|
||||||
|
note: required by `try_from`
|
||||||
|
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | fn try_from(value: T) -> Result<Self, Self::Error>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/hash-tyvid-regression-1.rs:9:5
|
||||||
|
|
|
||||||
|
LL | <[T; N.get()]>::try_from(())
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `Result`
|
||||||
|
|
|
||||||
|
= note: expected unit type `()`
|
||||||
|
found enum `Result<[T; _], Infallible>`
|
||||||
|
help: consider using a semicolon here
|
||||||
|
|
|
||||||
|
LL | <[T; N.get()]>::try_from(());
|
||||||
|
| +
|
||||||
|
help: try adding a return type
|
||||||
|
|
|
||||||
|
LL | -> Result<[T; _], Infallible> where
|
||||||
|
| +++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0277, E0308.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,18 @@
|
||||||
|
// revisions: cfail
|
||||||
|
#![feature(const_generics, const_evaluatable_checked)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
// regression test for #77650
|
||||||
|
struct C<T, const N: core::num::NonZeroUsize>([T; N.get()])
|
||||||
|
where
|
||||||
|
[T; N.get()]: Sized;
|
||||||
|
impl<'a, const N: core::num::NonZeroUsize, A, B: PartialEq<A>> PartialEq<&'a [A]> for C<B, N>
|
||||||
|
where
|
||||||
|
[B; N.get()]: Sized,
|
||||||
|
{
|
||||||
|
fn eq(&self, other: &&'a [A]) -> bool {
|
||||||
|
self.0 == other
|
||||||
|
//~^ error: can't compare
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,11 @@
|
||||||
|
error[E0277]: can't compare `[B; _]` with `&&[A]`
|
||||||
|
--> $DIR/hash-tyvid-regression-2.rs:12:16
|
||||||
|
|
|
||||||
|
LL | self.0 == other
|
||||||
|
| ^^ no implementation for `[B; _] == &&[A]`
|
||||||
|
|
|
||||||
|
= help: the trait `PartialEq<&&[A]>` is not implemented for `[B; _]`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,26 @@
|
||||||
|
// revisions: cfail
|
||||||
|
#![feature(const_generics, const_evaluatable_checked)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
// regression test for #79251
|
||||||
|
struct Node<const D: usize>
|
||||||
|
where
|
||||||
|
SmallVec<{ D * 2 }>: ,
|
||||||
|
{
|
||||||
|
keys: SmallVec<{ D * 2 }>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const D: usize> Node<D>
|
||||||
|
where
|
||||||
|
SmallVec<{ D * 2 }>: ,
|
||||||
|
{
|
||||||
|
fn new() -> Self {
|
||||||
|
let mut node = Node::new();
|
||||||
|
node.keys.some_function();
|
||||||
|
//~^ error: no method named
|
||||||
|
node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SmallVec<const D: usize> {}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0599]: no method named `some_function` found for struct `SmallVec` in the current scope
|
||||||
|
--> $DIR/hash-tyvid-regression-3.rs:17:19
|
||||||
|
|
|
||||||
|
LL | node.keys.some_function();
|
||||||
|
| ^^^^^^^^^^^^^ method not found in `SmallVec<{ D * 2 }>`
|
||||||
|
...
|
||||||
|
LL | struct SmallVec<const D: usize> {}
|
||||||
|
| ------------------------------- method `some_function` not found for this
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
|
@ -0,0 +1,40 @@
|
||||||
|
// revisions: cfail
|
||||||
|
#![feature(const_generics, const_evaluatable_checked)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
// regression test for #79251
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Node<K, const D: usize>
|
||||||
|
where
|
||||||
|
SmallVec<K, { D * 2 }>: ,
|
||||||
|
{
|
||||||
|
keys: SmallVec<K, { D * 2 }>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, const D: usize> Node<K, D>
|
||||||
|
where
|
||||||
|
SmallVec<K, { D * 2 }>: ,
|
||||||
|
{
|
||||||
|
fn new() -> Self {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn split(&mut self, i: usize, k: K, right: bool) -> Node<K, D> {
|
||||||
|
let mut node = Node::new();
|
||||||
|
node.keys.push(k);
|
||||||
|
//~^ error: no method named
|
||||||
|
node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SmallVec<T, const D: usize> {
|
||||||
|
data: [T; D],
|
||||||
|
}
|
||||||
|
impl<T, const D: usize> SmallVec<T, D> {
|
||||||
|
fn new() -> Self {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0599]: no method named `push` found for struct `SmallVec` in the current scope
|
||||||
|
--> $DIR/hash-tyvid-regression-4.rs:23:19
|
||||||
|
|
|
||||||
|
LL | node.keys.push(k);
|
||||||
|
| ^^^^ method not found in `SmallVec<_, { D * 2 }>`
|
||||||
|
...
|
||||||
|
LL | struct SmallVec<T, const D: usize> {
|
||||||
|
| ---------------------------------- method `push` not found for this
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
20
src/test/rustdoc-gui/code-tags.goml
Normal file
20
src/test/rustdoc-gui/code-tags.goml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// This test ensures that items and documentation code blocks are wrapped in <pre><code>
|
||||||
|
goto: file://|DOC_PATH|/test_docs/fn.foo.html
|
||||||
|
size: (1080, 600)
|
||||||
|
// There should be three doc codeblocks
|
||||||
|
// Check that their content is inside <pre><code>
|
||||||
|
assert-count: (".example-wrap pre > code", 3)
|
||||||
|
// Check that function signature is inside <pre><code>
|
||||||
|
assert: "pre.rust.fn > code"
|
||||||
|
|
||||||
|
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
|
||||||
|
assert: "pre.rust.struct > code"
|
||||||
|
|
||||||
|
goto: file://|DOC_PATH|/test_docs/enum.AnEnum.html
|
||||||
|
assert: "pre.rust.enum > code"
|
||||||
|
|
||||||
|
goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html
|
||||||
|
assert: "pre.rust.trait > code"
|
||||||
|
|
||||||
|
goto: file://|DOC_PATH|/test_docs/type.SomeType.html
|
||||||
|
assert: "pre.rust.typedef > code"
|
|
@ -12,4 +12,4 @@ assert-attribute: (".line-numbers > span:nth-child(5)", {"class": "line-highligh
|
||||||
assert-attribute: (".line-numbers > span:nth-child(6)", {"class": "line-highlighted"})
|
assert-attribute: (".line-numbers > span:nth-child(6)", {"class": "line-highlighted"})
|
||||||
assert-attribute-false: (".line-numbers > span:nth-child(7)", {"class": "line-highlighted"})
|
assert-attribute-false: (".line-numbers > span:nth-child(7)", {"class": "line-highlighted"})
|
||||||
// This is to ensure that the content is correctly align with the line numbers.
|
// This is to ensure that the content is correctly align with the line numbers.
|
||||||
compare-elements-position: ("//*[@id='1']", ".rust > span", ("y"))
|
compare-elements-position: ("//*[@id='1']", ".rust > code > span", ("y"))
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
type PartiallyDefined<T> = impl 'static;
|
type PartiallyDefined<T> = impl Sized;
|
||||||
//~^ ERROR: at least one trait must be specified
|
|
||||||
|
|
||||||
fn partially_defined<T: std::fmt::Debug>(_: T) -> PartiallyDefined<T> {
|
fn partially_defined<T: std::fmt::Debug>(_: T) -> PartiallyDefined<T> {
|
||||||
4u32
|
4u32
|
||||||
}
|
}
|
||||||
|
|
||||||
type PartiallyDefined2<T> = impl 'static;
|
type PartiallyDefined2<T> = impl Sized;
|
||||||
//~^ ERROR: at least one trait must be specified
|
|
||||||
|
|
||||||
fn partially_defined2<T: std::fmt::Debug>(_: T) -> PartiallyDefined2<T> {
|
fn partially_defined2<T: std::fmt::Debug>(_: T) -> PartiallyDefined2<T> {
|
||||||
4u32
|
4u32
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
error: at least one trait must be specified
|
|
||||||
--> $DIR/unused_generic_param.rs:5:28
|
|
||||||
|
|
|
||||||
LL | type PartiallyDefined<T> = impl 'static;
|
|
||||||
| ^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: at least one trait must be specified
|
|
||||||
--> $DIR/unused_generic_param.rs:12:29
|
|
||||||
|
|
|
||||||
LL | type PartiallyDefined2<T> = impl 'static;
|
|
||||||
| ^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue