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))
}
pub fn collect<C: From<UnordItems<T, I>>>(self) -> C {
self.into()
}
}
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
}
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

View File

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

View File

@ -198,7 +198,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
let (name, mut auto) = self.auto_labels(item_id, attr);
let except = self.except(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) {
self.tcx.sess.emit_fatal(errors::AssertionAuto { span: attr.span, name, e });
}
@ -377,17 +377,15 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
continue;
};
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();
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();
self.assert_dirty(item_span, dep_node);
}
for label in
assertion.loaded_from_disk.items().map(|x| x.as_str()).into_sorted_stable_ord()
{
for label in assertion.loaded_from_disk.items().into_sorted_stable_ord() {
let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap();
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();
if let Some(most_recent) = most_recent {
UnordMap::from(
deletion_candidates
.into_items()
.filter(|&((timestamp, _), _)| timestamp != most_recent)
.map(|((_, path), lock)| (path, lock)),
)
deletion_candidates
.into_items()
.filter(|&((timestamp, _), _)| timestamp != most_recent)
.map(|((_, path), lock)| (path, lock))
.collect()
} else {
UnordMap::default()
}

View File

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

View File

@ -421,11 +421,10 @@ fn document<'a, 'cx: 'a>(
display_fn(move |f| {
document_item_info(cx, item, parent).render_into(f).unwrap();
if parent.is_none() {
write!(f, "{}", document_full_collapsible(item, cx, heading_offset))?;
write!(f, "{}", document_full_collapsible(item, cx, heading_offset))
} 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() %}
<span class="item-info"> {# #}
<span class="item-info">
{% for item in items %}
{{item|safe}} {# #}
{% endfor %}

View File

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

View File

@ -1,5 +1,5 @@
<div class="main-heading"> {# #}
<h1> {# #}
<h1>
{{typ}}
{# The breadcrumbs of the item path, like std::string #}
{% for component in path_components %}
@ -12,7 +12,7 @@
alt="Copy item path"> {# #}
</button> {# #}
</h1> {# #}
<span class="out-of-band"> {# #}
<span class="out-of-band">
{% if !stability_since_raw.is_empty() %}
{{ stability_since_raw|safe +}} · {#+ #}
{% 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;
fn test(&self) -> impl Sized + '_;
async fn baz(&self) -> &i32;
}
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 foo() { todo!() }
}

View File

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

View File

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