Look at this beauty:
```rust
error: unresolved link to `S::h`
--> intra-link-errors.rs:51:6
|
51 | /// [type@S::h]
| ^^^^^^^^^ help: to link to the associated function, use its disambiguator: `S::h()`
|
= note: this link resolves to the associated function `h`, which is not in the type namespace
```
/// This is used to store the kind of associated items,
/// because `clean` and the disambiguator code expect them to be different.
/// See the code for associated items on inherent impls for details.
/// This is used to store the kind of associated items,
/// because `clean` and the disambiguator code expect them to be different.
/// See the code for associated items on inherent impls for details.
- kind_side_channel: Cell<Option<DefKind>>,
+ kind_side_channel: Cell<Option<(DefKind, DefId)>>,
}
impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
}
impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
) => {
debug!("looking for associated item named {} for item {:?}", item_name, did);
// Checks if item_name belongs to `impl SomeItem`
) => {
debug!("looking for associated item named {} for item {:?}", item_name, did);
// Checks if item_name belongs to `impl SomeItem`
.tcx
.inherent_impls(did)
.iter()
.tcx
.inherent_impls(did)
.iter()
+ .map(|item| (item.kind, item.def_id))
// There should only ever be one associated item that matches from any inherent impl
.next()
// Check if item_name belongs to `impl SomeTrait for SomeItem`
// There should only ever be one associated item that matches from any inherent impl
.next()
// Check if item_name belongs to `impl SomeTrait for SomeItem`
- if let Some(kind) = kind {
+ if let Some((kind, id)) = assoc_item {
let out = match kind {
ty::AssocKind::Fn => "method",
ty::AssocKind::Const => "associatedconstant",
let out = match kind {
ty::AssocKind::Fn => "method",
ty::AssocKind::Const => "associatedconstant",
// HACK(jynelson): `clean` expects the type, not the associated item.
// but the disambiguator logic expects the associated item.
// Store the kind in a side channel so that only the disambiguator logic looks at it.
// HACK(jynelson): `clean` expects the type, not the associated item.
// but the disambiguator logic expects the associated item.
// Store the kind in a side channel so that only the disambiguator logic looks at it.
- self.kind_side_channel.set(Some(kind.as_def_kind()));
+ self.kind_side_channel.set(Some((kind.as_def_kind(), id)));
Ok((ty_res, Some(format!("{}.{}", out, item_name))))
})
} else if ns == Namespace::ValueNS {
Ok((ty_res, Some(format!("{}.{}", out, item_name))))
})
} else if ns == Namespace::ValueNS {
item_name: Symbol,
ns: Namespace,
cx: &DocContext<'_>,
item_name: Symbol,
ns: Namespace,
cx: &DocContext<'_>,
-) -> Option<ty::AssocKind> {
+) -> Option<(ty::AssocKind, DefId)> {
let ty = cx.tcx.type_of(did);
// First consider automatic impls: `impl From<T> for T`
let implicit_impls = crate::clean::get_auto_trait_and_blanket_impls(cx, ty, did);
let ty = cx.tcx.type_of(did);
// First consider automatic impls: `impl From<T> for T`
let implicit_impls = crate::clean::get_auto_trait_and_blanket_impls(cx, ty, did);
// but provided methods come directly from `tcx`.
// Fortunately, we don't need the whole method, we just need to know
// what kind of associated item it is.
// but provided methods come directly from `tcx`.
// Fortunately, we don't need the whole method, we just need to know
// what kind of associated item it is.
- Some((assoc.def_id, kind))
+ Some((kind, assoc.def_id))
});
let assoc = items.next();
debug_assert_eq!(items.count(), 0);
});
let assoc = items.next();
debug_assert_eq!(items.count(), 0);
- .map(|assoc| (assoc.def_id, assoc.kind))
+ .map(|assoc| (assoc.kind, assoc.def_id))
}
}
_ => panic!("get_impls returned something that wasn't an impl"),
}
}
_ => panic!("get_impls returned something that wasn't an impl"),
cx.tcx
.associated_items(trait_)
.find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, trait_)
cx.tcx
.associated_items(trait_)
.find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, trait_)
- .map(|assoc| (assoc.def_id, assoc.kind))
+ .map(|assoc| (assoc.kind, assoc.def_id))
}));
}
// FIXME: warn about ambiguity
debug!("the candidates were {:?}", candidates);
}));
}
// FIXME: warn about ambiguity
debug!("the candidates were {:?}", candidates);
- candidates.pop().map(|(_, kind)| kind)
}
/// Given a type, return all traits in scope in `module` implemented by that type.
}
/// Given a type, return all traits in scope in `module` implemented by that type.
// used for reporting better errors
let check_full_res = |this: &mut Self, ns| {
// used for reporting better errors
let check_full_res = |this: &mut Self, ns| {
- match this.resolve(path_str, ns, ¤t_item, base_node, &extra_fragment) {
- Ok(res) => {
- debug!(
- "check_full_res: saw res for {} in {:?} ns: {:?}",
- path_str, ns, res.0
- );
- Some(res.0)
- }
- Err(ErrorKind::Resolve(kind)) => kind.full_res(),
- // TODO: add `Res` to AnchorFailure
- Err(ErrorKind::AnchorFailure(_)) => None,
- }
+ let res =
+ match this.resolve(path_str, ns, ¤t_item, base_node, &extra_fragment)
+ {
+ Ok(res) => {
+ debug!(
+ "check_full_res: saw res for {} in {:?} ns: {:?}",
+ path_str, ns, res.0
+ );
+ Some(res.0)
+ }
+ Err(ErrorKind::Resolve(kind)) => kind.full_res(),
+ // TODO: add `Res` to AnchorFailure
+ Err(ErrorKind::AnchorFailure(_)) => None,
+ };
+ this.kind_side_channel.take().map(|(kind, id)| Res::Def(kind, id)).or(res)
};
match disambiguator.map(Disambiguator::ns) {
};
match disambiguator.map(Disambiguator::ns) {
if kind.full_res().is_none() {
let other_ns = if ns == ValueNS { TypeNS } else { ValueNS };
if let Some(res) = check_full_res(self, other_ns) {
if kind.full_res().is_none() {
let other_ns = if ns == ValueNS { TypeNS } else { ValueNS };
if let Some(res) = check_full_res(self, other_ns) {
- kind = ResolutionFailure::WrongNamespace(res, other_ns);
+ // recall that this stores the _expected_ namespace
+ kind = ResolutionFailure::WrongNamespace(res, ns);
// Disallow e.g. linking to enums with `struct@`
if let Res::Def(kind, _) = res {
debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
// Disallow e.g. linking to enums with `struct@`
if let Res::Def(kind, _) = res {
debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
- match (self.kind_side_channel.take().unwrap_or(kind), disambiguator) {
+ match (self.kind_side_channel.take().map(|(kind, _)| kind).unwrap_or(kind), disambiguator) {
| (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
// NOTE: this allows 'method' to mean both normal functions and associated functions
// This can't cause ambiguity because both are in the same namespace.
| (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
// NOTE: this allows 'method' to mean both normal functions and associated functions
// This can't cause ambiguity because both are in the same namespace.
pub enum E { A, B, C }
/// [type@S::h]
pub enum E { A, B, C }
/// [type@S::h]
+//~^ ERROR unresolved link
+//~| HELP to link to the associated function
+//~| NOTE not in the type namespace
impl S {
pub fn h() {}
}
/// [type@T::g]
impl S {
pub fn h() {}
}
/// [type@T::g]
+//~^ ERROR unresolved link
+//~| HELP to link to the associated function
+//~| NOTE not in the type namespace
+
/// [T::h!]
pub trait T {
fn g() {}
/// [T::h!]
pub trait T {
fn g() {}
--> $DIR/intra-link-errors.rs:41:6
|
LL | /// [S!]
--> $DIR/intra-link-errors.rs:41:6
|
LL | /// [S!]
- | ^^ help: to link to the unit struct, use its disambiguator: `value@S`
+ | ^^ help: to link to the struct, use its disambiguator: `struct@S`
- = note: this link resolves to the unit struct `S`, which is not in the macro namespace
+ = note: this link resolves to the struct `S`, which is not in the macro namespace
error: unresolved link to `T::g`
error: unresolved link to `T::g`
- --> $DIR/intra-link-errors.rs:56:6
+ --> $DIR/intra-link-errors.rs:59:6
+ | ^^^^^^^^^ help: to link to the associated function, use its disambiguator: `T::g()`
- = note: this link partially resolves to the trait `T`
- = note: `T` has no field, variant, or associated item named `g`
+ = note: this link resolves to the associated function `g`, which is not in the type namespace
+
+error: unresolved link to `T::h`
+ --> $DIR/intra-link-errors.rs:64:6
+ |
+LL | /// [T::h!]
+ | ^^^^^
+ |
+ = note: no item named `T::h` is in scope
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: unresolved link to `S::h`
--> $DIR/intra-link-errors.rs:51:6
|
LL | /// [type@S::h]
error: unresolved link to `S::h`
--> $DIR/intra-link-errors.rs:51:6
|
LL | /// [type@S::h]
+ | ^^^^^^^^^ help: to link to the associated function, use its disambiguator: `S::h()`
- = note: this link partially resolves to the struct `S`
- = note: `S` has no field, variant, or associated item named `h`
+ = note: this link resolves to the associated function `h`, which is not in the type namespace
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors