Skip to content

Commit

Permalink
Auto merge of #90422 - GuillaumeGomez:rollup-s1mdag0, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #90156 (Remove underlines from non-top docblocks.)
 - #90183 (Show all Deref implementations recursively)
 - #90202 (Improve and test cross-crate hygiene)
 - #90375 (Use `is_global` in `candidate_should_be_dropped_in_favor_of`)
 - #90399 (Skipping verbose diagnostic suggestions when calling .as_ref() on type not implementing AsRef)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Oct 30, 2021
2 parents 2609fab + 197da45 commit e249ce6
Show file tree
Hide file tree
Showing 44 changed files with 968 additions and 71 deletions.
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

0 comments on commit e249ce6

Please sign in to comment.