Merge from rustc
This commit is contained in:
commit
3c055f73fe
1101 changed files with 17090 additions and 8617 deletions
|
|
@ -917,8 +917,24 @@ class RustBuild(object):
|
|||
if toml_val is not None:
|
||||
env["{}_{}".format(var_name, host_triple_sanitized)] = toml_val
|
||||
|
||||
# preserve existing RUSTFLAGS
|
||||
env.setdefault("RUSTFLAGS", "")
|
||||
# In src/etc/rust_analyzer_settings.json, we configure rust-analyzer to
|
||||
# pass RUSTC_BOOTSTRAP=1 to all cargo invocations because the standard
|
||||
# library uses unstable Cargo features. Without RUSTC_BOOTSTRAP,
|
||||
# rust-analyzer would fail to fetch workspace layout when the system's
|
||||
# default toolchain is not nightly.
|
||||
#
|
||||
# But that setting has the collateral effect of rust-analyzer also
|
||||
# passing RUSTC_BOOTSTRAP=1 to all x.py invocations too (the various overrideCommand).
|
||||
# For compiling bootstrap that can cause spurious rebuilding of bootstrap when
|
||||
# rust-analyzer x.py invocations are interleaved with handwritten ones on the
|
||||
# command line.
|
||||
#
|
||||
# Set RUSTC_BOOTSTRAP=1 consistently.
|
||||
env["RUSTC_BOOTSTRAP"] = "1"
|
||||
|
||||
default_rustflags = "" if env.get("RUSTFLAGS_BOOTSTRAP", "") else "-Zallow-features="
|
||||
|
||||
env.setdefault("RUSTFLAGS", default_rustflags)
|
||||
|
||||
target_features = []
|
||||
if self.get_toml("crt-static", build_section) == "true":
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ static SETTINGS_HASHES: &[&str] = &[
|
|||
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
|
||||
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
|
||||
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
|
||||
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
|
||||
];
|
||||
static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json");
|
||||
|
||||
|
|
|
|||
|
|
@ -1799,15 +1799,20 @@ impl<'a> Builder<'a> {
|
|||
}
|
||||
|
||||
if self.config.rust_remap_debuginfo {
|
||||
// FIXME: handle vendored sources
|
||||
let registry_src = t!(home::cargo_home()).join("registry").join("src");
|
||||
let mut env_var = OsString::new();
|
||||
for entry in t!(std::fs::read_dir(registry_src)) {
|
||||
if !env_var.is_empty() {
|
||||
env_var.push("\t");
|
||||
}
|
||||
env_var.push(t!(entry).path());
|
||||
if self.config.vendor {
|
||||
let vendor = self.build.src.join("vendor");
|
||||
env_var.push(vendor);
|
||||
env_var.push("=/rust/deps");
|
||||
} else {
|
||||
let registry_src = t!(home::cargo_home()).join("registry").join("src");
|
||||
for entry in t!(std::fs::read_dir(registry_src)) {
|
||||
if !env_var.is_empty() {
|
||||
env_var.push("\t");
|
||||
}
|
||||
env_var.push(t!(entry).path());
|
||||
env_var.push("=/rust/deps");
|
||||
}
|
||||
}
|
||||
cargo.env("RUSTC_CARGO_REGISTRY_SRC_TO_REMAP", env_var);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit f6bd083c4ccfc4ce6699b8b4154e3c45c5a27a8c
|
||||
Subproject commit 6bc2415218d4dd0cb01433d8320f5ccf79c343a1
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 3565c7978cfc9662f5963b135690ff9cbbfa0318
|
||||
Subproject commit 8c77e8be9da1a9c70545556218d563c8d061f1fd
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit c0be6299e52e4164c30ba6f41bd0ad0aaee64972
|
||||
Subproject commit ddf5cb0e6ee54ba2dd84c8ca3e1314120014e20d
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit d13e85152a977cd0bcaf583cf5f49e86225697de
|
||||
Subproject commit 4af29d1a7f64f88a36539662c6a84fe1fbe6cde1
|
||||
|
|
@ -246,6 +246,8 @@ approved by the appropriate team for that shared code before acceptance.
|
|||
introducing unconditional uses of features that another variation of the
|
||||
target may not have; use conditional compilation or runtime detection, as
|
||||
appropriate, to let each target run code supported by that target.
|
||||
- Tier 3 targets must be able to produce assembly using at least one of
|
||||
rustc's supported backends from any host target.
|
||||
|
||||
If a tier 3 target stops meeting these requirements, or the target maintainers
|
||||
no longer have interest or time, or the target shows no signs of activity and
|
||||
|
|
|
|||
|
|
@ -44,15 +44,20 @@ To enable checking of values, but to provide an *none*/empty set of expected val
|
|||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name)'
|
||||
rustc --check-cfg 'cfg(name, values())'
|
||||
rustc --check-cfg 'cfg(name, values(none()))'
|
||||
```
|
||||
|
||||
To enable checking of name but not values (i.e. unknown expected values), use this form:
|
||||
To enable checking of name but not values, use one of these forms:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name, values(any()))'
|
||||
```
|
||||
- No expected values (_will lint on every value_):
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name, values())'
|
||||
```
|
||||
|
||||
- Unknown expected values (_will never lint_):
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name, values(any()))'
|
||||
```
|
||||
|
||||
To avoid repeating the same set of values, use this form:
|
||||
|
||||
|
|
@ -114,18 +119,14 @@ as argument to `--check-cfg`.
|
|||
This table describe the equivalence of a `--cfg` argument to a `--check-cfg` argument.
|
||||
|
||||
| `--cfg` | `--check-cfg` |
|
||||
|-----------------------------|----------------------------------------------------------|
|
||||
|-------------------------------|------------------------------------------------------------|
|
||||
| *nothing* | *nothing* or `--check-cfg=cfg()` (to enable the checking) |
|
||||
| `--cfg foo` | `--check-cfg=cfg(foo), --check-cfg=cfg(foo, values())` or `--check-cfg=cfg(foo, values(none()))` |
|
||||
| `--cfg foo` | `--check-cfg=cfg(foo)` or `--check-cfg=cfg(foo, values(none()))` |
|
||||
| `--cfg foo=""` | `--check-cfg=cfg(foo, values(""))` |
|
||||
| `--cfg foo="bar"` | `--check-cfg=cfg(foo, values("bar"))` |
|
||||
| `--cfg foo="1" --cfg foo="2"` | `--check-cfg=cfg(foo, values("1", "2"))` |
|
||||
| `--cfg foo="1" --cfg bar="2"` | `--check-cfg=cfg(foo, values("1")) --check-cfg=cfg(bar, values("2"))` |
|
||||
| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo) --check-cfg=cfg(foo, values("bar"))` |
|
||||
|
||||
NOTE: There is (currently) no way to express that a condition name is expected but no (!= none)
|
||||
values are expected. Passing an empty `values()` means *(none)* in the sense of `#[cfg(foo)]`
|
||||
with no value. Users are expected to NOT pass a `--check-cfg` with that condition name.
|
||||
| `--cfg foo --cfg foo="bar"` | `--check-cfg=cfg(foo, values(none(), "bar"))` |
|
||||
|
||||
### Example: Cargo-like `feature` example
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"git.detectSubmodulesLimit": 20,
|
||||
"rust-analyzer.check.invocationLocation": "root",
|
||||
"rust-analyzer.check.invocationStrategy": "once",
|
||||
"rust-analyzer.check.overrideCommand": [
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ pub(crate) fn build_impls(
|
|||
let tcx = cx.tcx;
|
||||
|
||||
// for each implementation of an item represented by `did`, build the clean::Item for that impl
|
||||
for &did in tcx.inherent_impls(did).iter() {
|
||||
for &did in tcx.inherent_impls(did).into_iter().flatten() {
|
||||
build_impl(cx, did, attrs, ret);
|
||||
}
|
||||
|
||||
|
|
@ -325,7 +325,7 @@ pub(crate) fn build_impls(
|
|||
if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
|
||||
let type_ =
|
||||
if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) };
|
||||
for &did in tcx.incoherent_impls(type_) {
|
||||
for &did in tcx.incoherent_impls(type_).into_iter().flatten() {
|
||||
build_impl(cx, did, attrs, ret);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1862,7 +1862,7 @@ impl PrimitiveType {
|
|||
.get(self)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(move |&simp| tcx.incoherent_impls(simp))
|
||||
.flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten())
|
||||
.copied()
|
||||
}
|
||||
|
||||
|
|
@ -1870,7 +1870,7 @@ impl PrimitiveType {
|
|||
Self::simplified_types()
|
||||
.values()
|
||||
.flatten()
|
||||
.flat_map(move |&simp| tcx.incoherent_impls(simp))
|
||||
.flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter().flatten())
|
||||
.copied()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -312,7 +312,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
|
|||
|
||||
Symbol::intern(&match p.kind {
|
||||
// FIXME(never_patterns): does this make sense?
|
||||
PatKind::Wild | PatKind::Never | PatKind::Struct(..) => return kw::Underscore,
|
||||
PatKind::Wild | PatKind::Err(_) | PatKind::Never | PatKind::Struct(..) => {
|
||||
return kw::Underscore;
|
||||
}
|
||||
PatKind::Binding(_, _, ident, _) => return ident.name,
|
||||
PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
|
||||
PatKind::Or(pats) => {
|
||||
|
|
|
|||
|
|
@ -530,7 +530,6 @@ impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator
|
|||
for event in &mut self.inner {
|
||||
match &event.0 {
|
||||
Event::End(Tag::Heading(..)) => break,
|
||||
Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {}
|
||||
Event::Text(text) | Event::Code(text) => {
|
||||
id.extend(text.chars().filter_map(slugify));
|
||||
self.buf.push_back(event);
|
||||
|
|
@ -549,12 +548,10 @@ impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator
|
|||
|
||||
let level =
|
||||
std::cmp::min(level as u32 + (self.heading_offset as u32), MAX_HEADER_LEVEL);
|
||||
self.buf.push_back((Event::Html(format!("</a></h{level}>").into()), 0..0));
|
||||
self.buf.push_back((Event::Html(format!("</h{level}>").into()), 0..0));
|
||||
|
||||
let start_tags = format!(
|
||||
"<h{level} id=\"{id}\">\
|
||||
<a href=\"#{id}\">",
|
||||
);
|
||||
let start_tags =
|
||||
format!("<h{level} id=\"{id}\"><a class=\"doc-anchor\" href=\"#{id}\">§</a>");
|
||||
return Some((Event::Html(start_tags.into()), 0..0));
|
||||
}
|
||||
event
|
||||
|
|
|
|||
|
|
@ -311,26 +311,38 @@ fn test_header() {
|
|||
assert_eq!(output, expect, "original: {}", input);
|
||||
}
|
||||
|
||||
t("# Foo bar", "<h2 id=\"foo-bar\"><a href=\"#foo-bar\">Foo bar</a></h2>");
|
||||
t(
|
||||
"# Foo bar",
|
||||
"<h2 id=\"foo-bar\"><a class=\"doc-anchor\" href=\"#foo-bar\">§</a>Foo bar</h2>",
|
||||
);
|
||||
t(
|
||||
"## Foo-bar_baz qux",
|
||||
"<h3 id=\"foo-bar_baz-qux\">\
|
||||
<a href=\"#foo-bar_baz-qux\">Foo-bar_baz qux</a></h3>",
|
||||
<a class=\"doc-anchor\" href=\"#foo-bar_baz-qux\">§</a>\
|
||||
Foo-bar_baz qux\
|
||||
</h3>",
|
||||
);
|
||||
t(
|
||||
"### **Foo** *bar* baz!?!& -_qux_-%",
|
||||
"<h4 id=\"foo-bar-baz--qux-\">\
|
||||
<a href=\"#foo-bar-baz--qux-\"><strong>Foo</strong> \
|
||||
<em>bar</em> baz!?!& -<em>qux</em>-%</a>\
|
||||
<a class=\"doc-anchor\" href=\"#foo-bar-baz--qux-\">§</a>\
|
||||
<strong>Foo</strong> <em>bar</em> baz!?!& -<em>qux</em>-%\
|
||||
</h4>",
|
||||
);
|
||||
t(
|
||||
"#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux",
|
||||
"<h5 id=\"foo--bar--baz--qux\">\
|
||||
<a href=\"#foo--bar--baz--qux\"><strong>Foo?</strong> & *bar?!* \
|
||||
<em><code>baz</code></em> ❤ #qux</a>\
|
||||
<a class=\"doc-anchor\" href=\"#foo--bar--baz--qux\">§</a>\
|
||||
<strong>Foo?</strong> & *bar?!* <em><code>baz</code></em> ❤ #qux\
|
||||
</h5>",
|
||||
);
|
||||
t(
|
||||
"# Foo [bar](https://hello.yo)",
|
||||
"<h2 id=\"foo-bar\">\
|
||||
<a class=\"doc-anchor\" href=\"#foo-bar\">§</a>\
|
||||
Foo <a href=\"https://hello.yo\">bar</a>\
|
||||
</h2>",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -351,12 +363,36 @@ fn test_header_ids_multiple_blocks() {
|
|||
assert_eq!(output, expect, "original: {}", input);
|
||||
}
|
||||
|
||||
t(&mut map, "# Example", "<h2 id=\"example\"><a href=\"#example\">Example</a></h2>");
|
||||
t(&mut map, "# Panics", "<h2 id=\"panics\"><a href=\"#panics\">Panics</a></h2>");
|
||||
t(&mut map, "# Example", "<h2 id=\"example-1\"><a href=\"#example-1\">Example</a></h2>");
|
||||
t(&mut map, "# Search", "<h2 id=\"search-1\"><a href=\"#search-1\">Search</a></h2>");
|
||||
t(&mut map, "# Example", "<h2 id=\"example-2\"><a href=\"#example-2\">Example</a></h2>");
|
||||
t(&mut map, "# Panics", "<h2 id=\"panics-1\"><a href=\"#panics-1\">Panics</a></h2>");
|
||||
t(
|
||||
&mut map,
|
||||
"# Example",
|
||||
"<h2 id=\"example\"><a class=\"doc-anchor\" href=\"#example\">§</a>Example</h2>",
|
||||
);
|
||||
t(
|
||||
&mut map,
|
||||
"# Panics",
|
||||
"<h2 id=\"panics\"><a class=\"doc-anchor\" href=\"#panics\">§</a>Panics</h2>",
|
||||
);
|
||||
t(
|
||||
&mut map,
|
||||
"# Example",
|
||||
"<h2 id=\"example-1\"><a class=\"doc-anchor\" href=\"#example-1\">§</a>Example</h2>",
|
||||
);
|
||||
t(
|
||||
&mut map,
|
||||
"# Search",
|
||||
"<h2 id=\"search-1\"><a class=\"doc-anchor\" href=\"#search-1\">§</a>Search</h2>",
|
||||
);
|
||||
t(
|
||||
&mut map,
|
||||
"# Example",
|
||||
"<h2 id=\"example-2\"><a class=\"doc-anchor\" href=\"#example-2\">§</a>Example</h2>",
|
||||
);
|
||||
t(
|
||||
&mut map,
|
||||
"# Panics",
|
||||
"<h2 id=\"panics-1\"><a class=\"doc-anchor\" href=\"#panics-1\">§</a>Panics</h2>",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -1207,17 +1207,31 @@ impl<'a> AssocItemLink<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn write_impl_section_heading(mut w: impl fmt::Write, title: &str, id: &str) {
|
||||
pub fn write_section_heading(
|
||||
w: &mut impl fmt::Write,
|
||||
title: &str,
|
||||
id: &str,
|
||||
extra_class: Option<&str>,
|
||||
extra: impl fmt::Display,
|
||||
) {
|
||||
let (extra_class, whitespace) = match extra_class {
|
||||
Some(extra) => (extra, " "),
|
||||
None => ("", ""),
|
||||
};
|
||||
write!(
|
||||
w,
|
||||
"<h2 id=\"{id}\" class=\"section-header\">\
|
||||
"<h2 id=\"{id}\" class=\"{extra_class}{whitespace}section-header\">\
|
||||
{title}\
|
||||
<a href=\"#{id}\" class=\"anchor\">§</a>\
|
||||
</h2>"
|
||||
</h2>{extra}",
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) {
|
||||
write_section_heading(w, title, id, None, "")
|
||||
}
|
||||
|
||||
pub(crate) fn render_all_impls(
|
||||
mut w: impl Write,
|
||||
cx: &mut Context<'_>,
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ use super::{
|
|||
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
|
||||
render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
|
||||
render_impl, render_rightside, render_stability_since_raw,
|
||||
render_stability_since_raw_with_extra, AssocItemLink, AssocItemRender, Context,
|
||||
ImplRenderingParameters, RenderMode,
|
||||
render_stability_since_raw_with_extra, write_section_heading, AssocItemLink, AssocItemRender,
|
||||
Context, ImplRenderingParameters, RenderMode,
|
||||
};
|
||||
use crate::clean;
|
||||
use crate::config::ModuleSorting;
|
||||
|
|
@ -425,13 +425,12 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
|
|||
w.write_str(ITEM_TABLE_CLOSE);
|
||||
}
|
||||
last_section = Some(my_section);
|
||||
write!(
|
||||
write_section_heading(
|
||||
w,
|
||||
"<h2 id=\"{id}\" class=\"section-header\">\
|
||||
<a href=\"#{id}\">{name}</a>\
|
||||
</h2>{ITEM_TABLE_OPEN}",
|
||||
id = cx.derive_id(my_section.id()),
|
||||
name = my_section.name(),
|
||||
my_section.name(),
|
||||
&cx.derive_id(my_section.id()),
|
||||
None,
|
||||
ITEM_TABLE_OPEN,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -814,16 +813,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
// Trait documentation
|
||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
|
||||
|
||||
fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) {
|
||||
write!(
|
||||
w,
|
||||
"<h2 id=\"{0}\" class=\"section-header\">\
|
||||
{1}<a href=\"#{0}\" class=\"anchor\">§</a>\
|
||||
</h2>{2}",
|
||||
id, title, extra_content
|
||||
)
|
||||
}
|
||||
|
||||
fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) {
|
||||
let name = m.name.unwrap();
|
||||
info!("Documenting {name} on {ty_name:?}", ty_name = t.name);
|
||||
|
|
@ -857,10 +846,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
}
|
||||
|
||||
if !required_types.is_empty() {
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"required-associated-types",
|
||||
"Required Associated Types",
|
||||
"required-associated-types",
|
||||
None,
|
||||
"<div class=\"methods\">",
|
||||
);
|
||||
for t in required_types {
|
||||
|
|
@ -869,10 +859,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
w.write_str("</div>");
|
||||
}
|
||||
if !provided_types.is_empty() {
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"provided-associated-types",
|
||||
"Provided Associated Types",
|
||||
"provided-associated-types",
|
||||
None,
|
||||
"<div class=\"methods\">",
|
||||
);
|
||||
for t in provided_types {
|
||||
|
|
@ -882,10 +873,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
}
|
||||
|
||||
if !required_consts.is_empty() {
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"required-associated-consts",
|
||||
"Required Associated Constants",
|
||||
"required-associated-consts",
|
||||
None,
|
||||
"<div class=\"methods\">",
|
||||
);
|
||||
for t in required_consts {
|
||||
|
|
@ -894,10 +886,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
w.write_str("</div>");
|
||||
}
|
||||
if !provided_consts.is_empty() {
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"provided-associated-consts",
|
||||
"Provided Associated Constants",
|
||||
"provided-associated-consts",
|
||||
None,
|
||||
"<div class=\"methods\">",
|
||||
);
|
||||
for t in provided_consts {
|
||||
|
|
@ -908,10 +901,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
|
||||
// Output the documentation for each function individually
|
||||
if !required_methods.is_empty() || must_implement_one_of_functions.is_some() {
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"required-methods",
|
||||
"Required Methods",
|
||||
"required-methods",
|
||||
None,
|
||||
"<div class=\"methods\">",
|
||||
);
|
||||
|
||||
|
|
@ -929,10 +923,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
w.write_str("</div>");
|
||||
}
|
||||
if !provided_methods.is_empty() {
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"provided-methods",
|
||||
"Provided Methods",
|
||||
"provided-methods",
|
||||
None,
|
||||
"<div class=\"methods\">",
|
||||
);
|
||||
for m in provided_methods {
|
||||
|
|
@ -949,10 +944,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
let mut extern_crates = FxHashSet::default();
|
||||
|
||||
if !t.is_object_safe(cx.tcx()) {
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"object-safety",
|
||||
"Object Safety",
|
||||
"object-safety",
|
||||
None,
|
||||
&format!(
|
||||
"<div class=\"object-safety-info\">This trait is <b>not</b> \
|
||||
<a href=\"{base}/reference/items/traits.html#object-safety\">\
|
||||
|
|
@ -996,7 +992,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
foreign.sort_by_cached_key(|i| ImplString::new(i, cx));
|
||||
|
||||
if !foreign.is_empty() {
|
||||
write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "");
|
||||
write_section_heading(w, "Implementations on Foreign Types", "foreign-impls", None, "");
|
||||
|
||||
for implementor in foreign {
|
||||
let provided_methods = implementor.inner_impl().provided_trait_methods(tcx);
|
||||
|
|
@ -1021,10 +1017,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
}
|
||||
}
|
||||
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"implementors",
|
||||
"Implementors",
|
||||
"implementors",
|
||||
None,
|
||||
"<div id=\"implementors-list\">",
|
||||
);
|
||||
for implementor in concrete {
|
||||
|
|
@ -1033,10 +1030,11 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
w.write_str("</div>");
|
||||
|
||||
if t.is_auto(tcx) {
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"synthetic-implementors",
|
||||
"Auto implementors",
|
||||
"synthetic-implementors",
|
||||
None,
|
||||
"<div id=\"synthetic-implementors-list\">",
|
||||
);
|
||||
for implementor in synthetic {
|
||||
|
|
@ -1054,18 +1052,20 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
} else {
|
||||
// even without any implementations to write in, we still want the heading and list, so the
|
||||
// implementors javascript file pulled in below has somewhere to write the impls into
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"implementors",
|
||||
"Implementors",
|
||||
"implementors",
|
||||
None,
|
||||
"<div id=\"implementors-list\"></div>",
|
||||
);
|
||||
|
||||
if t.is_auto(tcx) {
|
||||
write_small_section_header(
|
||||
write_section_heading(
|
||||
w,
|
||||
"synthetic-implementors",
|
||||
"Auto implementors",
|
||||
"synthetic-implementors",
|
||||
None,
|
||||
"<div id=\"synthetic-implementors-list\"></div>",
|
||||
);
|
||||
}
|
||||
|
|
@ -1248,11 +1248,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
|
|||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
|
||||
|
||||
if let Some(inner_type) = &t.inner_type {
|
||||
write!(
|
||||
w,
|
||||
"<h2 id=\"aliased-type\" class=\"section-header\">\
|
||||
Aliased Type<a href=\"#aliased-type\" class=\"anchor\">§</a></h2>"
|
||||
);
|
||||
write_section_heading(w, "Aliased Type", "aliased-type", None, "");
|
||||
|
||||
match inner_type {
|
||||
clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => {
|
||||
|
|
@ -1673,16 +1669,14 @@ fn item_variants(
|
|||
enum_def_id: DefId,
|
||||
) {
|
||||
let tcx = cx.tcx();
|
||||
write!(
|
||||
write_section_heading(
|
||||
w,
|
||||
"<h2 id=\"variants\" class=\"variants section-header\">\
|
||||
Variants{}<a href=\"#variants\" class=\"anchor\">§</a>\
|
||||
</h2>\
|
||||
{}\
|
||||
<div class=\"variants\">",
|
||||
document_non_exhaustive_header(it),
|
||||
document_non_exhaustive(it)
|
||||
&format!("Variants{}", document_non_exhaustive_header(it)),
|
||||
"variants",
|
||||
Some("variants"),
|
||||
format!("{}<div class=\"variants\">", document_non_exhaustive(it)),
|
||||
);
|
||||
|
||||
let should_show_enum_discriminant = should_show_enum_discriminant(cx, enum_def_id, variants);
|
||||
for (index, variant) in variants.iter_enumerated() {
|
||||
if variant.is_stripped() {
|
||||
|
|
@ -1930,16 +1924,12 @@ fn item_fields(
|
|||
.peekable();
|
||||
if let None | Some(CtorKind::Fn) = ctor_kind {
|
||||
if fields.peek().is_some() {
|
||||
write!(
|
||||
w,
|
||||
"<h2 id=\"fields\" class=\"fields section-header\">\
|
||||
{}{}<a href=\"#fields\" class=\"anchor\">§</a>\
|
||||
</h2>\
|
||||
{}",
|
||||
let title = format!(
|
||||
"{}{}",
|
||||
if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
|
||||
document_non_exhaustive_header(it),
|
||||
document_non_exhaustive(it)
|
||||
);
|
||||
write_section_heading(w, &title, "fields", Some("fields"), document_non_exhaustive(it));
|
||||
for (index, (field, ty)) in fields.enumerate() {
|
||||
let field_name =
|
||||
field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
|
||||
|
|
|
|||
|
|
@ -849,11 +849,30 @@ nav.sub {
|
|||
h2.section-header > .anchor {
|
||||
padding-right: 6px;
|
||||
}
|
||||
a.doc-anchor {
|
||||
color: var(--main-color);
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: -17px;
|
||||
/* We add this padding so that when the cursor moves from the heading's text to the anchor,
|
||||
the anchor doesn't disappear. */
|
||||
padding-right: 5px;
|
||||
/* And this padding is used to make the anchor larger and easier to click on. */
|
||||
padding-left: 3px;
|
||||
}
|
||||
*:hover > .doc-anchor {
|
||||
display: block;
|
||||
}
|
||||
/* If the first element of the top doc block is a heading, we don't want to ever display its anchor
|
||||
because of the `[-]` element which would overlap with it. */
|
||||
.top-doc > .docblock > *:first-child > .doc-anchor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.main-heading a:hover,
|
||||
.example-wrap .rust a:hover,
|
||||
.all-items a:hover,
|
||||
.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,
|
||||
.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),
|
||||
.docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,
|
||||
.item-info a {
|
||||
text-decoration: underline;
|
||||
|
|
|
|||
|
|
@ -624,7 +624,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
// Checks if item_name belongs to `impl SomeItem`
|
||||
let mut assoc_items: Vec<_> = tcx
|
||||
.inherent_impls(did)
|
||||
.iter()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|&imp| {
|
||||
filter_assoc_items_by_name_and_namespace(
|
||||
tcx,
|
||||
|
|
|
|||
|
|
@ -56,13 +56,10 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
|
|||
| clean::TraitItem(..)
|
||||
| clean::FunctionItem(..)
|
||||
| clean::VariantItem(..)
|
||||
| clean::MethodItem(..)
|
||||
| clean::ForeignFunctionItem(..)
|
||||
| clean::ForeignStaticItem(..)
|
||||
| clean::ConstantItem(..)
|
||||
| clean::UnionItem(..)
|
||||
| clean::AssocConstItem(..)
|
||||
| clean::AssocTypeItem(..)
|
||||
| clean::TraitAliasItem(..)
|
||||
| clean::MacroItem(..)
|
||||
| clean::ForeignTypeItem => {
|
||||
|
|
@ -80,6 +77,16 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
|
||||
let item_id = i.item_id;
|
||||
if item_id.is_local()
|
||||
&& !self.effective_visibilities.is_reachable(self.tcx, item_id.expect_def_id())
|
||||
{
|
||||
debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
clean::StructFieldItem(..) => {
|
||||
if i.visibility(self.tcx) != Some(Visibility::Public) {
|
||||
return Some(strip_item(i));
|
||||
|
|
@ -192,16 +199,16 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
|
|||
&& imp.items.iter().all(|i| {
|
||||
let item_id = i.item_id;
|
||||
item_id.is_local()
|
||||
&& !is_item_reachable(
|
||||
self.tcx,
|
||||
self.is_json_output,
|
||||
&self.cache.effective_visibilities,
|
||||
item_id,
|
||||
)
|
||||
&& !self
|
||||
.cache
|
||||
.effective_visibilities
|
||||
.is_reachable(self.tcx, item_id.expect_def_id())
|
||||
})
|
||||
{
|
||||
debug!("ImplStripper: no public item; removing {imp:?}");
|
||||
return None;
|
||||
} else if imp.items.is_empty() && i.doc_value().is_empty() {
|
||||
debug!("ImplStripper: no item and no doc; removing {imp:?}");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
|
@ -212,13 +219,13 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
|
|||
&& !imp.for_.is_assoc_ty()
|
||||
&& !self.should_keep_impl(&i, did)
|
||||
{
|
||||
debug!("ImplStripper: impl item for stripped type; removing");
|
||||
debug!("ImplStripper: impl item for stripped type; removing {imp:?}");
|
||||
return None;
|
||||
}
|
||||
if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id())
|
||||
&& !self.should_keep_impl(&i, did)
|
||||
{
|
||||
debug!("ImplStripper: impl item for stripped trait; removing");
|
||||
debug!("ImplStripper: impl item for stripped trait; removing {imp:?}");
|
||||
return None;
|
||||
}
|
||||
if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
|
||||
|
|
@ -226,7 +233,7 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
|
|||
if let Some(did) = typaram.def_id(self.cache)
|
||||
&& !self.should_keep_impl(&i, did)
|
||||
{
|
||||
debug!("ImplStripper: stripped item in trait's generics; removing impl");
|
||||
debug!("ImplStripper: stripped item in trait's generics; removing {imp:?}");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 84976cd699f4aea56cb3a90ce3eedeed9e20d5a5
|
||||
Subproject commit 1ae631085f01c1a72d05df1ec81f3759a8360042
|
||||
|
|
@ -45,50 +45,72 @@ declare_lint_pass!(AsyncYieldsAsync => [ASYNC_YIELDS_ASYNC]);
|
|||
|
||||
impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
// For functions, with explicitly defined types, don't warn.
|
||||
// XXXkhuey maybe we should?
|
||||
if let ExprKind::Closure(Closure {
|
||||
kind:
|
||||
ClosureKind::Coroutine(CoroutineKind::Desugared(
|
||||
CoroutineDesugaring::Async,
|
||||
CoroutineSource::Block | CoroutineSource::Closure,
|
||||
)),
|
||||
let ExprKind::Closure(Closure {
|
||||
kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, kind)),
|
||||
body: body_id,
|
||||
..
|
||||
}) = expr.kind
|
||||
{
|
||||
if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() {
|
||||
let typeck_results = cx.tcx.typeck_body(*body_id);
|
||||
let body = cx.tcx.hir().body(*body_id);
|
||||
let expr_ty = typeck_results.expr_ty(body.value);
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
if implements_trait(cx, expr_ty, future_trait_def_id, &[]) {
|
||||
let return_expr_span = match &body.value.kind {
|
||||
// XXXkhuey there has to be a better way.
|
||||
ExprKind::Block(block, _) => block.expr.map(|e| e.span),
|
||||
ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(return_expr_span) = return_expr_span {
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
ASYNC_YIELDS_ASYNC,
|
||||
body.value.hir_id,
|
||||
let body_expr = match kind {
|
||||
CoroutineSource::Fn => {
|
||||
// For functions, with explicitly defined types, don't warn.
|
||||
// XXXkhuey maybe we should?
|
||||
return;
|
||||
},
|
||||
CoroutineSource::Block => cx.tcx.hir().body(*body_id).value,
|
||||
CoroutineSource::Closure => {
|
||||
// Like `async fn`, async closures are wrapped in an additional block
|
||||
// to move all of the closure's arguments into the future.
|
||||
|
||||
let async_closure_body = cx.tcx.hir().body(*body_id).value;
|
||||
let ExprKind::Block(block, _) = async_closure_body.kind else {
|
||||
return;
|
||||
};
|
||||
let Some(block_expr) = block.expr else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::DropTemps(body_expr) = block_expr.kind else {
|
||||
return;
|
||||
};
|
||||
body_expr
|
||||
},
|
||||
};
|
||||
|
||||
let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let typeck_results = cx.tcx.typeck_body(*body_id);
|
||||
let expr_ty = typeck_results.expr_ty(body_expr);
|
||||
|
||||
if implements_trait(cx, expr_ty, future_trait_def_id, &[]) {
|
||||
let return_expr_span = match &body_expr.kind {
|
||||
// XXXkhuey there has to be a better way.
|
||||
ExprKind::Block(block, _) => block.expr.map(|e| e.span),
|
||||
ExprKind::Path(QPath::Resolved(_, path)) => Some(path.span),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(return_expr_span) = return_expr_span {
|
||||
span_lint_hir_and_then(
|
||||
cx,
|
||||
ASYNC_YIELDS_ASYNC,
|
||||
body_expr.hir_id,
|
||||
return_expr_span,
|
||||
"an async construct yields a type which is itself awaitable",
|
||||
|db| {
|
||||
db.span_label(body_expr.span, "outer async construct");
|
||||
db.span_label(return_expr_span, "awaitable value not awaited");
|
||||
db.span_suggestion(
|
||||
return_expr_span,
|
||||
"an async construct yields a type which is itself awaitable",
|
||||
|db| {
|
||||
db.span_label(body.value.span, "outer async construct");
|
||||
db.span_label(return_expr_span, "awaitable value not awaited");
|
||||
db.span_suggestion(
|
||||
return_expr_span,
|
||||
"consider awaiting this value",
|
||||
format!("{}.await", snippet(cx, return_expr_span, "..")),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
},
|
||||
"consider awaiting this value",
|
||||
format!("{}.await", snippet(cx, return_expr_span, "..")),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
|
|||
/// (ZST fields having an arbitrary offset is completely inconsequential, and
|
||||
/// if there is only one field left after ignoring ZST fields then the offset
|
||||
/// of that field does not matter either.)
|
||||
fn is_union_with_two_non_zst_fields(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
||||
fn is_union_with_two_non_zst_fields<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
|
||||
if let ItemKind::Union(..) = &item.kind
|
||||
&& let ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -386,7 +386,8 @@ fn check_unsafe_derive_deserialize<'tcx>(
|
|||
&& cx
|
||||
.tcx
|
||||
.inherent_impls(def.did())
|
||||
.iter()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
|
||||
.any(|imp| has_unsafe(cx, imp))
|
||||
{
|
||||
|
|
@ -450,12 +451,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
|
|||
&& let Some(def_id) = trait_ref.trait_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
|
||||
&& let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
|
||||
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[])
|
||||
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])
|
||||
// If all of our fields implement `Eq`, we can implement `Eq` too
|
||||
&& adt
|
||||
.all_fields()
|
||||
.map(|f| f.ty(cx.tcx, args))
|
||||
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(), &[]))
|
||||
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[]))
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
|
|||
| PatKind::Binding(..)
|
||||
| PatKind::Wild
|
||||
| PatKind::Never
|
||||
| PatKind::Or(_) => false,
|
||||
| PatKind::Or(_)
|
||||
| PatKind::Err(_) => false,
|
||||
PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
|
||||
PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a),
|
||||
PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x),
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ enum ImplicitHasherType<'tcx> {
|
|||
|
||||
impl<'tcx> ImplicitHasherType<'tcx> {
|
||||
/// Checks that `ty` is a target type without a `BuildHasher`.
|
||||
fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Option<Self> {
|
||||
fn new(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Option<Self> {
|
||||
if let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind {
|
||||
let params: Vec<_> = path
|
||||
.segments
|
||||
|
|
|
|||
|
|
@ -53,9 +53,10 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
|
|||
// List of spans to lint. (lint_span, first_span)
|
||||
let mut lint_spans = Vec::new();
|
||||
|
||||
let Ok(impls) = cx.tcx.crate_inherent_impls(()) else { return };
|
||||
let inherent_impls = cx
|
||||
.tcx
|
||||
.with_stable_hashing_context(|hcx| cx.tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true));
|
||||
.with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true));
|
||||
|
||||
for (_, impl_ids) in inherent_impls.into_iter().filter(|(&id, impls)| {
|
||||
impls.len() > 1
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iter
|
|||
|
||||
fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> bool {
|
||||
if let Some(ty_did) = ty.ty_adt_def().map(ty::AdtDef::did) {
|
||||
cx.tcx.inherent_impls(ty_did).iter().any(|&did| {
|
||||
cx.tcx.inherent_impls(ty_did).into_iter().flatten().any(|&did| {
|
||||
cx.tcx
|
||||
.associated_items(did)
|
||||
.filter_by_name_unhygienic(method_name)
|
||||
|
|
|
|||
|
|
@ -441,7 +441,8 @@ fn check_for_is_empty(
|
|||
let is_empty = cx
|
||||
.tcx
|
||||
.inherent_impls(impl_ty)
|
||||
.iter()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty))
|
||||
.find(|item| item.kind == AssocKind::Fn);
|
||||
|
||||
|
|
@ -605,7 +606,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
|||
/// Checks the inherent impl's items for an `is_empty(self)` method.
|
||||
fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
|
||||
let is_empty = sym!(is_empty);
|
||||
cx.tcx.inherent_impls(id).iter().any(|imp| {
|
||||
cx.tcx.inherent_impls(id).into_iter().flatten().any(|imp| {
|
||||
cx.tcx
|
||||
.associated_items(*imp)
|
||||
.filter_by_name_unhygienic(is_empty)
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>(
|
|||
.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder())
|
||||
&& let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output
|
||||
&& let param_env = cx.tcx.param_env(fn_id)
|
||||
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, fn_id, &[])
|
||||
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[])
|
||||
&& let Some(into_iter_ty) =
|
||||
make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty])
|
||||
&& let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, P
|
|||
use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{ErrorGuaranteed, Symbol};
|
||||
|
||||
use super::MATCH_SAME_ARMS;
|
||||
|
||||
|
|
@ -167,6 +167,8 @@ enum NormalizedPat<'a> {
|
|||
/// contains everything afterwards. Note that either side, or both sides, may contain zero
|
||||
/// patterns.
|
||||
Slice(&'a [Self], Option<&'a [Self]>),
|
||||
/// A placeholder for a pattern that wasn't well formed in some way.
|
||||
Err(ErrorGuaranteed),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
|
@ -329,6 +331,7 @@ impl<'a> NormalizedPat<'a> {
|
|||
arena.alloc_from_iter(front.iter().map(|pat| Self::from_pat(cx, arena, pat))),
|
||||
wild_pat.map(|_| &*arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat)))),
|
||||
),
|
||||
PatKind::Err(guar) => Self::Err(guar),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ pub(super) fn check<'tcx>(
|
|||
let has_suggested_method = receiver_ty.ty_adt_def().is_some_and(|adt_def| {
|
||||
cx.tcx
|
||||
.inherent_impls(adt_def.did())
|
||||
.iter()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg))
|
||||
.any(|assoc| {
|
||||
assoc.fn_has_self_parameter
|
||||
|
|
|
|||
|
|
@ -257,9 +257,9 @@ fn is_call_with_ref_arg<'tcx>(
|
|||
..
|
||||
} = kind
|
||||
&& args.len() == 1
|
||||
&& let mir::Operand::Move(mir::Place { local, .. }) = &args[0]
|
||||
&& let mir::Operand::Move(mir::Place { local, .. }) = &args[0].node
|
||||
&& let ty::FnDef(def_id, _) = *func.ty(mir, cx.tcx).kind()
|
||||
&& let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(mir, cx.tcx))
|
||||
&& let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].node.ty(mir, cx.tcx))
|
||||
&& !is_copy(cx, inner_ty)
|
||||
{
|
||||
Some((def_id, *local, inner_ty, destination.as_local()?))
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ use clippy_utils::sugg::Sugg;
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor};
|
||||
use rustc_hir::{intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Node};
|
||||
use rustc_hir::{
|
||||
intravisit as hir_visit, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, ExprKind, Node,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
|
|
@ -166,10 +168,22 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
|
|||
if coroutine_kind.is_async()
|
||||
&& let hir::ExprKind::Closure(closure) = body.kind
|
||||
{
|
||||
let async_closure_body = cx.tcx.hir().body(closure.body);
|
||||
// Like `async fn`, async closures are wrapped in an additional block
|
||||
// to move all of the closure's arguments into the future.
|
||||
|
||||
let async_closure_body = cx.tcx.hir().body(closure.body).value;
|
||||
let ExprKind::Block(block, _) = async_closure_body.kind else {
|
||||
return;
|
||||
};
|
||||
let Some(block_expr) = block.expr else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::DropTemps(body_expr) = block_expr.kind else {
|
||||
return;
|
||||
};
|
||||
|
||||
// `async x` is a syntax error, so it becomes `async { x }`
|
||||
if !matches!(async_closure_body.value.kind, hir::ExprKind::Block(_, _)) {
|
||||
if !matches!(body_expr.kind, hir::ExprKind::Block(_, _)) {
|
||||
hint = hint.blockify();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -314,9 +314,9 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO
|
|||
impl<'tcx> LateLintPass<'tcx> for Types {
|
||||
fn check_fn(
|
||||
&mut self,
|
||||
cx: &LateContext<'_>,
|
||||
cx: &LateContext<'tcx>,
|
||||
fn_kind: FnKind<'_>,
|
||||
decl: &FnDecl<'_>,
|
||||
decl: &FnDecl<'tcx>,
|
||||
_: &Body<'_>,
|
||||
_: Span,
|
||||
def_id: LocalDefId,
|
||||
|
|
@ -346,7 +346,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
|||
);
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||
|
||||
match item.kind {
|
||||
|
|
@ -363,7 +363,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) {
|
||||
match item.kind {
|
||||
ImplItemKind::Const(ty, _) => {
|
||||
let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx
|
||||
|
|
@ -391,7 +391,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
|
||||
fn check_field_def(&mut self, cx: &LateContext<'tcx>, field: &hir::FieldDef<'tcx>) {
|
||||
let is_exported = cx.effective_visibilities.is_exported(field.def_id);
|
||||
|
||||
self.check_ty(
|
||||
|
|
@ -404,7 +404,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
|||
);
|
||||
}
|
||||
|
||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) {
|
||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'tcx>) {
|
||||
let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
|
||||
|
||||
let context = CheckTyContext {
|
||||
|
|
@ -421,7 +421,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
|
||||
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) {
|
||||
if let Some(ty) = local.ty {
|
||||
self.check_ty(
|
||||
cx,
|
||||
|
|
@ -444,7 +444,7 @@ impl Types {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, context: CheckTyContext) {
|
||||
fn check_fn_decl<'tcx>(&mut self, cx: &LateContext<'tcx>, decl: &FnDecl<'tcx>, context: CheckTyContext) {
|
||||
// Ignore functions in trait implementations as they are usually forced by the trait definition.
|
||||
//
|
||||
// FIXME: ideally we would like to warn *if the complicated type can be simplified*, but it's hard
|
||||
|
|
@ -466,7 +466,7 @@ impl Types {
|
|||
/// lint found.
|
||||
///
|
||||
/// The parameter `is_local` distinguishes the context of the type.
|
||||
fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, mut context: CheckTyContext) {
|
||||
fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, mut context: CheckTyContext) {
|
||||
if hir_ty.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_span::symbol::sym;
|
|||
|
||||
use super::{utils, REDUNDANT_ALLOCATION};
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: &QPath<'tcx>, def_id: DefId) -> bool {
|
||||
let mut applicability = Applicability::MaybeIncorrect;
|
||||
let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() {
|
||||
"Box"
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ use rustc_span::symbol::sym;
|
|||
|
||||
use super::VEC_BOX;
|
||||
|
||||
pub(super) fn check(
|
||||
cx: &LateContext<'_>,
|
||||
pub(super) fn check<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
hir_ty: &hir::Ty<'_>,
|
||||
qpath: &QPath<'_>,
|
||||
qpath: &QPath<'tcx>,
|
||||
def_id: DefId,
|
||||
box_size_threshold: u64,
|
||||
) -> bool {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ fn get_ty_def_id(ty: Ty<'_>) -> Option<DefId> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_hir_ty_def_id(tcx: TyCtxt<'_>, hir_ty: rustc_hir::Ty<'_>) -> Option<DefId> {
|
||||
fn get_hir_ty_def_id<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: rustc_hir::Ty<'tcx>) -> Option<DefId> {
|
||||
let TyKind::Path(qpath) = hir_ty.kind else { return None };
|
||||
match qpath {
|
||||
QPath::Resolved(_, path) => path.res.opt_def_id(),
|
||||
|
|
@ -229,7 +229,7 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local
|
|||
}
|
||||
}
|
||||
|
||||
fn is_default_method_on_current_ty(tcx: TyCtxt<'_>, qpath: QPath<'_>, implemented_ty_id: DefId) -> bool {
|
||||
fn is_default_method_on_current_ty<'tcx>(tcx: TyCtxt<'tcx>, qpath: QPath<'tcx>, implemented_ty_id: DefId) -> bool {
|
||||
match qpath {
|
||||
QPath::Resolved(_, path) => match path.segments {
|
||||
[first, .., last] => last.ident.name == kw::Default && first.res.opt_def_id() == Some(implemented_ty_id),
|
||||
|
|
|
|||
|
|
@ -57,11 +57,11 @@ impl LateLintPass<'_> for UninhabitedReferences {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_fn(
|
||||
fn check_fn<'tcx>(
|
||||
&mut self,
|
||||
cx: &LateContext<'_>,
|
||||
cx: &LateContext<'tcx>,
|
||||
kind: FnKind<'_>,
|
||||
fndecl: &'_ FnDecl<'_>,
|
||||
fndecl: &'_ FnDecl<'tcx>,
|
||||
_: &'_ Body<'_>,
|
||||
span: Span,
|
||||
_: LocalDefId,
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
|
|||
// Therefore they are not some form of constructor `C`,
|
||||
// with which a pattern `C(p_0)` may be formed,
|
||||
// which we would want to join with other `C(p_j)`s.
|
||||
Ident(.., None) | Lit(_) | Wild | Never | Path(..) | Range(..) | Rest | MacCall(_)
|
||||
Ident(.., None) | Lit(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_)
|
||||
// Skip immutable refs, as grouping them saves few characters,
|
||||
// and almost always requires adding parens (increasing noisiness).
|
||||
// In the case of only two patterns, replacement adds net characters.
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) {
|
||||
if !hir_ty.span.from_expansion()
|
||||
&& self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
|
||||
&& let Some(&StackItem::Check {
|
||||
|
|
|
|||
|
|
@ -710,6 +710,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
self.slice(start, |pat| self.pat(pat));
|
||||
self.slice(end, |pat| self.pat(pat));
|
||||
},
|
||||
PatKind::Err(_) => kind!("Err"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ declare_clippy_lint! {
|
|||
declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]);
|
||||
|
||||
impl LateLintPass<'_> for ZeroSizedMapValues {
|
||||
fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
|
||||
fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) {
|
||||
if !hir_ty.span.from_expansion()
|
||||
&& !in_trait_impl(cx, hir_ty.hir_id)
|
||||
&& let ty = ty_from_hir_ty(cx, hir_ty)
|
||||
|
|
@ -82,7 +82,7 @@ fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool {
|
|||
false
|
||||
}
|
||||
|
||||
fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> Ty<'tcx> {
|
||||
fn ty_from_hir_ty<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||
cx.maybe_typeck_results()
|
||||
.and_then(|results| {
|
||||
if results.hir_owner == hir_ty.hir_id.owner {
|
||||
|
|
|
|||
|
|
@ -1007,7 +1007,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
}
|
||||
e.hash(&mut self.s);
|
||||
},
|
||||
PatKind::Never | PatKind::Wild => {},
|
||||
PatKind::Never | PatKind::Wild | PatKind::Err(_) => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -534,10 +534,11 @@ fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<It
|
|||
"u128" => SimplifiedType::Uint(UintTy::U128),
|
||||
"f32" => SimplifiedType::Float(FloatTy::F32),
|
||||
"f64" => SimplifiedType::Float(FloatTy::F64),
|
||||
_ => return [].iter().copied(),
|
||||
#[allow(trivial_casts)]
|
||||
_ => return Result::<_, rustc_errors::ErrorGuaranteed>::Ok(&[] as &[_]).into_iter().flatten().copied(),
|
||||
};
|
||||
|
||||
tcx.incoherent_impls(ty).iter().copied()
|
||||
tcx.incoherent_impls(ty).into_iter().flatten().copied()
|
||||
}
|
||||
|
||||
fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
|
||||
|
|
@ -663,7 +664,8 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
|
|||
// `impl S { ... }`
|
||||
let inherent_impl_children = tcx
|
||||
.inherent_impls(def_id)
|
||||
.iter()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
|
||||
|
||||
let direct_children = item_children_by_name(tcx, def_id, segment);
|
||||
|
|
@ -1733,6 +1735,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
|
|||
},
|
||||
}
|
||||
},
|
||||
PatKind::Err(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b,
|
|||
let mut mutable_borrowers = vec![];
|
||||
|
||||
for op in args {
|
||||
match op {
|
||||
match &op.node {
|
||||
mir::Operand::Copy(p) | mir::Operand::Move(p) => {
|
||||
if let ty::Ref(_, _, Mutability::Mut) = self.body.local_decls[p.local].ty.kind() {
|
||||
mutable_borrowers.push(p.local);
|
||||
|
|
|
|||
|
|
@ -345,7 +345,7 @@ fn check_terminator<'tcx>(
|
|||
check_operand(tcx, func, span, body)?;
|
||||
|
||||
for arg in args {
|
||||
check_operand(tcx, arg, span, body)?;
|
||||
check_operand(tcx, &arg.node, span, body)?;
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -214,36 +214,21 @@ pub fn implements_trait<'tcx>(
|
|||
trait_id: DefId,
|
||||
args: &[GenericArg<'tcx>],
|
||||
) -> bool {
|
||||
let callee_id = cx
|
||||
.enclosing_body
|
||||
.map(|body| cx.tcx.hir().body_owner(body).owner.to_def_id());
|
||||
implements_trait_with_env_from_iter(
|
||||
cx.tcx,
|
||||
cx.param_env,
|
||||
ty,
|
||||
trait_id,
|
||||
callee_id,
|
||||
args.iter().map(|&x| Some(x)),
|
||||
)
|
||||
implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, None, args.iter().map(|&x| Some(x)))
|
||||
}
|
||||
|
||||
/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
|
||||
///
|
||||
/// The `callee_id` argument is used to determine whether this is a function call in a `const fn` environment, used for checking const traits.
|
||||
pub fn implements_trait_with_env<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
trait_id: DefId,
|
||||
callee_id: DefId,
|
||||
callee_id: Option<DefId>,
|
||||
args: &[GenericArg<'tcx>],
|
||||
) -> bool {
|
||||
implements_trait_with_env_from_iter(
|
||||
tcx,
|
||||
param_env,
|
||||
ty,
|
||||
trait_id,
|
||||
Some(callee_id),
|
||||
args.iter().map(|&x| Some(x)),
|
||||
)
|
||||
implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x)))
|
||||
}
|
||||
|
||||
/// Same as `implements_trait_from_env` but takes the arguments as an iterator.
|
||||
|
|
@ -258,6 +243,13 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
|
|||
// Clippy shouldn't have infer types
|
||||
assert!(!ty.has_infer());
|
||||
|
||||
// If a `callee_id` is passed, then we assert that it is a body owner
|
||||
// through calling `body_owner_kind`, which would panic if the callee
|
||||
// does not have a body.
|
||||
if let Some(callee_id) = callee_id {
|
||||
let _ = tcx.hir().body_owner_kind(callee_id);
|
||||
}
|
||||
|
||||
let ty = tcx.erase_regions(ty);
|
||||
if ty.has_escaping_bound_vars() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,11 @@ if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_
|
|||
&& expr2 = &cx.tcx.hir().body(body_id1).value
|
||||
&& let ExprKind::Block(block, None) = expr2.kind
|
||||
&& block.stmts.is_empty()
|
||||
&& block.expr.is_none()
|
||||
&& let Some(trailing_expr) = block.expr
|
||||
&& let ExprKind::DropTemps(expr3) = trailing_expr.kind
|
||||
&& let ExprKind::Block(block1, None) = expr3.kind
|
||||
&& block1.stmts.is_empty()
|
||||
&& block1.expr.is_none()
|
||||
{
|
||||
// report your lint here
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,15 @@ fn main() {
|
|||
eprintln!("warning: `tidy` is not installed; diffs will not be generated");
|
||||
}
|
||||
|
||||
if !config.profiler_support && config.mode == Mode::CoverageRun {
|
||||
let actioned = if config.bless { "blessed" } else { "checked" };
|
||||
eprintln!(
|
||||
r#"
|
||||
WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned}
|
||||
help: try setting `profiler = true` in the `[build]` section of `config.toml`"#
|
||||
);
|
||||
}
|
||||
|
||||
log_config(&config);
|
||||
run_tests(config);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ log = "0.4"
|
|||
rand = "0.8"
|
||||
smallvec = "1.7"
|
||||
aes = { version = "0.8.3", features = ["hazmat"] }
|
||||
measureme = "10.0.0"
|
||||
measureme = "11"
|
||||
ctrlc = "3.2.5"
|
||||
|
||||
# Copied from `compiler/rustc/Cargo.toml`.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#![feature(variant_count)]
|
||||
#![feature(yeet_expr)]
|
||||
#![feature(nonzero_ops)]
|
||||
#![feature(round_ties_even)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(lint_reasons)]
|
||||
#![feature(int_roundings)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//! The man pages for mmap/munmap suggest that it is possible to partly unmap a previously-mapped
|
||||
//! region of addres space, but to LLVM that would be partial deallocation, which LLVM does not
|
||||
//! region of address space, but to LLVM that would be partial deallocation, which LLVM does not
|
||||
//! support. So even though the man pages say this sort of use is possible, we must report UB.
|
||||
//@ignore-target-windows: No libc on Windows
|
||||
//@normalize-stderr-test: "size [0-9]+ and alignment" -> "size SIZE and alignment"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
trait Empty {}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct FunnyPointer(#[allow(dead_code)] dyn Empty);
|
||||
pub struct FunnyPointer(dyn Empty);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Meta {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//@compile-flags: -Cdebug-assertions=no
|
||||
|
||||
#[repr(transparent)]
|
||||
struct HasDrop(#[allow(dead_code)] u8);
|
||||
struct HasDrop(u8);
|
||||
|
||||
impl Drop for HasDrop {
|
||||
fn drop(&mut self) {}
|
||||
|
|
|
|||
|
|
@ -76,8 +76,7 @@ async fn uninhabited_variant() {
|
|||
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
|
||||
use std::task::{Context, Poll, Waker};
|
||||
|
||||
let waker = Waker::noop();
|
||||
let mut context = Context::from_waker(&waker);
|
||||
let mut context = Context::from_waker(Waker::noop());
|
||||
|
||||
let mut pinned = Box::pin(fut);
|
||||
loop {
|
||||
|
|
|
|||
|
|
@ -93,8 +93,7 @@ fn dispatch_on_pin_mut() {
|
|||
let mut fut = async_main();
|
||||
|
||||
// Poll loop, just to test the future...
|
||||
let waker = Waker::noop();
|
||||
let ctx = &mut Context::from_waker(&waker);
|
||||
let ctx = &mut Context::from_waker(Waker::noop());
|
||||
|
||||
loop {
|
||||
match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(round_ties_even)]
|
||||
#![feature(float_gamma)]
|
||||
#![allow(arithmetic_overflow)]
|
||||
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@ impl Future for DoStuff {
|
|||
}
|
||||
|
||||
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
|
||||
let waker = Waker::noop();
|
||||
let mut context = Context::from_waker(&waker);
|
||||
let mut context = Context::from_waker(Waker::noop());
|
||||
|
||||
let mut pinned = pin!(fut);
|
||||
loop {
|
||||
|
|
@ -90,8 +89,7 @@ fn run_fut<T>(fut: impl Future<Output = T>) -> T {
|
|||
}
|
||||
|
||||
fn self_referential_box() {
|
||||
let waker = Waker::noop();
|
||||
let cx = &mut Context::from_waker(&waker);
|
||||
let cx = &mut Context::from_waker(Waker::noop());
|
||||
|
||||
async fn my_fut() -> i32 {
|
||||
let val = 10;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ use std::task::{Context, Poll, Waker};
|
|||
|
||||
pub fn fuzzing_block_on<O, F: Future<Output = O>>(fut: F) -> O {
|
||||
let mut fut = std::pin::pin!(fut);
|
||||
let waker = Waker::noop();
|
||||
let mut context = Context::from_waker(&waker);
|
||||
let mut context = Context::from_waker(Waker::noop());
|
||||
loop {
|
||||
match fut.as_mut().poll(&mut context) {
|
||||
Poll::Ready(v) => return v,
|
||||
|
|
|
|||
|
|
@ -56,8 +56,7 @@ fn data_moved() {
|
|||
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
|
||||
use std::task::{Context, Poll, Waker};
|
||||
|
||||
let waker = Waker::noop();
|
||||
let mut context = Context::from_waker(&waker);
|
||||
let mut context = Context::from_waker(Waker::noop());
|
||||
|
||||
let mut pinned = Box::pin(fut);
|
||||
loop {
|
||||
|
|
|
|||
|
|
@ -98,11 +98,12 @@ pub fn files_for_miropt_test(
|
|||
from_file = format!("{}.{}.mir", test_name, first_pass);
|
||||
to_file = Some(second_file);
|
||||
} else {
|
||||
let ext_re = regex::Regex::new(r#"(\.(mir|dot|html))$"#).unwrap();
|
||||
let cap = ext_re
|
||||
.captures_iter(test_name)
|
||||
.next()
|
||||
.expect("test_name has an invalid extension");
|
||||
// Allow-list for file extensions that can be produced by MIR dumps.
|
||||
// Other extensions can be added here, as needed by new dump flags.
|
||||
let ext_re = regex::Regex::new(r#"(\.(mir|dot))$"#).unwrap();
|
||||
let cap = ext_re.captures_iter(test_name).next().unwrap_or_else(|| {
|
||||
panic!("in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}")
|
||||
});
|
||||
let extension = cap.get(1).unwrap().as_str();
|
||||
|
||||
expected_file =
|
||||
|
|
|
|||
|
|
@ -513,7 +513,8 @@ dependencies = [
|
|||
"mbe",
|
||||
"once_cell",
|
||||
"profile",
|
||||
"rustc-dependencies",
|
||||
"ra-ap-rustc_abi",
|
||||
"ra-ap-rustc_parse_format",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
"span",
|
||||
|
|
@ -579,7 +580,8 @@ dependencies = [
|
|||
"oorandom",
|
||||
"profile",
|
||||
"project-model",
|
||||
"rustc-dependencies",
|
||||
"ra-ap-rustc_abi",
|
||||
"ra-ap-rustc_index",
|
||||
"rustc-hash",
|
||||
"scoped-tls",
|
||||
"smallvec",
|
||||
|
|
@ -1196,7 +1198,7 @@ dependencies = [
|
|||
"drop_bomb",
|
||||
"expect-test",
|
||||
"limit",
|
||||
"rustc-dependencies",
|
||||
"ra-ap-rustc_lexer",
|
||||
"sourcegen",
|
||||
"stdx",
|
||||
]
|
||||
|
|
@ -1540,7 +1542,6 @@ dependencies = [
|
|||
"profile",
|
||||
"project-model",
|
||||
"rayon",
|
||||
"rustc-dependencies",
|
||||
"rustc-hash",
|
||||
"scip",
|
||||
"serde",
|
||||
|
|
@ -1567,9 +1568,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rust-analyzer-salsa"
|
||||
version = "0.17.0-pre.4"
|
||||
version = "0.17.0-pre.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16c42b8737c320578b441a82daf7cdf8d897468de64e8a774fa54b53a50b6cc0"
|
||||
checksum = "ca9d387a9801f4fb9b366789ad1bfc08448cafc49cf148d907cfcd88ab665d7f"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"lock_api",
|
||||
|
|
@ -1579,13 +1580,14 @@ dependencies = [
|
|||
"rust-analyzer-salsa-macros",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
"triomphe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-analyzer-salsa-macros"
|
||||
version = "0.17.0-pre.4"
|
||||
version = "0.17.0-pre.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db72b0883f3592ade2be15a10583c75e0b269ec26e1190800fda2e2ce5ae6634"
|
||||
checksum = "a2035f385d7fae31e9b086f40b272ee1d79c484472f31c9a10348a406e841eaf"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
|
@ -1599,16 +1601,6 @@ version = "0.1.23"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-dependencies"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_abi",
|
||||
"ra-ap-rustc_index",
|
||||
"ra-ap-rustc_lexer",
|
||||
"ra-ap-rustc_parse_format",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
|
|
@ -1751,6 +1743,12 @@ dependencies = [
|
|||
"vfs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
|
|
@ -1808,9 +1806,9 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"profile",
|
||||
"quote",
|
||||
"ra-ap-rustc_lexer",
|
||||
"rayon",
|
||||
"rowan",
|
||||
"rustc-dependencies",
|
||||
"rustc-hash",
|
||||
"smol_str",
|
||||
"sourcegen",
|
||||
|
|
@ -2028,9 +2026,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "triomphe"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0c5a71827ac326072b6405552093e2ad2accd25a32fd78d4edc82d98c7f2409"
|
||||
checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tt"
|
||||
|
|
|
|||
|
|
@ -78,7 +78,11 @@ toolchain = { path = "./crates/toolchain", version = "0.0.0" }
|
|||
tt = { path = "./crates/tt", version = "0.0.0" }
|
||||
vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
|
||||
vfs = { path = "./crates/vfs", version = "0.0.0" }
|
||||
rustc-dependencies = { path = "./crates/rustc-dependencies", version = "0.0.0" }
|
||||
|
||||
ra-ap-rustc_lexer = { version = "0.21.0", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.21.0", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.21.0", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.21.0", default-features = false }
|
||||
|
||||
# local crates that aren't published to crates.io. These should not have versions.
|
||||
sourcegen = { path = "./crates/sourcegen" }
|
||||
|
|
@ -108,7 +112,7 @@ itertools = "0.12.0"
|
|||
libc = "0.2.150"
|
||||
nohash-hasher = "0.2.0"
|
||||
rayon = "1.8.0"
|
||||
rust-analyzer-salsa = "0.17.0-pre.4"
|
||||
rust-analyzer-salsa = "0.17.0-pre.5"
|
||||
rustc-hash = "1.1.0"
|
||||
semver = "1.0.14"
|
||||
serde = { version = "1.0.192", features = ["derive"] }
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ mod change;
|
|||
|
||||
use std::panic;
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
use syntax::{ast, Parse, SourceFile};
|
||||
use triomphe::Arc;
|
||||
|
||||
|
|
@ -44,12 +43,13 @@ pub trait Upcast<T: ?Sized> {
|
|||
}
|
||||
|
||||
pub const DEFAULT_PARSE_LRU_CAP: usize = 128;
|
||||
pub const DEFAULT_BORROWCK_LRU_CAP: usize = 256;
|
||||
|
||||
pub trait FileLoader {
|
||||
/// Text of the file.
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str>;
|
||||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>;
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>>;
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>;
|
||||
}
|
||||
|
||||
/// Database which stores all significant input facts: source code and project
|
||||
|
|
@ -84,19 +84,21 @@ pub trait SourceDatabaseExt: SourceDatabase {
|
|||
#[salsa::input]
|
||||
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
|
||||
|
||||
fn source_root_crates(&self, id: SourceRootId) -> Arc<FxHashSet<CrateId>>;
|
||||
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
|
||||
}
|
||||
|
||||
fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<FxHashSet<CrateId>> {
|
||||
fn source_root_crates(db: &dyn SourceDatabaseExt, id: SourceRootId) -> Arc<[CrateId]> {
|
||||
let graph = db.crate_graph();
|
||||
let res = graph
|
||||
let mut crates = graph
|
||||
.iter()
|
||||
.filter(|&krate| {
|
||||
let root_file = graph[krate].root_file_id;
|
||||
db.file_source_root(root_file) == id
|
||||
})
|
||||
.collect();
|
||||
Arc::new(res)
|
||||
.collect::<Vec<_>>();
|
||||
crates.sort();
|
||||
crates.dedup();
|
||||
crates.into_iter().collect()
|
||||
}
|
||||
|
||||
/// Silly workaround for cyclic deps between the traits
|
||||
|
|
@ -113,7 +115,7 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
|
|||
source_root.resolve_path(path)
|
||||
}
|
||||
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> {
|
||||
let _p = profile::span("relevant_crates");
|
||||
let source_root = self.0.file_source_root(file_id);
|
||||
self.0.source_root_crates(source_root)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ smallvec.workspace = true
|
|||
hashbrown.workspace = true
|
||||
triomphe.workspace = true
|
||||
|
||||
rustc-dependencies.workspace = true
|
||||
ra-ap-rustc_parse_format.workspace = true
|
||||
ra-ap-rustc_abi.workspace = true
|
||||
|
||||
# local deps
|
||||
stdx.workspace = true
|
||||
|
|
@ -53,7 +54,7 @@ test-utils.workspace = true
|
|||
test-fixture.workspace = true
|
||||
|
||||
[features]
|
||||
in-rust-tree = ["rustc-dependencies/in-rust-tree"]
|
||||
in-rust-tree = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -207,6 +207,13 @@ impl Attrs {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn has_doc_notable_trait(&self) -> bool {
|
||||
self.by_key("doc").tt_values().any(|tt| {
|
||||
tt.delimiter.kind == DelimiterKind::Parenthesis &&
|
||||
matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "notable_trait")
|
||||
})
|
||||
}
|
||||
|
||||
pub fn doc_exprs(&self) -> impl Iterator<Item = DocExpr> + '_ {
|
||||
self.by_key("doc").tt_values().map(DocExpr::parse)
|
||||
}
|
||||
|
|
@ -355,7 +362,7 @@ fn parse_comma_sep<S>(subtree: &tt::Subtree<S>) -> Vec<SmolStr> {
|
|||
}
|
||||
|
||||
impl AttrsWithOwner {
|
||||
pub(crate) fn attrs_with_owner(db: &dyn DefDatabase, owner: AttrDefId) -> Self {
|
||||
pub fn attrs_with_owner(db: &dyn DefDatabase, owner: AttrDefId) -> Self {
|
||||
Self { attrs: db.attrs(owner), owner }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -965,11 +965,10 @@ impl ExprCollector<'_> {
|
|||
|
||||
let res = match self.def_map.modules[module]
|
||||
.scope
|
||||
.macro_invocations
|
||||
.get(&InFile::new(outer_file, self.ast_id_map.ast_id_for_ptr(syntax_ptr)))
|
||||
.macro_invoc(InFile::new(outer_file, self.ast_id_map.ast_id_for_ptr(syntax_ptr)))
|
||||
{
|
||||
// fast path, macro call is in a block module
|
||||
Some(&call) => Ok(self.expander.enter_expand_id(self.db, call)),
|
||||
Some(call) => Ok(self.expander.enter_expand_id(self.db, call)),
|
||||
None => self.expander.enter_expand(self.db, mcall, |path| {
|
||||
self.def_map
|
||||
.resolve_path(
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ impl ChildBySource for ItemScope {
|
|||
self.impls().for_each(|imp| add_impl(db, res, file_id, imp));
|
||||
self.extern_crate_decls().for_each(|ext| add_extern_crate(db, res, file_id, ext));
|
||||
self.use_decls().for_each(|ext| add_use(db, res, file_id, ext));
|
||||
self.unnamed_consts().for_each(|konst| {
|
||||
self.unnamed_consts(db).for_each(|konst| {
|
||||
let loc = konst.lookup(db);
|
||||
if loc.id.file_id() == file_id {
|
||||
res[keys::CONST].insert(loc.source(db).value, konst);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use hir_expand::{
|
|||
};
|
||||
use intern::Interned;
|
||||
use la_arena::{Arena, ArenaMap};
|
||||
use rustc_dependencies::abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
|
||||
use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
|
||||
use syntax::ast::{self, HasName, HasVisibility};
|
||||
use triomphe::Arc;
|
||||
|
||||
|
|
|
|||
|
|
@ -210,13 +210,10 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
|||
#[salsa::invoke(AttrsWithOwner::attrs_query)]
|
||||
fn attrs(&self, def: AttrDefId) -> Attrs;
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(lang_item::lang_attr_query)]
|
||||
fn lang_attr(&self, def: AttrDefId) -> Option<LangItem>;
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(AttrsWithOwner::attrs_with_owner)]
|
||||
fn attrs_with_owner(&self, def: AttrDefId) -> AttrsWithOwner;
|
||||
|
||||
// endregion:attrs
|
||||
|
||||
#[salsa::invoke(LangItems::lang_item_query)]
|
||||
|
|
@ -240,7 +237,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
|||
// endregion:visibilities
|
||||
|
||||
#[salsa::invoke(LangItems::crate_lang_items_query)]
|
||||
fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>;
|
||||
fn crate_lang_items(&self, krate: CrateId) -> Option<Arc<LangItems>>;
|
||||
|
||||
fn crate_supports_no_std(&self, crate_id: CrateId) -> bool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
item_scope::ItemInNs,
|
||||
nameres::DefMap,
|
||||
path::{ModPath, PathKind},
|
||||
visibility::Visibility,
|
||||
visibility::{Visibility, VisibilityExplicity},
|
||||
CrateRootModuleId, ModuleDefId, ModuleId,
|
||||
};
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ pub fn find_path(
|
|||
prefer_prelude: bool,
|
||||
) -> Option<ModPath> {
|
||||
let _p = profile::span("find_path");
|
||||
find_path_inner(db, item, from, None, prefer_no_std, prefer_prelude)
|
||||
find_path_inner(FindPathCtx { db, prefixed: None, prefer_no_std, prefer_prelude }, item, from)
|
||||
}
|
||||
|
||||
pub fn find_path_prefixed(
|
||||
|
|
@ -36,7 +36,11 @@ pub fn find_path_prefixed(
|
|||
prefer_prelude: bool,
|
||||
) -> Option<ModPath> {
|
||||
let _p = profile::span("find_path_prefixed");
|
||||
find_path_inner(db, item, from, Some(prefix_kind), prefer_no_std, prefer_prelude)
|
||||
find_path_inner(
|
||||
FindPathCtx { db, prefixed: Some(prefix_kind), prefer_no_std, prefer_prelude },
|
||||
item,
|
||||
from,
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
|
@ -83,64 +87,60 @@ impl PrefixKind {
|
|||
}
|
||||
}
|
||||
|
||||
/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId
|
||||
fn find_path_inner(
|
||||
db: &dyn DefDatabase,
|
||||
item: ItemInNs,
|
||||
from: ModuleId,
|
||||
#[derive(Copy, Clone)]
|
||||
struct FindPathCtx<'db> {
|
||||
db: &'db dyn DefDatabase,
|
||||
prefixed: Option<PrefixKind>,
|
||||
prefer_no_std: bool,
|
||||
prefer_prelude: bool,
|
||||
) -> Option<ModPath> {
|
||||
}
|
||||
|
||||
/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId
|
||||
fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
|
||||
// - if the item is a builtin, it's in scope
|
||||
if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item {
|
||||
return Some(ModPath::from_segments(PathKind::Plain, Some(builtin.as_name())));
|
||||
}
|
||||
|
||||
let def_map = from.def_map(db);
|
||||
let def_map = from.def_map(ctx.db);
|
||||
let crate_root = def_map.crate_root();
|
||||
// - if the item is a module, jump straight to module search
|
||||
if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item {
|
||||
let mut visited_modules = FxHashSet::default();
|
||||
return find_path_for_module(
|
||||
db,
|
||||
FindPathCtx {
|
||||
prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate),
|
||||
..ctx
|
||||
},
|
||||
&def_map,
|
||||
&mut visited_modules,
|
||||
crate_root,
|
||||
from,
|
||||
module_id,
|
||||
MAX_PATH_LEN,
|
||||
prefixed,
|
||||
prefer_no_std || db.crate_supports_no_std(crate_root.krate),
|
||||
prefer_prelude,
|
||||
)
|
||||
.map(|(item, _)| item);
|
||||
}
|
||||
|
||||
// - if the item is already in scope, return the name under which it is
|
||||
let scope_name = find_in_scope(db, &def_map, from, item);
|
||||
if prefixed.is_none() {
|
||||
let scope_name = find_in_scope(ctx.db, &def_map, from, item);
|
||||
if ctx.prefixed.is_none() {
|
||||
if let Some(scope_name) = scope_name {
|
||||
return Some(ModPath::from_segments(PathKind::Plain, Some(scope_name)));
|
||||
}
|
||||
}
|
||||
|
||||
// - if the item is in the prelude, return the name from there
|
||||
if let value @ Some(_) = find_in_prelude(db, &crate_root.def_map(db), &def_map, item, from) {
|
||||
if let value @ Some(_) =
|
||||
find_in_prelude(ctx.db, &crate_root.def_map(ctx.db), &def_map, item, from)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
|
||||
// - if the item is an enum variant, refer to it via the enum
|
||||
if let Some(mut path) = find_path_inner(
|
||||
db,
|
||||
ItemInNs::Types(variant.parent.into()),
|
||||
from,
|
||||
prefixed,
|
||||
prefer_no_std,
|
||||
prefer_prelude,
|
||||
) {
|
||||
let data = db.enum_data(variant.parent);
|
||||
if let Some(mut path) = find_path_inner(ctx, ItemInNs::Types(variant.parent.into()), from) {
|
||||
let data = ctx.db.enum_data(variant.parent);
|
||||
path.push_segment(data.variants[variant.local_id].name.clone());
|
||||
return Some(path);
|
||||
}
|
||||
|
|
@ -152,32 +152,29 @@ fn find_path_inner(
|
|||
let mut visited_modules = FxHashSet::default();
|
||||
|
||||
calculate_best_path(
|
||||
db,
|
||||
FindPathCtx {
|
||||
prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate),
|
||||
..ctx
|
||||
},
|
||||
&def_map,
|
||||
&mut visited_modules,
|
||||
crate_root,
|
||||
MAX_PATH_LEN,
|
||||
item,
|
||||
from,
|
||||
prefixed,
|
||||
prefer_no_std || db.crate_supports_no_std(crate_root.krate),
|
||||
prefer_prelude,
|
||||
scope_name,
|
||||
)
|
||||
.map(|(item, _)| item)
|
||||
}
|
||||
|
||||
fn find_path_for_module(
|
||||
db: &dyn DefDatabase,
|
||||
ctx: FindPathCtx<'_>,
|
||||
def_map: &DefMap,
|
||||
visited_modules: &mut FxHashSet<ModuleId>,
|
||||
crate_root: CrateRootModuleId,
|
||||
from: ModuleId,
|
||||
module_id: ModuleId,
|
||||
max_len: usize,
|
||||
prefixed: Option<PrefixKind>,
|
||||
prefer_no_std: bool,
|
||||
prefer_prelude: bool,
|
||||
) -> Option<(ModPath, Stability)> {
|
||||
if max_len == 0 {
|
||||
return None;
|
||||
|
|
@ -185,8 +182,8 @@ fn find_path_for_module(
|
|||
|
||||
// Base cases:
|
||||
// - if the item is already in scope, return the name under which it is
|
||||
let scope_name = find_in_scope(db, def_map, from, ItemInNs::Types(module_id.into()));
|
||||
if prefixed.is_none() {
|
||||
let scope_name = find_in_scope(ctx.db, def_map, from, ItemInNs::Types(module_id.into()));
|
||||
if ctx.prefixed.is_none() {
|
||||
if let Some(scope_name) = scope_name {
|
||||
return Some((ModPath::from_segments(PathKind::Plain, Some(scope_name)), Stable));
|
||||
}
|
||||
|
|
@ -198,20 +195,20 @@ fn find_path_for_module(
|
|||
}
|
||||
|
||||
// - if relative paths are fine, check if we are searching for a parent
|
||||
if prefixed.filter(PrefixKind::is_absolute).is_none() {
|
||||
if ctx.prefixed.filter(PrefixKind::is_absolute).is_none() {
|
||||
if let modpath @ Some(_) = find_self_super(def_map, module_id, from) {
|
||||
return modpath.zip(Some(Stable));
|
||||
}
|
||||
}
|
||||
|
||||
// - if the item is the crate root of a dependency crate, return the name from the extern prelude
|
||||
let root_def_map = crate_root.def_map(db);
|
||||
let root_def_map = crate_root.def_map(ctx.db);
|
||||
for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude() {
|
||||
if module_id == def_id {
|
||||
let name = scope_name.unwrap_or_else(|| name.clone());
|
||||
|
||||
let name_already_occupied_in_type_ns = def_map
|
||||
.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
|
||||
.with_ancestor_maps(ctx.db, from.local_id, &mut |def_map, local_id| {
|
||||
def_map[local_id]
|
||||
.scope
|
||||
.type_(&name)
|
||||
|
|
@ -229,21 +226,18 @@ fn find_path_for_module(
|
|||
}
|
||||
|
||||
if let value @ Some(_) =
|
||||
find_in_prelude(db, &root_def_map, &def_map, ItemInNs::Types(module_id.into()), from)
|
||||
find_in_prelude(ctx.db, &root_def_map, &def_map, ItemInNs::Types(module_id.into()), from)
|
||||
{
|
||||
return value.zip(Some(Stable));
|
||||
}
|
||||
calculate_best_path(
|
||||
db,
|
||||
ctx,
|
||||
def_map,
|
||||
visited_modules,
|
||||
crate_root,
|
||||
max_len,
|
||||
ItemInNs::Types(module_id.into()),
|
||||
from,
|
||||
prefixed,
|
||||
prefer_no_std,
|
||||
prefer_prelude,
|
||||
scope_name,
|
||||
)
|
||||
}
|
||||
|
|
@ -256,7 +250,7 @@ fn find_in_scope(
|
|||
item: ItemInNs,
|
||||
) -> Option<Name> {
|
||||
def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
|
||||
def_map[local_id].scope.name_of(item).map(|(name, _)| name.clone())
|
||||
def_map[local_id].scope.name_of(item).map(|(name, _, _)| name.clone())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -273,7 +267,7 @@ fn find_in_prelude(
|
|||
// Preludes in block DefMaps are ignored, only the crate DefMap is searched
|
||||
let prelude_def_map = prelude_module.def_map(db);
|
||||
let prelude_scope = &prelude_def_map[prelude_module.local_id].scope;
|
||||
let (name, vis) = prelude_scope.name_of(item)?;
|
||||
let (name, vis, _declared) = prelude_scope.name_of(item)?;
|
||||
if !vis.is_visible_from(db, from) {
|
||||
return None;
|
||||
}
|
||||
|
|
@ -315,16 +309,13 @@ fn find_self_super(def_map: &DefMap, item: ModuleId, from: ModuleId) -> Option<M
|
|||
}
|
||||
|
||||
fn calculate_best_path(
|
||||
db: &dyn DefDatabase,
|
||||
ctx: FindPathCtx<'_>,
|
||||
def_map: &DefMap,
|
||||
visited_modules: &mut FxHashSet<ModuleId>,
|
||||
crate_root: CrateRootModuleId,
|
||||
max_len: usize,
|
||||
item: ItemInNs,
|
||||
from: ModuleId,
|
||||
mut prefixed: Option<PrefixKind>,
|
||||
prefer_no_std: bool,
|
||||
prefer_prelude: bool,
|
||||
scope_name: Option<Name>,
|
||||
) -> Option<(ModPath, Stability)> {
|
||||
if max_len <= 1 {
|
||||
|
|
@ -341,32 +332,29 @@ fn calculate_best_path(
|
|||
};
|
||||
// Recursive case:
|
||||
// - otherwise, look for modules containing (reexporting) it and import it from one of those
|
||||
if item.krate(db) == Some(from.krate) {
|
||||
if item.krate(ctx.db) == Some(from.krate) {
|
||||
let mut best_path_len = max_len;
|
||||
// Item was defined in the same crate that wants to import it. It cannot be found in any
|
||||
// dependency in this case.
|
||||
for (module_id, name) in find_local_import_locations(db, item, from) {
|
||||
for (module_id, name) in find_local_import_locations(ctx.db, item, from) {
|
||||
if !visited_modules.insert(module_id) {
|
||||
cov_mark::hit!(recursive_imports);
|
||||
continue;
|
||||
}
|
||||
if let Some(mut path) = find_path_for_module(
|
||||
db,
|
||||
ctx,
|
||||
def_map,
|
||||
visited_modules,
|
||||
crate_root,
|
||||
from,
|
||||
module_id,
|
||||
best_path_len - 1,
|
||||
prefixed,
|
||||
prefer_no_std,
|
||||
prefer_prelude,
|
||||
) {
|
||||
path.0.push_segment(name);
|
||||
|
||||
let new_path = match best_path.take() {
|
||||
Some(best_path) => {
|
||||
select_best_path(best_path, path, prefer_no_std, prefer_prelude)
|
||||
select_best_path(best_path, path, ctx.prefer_no_std, ctx.prefer_prelude)
|
||||
}
|
||||
None => path,
|
||||
};
|
||||
|
|
@ -379,8 +367,8 @@ fn calculate_best_path(
|
|||
// too (unless we can't name it at all). It could *also* be (re)exported by the same crate
|
||||
// that wants to import it here, but we always prefer to use the external path here.
|
||||
|
||||
for dep in &db.crate_graph()[from.krate].dependencies {
|
||||
let import_map = db.import_map(dep.crate_id);
|
||||
for dep in &ctx.db.crate_graph()[from.krate].dependencies {
|
||||
let import_map = ctx.db.import_map(dep.crate_id);
|
||||
let Some(import_info_for) = import_map.import_info_for(item) else { continue };
|
||||
for info in import_info_for {
|
||||
if info.is_doc_hidden {
|
||||
|
|
@ -391,16 +379,13 @@ fn calculate_best_path(
|
|||
// Determine best path for containing module and append last segment from `info`.
|
||||
// FIXME: we should guide this to look up the path locally, or from the same crate again?
|
||||
let Some((mut path, path_stability)) = find_path_for_module(
|
||||
db,
|
||||
ctx,
|
||||
def_map,
|
||||
visited_modules,
|
||||
crate_root,
|
||||
from,
|
||||
info.container,
|
||||
max_len - 1,
|
||||
prefixed,
|
||||
prefer_no_std,
|
||||
prefer_prelude,
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
|
|
@ -413,17 +398,21 @@ fn calculate_best_path(
|
|||
);
|
||||
|
||||
let new_path_with_stab = match best_path.take() {
|
||||
Some(best_path) => {
|
||||
select_best_path(best_path, path_with_stab, prefer_no_std, prefer_prelude)
|
||||
}
|
||||
Some(best_path) => select_best_path(
|
||||
best_path,
|
||||
path_with_stab,
|
||||
ctx.prefer_no_std,
|
||||
ctx.prefer_prelude,
|
||||
),
|
||||
None => path_with_stab,
|
||||
};
|
||||
update_best_path(&mut best_path, new_path_with_stab);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(module) = item.module(db) {
|
||||
if module.containing_block().is_some() && prefixed.is_some() {
|
||||
let mut prefixed = ctx.prefixed;
|
||||
if let Some(module) = item.module(ctx.db) {
|
||||
if module.containing_block().is_some() && ctx.prefixed.is_some() {
|
||||
cov_mark::hit!(prefixed_in_block_expression);
|
||||
prefixed = Some(PrefixKind::Plain);
|
||||
}
|
||||
|
|
@ -548,34 +537,35 @@ fn find_local_import_locations(
|
|||
&ext_def_map[module.local_id]
|
||||
};
|
||||
|
||||
if let Some((name, vis)) = data.scope.name_of(item) {
|
||||
if let Some((name, vis, declared)) = data.scope.name_of(item) {
|
||||
if vis.is_visible_from(db, from) {
|
||||
let is_private = match vis {
|
||||
Visibility::Module(private_to) => private_to.local_id == module.local_id,
|
||||
Visibility::Public => false,
|
||||
};
|
||||
let is_original_def = match item.as_module_def_id() {
|
||||
Some(module_def_id) => data.scope.declarations().any(|it| it == module_def_id),
|
||||
None => false,
|
||||
let is_pub_or_explicit = match vis {
|
||||
Visibility::Module(_, VisibilityExplicity::Explicit) => {
|
||||
cov_mark::hit!(explicit_private_imports);
|
||||
true
|
||||
}
|
||||
Visibility::Module(_, VisibilityExplicity::Implicit) => {
|
||||
cov_mark::hit!(discount_private_imports);
|
||||
false
|
||||
}
|
||||
Visibility::Public => true,
|
||||
};
|
||||
|
||||
// Ignore private imports. these could be used if we are
|
||||
// Ignore private imports unless they are explicit. these could be used if we are
|
||||
// in a submodule of this module, but that's usually not
|
||||
// what the user wants; and if this module can import
|
||||
// the item and we're a submodule of it, so can we.
|
||||
// Also this keeps the cached data smaller.
|
||||
if !is_private || is_original_def {
|
||||
if is_pub_or_explicit || declared {
|
||||
locations.push((module, name.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Descend into all modules visible from `from`.
|
||||
for (ty, vis) in data.scope.types() {
|
||||
if let ModuleDefId::ModuleId(module) = ty {
|
||||
if vis.is_visible_from(db, from) {
|
||||
worklist.push(module);
|
||||
}
|
||||
for (module, vis) in data.scope.modules_in_scope() {
|
||||
if vis.is_visible_from(db, from) {
|
||||
worklist.push(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -625,16 +615,14 @@ mod tests {
|
|||
.expect("path does not resolve to a type");
|
||||
|
||||
let found_path = find_path_inner(
|
||||
&db,
|
||||
FindPathCtx { prefer_no_std: false, db: &db, prefixed: prefix_kind, prefer_prelude },
|
||||
ItemInNs::Types(resolved),
|
||||
module,
|
||||
prefix_kind,
|
||||
false,
|
||||
prefer_prelude,
|
||||
);
|
||||
assert_eq!(found_path, Some(mod_path), "on kind: {prefix_kind:?}");
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn check_found_path(
|
||||
ra_fixture: &str,
|
||||
unprefixed: &str,
|
||||
|
|
@ -1004,6 +992,7 @@ pub use crate::foo::bar::S;
|
|||
|
||||
#[test]
|
||||
fn discount_private_imports() {
|
||||
cov_mark::check!(discount_private_imports);
|
||||
check_found_path(
|
||||
r#"
|
||||
//- /main.rs
|
||||
|
|
@ -1021,6 +1010,47 @@ $0
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_private_imports_crate() {
|
||||
cov_mark::check!(explicit_private_imports);
|
||||
check_found_path(
|
||||
r#"
|
||||
//- /main.rs
|
||||
mod foo;
|
||||
pub mod bar { pub struct S; }
|
||||
pub(crate) use bar::S;
|
||||
//- /foo.rs
|
||||
$0
|
||||
"#,
|
||||
"crate::S",
|
||||
"crate::S",
|
||||
"crate::S",
|
||||
"crate::S",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_private_imports() {
|
||||
cov_mark::check!(explicit_private_imports);
|
||||
check_found_path(
|
||||
r#"
|
||||
//- /main.rs
|
||||
pub mod bar {
|
||||
mod foo;
|
||||
pub mod baz { pub struct S; }
|
||||
pub(self) use baz::S;
|
||||
}
|
||||
|
||||
//- /bar/foo.rs
|
||||
$0
|
||||
"#,
|
||||
"super::S",
|
||||
"super::S",
|
||||
"crate::bar::S",
|
||||
"super::S",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn import_cycle() {
|
||||
check_found_path(
|
||||
|
|
|
|||
|
|
@ -107,11 +107,11 @@ impl TypeOrConstParamData {
|
|||
impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);
|
||||
|
||||
/// Data about the generic parameters of a function, struct, impl, etc.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct GenericParams {
|
||||
pub type_or_consts: Arena<TypeOrConstParamData>,
|
||||
pub lifetimes: Arena<LifetimeParamData>,
|
||||
pub where_predicates: Vec<WherePredicate>,
|
||||
pub where_predicates: Box<[WherePredicate]>,
|
||||
}
|
||||
|
||||
/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined
|
||||
|
|
@ -142,109 +142,14 @@ pub enum WherePredicateTypeTarget {
|
|||
TypeOrConstParam(LocalTypeOrConstParamId),
|
||||
}
|
||||
|
||||
impl GenericParams {
|
||||
/// Iterator of type_or_consts field
|
||||
pub fn iter(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (Idx<TypeOrConstParamData>, &TypeOrConstParamData)> {
|
||||
self.type_or_consts.iter()
|
||||
}
|
||||
|
||||
pub(crate) fn generic_params_query(
|
||||
db: &dyn DefDatabase,
|
||||
def: GenericDefId,
|
||||
) -> Interned<GenericParams> {
|
||||
let _p = profile::span("generic_params_query");
|
||||
|
||||
let krate = def.module(db).krate;
|
||||
let cfg_options = db.crate_graph();
|
||||
let cfg_options = &cfg_options[krate].cfg_options;
|
||||
|
||||
// Returns the generic parameters that are enabled under the current `#[cfg]` options
|
||||
let enabled_params = |params: &Interned<GenericParams>, item_tree: &ItemTree| {
|
||||
let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);
|
||||
|
||||
// In the common case, no parameters will by disabled by `#[cfg]` attributes.
|
||||
// Therefore, make a first pass to check if all parameters are enabled and, if so,
|
||||
// clone the `Interned<GenericParams>` instead of recreating an identical copy.
|
||||
let all_type_or_consts_enabled =
|
||||
params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into()));
|
||||
let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into()));
|
||||
|
||||
if all_type_or_consts_enabled && all_lifetimes_enabled {
|
||||
params.clone()
|
||||
} else {
|
||||
Interned::new(GenericParams {
|
||||
type_or_consts: all_type_or_consts_enabled
|
||||
.then(|| params.type_or_consts.clone())
|
||||
.unwrap_or_else(|| {
|
||||
params
|
||||
.type_or_consts
|
||||
.iter()
|
||||
.filter_map(|(idx, param)| {
|
||||
enabled(idx.into()).then(|| param.clone())
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
lifetimes: all_lifetimes_enabled
|
||||
.then(|| params.lifetimes.clone())
|
||||
.unwrap_or_else(|| {
|
||||
params
|
||||
.lifetimes
|
||||
.iter()
|
||||
.filter_map(|(idx, param)| {
|
||||
enabled(idx.into()).then(|| param.clone())
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
where_predicates: params.where_predicates.clone(),
|
||||
})
|
||||
}
|
||||
};
|
||||
macro_rules! id_to_generics {
|
||||
($id:ident) => {{
|
||||
let id = $id.lookup(db).id;
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
enabled_params(&item.generic_params, &tree)
|
||||
}};
|
||||
}
|
||||
|
||||
match def {
|
||||
GenericDefId::FunctionId(id) => {
|
||||
let loc = id.lookup(db);
|
||||
let tree = loc.id.item_tree(db);
|
||||
let item = &tree[loc.id.value];
|
||||
|
||||
let enabled_params = enabled_params(&item.explicit_generic_params, &tree);
|
||||
let mut generic_params = GenericParams::clone(&enabled_params);
|
||||
|
||||
let module = loc.container.module(db);
|
||||
let func_data = db.function_data(id);
|
||||
|
||||
// Don't create an `Expander` if not needed since this
|
||||
// could cause a reparse after the `ItemTree` has been created due to the spanmap.
|
||||
let mut expander =
|
||||
Lazy::new(|| (module.def_map(db), Expander::new(db, loc.id.file_id(), module)));
|
||||
for param in func_data.params.iter() {
|
||||
generic_params.fill_implicit_impl_trait_args(db, &mut expander, param);
|
||||
}
|
||||
|
||||
Interned::new(generic_params)
|
||||
}
|
||||
GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id),
|
||||
GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id),
|
||||
GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id),
|
||||
GenericDefId::TraitId(id) => id_to_generics!(id),
|
||||
GenericDefId::TraitAliasId(id) => id_to_generics!(id),
|
||||
GenericDefId::TypeAliasId(id) => id_to_generics!(id),
|
||||
GenericDefId::ImplId(id) => id_to_generics!(id),
|
||||
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
|
||||
Interned::new(GenericParams::default())
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Default)]
|
||||
pub(crate) struct GenericParamsCollector {
|
||||
pub(crate) type_or_consts: Arena<TypeOrConstParamData>,
|
||||
lifetimes: Arena<LifetimeParamData>,
|
||||
where_predicates: Vec<WherePredicate>,
|
||||
}
|
||||
|
||||
impl GenericParamsCollector {
|
||||
pub(crate) fn fill(
|
||||
&mut self,
|
||||
lower_ctx: &LowerCtx<'_>,
|
||||
|
|
@ -444,11 +349,131 @@ impl GenericParams {
|
|||
});
|
||||
}
|
||||
|
||||
pub(crate) fn shrink_to_fit(&mut self) {
|
||||
let Self { lifetimes, type_or_consts: types, where_predicates } = self;
|
||||
pub(crate) fn finish(self) -> GenericParams {
|
||||
let Self { mut lifetimes, mut type_or_consts, where_predicates } = self;
|
||||
lifetimes.shrink_to_fit();
|
||||
types.shrink_to_fit();
|
||||
where_predicates.shrink_to_fit();
|
||||
type_or_consts.shrink_to_fit();
|
||||
GenericParams {
|
||||
type_or_consts,
|
||||
lifetimes,
|
||||
where_predicates: where_predicates.into_boxed_slice(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericParams {
|
||||
/// Iterator of type_or_consts field
|
||||
pub fn iter(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (Idx<TypeOrConstParamData>, &TypeOrConstParamData)> {
|
||||
self.type_or_consts.iter()
|
||||
}
|
||||
|
||||
pub(crate) fn generic_params_query(
|
||||
db: &dyn DefDatabase,
|
||||
def: GenericDefId,
|
||||
) -> Interned<GenericParams> {
|
||||
let _p = profile::span("generic_params_query");
|
||||
|
||||
let krate = def.module(db).krate;
|
||||
let cfg_options = db.crate_graph();
|
||||
let cfg_options = &cfg_options[krate].cfg_options;
|
||||
|
||||
// Returns the generic parameters that are enabled under the current `#[cfg]` options
|
||||
let enabled_params = |params: &Interned<GenericParams>, item_tree: &ItemTree| {
|
||||
let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);
|
||||
|
||||
// In the common case, no parameters will by disabled by `#[cfg]` attributes.
|
||||
// Therefore, make a first pass to check if all parameters are enabled and, if so,
|
||||
// clone the `Interned<GenericParams>` instead of recreating an identical copy.
|
||||
let all_type_or_consts_enabled =
|
||||
params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into()));
|
||||
let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into()));
|
||||
|
||||
if all_type_or_consts_enabled && all_lifetimes_enabled {
|
||||
params.clone()
|
||||
} else {
|
||||
Interned::new(GenericParams {
|
||||
type_or_consts: all_type_or_consts_enabled
|
||||
.then(|| params.type_or_consts.clone())
|
||||
.unwrap_or_else(|| {
|
||||
params
|
||||
.type_or_consts
|
||||
.iter()
|
||||
.filter_map(|(idx, param)| {
|
||||
enabled(idx.into()).then(|| param.clone())
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
lifetimes: all_lifetimes_enabled
|
||||
.then(|| params.lifetimes.clone())
|
||||
.unwrap_or_else(|| {
|
||||
params
|
||||
.lifetimes
|
||||
.iter()
|
||||
.filter_map(|(idx, param)| {
|
||||
enabled(idx.into()).then(|| param.clone())
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
where_predicates: params.where_predicates.clone(),
|
||||
})
|
||||
}
|
||||
};
|
||||
macro_rules! id_to_generics {
|
||||
($id:ident) => {{
|
||||
let id = $id.lookup(db).id;
|
||||
let tree = id.item_tree(db);
|
||||
let item = &tree[id.value];
|
||||
enabled_params(&item.generic_params, &tree)
|
||||
}};
|
||||
}
|
||||
|
||||
match def {
|
||||
GenericDefId::FunctionId(id) => {
|
||||
let loc = id.lookup(db);
|
||||
let tree = loc.id.item_tree(db);
|
||||
let item = &tree[loc.id.value];
|
||||
|
||||
let enabled_params = enabled_params(&item.explicit_generic_params, &tree);
|
||||
|
||||
let module = loc.container.module(db);
|
||||
let func_data = db.function_data(id);
|
||||
if func_data.params.is_empty() {
|
||||
enabled_params
|
||||
} else {
|
||||
let mut generic_params = GenericParamsCollector {
|
||||
type_or_consts: enabled_params.type_or_consts.clone(),
|
||||
lifetimes: enabled_params.lifetimes.clone(),
|
||||
where_predicates: enabled_params.where_predicates.clone().into(),
|
||||
};
|
||||
|
||||
// Don't create an `Expander` if not needed since this
|
||||
// could cause a reparse after the `ItemTree` has been created due to the spanmap.
|
||||
let mut expander = Lazy::new(|| {
|
||||
(module.def_map(db), Expander::new(db, loc.id.file_id(), module))
|
||||
});
|
||||
for param in func_data.params.iter() {
|
||||
generic_params.fill_implicit_impl_trait_args(db, &mut expander, param);
|
||||
}
|
||||
Interned::new(generic_params.finish())
|
||||
}
|
||||
}
|
||||
GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id),
|
||||
GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id),
|
||||
GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id),
|
||||
GenericDefId::TraitId(id) => id_to_generics!(id),
|
||||
GenericDefId::TraitAliasId(id) => id_to_generics!(id),
|
||||
GenericDefId::TypeAliasId(id) => id_to_generics!(id),
|
||||
GenericDefId::ImplId(id) => id_to_generics!(id),
|
||||
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
|
||||
Interned::new(GenericParams {
|
||||
type_or_consts: Default::default(),
|
||||
lifetimes: Default::default(),
|
||||
where_predicates: Default::default(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_type_by_name(&self, name: &Name, parent: GenericDefId) -> Option<TypeParamId> {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
use std::mem;
|
||||
|
||||
use hir_expand::name::Name;
|
||||
use rustc_dependencies::parse_format as parse;
|
||||
use rustc_parse_format as parse;
|
||||
use stdx::TupleExt;
|
||||
use syntax::{
|
||||
ast::{self, IsString},
|
||||
|
|
|
|||
|
|
@ -116,8 +116,7 @@ pub enum TypeRef {
|
|||
Path(Path),
|
||||
RawPtr(Box<TypeRef>, Mutability),
|
||||
Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability),
|
||||
// FIXME: for full const generics, the latter element (length) here is going to have to be an
|
||||
// expression that is further lowered later in hir_ty.
|
||||
// FIXME: This should be Array(Box<TypeRef>, Ast<ConstArg>),
|
||||
Array(Box<TypeRef>, ConstRef),
|
||||
Slice(Box<TypeRef>),
|
||||
/// A fn pointer. Last element of the vector is the return type.
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@ use stdx::format_to;
|
|||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId,
|
||||
ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId,
|
||||
TraitId, UseId,
|
||||
db::DefDatabase,
|
||||
per_ns::PerNs,
|
||||
visibility::{Visibility, VisibilityExplicity},
|
||||
AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId,
|
||||
ModuleDefId, ModuleId, TraitId, UseId,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
|
@ -105,7 +107,7 @@ pub struct ItemScope {
|
|||
/// The attribute macro invocations in this scope.
|
||||
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
|
||||
/// The macro invocations in this scope.
|
||||
pub macro_invocations: FxHashMap<AstId<ast::MacroCall>, MacroCallId>,
|
||||
macro_invocations: FxHashMap<AstId<ast::MacroCall>, MacroCallId>,
|
||||
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
|
||||
/// paired with the derive macro invocations for the specific attribute.
|
||||
derive_macros: FxHashMap<AstId<ast::Adt>, SmallVec<[DeriveMacroInvocation; 1]>>,
|
||||
|
|
@ -145,8 +147,8 @@ impl ItemScope {
|
|||
.chain(self.values.keys())
|
||||
.chain(self.macros.keys())
|
||||
.chain(self.unresolved.iter())
|
||||
.unique()
|
||||
.sorted()
|
||||
.dedup()
|
||||
.map(move |name| (name, self.get(name)))
|
||||
}
|
||||
|
||||
|
|
@ -157,8 +159,8 @@ impl ItemScope {
|
|||
.filter_map(ImportOrExternCrate::into_import)
|
||||
.chain(self.use_imports_values.keys().copied())
|
||||
.chain(self.use_imports_macros.keys().copied())
|
||||
.unique()
|
||||
.sorted()
|
||||
.dedup()
|
||||
}
|
||||
|
||||
pub fn fully_resolve_import(&self, db: &dyn DefDatabase, mut import: ImportId) -> PerNs {
|
||||
|
|
@ -234,20 +236,37 @@ impl ItemScope {
|
|||
self.impls.iter().copied()
|
||||
}
|
||||
|
||||
pub fn values(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
|
||||
self.values.values().copied().map(|(a, b, _)| (a, b))
|
||||
pub(crate) fn modules_in_scope(&self) -> impl Iterator<Item = (ModuleId, Visibility)> + '_ {
|
||||
self.types.values().copied().filter_map(|(def, vis, _)| match def {
|
||||
ModuleDefId::ModuleId(module) => Some((module, vis)),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn types(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
|
||||
self.types.values().copied().map(|(def, vis, _)| (def, vis))
|
||||
}
|
||||
pub fn unnamed_consts<'a>(
|
||||
&'a self,
|
||||
db: &'a dyn DefDatabase,
|
||||
) -> impl Iterator<Item = ConstId> + 'a {
|
||||
// FIXME: Also treat consts named `_DERIVE_*` as unnamed, since synstructure generates those.
|
||||
// Should be removed once synstructure stops doing that.
|
||||
let synstructure_hack_consts = self.values.values().filter_map(|(item, _, _)| match item {
|
||||
&ModuleDefId::ConstId(id) => {
|
||||
let loc = id.lookup(db);
|
||||
let item_tree = loc.id.item_tree(db);
|
||||
if item_tree[loc.id.value]
|
||||
.name
|
||||
.as_ref()
|
||||
.map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_"))
|
||||
{
|
||||
Some(id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
|
||||
self.unnamed_consts.iter().copied()
|
||||
self.unnamed_consts.iter().copied().chain(synstructure_hack_consts)
|
||||
}
|
||||
|
||||
/// Iterate over all module scoped macros
|
||||
|
|
@ -274,21 +293,18 @@ impl ItemScope {
|
|||
}
|
||||
|
||||
/// XXX: this is O(N) rather than O(1), try to not introduce new usages.
|
||||
pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
|
||||
pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility, /*declared*/ bool)> {
|
||||
match item {
|
||||
ItemInNs::Macros(def) => self
|
||||
.macros
|
||||
.iter()
|
||||
.find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
|
||||
ItemInNs::Types(def) => self
|
||||
.types
|
||||
.iter()
|
||||
.find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
|
||||
ItemInNs::Macros(def) => self.macros.iter().find_map(|(name, &(other_def, vis, i))| {
|
||||
(other_def == def).then_some((name, vis, i.is_none()))
|
||||
}),
|
||||
ItemInNs::Types(def) => self.types.iter().find_map(|(name, &(other_def, vis, i))| {
|
||||
(other_def == def).then_some((name, vis, i.is_none()))
|
||||
}),
|
||||
|
||||
ItemInNs::Values(def) => self
|
||||
.values
|
||||
.iter()
|
||||
.find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
|
||||
ItemInNs::Values(def) => self.values.iter().find_map(|(name, &(other_def, vis, i))| {
|
||||
(other_def == def).then_some((name, vis, i.is_none()))
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -316,6 +332,10 @@ impl ItemScope {
|
|||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn macro_invoc(&self, call: AstId<ast::MacroCall>) -> Option<MacroCallId> {
|
||||
self.macro_invocations.get(&call).copied()
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemScope {
|
||||
|
|
@ -624,18 +644,17 @@ impl ItemScope {
|
|||
pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) {
|
||||
self.types
|
||||
.values_mut()
|
||||
.map(|(def, vis, _)| (def, vis))
|
||||
.chain(self.values.values_mut().map(|(def, vis, _)| (def, vis)))
|
||||
.map(|(_, v)| v)
|
||||
.map(|(_, vis, _)| vis)
|
||||
.chain(self.values.values_mut().map(|(_, vis, _)| vis))
|
||||
.chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis))
|
||||
.for_each(|vis| *vis = Visibility::Module(this_module));
|
||||
.for_each(|vis| *vis = Visibility::Module(this_module, VisibilityExplicity::Implicit));
|
||||
|
||||
for (mac, vis, import) in self.macros.values_mut() {
|
||||
if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*vis = Visibility::Module(this_module);
|
||||
*vis = Visibility::Module(this_module, VisibilityExplicity::Implicit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ use crate::{
|
|||
generics::{GenericParams, LifetimeParamData, TypeOrConstParamData},
|
||||
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
|
||||
type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
|
||||
visibility::RawVisibility,
|
||||
visibility::{RawVisibility, VisibilityExplicity},
|
||||
BlockId, Lookup,
|
||||
};
|
||||
|
||||
|
|
@ -78,8 +78,9 @@ pub struct RawVisibilityId(u32);
|
|||
|
||||
impl RawVisibilityId {
|
||||
pub const PUB: Self = RawVisibilityId(u32::max_value());
|
||||
pub const PRIV: Self = RawVisibilityId(u32::max_value() - 1);
|
||||
pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 2);
|
||||
pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::max_value() - 1);
|
||||
pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::max_value() - 2);
|
||||
pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 3);
|
||||
}
|
||||
|
||||
impl fmt::Debug for RawVisibilityId {
|
||||
|
|
@ -87,7 +88,7 @@ impl fmt::Debug for RawVisibilityId {
|
|||
let mut f = f.debug_tuple("RawVisibilityId");
|
||||
match *self {
|
||||
Self::PUB => f.field(&"pub"),
|
||||
Self::PRIV => f.field(&"pub(self)"),
|
||||
Self::PRIV_IMPLICIT | Self::PRIV_EXPLICIT => f.field(&"pub(self)"),
|
||||
Self::PUB_CRATE => f.field(&"pub(crate)"),
|
||||
_ => f.field(&self.0),
|
||||
};
|
||||
|
|
@ -249,19 +250,30 @@ impl ItemVisibilities {
|
|||
fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId {
|
||||
match &vis {
|
||||
RawVisibility::Public => RawVisibilityId::PUB,
|
||||
RawVisibility::Module(path) if path.segments().is_empty() => match &path.kind {
|
||||
PathKind::Super(0) => RawVisibilityId::PRIV,
|
||||
PathKind::Crate => RawVisibilityId::PUB_CRATE,
|
||||
_ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
|
||||
},
|
||||
RawVisibility::Module(path, explicitiy) if path.segments().is_empty() => {
|
||||
match (&path.kind, explicitiy) {
|
||||
(PathKind::Super(0), VisibilityExplicity::Explicit) => {
|
||||
RawVisibilityId::PRIV_EXPLICIT
|
||||
}
|
||||
(PathKind::Super(0), VisibilityExplicity::Implicit) => {
|
||||
RawVisibilityId::PRIV_IMPLICIT
|
||||
}
|
||||
(PathKind::Crate, _) => RawVisibilityId::PUB_CRATE,
|
||||
_ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
|
||||
}
|
||||
}
|
||||
_ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VIS_PUB: RawVisibility = RawVisibility::Public;
|
||||
static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)));
|
||||
static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate));
|
||||
static VIS_PRIV_IMPLICIT: RawVisibility =
|
||||
RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Implicit);
|
||||
static VIS_PRIV_EXPLICIT: RawVisibility =
|
||||
RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Explicit);
|
||||
static VIS_PUB_CRATE: RawVisibility =
|
||||
RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicity::Explicit);
|
||||
|
||||
#[derive(Default, Debug, Eq, PartialEq)]
|
||||
struct ItemTreeData {
|
||||
|
|
@ -540,7 +552,8 @@ impl Index<RawVisibilityId> for ItemTree {
|
|||
type Output = RawVisibility;
|
||||
fn index(&self, index: RawVisibilityId) -> &Self::Output {
|
||||
match index {
|
||||
RawVisibilityId::PRIV => &VIS_PRIV,
|
||||
RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT,
|
||||
RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT,
|
||||
RawVisibilityId::PUB => &VIS_PUB,
|
||||
RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE,
|
||||
_ => &self.data().vis.arena[Idx::from_raw(index.0.into())],
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use hir_expand::{ast_id_map::AstIdMap, span_map::SpanMapRef, HirFileId};
|
|||
use syntax::ast::{self, HasModuleItem, HasTypeBounds};
|
||||
|
||||
use crate::{
|
||||
generics::{GenericParams, TypeParamData, TypeParamProvenance},
|
||||
generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
|
||||
type_ref::{LifetimeRef, TraitBoundModifier, TraitRef},
|
||||
LocalLifetimeParamId, LocalTypeOrConstParamId,
|
||||
};
|
||||
|
|
@ -386,17 +386,16 @@ impl<'a> Ctx<'a> {
|
|||
flags |= FnFlags::HAS_UNSAFE_KW;
|
||||
}
|
||||
|
||||
let mut res = Function {
|
||||
let res = Function {
|
||||
name,
|
||||
visibility,
|
||||
explicit_generic_params: Interned::new(GenericParams::default()),
|
||||
explicit_generic_params: self.lower_generic_params(HasImplicitSelf::No, func),
|
||||
abi,
|
||||
params,
|
||||
ret_type: Interned::new(ret_type),
|
||||
ast_id,
|
||||
flags,
|
||||
};
|
||||
res.explicit_generic_params = self.lower_generic_params(HasImplicitSelf::No, func);
|
||||
|
||||
Some(id(self.data().functions.alloc(res)))
|
||||
}
|
||||
|
|
@ -604,7 +603,7 @@ impl<'a> Ctx<'a> {
|
|||
has_implicit_self: HasImplicitSelf,
|
||||
node: &dyn ast::HasGenericParams,
|
||||
) -> Interned<GenericParams> {
|
||||
let mut generics = GenericParams::default();
|
||||
let mut generics = GenericParamsCollector::default();
|
||||
|
||||
if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
|
||||
// Traits and trait aliases get the Self type as an implicit first type parameter.
|
||||
|
|
@ -642,8 +641,7 @@ impl<'a> Ctx<'a> {
|
|||
};
|
||||
generics.fill(&self.body_ctx, node, add_param_attrs);
|
||||
|
||||
generics.shrink_to_fit();
|
||||
Interned::new(generics)
|
||||
Interned::new(generics.finish())
|
||||
}
|
||||
|
||||
fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Box<[Interned<TypeBound>]> {
|
||||
|
|
|
|||
|
|
@ -104,7 +104,9 @@ impl Printer<'_> {
|
|||
|
||||
fn print_visibility(&mut self, vis: RawVisibilityId) {
|
||||
match &self.tree[vis] {
|
||||
RawVisibility::Module(path) => w!(self, "pub({}) ", path.display(self.db.upcast())),
|
||||
RawVisibility::Module(path, _expl) => {
|
||||
w!(self, "pub({}) ", path.display(self.db.upcast()))
|
||||
}
|
||||
RawVisibility::Public => w!(self, "pub "),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,10 @@ impl LangItems {
|
|||
}
|
||||
|
||||
/// Salsa query. This will look for lang items in a specific crate.
|
||||
pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<LangItems> {
|
||||
pub(crate) fn crate_lang_items_query(
|
||||
db: &dyn DefDatabase,
|
||||
krate: CrateId,
|
||||
) -> Option<Arc<LangItems>> {
|
||||
let _p = profile::span("crate_lang_items_query");
|
||||
|
||||
let mut lang_items = LangItems::default();
|
||||
|
|
@ -150,7 +153,11 @@ impl LangItems {
|
|||
}
|
||||
}
|
||||
|
||||
Arc::new(lang_items)
|
||||
if lang_items.items.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Arc::new(lang_items))
|
||||
}
|
||||
}
|
||||
|
||||
/// Salsa query. Look for a lang item, starting from the specified crate and recursively
|
||||
|
|
@ -161,9 +168,9 @@ impl LangItems {
|
|||
item: LangItem,
|
||||
) -> Option<LangItemTarget> {
|
||||
let _p = profile::span("lang_item_query");
|
||||
let lang_items = db.crate_lang_items(start_crate);
|
||||
let start_crate_target = lang_items.items.get(&item);
|
||||
if let Some(&target) = start_crate_target {
|
||||
if let Some(target) =
|
||||
db.crate_lang_items(start_crate).and_then(|it| it.items.get(&item).copied())
|
||||
{
|
||||
return Some(target);
|
||||
}
|
||||
db.crate_graph()[start_crate]
|
||||
|
|
|
|||
|
|
@ -10,10 +10,17 @@
|
|||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! eprintln {
|
||||
($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
|
||||
}
|
||||
#[cfg(feature = "in-rust-tree")]
|
||||
extern crate rustc_parse_format;
|
||||
|
||||
#[cfg(not(feature = "in-rust-tree"))]
|
||||
extern crate ra_ap_rustc_parse_format as rustc_parse_format;
|
||||
|
||||
#[cfg(feature = "in-rust-tree")]
|
||||
extern crate rustc_abi;
|
||||
|
||||
#[cfg(not(feature = "in-rust-tree"))]
|
||||
extern crate ra_ap_rustc_abi as rustc_abi;
|
||||
|
||||
pub mod db;
|
||||
|
||||
|
|
@ -49,7 +56,7 @@ pub mod visibility;
|
|||
pub mod find_path;
|
||||
pub mod import_map;
|
||||
|
||||
pub use rustc_dependencies::abi as layout;
|
||||
pub use rustc_abi as layout;
|
||||
use triomphe::Arc;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -16,13 +16,12 @@ struct Foo;
|
|||
#[derive(Copy)]
|
||||
struct Foo;
|
||||
|
||||
impl < > core::marker::Copy for Foo< > where {}"#]],
|
||||
impl < > $crate::marker::Copy for Foo< > where {}"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_copy_expand_in_core() {
|
||||
cov_mark::check!(test_copy_expand_in_core);
|
||||
check(
|
||||
r#"
|
||||
//- /lib.rs crate:core
|
||||
|
|
@ -41,7 +40,7 @@ macro Copy {}
|
|||
#[derive(Copy)]
|
||||
struct Foo;
|
||||
|
||||
impl < > crate ::marker::Copy for Foo< > where {}"#]],
|
||||
impl < > $crate::marker::Copy for Foo< > where {}"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +56,7 @@ struct Foo<A, B>;
|
|||
#[derive(Copy)]
|
||||
struct Foo<A, B>;
|
||||
|
||||
impl <A: core::marker::Copy, B: core::marker::Copy, > core::marker::Copy for Foo<A, B, > where {}"#]],
|
||||
impl <A: $crate::marker::Copy, B: $crate::marker::Copy, > $crate::marker::Copy for Foo<A, B, > where {}"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +73,7 @@ struct Foo<A, B, 'a, 'b>;
|
|||
#[derive(Copy)]
|
||||
struct Foo<A, B, 'a, 'b>;
|
||||
|
||||
impl <A: core::marker::Copy, B: core::marker::Copy, > core::marker::Copy for Foo<A, B, > where {}"#]],
|
||||
impl <A: $crate::marker::Copy, B: $crate::marker::Copy, > $crate::marker::Copy for Foo<A, B, > where {}"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -98,7 +97,7 @@ enum Command<A, B> {
|
|||
Jump,
|
||||
}
|
||||
|
||||
impl <A: core::clone::Clone, B: core::clone::Clone, > core::clone::Clone for Command<A, B, > where {
|
||||
impl <A: $crate::clone::Clone, B: $crate::clone::Clone, > $crate::clone::Clone for Command<A, B, > where {
|
||||
fn clone(&self ) -> Self {
|
||||
match self {
|
||||
Command::Move {
|
||||
|
|
@ -158,7 +157,7 @@ where
|
|||
generic: Vec<T::InGenericArg>,
|
||||
}
|
||||
|
||||
impl <T: core::clone::Clone, > core::clone::Clone for Foo<T, > where T: Trait, T::InFieldShorthand: core::clone::Clone, T::InGenericArg: core::clone::Clone, {
|
||||
impl <T: $crate::clone::Clone, > $crate::clone::Clone for Foo<T, > where T: Trait, T::InFieldShorthand: $crate::clone::Clone, T::InGenericArg: $crate::clone::Clone, {
|
||||
fn clone(&self ) -> Self {
|
||||
match self {
|
||||
Foo {
|
||||
|
|
@ -186,7 +185,7 @@ struct Foo<const X: usize, T>(u32);
|
|||
#[derive(Clone)]
|
||||
struct Foo<const X: usize, T>(u32);
|
||||
|
||||
impl <const X: usize, T: core::clone::Clone, > core::clone::Clone for Foo<X, T, > where {
|
||||
impl <const X: usize, T: $crate::clone::Clone, > $crate::clone::Clone for Foo<X, T, > where {
|
||||
fn clone(&self ) -> Self {
|
||||
match self {
|
||||
Foo(f0, )=>Foo(f0.clone(), ),
|
||||
|
|
@ -226,14 +225,14 @@ enum Bar {
|
|||
Bar,
|
||||
}
|
||||
|
||||
impl < > core::default::Default for Foo< > where {
|
||||
impl < > $crate::default::Default for Foo< > where {
|
||||
fn default() -> Self {
|
||||
Foo {
|
||||
field1: core::default::Default::default(), field2: core::default::Default::default(),
|
||||
field1: $crate::default::Default::default(), field2: $crate::default::Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl < > core::default::Default for Bar< > where {
|
||||
impl < > $crate::default::Default for Bar< > where {
|
||||
fn default() -> Self {
|
||||
Bar::Bar
|
||||
}
|
||||
|
|
@ -261,7 +260,7 @@ enum Command {
|
|||
Jump,
|
||||
}
|
||||
|
||||
impl < > core::cmp::PartialEq for Command< > where {
|
||||
impl < > $crate::cmp::PartialEq for Command< > where {
|
||||
fn eq(&self , other: &Self ) -> bool {
|
||||
match (self , other) {
|
||||
(Command::Move {
|
||||
|
|
@ -274,7 +273,7 @@ impl < > core::cmp::PartialEq for Command< > where {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl < > core::cmp::Eq for Command< > where {}"#]],
|
||||
impl < > $crate::cmp::Eq for Command< > where {}"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +298,7 @@ enum Command {
|
|||
Jump,
|
||||
}
|
||||
|
||||
impl < > core::cmp::PartialEq for Command< > where {
|
||||
impl < > $crate::cmp::PartialEq for Command< > where {
|
||||
fn eq(&self , other: &Self ) -> bool {
|
||||
match (self , other) {
|
||||
(Command::Move {
|
||||
|
|
@ -312,7 +311,7 @@ impl < > core::cmp::PartialEq for Command< > where {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl < > core::cmp::Eq for Command< > where {}"#]],
|
||||
impl < > $crate::cmp::Eq for Command< > where {}"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -336,10 +335,10 @@ enum Command {
|
|||
Jump,
|
||||
}
|
||||
|
||||
impl < > core::cmp::PartialOrd for Command< > where {
|
||||
fn partial_cmp(&self , other: &Self ) -> core::option::Option::Option<core::cmp::Ordering> {
|
||||
match core::intrinsics::discriminant_value(self ).partial_cmp(&core::intrinsics::discriminant_value(other)) {
|
||||
core::option::Option::Some(core::cmp::Ordering::Equal)=> {
|
||||
impl < > $crate::cmp::PartialOrd for Command< > where {
|
||||
fn partial_cmp(&self , other: &Self ) -> $crate::option::Option::Option<$crate::cmp::Ordering> {
|
||||
match $crate::intrinsics::discriminant_value(self ).partial_cmp(&$crate::intrinsics::discriminant_value(other)) {
|
||||
$crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
|
||||
match (self , other) {
|
||||
(Command::Move {
|
||||
x: x_self, y: y_self,
|
||||
|
|
@ -348,10 +347,10 @@ impl < > core::cmp::PartialOrd for Command< > where {
|
|||
x: x_other, y: y_other,
|
||||
}
|
||||
)=>match x_self.partial_cmp(&x_other) {
|
||||
core::option::Option::Some(core::cmp::Ordering::Equal)=> {
|
||||
$crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
|
||||
match y_self.partial_cmp(&y_other) {
|
||||
core::option::Option::Some(core::cmp::Ordering::Equal)=> {
|
||||
core::option::Option::Some(core::cmp::Ordering::Equal)
|
||||
$crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
|
||||
$crate::option::Option::Some($crate::cmp::Ordering::Equal)
|
||||
}
|
||||
c=>return c,
|
||||
}
|
||||
|
|
@ -359,22 +358,22 @@ impl < > core::cmp::PartialOrd for Command< > where {
|
|||
c=>return c,
|
||||
}
|
||||
, (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.partial_cmp(&f0_other) {
|
||||
core::option::Option::Some(core::cmp::Ordering::Equal)=> {
|
||||
core::option::Option::Some(core::cmp::Ordering::Equal)
|
||||
$crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
|
||||
$crate::option::Option::Some($crate::cmp::Ordering::Equal)
|
||||
}
|
||||
c=>return c,
|
||||
}
|
||||
, (Command::Jump, Command::Jump)=>core::option::Option::Some(core::cmp::Ordering::Equal), _unused=>core::option::Option::Some(core::cmp::Ordering::Equal)
|
||||
, (Command::Jump, Command::Jump)=>$crate::option::Option::Some($crate::cmp::Ordering::Equal), _unused=>$crate::option::Option::Some($crate::cmp::Ordering::Equal)
|
||||
}
|
||||
}
|
||||
c=>return c,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl < > core::cmp::Ord for Command< > where {
|
||||
fn cmp(&self , other: &Self ) -> core::cmp::Ordering {
|
||||
match core::intrinsics::discriminant_value(self ).cmp(&core::intrinsics::discriminant_value(other)) {
|
||||
core::cmp::Ordering::Equal=> {
|
||||
impl < > $crate::cmp::Ord for Command< > where {
|
||||
fn cmp(&self , other: &Self ) -> $crate::cmp::Ordering {
|
||||
match $crate::intrinsics::discriminant_value(self ).cmp(&$crate::intrinsics::discriminant_value(other)) {
|
||||
$crate::cmp::Ordering::Equal=> {
|
||||
match (self , other) {
|
||||
(Command::Move {
|
||||
x: x_self, y: y_self,
|
||||
|
|
@ -383,10 +382,10 @@ impl < > core::cmp::Ord for Command< > where {
|
|||
x: x_other, y: y_other,
|
||||
}
|
||||
)=>match x_self.cmp(&x_other) {
|
||||
core::cmp::Ordering::Equal=> {
|
||||
$crate::cmp::Ordering::Equal=> {
|
||||
match y_self.cmp(&y_other) {
|
||||
core::cmp::Ordering::Equal=> {
|
||||
core::cmp::Ordering::Equal
|
||||
$crate::cmp::Ordering::Equal=> {
|
||||
$crate::cmp::Ordering::Equal
|
||||
}
|
||||
c=>return c,
|
||||
}
|
||||
|
|
@ -394,12 +393,12 @@ impl < > core::cmp::Ord for Command< > where {
|
|||
c=>return c,
|
||||
}
|
||||
, (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.cmp(&f0_other) {
|
||||
core::cmp::Ordering::Equal=> {
|
||||
core::cmp::Ordering::Equal
|
||||
$crate::cmp::Ordering::Equal=> {
|
||||
$crate::cmp::Ordering::Equal
|
||||
}
|
||||
c=>return c,
|
||||
}
|
||||
, (Command::Jump, Command::Jump)=>core::cmp::Ordering::Equal, _unused=>core::cmp::Ordering::Equal
|
||||
, (Command::Jump, Command::Jump)=>$crate::cmp::Ordering::Equal, _unused=>$crate::cmp::Ordering::Equal
|
||||
}
|
||||
}
|
||||
c=>return c,
|
||||
|
|
@ -433,8 +432,8 @@ struct Foo {
|
|||
z: (i32, u64),
|
||||
}
|
||||
|
||||
impl < > core::hash::Hash for Foo< > where {
|
||||
fn hash<H: core::hash::Hasher>(&self , ra_expand_state: &mut H) {
|
||||
impl < > $crate::hash::Hash for Foo< > where {
|
||||
fn hash<H: $crate::hash::Hasher>(&self , ra_expand_state: &mut H) {
|
||||
match self {
|
||||
Foo {
|
||||
x: x, y: y, z: z,
|
||||
|
|
@ -471,9 +470,9 @@ enum Command {
|
|||
Jump,
|
||||
}
|
||||
|
||||
impl < > core::hash::Hash for Command< > where {
|
||||
fn hash<H: core::hash::Hasher>(&self , ra_expand_state: &mut H) {
|
||||
core::mem::discriminant(self ).hash(ra_expand_state);
|
||||
impl < > $crate::hash::Hash for Command< > where {
|
||||
fn hash<H: $crate::hash::Hasher>(&self , ra_expand_state: &mut H) {
|
||||
$crate::mem::discriminant(self ).hash(ra_expand_state);
|
||||
match self {
|
||||
Command::Move {
|
||||
x: x, y: y,
|
||||
|
|
@ -517,8 +516,8 @@ enum Command {
|
|||
Jump,
|
||||
}
|
||||
|
||||
impl < > core::fmt::Debug for Command< > where {
|
||||
fn fmt(&self , f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
impl < > $crate::fmt::Debug for Command< > where {
|
||||
fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
|
||||
match self {
|
||||
Command::Move {
|
||||
x: x, y: y,
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ fn main() { option_env!("TEST_ENV_VAR"); }
|
|||
#[rustc_builtin_macro]
|
||||
macro_rules! option_env {() => {}}
|
||||
|
||||
fn main() { ::core::option::Option::None:: < &str>; }
|
||||
fn main() { $crate::option::Option::None:: < &str>; }
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ use crate::{
|
|||
nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
|
||||
path::ModPath,
|
||||
per_ns::PerNs,
|
||||
visibility::Visibility,
|
||||
visibility::{Visibility, VisibilityExplicity},
|
||||
AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, LocalModuleId, Lookup,
|
||||
MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
|
||||
};
|
||||
|
|
@ -332,7 +332,10 @@ impl DefMap {
|
|||
// NB: we use `None` as block here, which would be wrong for implicit
|
||||
// modules declared by blocks with items. At the moment, we don't use
|
||||
// this visibility for anything outside IDE, so that's probably OK.
|
||||
let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
|
||||
let visibility = Visibility::Module(
|
||||
ModuleId { krate, local_id, block: None },
|
||||
VisibilityExplicity::Implicit,
|
||||
);
|
||||
let module_data = ModuleData::new(
|
||||
ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id },
|
||||
visibility,
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ impl DefMap {
|
|||
within_impl: bool,
|
||||
) -> Option<Visibility> {
|
||||
let mut vis = match visibility {
|
||||
RawVisibility::Module(path) => {
|
||||
RawVisibility::Module(path, explicity) => {
|
||||
let (result, remaining) =
|
||||
self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None);
|
||||
if remaining.is_some() {
|
||||
|
|
@ -95,7 +95,7 @@ impl DefMap {
|
|||
}
|
||||
let types = result.take_types()?;
|
||||
match types {
|
||||
ModuleDefId::ModuleId(m) => Visibility::Module(m),
|
||||
ModuleDefId::ModuleId(m) => Visibility::Module(m, *explicity),
|
||||
// error: visibility needs to refer to module
|
||||
_ => {
|
||||
return None;
|
||||
|
|
@ -108,11 +108,11 @@ impl DefMap {
|
|||
// In block expressions, `self` normally refers to the containing non-block module, and
|
||||
// `super` to its parent (etc.). However, visibilities must only refer to a module in the
|
||||
// DefMap they're written in, so we restrict them when that happens.
|
||||
if let Visibility::Module(m) = vis {
|
||||
if let Visibility::Module(m, mv) = vis {
|
||||
// ...unless we're resolving visibility for an associated item in an impl.
|
||||
if self.block_id() != m.block && !within_impl {
|
||||
cov_mark::hit!(adjust_vis_in_block_def_map);
|
||||
vis = Visibility::Module(self.module_id(Self::ROOT));
|
||||
vis = Visibility::Module(self.module_id(Self::ROOT), mv);
|
||||
tracing::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1264,6 +1264,54 @@ struct A;
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_include() {
|
||||
check(
|
||||
r#"
|
||||
//- minicore: include
|
||||
//- /lib.rs
|
||||
include!("out_dir/includes.rs");
|
||||
|
||||
//- /out_dir/includes.rs
|
||||
pub mod company_name {
|
||||
pub mod network {
|
||||
pub mod v1 {
|
||||
include!("company_name.network.v1.rs");
|
||||
}
|
||||
}
|
||||
}
|
||||
//- /out_dir/company_name.network.v1.rs
|
||||
pub struct IpAddress {
|
||||
pub ip_type: &'static str,
|
||||
}
|
||||
/// Nested message and enum types in `IpAddress`.
|
||||
pub mod ip_address {
|
||||
pub enum IpType {
|
||||
IpV4(u32),
|
||||
}
|
||||
}
|
||||
|
||||
"#,
|
||||
expect![[r#"
|
||||
crate
|
||||
company_name: t
|
||||
|
||||
crate::company_name
|
||||
network: t
|
||||
|
||||
crate::company_name::network
|
||||
v1: t
|
||||
|
||||
crate::company_name::network::v1
|
||||
IpAddress: t
|
||||
ip_address: t
|
||||
|
||||
crate::company_name::network::v1::ip_address
|
||||
IpType: t
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn macro_use_imports_all_macro_types() {
|
||||
let db = TestDB::with_files(
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ impl Resolver {
|
|||
let within_impl =
|
||||
self.scopes().find(|scope| matches!(scope, Scope::ImplDefScope(_))).is_some();
|
||||
match visibility {
|
||||
RawVisibility::Module(_) => {
|
||||
RawVisibility::Module(_, _) => {
|
||||
let (item_map, module) = self.item_scope();
|
||||
item_map.resolve_visibility(db, module, visibility, within_impl)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use base_db::{
|
|||
Upcast,
|
||||
};
|
||||
use hir_expand::{db::ExpandDatabase, InFile};
|
||||
use rustc_hash::FxHashSet;
|
||||
use syntax::{algo, ast, AstNode};
|
||||
use triomphe::Arc;
|
||||
|
||||
|
|
@ -76,7 +75,7 @@ impl FileLoader for TestDB {
|
|||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
|
||||
FileLoaderDelegate(self).resolve_path(path)
|
||||
}
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]> {
|
||||
FileLoaderDelegate(self).relevant_crates(file_id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,14 +20,14 @@ use crate::{
|
|||
pub enum RawVisibility {
|
||||
/// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is
|
||||
/// equivalent to `pub(self)`.
|
||||
Module(ModPath),
|
||||
Module(ModPath, VisibilityExplicity),
|
||||
/// `pub`.
|
||||
Public,
|
||||
}
|
||||
|
||||
impl RawVisibility {
|
||||
pub(crate) const fn private() -> RawVisibility {
|
||||
RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)))
|
||||
RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicity::Implicit)
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast(
|
||||
|
|
@ -41,18 +41,9 @@ impl RawVisibility {
|
|||
db: &dyn DefDatabase,
|
||||
node: Option<ast::Visibility>,
|
||||
span_map: SpanMapRef<'_>,
|
||||
) -> RawVisibility {
|
||||
Self::from_ast_with_span_map_and_default(db, node, RawVisibility::private(), span_map)
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast_with_span_map_and_default(
|
||||
db: &dyn DefDatabase,
|
||||
node: Option<ast::Visibility>,
|
||||
default: RawVisibility,
|
||||
span_map: SpanMapRef<'_>,
|
||||
) -> RawVisibility {
|
||||
let node = match node {
|
||||
None => return default,
|
||||
None => return RawVisibility::private(),
|
||||
Some(node) => node,
|
||||
};
|
||||
match node.kind() {
|
||||
|
|
@ -62,19 +53,19 @@ impl RawVisibility {
|
|||
None => return RawVisibility::private(),
|
||||
Some(path) => path,
|
||||
};
|
||||
RawVisibility::Module(path)
|
||||
RawVisibility::Module(path, VisibilityExplicity::Explicit)
|
||||
}
|
||||
ast::VisibilityKind::PubCrate => {
|
||||
let path = ModPath::from_kind(PathKind::Crate);
|
||||
RawVisibility::Module(path)
|
||||
RawVisibility::Module(path, VisibilityExplicity::Explicit)
|
||||
}
|
||||
ast::VisibilityKind::PubSuper => {
|
||||
let path = ModPath::from_kind(PathKind::Super(1));
|
||||
RawVisibility::Module(path)
|
||||
RawVisibility::Module(path, VisibilityExplicity::Explicit)
|
||||
}
|
||||
ast::VisibilityKind::PubSelf => {
|
||||
let path = ModPath::from_kind(PathKind::Super(0));
|
||||
RawVisibility::Module(path)
|
||||
RawVisibility::Module(path, VisibilityExplicity::Explicit)
|
||||
}
|
||||
ast::VisibilityKind::Pub => RawVisibility::Public,
|
||||
}
|
||||
|
|
@ -94,7 +85,7 @@ impl RawVisibility {
|
|||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Visibility {
|
||||
/// Visibility is restricted to a certain module.
|
||||
Module(ModuleId),
|
||||
Module(ModuleId, VisibilityExplicity),
|
||||
/// Visibility is unrestricted.
|
||||
Public,
|
||||
}
|
||||
|
|
@ -102,7 +93,7 @@ pub enum Visibility {
|
|||
impl Visibility {
|
||||
pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool {
|
||||
let to_module = match self {
|
||||
Visibility::Module(m) => m,
|
||||
Visibility::Module(m, _) => m,
|
||||
Visibility::Public => return true,
|
||||
};
|
||||
// if they're not in the same crate, it can't be visible
|
||||
|
|
@ -124,7 +115,7 @@ impl Visibility {
|
|||
mut from_module: LocalModuleId,
|
||||
) -> bool {
|
||||
let mut to_module = match self {
|
||||
Visibility::Module(m) => m,
|
||||
Visibility::Module(m, _) => m,
|
||||
Visibility::Public => return true,
|
||||
};
|
||||
|
||||
|
|
@ -181,9 +172,9 @@ impl Visibility {
|
|||
/// visible in unrelated modules).
|
||||
pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
|
||||
match (self, other) {
|
||||
(Visibility::Module(_) | Visibility::Public, Visibility::Public)
|
||||
| (Visibility::Public, Visibility::Module(_)) => Some(Visibility::Public),
|
||||
(Visibility::Module(mod_a), Visibility::Module(mod_b)) => {
|
||||
(Visibility::Module(_, _) | Visibility::Public, Visibility::Public)
|
||||
| (Visibility::Public, Visibility::Module(_, _)) => Some(Visibility::Public),
|
||||
(Visibility::Module(mod_a, vis_a), Visibility::Module(mod_b, vis_b)) => {
|
||||
if mod_a.krate != mod_b.krate {
|
||||
return None;
|
||||
}
|
||||
|
|
@ -199,12 +190,12 @@ impl Visibility {
|
|||
|
||||
if a_ancestors.any(|m| m == mod_b.local_id) {
|
||||
// B is above A
|
||||
return Some(Visibility::Module(mod_b));
|
||||
return Some(Visibility::Module(mod_b, vis_b));
|
||||
}
|
||||
|
||||
if b_ancestors.any(|m| m == mod_a.local_id) {
|
||||
// A is above B
|
||||
return Some(Visibility::Module(mod_a));
|
||||
return Some(Visibility::Module(mod_a, vis_a));
|
||||
}
|
||||
|
||||
None
|
||||
|
|
@ -213,6 +204,19 @@ impl Visibility {
|
|||
}
|
||||
}
|
||||
|
||||
/// Whether the item was imported through `pub(crate) use` or just `use`.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum VisibilityExplicity {
|
||||
Explicit,
|
||||
Implicit,
|
||||
}
|
||||
|
||||
impl VisibilityExplicity {
|
||||
pub fn is_explicit(&self) -> bool {
|
||||
matches!(self, Self::Explicit)
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve visibility of all specific fields of a struct or union variant.
|
||||
pub(crate) fn field_visibilities_query(
|
||||
db: &dyn DefDatabase,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
//! Builtin derives.
|
||||
|
||||
use base_db::{CrateOrigin, LangCrateOrigin};
|
||||
use itertools::izip;
|
||||
use rustc_hash::FxHashSet;
|
||||
use span::{MacroCallId, Span};
|
||||
|
|
@ -10,6 +9,7 @@ use tracing::debug;
|
|||
use crate::{
|
||||
hygiene::span_with_def_site_ctxt,
|
||||
name::{AsName, Name},
|
||||
quote::dollar_crate,
|
||||
span_map::SpanMapRef,
|
||||
tt,
|
||||
};
|
||||
|
|
@ -38,7 +38,7 @@ macro_rules! register_builtin {
|
|||
|
||||
let span = db.lookup_intern_macro_call(id).call_site;
|
||||
let span = span_with_def_site_ctxt(db, span, id);
|
||||
expander(db, id, span, tt, token_map)
|
||||
expander(span, tt, token_map)
|
||||
}
|
||||
|
||||
fn find_by_name(name: &name::Name) -> Option<Self> {
|
||||
|
|
@ -398,41 +398,13 @@ fn expand_simple_derive(
|
|||
ExpandResult::ok(expanded)
|
||||
}
|
||||
|
||||
fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId, span: Span) -> tt::TokenTree {
|
||||
// FIXME: make hygiene works for builtin derive macro
|
||||
// such that $crate can be used here.
|
||||
let cg = db.crate_graph();
|
||||
let krate = db.lookup_intern_macro_call(id).krate;
|
||||
|
||||
let tt = if matches!(cg[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core)) {
|
||||
cov_mark::hit!(test_copy_expand_in_core);
|
||||
quote! {span => crate }
|
||||
} else {
|
||||
quote! {span => core }
|
||||
};
|
||||
|
||||
tt.token_trees[0].clone()
|
||||
}
|
||||
|
||||
fn copy_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let krate = find_builtin_crate(db, id, span);
|
||||
fn copy_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
let krate = dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
|
||||
}
|
||||
|
||||
fn clone_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let krate = find_builtin_crate(db, id, span);
|
||||
fn clone_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
let krate = dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::clone::Clone }, |adt| {
|
||||
if matches!(adt.shape, AdtShape::Union) {
|
||||
let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
|
||||
|
|
@ -482,14 +454,8 @@ fn and_and(span: Span) -> tt::Subtree {
|
|||
quote! {span => #and& }
|
||||
}
|
||||
|
||||
fn default_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &find_builtin_crate(db, id, span);
|
||||
fn default_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::default::Default }, |adt| {
|
||||
let body = match &adt.shape {
|
||||
AdtShape::Struct(fields) => {
|
||||
|
|
@ -527,14 +493,8 @@ fn default_expand(
|
|||
})
|
||||
}
|
||||
|
||||
fn debug_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &find_builtin_crate(db, id, span);
|
||||
fn debug_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::fmt::Debug }, |adt| {
|
||||
let for_variant = |name: String, v: &VariantShape| match v {
|
||||
VariantShape::Struct(fields) => {
|
||||
|
|
@ -605,14 +565,8 @@ fn debug_expand(
|
|||
})
|
||||
}
|
||||
|
||||
fn hash_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &find_builtin_crate(db, id, span);
|
||||
fn hash_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::hash::Hash }, |adt| {
|
||||
if matches!(adt.shape, AdtShape::Union) {
|
||||
// FIXME: Return expand error here
|
||||
|
|
@ -658,25 +612,13 @@ fn hash_expand(
|
|||
})
|
||||
}
|
||||
|
||||
fn eq_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let krate = find_builtin_crate(db, id, span);
|
||||
fn eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
let krate = dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
|
||||
}
|
||||
|
||||
fn partial_eq_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let krate = find_builtin_crate(db, id, span);
|
||||
fn partial_eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
let krate = dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialEq }, |adt| {
|
||||
if matches!(adt.shape, AdtShape::Union) {
|
||||
// FIXME: Return expand error here
|
||||
|
|
@ -747,17 +689,11 @@ fn self_and_other_patterns(
|
|||
(self_patterns, other_patterns)
|
||||
}
|
||||
|
||||
fn ord_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &find_builtin_crate(db, id, span);
|
||||
fn ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Ord }, |adt| {
|
||||
fn compare(
|
||||
krate: &tt::TokenTree,
|
||||
krate: &tt::Ident,
|
||||
left: tt::Subtree,
|
||||
right: tt::Subtree,
|
||||
rest: tt::Subtree,
|
||||
|
|
@ -811,17 +747,11 @@ fn ord_expand(
|
|||
})
|
||||
}
|
||||
|
||||
fn partial_ord_expand(
|
||||
db: &dyn ExpandDatabase,
|
||||
id: MacroCallId,
|
||||
span: Span,
|
||||
tt: &ast::Adt,
|
||||
tm: SpanMapRef<'_>,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &find_builtin_crate(db, id, span);
|
||||
fn partial_ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
|
||||
let krate = &dollar_crate(span);
|
||||
expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialOrd }, |adt| {
|
||||
fn compare(
|
||||
krate: &tt::TokenTree,
|
||||
krate: &tt::Ident,
|
||||
left: tt::Subtree,
|
||||
right: tt::Subtree,
|
||||
rest: tt::Subtree,
|
||||
|
|
|
|||
|
|
@ -6,18 +6,16 @@ use either::Either;
|
|||
use itertools::Itertools;
|
||||
use mbe::{parse_exprs_with_sep, parse_to_token_tree};
|
||||
use span::{Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
|
||||
use syntax::{
|
||||
ast::{self, AstToken},
|
||||
SmolStr,
|
||||
};
|
||||
use syntax::ast::{self, AstToken};
|
||||
|
||||
use crate::{
|
||||
db::ExpandDatabase,
|
||||
hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt},
|
||||
name::{self, known},
|
||||
quote,
|
||||
quote::dollar_crate,
|
||||
tt::{self, DelimSpan},
|
||||
ExpandError, ExpandResult, HirFileIdExt, MacroCallId,
|
||||
ExpandError, ExpandResult, HirFileIdExt, MacroCallId, MacroFileIdExt,
|
||||
};
|
||||
|
||||
macro_rules! register_builtin {
|
||||
|
|
@ -205,7 +203,7 @@ fn assert_expand(
|
|||
) -> ExpandResult<tt::Subtree> {
|
||||
let call_site_span = span_with_call_site_ctxt(db, span, id);
|
||||
let args = parse_exprs_with_sep(tt, ',', call_site_span);
|
||||
let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span };
|
||||
let dollar_crate = dollar_crate(span);
|
||||
let expanded = match &*args {
|
||||
[cond, panic_args @ ..] => {
|
||||
let comma = tt::Subtree {
|
||||
|
|
@ -300,7 +298,7 @@ fn asm_expand(
|
|||
[tt::TokenTree::Leaf(tt::Leaf::Literal(lit))]
|
||||
| [tt::TokenTree::Leaf(tt::Leaf::Literal(lit)), tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', span: _, spacing: _ }))] =>
|
||||
{
|
||||
let dollar_krate = tt::Ident { text: SmolStr::new_inline("$crate"), span };
|
||||
let dollar_krate = dollar_crate(span);
|
||||
literals.push(quote!(span=>#dollar_krate::format_args!(#lit);));
|
||||
}
|
||||
_ => break,
|
||||
|
|
@ -345,7 +343,7 @@ fn panic_expand(
|
|||
tt: &tt::Subtree,
|
||||
span: Span,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span };
|
||||
let dollar_crate = dollar_crate(span);
|
||||
let call_site_span = span_with_call_site_ctxt(db, span, id);
|
||||
|
||||
let mac =
|
||||
|
|
@ -371,7 +369,7 @@ fn unreachable_expand(
|
|||
tt: &tt::Subtree,
|
||||
span: Span,
|
||||
) -> ExpandResult<tt::Subtree> {
|
||||
let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span };
|
||||
let dollar_crate = dollar_crate(span);
|
||||
let call_site_span = span_with_call_site_ctxt(db, span, id);
|
||||
|
||||
let mac = if use_panic_2021(db, call_site_span) {
|
||||
|
|
@ -611,7 +609,7 @@ fn relative_file(
|
|||
path_str: &str,
|
||||
allow_recursion: bool,
|
||||
) -> Result<FileId, ExpandError> {
|
||||
let call_site = call_id.as_file().original_file(db);
|
||||
let call_site = call_id.as_macro_file().parent(db).original_file_respecting_includes(db);
|
||||
let path = AnchoredPath { anchor: call_site, path: path_str };
|
||||
let res = db
|
||||
.resolve_path(path)
|
||||
|
|
@ -763,10 +761,10 @@ fn option_env_expand(
|
|||
return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e)
|
||||
}
|
||||
};
|
||||
// FIXME: Use `DOLLAR_CRATE` when that works in eager macros.
|
||||
let dollar_crate = dollar_crate(span);
|
||||
let expanded = match get_env_inner(db, arg_id, &key) {
|
||||
None => quote! {span => ::core::option::Option::None::<&str> },
|
||||
Some(s) => quote! {span => ::core::option::Option::Some(#s) },
|
||||
None => quote! {span => #dollar_crate::option::Option::None::<&str> },
|
||||
Some(s) => quote! {span => #dollar_crate::option::Option::Some(#s) },
|
||||
};
|
||||
|
||||
ExpandResult::ok(expanded)
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ pub trait MacroFileIdExt {
|
|||
fn expansion_level(self, db: &dyn ExpandDatabase) -> u32;
|
||||
/// If this is a macro call, returns the syntax node of the call.
|
||||
fn call_node(self, db: &dyn ExpandDatabase) -> InFile<SyntaxNode>;
|
||||
fn parent(self, db: &dyn ExpandDatabase) -> HirFileId;
|
||||
|
||||
fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo;
|
||||
|
||||
|
|
@ -353,6 +354,9 @@ impl MacroFileIdExt for MacroFileId {
|
|||
};
|
||||
}
|
||||
}
|
||||
fn parent(self, db: &dyn ExpandDatabase) -> HirFileId {
|
||||
self.macro_call_id.lookup(db).kind.file_id()
|
||||
}
|
||||
|
||||
/// Return expansion information if it is a macro-expansion file
|
||||
fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ use span::Span;
|
|||
|
||||
use crate::name::Name;
|
||||
|
||||
pub(crate) fn dollar_crate(span: Span) -> tt::Ident<Span> {
|
||||
tt::Ident { text: syntax::SmolStr::new_inline("$crate"), span }
|
||||
}
|
||||
|
||||
// A helper macro quote macro
|
||||
// FIXME:
|
||||
// 1. Not all puncts are handled
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ nohash-hasher.workspace = true
|
|||
typed-arena = "2.0.1"
|
||||
indexmap.workspace = true
|
||||
|
||||
rustc-dependencies.workspace = true
|
||||
ra-ap-rustc_abi.workspace = true
|
||||
ra-ap-rustc_index.workspace = true
|
||||
|
||||
|
||||
# local deps
|
||||
stdx.workspace = true
|
||||
|
|
@ -58,7 +60,7 @@ test-utils.workspace = true
|
|||
test-fixture.workspace = true
|
||||
|
||||
[features]
|
||||
in-rust-tree = ["rustc-dependencies/in-rust-tree"]
|
||||
in-rust-tree = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
|
|||
}
|
||||
});
|
||||
})
|
||||
.map(|block_id| self.db.trait_impls_in_block(block_id));
|
||||
.filter_map(|block_id| self.db.trait_impls_in_block(block_id));
|
||||
|
||||
let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db);
|
||||
let mut result = vec![];
|
||||
|
|
@ -183,7 +183,8 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
|
|||
def_blocks
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.for_each(|it| f(&self.db.trait_impls_in_block(it)));
|
||||
.filter_map(|it| self.db.trait_impls_in_block(it))
|
||||
.for_each(|it| f(&it));
|
||||
}
|
||||
fps => {
|
||||
let mut f =
|
||||
|
|
@ -198,7 +199,8 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
|
|||
def_blocks
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.for_each(|it| f(&self.db.trait_impls_in_block(it)));
|
||||
.filter_map(|it| self.db.trait_impls_in_block(it))
|
||||
.for_each(|it| f(&it));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
|||
#[salsa::invoke(crate::infer::infer_query)]
|
||||
fn infer_query(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
|
||||
|
||||
// region:mir
|
||||
|
||||
#[salsa::invoke(crate::mir::mir_body_query)]
|
||||
#[salsa::cycle(crate::mir::mir_body_recover)]
|
||||
fn mir_body(&self, def: DefWithBodyId) -> Result<Arc<MirBody>, MirLowerError>;
|
||||
|
|
@ -61,20 +63,6 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
|||
#[salsa::invoke(crate::mir::borrowck_query)]
|
||||
fn borrowck(&self, def: DefWithBodyId) -> Result<Arc<[BorrowckResult]>, MirLowerError>;
|
||||
|
||||
#[salsa::invoke(crate::lower::ty_query)]
|
||||
#[salsa::cycle(crate::lower::ty_recover)]
|
||||
fn ty(&self, def: TyDefId) -> Binders<Ty>;
|
||||
|
||||
#[salsa::invoke(crate::lower::value_ty_query)]
|
||||
fn value_ty(&self, def: ValueTyDefId) -> Binders<Ty>;
|
||||
|
||||
#[salsa::invoke(crate::lower::impl_self_ty_query)]
|
||||
#[salsa::cycle(crate::lower::impl_self_ty_recover)]
|
||||
fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
|
||||
|
||||
#[salsa::invoke(crate::lower::const_param_ty_query)]
|
||||
fn const_param_ty(&self, def: ConstParamId) -> Ty;
|
||||
|
||||
#[salsa::invoke(crate::consteval::const_eval_query)]
|
||||
#[salsa::cycle(crate::consteval::const_eval_recover)]
|
||||
fn const_eval(
|
||||
|
|
@ -92,6 +80,22 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
|||
#[salsa::cycle(crate::consteval::const_eval_discriminant_recover)]
|
||||
fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>;
|
||||
|
||||
// endregion:mir
|
||||
|
||||
#[salsa::invoke(crate::lower::ty_query)]
|
||||
#[salsa::cycle(crate::lower::ty_recover)]
|
||||
fn ty(&self, def: TyDefId) -> Binders<Ty>;
|
||||
|
||||
#[salsa::invoke(crate::lower::value_ty_query)]
|
||||
fn value_ty(&self, def: ValueTyDefId) -> Binders<Ty>;
|
||||
|
||||
#[salsa::invoke(crate::lower::impl_self_ty_query)]
|
||||
#[salsa::cycle(crate::lower::impl_self_ty_recover)]
|
||||
fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
|
||||
|
||||
#[salsa::invoke(crate::lower::const_param_ty_query)]
|
||||
fn const_param_ty(&self, def: ConstParamId) -> Ty;
|
||||
|
||||
#[salsa::invoke(crate::lower::impl_trait_query)]
|
||||
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
|
||||
|
||||
|
|
@ -158,7 +162,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
|||
fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>;
|
||||
|
||||
#[salsa::invoke(InherentImpls::inherent_impls_in_block_query)]
|
||||
fn inherent_impls_in_block(&self, block: BlockId) -> Arc<InherentImpls>;
|
||||
fn inherent_impls_in_block(&self, block: BlockId) -> Option<Arc<InherentImpls>>;
|
||||
|
||||
/// Collects all crates in the dependency graph that have impls for the
|
||||
/// given fingerprint. This is only used for primitive types and types
|
||||
|
|
@ -175,7 +179,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
|||
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
|
||||
|
||||
#[salsa::invoke(TraitImpls::trait_impls_in_block_query)]
|
||||
fn trait_impls_in_block(&self, block: BlockId) -> Arc<TraitImpls>;
|
||||
fn trait_impls_in_block(&self, block: BlockId) -> Option<Arc<TraitImpls>>;
|
||||
|
||||
#[salsa::invoke(TraitImpls::trait_impls_in_deps_query)]
|
||||
fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<[Arc<TraitImpls>]>;
|
||||
|
|
|
|||
|
|
@ -1629,7 +1629,7 @@ pub fn write_visibility(
|
|||
) -> Result<(), HirDisplayError> {
|
||||
match vis {
|
||||
Visibility::Public => write!(f, "pub "),
|
||||
Visibility::Module(vis_id) => {
|
||||
Visibility::Module(vis_id, _) => {
|
||||
let def_map = module_id.def_map(f.db.upcast());
|
||||
let root_module_id = def_map.module_id(DefMap::ROOT);
|
||||
if vis_id == module_id {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,9 @@ use hir_def::{
|
|||
LocalEnumVariantId, LocalFieldId, StructId,
|
||||
};
|
||||
use la_arena::{Idx, RawIdx};
|
||||
use rustc_dependencies::{
|
||||
abi::AddressSpace,
|
||||
index::{IndexSlice, IndexVec},
|
||||
};
|
||||
use rustc_abi::AddressSpace;
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
|
||||
use stdx::never;
|
||||
use triomphe::Arc;
|
||||
|
||||
|
|
@ -35,7 +34,7 @@ mod target;
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct RustcEnumVariantIdx(pub LocalEnumVariantId);
|
||||
|
||||
impl rustc_dependencies::index::Idx for RustcEnumVariantIdx {
|
||||
impl rustc_index::Idx for RustcEnumVariantIdx {
|
||||
fn new(idx: usize) -> Self {
|
||||
RustcEnumVariantIdx(Idx::from_raw(RawIdx::from(idx as u32)))
|
||||
}
|
||||
|
|
@ -54,7 +53,7 @@ impl RustcFieldIdx {
|
|||
}
|
||||
}
|
||||
|
||||
impl rustc_dependencies::index::Idx for RustcFieldIdx {
|
||||
impl rustc_index::Idx for RustcFieldIdx {
|
||||
fn new(idx: usize) -> Self {
|
||||
RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use hir_def::{
|
|||
AdtId, EnumVariantId, LocalEnumVariantId, VariantId,
|
||||
};
|
||||
use la_arena::RawIdx;
|
||||
use rustc_dependencies::index::IndexVec;
|
||||
use rustc_index::IndexVec;
|
||||
use smallvec::SmallVec;
|
||||
use triomphe::Arc;
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ fn check_fail(ra_fixture: &str, e: LayoutError) {
|
|||
macro_rules! size_and_align {
|
||||
(minicore: $($x:tt),*;$($t:tt)*) => {
|
||||
{
|
||||
#[allow(dead_code)]
|
||||
#![allow(dead_code)]
|
||||
$($t)*
|
||||
check_size_and_align(
|
||||
stringify!($($t)*),
|
||||
|
|
@ -130,7 +130,7 @@ macro_rules! size_and_align {
|
|||
};
|
||||
($($t:tt)*) => {
|
||||
{
|
||||
#[allow(dead_code)]
|
||||
#![allow(dead_code)]
|
||||
$($t)*
|
||||
check_size_and_align(
|
||||
stringify!($($t)*),
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue