mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-07 12:48:30 +00:00
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:
commit
065a1f5df9
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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(())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 %}
|
||||||
|
@ -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>
|
||||||
|
@ -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 %}
|
||||||
|
18
tests/rustdoc-gui/fields.goml
Normal file
18
tests/rustdoc-gui/fields.goml
Normal 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|
|
@ -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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
11
tests/rustdoc/union-fields-html.rs
Normal file
11
tests/rustdoc/union-fields-html.rs
Normal 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,
|
||||||
|
}
|
@ -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!() }
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user