Skip to content

Commit 6a1a449

Browse files
committed
Error only in the case of overlap
1 parent d44910c commit 6a1a449

File tree

1 file changed

+49
-20
lines changed

1 file changed

+49
-20
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -856,16 +856,16 @@ impl Clean<Attributes> for [ast::Attribute] {
856856
let def = {
857857
let mut kind = PathKind::Unknown;
858858
let path_str = if let Some(prefix) =
859-
["struct", "enum", "type",
860-
"trait", "union"].iter()
859+
["struct@", "enum@", "type@",
860+
"trait@", "union@"].iter()
861861
.find(|p| link.starts_with(**p)) {
862862
kind = PathKind::Type;
863-
link.trim_left_matches(prefix).trim_left_matches('@')
863+
link.trim_left_matches(prefix)
864864
} else if let Some(prefix) =
865-
["const", "static"].iter()
865+
["const@", "static@"].iter()
866866
.find(|p| link.starts_with(**p)) {
867867
kind = PathKind::Value;
868-
link.trim_left_matches(prefix).trim_left_matches('@')
868+
link.trim_left_matches(prefix)
869869
} else if link.ends_with("()") {
870870
kind = PathKind::Value;
871871
link.trim_right_matches("()")
@@ -923,24 +923,53 @@ impl Clean<Attributes> for [ast::Attribute] {
923923
// try both!
924924
// It is imperative we search for not-a-value first
925925
// Otherwise we will find struct ctors for when we are looking
926-
// for structs, etc, and the link won't work.
926+
// for structs, and the link won't work.
927927
if let Ok(path) = resolve(false) {
928+
// if there is something in both namespaces
929+
if let Ok(value_path) = resolve(true) {
930+
let kind = match value_path.def {
931+
// structs and mods exist in both namespaces. skip them
932+
Def::StructCtor(..) | Def::Mod(..) => None,
933+
Def::Variant(..) | Def::VariantCtor(..)
934+
=> Some(("variant", format!("{}()", path_str))),
935+
Def::Fn(..)
936+
=> Some(("function", format!("{}()", path_str))),
937+
Def::Method(..)
938+
=> Some(("method", format!("{}()", path_str))),
939+
Def::Const(..)
940+
=> Some(("const", format!("const@{}", path_str))),
941+
Def::Static(..)
942+
=> Some(("static", format!("static@{}", path_str))),
943+
_ => Some(("value", format!("static@{}", path_str))),
944+
};
945+
if let Some((value_kind, disambig)) = kind {
946+
let (type_kind, article) = match path.def {
947+
// we can still have non-tuple structs
948+
Def::Struct(..) => ("struct", "a"),
949+
Def::Enum(..) => ("enum", "an"),
950+
Def::Trait(..) => ("trait", "a"),
951+
Def::Union(..) => ("union", "a"),
952+
_ => ("type", "a"),
953+
};
954+
let sp = attrs.doc_strings.first()
955+
.map_or(DUMMY_SP, |a| a.span());
956+
cx.sess()
957+
.struct_span_err(sp,
958+
&format!("`{}` is both {} {} and a {}",
959+
path_str, article, type_kind,
960+
value_kind))
961+
.help(&format!("try `{0}` if you want to select the {1}, \
962+
or `{2}@{3}` if you want to \
963+
select the {2}",
964+
disambig, value_kind, type_kind,
965+
path_str))
966+
.emit();
967+
continue;
968+
}
969+
}
928970
path.def
929971
} else if let Ok(path) = resolve(true) {
930-
let kind = match path.def {
931-
Def::Variant(..) | Def::VariantCtor(..) => ("variant", format!("{}()", path_str)),
932-
Def::Fn(..) => ("function", format!("{}()", path_str)),
933-
Def::Method(..) => ("method", format!("{}()", path_str)),
934-
Def::Const(..) => ("const", format!("const@{}", path_str)),
935-
Def::Static(..) => ("static", format!("static@{}", path_str)),
936-
_ => ("value", format!("static@{}", path_str)),
937-
};
938-
let sp = attrs.doc_strings.first().map_or(DUMMY_SP, |a| a.span());
939-
cx.sess().struct_span_err(sp, &format!("could not resolve `{}` as a type, it is a {}",
940-
path_str, kind.0))
941-
.help(&format!("try `{}`", kind.1))
942-
.emit();
943-
continue;
972+
path.def
944973
} else {
945974
// this could just be a normal link
946975
continue;

0 commit comments

Comments
 (0)