Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #90422

Merged
merged 22 commits into from
Oct 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4ecb49e
Handle cross-crate module `ExpnId`s consistently
matthewjasper Oct 21, 2021
1536d72
Don't suggest importing items with hygienic names
matthewjasper Oct 21, 2021
fabede1
Add more tests for cross-crate hygiene
matthewjasper Oct 23, 2021
6c61db4
Use `is_global` in `candidate_should_be_dropped_in_favor_of`
yanok Oct 28, 2021
6f942a2
Reformat the changed line to make tidy happy
yanok Oct 28, 2021
9a0a622
Add test cases
yanok Oct 28, 2021
d8426ea
Remove `ModData` from rustc_metadata
matthewjasper Oct 28, 2021
a76a2d4
Add comments to hygiene tests
matthewjasper Oct 28, 2021
8a473ca
Recursively document Deref
GuillaumeGomez Oct 22, 2021
0c38f31
Add tests for recursive deref
GuillaumeGomez Oct 22, 2021
3398877
Remove the Rc wrapping of deref_id_map
GuillaumeGomez Oct 23, 2021
dd68d20
Don't display "Methods from Deref<...>" if no method is display (the …
GuillaumeGomez Oct 23, 2021
f09b67a
Fix panic when documenting libproc-macro
GuillaumeGomez Oct 23, 2021
e215149
Skip suggestions for the AsRef trait
Oct 27, 2021
cad2d21
Explicitly skipping suggestions for 'Pin' as it does not implement th…
Oct 29, 2021
78b6045
Document tests a bit more
GuillaumeGomez Oct 30, 2021
a65c98f
Remove underlines from non-top docblocks.
jsha Oct 22, 2021
ec83b95
Rollup merge of #90156 - jsha:less-border-bottom-2, r=GuillaumeGomez
GuillaumeGomez Oct 30, 2021
7349440
Rollup merge of #90183 - GuillaumeGomez:recurse-deref, r=jyn514
GuillaumeGomez Oct 30, 2021
1a1f525
Rollup merge of #90202 - matthewjasper:xcrate-hygiene, r=petrochenkov
GuillaumeGomez Oct 30, 2021
06bb1ff
Rollup merge of #90375 - yanok:master, r=lcnr
GuillaumeGomez Oct 30, 2021
197da45
Rollup merge of #90399 - yuvaldolev:as-ref-overly-verbose-diagnostic,…
GuillaumeGomez Oct 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1198,8 +1198,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}
}

if let EntryKind::Mod(data) = kind {
for exp in data.decode((self, sess)).reexports.decode((self, sess)) {
if let EntryKind::Mod(exports) = kind {
for exp in exports.decode((self, sess)) {
match exp.res {
Res::Def(DefKind::Macro(..), _) => {}
_ if macros_only => continue,
Expand All @@ -1219,10 +1219,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}

fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId {
if let EntryKind::Mod(m) = self.kind(id) {
m.decode((self, sess)).expansion
} else {
panic!("Expected module, found {:?}", self.local_def_id(id))
match self.kind(id) {
EntryKind::Mod(_) | EntryKind::Enum(_) | EntryKind::Trait(_) => {
self.get_expn_that_defined(id, sess)
}
_ => panic!("Expected module, found {:?}", self.local_def_id(id)),
}
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1086,11 +1086,11 @@ impl EncodeContext<'a, 'tcx> {
Lazy::empty()
};

let data = ModData { reexports, expansion: tcx.expn_that_defined(local_def_id) };

record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports));
if self.is_proc_macro {
record!(self.tables.children[def_id] <- &[]);
// Encode this here because we don't do it in encode_def_ids.
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
} else {
record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| {
item_id.def_id.local_def_index
Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ enum EntryKind {
Union(Lazy<VariantData>, ReprOptions),
Fn(Lazy<FnData>),
ForeignFn(Lazy<FnData>),
Mod(Lazy<ModData>),
Mod(Lazy<[Export]>),
MacroDef(Lazy<MacroDef>),
ProcMacro(MacroKind),
Closure,
Expand All @@ -364,12 +364,6 @@ enum EntryKind {
#[derive(Encodable, Decodable)]
struct RenderedConst(String);

#[derive(MetadataEncodable, MetadataDecodable)]
struct ModData {
reexports: Lazy<[Export]>,
expansion: ExpnId,
}

#[derive(MetadataEncodable, MetadataDecodable)]
struct FnData {
asyncness: hir::IsAsync,
Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,11 @@ impl<'a> Resolver<'a> {
} else {
def_key.disambiguated_data.data.get_opt_name().expect("module without name")
};
let expn_id = if def_kind == DefKind::Mod {
self.cstore().module_expansion_untracked(def_id, &self.session)
} else {
// FIXME: Parent expansions for enums and traits are not kept in metadata.
ExpnId::root()
};

Some(self.new_module(
parent,
ModuleKind::Def(def_kind, def_id, name),
expn_id,
self.cstore().module_expansion_untracked(def_id, &self.session),
self.cstore().get_span_untracked(def_id, &self.session),
// FIXME: Account for `#[no_implicit_prelude]` attributes.
parent.map_or(false, |module| module.no_implicit_prelude),
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,9 +842,11 @@ impl<'a> Resolver<'a> {

// collect results based on the filter function
// avoid suggesting anything from the same module in which we are resolving
// avoid suggesting anything with a hygienic name
if ident.name == lookup_ident.name
&& ns == namespace
&& !ptr::eq(in_module, parent_scope.module)
&& !ident.span.normalize_to_macros_2_0().from_expansion()
{
let res = name_binding.res();
if filter_fn(res) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_span/src/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ impl SyntaxContext {
/// pub fn f() {} // `f`'s `SyntaxContext` has a single `ExpnId` from `m`.
/// pub fn $i() {} // `$i`'s `SyntaxContext` is empty.
/// }
/// n(f);
/// n!(f);
/// macro n($j:ident) {
/// use foo::*;
/// f(); // `f`'s `SyntaxContext` has a mark from `m` and a mark from `n`
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1547,8 +1547,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Check if a bound would previously have been removed when normalizing
// the param_env so that it can be given the lowest priority. See
// #50825 for the motivation for this.
let is_global =
|cand: &ty::PolyTraitRef<'_>| cand.is_known_global() && !cand.has_late_bound_regions();
let is_global = |cand: &ty::PolyTraitRef<'tcx>| {
cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions()
};

// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
// and `DiscriminantKindCandidate` to anything else.
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rustc_middle::ty::print::with_crate_prefix;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_span::lev_distance;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{source_map, FileName, MultiSpan, Span};
use rustc_span::{source_map, FileName, MultiSpan, Span, Symbol};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{FulfillmentError, Obligation};

Expand Down Expand Up @@ -1251,6 +1251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.lang_items().deref_trait(),
self.tcx.lang_items().deref_mut_trait(),
self.tcx.lang_items().drop_trait(),
self.tcx.get_diagnostic_item(sym::AsRef),
];
// Try alternative arbitrary self types that could fulfill this call.
// FIXME: probe for all types that *could* be arbitrary self-types, not
Expand Down Expand Up @@ -1300,7 +1301,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We don't want to suggest a container type when the missing
// method is `.clone()` or `.deref()` otherwise we'd suggest
// `Arc::new(foo).clone()`, which is far from what the user wants.
let skip = skippable.contains(&did);
// Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
// implement the `AsRef` trait.
let skip = skippable.contains(&did)
|| (("Pin::new" == *pre)
&& (Symbol::intern("as_ref") == item_name.name));
// Make sure the method is defined for the *actual* receiver: we don't
// want to treat `Box<Self>` as a receiver if it only works because of
// an autoderef to `&self`
Expand Down
9 changes: 7 additions & 2 deletions src/librustdoc/html/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver};

use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::edition::Edition;
Expand Down Expand Up @@ -54,6 +54,9 @@ crate struct Context<'tcx> {
/// real location of an item. This is used to allow external links to
/// publicly reused items to redirect to the right location.
pub(super) render_redirect_pages: bool,
/// Tracks section IDs for `Deref` targets so they match in both the main
/// body and the sidebar.
pub(super) deref_id_map: RefCell<FxHashMap<DefId, String>>,
/// The map used to ensure all generated 'id=' attributes are unique.
pub(super) id_map: RefCell<IdMap>,
/// Shared mutable state.
Expand All @@ -70,7 +73,7 @@ crate struct Context<'tcx> {

// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 104);
rustc_data_structures::static_assert_size!(Context<'_>, 144);

/// Shared mutable state used in [`Context`] and elsewhere.
crate struct SharedContext<'tcx> {
Expand Down Expand Up @@ -513,6 +516,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
dst,
render_redirect_pages: false,
id_map: RefCell::new(id_map),
deref_id_map: RefCell::new(FxHashMap::default()),
shared: Rc::new(scx),
include_sources,
};
Expand All @@ -536,6 +540,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
current: self.current.clone(),
dst: self.dst.clone(),
render_redirect_pages: self.render_redirect_pages,
deref_id_map: RefCell::new(FxHashMap::default()),
id_map: RefCell::new(IdMap::new()),
shared: Rc::clone(&self.shared),
include_sources: self.include_sources,
Expand Down
94 changes: 78 additions & 16 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,19 @@ fn render_assoc_items(
containing_item: &clean::Item,
it: DefId,
what: AssocItemRender<'_>,
) {
let mut derefs = FxHashSet::default();
derefs.insert(it);
render_assoc_items_inner(w, cx, containing_item, it, what, &mut derefs)
}

fn render_assoc_items_inner(
w: &mut Buffer,
cx: &Context<'_>,
containing_item: &clean::Item,
it: DefId,
what: AssocItemRender<'_>,
derefs: &mut FxHashSet<DefId>,
) {
info!("Documenting associated items of {:?}", containing_item.name);
let cache = cx.cache();
Expand All @@ -1063,31 +1076,39 @@ fn render_assoc_items(
};
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
if !non_trait.is_empty() {
let mut tmp_buf = Buffer::empty_from(w);
let render_mode = match what {
AssocItemRender::All => {
w.write_str(
tmp_buf.write_str(
"<h2 id=\"implementations\" class=\"small-section-header\">\
Implementations<a href=\"#implementations\" class=\"anchor\"></a>\
</h2>",
);
RenderMode::Normal
}
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
let id =
cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
if let Some(def_id) = type_.def_id(cx.cache()) {
cx.deref_id_map.borrow_mut().insert(def_id, id.clone());
}
write!(
w,
"<h2 id=\"deref-methods\" class=\"small-section-header\">\
tmp_buf,
"<h2 id=\"{id}\" class=\"small-section-header\">\
<span>Methods from {trait_}&lt;Target = {type_}&gt;</span>\
<a href=\"#deref-methods\" class=\"anchor\"></a>\
<a href=\"#{id}\" class=\"anchor\"></a>\
</h2>",
id = id,
trait_ = trait_.print(cx),
type_ = type_.print(cx),
);
RenderMode::ForDeref { mut_: deref_mut_ }
}
};
let mut impls_buf = Buffer::empty_from(w);
for i in &non_trait {
render_impl(
w,
&mut impls_buf,
cx,
i,
containing_item,
Expand All @@ -1104,18 +1125,27 @@ fn render_assoc_items(
},
);
}
if !impls_buf.is_empty() {
w.push_buffer(tmp_buf);
w.push_buffer(impls_buf);
}
}
if let AssocItemRender::DerefFor { .. } = what {
return;
}

if !traits.is_empty() {
let deref_impl =
traits.iter().find(|t| t.trait_did() == cx.tcx().lang_items().deref_trait());
if let Some(impl_) = deref_impl {
let has_deref_mut =
traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait());
render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, derefs);
}

// If we were already one level into rendering deref methods, we don't want to render
// anything after recursing into any further deref methods above.
if let AssocItemRender::DerefFor { .. } = what {
return;
}

let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
traits.iter().partition(|t| t.inner_impl().synthetic);
let (blanket_impl, concrete): (Vec<&&Impl>, _) =
Expand Down Expand Up @@ -1167,6 +1197,7 @@ fn render_deref_methods(
impl_: &Impl,
container_item: &clean::Item,
deref_mut: bool,
derefs: &mut FxHashSet<DefId>,
) {
let cache = cx.cache();
let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
Expand All @@ -1188,16 +1219,16 @@ fn render_deref_methods(
if let Some(did) = target.def_id(cache) {
if let Some(type_did) = impl_.inner_impl().for_.def_id(cache) {
// `impl Deref<Target = S> for S`
if did == type_did {
if did == type_did || !derefs.insert(did) {
// Avoid infinite cycles
return;
}
}
render_assoc_items(w, cx, container_item, did, what);
render_assoc_items_inner(w, cx, container_item, did, what, derefs);
} else {
if let Some(prim) = target.primitive_type() {
if let Some(&did) = cache.primitive_locations.get(&prim) {
render_assoc_items(w, cx, container_item, did, what);
render_assoc_items_inner(w, cx, container_item, did, what, derefs);
}
}
}
Expand Down Expand Up @@ -1987,7 +2018,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
if let Some(impl_) =
v.iter().find(|i| i.trait_did() == cx.tcx().lang_items().deref_trait())
{
sidebar_deref_methods(cx, out, impl_, v);
let mut derefs = FxHashSet::default();
derefs.insert(did);
sidebar_deref_methods(cx, out, impl_, v, &mut derefs);
}

let format_impls = |impls: Vec<&Impl>| {
Expand Down Expand Up @@ -2061,7 +2094,13 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
}
}

fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[Impl]) {
fn sidebar_deref_methods(
cx: &Context<'_>,
out: &mut Buffer,
impl_: &Impl,
v: &[Impl],
derefs: &mut FxHashSet<DefId>,
) {
let c = cx.cache();

debug!("found Deref: {:?}", impl_);
Expand All @@ -2078,7 +2117,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
if let Some(did) = target.def_id(c) {
if let Some(type_did) = impl_.inner_impl().for_.def_id(c) {
// `impl Deref<Target = S> for S`
if did == type_did {
if did == type_did || !derefs.insert(did) {
// Avoid infinite cycles
return;
}
Expand All @@ -2102,9 +2141,17 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
})
.collect::<Vec<_>>();
if !ret.is_empty() {
let map;
let id = if let Some(target_def_id) = real_target.def_id(c) {
map = cx.deref_id_map.borrow();
map.get(&target_def_id).expect("Deref section without derived id")
} else {
"deref-methods"
};
write!(
out,
"<h3 class=\"sidebar-title\"><a href=\"#deref-methods\">Methods from {}&lt;Target={}&gt;</a></h3>",
"<h3 class=\"sidebar-title\"><a href=\"#{}\">Methods from {}&lt;Target={}&gt;</a></h3>",
id,
Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(cx))),
Escape(&format!("{:#}", real_target.print(cx))),
);
Expand All @@ -2117,6 +2164,21 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &[
out.push_str("</div>");
}
}

// Recurse into any further impls that might exist for `target`
if let Some(target_did) = target.def_id_no_primitives() {
if let Some(target_impls) = c.impls.get(&target_did) {
if let Some(target_deref_impl) = target_impls.iter().find(|i| {
i.inner_impl()
.trait_
.as_ref()
.map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait())
.unwrap_or(false)
}) {
sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs);
}
}
}
}
}

Expand Down
Loading