Merge from rustc

This commit is contained in:
The Miri Conjob Bot 2024-01-21 05:45:45 +00:00
commit 3c055f73fe
1101 changed files with 17090 additions and 8617 deletions

View file

@ -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":

View file

@ -37,6 +37,7 @@ static SETTINGS_HASHES: &[&str] = &[
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
];
static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json");

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,4 +1,5 @@
{
"git.detectSubmodulesLimit": 20,
"rust-analyzer.check.invocationLocation": "root",
"rust-analyzer.check.invocationStrategy": "once",
"rust-analyzer.check.overrideCommand": [

View file

@ -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);
}
}

View file

@ -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()
}

View file

@ -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) => {

View file

@ -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

View file

@ -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!?!&amp; -<em>qux</em>-%</a>\
<a class=\"doc-anchor\" href=\"#foo-bar-baz--qux-\">§</a>\
<strong>Foo</strong> <em>bar</em> baz!?!&amp; -<em>qux</em>-%\
</h4>",
);
t(
"#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux",
"<h5 id=\"foo--bar--baz--qux\">\
<a href=\"#foo--bar--baz--qux\"><strong>Foo?</strong> &amp; *bar?!* \
<em><code>baz</code></em> #qux</a>\
<a class=\"doc-anchor\" href=\"#foo--bar--baz--qux\">§</a>\
<strong>Foo?</strong> &amp; *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]

View file

@ -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<'_>,

View file

@ -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());

View file

@ -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;

View file

@ -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,

View file

@ -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

View file

@ -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,
);
}
}
},
);
}
}
}

View file

@ -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()
{

View file

@ -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,

View file

@ -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),

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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),
}
}

View file

@ -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

View file

@ -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()?))

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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"

View file

@ -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 {

View file

@ -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),

View file

@ -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,

View file

@ -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.

View file

@ -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 {

View file

@ -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"),
}
}

View file

@ -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 {

View file

@ -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(_) => {},
}
}

View file

@ -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,
}
}

View file

@ -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);

View file

@ -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 {

View file

@ -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;

View file

@ -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
}

View file

@ -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);
}

View file

@ -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`.

View file

@ -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)]

View file

@ -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"

View file

@ -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 {

View file

@ -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) {}

View file

@ -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 {

View file

@ -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) } {

View file

@ -1,5 +1,4 @@
#![feature(stmt_expr_attributes)]
#![feature(round_ties_even)]
#![feature(float_gamma)]
#![allow(arithmetic_overflow)]

View file

@ -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;

View file

@ -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,

View file

@ -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 {

View file

@ -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 =

View 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"

View file

@ -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"] }

View file

@ -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)

View file

@ -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

View file

@ -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 }
}

View file

@ -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(

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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(

View file

@ -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> {

View file

@ -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},

View file

@ -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.

View file

@ -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);
}
}

View file

@ -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())],

View file

@ -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>]> {

View file

@ -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 "),
};
}

View file

@ -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]

View file

@ -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)]

View file

@ -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,

View file

@ -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>; }
"#]],
);
}

View file

@ -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,

View file

@ -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);
}
}

View file

@ -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(

View file

@ -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)
}

View file

@ -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)
}
}

View file

@ -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,

View file

@ -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,

View file

@ -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)

View file

@ -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 {

View file

@ -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

View file

@ -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

View file

@ -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));
}
}

View file

@ -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>]>;

View file

@ -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 {

View file

@ -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)))
}

View file

@ -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;

View file

@ -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