Skip to content

Rollup of 5 pull requests #69004

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

Merged
merged 16 commits into from
Feb 9, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/liballoc/string.rs
Original file line number Diff line number Diff line change
@@ -319,7 +319,7 @@ pub struct String {
/// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FromUtf8Error {
bytes: Vec<u8>,
error: Utf8Error,
@@ -2208,6 +2208,14 @@ impl AsRef<str> for String {
}
}

#[stable(feature = "string_as_mut", since = "1.43.0")]
impl AsMut<str> for String {
#[inline]
fn as_mut(&mut self) -> &mut str {
self
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<[u8]> for String {
#[inline]
4 changes: 4 additions & 0 deletions src/liballoc/tests/string.rs
Original file line number Diff line number Diff line change
@@ -50,7 +50,11 @@ fn test_from_utf8() {

let xs = b"hello\xFF".to_vec();
let err = String::from_utf8(xs).unwrap_err();
assert_eq!(err.as_bytes(), b"hello\xff");
let err_clone = err.clone();
assert_eq!(err, err_clone);
assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
assert_eq!(err_clone.utf8_error().valid_up_to(), 5);
}

#[test]
2 changes: 1 addition & 1 deletion src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
@@ -323,7 +323,7 @@ rustc_queries! {
query associated_item(_: DefId) -> ty::AssocItem {}

/// Collects the associated items defined on a trait or impl.
query associated_items(key: DefId) -> ty::AssocItemsIterator<'tcx> {
query associated_items(key: DefId) -> &'tcx [ty::AssocItem] {
desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
}

1 change: 1 addition & 0 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -541,6 +541,7 @@ fn vtable_methods<'tcx>(
tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
let trait_methods = tcx
.associated_items(trait_ref.def_id())
.iter()
.filter(|item| item.kind == ty::AssocKind::Method);

// Now list each method's DefId and InternalSubsts (for within its trait).
6 changes: 5 additions & 1 deletion src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
@@ -212,6 +212,7 @@ fn object_safety_violations_for_trait(
// Check methods for violations.
let mut violations: Vec<_> = tcx
.associated_items(trait_def_id)
.iter()
.filter(|item| item.kind == ty::AssocKind::Method)
.filter_map(|item| {
object_safety_violation_for_method(tcx, trait_def_id, &item)
@@ -277,6 +278,7 @@ fn object_safety_violations_for_trait(

violations.extend(
tcx.associated_items(trait_def_id)
.iter()
.filter(|item| item.kind == ty::AssocKind::Const)
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
);
@@ -632,7 +634,9 @@ fn object_ty_for_trait<'tcx>(

let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
.flat_map(|super_trait_ref| {
tcx.associated_items(super_trait_ref.def_id()).map(move |item| (super_trait_ref, item))
tcx.associated_items(super_trait_ref.def_id())
.iter()
.map(move |item| (super_trait_ref, item))
})
.filter(|(_, item)| item.kind == ty::AssocKind::Type)
.collect::<Vec<_>>();
2 changes: 1 addition & 1 deletion src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
@@ -1473,7 +1473,7 @@ fn assoc_ty_def(
{
return specialization_graph::NodeItem {
node: specialization_graph::Node::Impl(impl_def_id),
item,
item: *item,
};
}
}
11 changes: 7 additions & 4 deletions src/librustc/traits/types/specialization_graph.rs
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ impl<'tcx> Node {
}

/// Iterate over the items defined directly by the given (impl or trait) node.
pub fn items(&self, tcx: TyCtxt<'tcx>) -> ty::AssocItemsIterator<'tcx> {
pub fn items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ty::AssocItem] {
tcx.associated_items(self.def_id())
}

@@ -98,8 +98,10 @@ impl<'tcx> Node {
) -> Option<ty::AssocItem> {
use crate::ty::AssocKind::*;

tcx.associated_items(self.def_id()).find(move |impl_item| {
match (trait_item_kind, impl_item.kind) {
tcx.associated_items(self.def_id())
.iter()
.find(move |impl_item| {
match (trait_item_kind, impl_item.kind) {
| (Const, Const)
| (Method, Method)
| (Type, Type)
@@ -112,7 +114,8 @@ impl<'tcx> Node {
| (OpaqueTy, _)
=> false,
}
})
})
.copied()
}

pub fn def_id(&self) -> DefId {
5 changes: 3 additions & 2 deletions src/librustc/traits/wf.rs
Original file line number Diff line number Diff line change
@@ -166,7 +166,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let extend_cause_with_original_assoc_item_obligation =
|cause: &mut traits::ObligationCause<'_>,
pred: &ty::Predicate<'_>,
trait_assoc_items: ty::AssocItemsIterator<'_>| {
trait_assoc_items: &[ty::AssocItem]| {
let trait_item = tcx
.hir()
.as_local_hir_id(trait_ref.def_id)
@@ -283,6 +283,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind))
{
if let Some((impl_item, trait_assoc_item)) = trait_assoc_items
.iter()
.filter(|i| i.def_id == *item_def_id)
.next()
.and_then(|trait_assoc_item| {
@@ -325,7 +326,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
extend_cause_with_original_assoc_item_obligation(
&mut cause,
&pred,
trait_assoc_items.clone(),
trait_assoc_items,
);
traits::Obligation::new(cause, param_env, pred)
});
1 change: 1 addition & 0 deletions src/librustc/ty/adjustment.rs
Original file line number Diff line number Diff line change
@@ -122,6 +122,7 @@ impl<'tcx> OverloadedDeref<'tcx> {
};
let method_def_id = tcx
.associated_items(trait_def_id.unwrap())
.iter()
.find(|m| m.kind == ty::AssocKind::Method)
.unwrap()
.def_id;
1 change: 1 addition & 0 deletions src/librustc/ty/instance.rs
Original file line number Diff line number Diff line change
@@ -376,6 +376,7 @@ impl<'tcx> Instance<'tcx> {
let fn_once = tcx.lang_items().fn_once_trait().unwrap();
let call_once = tcx
.associated_items(fn_once)
.iter()
.find(|it| it.kind == ty::AssocKind::Method)
.unwrap()
.def_id;
25 changes: 3 additions & 22 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -2705,14 +2705,14 @@ impl<'tcx> TyCtxt<'tcx> {
.for_each(|&body_id| f(self.hir().body_owner_def_id(body_id)));
}

pub fn provided_trait_methods(self, id: DefId) -> Vec<AssocItem> {
pub fn provided_trait_methods(self, id: DefId) -> impl Iterator<Item = &'tcx AssocItem> {
self.associated_items(id)
.iter()
.filter(|item| item.kind == AssocKind::Method && item.defaultness.has_value())
.collect()
}

pub fn trait_relevant_for_never(self, did: DefId) -> bool {
self.associated_items(did).any(|item| item.relevant_for_never())
self.associated_items(did).iter().any(|item| item.relevant_for_never())
}

pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
@@ -2974,25 +2974,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}

#[derive(Copy, Clone, HashStable)]
pub struct AssocItemsIterator<'tcx> {
pub items: &'tcx [AssocItem],
}

impl<'tcx> Iterator for AssocItemsIterator<'tcx> {
type Item = AssocItem;

#[inline]
fn next(&mut self) -> Option<AssocItem> {
if let Some((first, rest)) = self.items.split_first() {
self.items = rest;
Some(*first)
} else {
None
}
}
}

#[derive(Clone, HashStable)]
pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]);

1 change: 1 addition & 0 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -1066,6 +1066,7 @@ impl<'tcx> ProjectionTy<'tcx> {
) -> ProjectionTy<'tcx> {
let item_def_id = tcx
.associated_items(trait_ref.def_id)
.iter()
.find(|item| {
item.kind == ty::AssocKind::Type
&& tcx.hygienic_eq(item_name, item.ident, trait_ref.def_id)
2 changes: 1 addition & 1 deletion src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
@@ -355,7 +355,7 @@ impl<'tcx> TyCtxt<'tcx> {
let mut dtor_did = None;
let ty = self.type_of(adt_did);
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
if let Some(item) = self.associated_items(impl_did).next() {
if let Some(item) = self.associated_items(impl_did).first() {
if validate(self, impl_did).is_ok() {
dtor_did = Some(item.def_id);
}
5 changes: 4 additions & 1 deletion src/librustc_ast_pretty/pprust.rs
Original file line number Diff line number Diff line change
@@ -1074,12 +1074,15 @@ impl<'a> State<'a> {
fn print_associated_type(
&mut self,
ident: ast::Ident,
generics: &ast::Generics,
bounds: &ast::GenericBounds,
ty: Option<&ast::Ty>,
) {
self.word_space("type");
self.print_ident(ident);
self.print_generic_params(&generics.params);
self.print_type_bounds(":", bounds);
self.print_where_clause(&generics.where_clause);
if let Some(ty) = ty {
self.s.space();
self.word_space("=");
@@ -1474,7 +1477,7 @@ impl<'a> State<'a> {
self.print_fn_full(sig, item.ident, &item.generics, &item.vis, body, &item.attrs);
}
ast::AssocItemKind::TyAlias(bounds, ty) => {
self.print_associated_type(item.ident, bounds, ty.as_deref());
self.print_associated_type(item.ident, &item.generics, bounds, ty.as_deref());
}
ast::AssocItemKind::Macro(mac) => {
self.print_mac(mac);
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/debuginfo/mod.rs
Original file line number Diff line number Diff line change
@@ -559,7 +559,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
file_metadata,
loc.line as c_uint,
type_metadata,
self.sess().opts.optimize != config::OptLevel::No,
true,
DIFlags::FlagZero,
argument_index,
align.bytes() as u32,
6 changes: 5 additions & 1 deletion src/librustc_hir/print.rs
Original file line number Diff line number Diff line change
@@ -454,14 +454,17 @@ impl<'a> State<'a> {
fn print_associated_type(
&mut self,
ident: ast::Ident,
generics: &hir::Generics<'_>,
bounds: Option<hir::GenericBounds<'_>>,
ty: Option<&hir::Ty<'_>>,
) {
self.word_space("type");
self.print_ident(ident);
self.print_generic_params(&generics.params);
if let Some(bounds) = bounds {
self.print_bounds(":", bounds);
}
self.print_where_clause(&generics.where_clause);
if let Some(ty) = ty {
self.s.space();
self.word_space("=");
@@ -902,6 +905,7 @@ impl<'a> State<'a> {
hir::TraitItemKind::Type(ref bounds, ref default) => {
self.print_associated_type(
ti.ident,
&ti.generics,
Some(bounds),
default.as_ref().map(|ty| &**ty),
);
@@ -930,7 +934,7 @@ impl<'a> State<'a> {
self.ann.nested(self, Nested::Body(body));
}
hir::ImplItemKind::TyAlias(ref ty) => {
self.print_associated_type(ii.ident, None, Some(ty));
self.print_associated_type(ii.ident, &ii.generics, None, Some(ty));
}
hir::ImplItemKind::OpaqueTy(bounds) => {
self.word_space("type");
1 change: 1 addition & 0 deletions src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
@@ -68,6 +68,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
let fn_mut = tcx.lang_items().fn_mut_trait().unwrap();
let call_mut = tcx
.associated_items(fn_mut)
.iter()
.find(|it| it.kind == ty::AssocKind::Method)
.unwrap()
.def_id;
2 changes: 1 addition & 1 deletion src/librustc_mir/util/elaborate_drops.rs
Original file line number Diff line number Diff line change
@@ -539,7 +539,7 @@ where
debug!("destructor_call_block({:?}, {:?})", self, succ);
let tcx = self.tcx();
let drop_trait = tcx.lang_items().drop_trait().unwrap();
let drop_fn = tcx.associated_items(drop_trait).next().unwrap();
let drop_fn = tcx.associated_items(drop_trait)[0];
let ty = self.place_ty(self.place);
let substs = tcx.mk_substs_trait(ty, &[]);

12 changes: 6 additions & 6 deletions src/librustc_passes/reachable.rs
Original file line number Diff line number Diff line change
@@ -362,12 +362,12 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
return;
}

let provided_trait_methods = self.tcx.provided_trait_methods(trait_def_id);
self.worklist.reserve(provided_trait_methods.len());
for default_method in provided_trait_methods {
let hir_id = self.tcx.hir().as_local_hir_id(default_method.def_id).unwrap();
self.worklist.push(hir_id);
}
// FIXME(#53488) remove `let`
let tcx = self.tcx;
self.worklist.extend(
tcx.provided_trait_methods(trait_def_id)
.map(|assoc| tcx.hir().as_local_hir_id(assoc.def_id).unwrap()),
);
}
}
}
1 change: 1 addition & 0 deletions src/librustc_passes/stability.rs
Original file line number Diff line number Diff line change
@@ -468,6 +468,7 @@ impl Visitor<'tcx> for Checker<'tcx> {
let trait_item_def_id = self
.tcx
.associated_items(trait_did)
.iter()
.find(|item| item.ident.name == impl_item.ident.name)
.map(|item| item.def_id);
if let Some(def_id) = trait_item_def_id {
2 changes: 2 additions & 0 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
@@ -423,6 +423,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
qualname.push_str(&self.tcx.def_path_str(def_id));
self.tcx
.associated_items(def_id)
.iter()
.find(|item| item.ident.name == ident.name)
.map(|item| decl_id = Some(item.def_id));
}
@@ -717,6 +718,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
let ti = self.tcx.associated_item(decl_id);
self.tcx
.associated_items(ti.container.id())
.iter()
.find(|item| {
item.ident.name == ti.ident.name && item.defaultness.has_value()
})
10 changes: 4 additions & 6 deletions src/librustc_ty/ty.rs
Original file line number Diff line number Diff line change
@@ -206,12 +206,10 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
}
}

fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AssocItemsIterator<'tcx> {
ty::AssocItemsIterator {
items: tcx.arena.alloc_from_iter(
tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)),
),
}
fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [ty::AssocItem] {
tcx.arena.alloc_from_iter(
tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)),
)
}

fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
6 changes: 5 additions & 1 deletion src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
@@ -1109,7 +1109,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_def_id: DefId,
assoc_name: ast::Ident,
) -> bool {
self.tcx().associated_items(trait_def_id).any(|item| {
self.tcx().associated_items(trait_def_id).iter().any(|item| {
item.kind == ty::AssocKind::Type
&& self.tcx().hygienic_eq(assoc_name, item.ident, trait_def_id)
})
@@ -1347,6 +1347,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
let assoc_ty = tcx
.associated_items(candidate.def_id())
.iter()
.find(|i| i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident)
.expect("missing associated type");

@@ -1512,6 +1513,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::Predicate::Trait(pred, _) => {
associated_types.entry(span).or_default().extend(
tcx.associated_items(pred.def_id())
.iter()
.filter(|item| item.kind == ty::AssocKind::Type)
.map(|item| item.def_id),
);
@@ -1969,6 +1971,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let bound_span = self
.tcx()
.associated_items(bound.def_id())
.iter()
.find(|item| {
item.kind == ty::AssocKind::Type
&& self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id())
@@ -2198,6 +2201,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
let item = tcx
.associated_items(trait_did)
.iter()
.find(|i| Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident)
.expect("missing associated type");

4 changes: 2 additions & 2 deletions src/librustc_typeck/check/closure.rs
Original file line number Diff line number Diff line change
@@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if is_gen {
// Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
// associated item and not yield.
let return_assoc_item = self.tcx.associated_items(gen_trait).nth(1).unwrap().def_id;
let return_assoc_item = self.tcx.associated_items(gen_trait)[1].def_id;
if return_assoc_item != projection.projection_def_id() {
debug!("deduce_sig_from_projection: not return assoc item of generator");
return None;
@@ -673,7 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// The `Future` trait has only one associted item, `Output`,
// so check that this is what we see.
let output_assoc_item = self.tcx.associated_items(future_trait).nth(0).unwrap().def_id;
let output_assoc_item = self.tcx.associated_items(future_trait)[0].def_id;
if output_assoc_item != predicate.projection_ty.item_def_id {
span_bug!(
cause_span,
1 change: 1 addition & 0 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
@@ -536,6 +536,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let item_def_id = self
.tcx
.associated_items(deref_trait)
.iter()
.find(|item| item.kind == ty::AssocKind::Type)
.unwrap()
.def_id;
11 changes: 8 additions & 3 deletions src/librustc_typeck/check/method/mod.rs
Original file line number Diff line number Diff line change
@@ -474,8 +474,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_name: ast::Ident,
ns: Namespace,
) -> Option<ty::AssocItem> {
self.tcx.associated_items(def_id).find(|item| {
Namespace::from(item.kind) == ns && self.tcx.hygienic_eq(item_name, item.ident, def_id)
})
self.tcx
.associated_items(def_id)
.iter()
.find(|item| {
Namespace::from(item.kind) == ns
&& self.tcx.hygienic_eq(item_name, item.ident, def_id)
})
.copied()
}
}
4 changes: 3 additions & 1 deletion src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
@@ -1696,18 +1696,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let max_dist = max(name.as_str().len(), 3) / 3;
self.tcx
.associated_items(def_id)
.iter()
.filter(|x| {
let dist = lev_distance(&*name.as_str(), &x.ident.as_str());
Namespace::from(x.kind) == Namespace::Value && dist > 0 && dist <= max_dist
})
.copied()
.collect()
} else {
self.fcx
.associated_item(def_id, name, Namespace::Value)
.map_or(Vec::new(), |x| vec![x])
}
} else {
self.tcx.associated_items(def_id).collect()
self.tcx.associated_items(def_id).to_vec()
}
}
}
6 changes: 4 additions & 2 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -1976,13 +1976,15 @@ fn check_impl_items_against_trait<'tcx>(
let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id));
let ty_trait_item = tcx
.associated_items(impl_trait_ref.def_id)
.iter()
.find(|ac| {
Namespace::from(&impl_item.kind) == Namespace::from(ac.kind)
&& tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id)
})
.or_else(|| {
// Not compatible, but needed for the error message
tcx.associated_items(impl_trait_ref.def_id)
.iter()
.find(|ac| tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id))
});

@@ -2096,7 +2098,7 @@ fn check_impl_items_against_trait<'tcx>(

if !is_implemented && !traits::impl_is_default(tcx, impl_id) {
if !trait_item.defaultness.has_value() {
missing_items.push(trait_item);
missing_items.push(*trait_item);
} else if associated_type_overridden {
invalidated_items.push(trait_item.ident);
}
@@ -5175,7 +5177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check for `Future` implementations by constructing a predicate to
// prove: `<T as Future>::Output == U`
let future_trait = self.tcx.lang_items().future_trait().unwrap();
let item_def_id = self.tcx.associated_items(future_trait).next().unwrap().def_id;
let item_def_id = self.tcx.associated_items(future_trait)[0].def_id;
let predicate =
ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
// `<T as Future>::Output`
94 changes: 59 additions & 35 deletions src/librustc_typeck/coherence/inherent_impls_overlap.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::namespace::Namespace;
use rustc::traits::{self, IntercrateMode, SkipLeakCheck};
use rustc::ty::TyCtxt;
use rustc::ty::{AssocItem, TyCtxt};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
@@ -17,38 +17,60 @@ struct InherentOverlapChecker<'tcx> {
}

impl InherentOverlapChecker<'tcx> {
/// Checks whether any associated items in impls 1 and 2 share the same identifier and
/// namespace.
fn impls_have_common_items(&self, impl1: DefId, impl2: DefId) -> bool {
let impl_items1 = self.tcx.associated_items(impl1);
let impl_items2 = self.tcx.associated_items(impl2);

for item1 in &impl_items1[..] {
for item2 in &impl_items2[..] {
// Avoid costly `.modern()` calls as much as possible by doing them as late as we
// can. Compare raw symbols first.
if item1.ident.name == item2.ident.name
&& Namespace::from(item1.kind) == Namespace::from(item2.kind)
{
// Symbols and namespace match, compare hygienically.
if item1.ident.modern() == item2.ident.modern() {
return true;
}
}
}
}

false
}

fn check_for_common_items_in_impls(
&self,
impl1: DefId,
impl2: DefId,
overlap: traits::OverlapResult<'_>,
) {
let name_and_namespace = |def_id| {
let item = self.tcx.associated_item(def_id);
(item.ident.modern(), Namespace::from(item.kind))
};
let name_and_namespace =
|assoc: &AssocItem| (assoc.ident.modern(), Namespace::from(assoc.kind));

let impl_items1 = self.tcx.associated_item_def_ids(impl1);
let impl_items2 = self.tcx.associated_item_def_ids(impl2);
let impl_items1 = self.tcx.associated_items(impl1);
let impl_items2 = self.tcx.associated_items(impl2);

for &item1 in &impl_items1[..] {
for item1 in &impl_items1[..] {
let (name, namespace) = name_and_namespace(item1);

for &item2 in &impl_items2[..] {
for item2 in &impl_items2[..] {
if (name, namespace) == name_and_namespace(item2) {
let mut err = struct_span_err!(
self.tcx.sess,
self.tcx.span_of_impl(item1).unwrap(),
self.tcx.span_of_impl(item1.def_id).unwrap(),
E0592,
"duplicate definitions with name `{}`",
name
);
err.span_label(
self.tcx.span_of_impl(item1).unwrap(),
self.tcx.span_of_impl(item1.def_id).unwrap(),
format!("duplicate definitions for `{}`", name),
);
err.span_label(
self.tcx.span_of_impl(item2).unwrap(),
self.tcx.span_of_impl(item2.def_id).unwrap(),
format!("other definition for `{}`", name),
);

@@ -66,27 +88,21 @@ impl InherentOverlapChecker<'tcx> {
}
}

fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
let impls = self.tcx.inherent_impls(ty_def_id);

for (i, &impl1_def_id) in impls.iter().enumerate() {
for &impl2_def_id in &impls[(i + 1)..] {
traits::overlapping_impls(
self.tcx,
impl1_def_id,
impl2_def_id,
IntercrateMode::Issue43355,
// We go ahead and just skip the leak check for
// inherent impls without warning.
SkipLeakCheck::Yes,
|overlap| {
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
false
},
|| true,
);
}
}
fn check_for_overlapping_inherent_impls(&self, impl1_def_id: DefId, impl2_def_id: DefId) {
traits::overlapping_impls(
self.tcx,
impl1_def_id,
impl2_def_id,
IntercrateMode::Issue43355,
// We go ahead and just skip the leak check for
// inherent impls without warning.
SkipLeakCheck::Yes,
|overlap| {
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
false
},
|| true,
);
}
}

@@ -97,8 +113,16 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
| hir::ItemKind::Struct(..)
| hir::ItemKind::Trait(..)
| hir::ItemKind::Union(..) => {
let type_def_id = self.tcx.hir().local_def_id(item.hir_id);
self.check_for_overlapping_inherent_impls(type_def_id);
let ty_def_id = self.tcx.hir().local_def_id(item.hir_id);
let impls = self.tcx.inherent_impls(ty_def_id);

for (i, &impl1_def_id) in impls.iter().enumerate() {
for &impl2_def_id in &impls[(i + 1)..] {
if self.impls_have_common_items(impl1_def_id, impl2_def_id) {
self.check_for_overlapping_inherent_impls(impl1_def_id, impl2_def_id);
}
}
}
}
_ => {}
}
3 changes: 2 additions & 1 deletion src/librustdoc/clean/blanket_impl.rs
Original file line number Diff line number Diff line change
@@ -87,7 +87,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
.cx
.tcx
.provided_trait_methods(trait_def_id)
.into_iter()
.map(|meth| meth.ident.to_string())
.collect();

@@ -115,6 +114,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
.cx
.tcx
.associated_items(impl_def_id)
.iter()
.copied()
.collect::<Vec<_>>()
.clean(self.cx),
polarity: None,
7 changes: 3 additions & 4 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
@@ -191,7 +191,7 @@ pub fn record_extern_fqn(cx: &DocContext<'_>, did: DefId, kind: clean::TypeKind)

pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
let auto_trait = cx.tcx.trait_def(did).has_auto_impl;
let trait_items = cx.tcx.associated_items(did).map(|item| item.clean(cx)).collect();
let trait_items = cx.tcx.associated_items(did).iter().map(|item| item.clean(cx)).collect();
let predicates = cx.tcx.predicates_of(did);
let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
let generics = filter_non_trait_generics(did, generics);
@@ -376,6 +376,7 @@ pub fn build_impl(
} else {
(
tcx.associated_items(did)
.iter()
.filter_map(|item| {
if associated_trait.is_some() || item.vis == ty::Visibility::Public {
Some(item.clean(cx))
@@ -401,9 +402,7 @@ pub fn build_impl(

let provided = trait_
.def_id()
.map(|did| {
tcx.provided_trait_methods(did).into_iter().map(|meth| meth.ident.to_string()).collect()
})
.map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect())
.unwrap_or_default();

debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
6 changes: 1 addition & 5 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -2108,11 +2108,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
let provided: FxHashSet<String> = trait_
.def_id()
.map(|did| {
cx.tcx
.provided_trait_methods(did)
.into_iter()
.map(|meth| meth.ident.to_string())
.collect()
cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect()
})
.unwrap_or_default();

1 change: 1 addition & 0 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Original file line number Diff line number Diff line change
@@ -206,6 +206,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
return cx
.tcx
.associated_items(did)
.iter()
.find(|item| item.ident.name == item_name)
.and_then(|item| match item.kind {
ty::AssocKind::Method => Some("method"),
25 changes: 25 additions & 0 deletions src/test/pretty/gat-bounds.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Check that associated types print generic parameters and where clauses.
// See issue #67509.

// pretty-compare-only
// pp-exact:gat-bounds.pp

#![feature(generic_associated_types)]

trait X {
type
Y<T>: Trait
where
Self: Sized;
}

impl X for () {
type
Y<T>
where
Self: Sized
=
u32;
}

fn main() { }
17 changes: 17 additions & 0 deletions src/test/pretty/gat-bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Check that associated types print generic parameters and where clauses.
// See issue #67509.

// pretty-compare-only
// pp-exact:gat-bounds.pp

#![feature(generic_associated_types)]

trait X {
type Y<T>: Trait where Self: Sized;
}

impl X for () {
type Y<T> where Self: Sized = u32;
}

fn main() { }