Auto merge of #112900 - GuillaumeGomez:rollup-1blf4io, r=GuillaumeGomez

Rollup of 4 pull requests

Successful merges:

 - #112538 (Removed unnecessary &String -> &str, now that &String implements StableOrd as well)
 - #112868 (Liberate bound vars properly when suggesting missing async-fn-in-trait)
 - #112892 (resolve: Minor cleanup to `fn resolve_path_with_ribs`)
 - #112894 (Fix union fields display)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-06-21 19:48:41 +00:00
commit 065a1f5df9
15 changed files with 134 additions and 95 deletions

View File

@ -107,6 +107,10 @@ impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
{ {
UnordItems(self.0.flat_map(f)) UnordItems(self.0.flat_map(f))
} }
pub fn collect<C: From<UnordItems<T, I>>>(self) -> C {
self.into()
}
} }
impl<T> UnordItems<T, std::iter::Empty<T>> { impl<T> UnordItems<T, std::iter::Empty<T>> {
@ -161,10 +165,6 @@ impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
items items
} }
pub fn collect<C: From<UnordItems<T, I>>>(self) -> C {
self.into()
}
} }
/// This is a set collection type that tries very hard to not expose /// This is a set collection type that tries very hard to not expose

View File

@ -470,19 +470,16 @@ fn suggestion_signature<'tcx>(
); );
match assoc.kind { match assoc.kind {
ty::AssocKind::Fn => { ty::AssocKind::Fn => fn_sig_suggestion(
// We skip the binder here because the binder would deanonymize all tcx,
// late-bound regions, and we don't want method signatures to show up tcx.liberate_late_bound_regions(
// `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound assoc.def_id,
// regions just fine, showing `fn(&MyType)`. tcx.fn_sig(assoc.def_id).subst(tcx, substs),
fn_sig_suggestion( ),
tcx, assoc.ident(tcx),
tcx.fn_sig(assoc.def_id).subst(tcx, substs).skip_binder(), tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
assoc.ident(tcx), assoc,
tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs), ),
assoc,
)
}
ty::AssocKind::Type => { ty::AssocKind::Type => {
let (generics, where_clauses) = bounds_from_generic_predicates( let (generics, where_clauses) = bounds_from_generic_predicates(
tcx, tcx,

View File

@ -198,7 +198,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
let (name, mut auto) = self.auto_labels(item_id, attr); let (name, mut auto) = self.auto_labels(item_id, attr);
let except = self.except(attr); let except = self.except(attr);
let loaded_from_disk = self.loaded_from_disk(attr); let loaded_from_disk = self.loaded_from_disk(attr);
for e in except.items().map(|x| x.as_str()).into_sorted_stable_ord() { for e in except.items().into_sorted_stable_ord() {
if !auto.remove(e) { if !auto.remove(e) {
self.tcx.sess.emit_fatal(errors::AssertionAuto { span: attr.span, name, e }); self.tcx.sess.emit_fatal(errors::AssertionAuto { span: attr.span, name, e });
} }
@ -377,17 +377,15 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
continue; continue;
}; };
self.checked_attrs.insert(attr.id); self.checked_attrs.insert(attr.id);
for label in assertion.clean.items().map(|x| x.as_str()).into_sorted_stable_ord() { for label in assertion.clean.items().into_sorted_stable_ord() {
let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap();
self.assert_clean(item_span, dep_node); self.assert_clean(item_span, dep_node);
} }
for label in assertion.dirty.items().map(|x| x.as_str()).into_sorted_stable_ord() { for label in assertion.dirty.items().into_sorted_stable_ord() {
let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap();
self.assert_dirty(item_span, dep_node); self.assert_dirty(item_span, dep_node);
} }
for label in for label in assertion.loaded_from_disk.items().into_sorted_stable_ord() {
assertion.loaded_from_disk.items().map(|x| x.as_str()).into_sorted_stable_ord()
{
let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap();
self.assert_loaded_from_disk(item_span, dep_node); self.assert_loaded_from_disk(item_span, dep_node);
} }

View File

@ -855,12 +855,11 @@ fn all_except_most_recent(
let most_recent = deletion_candidates.items().map(|(&(timestamp, _), _)| timestamp).max(); let most_recent = deletion_candidates.items().map(|(&(timestamp, _), _)| timestamp).max();
if let Some(most_recent) = most_recent { if let Some(most_recent) = most_recent {
UnordMap::from( deletion_candidates
deletion_candidates .into_items()
.into_items() .filter(|&((timestamp, _), _)| timestamp != most_recent)
.filter(|&((timestamp, _), _)| timestamp != most_recent) .map(|((_, path), lock)| (path, lock))
.map(|((_, path), lock)| (path, lock)), .collect()
)
} else { } else {
UnordMap::default() UnordMap::default()
} }

View File

@ -1459,60 +1459,47 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}); });
} }
enum FindBindingResult<'a> { let binding = if let Some(module) = module {
Binding(Result<&'a NameBinding<'a>, Determinacy>), self.resolve_ident_in_module(
Res(Res), module,
} ident,
let find_binding_in_ns = |this: &mut Self, ns| { ns,
let binding = if let Some(module) = module { parent_scope,
this.resolve_ident_in_module( finalize,
module, ignore_binding,
ident, )
ns, } else if let Some(ribs) = ribs && let Some(TypeNS | ValueNS) = opt_ns {
parent_scope, match self.resolve_ident_in_lexical_scope(
finalize, ident,
ignore_binding, ns,
) parent_scope,
} else if let Some(ribs) = ribs finalize,
&& let Some(TypeNS | ValueNS) = opt_ns &ribs[ns],
{ ignore_binding,
match this.resolve_ident_in_lexical_scope( ) {
ident, // we found a locally-imported or available item/module
ns, Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
parent_scope, // we found a local variable or type param
finalize, Some(LexicalScopeBinding::Res(res)) => {
&ribs[ns], record_segment_res(self, res);
ignore_binding, return PathResult::NonModule(PartialRes::with_unresolved_segments(
) { res,
// we found a locally-imported or available item/module path.len() - 1,
Some(LexicalScopeBinding::Item(binding)) => Ok(binding), ));
// we found a local variable or type param
Some(LexicalScopeBinding::Res(res)) => return FindBindingResult::Res(res),
_ => Err(Determinacy::determined(finalize.is_some())),
} }
} else { _ => Err(Determinacy::determined(finalize.is_some())),
let scopes = ScopeSet::All(ns, opt_ns.is_none());
this.early_resolve_ident_in_lexical_scope(
ident,
scopes,
parent_scope,
finalize,
finalize.is_some(),
ignore_binding,
)
};
FindBindingResult::Binding(binding)
};
let binding = match find_binding_in_ns(self, ns) {
FindBindingResult::Res(res) => {
record_segment_res(self, res);
return PathResult::NonModule(PartialRes::with_unresolved_segments(
res,
path.len() - 1,
));
} }
FindBindingResult::Binding(binding) => binding, } else {
self.early_resolve_ident_in_lexical_scope(
ident,
ScopeSet::All(ns, opt_ns.is_none()),
parent_scope,
finalize,
finalize.is_some(),
ignore_binding,
)
}; };
match binding { match binding {
Ok(binding) => { Ok(binding) => {
if segment_idx == 1 { if segment_idx == 1 {

View File

@ -421,11 +421,10 @@ fn document<'a, 'cx: 'a>(
display_fn(move |f| { display_fn(move |f| {
document_item_info(cx, item, parent).render_into(f).unwrap(); document_item_info(cx, item, parent).render_into(f).unwrap();
if parent.is_none() { if parent.is_none() {
write!(f, "{}", document_full_collapsible(item, cx, heading_offset))?; write!(f, "{}", document_full_collapsible(item, cx, heading_offset))
} else { } else {
write!(f, "{}", document_full(item, cx, heading_offset))?; write!(f, "{}", document_full(item, cx, heading_offset))
} }
Ok(())
}) })
} }

View File

@ -1,5 +1,5 @@
{% if !items.is_empty() %} {% if !items.is_empty() %}
<span class="item-info"> {# #} <span class="item-info">
{% for item in items %} {% for item in items %}
{{item|safe}} {# #} {{item|safe}} {# #}
{% endfor %} {% endfor %}

View File

@ -4,14 +4,15 @@
</code></pre> </code></pre>
{{ self.document() | safe }} {{ self.document() | safe }}
{% if self.fields_iter().peek().is_some() %} {% if self.fields_iter().peek().is_some() %}
<h2 id="fields" class="fields small-section-header"> <h2 id="fields" class="fields small-section-header"> {# #}
Fields<a href="#fields" class="anchor">§</a> Fields<a href="#fields" class="anchor">§</a> {# #}
</h2> </h2>
{% for (field, ty) in self.fields_iter() %} {% for (field, ty) in self.fields_iter() %}
{% let name = field.name.expect("union field name") %} {% let name = field.name.expect("union field name") %}
<span id="structfield.{{ name }}" class="{{ ItemType::StructField }} small-section-header"> <span id="structfield.{{ name }}" {#+ #}
<a href="#structfield.{{ name }}" class="anchor field">§</a> class="{{ ItemType::StructField +}} small-section-header"> {# #}
<code>{{ name }}: {{ self.print_ty(ty) | safe }}</code> <a href="#structfield.{{ name }}" class="anchor field">§</a> {# #}
<code>{{ name }}: {{+ self.print_ty(ty) | safe }}</code> {# #}
</span> </span>
{% if let Some(stability_class) = self.stability_field(field) %} {% if let Some(stability_class) = self.stability_field(field) %}
<span class="stab {{ stability_class }}"></span> <span class="stab {{ stability_class }}"></span>

View File

@ -1,5 +1,5 @@
<div class="main-heading"> {# #} <div class="main-heading"> {# #}
<h1> {# #} <h1>
{{typ}} {{typ}}
{# The breadcrumbs of the item path, like std::string #} {# The breadcrumbs of the item path, like std::string #}
{% for component in path_components %} {% for component in path_components %}
@ -12,7 +12,7 @@
alt="Copy item path"> {# #} alt="Copy item path"> {# #}
</button> {# #} </button> {# #}
</h1> {# #} </h1> {# #}
<span class="out-of-band"> {# #} <span class="out-of-band">
{% if !stability_since_raw.is_empty() %} {% if !stability_since_raw.is_empty() %}
{{ stability_since_raw|safe +}} · {#+ #} {{ stability_since_raw|safe +}} · {#+ #}
{% endif %} {% endif %}

View File

@ -0,0 +1,18 @@
// This test checks that fields are displayed as expected (one by line).
go-to: "file://" + |DOC_PATH| + "/test_docs/fields/struct.Struct.html"
store-position: ("#structfield\.a", {"y": a_y})
store-position: ("#structfield\.b", {"y": b_y})
assert: |a_y| < |b_y|
go-to: "file://" + |DOC_PATH| + "/test_docs/fields/union.Union.html"
store-position: ("#structfield\.a", {"y": a_y})
store-position: ("#structfield\.b", {"y": b_y})
assert: |a_y| < |b_y|
go-to: "file://" + |DOC_PATH| + "/test_docs/fields/enum.Enum.html"
store-position: ("#variant\.A\.field\.a", {"y": a_y})
store-position: ("#variant\.A\.field\.b", {"y": b_y})
assert: |a_y| < |b_y|
store-position: ("#variant\.B\.field\.a", {"y": a_y})
store-position: ("#variant\.B\.field\.b", {"y": b_y})
assert: |a_y| < |b_y|

View File

@ -486,3 +486,24 @@ pub mod search_results {
} }
} }
pub mod fields {
pub struct Struct {
pub a: u8,
pub b: u32,
}
pub union Union {
pub a: u8,
pub b: u32,
}
pub enum Enum {
A {
a: u8,
b: u32,
},
B {
a: u8,
b: u32,
},
}
}

View File

@ -0,0 +1,11 @@
#![crate_name = "foo"]
// @has 'foo/union.Union.html'
// Checking that there is a whitespace after `:`.
// @has - '//*[@id="structfield.a"]/code' 'a: u8'
// @has - '//*[@id="structfield.b"]/code' 'b: u32'
pub union Union {
pub a: u8,
/// tadam
pub b: u32,
}

View File

@ -9,11 +9,14 @@ trait Trait {
async fn bar() -> i32; async fn bar() -> i32;
fn test(&self) -> impl Sized + '_; fn test(&self) -> impl Sized + '_;
async fn baz(&self) -> &i32;
} }
struct S; struct S;
impl Trait for S {fn test(&self) -> impl Sized + '_ { todo!() } impl Trait for S {async fn baz(&self) -> &i32 { todo!() }
fn test(&self) -> impl Sized + '_ { todo!() }
async fn bar() -> i32 { todo!() } async fn bar() -> i32 { todo!() }
async fn foo() { todo!() } async fn foo() { todo!() }
} }

View File

@ -9,6 +9,8 @@ trait Trait {
async fn bar() -> i32; async fn bar() -> i32;
fn test(&self) -> impl Sized + '_; fn test(&self) -> impl Sized + '_;
async fn baz(&self) -> &i32;
} }
struct S; struct S;

View File

@ -1,5 +1,5 @@
error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test` error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`, `baz`
--> $DIR/suggest-missing-item.rs:16:1 --> $DIR/suggest-missing-item.rs:18:1
| |
LL | async fn foo(); LL | async fn foo();
| --------------- `foo` from trait | --------------- `foo` from trait
@ -9,9 +9,12 @@ LL | async fn bar() -> i32;
LL | LL |
LL | fn test(&self) -> impl Sized + '_; LL | fn test(&self) -> impl Sized + '_;
| ---------------------------------- `test` from trait | ---------------------------------- `test` from trait
LL |
LL | async fn baz(&self) -> &i32;
| ---------------------------- `baz` from trait
... ...
LL | impl Trait for S {} LL | impl Trait for S {}
| ^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `test` in implementation | ^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `test`, `baz` in implementation
error: aborting due to previous error error: aborting due to previous error