Change:
I tried to document this code: I expected to see this happen: charstd::char` points to module page of char type points to char primitive page Instead, this happened: type points to module page of char :
I think the problem is that modules are in the type namespace, so is doing exactly what you are asking it for (the module, since it has higher priority). Since the built-in types scope is the lowest precedence, perhaps there needs to be a way to access it directly? Maybe something like or ? Or maybe should skip over modules, and keep looking deeper in the scope hierarchy? (cc )
Oh hmm I see what you mean. There are : Types, values, and macros. Since modules and types are in the same namespace, it uses the first one it finds. Maybe we could work around this by first resolving in an empty module (so it has nothing in scope), then only falling back to the current scope if we don't find something there?
I'm surprised this hasn't caused trouble before now. Does the root of never use the primitive?
I don't know how it works, but the resolver is smart enough to know that in a type context won't match a module (like , the won't match a module named "char". Maybe it has something to do with late-resolution  which has a to give it some context?
Adding that would be more of area ... I can give it a shot though.
It looks like doesn't even return a resolution and only records it for later use ... I'm going to go with the empty module workaround and we can fix it later if it turns out to cause issues.
The double resolve seems hacky. We could probably make type@ specifically not resolve to a module, perhaps? Also, note that modules are in all namespaces
How would that work? We could skip any module resolutions, but since modules have precedence over types I don't know how we'd get the primitive type to resolve afterwards.
Oh hold on we have a function already. We can look at directly.
This doesn't have anything to do with primitives, this has to do with glob imports vs non-glob imports. You can get the same issue with the following:
This also doesn't have to do with modules being "resolved first" or anything. Things that are non-glob in-scope are resolved first.
Actually, my bad: This does have to do with primitives in the sense that primitives are the only thing that still work when shadowed because of some special code in checking the primitive tables. I think when the string matches one of the primitive table entries for TypeNS lookups that were explicitly annotated with type@ and resolve to a module we can hack this in. In the future we might want to tighten up this code so that e.g. can't resolve to an enum, etc.
do you mind if I fix at the same time and resolve primitives even before modules? That seems like the less surprising behavior to me, the module can still be disambiguated with .
I'm a bit wary of doing this because having the char module in scope is not a common situation, and it will get weirder for people who have a different char module. I think we should resolve to whatever is in scope, but if is explicitly mentioned we can then force resolve to the primitive.

Discussion:
fn resolve( &self, path_str: &str, <ins> disambiguator: Option<&str>, </ins> ns: Namespace, current_item: &Option<String>, parent_id: Option<hir::HirId>,

} return Ok((res, Some(path_str.to_owned()))); } <del> other => { debug!( "failed to resolve {} in namespace {:?} (got {:?})", path_str, ns, other ); </del> <ins> Res::Def(DefKind::Mod, _) => { // This resolved to a module, but if we were passed `type@`, // we want primitive types to take precedence instead. if disambiguator == Some("type") { if let Some(prim) = is_primitive(path_str, ns) { if extra_fragment.is_some() { return Err(ErrorKind::AnchorFailure( "primitive types cannot be followed by anchors", )); } return Ok((prim, Some(path_str.to_owned()))); } } return Ok((res, extra_fragment.clone())); } _ => { </ins> return Ok((res, extra_fragment.clone())); } };

let mut path_str; let (res, fragment) = { let mut kind = None; <ins> let mut disambiguator = None; </ins> path_str = if let Some(prefix) = ["struct@", "enum@", "type@", "trait@", "union@"] .iter() .find(|p| link.starts_with(**p)) { kind = Some(TypeNS); <ins> disambiguator = Some(&prefix[..prefix.len() - 1]); </ins> link.trim_start_matches(prefix) } else if let Some(prefix) = [ "const@",

.find(|p| link.starts_with(**p)) { kind = Some(ValueNS); <ins> disambiguator = Some(&prefix[..prefix.len() - 1]); </ins> link.trim_start_matches(prefix) } else if link.ends_with("()") { kind = Some(ValueNS); <ins> disambiguator = Some("fn"); </ins> link.trim_end_matches("()") } else if link.starts_with("macro@") { kind = Some(MacroNS); <ins> disambiguator = Some("macro"); </ins> link.trim_start_matches("macro@") } else if link.starts_with("derive@") { kind = Some(MacroNS); <ins> disambiguator = Some("derive"); </ins> link.trim_start_matches("derive@") } else if link.ends_with('!') { kind = Some(MacroNS); <ins> disambiguator = Some("macro"); </ins> link.trim_end_matches('!') } else { &link[..]

Some(ns @ ValueNS) => { match self.resolve( path_str, <ins> disambiguator, </ins> ns, &current_item, base_node,

Some(ns @ TypeNS) => { match self.resolve( path_str, <ins> disambiguator, </ins> ns, &current_item, base_node,

.map(|res| (res, extra_fragment.clone())), type_ns: match self.resolve( path_str, <ins> disambiguator, </ins> TypeNS, &current_item, base_node,

}, value_ns: match self.resolve( path_str, <ins> disambiguator, </ins> ValueNS, &current_item, base_node,

<ins> // ignore-tidy-linelength #![deny(intra_doc_resolution_failure)] pub mod char {} /// See also [type@char] // @has intra_link_prim_precedence/struct.MyString.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html' pub struct MyString; /// See also [char] // @has intra_link_prim_precedence/struct.MyString2.html '//a/@href' 'intra_link_prim_precedence/char/index.html' pub struct MyString2; </ins>