From 3aa1503a61d03834643a39f3e4c9de6721c31bdb Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Dec 2018 13:28:06 +0200 Subject: [PATCH 01/12] add support for principal-less trait object types should be a pure refactoring. --- src/librustc/traits/coherence.rs | 8 +++- src/librustc/traits/select.rs | 21 ++++++--- src/librustc/ty/error.rs | 6 ++- src/librustc/ty/fast_reject.rs | 12 +++--- src/librustc/ty/item_path.rs | 2 +- src/librustc/ty/sty.rs | 21 ++++++--- src/librustc/ty/wf.rs | 2 +- src/librustc/util/ppaux.rs | 22 +++++----- src/librustc_codegen_llvm/context.rs | 5 ++- .../debuginfo/metadata.rs | 3 +- .../debuginfo/type_names.rs | 16 ++++--- src/librustc_codegen_ssa/meth.rs | 13 ++++-- src/librustc_codegen_ssa/traits/misc.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/interpret/traits.rs | 13 ++++-- src/librustc_mir/monomorphize/collector.rs | 23 +++++----- src/librustc_mir/monomorphize/item.rs | 17 +++++--- src/librustc_typeck/check/cast.rs | 4 +- src/librustc_typeck/check/closure.rs | 4 +- src/librustc_typeck/check/method/confirm.rs | 6 ++- src/librustc_typeck/check/method/probe.rs | 33 +++++++------- src/librustc_typeck/check/method/suggest.rs | 3 +- .../coherence/inherent_impls.rs | 4 +- src/librustc_typeck/coherence/mod.rs | 39 +++++++++-------- .../outlives/implicit_infer.rs | 43 ++++++++++--------- src/librustc_typeck/variance/constraints.rs | 11 ++--- 26 files changed, 203 insertions(+), 132 deletions(-) diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index b3d732ebcd7dc..5a4fc23a603f1 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -485,7 +485,13 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { ty::Adt(def, _) => def_id_is_local(def.did, in_crate), ty::Foreign(did) => def_id_is_local(did, in_crate), - ty::Dynamic(ref tt, ..) => def_id_is_local(tt.principal().def_id(), in_crate), + ty::Dynamic(ref tt, ..) => { + if let Some(principal) = tt.principal() { + def_id_is_local(principal.def_id(), in_crate) + } else { + false + } + } ty::Error => true, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 373ec2d5e490f..7c4a29ecb54be 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2016,7 +2016,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } - data.principal().with_self_ty(self.tcx(), self_ty) + if let Some(principal) = data.principal() { + principal.with_self_ty(self.tcx(), self_ty) + } else { + // Only auto-trait bounds exist. + return; + } } ty::Infer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); @@ -2108,7 +2113,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // // We always upcast when we can because of reason // #2 (region bounds). - data_a.principal().def_id() == data_b.principal().def_id() + data_a.principal_def_id() == data_b.principal_def_id() && data_b.auto_traits() // All of a's auto traits need to be in b's auto traits. .all(|b| data_a.auto_traits().any(|a| a == b)) @@ -2919,7 +2924,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let self_ty = self.infcx .shallow_resolve(*obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.sty { - ty::Dynamic(ref data, ..) => data.principal().with_self_ty(self.tcx(), self_ty), + ty::Dynamic(ref data, ..) => + data.principal().unwrap_or_else(|| { + span_bug!(obligation.cause.span, "object candidate with no principal") + }).with_self_ty(self.tcx(), self_ty), _ => span_bug!(obligation.cause.span, "object candidate with non-object"), }; @@ -3222,8 +3230,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { (&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => { // See assemble_candidates_for_unsizing for more info. let existential_predicates = data_a.map_bound(|data_a| { - let iter = iter::once(ty::ExistentialPredicate::Trait(data_a.principal())) - .chain( + let iter = + data_a.principal().map(|x| ty::ExistentialPredicate::Trait(x)) + .into_iter().chain( data_a .projection_bounds() .map(|x| ty::ExistentialPredicate::Projection(x)), @@ -3260,7 +3269,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // T -> Trait. (_, &ty::Dynamic(ref data, r)) => { let mut object_dids = data.auto_traits() - .chain(iter::once(data.principal().def_id())); + .chain(data.principal_def_id()); if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) { return Err(TraitNotObjectSafe(did)); } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 76e102d88d7ce..1ba367b8688a6 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -183,7 +183,11 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::FnDef(..) => "fn item".into(), ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(ref inner, ..) => { - format!("trait {}", tcx.item_path_str(inner.principal().def_id())).into() + if let Some(principal) = inner.principal() { + format!("trait {}", tcx.item_path_str(principal.def_id())).into() + } else { + "trait".into() + } } ty::Closure(..) => "closure".into(), ty::Generator(..) => "generator".into(), diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 7fbbfb337ea4f..2b41fc4fe341f 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -71,11 +71,11 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType), ty::RawPtr(_) => Some(PtrSimplifiedType), ty::Dynamic(ref trait_info, ..) => { - let principal_def_id = trait_info.principal().def_id(); - if tcx.trait_is_auto(principal_def_id) { - Some(MarkerTraitObjectSimplifiedType) - } else { - Some(TraitSimplifiedType(principal_def_id)) + match trait_info.principal_def_id() { + Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { + Some(TraitSimplifiedType(principal_def_id)) + } + _ => Some(MarkerTraitObjectSimplifiedType) } } ty::Ref(_, ty, _) => { @@ -140,9 +140,9 @@ impl SimplifiedTypeGen { ArraySimplifiedType => ArraySimplifiedType, PtrSimplifiedType => PtrSimplifiedType, NeverSimplifiedType => NeverSimplifiedType, + MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, TupleSimplifiedType(n) => TupleSimplifiedType(n), TraitSimplifiedType(d) => TraitSimplifiedType(map(d)), - MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)), GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)), GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n), diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index da467f57d2544..417e14054d24f 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -479,7 +479,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { match ty.sty { ty::Adt(adt_def, _) => Some(adt_def.did), - ty::Dynamic(data, ..) => Some(data.principal().def_id()), + ty::Dynamic(data, ..) => data.principal_def_id(), ty::Array(subty, _) | ty::Slice(subty) => characteristic_def_id_of_type(subty), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index a2720bdf385cd..45fb8cf3dc9b4 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -569,13 +569,18 @@ impl<'a, 'gcx, 'tcx> Binder> { impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List> {} impl<'tcx> List> { - pub fn principal(&self) -> ExistentialTraitRef<'tcx> { + pub fn principal(&self) -> Option> { match self[0] { - ExistentialPredicate::Trait(tr) => tr, + ExistentialPredicate::Trait(tr) => Some(tr), other => bug!("first predicate is {:?}", other), } } + + pub fn principal_def_id(&self) -> Option { + self.principal().map(|d| d.def_id) + } + #[inline] pub fn projection_bounds<'a>(&'a self) -> impl Iterator> + 'a { @@ -599,8 +604,12 @@ impl<'tcx> List> { } impl<'tcx> Binder<&'tcx List>> { - pub fn principal(&self) -> PolyExistentialTraitRef<'tcx> { - Binder::bind(self.skip_binder().principal()) + pub fn principal(&self) -> Option>> { + self.skip_binder().principal().map(Binder::bind) + } + + pub fn principal_def_id(&self) -> Option { + self.skip_binder().principal_def_id() } #[inline] @@ -1917,7 +1926,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } Dynamic(ref obj, region) => { out.push(region); - out.extend(obj.principal().skip_binder().substs.regions()); + if let Some(principal) = obj.principal() { + out.extend(principal.skip_binder().substs.regions()); + } } Adt(_, substs) | Opaque(_, substs) => { out.extend(substs.regions()) diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index aacc63c47de61..1fad96435991d 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let cause = self.cause(traits::MiscObligation); let component_traits = - data.auto_traits().chain(once(data.principal().def_id())); + data.auto_traits().chain(data.principal_def_id()); self.out.extend( component_traits.map(|did| traits::Obligation::new( cause.clone(), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 79405b124001d..d55d9c8c2ed1c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -713,16 +713,18 @@ define_print! { // Use a type that can't appear in defaults of type parameters. let dummy_self = tcx.mk_infer(ty::FreshTy(0)); - let principal = tcx - .lift(&self.principal()) - .expect("could not lift TraitRef for printing") - .with_self_ty(tcx, dummy_self); - let projections = self.projection_bounds().map(|p| { - tcx.lift(&p) - .expect("could not lift projection for printing") - .with_self_ty(tcx, dummy_self) - }).collect::>(); - cx.parameterized(f, principal.substs, principal.def_id, &projections)?; + if let Some(principal) = self.principal() { + let principal = tcx + .lift(&principal) + .expect("could not lift TraitRef for printing") + .with_self_ty(tcx, dummy_self); + let projections = self.projection_bounds().map(|p| { + tcx.lift(&p) + .expect("could not lift projection for printing") + .with_self_ty(tcx, dummy_self) + }).collect::>(); + cx.parameterized(f, principal.substs, principal.def_id, &projections)?; + } // Builtin bounds. for did in self.auto_traits() { diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 3a5da29c68118..2b03e99161db8 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -50,7 +50,8 @@ pub struct CodegenCx<'ll, 'tcx: 'll> { /// Cache instances of monomorphic and polymorphic items pub instances: RefCell, &'ll Value>>, /// Cache generated vtables - pub vtables: RefCell, ty::PolyExistentialTraitRef<'tcx>), &'ll Value>>, + pub vtables: RefCell, Option>), &'ll Value>>, /// Cache of constant strings, pub const_cstr_cache: RefCell>, @@ -311,7 +312,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn vtables(&self) -> &RefCell, - ty::PolyExistentialTraitRef<'tcx>), &'ll Value>> + Option>), &'ll Value>> { &self.vtables } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 0fd04e9d20393..72ed55df94658 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -429,7 +429,8 @@ fn trait_pointer_metadata( // But it does not describe the trait's methods. let containing_scope = match trait_type.sty { - ty::Dynamic(ref data, ..) => Some(get_namespace_for_item(cx, data.principal().def_id())), + ty::Dynamic(ref data, ..) => + data.principal_def_id().map(|did| get_namespace_for_item(cx, did)), _ => { bug!("debuginfo: Unexpected trait-object type in \ trait_pointer_metadata(): {:?}", diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index c8cbd735e850d..32432f7e4ec10 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -107,12 +107,16 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } }, ty::Dynamic(ref trait_data, ..) => { - let principal = cx.tcx.normalize_erasing_late_bound_regions( - ty::ParamEnv::reveal_all(), - &trait_data.principal(), - ); - push_item_name(cx, principal.def_id, false, output); - push_type_params(cx, principal.substs, output); + if let Some(principal) = trait_data.principal() { + let principal = cx.tcx.normalize_erasing_late_bound_regions( + ty::ParamEnv::reveal_all(), + &principal, + ); + push_item_name(cx, principal.def_id, false, output); + push_type_params(cx, principal.substs, output); + } else { + output.push_str("dyn '_"); + } }, ty::FnDef(..) | ty::FnPtr(_) => { let sig = t.fn_sig(cx.tcx); diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 31640826262b8..98ad2616eeaae 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx: 'a> VirtualIndex { pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( cx: &Cx, ty: Ty<'tcx>, - trait_ref: ty::PolyExistentialTraitRef<'tcx>, + trait_ref: Option>, ) -> Cx::Value { let tcx = cx.tcx(); @@ -83,8 +83,15 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( // Not in the cache. Build it. let nullptr = cx.const_null(cx.type_i8p()); - let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty)); - let methods = methods.iter().cloned().map(|opt_mth| { + let methods_root; + let methods = if let Some(trait_ref) = trait_ref { + methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty)); + methods_root.iter() + } else { + (&[]).iter() + }; + + let methods = methods.cloned().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { callee::resolve_and_get_fn_for_vtable(cx, def_id, substs) }) diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index c297288b25542..b23155563665d 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -11,7 +11,7 @@ use std::sync::Arc; pub trait MiscMethods<'tcx>: BackendTypes { fn vtables( &self, - ) -> &RefCell, ty::PolyExistentialTraitRef<'tcx>), Self::Value>>; + ) -> &RefCell, Option>), Self::Value>>; fn check_overflow(&self) -> bool; fn instances(&self) -> &RefCell, Self::Value>>; fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value; diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 9a76a36ef2293..19362b6cfdb1c 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -42,7 +42,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> { pub(crate) stack: Vec>, /// A cache for deduplicating vtables - pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>, + pub(super) vtables: FxHashMap<(Ty<'tcx>, Option>), AllocId>, } /// A stack frame. diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 69a52b002ce54..642bbc114f562 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::sync::Lrc; use rustc::ty::{self, Ty}; use rustc::ty::layout::{Size, Align, LayoutOf}; use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic}; @@ -14,7 +15,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> pub fn get_vtable( &mut self, ty: Ty<'tcx>, - poly_trait_ref: ty::PolyExistentialTraitRef<'tcx>, + poly_trait_ref: Option>, ) -> EvalResult<'tcx, Pointer> { trace!("get_vtable(trait_ref={:?})", poly_trait_ref); @@ -24,10 +25,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> return Ok(Pointer::from(vtable).with_default_tag()); } - let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty); - let trait_ref = self.tcx.erase_regions(&trait_ref); + let methods = if let Some(poly_trait_ref) = poly_trait_ref { + let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty); + let trait_ref = self.tcx.erase_regions(&trait_ref); - let methods = self.tcx.vtable_methods(trait_ref); + self.tcx.vtable_methods(trait_ref) + } else { + Lrc::new(Vec::new()) + }; let layout = self.layout_of(ty)?; assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index d81a4d6a4bc84..e299dbc3c8f2f 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -894,20 +894,23 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, !impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars()); if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty { - let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty); - assert!(!poly_trait_ref.has_escaping_bound_vars()); - - // Walk all methods of the trait, including those of its supertraits - let methods = tcx.vtable_methods(poly_trait_ref); - let methods = methods.iter().cloned().filter_map(|method| method) - .map(|(def_id, substs)| ty::Instance::resolve_for_vtable( + if let Some(principal) = trait_ty.principal() { + let poly_trait_ref = principal.with_self_ty(tcx, impl_ty); + assert!(!poly_trait_ref.has_escaping_bound_vars()); + + // Walk all methods of the trait, including those of its supertraits + let methods = tcx.vtable_methods(poly_trait_ref); + let methods = methods.iter().cloned().filter_map(|method| method) + .map(|(def_id, substs)| ty::Instance::resolve_for_vtable( tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap()) - .filter(|&instance| should_monomorphize_locally(tcx, &instance)) - .map(|instance| create_fn_mono_item(instance)); - output.extend(methods); + .filter(|&instance| should_monomorphize_locally(tcx, &instance)) + .map(|instance| create_fn_mono_item(instance)); + output.extend(methods); + } + // Also add the destructor visit_drop_use(tcx, impl_ty, false, output); } diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index e7f4451fdd7ee..7014f539d5754 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -304,13 +304,16 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.push(']'); }, ty::Dynamic(ref trait_data, ..) => { - let principal = trait_data.principal(); - self.push_def_path(principal.def_id(), output); - self.push_type_params( - principal.skip_binder().substs, - trait_data.projection_bounds(), - output, - ); + if let Some(principal) = trait_data.principal() { + self.push_def_path(principal.def_id(), output); + self.push_type_params( + principal.skip_binder().substs, + trait_data.projection_bounds(), + output, + ); + } else { + output.push_str("dyn '_"); + } }, ty::Foreign(did) => self.push_def_path(did, output), ty::FnDef(..) | diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 9d418704f487d..38f9adee0a48f 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -63,7 +63,7 @@ enum PointerKind<'tcx> { /// No metadata attached, ie pointer to sized type or foreign type Thin, /// A trait object - Vtable(DefId), + Vtable(Option), /// Slice Length, /// The unsize info of this projection @@ -95,7 +95,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Ok(match t.sty { ty::Slice(_) | ty::Str => Some(PointerKind::Length), ty::Dynamic(ref tty, ..) => - Some(PointerKind::Vtable(tty.principal().def_id())), + Some(PointerKind::Vtable(tty.principal_def_id())), ty::Adt(def, substs) if def.is_struct() => { match def.non_enum_variant().fields.last() { None => Some(PointerKind::Thin), diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 25b1c0836c28b..ff3b22dd1dec7 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -190,7 +190,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.deduce_sig_from_projection(None, &pb) }) .next(); - let kind = self.tcx.lang_items().fn_trait_kind(object_type.principal().def_id()); + let kind = object_type.principal_def_id().and_then(|did| { + self.tcx.lang_items().fn_trait_kind(did) + }); (sig, kind) } ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 4343f751e6aee..2cf2974a45a1c 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -280,7 +280,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { .include_raw_pointers() .filter_map(|(ty, _)| match ty.sty { - ty::Dynamic(ref data, ..) => Some(closure(self, ty, data.principal())), + ty::Dynamic(ref data, ..) => { + Some(closure(self, ty, data.principal().unwrap_or_else(|| { + span_bug!(self.span, "calling trait method on empty object?") + }))) + }, _ => None, } ) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 30a868622a596..9a828ce01775c 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -505,17 +505,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { match self_ty.value.value.sty { ty::Dynamic(ref data, ..) => { - let p = data.principal(); - self.fcx.probe(|_| { - let InferOk { value: self_ty, obligations: _ } = - self.fcx.probe_instantiate_query_response( - self.span, &self.orig_steps_var_values, self_ty) - .unwrap_or_else(|_| { - span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty) - }); - self.assemble_inherent_candidates_from_object(self_ty); - }); - self.assemble_inherent_impl_candidates_for_type(p.def_id()); + if let Some(p) = data.principal() { + self.fcx.probe(|_| { + let InferOk { value: self_ty, obligations: _ } = + self.fcx.probe_instantiate_query_response( + self.span, &self.orig_steps_var_values, self_ty) + .unwrap_or_else(|_| { + span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty) + }); + self.assemble_inherent_candidates_from_object(self_ty); + }); + self.assemble_inherent_impl_candidates_for_type(p.def_id()); + } } ty::Adt(def, _) => { self.assemble_inherent_impl_candidates_for_type(def.did); @@ -680,10 +681,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self_ty); let principal = match self_ty.sty { - ty::Dynamic(ref data, ..) => data.principal(), - _ => span_bug!(self.span, "non-object {:?} in assemble_inherent_candidates_from_object", - self_ty) - }; + ty::Dynamic(ref data, ..) => Some(data), + _ => None + }.and_then(|data| data.principal()).unwrap_or_else(|| { + span_bug!(self.span, "non-object {:?} in assemble_inherent_candidates_from_object", + self_ty) + }); // It is illegal to invoke a method on a trait instance that // refers to the `Self` type. An error will be reported by diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 98c425655d2d3..23bcd88d6afb5 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -651,7 +651,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Adt(def, _) => def.did.is_local(), ty::Foreign(did) => did.is_local(), - ty::Dynamic(ref tr, ..) => tr.principal().def_id().is_local(), + ty::Dynamic(ref tr, ..) => + tr.principal().map(|d| d.def_id().is_local()).unwrap_or(false), ty::Param(_) => true, diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index b9324a17fccd2..93cc86423ace3 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -95,8 +95,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> { ty::Foreign(did) => { self.check_def_id(item, did); } - ty::Dynamic(ref data, ..) => { - self.check_def_id(item, data.principal().def_id()); + ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => { + self.check_def_id(item, data.principal_def_id().unwrap()); } ty::Char => { self.check_primitive_impl(def_id, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 060fc4977a709..ce71be07efd42 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -171,25 +171,28 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. - if !tcx.is_object_safe(data.principal().def_id()) { - // This is an error, but it will be reported by wfcheck. Ignore it here. - // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. - } else { - let mut supertrait_def_ids = - traits::supertrait_def_ids(tcx, data.principal().def_id()); - if supertrait_def_ids.any(|d| d == trait_def_id) { - let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()); - struct_span_err!(tcx.sess, - sp, - E0371, - "the object type `{}` automatically implements the trait `{}`", - trait_ref.self_ty(), - tcx.item_path_str(trait_def_id)) - .span_label(sp, format!("`{}` automatically implements trait `{}`", - trait_ref.self_ty(), - tcx.item_path_str(trait_def_id))) - .emit(); + if let Some(principal_def_id) = data.principal_def_id() { + if !tcx.is_object_safe(principal_def_id) { + // This is an error, but it will be reported by wfcheck. Ignore it here. + // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. + } else { + let mut supertrait_def_ids = + traits::supertrait_def_ids(tcx, principal_def_id); + if supertrait_def_ids.any(|d| d == trait_def_id) { + let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()); + struct_span_err!(tcx.sess, + sp, + E0371, + "the object type `{}` automatically implements the trait `{}`", + trait_ref.self_ty(), + tcx.item_path_str(trait_def_id)) + .span_label(sp, format!("`{}` automatically implements trait `{}`", + trait_ref.self_ty(), + tcx.item_path_str(trait_def_id))) + .emit(); + } } } + // FIXME: also check auto-trait def-ids? (e.g. `impl Sync for Foo+Sync`)? } } diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 8929f5e5c6a3e..e388a3e0d0c2f 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -194,27 +194,28 @@ fn insert_required_predicates_to_be_wf<'tcx>( debug!("Dynamic"); debug!("field_ty = {}", &field_ty); debug!("ty in field = {}", &ty); - let ex_trait_ref = obj.principal(); - // Here, we are passing the type `usize` as a - // placeholder value with the function - // `with_self_ty`, since there is no concrete type - // `Self` for a `dyn Trait` at this - // stage. Therefore when checking explicit - // predicates in `check_explicit_predicates` we - // need to ignore checking the explicit_map for - // Self type. - let substs = ex_trait_ref - .with_self_ty(tcx, tcx.types.usize) - .skip_binder() - .substs; - check_explicit_predicates( - tcx, - &ex_trait_ref.skip_binder().def_id, - substs, - required_predicates, - explicit_map, - IgnoreSelfTy(true), - ); + if let Some(ex_trait_ref) = obj.principal() { + // Here, we are passing the type `usize` as a + // placeholder value with the function + // `with_self_ty`, since there is no concrete type + // `Self` for a `dyn Trait` at this + // stage. Therefore when checking explicit + // predicates in `check_explicit_predicates` we + // need to ignore checking the explicit_map for + // Self type. + let substs = ex_trait_ref + .with_self_ty(tcx, tcx.types.usize) + .skip_binder() + .substs; + check_explicit_predicates( + tcx, + &ex_trait_ref.skip_binder().def_id, + substs, + required_predicates, + explicit_map, + IgnoreSelfTy(true), + ); + } } ty::Projection(obj) => { diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 51d89688dc2a0..868c1132e44c5 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -301,11 +301,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let contra = self.contravariant(variance); self.add_constraints_from_region(current, r, contra); - let poly_trait_ref = data - .principal() - .with_self_ty(self.tcx(), self.tcx().types.err); - self.add_constraints_from_trait_ref( - current, *poly_trait_ref.skip_binder(), variance); + if let Some(poly_trait_ref) = data.principal() { + let poly_trait_ref = + poly_trait_ref.with_self_ty(self.tcx(), self.tcx().types.err); + self.add_constraints_from_trait_ref( + current, *poly_trait_ref.skip_binder(), variance); + } for projection in data.projection_bounds() { self.add_constraints_from_ty( From 571a15bd15f02a65f1978b9b72589beb89a60782 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 4 Dec 2018 15:17:35 +0200 Subject: [PATCH 02/12] avoid giving a principal to marker-only trait objects Fixes #33140. --- src/librustc/ty/sty.rs | 2 +- src/librustc_typeck/astconv.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 45fb8cf3dc9b4..10f89c965d170 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -572,7 +572,7 @@ impl<'tcx> List> { pub fn principal(&self) -> Option> { match self[0] { ExistentialPredicate::Trait(tr) => Some(tr), - other => bug!("first predicate is {:?}", other), + _ => None } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1db7141917f98..22d609ea8a439 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1138,13 +1138,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { auto_traits.dedup(); // Calling `skip_binder` is okay, because the predicates are re-bound. + let principal = if tcx.trait_is_auto(existential_principal.def_id()) { + ty::ExistentialPredicate::AutoTrait(existential_principal.def_id()) + } else { + ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()) + }; let mut v = - iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder())) + iter::once(principal) .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait)) .chain(existential_projections .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder()))) .collect::>(); v.sort_by(|a, b| a.stable_cmp(tcx, b)); + v.dedup(); let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter())); // Use explicitly-specified region bound. From 4ab27b255cad40d62954fa5e619e8d243e70bc8c Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 15 Dec 2018 01:52:50 +0200 Subject: [PATCH 03/12] fix ppaux --- src/librustc/util/ppaux.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d55d9c8c2ed1c..b49852be38dde 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -712,6 +712,7 @@ define_print! { ty::tls::with(|tcx| { // Use a type that can't appear in defaults of type parameters. let dummy_self = tcx.mk_infer(ty::FreshTy(0)); + let mut first = true; if let Some(principal) = self.principal() { let principal = tcx @@ -724,11 +725,17 @@ define_print! { .with_self_ty(tcx, dummy_self) }).collect::>(); cx.parameterized(f, principal.substs, principal.def_id, &projections)?; + first = false; } // Builtin bounds. for did in self.auto_traits() { - write!(f, " + {}", tcx.item_path_str(did))?; + if !first { + write!(f, " + ")?; + } + first = false; + + write!(f, "{}", tcx.item_path_str(did))?; } Ok(()) From c2aa7485d28f684834630b754bd68bb5850f2f4a Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 15 Dec 2018 03:21:00 +0200 Subject: [PATCH 04/12] add tests --- .../traits/principal-less-trait-objects.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/test/run-pass/traits/principal-less-trait-objects.rs diff --git a/src/test/run-pass/traits/principal-less-trait-objects.rs b/src/test/run-pass/traits/principal-less-trait-objects.rs new file mode 100644 index 0000000000000..0984362993cb9 --- /dev/null +++ b/src/test/run-pass/traits/principal-less-trait-objects.rs @@ -0,0 +1,41 @@ +// Check that trait-objects without a principal codegen properly. + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::mem; + +// Array is to make sure the size is not exactly pointer-size, so +// we can be sure we are measuring the right size in the +// `size_of_val` test. +struct SetOnDrop<'a>(&'a AtomicUsize, [u8; 64]); +impl<'a> Drop for SetOnDrop<'a> { + fn drop(&mut self) { + self.0.store(self.0.load(Ordering::Relaxed)+1, Ordering::Relaxed); + } +} + +trait TypeEq {} +impl TypeEq for T {} +fn assert_types_eq() where U: TypeEq {} + +fn main() { + // Check that different ways of writing the same type are equal. + assert_types_eq::(); + assert_types_eq::(); + assert_types_eq::(); + + // Check that codegen works. + // + // Using `AtomicUsize` here because `Cell` is not `Sync`, and + // so can't be made into a `Box`. + let c = AtomicUsize::new(0); + { + let d: Box = Box::new(SetOnDrop(&c, [0; 64])); + + assert_eq!(mem::size_of_val(&*d), + mem::size_of::()); + assert_eq!(mem::align_of_val(&*d), + mem::align_of::()); + assert_eq!(c.load(Ordering::Relaxed), 0); + } + assert_eq!(c.load(Ordering::Relaxed), 1); +} From 64857de2bd49ddf24600835cc3a7d5917504c769 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 15 Dec 2018 17:35:55 +0200 Subject: [PATCH 05/12] hack-fix to rustdoc --- src/librustdoc/clean/mod.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 38b2452b420e9..0183e0932601c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2643,13 +2643,24 @@ impl<'tcx> Clean for Ty<'tcx> { } } ty::Dynamic(ref obj, ref reg) => { - let principal = obj.principal(); - let did = principal.def_id(); + // HACK: pick the first `did` as the `did` of the trait object. Someone + // might want to implement "native" support for marker-trait-only + // trait objects. + let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits()); + let did = dids.next().unwrap_or_else(|| { + panic!("found trait object `{:?}` with no traits?", self) + }); + let substs = match obj.principal() { + Some(principal) => principal.skip_binder().substs, + // marker traits have no substs. + _ => cx.tcx.intern_substs(&[]) + }; + inline::record_extern_fqn(cx, did, TypeKind::Trait); let mut typarams = vec![]; reg.clean(cx).map(|b| typarams.push(GenericBound::Outlives(b))); - for did in obj.auto_traits() { + for did in dids { let empty = cx.tcx.intern_substs(&[]); let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); @@ -2675,7 +2686,7 @@ impl<'tcx> Clean for Ty<'tcx> { } let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), - false, bindings, principal.skip_binder().substs); + false, bindings, substs); ResolvedPath { path, typarams: Some(typarams), From 391a7ebd830bc8118a9d92979d2660bfc63b0315 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 18 Dec 2018 00:50:58 +0200 Subject: [PATCH 06/12] add comment to >::principal --- src/librustc/ty/sty.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 10f89c965d170..05e10784e2dba 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -569,6 +569,31 @@ impl<'a, 'gcx, 'tcx> Binder> { impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List> {} impl<'tcx> List> { + /// Returns the "principal def id" of this set of existential predicates. + /// + /// A Rust trait object type consists (in addition to a lifetime bound) + /// of a set of trait bounds, which are separated into any number + /// of auto-trait bounds, and at most 1 non-auto-trait bound. The + /// non-auto-trait bound is called the "principal" of the trait + /// object. + /// + /// Only the principal can have methods or type parameters (because + /// auto traits can have neither of them). This is important, because + /// it means the auto traits can be treated as an unordered set (methods + /// would force an order for the vtable, while relating traits with + /// type parameters without knowing the order to relate them in is + /// a rather non-trivial task). + /// + /// For example, in the trait object `dyn fmt::Debug + Sync`, the + /// principal bound is `Some(fmt::Debug)`, while the auto-trait bounds + /// are the set `{Sync}`. + /// + /// It is also possible to have a "trivial" trait object that + /// consists only of auto traits, with no principal - for example, + /// `dyn Send + Sync`. In that case, the set of auto-trait bounds + /// is `{Send, Sync}`, while there is no principal. These trait objects + /// have a "trivial" vtable consisting of just the size, alignment, + /// and destructor. pub fn principal(&self) -> Option> { match self[0] { ExistentialPredicate::Trait(tr) => Some(tr), @@ -576,7 +601,6 @@ impl<'tcx> List> { } } - pub fn principal_def_id(&self) -> Option { self.principal().map(|d| d.def_id) } From e030aa801583ec7ce250088bb180d65b760eedec Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 1 Jan 2019 23:22:37 +0200 Subject: [PATCH 07/12] Revert "fix stupid bug" This reverts commit 6e4b2b3ae79770c7ccfcdbfc90dc34fe47ec5f09. --- .../coherence/inherent_impls_overlap.rs | 86 ++++++++----------- 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 8d27a77b29c6c..0fe8e0b1d1b57 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -88,38 +88,12 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i + 1)..] { - // First, check if the impl was forbidden under the - // old rules. In that case, just have an error. - let used_to_be_allowed = traits::overlapping_impls( + let mut used_to_be_allowed = traits::overlapping_impls( self.tcx, impl1_def_id, impl2_def_id, IntercrateMode::Issue43355, TraitObjectMode::NoSquash, - |overlap| { - self.check_for_common_items_in_impls( - impl1_def_id, - impl2_def_id, - overlap, - None, - ); - false - }, - || true, - ); - - if !used_to_be_allowed { - continue; - } - - // Then, check if the impl was forbidden under only - // #43355. In that case, emit an #43355 error. - let used_to_be_allowed = traits::overlapping_impls( - self.tcx, - impl1_def_id, - impl2_def_id, - IntercrateMode::Fixed, - TraitObjectMode::NoSquash, |overlap| { self.check_for_common_items_in_impls( impl1_def_id, @@ -132,29 +106,45 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { || true, ); - if !used_to_be_allowed { - continue; + if used_to_be_allowed { + used_to_be_allowed = traits::overlapping_impls( + self.tcx, + impl1_def_id, + impl2_def_id, + IntercrateMode::Fixed, + TraitObjectMode::NoSquash, + |overlap| { + self.check_for_common_items_in_impls( + impl1_def_id, + impl2_def_id, + overlap, + None, + ); + false + }, + || true, + ); } - // Then, check if the impl was forbidden under - // #33140. In that case, emit a #33140 error. - traits::overlapping_impls( - self.tcx, - impl1_def_id, - impl2_def_id, - IntercrateMode::Fixed, - TraitObjectMode::SquashAutoTraitsIssue33140, - |overlap| { - self.check_for_common_items_in_impls( - impl1_def_id, - impl2_def_id, - overlap, - Some(FutureCompatOverlapErrorKind::Issue33140), - ); - false - }, - || true, - ); + if used_to_be_allowed { + traits::overlapping_impls( + self.tcx, + impl1_def_id, + impl2_def_id, + IntercrateMode::Fixed, + TraitObjectMode::SquashAutoTraitsIssue33140, + |overlap| { + self.check_for_common_items_in_impls( + impl1_def_id, + impl2_def_id, + overlap, + Some(FutureCompatOverlapErrorKind::Issue33140), + ); + false + }, + || true, + ); + } } } } From 7eb444e4f18d50e48868861010b3d87d741d1218 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 1 Jan 2019 23:53:52 +0200 Subject: [PATCH 08/12] Revert "add coherence future-compat warnings for marker-only trait objects" This reverts commit 760639635facb6c9a0926ac9278bcba71880b0b3. --- src/librustc/infer/combine.rs | 4 - src/librustc/infer/equate.rs | 4 - src/librustc/infer/glb.rs | 6 +- src/librustc/infer/lub.rs | 6 +- src/librustc/infer/mod.rs | 19 +--- src/librustc/infer/nll_relate/mod.rs | 14 --- src/librustc/infer/sub.rs | 6 +- src/librustc/traits/coherence.rs | 12 +-- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/mod.rs | 2 - src/librustc/traits/select.rs | 12 +-- src/librustc/traits/specialize/mod.rs | 20 ++--- .../traits/specialize/specialization_graph.rs | 44 +-------- src/librustc/ty/_match.rs | 13 +-- src/librustc/ty/relate.rs | 49 +--------- .../chalk_context/resolvent_ops.rs | 6 +- .../coherence/inherent_impls_overlap.rs | 89 ++++++------------- 17 files changed, 54 insertions(+), 254 deletions(-) diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index ed251d81e625e..40c11695d51e2 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -337,10 +337,6 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' self.infcx.tcx } - fn trait_object_mode(&self) -> relate::TraitObjectMode { - self.infcx.trait_object_mode() - } - fn tag(&self) -> &'static str { "Generalizer" } diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 38d3258d140e1..60a7eb0d54f8b 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -29,10 +29,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() } - fn trait_object_mode(&self) -> relate::TraitObjectMode { - self.fields.infcx.trait_object_mode() - } - fn a_is_expected(&self) -> bool { self.a_is_expected } fn relate_item_substs(&mut self, diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs index aebacd28f4581..635a6d00270b7 100644 --- a/src/librustc/infer/glb.rs +++ b/src/librustc/infer/glb.rs @@ -5,7 +5,7 @@ use super::Subtype; use traits::ObligationCause; use ty::{self, Ty, TyCtxt}; -use ty::relate::{self, Relate, RelateResult, TypeRelation}; +use ty::relate::{Relate, RelateResult, TypeRelation}; /// "Greatest lower bound" (common subtype) pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> { @@ -26,10 +26,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> { fn tag(&self) -> &'static str { "Glb" } - fn trait_object_mode(&self) -> relate::TraitObjectMode { - self.fields.infcx.trait_object_mode() - } - fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() } fn a_is_expected(&self) -> bool { self.a_is_expected } diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs index c6af8e4967150..0b9839f69fa2a 100644 --- a/src/librustc/infer/lub.rs +++ b/src/librustc/infer/lub.rs @@ -5,7 +5,7 @@ use super::Subtype; use traits::ObligationCause; use ty::{self, Ty, TyCtxt}; -use ty::relate::{self, Relate, RelateResult, TypeRelation}; +use ty::relate::{Relate, RelateResult, TypeRelation}; /// "Least upper bound" (common supertype) pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> { @@ -26,10 +26,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> { fn tag(&self) -> &'static str { "Lub" } - fn trait_object_mode(&self) -> relate::TraitObjectMode { - self.fields.infcx.trait_object_mode() - } - fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() } fn a_is_expected(&self) -> bool { self.a_is_expected } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 2d3fb137fafdd..958982545750f 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -25,7 +25,7 @@ use syntax_pos::{self, Span}; use traits::{self, ObligationCause, PredicateObligations, TraitEngine}; use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use ty::fold::TypeFoldable; -use ty::relate::{RelateResult, TraitObjectMode}; +use ty::relate::RelateResult; use ty::subst::{Kind, Substs}; use ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners}; use ty::{FloatVid, IntVid, TyVid}; @@ -171,9 +171,6 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { // This flag is true while there is an active snapshot. in_snapshot: Cell, - // The TraitObjectMode used here, - trait_object_mode: TraitObjectMode, - // A set of constraints that regionck must validate. Each // constraint has the form `T:'a`, meaning "some type `T` must // outlive the lifetime 'a". These constraints derive from @@ -465,7 +462,6 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { arena: SyncDroplessArena, interners: Option>, fresh_tables: Option>>, - trait_object_mode: TraitObjectMode, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { @@ -475,7 +471,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { arena: SyncDroplessArena::default(), interners: None, fresh_tables: None, - trait_object_mode: TraitObjectMode::NoSquash, } } } @@ -488,12 +483,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { self } - pub fn with_trait_object_mode(mut self, mode: TraitObjectMode) -> Self { - debug!("with_trait_object_mode: setting mode to {:?}", mode); - self.trait_object_mode = mode; - self - } - /// Given a canonical value `C` as a starting point, create an /// inference context that contains each of the bound values /// within instantiated as a fresh variable. The `f` closure is @@ -520,7 +509,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { pub fn enter(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R { let InferCtxtBuilder { global_tcx, - trait_object_mode, ref arena, ref mut interners, ref fresh_tables, @@ -532,7 +520,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { f(InferCtxt { tcx, in_progress_tables, - trait_object_mode, projection_cache: Default::default(), type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(ut::UnificationTable::new()), @@ -614,10 +601,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.in_snapshot.get() } - pub fn trait_object_mode(&self) -> TraitObjectMode { - self.trait_object_mode - } - pub fn freshen>(&self, t: T) -> T { t.fold_with(&mut self.freshener()) } diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index db5ec3c1c0c46..7671a47135702 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -372,13 +372,6 @@ where self.infcx.tcx } - fn trait_object_mode(&self) -> relate::TraitObjectMode { - // squashing should only be done in coherence, not NLL - assert_eq!(self.infcx.trait_object_mode(), - relate::TraitObjectMode::NoSquash); - relate::TraitObjectMode::NoSquash - } - fn tag(&self) -> &'static str { "nll::subtype" } @@ -693,13 +686,6 @@ where self.infcx.tcx } - fn trait_object_mode(&self) -> relate::TraitObjectMode { - // squashing should only be done in coherence, not NLL - assert_eq!(self.infcx.trait_object_mode(), - relate::TraitObjectMode::NoSquash); - relate::TraitObjectMode::NoSquash - } - fn tag(&self) -> &'static str { "nll::generalizer" } diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 1d4842a6d5626..df76d1d3afb34 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -5,7 +5,7 @@ use traits::Obligation; use ty::{self, Ty, TyCtxt}; use ty::TyVar; use ty::fold::TypeFoldable; -use ty::relate::{self, Cause, Relate, RelateResult, TypeRelation}; +use ty::relate::{Cause, Relate, RelateResult, TypeRelation}; use std::mem; /// Ensures `a` is made a subtype of `b`. Returns `a` on success. @@ -33,10 +33,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Sub<'combine, 'infcx, 'gcx, 'tcx> { fn tag(&self) -> &'static str { "Sub" } - fn trait_object_mode(&self) -> relate::TraitObjectMode { - self.fields.infcx.trait_object_mode() - } - fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx } fn a_is_expected(&self) -> bool { self.a_is_expected } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 5a4fc23a603f1..54687bd76e59d 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -11,7 +11,6 @@ use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause}; use traits::IntercrateMode; use traits::select::IntercrateAmbiguityCause; use ty::{self, Ty, TyCtxt}; -use ty::relate::TraitObjectMode; use ty::fold::TypeFoldable; use ty::subst::Subst; @@ -55,7 +54,6 @@ pub fn overlapping_impls<'gcx, F1, F2, R>( impl1_def_id: DefId, impl2_def_id: DefId, intercrate_mode: IntercrateMode, - trait_object_mode: TraitObjectMode, on_overlap: F1, no_overlap: F2, ) -> R @@ -66,14 +64,12 @@ where debug!("overlapping_impls(\ impl1_def_id={:?}, \ impl2_def_id={:?}, - intercrate_mode={:?}, - trait_object_mode={:?})", + intercrate_mode={:?})", impl1_def_id, impl2_def_id, - intercrate_mode, - trait_object_mode); + intercrate_mode); - let overlaps = tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| { + let overlaps = tcx.infer_ctxt().enter(|infcx| { let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode); overlap(selcx, impl1_def_id, impl2_def_id).is_some() }); @@ -85,7 +81,7 @@ where // In the case where we detect an error, run the check again, but // this time tracking intercrate ambuiguity causes for better // diagnostics. (These take time and can lead to false errors.) - tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| { + tcx.infer_ctxt().enter(|infcx| { let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode); selcx.enable_tracking_intercrate_ambiguity_causes(); on_overlap(overlap(selcx, impl1_def_id, impl2_def_id).unwrap()) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 21352ac1053a8..741053cc17737 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -449,7 +449,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), - true,); + true); let all_impls = self.tcx.all_impls(trait_ref.def_id()); match simp { diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b42d742b7f841..1a9f1ada111bd 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -56,8 +56,6 @@ pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; pub use self::specialize::{OverlapError, specialization_graph, translate_substs}; pub use self::specialize::find_associated_item; -pub use self::specialize::specialization_graph::FutureCompatOverlapError; -pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 7c4a29ecb54be..9ad974d8e084a 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -33,7 +33,7 @@ use infer::{InferCtxt, InferOk, TypeFreshener}; use middle::lang_items; use mir::interpret::GlobalId; use ty::fast_reject; -use ty::relate::{TypeRelation, TraitObjectMode}; +use ty::relate::TypeRelation; use ty::subst::{Subst, Substs}; use ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; @@ -1416,13 +1416,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return false; } - // Same idea as the above, but for alt trait object modes. These - // should only be used in intercrate mode - better safe than sorry. - if self.infcx.trait_object_mode() != TraitObjectMode::NoSquash { - bug!("using squashing TraitObjectMode outside of intercrate mode? param_env={:?}", - param_env); - } - // Otherwise, we can use the global cache. true } @@ -3580,8 +3573,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { previous: &ty::PolyTraitRef<'tcx>, current: &ty::PolyTraitRef<'tcx>, ) -> bool { - let mut matcher = ty::_match::Match::new( - self.tcx(), self.infcx.trait_object_mode()); + let mut matcher = ty::_match::Match::new(self.tcx()); matcher.relate(previous, current).is_ok() } diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 63f52a34dfa70..5ab54b2c99d42 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -14,11 +14,11 @@ pub mod specialization_graph; use hir::def_id::DefId; use infer::{InferCtxt, InferOk}; use lint; -use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; use traits::coherence; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax_pos::DUMMY_SP; +use traits::{self, ObligationCause, TraitEngine}; use traits::select::IntercrateAmbiguityCause; use ty::{self, TyCtxt, TypeFoldable}; use ty::subst::{Subst, Substs}; @@ -27,7 +27,6 @@ use super::{SelectionContext, FulfillmentContext}; use super::util::impl_trait_ref_and_oblig; /// Information pertinent to an overlapping impl error. -#[derive(Debug)] pub struct OverlapError { pub with_impl: DefId, pub trait_desc: String, @@ -311,9 +310,8 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>( let insert_result = sg.insert(tcx, impl_def_id); // Report error if there was one. let (overlap, used_to_be_allowed) = match insert_result { - Err(overlap) => (Some(overlap), None), - Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)), - Ok(None) => (None, None) + Err(overlap) => (Some(overlap), false), + Ok(opt_overlap) => (opt_overlap, true) }; if let Some(overlap) = overlap { @@ -323,20 +321,14 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>( String::new(), |ty| { format!(" for type `{}`", ty) }), - if used_to_be_allowed.is_some() { " (E0119)" } else { "" } + if used_to_be_allowed { " (E0119)" } else { "" } ); let impl_span = tcx.sess.source_map().def_span( tcx.span_of_impl(impl_def_id).unwrap() ); - let mut err = if let Some(kind) = used_to_be_allowed { - let lint = match kind { - FutureCompatOverlapErrorKind::Issue43355 => - lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, - FutureCompatOverlapErrorKind::Issue33140 => - lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS, - }; + let mut err = if used_to_be_allowed { tcx.struct_span_lint_node( - lint, + lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, tcx.hir().as_local_node_id(impl_def_id).unwrap(), impl_span, &msg) diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index db3547b2b7479..c22adeb55a269 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -7,7 +7,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, use traits; use ty::{self, TyCtxt, TypeFoldable}; use ty::fast_reject::{self, SimplifiedType}; -use ty::relate::TraitObjectMode; use rustc_data_structures::sync::Lrc; use syntax::ast::Ident; use util::captures::Captures; @@ -59,22 +58,10 @@ struct Children { blanket_impls: Vec, } -#[derive(Copy, Clone, Debug)] -pub enum FutureCompatOverlapErrorKind { - Issue43355, - Issue33140, -} - -#[derive(Debug)] -pub struct FutureCompatOverlapError { - pub error: OverlapError, - pub kind: FutureCompatOverlapErrorKind -} - /// The result of attempting to insert an impl into a group of children. enum Inserted { /// The impl was inserted as a new child in this group of children. - BecameNewSibling(Option), + BecameNewSibling(Option), /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc. ReplaceChildren(Vec), @@ -174,7 +161,6 @@ impl<'a, 'gcx, 'tcx> Children { possible_sibling, impl_def_id, traits::IntercrateMode::Issue43355, - TraitObjectMode::NoSquash, |overlap| { if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { return Ok((false, false)); @@ -205,36 +191,12 @@ impl<'a, 'gcx, 'tcx> Children { replace_children.push(possible_sibling); } else { if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { - // do future-compat checks for overlap. Have issue #43355 - // errors overwrite issue #33140 errors when both are present. - - traits::overlapping_impls( - tcx, - possible_sibling, - impl_def_id, - traits::IntercrateMode::Fixed, - TraitObjectMode::SquashAutoTraitsIssue33140, - |overlap| { - last_lint = Some(FutureCompatOverlapError { - error: overlap_error(overlap), - kind: FutureCompatOverlapErrorKind::Issue33140 - }); - }, - || (), - ); - traits::overlapping_impls( tcx, possible_sibling, impl_def_id, traits::IntercrateMode::Fixed, - TraitObjectMode::NoSquash, - |overlap| { - last_lint = Some(FutureCompatOverlapError { - error: overlap_error(overlap), - kind: FutureCompatOverlapErrorKind::Issue43355 - }); - }, + |overlap| last_lint = Some(overlap_error(overlap)), || (), ); } @@ -301,7 +263,7 @@ impl<'a, 'gcx, 'tcx> Graph { pub fn insert(&mut self, tcx: TyCtxt<'a, 'gcx, 'tcx>, impl_def_id: DefId) - -> Result, OverlapError> { + -> Result, OverlapError> { assert!(impl_def_id.is_local()); let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs index 3657a880804e1..34b94d4217d8b 100644 --- a/src/librustc/ty/_match.rs +++ b/src/librustc/ty/_match.rs @@ -19,24 +19,17 @@ use ty::relate::{self, Relate, TypeRelation, RelateResult}; /// important thing about the result is Ok/Err. Also, matching never /// affects any type variables or unification state. pub struct Match<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx>, - trait_object_mode: relate::TraitObjectMode + tcx: TyCtxt<'a, 'gcx, 'tcx> } impl<'a, 'gcx, 'tcx> Match<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, - trait_object_mode: relate::TraitObjectMode) - -> Match<'a, 'gcx, 'tcx> { - Match { tcx, trait_object_mode } + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Match<'a, 'gcx, 'tcx> { + Match { tcx } } } impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Match<'a, 'gcx, 'tcx> { fn tag(&self) -> &'static str { "Match" } - fn trait_object_mode(&self) -> relate::TraitObjectMode { - self.trait_object_mode - } - fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx } fn a_is_expected(&self) -> bool { true } // irrelevant diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 84e15a751353e..43ec90eb95bec 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -25,20 +25,9 @@ pub enum Cause { ExistentialRegionBound, // relating an existential region bound } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum TraitObjectMode { - NoSquash, - /// A temporary mode to treat `Send + Sync = Sync + Send`, should be - /// used only in coherence. - SquashAutoTraitsIssue33140 -} - pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized { fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx>; - /// Return the trait object mode to be used. - fn trait_object_mode(&self) -> TraitObjectMode; - /// Returns a static string we can use for printouts. fn tag(&self) -> &'static str; @@ -597,44 +586,14 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List> { a: &Self, b: &Self) -> RelateResult<'tcx, Self> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - use ty::ExistentialPredicate::*; + where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - let tcx = relation.tcx(); - let (a_buf, b_buf); - let (a_norm, b_norm): (&[_], &[_]) = match relation.trait_object_mode() { - TraitObjectMode::NoSquash => { - (a, b) - } - TraitObjectMode::SquashAutoTraitsIssue33140 => { - // Treat auto-trait "principal" components as equal - // to the non-principal components, to make - // `dyn Send+Sync = dyn Sync+Send`. - let normalize = |d: &[ty::ExistentialPredicate<'tcx>]| { - let mut result: Vec<_> = d.iter().map(|pi| match pi { - Trait(ref a) if tcx.trait_is_auto(a.def_id) => { - AutoTrait(a.def_id) - }, - other => *other - }).collect(); - - result.sort_by(|a, b| a.stable_cmp(tcx, b)); - result.dedup(); - result - }; - - a_buf = normalize(a); - b_buf = normalize(b); - - (&a_buf, &b_buf) - } - }; - - if a_norm.len() != b_norm.len() { + if a.len() != b.len() { return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); } - let v = a_norm.iter().zip(b_norm.iter()).map(|(ep_a, ep_b)| { + let tcx = relation.tcx(); + let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| { use ty::ExistentialPredicate::*; match (*ep_a, *ep_b) { (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)), diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index f7bbf621c0973..932501cc04fe0 100644 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ b/src/librustc_traits/chalk_context/resolvent_ops.rs @@ -17,7 +17,7 @@ use rustc::traits::{ }; use rustc::ty::{self, Ty}; use rustc::ty::subst::Kind; -use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation}; +use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use syntax_pos::DUMMY_SP; use super::{ChalkInferenceContext, ChalkArenas, ChalkExClause, ConstrainedSubst}; @@ -157,10 +157,6 @@ impl TypeRelation<'cx, 'gcx, 'tcx> for AnswerSubstitutor<'cx, 'gcx, 'tcx> { self.infcx.tcx } - fn trait_object_mode(&self) -> relate::TraitObjectMode { - self.infcx.trait_object_mode() - } - fn tag(&self) -> &'static str { "chalk_context::answer_substitutor" } diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 0fe8e0b1d1b57..52dee29294cb7 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -2,9 +2,8 @@ use namespace::Namespace; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::traits::{self, IntercrateMode, FutureCompatOverlapErrorKind}; +use rustc::traits::{self, IntercrateMode}; use rustc::ty::TyCtxt; -use rustc::ty::relate::TraitObjectMode; use lint; @@ -20,11 +19,9 @@ struct InherentOverlapChecker<'a, 'tcx: 'a> { } impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { - fn check_for_common_items_in_impls( - &self, impl1: DefId, impl2: DefId, - overlap: traits::OverlapResult, - used_to_be_allowed: Option) - { + fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId, + overlap: traits::OverlapResult, + used_to_be_allowed: bool) { let name_and_namespace = |def_id| { let item = self.tcx.associated_item(def_id); @@ -40,28 +37,19 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { for &item2 in &impl_items2[..] { if (name, namespace) == name_and_namespace(item2) { let node_id = self.tcx.hir().as_local_node_id(impl1); - let mut err = match used_to_be_allowed { - Some(kind) if node_id.is_some() => { - let lint = match kind { - FutureCompatOverlapErrorKind::Issue43355 => - lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, - FutureCompatOverlapErrorKind::Issue33140 => - lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS, - }; - self.tcx.struct_span_lint_node( - lint, - node_id.unwrap(), - self.tcx.span_of_impl(item1).unwrap(), - &format!("duplicate definitions with name `{}` (E0592)", name) - ) - } - _ => { - struct_span_err!(self.tcx.sess, - self.tcx.span_of_impl(item1).unwrap(), - E0592, - "duplicate definitions with name `{}`", - name) - } + let mut err = if used_to_be_allowed && node_id.is_some() { + self.tcx.struct_span_lint_node( + lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, + node_id.unwrap(), + self.tcx.span_of_impl(item1).unwrap(), + &format!("duplicate definitions with name `{}` (E0592)", name) + ) + } else { + struct_span_err!(self.tcx.sess, + self.tcx.span_of_impl(item1).unwrap(), + E0592, + "duplicate definitions with name `{}`", + name) }; err.span_label(self.tcx.span_of_impl(item1).unwrap(), @@ -88,61 +76,36 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i + 1)..] { - let mut used_to_be_allowed = traits::overlapping_impls( + let used_to_be_allowed = traits::overlapping_impls( self.tcx, impl1_def_id, impl2_def_id, IntercrateMode::Issue43355, - TraitObjectMode::NoSquash, |overlap| { self.check_for_common_items_in_impls( impl1_def_id, impl2_def_id, overlap, - Some(FutureCompatOverlapErrorKind::Issue43355), + false, ); false }, || true, ); - if used_to_be_allowed { - used_to_be_allowed = traits::overlapping_impls( - self.tcx, - impl1_def_id, - impl2_def_id, - IntercrateMode::Fixed, - TraitObjectMode::NoSquash, - |overlap| { - self.check_for_common_items_in_impls( - impl1_def_id, - impl2_def_id, - overlap, - None, - ); - false - }, - || true, - ); - } - if used_to_be_allowed { traits::overlapping_impls( self.tcx, impl1_def_id, impl2_def_id, IntercrateMode::Fixed, - TraitObjectMode::SquashAutoTraitsIssue33140, - |overlap| { - self.check_for_common_items_in_impls( - impl1_def_id, - impl2_def_id, - overlap, - Some(FutureCompatOverlapErrorKind::Issue33140), - ); - false - }, - || true, + |overlap| self.check_for_common_items_in_impls( + impl1_def_id, + impl2_def_id, + overlap, + true, + ), + || (), ); } } From 0b511b7bd22bde3c647191de79ba5a019b183269 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 3 Jan 2019 23:46:46 +0200 Subject: [PATCH 09/12] implement a hack to make traitobject 0.1.0 compile --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/traits/mod.rs | 2 + src/librustc/traits/select.rs | 3 +- src/librustc/traits/specialize/mod.rs | 21 ++- .../traits/specialize/specialization_graph.rs | 44 ++++++- src/librustc/ty/mod.rs | 122 +++++++++++++++++- src/librustc/ty/query/mod.rs | 2 + src/librustc/ty/query/plumbing.rs | 1 + src/test/run-pass/issues/issue-33140.rs | 47 ------- .../ui/issues/issue-33140-hack-boundaries.rs | 80 ++++++++++++ .../issues/issue-33140-hack-boundaries.stderr | 67 ++++++++++ .../issues/issue-33140-traitobject-crate.rs | 101 +++++++++++++++ .../issue-33140-traitobject-crate.stderr | 39 ++++++ src/test/ui/issues/issue-33140.rs | 5 - src/test/ui/issues/issue-33140.stderr | 33 ++--- 15 files changed, 478 insertions(+), 90 deletions(-) delete mode 100644 src/test/run-pass/issues/issue-33140.rs create mode 100644 src/test/ui/issues/issue-33140-hack-boundaries.rs create mode 100644 src/test/ui/issues/issue-33140-hack-boundaries.stderr create mode 100644 src/test/ui/issues/issue-33140-traitobject-crate.rs create mode 100644 src/test/ui/issues/issue-33140-traitobject-crate.stderr diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 070551c0b7b0a..3156f17e0c4c5 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -492,6 +492,7 @@ define_dep_nodes!( <'tcx> [] AdtDefOfItem(DefId), [] ImplTraitRef(DefId), [] ImplPolarity(DefId), + [] Issue33140SelfTy(DefId), [] FnSignature(DefId), [] CoerceUnsizedInfo(DefId), diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 1a9f1ada111bd..b42d742b7f841 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -56,6 +56,8 @@ pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; pub use self::specialize::{OverlapError, specialization_graph, translate_substs}; pub use self::specialize::find_associated_item; +pub use self::specialize::specialization_graph::FutureCompatOverlapError; +pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 9ad974d8e084a..6db6fe31fba70 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2260,7 +2260,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ImplCandidate(victim_def) => { let tcx = self.tcx().global_tcx(); return tcx.specializes((other_def, victim_def)) - || tcx.impls_are_allowed_to_overlap(other_def, victim_def); + || tcx.impls_are_allowed_to_overlap( + other_def, victim_def).is_some(); } ParamCandidate(ref cand) => { // Prefer the impl to a global where clause candidate. diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 5ab54b2c99d42..e5ed16e755860 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -14,11 +14,10 @@ pub mod specialization_graph; use hir::def_id::DefId; use infer::{InferCtxt, InferOk}; use lint; -use traits::coherence; +use traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax_pos::DUMMY_SP; -use traits::{self, ObligationCause, TraitEngine}; use traits::select::IntercrateAmbiguityCause; use ty::{self, TyCtxt, TypeFoldable}; use ty::subst::{Subst, Substs}; @@ -27,6 +26,7 @@ use super::{SelectionContext, FulfillmentContext}; use super::util::impl_trait_ref_and_oblig; /// Information pertinent to an overlapping impl error. +#[derive(Debug)] pub struct OverlapError { pub with_impl: DefId, pub trait_desc: String, @@ -310,8 +310,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>( let insert_result = sg.insert(tcx, impl_def_id); // Report error if there was one. let (overlap, used_to_be_allowed) = match insert_result { - Err(overlap) => (Some(overlap), false), - Ok(opt_overlap) => (opt_overlap, true) + Err(overlap) => (Some(overlap), None), + Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)), + Ok(None) => (None, None) }; if let Some(overlap) = overlap { @@ -321,14 +322,20 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>( String::new(), |ty| { format!(" for type `{}`", ty) }), - if used_to_be_allowed { " (E0119)" } else { "" } + if used_to_be_allowed.is_some() { " (E0119)" } else { "" } ); let impl_span = tcx.sess.source_map().def_span( tcx.span_of_impl(impl_def_id).unwrap() ); - let mut err = if used_to_be_allowed { + let mut err = if let Some(kind) = used_to_be_allowed { + let lint = match kind { + FutureCompatOverlapErrorKind::Issue43355 => + lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, + FutureCompatOverlapErrorKind::Issue33140 => + lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS, + }; tcx.struct_span_lint_node( - lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS, + lint, tcx.hir().as_local_node_id(impl_def_id).unwrap(), impl_span, &msg) diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index c22adeb55a269..e5780a26a1918 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -58,10 +58,22 @@ struct Children { blanket_impls: Vec, } +#[derive(Copy, Clone, Debug)] +pub enum FutureCompatOverlapErrorKind { + Issue43355, + Issue33140, +} + +#[derive(Debug)] +pub struct FutureCompatOverlapError { + pub error: OverlapError, + pub kind: FutureCompatOverlapErrorKind +} + /// The result of attempting to insert an impl into a group of children. enum Inserted { /// The impl was inserted as a new child in this group of children. - BecameNewSibling(Option), + BecameNewSibling(Option), /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc. ReplaceChildren(Vec), @@ -162,7 +174,19 @@ impl<'a, 'gcx, 'tcx> Children { impl_def_id, traits::IntercrateMode::Issue43355, |overlap| { - if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { + if let Some(overlap_kind) = + tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) + { + match overlap_kind { + ty::ImplOverlapKind::Permitted => {} + ty::ImplOverlapKind::Issue33140 => { + last_lint = Some(FutureCompatOverlapError { + error: overlap_error(overlap), + kind: FutureCompatOverlapErrorKind::Issue33140 + }); + } + } + return Ok((false, false)); } @@ -190,13 +214,23 @@ impl<'a, 'gcx, 'tcx> Children { replace_children.push(possible_sibling); } else { - if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { + if let None = tcx.impls_are_allowed_to_overlap( + impl_def_id, possible_sibling) + { + // do future-compat checks for overlap. Have issue #33140 + // errors overwrite issue #43355 errors when both are present. + traits::overlapping_impls( tcx, possible_sibling, impl_def_id, traits::IntercrateMode::Fixed, - |overlap| last_lint = Some(overlap_error(overlap)), + |overlap| { + last_lint = Some(FutureCompatOverlapError { + error: overlap_error(overlap), + kind: FutureCompatOverlapErrorKind::Issue43355 + }); + }, || (), ); } @@ -263,7 +297,7 @@ impl<'a, 'gcx, 'tcx> Graph { pub fn insert(&mut self, tcx: TyCtxt<'a, 'gcx, 'tcx>, impl_def_id: DefId) - -> Result, OverlapError> { + -> Result, OverlapError> { assert!(impl_def_id.is_local()); let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d40dd830e9fb9..aa3ff5e4a2dc2 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2637,6 +2637,45 @@ impl<'gcx> ::std::ops::Deref for Attributes<'gcx> { } } +#[derive(Debug, PartialEq, Eq)] +pub enum ImplOverlapKind { + /// These impls are always allowed to overlap. + Permitted, + /// These impls are allowed to overlap, but that raises + /// an issue #33140 future-compatibility warning. + /// + /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's + /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different. + /// + /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied + /// that difference, making what reduces to the following set of impls: + /// + /// ``` + /// trait Trait {} + /// impl Trait for dyn Send + Sync {} + /// impl Trait for dyn Sync + Send {} + /// ``` + /// + /// Obviously, once we made these types be identical, that code causes a coherence + /// error and a fairly big headache for us. However, luckily for us, the trait + /// `Trait` used in this case is basically a marker trait, and therefore having + /// overlapping impls for it is sound. + /// + /// To handle this, we basically regard the trait as a marker trait, with an additional + /// future-compatibility warning. To avoid accidentally "stabilizing" this feature, + /// it has the following restrictions: + /// + /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be + /// positive impls. + /// 2. The trait-ref of both impls must be equal. + /// 3. The trait-ref of both impls must be a trait object type consisting only of + /// marker traits. + /// 4. Neither of the impls can have any where-clauses. + /// + /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed. + Issue33140 +} + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> { self.typeck_tables_of(self.hir().body_owner_def_id(body)) @@ -2788,8 +2827,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns `true` if the impls are the same polarity and the trait either /// has no items or is annotated #[marker] and prevents item overrides. - pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool { - if self.features().overlapping_marker_traits { + pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) + -> Option + { + let is_legit = if self.features().overlapping_marker_traits { let trait1_is_empty = self.impl_trait_ref(def_id1) .map_or(false, |trait_ref| { self.associated_item_def_ids(trait_ref.def_id).is_empty() @@ -2811,6 +2852,29 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { && is_marker_impl(def_id2) } else { false + }; + + if is_legit { + debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted)", + def_id1, def_id2); + Some(ImplOverlapKind::Permitted) + } else { + if let Some(self_ty1) = self.issue33140_self_ty(def_id1) { + if let Some(self_ty2) = self.issue33140_self_ty(def_id2) { + if self_ty1 == self_ty2 { + debug!("impls_are_allowed_to_overlap({:?}, {:?}) - issue #33140 HACK", + def_id1, def_id2); + return Some(ImplOverlapKind::Issue33140); + } else { + debug!("impls_are_allowed_to_overlap({:?}, {:?}) - found {:?} != {:?}", + def_id1, def_id2, self_ty1, self_ty2); + } + } + } + + debug!("impls_are_allowed_to_overlap({:?}, {:?}) = None", + def_id1, def_id2); + None } } @@ -3203,6 +3267,59 @@ fn instance_def_size_estimate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } +/// If `def_id` is an issue 33140 hack impl, return its self type. Otherwise +/// return None. +/// +/// See ImplOverlapKind::Issue33140 for more details. +fn issue33140_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> Option> +{ + debug!("issue33140_self_ty({:?})", def_id); + + let trait_ref = tcx.impl_trait_ref(def_id).unwrap_or_else(|| { + bug!("issue33140_self_ty called on inherent impl {:?}", def_id) + }); + + debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref); + + let is_marker_like = + tcx.impl_polarity(def_id) == hir::ImplPolarity::Positive && + tcx.associated_item_def_ids(trait_ref.def_id).is_empty(); + + // Check whether these impls would be ok for a marker trait. + if !is_marker_like { + debug!("issue33140_self_ty - not marker-like!"); + return None; + } + + // impl must be `impl Trait for dyn Marker1 + Marker2 + ...` + if trait_ref.substs.len() != 1 { + debug!("issue33140_self_ty - impl has substs!"); + return None; + } + + let predicates = tcx.predicates_of(def_id); + if predicates.parent.is_some() || !predicates.predicates.is_empty() { + debug!("issue33140_self_ty - impl has predicates {:?}!", predicates); + return None; + } + + let self_ty = trait_ref.self_ty(); + let self_ty_matches = match self_ty.sty { + ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(), + _ => false + }; + + if self_ty_matches { + debug!("issue33140_self_ty - MATCHES!"); + Some(self_ty) + } else { + debug!("issue33140_self_ty - non-matching self type"); + None + } +} + pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); erase_regions::provide(providers); @@ -3221,6 +3338,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { crate_hash, trait_impls_of: trait_def::trait_impls_of_provider, instance_def_size_estimate, + issue33140_self_ty, ..*providers }; } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 4d026b97233ee..99dd3569491bc 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -202,6 +202,8 @@ define_queries! { <'tcx> [] fn impl_trait_ref: ImplTraitRef(DefId) -> Option>, [] fn impl_polarity: ImplPolarity(DefId) -> hir::ImplPolarity, + + [] fn issue33140_self_ty: Issue33140SelfTy(DefId) -> Option>, }, TypeChecking { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 6887f480f72e0..9a1ab559688a8 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1275,6 +1275,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); } DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); } DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); } + DepKind::Issue33140SelfTy => { force!(issue33140_self_ty, def_id!()); } DepKind::FnSignature => { force!(fn_sig, def_id!()); } DepKind::CoerceUnsizedInfo => { force!(coerce_unsized_info, def_id!()); } DepKind::ItemVariances => { force!(variances_of, def_id!()); } diff --git a/src/test/run-pass/issues/issue-33140.rs b/src/test/run-pass/issues/issue-33140.rs deleted file mode 100644 index 4d91af2fb19ca..0000000000000 --- a/src/test/run-pass/issues/issue-33140.rs +++ /dev/null @@ -1,47 +0,0 @@ -#![allow(order_dependent_trait_objects)] - -trait Trait { - fn xyz() -> bool; -} - -impl Trait for dyn Send + Sync { - fn xyz() -> bool { false } -} - -impl Trait for dyn Sync + Send { - fn xyz() -> bool { true } -} - -trait Trait2 { - fn uvw() -> bool; -} - -impl Trait2 for dyn Send + Sync { - fn uvw() -> bool { false } -} - -impl Trait2 for dyn Sync + Send + Sync { - fn uvw() -> bool { true } -} - -struct Foo(T); -impl Foo { - fn abc() -> bool { - false - } -} - -impl Foo { - fn abc() -> bool { - true - } -} - -fn main() { - assert_eq!(::xyz(), false); - assert_eq!(::xyz(), true); - assert_eq!(::uvw(), false); - assert_eq!(::uvw(), true); - assert_eq!(>::abc(), false); - assert_eq!(>::abc(), true); -} diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.rs b/src/test/ui/issues/issue-33140-hack-boundaries.rs new file mode 100644 index 0000000000000..fbdef51c13255 --- /dev/null +++ b/src/test/ui/issues/issue-33140-hack-boundaries.rs @@ -0,0 +1,80 @@ +#![feature(optin_builtin_traits)] +#![allow(order_dependent_trait_objects)] + +// Check that the issue #33140 hack does not allow unintended things. + +// OK +trait Trait0 { +} + +impl Trait0 for dyn Send {} +impl Trait0 for dyn Send {} + +// Problem 1: associated types +trait Trait1 { + fn my_fn(&self) {} +} + +impl Trait1 for dyn Send {} +impl Trait1 for dyn Send {} +//~^ ERROR E0119 + +// Problem 2: negative impl +trait Trait2 { +} + +impl Trait2 for dyn Send {} +impl !Trait2 for dyn Send {} +//~^ ERROR E0119 + + +// Problem 3: type parameter +trait Trait3 { +} + +impl Trait3 for dyn Send {} +impl Trait3 for dyn Send {} +//~^ ERROR E0119 + +// Problem 4a: not a trait object - generic +trait Trait4a { +} + +impl Trait4a for T {} +impl Trait4a for dyn Send {} +//~^ ERROR E0119 + +// Problem 4b: not a trait object - misc +trait Trait4b { +} + +impl Trait4b for () {} +impl Trait4b for () {} +//~^ ERROR E0119 + +// Problem 4c: not a principal-less trait object +trait Trait4c { +} + +impl Trait4c for dyn Trait1 + Send {} +impl Trait4c for dyn Trait1 + Send {} +//~^ ERROR E0119 + +// Problem 4d: lifetimes +trait Trait4d { +} + +impl<'a> Trait4d for dyn Send + 'a {} +impl<'a> Trait4d for dyn Send + 'a {} +//~^ ERROR E0119 + + +// Problem 5: where-clauses +trait Trait5 { +} + +impl Trait5 for dyn Send {} +impl Trait5 for dyn Send where u32: Copy {} +//~^ ERROR E0119 + +fn main() {} diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.stderr b/src/test/ui/issues/issue-33140-hack-boundaries.stderr new file mode 100644 index 0000000000000..95aaa55ba7c67 --- /dev/null +++ b/src/test/ui/issues/issue-33140-hack-boundaries.stderr @@ -0,0 +1,67 @@ +error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn std::marker::Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:19:1 + | +LL | impl Trait1 for dyn Send {} + | ------------------------ first implementation here +LL | impl Trait1 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:27:1 + | +LL | impl Trait2 for dyn Send {} + | ------------------------ first implementation here +LL | impl !Trait2 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait3<(dyn std::marker::Sync + 'static)>` for type `(dyn std::marker::Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:36:1 + | +LL | impl Trait3 for dyn Send {} + | ---------------------------------- first implementation here +LL | impl Trait3 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn std::marker::Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:44:1 + | +LL | impl Trait4a for T {} + | ----------------------------- first implementation here +LL | impl Trait4a for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait4b` for type `()`: + --> $DIR/issue-33140-hack-boundaries.rs:52:1 + | +LL | impl Trait4b for () {} + | ------------------- first implementation here +LL | impl Trait4b for () {} + | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + std::marker::Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:60:1 + | +LL | impl Trait4c for dyn Trait1 + Send {} + | ---------------------------------- first implementation here +LL | impl Trait4c for dyn Trait1 + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + std::marker::Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn std::marker::Send`: + --> $DIR/issue-33140-hack-boundaries.rs:68:1 + | +LL | impl<'a> Trait4d for dyn Send + 'a {} + | ---------------------------------- first implementation here +LL | impl<'a> Trait4d for dyn Send + 'a {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn std::marker::Send` + +error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn std::marker::Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:77:1 + | +LL | impl Trait5 for dyn Send {} + | ------------------------ first implementation here +LL | impl Trait5 for dyn Send where u32: Copy {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.rs b/src/test/ui/issues/issue-33140-traitobject-crate.rs new file mode 100644 index 0000000000000..2b644817df115 --- /dev/null +++ b/src/test/ui/issues/issue-33140-traitobject-crate.rs @@ -0,0 +1,101 @@ +// compile-pass + +#![warn(order_dependent_trait_objects)] + +// Check that traitobject 0.1.0 compiles + +//! # traitobject +//! +//! Unsafe helpers for working with raw TraitObjects. + +/// A trait implemented for all trait objects. +/// +/// Implementations for all traits in std are provided. +pub unsafe trait Trait {} + +unsafe impl Trait for ::std::any::Any + Send { } +unsafe impl Trait for ::std::any::Any + Sync { } +unsafe impl Trait for ::std::any::Any + Send + Sync { } +unsafe impl Trait for ::std::borrow::Borrow + Send { } +unsafe impl Trait for ::std::borrow::Borrow + Sync { } +unsafe impl Trait for ::std::borrow::Borrow + Send + Sync { } +unsafe impl Trait for ::std::borrow::BorrowMut + Send { } +unsafe impl Trait for ::std::borrow::BorrowMut + Sync { } +unsafe impl Trait for ::std::borrow::BorrowMut + Send + Sync { } +unsafe impl Trait for ::std::convert::AsMut + Send { } +unsafe impl Trait for ::std::convert::AsMut + Sync { } +unsafe impl Trait for ::std::convert::AsMut + Send + Sync { } +unsafe impl Trait for ::std::convert::AsRef + Send { } +unsafe impl Trait for ::std::convert::AsRef + Sync { } +unsafe impl Trait for ::std::convert::AsRef + Send + Sync { } +unsafe impl Trait for ::std::error::Error + Send { } +unsafe impl Trait for ::std::error::Error + Sync { } +unsafe impl Trait for ::std::error::Error + Send + Sync { } +unsafe impl Trait for ::std::fmt::Binary + Send { } +unsafe impl Trait for ::std::fmt::Binary + Sync { } +unsafe impl Trait for ::std::fmt::Binary + Send + Sync { } +unsafe impl Trait for ::std::fmt::Debug + Send { } +unsafe impl Trait for ::std::fmt::Debug + Sync { } +unsafe impl Trait for ::std::fmt::Debug + Send + Sync { } +unsafe impl Trait for ::std::fmt::Display + Send { } +unsafe impl Trait for ::std::fmt::Display + Sync { } +unsafe impl Trait for ::std::fmt::Display + Send + Sync { } +unsafe impl Trait for ::std::fmt::LowerExp + Send { } +unsafe impl Trait for ::std::fmt::LowerExp + Sync { } +unsafe impl Trait for ::std::fmt::LowerExp + Send + Sync { } +unsafe impl Trait for ::std::fmt::LowerHex + Send { } +unsafe impl Trait for ::std::fmt::LowerHex + Sync { } +unsafe impl Trait for ::std::fmt::LowerHex + Send + Sync { } +unsafe impl Trait for ::std::fmt::Octal + Send { } +unsafe impl Trait for ::std::fmt::Octal + Sync { } +unsafe impl Trait for ::std::fmt::Octal + Send + Sync { } +unsafe impl Trait for ::std::fmt::Pointer + Send { } +unsafe impl Trait for ::std::fmt::Pointer + Sync { } +unsafe impl Trait for ::std::fmt::Pointer + Send + Sync { } +unsafe impl Trait for ::std::fmt::UpperExp + Send { } +unsafe impl Trait for ::std::fmt::UpperExp + Sync { } +unsafe impl Trait for ::std::fmt::UpperExp + Send + Sync { } +unsafe impl Trait for ::std::fmt::UpperHex + Send { } +unsafe impl Trait for ::std::fmt::UpperHex + Sync { } +unsafe impl Trait for ::std::fmt::UpperHex + Send + Sync { } +unsafe impl Trait for ::std::fmt::Write + Send { } +unsafe impl Trait for ::std::fmt::Write + Sync { } +unsafe impl Trait for ::std::fmt::Write + Send + Sync { } +unsafe impl Trait for ::std::hash::Hasher + Send { } +unsafe impl Trait for ::std::hash::Hasher + Sync { } +unsafe impl Trait for ::std::hash::Hasher + Send + Sync { } +unsafe impl Trait for ::std::io::BufRead + Send { } +unsafe impl Trait for ::std::io::BufRead + Sync { } +unsafe impl Trait for ::std::io::BufRead + Send + Sync { } +unsafe impl Trait for ::std::io::Read + Send { } +unsafe impl Trait for ::std::io::Read + Sync { } +unsafe impl Trait for ::std::io::Read + Send + Sync { } +unsafe impl Trait for ::std::io::Seek + Send { } +unsafe impl Trait for ::std::io::Seek + Sync { } +unsafe impl Trait for ::std::io::Seek + Send + Sync { } +unsafe impl Trait for ::std::io::Write + Send { } +unsafe impl Trait for ::std::io::Write + Sync { } +unsafe impl Trait for ::std::io::Write + Send + Sync { } +unsafe impl Trait for ::std::iter::IntoIterator { } +unsafe impl Trait for ::std::iter::Iterator + Send { } +unsafe impl Trait for ::std::iter::Iterator + Sync { } +unsafe impl Trait for ::std::iter::Iterator + Send + Sync { } +unsafe impl Trait for ::std::marker::Send + Send { } +unsafe impl Trait for ::std::marker::Send + Sync { } +unsafe impl Trait for ::std::marker::Send + Send + Sync { } +unsafe impl Trait for ::std::marker::Sync + Send { } +unsafe impl Trait for ::std::marker::Sync + Sync { } +unsafe impl Trait for ::std::marker::Sync + Send + Sync { } +unsafe impl Trait for ::std::ops::Drop + Send { } +unsafe impl Trait for ::std::ops::Drop + Sync { } +unsafe impl Trait for ::std::ops::Drop + Send + Sync { } +unsafe impl Trait for ::std::string::ToString + Send { } +unsafe impl Trait for ::std::string::ToString + Sync { } +unsafe impl Trait for ::std::string::ToString + Send + Sync { } +fn assert_trait() {} + +fn main() { + assert_trait::(); + assert_trait::(); + assert_trait::(); +} diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.stderr b/src/test/ui/issues/issue-33140-traitobject-crate.stderr new file mode 100644 index 0000000000000..28193b0eeb992 --- /dev/null +++ b/src/test/ui/issues/issue-33140-traitobject-crate.stderr @@ -0,0 +1,39 @@ +warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:85:1 + | +LL | unsafe impl Trait for ::std::marker::Send + Sync { } + | ------------------------------------------------ first implementation here +LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` + | +note: lint level defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:86:1 + | +LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { } + | ------------------------------------------------------- first implementation here +LL | unsafe impl Trait for ::std::marker::Sync + Send { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:88:1 + | +LL | unsafe impl Trait for ::std::marker::Sync + Send { } + | ------------------------------------------------ first implementation here +LL | unsafe impl Trait for ::std::marker::Sync + Sync { } +LL | unsafe impl Trait for ::std::marker::Sync + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + diff --git a/src/test/ui/issues/issue-33140.rs b/src/test/ui/issues/issue-33140.rs index 8d19248d5e0ea..930e24218ac72 100644 --- a/src/test/ui/issues/issue-33140.rs +++ b/src/test/ui/issues/issue-33140.rs @@ -1,5 +1,3 @@ -#![deny(order_dependent_trait_objects)] - trait Trait { fn xyz() -> bool; } @@ -10,7 +8,6 @@ impl Trait for dyn Send + Sync { impl Trait for dyn Sync + Send { //~^ ERROR conflicting implementations -//~| hard error fn xyz() -> bool { true } } @@ -24,14 +21,12 @@ impl Trait2 for dyn Send + Sync { impl Trait2 for dyn Sync + Send + Sync { //~^ ERROR conflicting implementations -//~| hard error fn uvw() -> bool { true } } struct Foo(T); impl Foo { fn abc() -> bool { //~ ERROR duplicate definitions with name `abc` - //~| hard error false } } diff --git a/src/test/ui/issues/issue-33140.stderr b/src/test/ui/issues/issue-33140.stderr index 520921a751239..6e63828f5f7f5 100644 --- a/src/test/ui/issues/issue-33140.stderr +++ b/src/test/ui/issues/issue-33140.stderr @@ -1,37 +1,25 @@ -error: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) - --> $DIR/issue-33140.rs:11:1 +error[E0119]: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: + --> $DIR/issue-33140.rs:9:1 | LL | impl Trait for dyn Send + Sync { | ------------------------------ first implementation here ... LL | impl Trait for dyn Sync + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` - | -note: lint level defined here - --> $DIR/issue-33140.rs:1:9 - | -LL | #![deny(order_dependent_trait_objects)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #56484 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` -error: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) - --> $DIR/issue-33140.rs:25:1 +error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: + --> $DIR/issue-33140.rs:22:1 | LL | impl Trait2 for dyn Send + Sync { | ------------------------------- first implementation here ... LL | impl Trait2 for dyn Sync + Send + Sync { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #56484 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` -error: duplicate definitions with name `abc` (E0592) - --> $DIR/issue-33140.rs:33:5 +error[E0592]: duplicate definitions with name `abc` + --> $DIR/issue-33140.rs:29:5 | LL | / fn abc() -> bool { //~ ERROR duplicate definitions with name `abc` -LL | | //~| hard error LL | | false LL | | } | |_____^ duplicate definitions for `abc` @@ -40,9 +28,8 @@ LL | / fn abc() -> bool { LL | | true LL | | } | |_____- other definition for `abc` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #56484 error: aborting due to 3 previous errors +Some errors occurred: E0119, E0592. +For more information about an error, try `rustc --explain E0119`. From 10a89400cf03770eec63dd007ff38ff0163216c9 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Fri, 4 Jan 2019 15:09:09 +0200 Subject: [PATCH 10/12] alphabetize marker traits when printed This makes sure they are printed in a compiler-version-independent order, avoiding ui test instability. --- src/librustc/util/ppaux.rs | 17 +++++++++++++++-- .../issues/issue-33140-traitobject-crate.stderr | 12 ++++++------ src/test/ui/issues/issue-33140.stderr | 8 ++++---- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index b49852be38dde..c5601d4426544 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -729,13 +729,26 @@ define_print! { } // Builtin bounds. - for did in self.auto_traits() { + let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { + tcx.item_path_str(did) + }).collect(); + + // The auto traits come ordered by `DefPathHash`. While + // `DefPathHash` is *stable* in the sense that it depends on + // neither the host nor the phase of the moon, it depends + // "pseudorandomly" on the compiler version and the target. + // + // To avoid that causing instabilities in compiletest + // output, sort the auto-traits alphabetically. + auto_traits.sort(); + + for auto_trait in auto_traits { if !first { write!(f, " + ")?; } first = false; - write!(f, "{}", tcx.item_path_str(did))?; + write!(f, "{}", auto_trait)?; } Ok(()) diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.stderr b/src/test/ui/issues/issue-33140-traitobject-crate.stderr index 28193b0eeb992..6f71e79d0ee7a 100644 --- a/src/test/ui/issues/issue-33140-traitobject-crate.stderr +++ b/src/test/ui/issues/issue-33140-traitobject-crate.stderr @@ -1,10 +1,10 @@ -warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: (E0119) +warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) --> $DIR/issue-33140-traitobject-crate.rs:85:1 | LL | unsafe impl Trait for ::std::marker::Send + Sync { } | ------------------------------------------------ first implementation here LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` | note: lint level defined here --> $DIR/issue-33140-traitobject-crate.rs:3:9 @@ -14,25 +14,25 @@ LL | #![warn(order_dependent_trait_objects)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #56484 -warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: (E0119) +warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) --> $DIR/issue-33140-traitobject-crate.rs:86:1 | LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { } | ------------------------------------------------------- first implementation here LL | unsafe impl Trait for ::std::marker::Sync + Send { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #56484 -warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: (E0119) +warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119) --> $DIR/issue-33140-traitobject-crate.rs:88:1 | LL | unsafe impl Trait for ::std::marker::Sync + Send { } | ------------------------------------------------ first implementation here LL | unsafe impl Trait for ::std::marker::Sync + Sync { } LL | unsafe impl Trait for ::std::marker::Sync + Send + Sync { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #56484 diff --git a/src/test/ui/issues/issue-33140.stderr b/src/test/ui/issues/issue-33140.stderr index 6e63828f5f7f5..e2631e971c516 100644 --- a/src/test/ui/issues/issue-33140.stderr +++ b/src/test/ui/issues/issue-33140.stderr @@ -1,20 +1,20 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: +error[E0119]: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: --> $DIR/issue-33140.rs:9:1 | LL | impl Trait for dyn Send + Sync { | ------------------------------ first implementation here ... LL | impl Trait for dyn Sync + Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` -error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: +error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: --> $DIR/issue-33140.rs:22:1 | LL | impl Trait2 for dyn Send + Sync { | ------------------------------- first implementation here ... LL | impl Trait2 for dyn Sync + Send + Sync { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)` error[E0592]: duplicate definitions with name `abc` --> $DIR/issue-33140.rs:29:5 From bb1afa19f5631839a85af9273785e3cab6d68806 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Fri, 4 Jan 2019 15:27:55 +0200 Subject: [PATCH 11/12] add some debug logging to collect --- src/librustc_typeck/collect.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9fc2f11b19738..e0e173901ef38 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1618,6 +1618,7 @@ fn predicates_defined_on<'a, 'tcx>( .predicates .extend(inferred_outlives.iter().map(|&p| (p, span))); } + debug!("predicates_defined_on({:?}) = {:?}", def_id, result); result } @@ -1645,6 +1646,7 @@ fn predicates_of<'a, 'tcx>( .predicates .push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); } + debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); result } @@ -1972,10 +1974,12 @@ fn explicit_predicates_of<'a, 'tcx>( ); } - Lrc::new(ty::GenericPredicates { + let result = Lrc::new(ty::GenericPredicates { parent: generics.parent, predicates, - }) + }); + debug!("explicit_predicates_of(def_id={:?}) = {:?}", def_id, result); + result } pub enum SizedByDefault { From c213b0db2e8e344c419095450dbbdae71afa8c61 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Fri, 4 Jan 2019 21:53:00 +0200 Subject: [PATCH 12/12] add test for #57162 Fixes #57162. --- src/test/ui/issues/issue-57162.rs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/test/ui/issues/issue-57162.rs diff --git a/src/test/ui/issues/issue-57162.rs b/src/test/ui/issues/issue-57162.rs new file mode 100644 index 0000000000000..abe0887e927b5 --- /dev/null +++ b/src/test/ui/issues/issue-57162.rs @@ -0,0 +1,7 @@ +// compile-pass + +trait Foo {} +impl Foo for dyn Send {} + +impl Foo for T {} +fn main() {}