From 6421127340047130e546af9dc3afb45643cf692f Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 7 Jan 2020 00:51:00 +0900 Subject: [PATCH 01/15] Update rustc-guide --- src/doc/rustc-guide | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide index b5c6babcdd4ce..92baf7293dd2d 160000 --- a/src/doc/rustc-guide +++ b/src/doc/rustc-guide @@ -1 +1 @@ -Subproject commit b5c6babcdd4ce1fa90458b7827a5fde082e79e87 +Subproject commit 92baf7293dd2d418d2ac4b141b0faa822075d9f7 From 12f029b7eecc01a38fbeec0eebe9041aa1bab7a5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Jan 2020 02:07:13 +0100 Subject: [PATCH 02/15] Fix deref impl on type alias --- src/librustdoc/clean/inline.rs | 18 ++++++++++++ src/librustdoc/clean/mod.rs | 24 ++++++++++++++-- src/librustdoc/clean/types.rs | 8 ++++++ src/librustdoc/html/render.rs | 24 +++++++++++----- src/librustdoc/html/render/cache.rs | 43 +++++++++++++++++------------ 5 files changed, 90 insertions(+), 27 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c7e0f1e9e704b..fc75bf35b250d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -273,6 +273,24 @@ fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef { clean::Typedef { type_: cx.tcx.type_of(did).clean(cx), generics: (cx.tcx.generics_of(did), predicates).clean(cx), + item_type: build_type_alias_type(cx, did), + } +} + +fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option { + let type_ = cx.tcx.type_of(did).clean(cx); + type_.def_id().and_then(|did| build_ty(cx, did)) +} + +pub fn build_ty(cx: &DocContext, did: DefId) -> Option { + match cx.tcx.def_kind(did)? { + DefKind::Struct | + DefKind::Union | + DefKind::Enum | + DefKind::Const | + DefKind::Static => Some(cx.tcx.type_of(did).clean(cx)), + DefKind::TyAlias => build_type_alias_type(cx, did), + _ => None, } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index be9654612f504..0cc4c55f49be8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1122,7 +1122,16 @@ impl Clean for hir::ImplItem<'_> { MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx)) } hir::ImplItemKind::TyAlias(ref ty) => { - TypedefItem(Typedef { type_: ty.clean(cx), generics: Generics::default() }, true) + let type_ = ty.clean(cx); + let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); + TypedefItem( + Typedef { + type_, + generics: Generics::default(), + item_type, + }, + true, + ) } hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem( OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() }, @@ -1282,10 +1291,13 @@ impl Clean for ty::AssocItem { AssocTypeItem(bounds, ty.clean(cx)) } else { + let type_ = cx.tcx.type_of(self.def_id).clean(cx); + let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); TypedefItem( Typedef { - type_: cx.tcx.type_of(self.def_id).clean(cx), + type_, generics: Generics { params: Vec::new(), where_predicates: Vec::new() }, + item_type, }, true, ) @@ -1989,6 +2001,8 @@ impl Clean for ast::Name { impl Clean for doctree::Typedef<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { + let type_ = self.ty.clean(cx); + let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -1998,7 +2012,11 @@ impl Clean for doctree::Typedef<'_> { stability: cx.stability(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx), inner: TypedefItem( - Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx) }, + Typedef { + type_, + generics: self.gen.clean(cx), + item_type, + }, false, ), } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5d8e27ecadb82..79a078ca7a991 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1406,6 +1406,14 @@ pub struct PathSegment { pub struct Typedef { pub type_: Type, pub generics: Generics, + // Type of target item. + pub item_type: Option, +} + +impl GetDefId for Typedef { + fn def_id(&self) -> Option { + self.type_.def_id() + } } #[derive(Clone, Debug)] diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2d932eb7668c4..69e268f3f80c1 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3469,22 +3469,27 @@ fn render_deref_methods( deref_mut: bool, ) { let deref_type = impl_.inner_impl().trait_.as_ref().unwrap(); - let target = impl_ + let (target, real_target) = impl_ .inner_impl() .items .iter() .filter_map(|item| match item.inner { - clean::TypedefItem(ref t, true) => Some(&t.type_), + clean::TypedefItem(ref t, true) => { + Some(match *t { + clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_), + _ => (&t.type_, &t.type_), + }) + } _ => None, }) .next() .expect("Expected associated type binding"); let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target, deref_mut_: deref_mut }; - if let Some(did) = target.def_id() { + if let Some(did) = real_target.def_id() { render_assoc_items(w, cx, container_item, did, what) } else { - if let Some(prim) = target.primitive_type() { + if let Some(prim) = real_target.primitive_type() { if let Some(&did) = cx.cache.primitive_locations.get(&prim) { render_assoc_items(w, cx, container_item, did, what); } @@ -4123,17 +4128,22 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { .filter(|i| i.inner_impl().trait_.is_some()) .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did) { - if let Some(target) = impl_ + if let Some((target, real_target)) = impl_ .inner_impl() .items .iter() .filter_map(|item| match item.inner { - clean::TypedefItem(ref t, true) => Some(&t.type_), + clean::TypedefItem(ref t, true) => { + Some(match *t { + clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_), + _ => (&t.type_, &t.type_), + }) + } _ => None, }) .next() { - let inner_impl = target + let inner_impl = real_target .def_id() .or(target .primitive_type() diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 22507443b0842..cdfd6b3073adf 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -277,7 +277,7 @@ impl DocFolder for Cache { | clean::StructFieldItem(..) | clean::VariantItem(..) => ( ( - Some(*self.parent_stack.last().unwrap()), + Some(*self.parent_stack.last().expect("parent_stack is empty")), Some(&self.stack[..self.stack.len() - 1]), ), false, @@ -286,7 +286,7 @@ impl DocFolder for Cache { if self.parent_stack.is_empty() { ((None, None), false) } else { - let last = self.parent_stack.last().unwrap(); + let last = self.parent_stack.last().expect("parent_stack is empty 2"); let did = *last; let path = match self.paths.get(&did) { // The current stack not necessarily has correlation @@ -468,7 +468,7 @@ impl DocFolder for Cache { self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); } } else { - let trait_did = impl_item.trait_did().unwrap(); + let trait_did = impl_item.trait_did().expect("no trait did"); self.orphan_trait_impls.push((trait_did, dids, impl_item)); } None @@ -478,10 +478,10 @@ impl DocFolder for Cache { }); if pushed { - self.stack.pop().unwrap(); + self.stack.pop().expect("stack already empty"); } if parent_pushed { - self.parent_stack.pop().unwrap(); + self.parent_stack.pop().expect("parent stack already empty"); } self.stripped_mod = orig_stripped_mod; self.parent_is_trait_impl = orig_parent_is_trait_impl; @@ -574,6 +574,9 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { // has since been learned. for &(did, ref item) in orphan_impl_items { if let Some(&(ref fqp, _)) = paths.get(&did) { + if item.name.is_none() { // this is most likely from a typedef + continue; + } search_index.push(IndexItem { ty: item.type_(), name: item.name.clone().unwrap(), @@ -592,19 +595,25 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { let mut lastpathid = 0usize; for item in search_index { - item.parent_idx = item.parent.map(|nodeid| { - if nodeid_to_pathid.contains_key(&nodeid) { - *nodeid_to_pathid.get(&nodeid).unwrap() - } else { - let pathid = lastpathid; - nodeid_to_pathid.insert(nodeid, pathid); - lastpathid += 1; + item.parent_idx = match item.parent { + Some(nodeid) => { + Some(if nodeid_to_pathid.contains_key(&nodeid) { + *nodeid_to_pathid.get(&nodeid).expect("no pathid") + } else { + let pathid = lastpathid; + nodeid_to_pathid.insert(nodeid, pathid); + lastpathid += 1; - let &(ref fqp, short) = paths.get(&nodeid).unwrap(); - crate_paths.push((short, fqp.last().unwrap().clone())); - pathid + if let Some(&(ref fqp, short)) = paths.get(&nodeid) { + crate_paths.push((short, fqp.last().expect("no fqp").clone())); + } else { + continue + } + pathid + }) } - }); + None => None, + }; // Omit the parent path if it is same to that of the prior item. if lastpath == item.path { @@ -639,7 +648,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { items: crate_items, paths: crate_paths, }) - .unwrap() + .expect("failed serde conversion") ) } From fd4a88f3098ab1b20267716102d49c8a43d151d8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Jan 2020 14:41:46 +0100 Subject: [PATCH 03/15] Add test for typedef deref --- src/test/rustdoc/deref-typedef.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/test/rustdoc/deref-typedef.rs diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs new file mode 100644 index 0000000000000..b2dc20a5030e7 --- /dev/null +++ b/src/test/rustdoc/deref-typedef.rs @@ -0,0 +1,19 @@ +#![crate_name = "foo"] + +// @has 'foo/struct.Bar.html' +// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref' +// @has '-' '//*[@class="impl-items"]//*[@id="method.happy"]' 'pub fn happy(&self)' +// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.happy"]' 'happy' +pub struct FooA; +pub type FooB = FooA; + +impl FooA { + pub fn happy(&self) {} +} + +pub struct Bar; +impl std::ops::Deref for Bar { + type Target = FooB; + fn deref(&self) -> &FooB { unimplemented!() } +} From 81a5b94ac60cc1a9c8d365d8c6166c148279276c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 10 Jan 2020 14:46:28 +0100 Subject: [PATCH 04/15] formatting --- src/librustdoc/clean/inline.rs | 8 +++----- src/librustdoc/clean/mod.rs | 18 ++--------------- src/librustdoc/html/render.rs | 20 ++++++++----------- src/librustdoc/html/render/cache.rs | 31 ++++++++++++++--------------- 4 files changed, 28 insertions(+), 49 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index fc75bf35b250d..e54e716e042fe 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -284,11 +284,9 @@ fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option pub fn build_ty(cx: &DocContext, did: DefId) -> Option { match cx.tcx.def_kind(did)? { - DefKind::Struct | - DefKind::Union | - DefKind::Enum | - DefKind::Const | - DefKind::Static => Some(cx.tcx.type_of(did).clean(cx)), + DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Const | DefKind::Static => { + Some(cx.tcx.type_of(did).clean(cx)) + } DefKind::TyAlias => build_type_alias_type(cx, did), _ => None, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0cc4c55f49be8..027975a6d3288 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1124,14 +1124,7 @@ impl Clean for hir::ImplItem<'_> { hir::ImplItemKind::TyAlias(ref ty) => { let type_ = ty.clean(cx); let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); - TypedefItem( - Typedef { - type_, - generics: Generics::default(), - item_type, - }, - true, - ) + TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true) } hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem( OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() }, @@ -2011,14 +2004,7 @@ impl Clean for doctree::Typedef<'_> { visibility: self.vis.clean(cx), stability: cx.stability(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx), - inner: TypedefItem( - Typedef { - type_, - generics: self.gen.clean(cx), - item_type, - }, - false, - ), + inner: TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false), } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 69e268f3f80c1..86d59a0cccd9a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3474,12 +3474,10 @@ fn render_deref_methods( .items .iter() .filter_map(|item| match item.inner { - clean::TypedefItem(ref t, true) => { - Some(match *t { - clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_), - _ => (&t.type_, &t.type_), - }) - } + clean::TypedefItem(ref t, true) => Some(match *t { + clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_), + _ => (&t.type_, &t.type_), + }), _ => None, }) .next() @@ -4133,12 +4131,10 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { .items .iter() .filter_map(|item| match item.inner { - clean::TypedefItem(ref t, true) => { - Some(match *t { - clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_), - _ => (&t.type_, &t.type_), - }) - } + clean::TypedefItem(ref t, true) => Some(match *t { + clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_), + _ => (&t.type_, &t.type_), + }), _ => None, }) .next() diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index cdfd6b3073adf..fd9c47d0c4a44 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -574,7 +574,8 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { // has since been learned. for &(did, ref item) in orphan_impl_items { if let Some(&(ref fqp, _)) = paths.get(&did) { - if item.name.is_none() { // this is most likely from a typedef + if item.name.is_none() { + // this is most likely from a typedef continue; } search_index.push(IndexItem { @@ -596,22 +597,20 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { for item in search_index { item.parent_idx = match item.parent { - Some(nodeid) => { - Some(if nodeid_to_pathid.contains_key(&nodeid) { - *nodeid_to_pathid.get(&nodeid).expect("no pathid") - } else { - let pathid = lastpathid; - nodeid_to_pathid.insert(nodeid, pathid); - lastpathid += 1; + Some(nodeid) => Some(if nodeid_to_pathid.contains_key(&nodeid) { + *nodeid_to_pathid.get(&nodeid).expect("no pathid") + } else { + let pathid = lastpathid; + nodeid_to_pathid.insert(nodeid, pathid); + lastpathid += 1; - if let Some(&(ref fqp, short)) = paths.get(&nodeid) { - crate_paths.push((short, fqp.last().expect("no fqp").clone())); - } else { - continue - } - pathid - }) - } + if let Some(&(ref fqp, short)) = paths.get(&nodeid) { + crate_paths.push((short, fqp.last().expect("no fqp").clone())); + } else { + continue; + } + pathid + }), None => None, }; From 6e791464bcabc3d64b8fd5de6f2217c67d81a8b1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Jan 2020 13:56:11 +0100 Subject: [PATCH 05/15] remove unneeded code from cache.rs --- src/librustdoc/html/render/cache.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index fd9c47d0c4a44..f1f83acdda59e 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -574,10 +574,6 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { // has since been learned. for &(did, ref item) in orphan_impl_items { if let Some(&(ref fqp, _)) = paths.get(&did) { - if item.name.is_none() { - // this is most likely from a typedef - continue; - } search_index.push(IndexItem { ty: item.type_(), name: item.name.clone().unwrap(), @@ -596,23 +592,19 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { let mut lastpathid = 0usize; for item in search_index { - item.parent_idx = match item.parent { - Some(nodeid) => Some(if nodeid_to_pathid.contains_key(&nodeid) { + item.parent_idx = item.parent.map(|nodeid| { + if nodeid_to_pathid.contains_key(&nodeid) { *nodeid_to_pathid.get(&nodeid).expect("no pathid") } else { let pathid = lastpathid; nodeid_to_pathid.insert(nodeid, pathid); lastpathid += 1; - if let Some(&(ref fqp, short)) = paths.get(&nodeid) { - crate_paths.push((short, fqp.last().expect("no fqp").clone())); - } else { - continue; - } + let &(ref fqp, short) = paths.get(&nodeid).unwrap(); + crate_paths.push((short, fqp.last().unwrap().clone())); pathid - }), - None => None, - }; + } + }); // Omit the parent path if it is same to that of the prior item. if lastpath == item.path { From e6ad49aa67b7e6e0d9c5bc4bd68f44a009f91595 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Jan 2020 15:07:27 +0100 Subject: [PATCH 06/15] Include type alias implementations --- src/librustdoc/html/render.rs | 53 +++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 86d59a0cccd9a..aafc7a8a10ff6 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2595,7 +2595,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait) } // If there are methods directly on this trait object, render them here. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All); + render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All); let mut synthetic_types = Vec::new(); @@ -2942,7 +2942,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct } } } - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) } fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union) { @@ -2988,7 +2988,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union) document(w, cx, field); } } - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) } fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) { @@ -3130,7 +3130,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) { render_stability_since(w, variant, it); } } - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) } fn render_attribute(attr: &ast::MetaItem) -> Option { @@ -3344,7 +3344,7 @@ fn render_assoc_items( cx: &Context, containing_item: &clean::Item, it: DefId, - what: AssocItemRender<'_>, + what: &AssocItemRender<'_>, ) { let c = &cx.cache; let v = match c.impls.get(&it) { @@ -3377,7 +3377,7 @@ fn render_assoc_items( trait_.print(), type_.print() ); - RenderMode::ForDeref { mut_: deref_mut_ } + RenderMode::ForDeref { mut_: *deref_mut_ } } }; for i in &non_trait { @@ -3461,6 +3461,19 @@ fn render_assoc_items( } } +fn get_def_id(real_target: &clean::Type, cx: &Context) -> Option { + if let Some(did) = real_target.def_id() { + return Some(did); + } else { + if let Some(prim) = real_target.primitive_type() { + if let Some(&did) = cx.cache.primitive_locations.get(&prim) { + return Some(did); + } + } + } + None +} + fn render_deref_methods( w: &mut Buffer, cx: &Context, @@ -3475,23 +3488,21 @@ fn render_deref_methods( .iter() .filter_map(|item| match item.inner { clean::TypedefItem(ref t, true) => Some(match *t { - clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_), - _ => (&t.type_, &t.type_), + clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, Some(type_)), + _ => (&t.type_, None), }), _ => None, }) .next() .expect("Expected associated type binding"); + let did = get_def_id(&target, cx); let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target, deref_mut_: deref_mut }; - if let Some(did) = real_target.def_id() { - render_assoc_items(w, cx, container_item, did, what) - } else { - if let Some(prim) = real_target.primitive_type() { - if let Some(&did) = cx.cache.primitive_locations.get(&prim) { - render_assoc_items(w, cx, container_item, did, what); - } - } + if let Some(did) = did { + render_assoc_items(w, cx, container_item, did, &what); + } + if let Some(did) = real_target.and_then(|x| get_def_id(x, cx)) { + render_assoc_items(w, cx, container_item, did, &what); } } @@ -3873,7 +3884,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Opa // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) } fn item_trait_alias(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::TraitAlias) { @@ -3894,7 +3905,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::T // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) } fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typedef) { @@ -3915,7 +3926,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typed // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) } fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item) { @@ -3930,7 +3941,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item) { document(w, cx, it); - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) } fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { @@ -4602,7 +4613,7 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::Pr fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item) { document(w, cx, it); - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) } fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) { From d755238172ead0c619ac404487615534abc51ef1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Jan 2020 18:52:04 +0100 Subject: [PATCH 07/15] Simplify deref impls for type aliases --- src/librustdoc/clean/mod.rs | 31 +++++++++++++++-- src/librustdoc/html/render.rs | 63 +++++++++++++++-------------------- 2 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 027975a6d3288..ae15b458fbaea 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2105,7 +2105,7 @@ impl Clean> for doctree::Impl<'_> { build_deref_target_impls(cx, &items, &mut ret); } - let provided = trait_ + let provided: FxHashSet = trait_ .def_id() .map(|did| { cx.tcx @@ -2116,6 +2116,33 @@ impl Clean> for doctree::Impl<'_> { }) .unwrap_or_default(); + let for_ = self.for_.clean(cx); + let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) { + Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)), + _ => None, + }); + if let Some(type_alias) = type_alias { + ret.push(Item { + name: None, + attrs: self.attrs.clean(cx), + source: self.whence.clean(cx), + def_id, + visibility: self.vis.clean(cx), + stability: cx.stability(self.id).clean(cx), + deprecation: cx.deprecation(self.id).clean(cx), + inner: ImplItem(Impl { + unsafety: self.unsafety, + generics: self.generics.clean(cx), + provided_trait_methods: provided.clone(), + trait_: trait_.clone(), + for_: type_alias, + items: items.clone(), + polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), + synthetic: false, + blanket_impl: None, + }), + }); + } ret.push(Item { name: None, attrs: self.attrs.clean(cx), @@ -2129,7 +2156,7 @@ impl Clean> for doctree::Impl<'_> { generics: self.generics.clean(cx), provided_trait_methods: provided, trait_, - for_: self.for_.clean(cx), + for_, items, polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), synthetic: false, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index aafc7a8a10ff6..aaacae045b903 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2595,7 +2595,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait) } // If there are methods directly on this trait object, render them here. - render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All); + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All); let mut synthetic_types = Vec::new(); @@ -2942,7 +2942,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct } } } - render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union) { @@ -2988,7 +2988,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union) document(w, cx, field); } } - render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) { @@ -3130,7 +3130,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) { render_stability_since(w, variant, it); } } - render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } fn render_attribute(attr: &ast::MetaItem) -> Option { @@ -3344,7 +3344,7 @@ fn render_assoc_items( cx: &Context, containing_item: &clean::Item, it: DefId, - what: &AssocItemRender<'_>, + what: AssocItemRender<'_>, ) { let c = &cx.cache; let v = match c.impls.get(&it) { @@ -3377,7 +3377,7 @@ fn render_assoc_items( trait_.print(), type_.print() ); - RenderMode::ForDeref { mut_: *deref_mut_ } + RenderMode::ForDeref { mut_: deref_mut_ } } }; for i in &non_trait { @@ -3461,19 +3461,6 @@ fn render_assoc_items( } } -fn get_def_id(real_target: &clean::Type, cx: &Context) -> Option { - if let Some(did) = real_target.def_id() { - return Some(did); - } else { - if let Some(prim) = real_target.primitive_type() { - if let Some(&did) = cx.cache.primitive_locations.get(&prim) { - return Some(did); - } - } - } - None -} - fn render_deref_methods( w: &mut Buffer, cx: &Context, @@ -3488,21 +3475,23 @@ fn render_deref_methods( .iter() .filter_map(|item| match item.inner { clean::TypedefItem(ref t, true) => Some(match *t { - clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, Some(type_)), - _ => (&t.type_, None), + clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_), + _ => (&t.type_, &t.type_), }), _ => None, }) .next() .expect("Expected associated type binding"); - let did = get_def_id(&target, cx); let what = - AssocItemRender::DerefFor { trait_: deref_type, type_: target, deref_mut_: deref_mut }; - if let Some(did) = did { - render_assoc_items(w, cx, container_item, did, &what); - } - if let Some(did) = real_target.and_then(|x| get_def_id(x, cx)) { - render_assoc_items(w, cx, container_item, did, &what); + AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut }; + if let Some(did) = target.def_id() { + render_assoc_items(w, cx, container_item, did, what); + } else { + if let Some(prim) = target.primitive_type() { + if let Some(&did) = cx.cache.primitive_locations.get(&prim) { + render_assoc_items(w, cx, container_item, did, what); + } + } } } @@ -3884,7 +3873,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Opa // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } fn item_trait_alias(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::TraitAlias) { @@ -3905,7 +3894,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::T // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typedef) { @@ -3926,7 +3915,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typed // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item) { @@ -3941,7 +3930,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item) { document(w, cx, it); - render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { @@ -4137,20 +4126,20 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { .filter(|i| i.inner_impl().trait_.is_some()) .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did) { - if let Some((target, real_target)) = impl_ + if let Some(target) = impl_ .inner_impl() .items .iter() .filter_map(|item| match item.inner { clean::TypedefItem(ref t, true) => Some(match *t { - clean::Typedef { item_type: Some(ref type_), .. } => (&t.type_, type_), - _ => (&t.type_, &t.type_), + clean::Typedef { item_type: Some(ref type_), .. } => type_, + _ => &t.type_, }), _ => None, }) .next() { - let inner_impl = real_target + let inner_impl = target .def_id() .or(target .primitive_type() @@ -4613,7 +4602,7 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::Pr fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item) { document(w, cx, it); - render_assoc_items(w, cx, it, it.def_id, &AssocItemRender::All) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) { From 8a9b951f578a1389507c7251b5c75258ac215bf9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 Jan 2020 21:34:15 +0100 Subject: [PATCH 08/15] Fix rendering on sidebar and update tests --- src/librustdoc/html/render.rs | 8 ++++---- src/test/rustdoc/deref-typedef.rs | 28 +++++++++++++++++++++------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index aaacae045b903..9406803825350 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -4126,14 +4126,14 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { .filter(|i| i.inner_impl().trait_.is_some()) .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did) { - if let Some(target) = impl_ + if let Some((target, real_target)) = impl_ .inner_impl() .items .iter() .filter_map(|item| match item.inner { clean::TypedefItem(ref t, true) => Some(match *t { - clean::Typedef { item_type: Some(ref type_), .. } => type_, - _ => &t.type_, + clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_), + _ => (&t.type_, &t.type_), }), _ => None, }) @@ -4153,7 +4153,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { "{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print() )), - Escape(&format!("{:#}", target.print())) + Escape(&format!("{:#}", real_target.print())) )); out.push_str(""); let mut ret = impls diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs index b2dc20a5030e7..770f8d7289c3b 100644 --- a/src/test/rustdoc/deref-typedef.rs +++ b/src/test/rustdoc/deref-typedef.rs @@ -1,19 +1,33 @@ #![crate_name = "foo"] // @has 'foo/struct.Bar.html' -// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref' -// @has '-' '//*[@class="impl-items"]//*[@id="method.happy"]' 'pub fn happy(&self)' -// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref' -// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.happy"]' 'happy' +// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref' +// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)' +// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)' +// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)' +// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c' + pub struct FooA; pub type FooB = FooA; +pub type FooC = FooB; impl FooA { - pub fn happy(&self) {} + pub fn foo_a(&self) {} +} + +impl FooB { + pub fn foo_b(&self) {} +} + +impl FooC { + pub fn foo_c(&self) {} } pub struct Bar; impl std::ops::Deref for Bar { - type Target = FooB; - fn deref(&self) -> &FooB { unimplemented!() } + type Target = FooC; + fn deref(&self) -> &Self::Target { unimplemented!() } } From 25a8f9473f29e732838b6d88394dd80fe645b7f6 Mon Sep 17 00:00:00 2001 From: jumbatm <30644300+jumbatm@users.noreply.github.com> Date: Sat, 23 Nov 2019 14:52:40 +1000 Subject: [PATCH 09/15] Don't warn about snake case for field puns that don't introduce a new name. --- src/librustc_lint/nonstandard_style.rs | 15 ++++++++- ...62-no-snake-case-warning-for-field-puns.rs | 29 +++++++++++++++++ ...o-snake-case-warning-for-field-puns.stderr | 32 +++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs create mode 100644 src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index a2b7884241ff7..394da4a5bb0c1 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -350,7 +350,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } fn check_pat(&mut self, cx: &LateContext<'_, '_>, p: &hir::Pat<'_>) { - if let &PatKind::Binding(_, _, ident, _) = &p.kind { + if let &PatKind::Binding(_, hid, ident, _) = &p.kind { + if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid)) + { + if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind { + for field in field_pats.iter() { + if field.ident != ident { + // Only check if a new name has been introduced, to avoid warning + // on both the struct definition and this pattern. + self.check_snake_case(cx, "variable", &ident); + } + } + return; + } + } self.check_snake_case(cx, "variable", &ident); } } diff --git a/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs new file mode 100644 index 0000000000000..c2b81959f2cb8 --- /dev/null +++ b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs @@ -0,0 +1,29 @@ +#![deny(non_snake_case)] +#![allow(unused_variables)] +#![allow(dead_code)] + +enum Foo { + Bad { + lowerCamelCaseName: bool, + //~^ ERROR structure field `lowerCamelCaseName` should have a snake case name + }, + Good { + snake_case_name: bool, + }, +} + +fn main() { + let b = Foo::Bad { lowerCamelCaseName: true }; + + match b { + Foo::Bad { lowerCamelCaseName } => {} + Foo::Good { snake_case_name: lowerCamelCaseBinding } => { } + //~^ ERROR variable `lowerCamelCaseBinding` should have a snake case name + } + + if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { } + //~^ ERROR variable `anotherLowerCamelCaseBinding` should have a snake case name + + if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { } + //~^ ERROR variable `yetAnotherLowerCamelCaseBinding` should have a snake case name +} diff --git a/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr new file mode 100644 index 0000000000000..68956f21e8f1b --- /dev/null +++ b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr @@ -0,0 +1,32 @@ +error: structure field `lowerCamelCaseName` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:7:9 + | +LL | lowerCamelCaseName: bool, + | ^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_name` + | +note: lint level defined here + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: variable `lowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:20:38 + | +LL | Foo::Good { snake_case_name: lowerCamelCaseBinding } => { } + | ^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_binding` + +error: variable `anotherLowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:24:41 + | +LL | if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `another_lower_camel_case_binding` + +error: variable `yetAnotherLowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:27:43 + | +LL | if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `yet_another_lower_camel_case_binding` + +error: aborting due to 4 previous errors + From 3094c3792bb0bffbaaa0688d02c970054c353d1f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 16 Jan 2020 21:36:39 +0100 Subject: [PATCH 10/15] Improve code readability --- src/librustdoc/clean/mod.rs | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ae15b458fbaea..0e9f363bec3f3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2121,8 +2121,8 @@ impl Clean> for doctree::Impl<'_> { Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)), _ => None, }); - if let Some(type_alias) = type_alias { - ret.push(Item { + let make_item = |trait_: Option, for_: Type, items: Vec| { + Item { name: None, attrs: self.attrs.clean(cx), source: self.whence.clean(cx), @@ -2134,35 +2134,19 @@ impl Clean> for doctree::Impl<'_> { unsafety: self.unsafety, generics: self.generics.clean(cx), provided_trait_methods: provided.clone(), - trait_: trait_.clone(), - for_: type_alias, - items: items.clone(), + trait_, + for_, + items, polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), synthetic: false, blanket_impl: None, }), - }); + } + }; + if let Some(type_alias) = type_alias { + ret.push(make_item(trait_.clone(), type_alias, items.clone())); } - ret.push(Item { - name: None, - attrs: self.attrs.clean(cx), - source: self.whence.clean(cx), - def_id, - visibility: self.vis.clean(cx), - stability: cx.stability(self.id).clean(cx), - deprecation: cx.deprecation(self.id).clean(cx), - inner: ImplItem(Impl { - unsafety: self.unsafety, - generics: self.generics.clean(cx), - provided_trait_methods: provided, - trait_, - for_, - items, - polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), - synthetic: false, - blanket_impl: None, - }), - }); + ret.push(make_item(trait_, for_, items)); ret } } From cdc828e7f92c5835db4188f27cbdb7170d32c94e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 17 Jan 2020 17:09:05 +0100 Subject: [PATCH 11/15] Stop treating `FalseEdges` and `FalseUnwind` as having semantic value for const eval --- .../transform/qualify_min_const_fn.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 7034556740849..d927553c72e8b 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -309,7 +309,11 @@ fn check_terminator( ) -> McfResult { let span = terminator.source_info.span; match &terminator.kind { - TerminatorKind::Goto { .. } | TerminatorKind::Return | TerminatorKind::Resume => Ok(()), + TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::Goto { .. } + | TerminatorKind::Return + | TerminatorKind::Resume => Ok(()), TerminatorKind::Drop { location, .. } => check_place(tcx, location, span, def_id, body), TerminatorKind::DropAndReplace { location, value, .. } => { @@ -317,13 +321,10 @@ fn check_terminator( check_operand(tcx, value, span, def_id, body) } - TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } - if !feature_allowed(tcx, def_id, sym::const_if_match) => - { + TerminatorKind::SwitchInt { .. } if !feature_allowed(tcx, def_id, sym::const_if_match) => { Err((span, "loops and conditional expressions are not stable in const fn".into())) } - TerminatorKind::FalseEdges { .. } => Ok(()), TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => { check_operand(tcx, discr, span, def_id, body) } @@ -367,13 +368,5 @@ fn check_terminator( TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => { check_operand(tcx, cond, span, def_id, body) } - - TerminatorKind::FalseUnwind { .. } if feature_allowed(tcx, def_id, sym::const_loop) => { - Ok(()) - } - - TerminatorKind::FalseUnwind { .. } => { - Err((span, "loops are not allowed in const fn".into())) - } } } From a91f77ca26f65e566b93a0f086a894e60ec7c257 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Jan 2020 14:21:14 +0000 Subject: [PATCH 12/15] Add regression test for integer literals in generic arguments in where clauses --- ...eger-literal-generic-arg-in-where-clause.rs | 18 ++++++++++++++++++ ...-literal-generic-arg-in-where-clause.stderr | 8 ++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs create mode 100644 src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs new file mode 100644 index 0000000000000..30fbfda112c55 --- /dev/null +++ b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn takes_closure_of_array_3(f: F) where F: Fn([i32; 3]) { + f([1, 2, 3]); +} + +fn takes_closure_of_array_3_apit(f: impl Fn([i32; 3])) { + f([1, 2, 3]); +} + +fn returns_closure_of_array_3() -> impl Fn([i32; 3]) { + |_| {} +} + +fn main() {} diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr new file mode 100644 index 0000000000000..7f37f3e2791ec --- /dev/null +++ b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/integer-literal-generic-arg-in-where-clause.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + From 9c6c2f16f00ed6f24866d2d4927b49d79b453a23 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 16 Jan 2020 14:35:37 +0100 Subject: [PATCH 13/15] Clean up E0198 explanation --- src/librustc_error_codes/error_codes/E0198.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0198.md b/src/librustc_error_codes/error_codes/E0198.md index 6504d60dbd1d5..687214a205096 100644 --- a/src/librustc_error_codes/error_codes/E0198.md +++ b/src/librustc_error_codes/error_codes/E0198.md @@ -1,17 +1,18 @@ -A negative implementation is one that excludes a type from implementing a -particular trait. Not being able to use a trait is always a safe operation, -so negative implementations are always safe and never need to be marked as -unsafe. +A negative implementation was marked as unsafe. -```compile_fail -#![feature(optin_builtin_traits)] +Erroneous code example: +```compile_fail struct Foo; -// unsafe is unnecessary -unsafe impl !Clone for Foo { } +unsafe impl !Clone for Foo { } // error! ``` +A negative implementation is one that excludes a type from implementing a +particular trait. Not being able to use a trait is always a safe operation, +so negative implementations are always safe and never need to be marked as +unsafe. + This will compile: ```ignore (ignore auto_trait future compatibility warning) From 482dc77dee59dd44448973758980806bd63aa5a3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 Jan 2020 19:51:07 +0100 Subject: [PATCH 14/15] formatting --- src/librustdoc/clean/mod.rs | 40 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0e9f363bec3f3..20a5a6c54984d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2121,27 +2121,25 @@ impl Clean> for doctree::Impl<'_> { Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)), _ => None, }); - let make_item = |trait_: Option, for_: Type, items: Vec| { - Item { - name: None, - attrs: self.attrs.clean(cx), - source: self.whence.clean(cx), - def_id, - visibility: self.vis.clean(cx), - stability: cx.stability(self.id).clean(cx), - deprecation: cx.deprecation(self.id).clean(cx), - inner: ImplItem(Impl { - unsafety: self.unsafety, - generics: self.generics.clean(cx), - provided_trait_methods: provided.clone(), - trait_, - for_, - items, - polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), - synthetic: false, - blanket_impl: None, - }), - } + let make_item = |trait_: Option, for_: Type, items: Vec| Item { + name: None, + attrs: self.attrs.clean(cx), + source: self.whence.clean(cx), + def_id, + visibility: self.vis.clean(cx), + stability: cx.stability(self.id).clean(cx), + deprecation: cx.deprecation(self.id).clean(cx), + inner: ImplItem(Impl { + unsafety: self.unsafety, + generics: self.generics.clean(cx), + provided_trait_methods: provided.clone(), + trait_, + for_, + items, + polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), + synthetic: false, + blanket_impl: None, + }), }; if let Some(type_alias) = type_alias { ret.push(make_item(trait_.clone(), type_alias, items.clone())); From e8a4b9319cbf5b3f56b3cdd8ad11e86ff7168345 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 Jan 2020 19:54:07 +0100 Subject: [PATCH 15/15] Clean up E0199 explanation --- src/librustc_error_codes/error_codes/E0199.md | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0199.md b/src/librustc_error_codes/error_codes/E0199.md index d0c12dc6f1755..88130e8e5e596 100644 --- a/src/librustc_error_codes/error_codes/E0199.md +++ b/src/librustc_error_codes/error_codes/E0199.md @@ -1,14 +1,23 @@ +A trait implementation was marked as unsafe while the trait is safe. + +Erroneous code example: + +```compile_fail,E0199 +struct Foo; + +trait Bar { } + +unsafe impl Bar for Foo { } // error! +``` + Safe traits should not have unsafe implementations, therefore marking an implementation for a safe trait unsafe will cause a compiler error. Removing -the unsafe marker on the trait noted in the error will resolve this problem. +the unsafe marker on the trait noted in the error will resolve this problem: -```compile_fail,E0199 +``` struct Foo; trait Bar { } -// this won't compile because Bar is safe -unsafe impl Bar for Foo { } -// this will compile -impl Bar for Foo { } +impl Bar for Foo { } // ok! ```