-
Notifications
You must be signed in to change notification settings - Fork 13.3k
collect doc alias as tips during resolution #127721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -11,6 +11,7 @@ use rustc_ast::{ | |||||
Item, ItemKind, MethodCall, NodeId, Path, Ty, TyKind, | ||||||
}; | ||||||
use rustc_ast_pretty::pprust::where_bound_predicate_to_string; | ||||||
use rustc_attr::collect_doc_alias_symbol_from_attrs; | ||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; | ||||||
use rustc_errors::codes::*; | ||||||
use rustc_errors::{ | ||||||
|
@@ -40,7 +41,7 @@ use crate::late::{ | |||||
}; | ||||||
use crate::ty::fast_reject::SimplifiedType; | ||||||
use crate::{ | ||||||
Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Segment, errors, | ||||||
Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, Segment, errors, | ||||||
path_names_to_string, | ||||||
}; | ||||||
|
||||||
|
@@ -459,6 +460,18 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { | |||||
return (err, Vec::new()); | ||||||
} | ||||||
|
||||||
if let Some(did) = self.lookup_doc_alias_name(path, source.namespace()) { | ||||||
err.span_label( | ||||||
self.r.def_span(did), | ||||||
format!( | ||||||
"`{}` has a name defined in the doc alias attribute as `{}`", | ||||||
self.r.tcx.item_name(did), | ||||||
path.last().unwrap().ident.as_str() | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
), | ||||||
); | ||||||
return (err, Vec::new()); | ||||||
}; | ||||||
|
||||||
let (found, mut candidates) = self.try_lookup_name_relaxed( | ||||||
&mut err, | ||||||
source, | ||||||
|
@@ -783,6 +796,50 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { | |||||
(false, candidates) | ||||||
} | ||||||
|
||||||
fn lookup_doc_alias_name(&mut self, path: &[Segment], ns: Namespace) -> Option<DefId> { | ||||||
let item_str = path.last().unwrap().ident; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
let find_doc_alias_name = |r: &mut Resolver<'ra, '_>, m: Module<'ra>| { | ||||||
for resolution in r.resolutions(m).borrow().values() { | ||||||
let Some(did) = | ||||||
resolution.borrow().binding.and_then(|binding| binding.res().opt_def_id()) | ||||||
else { | ||||||
continue; | ||||||
}; | ||||||
if did.is_local() { | ||||||
// We don't record the doc alias name in the local crate | ||||||
// because the people who write doc alias are usually not | ||||||
// confused by them. | ||||||
continue; | ||||||
} | ||||||
let symbols = collect_doc_alias_symbol_from_attrs(r.tcx.get_attrs(did, sym::doc)); | ||||||
if symbols.contains(&item_str.name) { | ||||||
return Some(did); | ||||||
} | ||||||
} | ||||||
None | ||||||
}; | ||||||
|
||||||
if path.len() == 1 { | ||||||
for rib in self.ribs[ns].iter().rev() { | ||||||
if let RibKind::Module(module) = rib.kind | ||||||
&& let Some(did) = find_doc_alias_name(self.r, module) | ||||||
{ | ||||||
return Some(did); | ||||||
} | ||||||
} | ||||||
} else { | ||||||
let mod_path = &path[..path.len() - 1]; | ||||||
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = | ||||||
self.resolve_path(mod_path, Some(TypeNS), None) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think the logic is right, we are reporting an error for one specific unresolved segment in a path (and it's not necessarily the last one), not for all segments, and all segments before the one unresolved segment should be already resolved and recorded into So
|
||||||
&& let Some(did) = find_doc_alias_name(self.r, module) | ||||||
{ | ||||||
return Some(did); | ||||||
} | ||||||
} | ||||||
None | ||||||
} | ||||||
|
||||||
fn suggest_trait_and_bounds( | ||||||
&mut self, | ||||||
err: &mut Diag<'_>, | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#[doc(alias="DocAliasS1")] | ||
pub struct S1; | ||
|
||
#[doc(alias="DocAliasS2")] | ||
#[doc(alias("DocAliasS3", "DocAliasS4"))] | ||
pub struct S2; | ||
|
||
#[doc(alias("doc_alias_f1", "doc_alias_f2"))] | ||
pub fn f() {} | ||
|
||
pub mod m { | ||
#[doc(alias="DocAliasS5")] | ||
pub struct S5; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
//@ aux-build: use-doc-alias-name-extern.rs | ||
//@ error-pattern: `S1` has a name defined in the doc alias attribute as `DocAliasS1` | ||
//@ error-pattern: `S2` has a name defined in the doc alias attribute as `DocAliasS2` | ||
//@ error-pattern: `S2` has a name defined in the doc alias attribute as `DocAliasS3` | ||
//@ error-pattern: `S2` has a name defined in the doc alias attribute as `DocAliasS4` | ||
//@ error-pattern: `f` has a name defined in the doc alias attribute as `doc_alias_f1` | ||
//@ error-pattern: `f` has a name defined in the doc alias attribute as `doc_alias_f2` | ||
//@ error-pattern: `S5` has a name defined in the doc alias attribute as `DocAliasS5` | ||
|
||
// issue#124273 | ||
|
||
extern crate use_doc_alias_name_extern; | ||
|
||
use use_doc_alias_name_extern::*; | ||
|
||
#[doc(alias="LocalDocAliasS")] | ||
struct S; | ||
|
||
fn main() { | ||
LocalDocAliasS; | ||
//~^ ERROR: cannot find value `LocalDocAliasS` in this scope | ||
DocAliasS1; | ||
//~^ ERROR: cannot find value `DocAliasS1` in this scope | ||
DocAliasS2; | ||
//~^ ERROR: cannot find value `DocAliasS2` in this scope | ||
DocAliasS3; | ||
//~^ ERROR: cannot find value `DocAliasS3` in this scope | ||
DocAliasS4; | ||
//~^ ERROR: cannot find value `DocAliasS4` in this scope | ||
doc_alias_f1(); | ||
//~^ ERROR: cannot find function `doc_alias_f1` in this scope | ||
doc_alias_f2(); | ||
//~^ ERROR: cannot find function `doc_alias_f2` in this scope | ||
m::DocAliasS5; | ||
//~^ ERROR: cannot find value `DocAliasS5` in module `m` | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
error[E0425]: cannot find value `LocalDocAliasS` in this scope | ||
--> $DIR/use-doc-alias-name.rs:20:5 | ||
| | ||
LL | LocalDocAliasS; | ||
| ^^^^^^^^^^^^^^ not found in this scope | ||
|
||
error[E0425]: cannot find value `DocAliasS1` in this scope | ||
--> $DIR/use-doc-alias-name.rs:22:5 | ||
| | ||
LL | DocAliasS1; | ||
| ^^^^^^^^^^ | ||
| | ||
::: $DIR/auxiliary/use-doc-alias-name-extern.rs:2:1 | ||
| | ||
LL | pub struct S1; | ||
| ------------- `S1` has a name defined in the doc alias attribute as `DocAliasS1` | ||
|
||
error[E0425]: cannot find value `DocAliasS2` in this scope | ||
--> $DIR/use-doc-alias-name.rs:24:5 | ||
| | ||
LL | DocAliasS2; | ||
| ^^^^^^^^^^ | ||
| | ||
::: $DIR/auxiliary/use-doc-alias-name-extern.rs:6:1 | ||
| | ||
LL | pub struct S2; | ||
| ------------- `S2` has a name defined in the doc alias attribute as `DocAliasS2` | ||
|
||
error[E0425]: cannot find value `DocAliasS3` in this scope | ||
--> $DIR/use-doc-alias-name.rs:26:5 | ||
| | ||
LL | DocAliasS3; | ||
| ^^^^^^^^^^ | ||
| | ||
::: $DIR/auxiliary/use-doc-alias-name-extern.rs:6:1 | ||
| | ||
LL | pub struct S2; | ||
| ------------- `S2` has a name defined in the doc alias attribute as `DocAliasS3` | ||
|
||
error[E0425]: cannot find value `DocAliasS4` in this scope | ||
--> $DIR/use-doc-alias-name.rs:28:5 | ||
| | ||
LL | DocAliasS4; | ||
| ^^^^^^^^^^ | ||
| | ||
::: $DIR/auxiliary/use-doc-alias-name-extern.rs:6:1 | ||
| | ||
LL | pub struct S2; | ||
| ------------- `S2` has a name defined in the doc alias attribute as `DocAliasS4` | ||
|
||
error[E0425]: cannot find value `DocAliasS5` in module `m` | ||
--> $DIR/use-doc-alias-name.rs:34:8 | ||
| | ||
LL | m::DocAliasS5; | ||
| ^^^^^^^^^^ | ||
| | ||
::: $DIR/auxiliary/use-doc-alias-name-extern.rs:13:5 | ||
| | ||
LL | pub struct S5; | ||
| ------------- `S5` has a name defined in the doc alias attribute as `DocAliasS5` | ||
|
||
error[E0425]: cannot find function `doc_alias_f1` in this scope | ||
--> $DIR/use-doc-alias-name.rs:30:5 | ||
| | ||
LL | doc_alias_f1(); | ||
| ^^^^^^^^^^^^ | ||
| | ||
::: $DIR/auxiliary/use-doc-alias-name-extern.rs:9:1 | ||
| | ||
LL | pub fn f() {} | ||
| ---------- `f` has a name defined in the doc alias attribute as `doc_alias_f1` | ||
|
||
error[E0425]: cannot find function `doc_alias_f2` in this scope | ||
--> $DIR/use-doc-alias-name.rs:32:5 | ||
| | ||
LL | doc_alias_f2(); | ||
| ^^^^^^^^^^^^ | ||
| | ||
::: $DIR/auxiliary/use-doc-alias-name-extern.rs:9:1 | ||
| | ||
LL | pub fn f() {} | ||
| ---------- `f` has a name defined in the doc alias attribute as `doc_alias_f2` | ||
|
||
error: aborting due to 8 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0425`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both calls to this function immediately use
contains(sym)
on the result, so it's probably better to passsym
to here and avoid the collection.