From 0eb87ed55fa76e11777254c77ff7f11c74aa2bfa Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 23 Jun 2020 17:57:24 +0100 Subject: [PATCH 01/34] Rename projection_predicates to item_bounds --- .../rustc_infer/src/infer/outlives/verify.rs | 4 +-- compiler/rustc_middle/src/query/mod.rs | 4 +-- .../src/traits/project.rs | 6 ++--- .../src/traits/select/mod.rs | 6 ++--- compiler/rustc_ty/src/ty.rs | 25 +++++++------------ .../rustc_typeck/src/check/compare_method.rs | 8 +++--- 6 files changed, 21 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 07924298c241b..2b827f4f4eddc 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -328,8 +328,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { assoc_item_def_id: DefId, ) -> impl Iterator> { let tcx = self.tcx; - let predicates = tcx.projection_predicates(assoc_item_def_id); - predicates + let bounds = tcx.item_bounds(assoc_item_def_id); + bounds .into_iter() .filter_map(|p| p.to_opt_type_outlives()) .filter_map(|p| p.no_bound_vars()) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index fe115bbb9c334..fadc7621785af 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -156,7 +156,7 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } - /// Returns the list of predicates that can be used for + /// Returns the list of bounds that can be used for /// `SelectionCandidate::ProjectionCandidate` and /// `ProjectionTyCandidate::TraitDef`. /// Specifically this is the bounds (equivalent to) those @@ -169,7 +169,7 @@ rustc_queries! { /// ^^^^^^^^^^^^^^^ /// /// `key` is the `DefId` of the associated type or opaque type. - query projection_predicates(key: DefId) -> &'tcx ty::List> { + query item_bounds(key: DefId) -> &'tcx ty::List> { desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index ef8f7b69b5d60..71e34d2dcd05f 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -909,10 +909,8 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( // Check whether the self-type is itself a projection. // If so, extract what we know from the trait and try to come up with a good answer. let bounds = match *obligation_trait_ref.self_ty().kind() { - ty::Projection(ref data) => { - tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs) - } - ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs), + ty::Projection(ref data) => tcx.item_bounds(data.item_def_id).subst(tcx, data.substs), + ty::Opaque(def_id, substs) => tcx.item_bounds(def_id).subst(tcx, substs), ty::Infer(ty::TyVar(_)) => { // If the self-type is an inference variable, then it MAY wind up // being a projected type, so induce an ambiguity. diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 114dc79c44f50..9bebf8d90c21e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1171,10 +1171,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.infcx.tcx; let predicates = match *placeholder_trait_predicate.trait_ref.self_ty().kind() { - ty::Projection(ref data) => { - tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs) - } - ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs), + ty::Projection(ref data) => tcx.item_bounds(data.item_def_id).subst(tcx, data.substs), + ty::Opaque(def_id, substs) => tcx.item_bounds(def_id).subst(tcx, substs), _ => { span_bug!( obligation.cause.span, diff --git a/compiler/rustc_ty/src/ty.rs b/compiler/rustc_ty/src/ty.rs index c4b6b64339a03..2be466bf77348 100644 --- a/compiler/rustc_ty/src/ty.rs +++ b/compiler/rustc_ty/src/ty.rs @@ -500,7 +500,7 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { /// simplify checking that these bounds are met in impls. This means that /// a bound such as `for<'b> >::U: Clone` can't be used, as in /// `hr-associated-type-bound-1.rs`. -fn associated_type_projection_predicates( +fn associated_type_bounds( tcx: TyCtxt<'_>, assoc_item_def_id: DefId, ) -> &'_ ty::List> { @@ -545,21 +545,14 @@ fn associated_type_projection_predicates( }); let result = tcx.mk_predicates(predicates); - debug!( - "associated_type_projection_predicates({}) = {:?}", - tcx.def_path_str(assoc_item_def_id), - result - ); + debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), result); result } /// Opaque types don't have the same issues as associated types: the only /// predicates on an opaque type (excluding those it inherits from its parent /// item) should be of the form we're expecting. -fn opaque_type_projection_predicates( - tcx: TyCtxt<'_>, - def_id: DefId, -) -> &'_ ty::List> { +fn opaque_type_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { let substs = InternalSubsts::identity_for_item(tcx, def_id); let bounds = tcx.predicates_of(def_id); @@ -607,15 +600,15 @@ fn opaque_type_projection_predicates( }); let result = tcx.mk_predicates(filtered_predicates); - debug!("opaque_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result); + debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(def_id), result); result } -fn projection_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { +fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { match tcx.def_kind(def_id) { - DefKind::AssocTy => associated_type_projection_predicates(tcx, def_id), - DefKind::OpaqueTy => opaque_type_projection_predicates(tcx, def_id), - k => bug!("projection_predicates called on {}", k.descr(def_id)), + DefKind::AssocTy => associated_type_bounds(tcx, def_id), + DefKind::OpaqueTy => opaque_type_bounds(tcx, def_id), + k => bug!("item_bounds called on {}", k.descr(def_id)), } } @@ -636,7 +629,7 @@ pub fn provide(providers: &mut ty::query::Providers) { instance_def_size_estimate, issue33140_self_ty, impl_defaultness, - projection_predicates, + item_bounds, ..*providers }; } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 7aa54e0ebcc6b..8111a0bad9fbf 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1052,7 +1052,7 @@ crate fn compare_ty_impl<'tcx>( compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?; - compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref) + check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref) })(); } @@ -1170,7 +1170,7 @@ fn compare_type_predicate_entailment<'tcx>( /// For default associated types the normalization is not possible (the value /// from the impl could be overridden). We also can't normalize generic /// associated types (yet) because they contain bound parameters. -fn compare_projection_bounds<'tcx>( +fn check_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, trait_ty: &ty::AssocItem, impl_ty: &ty::AssocItem, @@ -1237,8 +1237,8 @@ fn compare_projection_bounds<'tcx>( ObligationCauseCode::ItemObligation(trait_ty.def_id), ); - let predicates = tcx.projection_predicates(trait_ty.def_id); - debug!("compare_projection_bounds: projection_predicates={:?}", predicates); + let predicates = tcx.item_bounds(trait_ty.def_id); + debug!("check_type_bounds: item_bounds={:?}", predicates); for predicate in predicates { let concrete_ty_predicate = predicate.subst(tcx, rebased_substs); From a7ead3bd539e75cb2e881238406a203023f1acd3 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 23 Jun 2020 18:18:06 +0100 Subject: [PATCH 02/34] Move item_bounds to typeck::collect --- compiler/rustc_ty/src/ty.rs | 125 +---------------- compiler/rustc_typeck/src/collect.rs | 2 + .../rustc_typeck/src/collect/item_bounds.rs | 126 ++++++++++++++++++ 3 files changed, 129 insertions(+), 124 deletions(-) create mode 100644 compiler/rustc_typeck/src/collect/item_bounds.rs diff --git a/compiler/rustc_ty/src/ty.rs b/compiler/rustc_ty/src/ty.rs index 2be466bf77348..1f21d9488a454 100644 --- a/compiler/rustc_ty/src/ty.rs +++ b/compiler/rustc_ty/src/ty.rs @@ -1,11 +1,9 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::svh::Svh; use rustc_hir as hir; -use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; -use rustc_infer::traits::util; use rustc_middle::hir::map as hir_map; -use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{ self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, }; @@ -492,126 +490,6 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn_like.asyncness() } -/// For associated types we allow bounds written on the associated type -/// (`type X: Trait`) to be used as candidates. We also allow the same bounds -/// when desugared as bounds on the trait `where Self::X: Trait`. -/// -/// Note that this filtering is done with the items identity substs to -/// simplify checking that these bounds are met in impls. This means that -/// a bound such as `for<'b> >::U: Clone` can't be used, as in -/// `hr-associated-type-bound-1.rs`. -fn associated_type_bounds( - tcx: TyCtxt<'_>, - assoc_item_def_id: DefId, -) -> &'_ ty::List> { - let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id); - // We include predicates from the trait as well to handle - // `where Self::X: Trait`. - let item_bounds = generic_trait_bounds.instantiate_identity(tcx); - let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter()); - - let assoc_item_ty = ty::ProjectionTy { - item_def_id: assoc_item_def_id, - substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id), - }; - - let predicates = item_predicates.filter_map(|obligation| { - let pred = obligation.predicate; - match pred.skip_binders() { - ty::PredicateAtom::Trait(tr, _) => { - if let ty::Projection(p) = *tr.self_ty().kind() { - if p == assoc_item_ty { - return Some(pred); - } - } - } - ty::PredicateAtom::Projection(proj) => { - if let ty::Projection(p) = *proj.projection_ty.self_ty().kind() { - if p == assoc_item_ty { - return Some(pred); - } - } - } - ty::PredicateAtom::TypeOutlives(outlives) => { - if let ty::Projection(p) = *outlives.0.kind() { - if p == assoc_item_ty { - return Some(pred); - } - } - } - _ => {} - } - None - }); - - let result = tcx.mk_predicates(predicates); - debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), result); - result -} - -/// Opaque types don't have the same issues as associated types: the only -/// predicates on an opaque type (excluding those it inherits from its parent -/// item) should be of the form we're expecting. -fn opaque_type_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - - let bounds = tcx.predicates_of(def_id); - let predicates = - util::elaborate_predicates(tcx, bounds.predicates.iter().map(|&(pred, _)| pred)); - - let filtered_predicates = predicates.filter_map(|obligation| { - let pred = obligation.predicate; - match pred.skip_binders() { - ty::PredicateAtom::Trait(tr, _) => { - if let ty::Opaque(opaque_def_id, opaque_substs) = *tr.self_ty().kind() { - if opaque_def_id == def_id && opaque_substs == substs { - return Some(pred); - } - } - } - ty::PredicateAtom::Projection(proj) => { - if let ty::Opaque(opaque_def_id, opaque_substs) = - *proj.projection_ty.self_ty().kind() - { - if opaque_def_id == def_id && opaque_substs == substs { - return Some(pred); - } - } - } - ty::PredicateAtom::TypeOutlives(outlives) => { - if let ty::Opaque(opaque_def_id, opaque_substs) = *outlives.0.kind() { - if opaque_def_id == def_id && opaque_substs == substs { - return Some(pred); - } - } else { - // These can come from elaborating other predicates - return None; - } - } - // These can come from elaborating other predicates - ty::PredicateAtom::RegionOutlives(_) => return None, - _ => {} - } - tcx.sess.delay_span_bug( - obligation.cause.span(tcx), - &format!("unexpected predicate {:?} on opaque type", pred), - ); - None - }); - - let result = tcx.mk_predicates(filtered_predicates); - debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(def_id), result); - result -} - -fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { - match tcx.def_kind(def_id) { - DefKind::AssocTy => associated_type_bounds(tcx, def_id), - DefKind::OpaqueTy => opaque_type_bounds(tcx, def_id), - k => bug!("item_bounds called on {}", k.descr(def_id)), - } -} - pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { asyncness, @@ -629,7 +507,6 @@ pub fn provide(providers: &mut ty::query::Providers) { instance_def_size_estimate, issue33140_self_ty, impl_defaultness, - item_bounds, ..*providers }; } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 1f4f40fca9be3..b4ce3ac74e67e 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -50,6 +50,7 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; +mod item_bounds; mod type_of; struct OnlySelfBounds(bool); @@ -68,6 +69,7 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { opt_const_param_of: type_of::opt_const_param_of, type_of: type_of::type_of, + item_bounds: item_bounds::item_bounds, generics_of, predicates_of, predicates_defined_on, diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs new file mode 100644 index 0000000000000..c43f830787dba --- /dev/null +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -0,0 +1,126 @@ +use rustc_hir::def::DefKind; +use rustc_infer::traits::util; +use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::def_id::DefId; + +/// For associated types we allow bounds written on the associated type +/// (`type X: Trait`) to be used as candidates. We also allow the same bounds +/// when desugared as bounds on the trait `where Self::X: Trait`. +/// +/// Note that this filtering is done with the items identity substs to +/// simplify checking that these bounds are met in impls. This means that +/// a bound such as `for<'b> >::U: Clone` can't be used, as in +/// `hr-associated-type-bound-1.rs`. +fn associated_type_bounds( + tcx: TyCtxt<'_>, + assoc_item_def_id: DefId, +) -> &'_ ty::List> { + let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id); + // We include predicates from the trait as well to handle + // `where Self::X: Trait`. + let item_bounds = generic_trait_bounds.instantiate_identity(tcx); + let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter()); + + let assoc_item_ty = ty::ProjectionTy { + item_def_id: assoc_item_def_id, + substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id), + }; + + let predicates = item_predicates.filter_map(|obligation| { + let pred = obligation.predicate; + match pred.kind() { + ty::PredicateKind::Trait(tr, _) => { + if let ty::Projection(p) = *tr.skip_binder().self_ty().kind() { + if p == assoc_item_ty { + return Some(pred); + } + } + } + ty::PredicateKind::Projection(proj) => { + if let ty::Projection(p) = *proj.skip_binder().projection_ty.self_ty().kind() { + if p == assoc_item_ty { + return Some(pred); + } + } + } + ty::PredicateKind::TypeOutlives(outlives) => { + if let ty::Projection(p) = *outlives.skip_binder().0.kind() { + if p == assoc_item_ty { + return Some(pred); + } + } + } + _ => {} + } + None + }); + + let result = tcx.mk_predicates(predicates); + debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), result); + result +} + +/// Opaque types don't have the same issues as associated types: the only +/// predicates on an opaque type (excluding those it inherits from its parent +/// item) should be of the form we're expecting. +fn opaque_type_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + + let bounds = tcx.predicates_of(def_id); + let predicates = + util::elaborate_predicates(tcx, bounds.predicates.iter().map(|&(pred, _)| pred)); + + let filtered_predicates = predicates.filter_map(|obligation| { + let pred = obligation.predicate; + match pred.kind() { + ty::PredicateKind::Trait(tr, _) => { + if let ty::Opaque(opaque_def_id, opaque_substs) = *tr.skip_binder().self_ty().kind() + { + if opaque_def_id == def_id && opaque_substs == substs { + return Some(pred); + } + } + } + ty::PredicateKind::Projection(proj) => { + if let ty::Opaque(opaque_def_id, opaque_substs) = + *proj.skip_binder().projection_ty.self_ty().kind() + { + if opaque_def_id == def_id && opaque_substs == substs { + return Some(pred); + } + } + } + ty::PredicateKind::TypeOutlives(outlives) => { + if let ty::Opaque(opaque_def_id, opaque_substs) = *outlives.skip_binder().0.kind() { + if opaque_def_id == def_id && opaque_substs == substs { + return Some(pred); + } + } else { + // These can come from elaborating other predicates + return None; + } + } + // These can come from elaborating other predicates + ty::PredicateKind::RegionOutlives(_) => return None, + _ => {} + } + tcx.sess.delay_span_bug( + obligation.cause.span(tcx), + &format!("unexpected predicate {:?} on opaque type", pred), + ); + None + }); + + let result = tcx.mk_predicates(filtered_predicates); + debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(def_id), result); + result +} + +pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { + match tcx.def_kind(def_id) { + DefKind::AssocTy => associated_type_bounds(tcx, def_id), + DefKind::OpaqueTy => opaque_type_bounds(tcx, def_id), + k => bug!("item_bounds called on {}", k.descr(def_id)), + } +} From d297147e620431dacfd4bbe90c6f82911b7d72c5 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 24 Jun 2020 19:13:44 +0100 Subject: [PATCH 03/34] Split bounds from predicates --- compiler/rustc_metadata/src/rmeta/decoder.rs | 15 +- .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 13 +- compiler/rustc_metadata/src/rmeta/mod.rs | 10 +- compiler/rustc_middle/src/query/mod.rs | 7 +- compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- .../rustc_trait_selection/src/opaque_types.rs | 27 +-- compiler/rustc_typeck/src/bounds.rs | 6 +- compiler/rustc_typeck/src/collect.rs | 112 +---------- .../rustc_typeck/src/collect/item_bounds.rs | 189 ++++++++---------- 10 files changed, 153 insertions(+), 231 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 8b11d2c913ac2..2662f6b6ed65c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -937,7 +937,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .inferred_outlives .get(self, item_id) - .map(|predicates| predicates.decode((self, tcx))) + .map(|predicates| tcx.arena.alloc_from_iter(predicates.decode((self, tcx)))) .unwrap_or_default() } @@ -949,6 +949,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.super_predicates.get(self, item_id).unwrap().decode((self, tcx)) } + fn get_explicit_item_bounds( + &self, + item_id: DefIndex, + tcx: TyCtxt<'tcx>, + ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + self.root + .tables + .explicit_item_bounds + .get(self, item_id) + .map(|bounds| tcx.arena.alloc_from_iter(bounds.decode((self, tcx)))) + .unwrap_or_default() + } + fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics { self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess)) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 578ce382912f0..60705f68681a1 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -89,6 +89,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, explicit_predicates_of => { cdata.get_explicit_predicates(def_id.index, tcx) } inferred_outlives_of => { cdata.get_inferred_outlives(def_id.index, tcx) } super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } + explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) } trait_def => { cdata.get_trait_def(def_id.index, tcx.sess) } adt_def => { cdata.get_adt_def(def_id.index, tcx) } adt_destructor => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4350ac5c27a88..9f12edf9cb2f8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -965,6 +965,14 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id)); } + fn encode_explicit_item_bounds(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id); + let bounds = self.tcx.explicit_item_bounds(def_id); + if !bounds.is_empty() { + record!(self.tables.explicit_item_bounds[def_id] <- bounds); + } + } + fn encode_info_for_trait_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; @@ -1017,7 +1025,10 @@ impl EncodeContext<'a, 'tcx> { has_self: trait_item.fn_has_self_parameter, })) } - ty::AssocKind::Type => EntryKind::AssocType(container), + ty::AssocKind::Type => { + self.encode_explicit_item_bounds(def_id); + EntryKind::AssocType(container) + } }); record!(self.tables.visibility[def_id] <- trait_item.vis); record!(self.tables.span[def_id] <- ast_item.span); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 9e26d02e4e16d..2bd2019d3cdb5 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -295,13 +295,11 @@ define_tables! { generics: Table>, explicit_predicates: Table)>, expn_that_defined: Table>, - // FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate` - // doesn't handle shorthands in its own (de)serialization impls, - // as it's an `enum` for which we want to derive (de)serialization, - // so the `ty::codec` APIs handle the whole `&'tcx [...]` at once. - // Also, as an optimization, a missing entry indicates an empty `&[]`. - inferred_outlives: Table, Span)])>, + // As an optimization, a missing entry indicates an empty `&[]`. + inferred_outlives: Table, Span)])>, super_predicates: Table)>, + // As an optimization, a missing entry indicates an empty `&[]`. + explicit_item_bounds: Table, Span)])>, mir: Table)>, promoted_mir: Table>)>, mir_abstract_consts: Table])>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index fadc7621785af..8b94818d8e651 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -169,8 +169,13 @@ rustc_queries! { /// ^^^^^^^^^^^^^^^ /// /// `key` is the `DefId` of the associated type or opaque type. + query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } + } + + /// Elaborated the predicates from `explicit_item_bounds`. query item_bounds(key: DefId) -> &'tcx ty::List> { - desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) } + desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } query projection_ty_from_predicates(key: (DefId, DefId)) -> Option> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 238bce94cf505..5cd8f3e787751 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -607,12 +607,12 @@ pub trait PrettyPrinter<'tcx>: } // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs); + let bounds = self.tcx().item_bounds(def_id).subst(self.tcx(), substs); let mut first = true; let mut is_sized = false; p!("impl"); - for predicate in bounds.predicates { + for predicate in bounds { // Note: We can't use `to_opt_poly_trait_ref` here as `predicate` // may contain unbound variables. We therefore do this manually. // diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 618f3e045e712..1babfb8508ed8 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -10,7 +10,7 @@ use rustc_infer::infer::free_regions::FreeRegionRelations; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, InferOk}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::config::nightly_options; use rustc_span::Span; @@ -428,14 +428,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // If there are required region bounds, we can use them. if opaque_defn.has_required_region_bounds { - let predicates_of = tcx.predicates_of(def_id); - debug!("constrain_opaque_type: predicates: {:#?}", predicates_of,); - let bounds = predicates_of.instantiate(tcx, opaque_defn.substs); + let bounds = tcx.explicit_item_bounds(def_id); + debug!("constrain_opaque_type: predicates: {:#?}", bounds); + let bounds: Vec<_> = + bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_defn.substs)).collect(); debug!("constrain_opaque_type: bounds={:#?}", bounds); let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); let required_region_bounds = - required_region_bounds(tcx, opaque_type, bounds.predicates.into_iter()); + required_region_bounds(tcx, opaque_type, bounds.into_iter()); debug_assert!(!required_region_bounds.is_empty()); for required_region in required_region_bounds { @@ -1112,9 +1113,10 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { let ty_var = infcx .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); - let predicates_of = tcx.predicates_of(def_id); - debug!("instantiate_opaque_types: predicates={:#?}", predicates_of,); - let bounds = predicates_of.instantiate(tcx, substs); + let item_bounds = tcx.explicit_item_bounds(def_id); + debug!("instantiate_opaque_types: bounds={:#?}", item_bounds); + let bounds: Vec<_> = + item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect(); let param_env = tcx.param_env(def_id); let InferOk { value: bounds, obligations } = @@ -1123,8 +1125,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { debug!("instantiate_opaque_types: bounds={:?}", bounds); - let required_region_bounds = - required_region_bounds(tcx, ty, bounds.predicates.iter().cloned()); + let required_region_bounds = required_region_bounds(tcx, ty, bounds.iter().copied()); debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds); // Make sure that we are in fact defining the *entire* type @@ -1153,7 +1154,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { ); debug!("instantiate_opaque_types: ty_var={:?}", ty_var); - for predicate in &bounds.predicates { + for predicate in &bounds { if let ty::PredicateAtom::Projection(projection) = predicate.skip_binders() { if projection.ty.references_error() { // No point on adding these obligations since there's a type error involved. @@ -1162,8 +1163,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { } } - self.obligations.reserve(bounds.predicates.len()); - for predicate in bounds.predicates { + self.obligations.reserve(bounds.len()); + for predicate in bounds { // Change the predicate to refer to the type variable, // which will be the concrete type instead of the opaque type. // This also instantiates nested instances of `impl Trait`. diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 63295f5faacc9..80f39051c587f 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -71,12 +71,8 @@ impl<'tcx> Bounds<'tcx> { self.region_bounds .iter() .map(|&(region_bound, span)| { - // Account for the binder being introduced below; no need to shift `param_ty` - // because, at present at least, it either only refers to early-bound regions, - // or it's a generic associated type that deliberately has escaping bound vars. - let region_bound = ty::fold::shift_region(tcx, region_bound, 1); let outlives = ty::OutlivesPredicate(param_ty, region_bound); - (ty::Binder::bind(outlives).to_predicate(tcx), span) + (ty::Binder::dummy(outlives).to_predicate(tcx), span) }) .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| { let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index b4ce3ac74e67e..4df5135cca579 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -70,6 +70,7 @@ pub fn provide(providers: &mut Providers) { opt_const_param_of: type_of::opt_const_param_of, type_of: type_of::type_of, item_bounds: item_bounds::item_bounds, + explicit_item_bounds: item_bounds::explicit_item_bounds, generics_of, predicates_of, predicates_defined_on, @@ -1728,7 +1729,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat let mut is_trait = None; let mut is_default_impl_trait = None; - let mut is_trait_associated_type = None; let icx = ItemCtxt::new(tcx, def_id); let constness = icx.default_constness_for_trait_bounds(); @@ -1741,12 +1741,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default(); let ast_generics = match node { - Node::TraitItem(item) => { - if let hir::TraitItemKind::Type(bounds, _) = item.kind { - is_trait_associated_type = Some((bounds, item.span)); - } - &item.generics - } + Node::TraitItem(item) => &item.generics, Node::ImplItem(item) => &item.generics, @@ -1764,44 +1759,26 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) => generics, - ItemKind::Trait(_, _, ref generics, .., items) => { - is_trait = Some((ty::TraitRef::identity(tcx, def_id), items)); + ItemKind::Trait(_, _, ref generics, ..) => { + is_trait = Some(ty::TraitRef::identity(tcx, def_id)); generics } ItemKind::TraitAlias(ref generics, _) => { - is_trait = Some((ty::TraitRef::identity(tcx, def_id), &[])); + is_trait = Some(ty::TraitRef::identity(tcx, def_id)); generics } ItemKind::OpaqueTy(OpaqueTy { - ref bounds, + bounds: _, impl_trait_fn, ref generics, origin: _, }) => { - let bounds_predicates = ty::print::with_no_queries(|| { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - let opaque_ty = tcx.mk_opaque(def_id, substs); - - // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`. - let bounds = AstConv::compute_bounds( - &icx, - opaque_ty, - bounds, - SizedByDefault::Yes, - tcx.def_span(def_id), - ); - - bounds.predicates(tcx, opaque_ty) - }); if impl_trait_fn.is_some() { - // opaque types - return ty::GenericPredicates { - parent: None, - predicates: tcx.arena.alloc_from_iter(bounds_predicates), - }; + // return-position impl trait + // TODO: Investigate why we have this special case? + return ty::GenericPredicates { parent: None, predicates: &[] }; } else { - // named opaque types - predicates.extend(bounds_predicates); + // type alias impl trait generics } } @@ -1827,7 +1804,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat // and the explicit where-clauses, but to get the full set of predicates // on a trait we need to add in the supertrait bounds and bounds found on // associated types. - if let Some((_trait_ref, _)) = is_trait { + if let Some(_trait_ref) = is_trait { predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); } @@ -1994,24 +1971,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat } } - // Add predicates from associated type bounds (`type X: Bound`) - if tcx.features().generic_associated_types { - // New behavior: bounds declared on associate type are predicates of that - // associated type. Not the default because it needs more testing. - if let Some((bounds, span)) = is_trait_associated_type { - let projection_ty = - tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id)); - - predicates.extend(associated_item_bounds(tcx, def_id, bounds, projection_ty, span)) - } - } else if let Some((self_trait_ref, trait_items)) = is_trait { - // Current behavior: bounds declared on associate type are predicates - // of its parent trait. - predicates.extend(trait_items.iter().flat_map(|trait_item_ref| { - trait_associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref) - })) - } - if tcx.features().const_evaluatable_checked { predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local())); } @@ -2155,55 +2114,6 @@ fn projection_ty_from_predicates( projection_ty } -fn trait_associated_item_predicates( - tcx: TyCtxt<'tcx>, - def_id: DefId, - self_trait_ref: ty::TraitRef<'tcx>, - trait_item_ref: &hir::TraitItemRef, -) -> Vec<(ty::Predicate<'tcx>, Span)> { - let trait_item = tcx.hir().trait_item(trait_item_ref.id); - let item_def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id); - let bounds = match trait_item.kind { - hir::TraitItemKind::Type(ref bounds, _) => bounds, - _ => return Vec::new(), - }; - - if !tcx.generics_of(item_def_id).params.is_empty() { - // For GATs the substs provided to the mk_projection call below are - // wrong. We should emit a feature gate error if we get here so skip - // this type. - tcx.sess.delay_span_bug(trait_item.span, "gats used without feature gate"); - return Vec::new(); - } - - let assoc_ty = tcx.mk_projection( - tcx.hir().local_def_id(trait_item.hir_id).to_def_id(), - self_trait_ref.substs, - ); - - associated_item_bounds(tcx, def_id, bounds, assoc_ty, trait_item.span) -} - -fn associated_item_bounds( - tcx: TyCtxt<'tcx>, - def_id: DefId, - bounds: &'tcx [hir::GenericBound<'tcx>], - projection_ty: Ty<'tcx>, - span: Span, -) -> Vec<(ty::Predicate<'tcx>, Span)> { - let bounds = AstConv::compute_bounds( - &ItemCtxt::new(tcx, def_id), - projection_ty, - bounds, - SizedByDefault::Yes, - span, - ); - - let predicates = bounds.predicates(tcx, projection_ty); - - predicates -} - /// Converts a specific `GenericBound` from the AST into a set of /// predicates that apply to the self type. A vector is returned /// because this can be anywhere from zero predicates (`T: ?Sized` adds no diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index c43f830787dba..96e331ba516de 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -1,126 +1,113 @@ -use rustc_hir::def::DefKind; +use super::ItemCtxt; +use crate::astconv::{AstConv, SizedByDefault}; +use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; +use rustc_span::Span; -/// For associated types we allow bounds written on the associated type -/// (`type X: Trait`) to be used as candidates. We also allow the same bounds -/// when desugared as bounds on the trait `where Self::X: Trait`. +/// For associated types we include both bounds written on the type +/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`. /// /// Note that this filtering is done with the items identity substs to /// simplify checking that these bounds are met in impls. This means that /// a bound such as `for<'b> >::U: Clone` can't be used, as in /// `hr-associated-type-bound-1.rs`. -fn associated_type_bounds( - tcx: TyCtxt<'_>, +fn associated_type_bounds<'tcx>( + tcx: TyCtxt<'tcx>, assoc_item_def_id: DefId, -) -> &'_ ty::List> { - let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id); - // We include predicates from the trait as well to handle - // `where Self::X: Trait`. - let item_bounds = generic_trait_bounds.instantiate_identity(tcx); - let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter()); + bounds: &'tcx [hir::GenericBound<'tcx>], + span: Span, +) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + let item_ty = tcx.mk_projection( + assoc_item_def_id, + InternalSubsts::identity_for_item(tcx, assoc_item_def_id), + ); - let assoc_item_ty = ty::ProjectionTy { - item_def_id: assoc_item_def_id, - substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id), - }; + let bounds = AstConv::compute_bounds( + &ItemCtxt::new(tcx, assoc_item_def_id), + item_ty, + bounds, + SizedByDefault::Yes, + span, + ); - let predicates = item_predicates.filter_map(|obligation| { - let pred = obligation.predicate; - match pred.kind() { - ty::PredicateKind::Trait(tr, _) => { - if let ty::Projection(p) = *tr.skip_binder().self_ty().kind() { - if p == assoc_item_ty { - return Some(pred); - } - } - } + let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id(); + let trait_predicates = tcx.predicates_of(trait_def_id); + + let bounds_from_parent = + trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.kind() { + ty::PredicateKind::Trait(tr, _) => tr.skip_binder().self_ty() == item_ty, ty::PredicateKind::Projection(proj) => { - if let ty::Projection(p) = *proj.skip_binder().projection_ty.self_ty().kind() { - if p == assoc_item_ty { - return Some(pred); - } - } - } - ty::PredicateKind::TypeOutlives(outlives) => { - if let ty::Projection(p) = *outlives.skip_binder().0.kind() { - if p == assoc_item_ty { - return Some(pred); - } - } + proj.skip_binder().projection_ty.self_ty() == item_ty } - _ => {} - } - None - }); + ty::PredicateKind::TypeOutlives(outlives) => outlives.skip_binder().0 == item_ty, + _ => false, + }); - let result = tcx.mk_predicates(predicates); - debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), result); - result + let all_bounds = tcx + .arena + .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent)); + debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds); + all_bounds } -/// Opaque types don't have the same issues as associated types: the only -/// predicates on an opaque type (excluding those it inherits from its parent -/// item) should be of the form we're expecting. -fn opaque_type_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - - let bounds = tcx.predicates_of(def_id); - let predicates = - util::elaborate_predicates(tcx, bounds.predicates.iter().map(|&(pred, _)| pred)); +/// Opaque types don't inherit bounds from their parent: for return position +/// impl trait it isn't possible to write a suitable predicate on the +/// containing function and for type-alias impl trait we don't have a backwards +/// compatibility issue. +fn opaque_type_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + opaque_def_id: DefId, + bounds: &'tcx [hir::GenericBound<'tcx>], + span: Span, +) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + let item_ty = + tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); - let filtered_predicates = predicates.filter_map(|obligation| { - let pred = obligation.predicate; - match pred.kind() { - ty::PredicateKind::Trait(tr, _) => { - if let ty::Opaque(opaque_def_id, opaque_substs) = *tr.skip_binder().self_ty().kind() - { - if opaque_def_id == def_id && opaque_substs == substs { - return Some(pred); - } - } - } - ty::PredicateKind::Projection(proj) => { - if let ty::Opaque(opaque_def_id, opaque_substs) = - *proj.skip_binder().projection_ty.self_ty().kind() - { - if opaque_def_id == def_id && opaque_substs == substs { - return Some(pred); - } - } - } - ty::PredicateKind::TypeOutlives(outlives) => { - if let ty::Opaque(opaque_def_id, opaque_substs) = *outlives.skip_binder().0.kind() { - if opaque_def_id == def_id && opaque_substs == substs { - return Some(pred); - } - } else { - // These can come from elaborating other predicates - return None; - } - } - // These can come from elaborating other predicates - ty::PredicateKind::RegionOutlives(_) => return None, - _ => {} - } - tcx.sess.delay_span_bug( - obligation.cause.span(tcx), - &format!("unexpected predicate {:?} on opaque type", pred), - ); - None + let bounds = ty::print::with_no_queries(|| { + AstConv::compute_bounds( + &ItemCtxt::new(tcx, opaque_def_id), + item_ty, + bounds, + SizedByDefault::Yes, + span, + ) }); - let result = tcx.mk_predicates(filtered_predicates); - debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(def_id), result); - result + let bounds = bounds.predicates(tcx, item_ty); + debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds); + + tcx.arena.alloc_slice(&bounds) } -pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { - match tcx.def_kind(def_id) { - DefKind::AssocTy => associated_type_bounds(tcx, def_id), - DefKind::OpaqueTy => opaque_type_bounds(tcx, def_id), - k => bug!("item_bounds called on {}", k.descr(def_id)), +pub(super) fn explicit_item_bounds( + tcx: TyCtxt<'_>, + def_id: DefId, +) -> &'_ [(ty::Predicate<'_>, Span)] { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + match tcx.hir().get(hir_id) { + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Type(bounds, _), + span, + .. + }) => associated_type_bounds(tcx, def_id, bounds, *span), + hir::Node::Item(hir::Item { + kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }), + span, + .. + }) => opaque_type_bounds(tcx, def_id, bounds, *span), + _ => bug!("item_bounds called on {:?}", def_id), } } + +pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List> { + tcx.mk_predicates( + util::elaborate_predicates( + tcx, + tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), + ) + .map(|obligation| obligation.predicate), + ) +} From f958e6c24615c4b1f1e77b0ee3d4f32383fb3617 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 27 Jun 2020 21:36:35 +0100 Subject: [PATCH 04/34] Separate bounds and predicates for associated/opaque types --- compiler/rustc_ast_lowering/src/expr.rs | 30 +-- compiler/rustc_infer/src/traits/util.rs | 31 +-- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +- compiler/rustc_middle/src/ty/print/pretty.rs | 5 +- compiler/rustc_privacy/src/lib.rs | 21 +- compiler/rustc_traits/src/chalk/db.rs | 27 ++- compiler/rustc_traits/src/chalk/lowering.rs | 78 ++++++++ compiler/rustc_typeck/src/check/check.rs | 28 ++- .../rustc_typeck/src/check/compare_method.rs | 33 ++-- compiler/rustc_typeck/src/check/wfcheck.rs | 106 ++-------- compiler/rustc_typeck/src/collect.rs | 20 +- .../bad-bounds-on-assoc-in-trait.rs | 8 +- .../bad-bounds-on-assoc-in-trait.stderr | 97 ++++------ .../bounds-on-assoc-in-trait.rs | 7 +- .../bounds-on-assoc-in-trait.stderr | 36 ++++ .../associated-type-bounds/duplicate.stderr | 26 +-- .../associated-types-unconstrained.stderr | 9 +- .../defaults-cyclic-fail-1.rs | 7 +- .../defaults-cyclic-fail-1.stderr | 28 +-- .../defaults-cyclic-fail-2.rs | 6 - .../defaults-cyclic-fail-2.stderr | 28 +-- .../associated-types/defaults-suitability.rs | 32 ++- .../defaults-suitability.stderr | 169 +++++++--------- .../defaults-unsound-62211-1.rs | 17 +- .../defaults-unsound-62211-1.stderr | 182 +++++++----------- .../defaults-unsound-62211-2.rs | 17 +- .../defaults-unsound-62211-2.stderr | 182 +++++++----------- src/test/ui/associated-types/defaults-wf.rs | 11 ++ .../ui/associated-types/defaults-wf.stderr | 16 ++ src/test/ui/associated-types/issue-43924.rs | 7 +- .../ui/associated-types/issue-43924.stderr | 40 ++-- .../ui/associated-types/issue-63593.stderr | 7 +- src/test/ui/associated-types/issue-65774-1.rs | 2 +- .../ui/associated-types/issue-65774-1.stderr | 23 ++- src/test/ui/associated-types/issue-65774-2.rs | 2 +- .../ui/associated-types/issue-65774-2.stderr | 22 +-- src/test/ui/associated-types/issue-72806.rs | 3 +- .../ui/associated-types/issue-72806.stderr | 9 +- .../point-at-type-on-obligation-failure-2.rs | 4 +- ...int-at-type-on-obligation-failure-2.stderr | 17 +- .../point-at-type-on-obligation-failure-3.rs | 11 ++ ...int-at-type-on-obligation-failure-3.stderr | 12 ++ .../point-at-type-on-obligation-failure.rs | 3 +- ...point-at-type-on-obligation-failure.stderr | 9 +- src/test/ui/chalkify/impl_wf.rs | 13 -- src/test/ui/chalkify/impl_wf.stderr | 15 +- src/test/ui/chalkify/impl_wf_2.rs | 33 ++++ src/test/ui/chalkify/impl_wf_2.stderr | 12 ++ .../feature-gate-associated_type_bounds.rs | 1 + ...feature-gate-associated_type_bounds.stderr | 52 +++-- src/test/ui/generator/sized-yield.stderr | 5 + .../issue-68641-check-gat-bounds.stderr | 2 +- .../issue-68642-broken-llvm-ir.stderr | 2 +- .../issue-68643-broken-mir.stderr | 2 +- .../issue-68644-codegen-selection.stderr | 2 +- .../issue-68645-codegen-fulfillment.stderr | 2 +- .../issue-68656-unsized-values.stderr | 2 +- .../unsatisfied-outlives-bound.rs | 4 +- .../unsatisfied-outlives-bound.stderr | 20 +- ...r-async-enabled-impl-trait-bindings.stderr | 6 +- .../ui/inference/cannot-infer-async.stderr | 4 +- .../ui/inference/cannot-infer-closure.stderr | 4 +- src/test/ui/issues/issue-20605.stderr | 5 +- src/test/ui/issues/issue-20831-debruijn.rs | 3 - .../ui/issues/issue-20831-debruijn.stderr | 85 +------- src/test/ui/issues/issue-21946.rs | 1 - src/test/ui/issues/issue-21946.stderr | 12 +- src/test/ui/issues/issue-23122-1.rs | 1 - src/test/ui/issues/issue-23122-1.stderr | 12 +- src/test/ui/issues/issue-23122-2.rs | 1 - src/test/ui/issues/issue-23122-2.stderr | 15 +- src/test/ui/issues/issue-24204.rs | 2 +- src/test/ui/issues/issue-24204.stderr | 17 +- src/test/ui/issues/issue-28098.stderr | 5 +- src/test/ui/issues/issue-33941.stderr | 4 +- src/test/ui/issues/issue-38091.stderr | 2 +- .../issues/issue-43784-associated-type.stderr | 9 +- .../ui/issues/issue-43784-supertrait.stderr | 3 + src/test/ui/issues/issue-65673.stderr | 8 +- src/test/ui/never_type/issue-51506.stderr | 2 +- .../impl-fn-ignore-binder-via-bottom.rs | 1 - .../impl-fn-ignore-binder-via-bottom.stderr | 8 +- .../ui/privacy/private-in-public-assoc-ty.rs | 4 + .../privacy/private-in-public-assoc-ty.stderr | 30 +-- src/test/ui/privacy/private-in-public-warn.rs | 2 +- .../ui/privacy/private-in-public-warn.stderr | 14 +- src/test/ui/privacy/pub-priv-dep/pub-priv1.rs | 17 +- .../ui/privacy/pub-priv-dep/pub-priv1.stderr | 6 +- src/test/ui/question-mark-type-infer.stderr | 4 +- src/test/ui/range/range-1.stderr | 2 +- ...ssoc-type-region-bound-in-trait-not-met.rs | 4 +- ...-type-region-bound-in-trait-not-met.stderr | 50 ++--- ...ssoc-type-static-bound-in-trait-not-met.rs | 2 +- ...-type-static-bound-in-trait-not-met.stderr | 26 +-- .../deafult-associated-type-bound-1.stderr | 2 +- .../deafult-associated-type-bound-2.stderr | 2 +- .../deafult-generic-associated-type-bound.rs | 2 +- ...afult-generic-associated-type-bound.stderr | 4 +- src/test/ui/specialization/issue-44861.stderr | 2 +- src/test/ui/specialization/issue-59435.stderr | 2 +- .../missing-assoc-type-bound-restriction.rs | 2 - ...issing-assoc-type-bound-restriction.stderr | 45 +---- src/test/ui/traits/cycle-cache-err-60010.rs | 4 +- .../traits-inductive-overflow-two-traits.rs | 1 + ...raits-inductive-overflow-two-traits.stderr | 21 +- .../ui/try-block/try-block-bad-type.stderr | 2 +- 107 files changed, 934 insertions(+), 1128 deletions(-) create mode 100644 src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr create mode 100644 src/test/ui/associated-types/defaults-wf.rs create mode 100644 src/test/ui/associated-types/defaults-wf.stderr create mode 100644 src/test/ui/associated-types/point-at-type-on-obligation-failure-3.rs create mode 100644 src/test/ui/associated-types/point-at-type-on-obligation-failure-3.stderr create mode 100644 src/test/ui/chalkify/impl_wf_2.rs create mode 100644 src/test/ui/chalkify/impl_wf_2.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c97f80cf09ba1..4676ad5c31fca 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -432,17 +432,25 @@ impl<'hir> LoweringContext<'_, 'hir> { self.with_catch_scope(body.id, |this| { let mut block = this.lower_block_noalloc(body, true); - let try_span = this.mark_span_with_reason( - DesugaringKind::TryBlock, - body.span, - this.allow_try_trait.clone(), - ); - // Final expression of the block (if present) or `()` with span at the end of block - let tail_expr = block - .expr - .take() - .unwrap_or_else(|| this.expr_unit(this.sess.source_map().end_point(try_span))); + let (try_span, tail_expr) = if let Some(expr) = block.expr.take() { + ( + this.mark_span_with_reason( + DesugaringKind::TryBlock, + expr.span, + this.allow_try_trait.clone(), + ), + expr, + ) + } else { + let try_span = this.mark_span_with_reason( + DesugaringKind::TryBlock, + this.sess.source_map().end_point(body.span), + this.allow_try_trait.clone(), + ); + + (try_span, this.expr_unit(try_span)) + }; let ok_wrapped_span = this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None); @@ -1553,7 +1561,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::TryFromError, unstable_span, from_expr, - try_span, + unstable_span, ); let thin_attrs = ThinVec::from(attrs); let catch_scope = self.catch_scopes.last().copied(); diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 9c0d934a03529..1b7269706a758 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -4,7 +4,6 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::ty::outlives::Component; use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; -use rustc_span::Span; pub fn anonymize_predicate<'tcx>( tcx: TyCtxt<'tcx>, @@ -94,7 +93,11 @@ pub fn elaborate_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: impl Iterator>, ) -> Elaborator<'tcx> { - let obligations = predicates.map(|predicate| predicate_obligation(predicate, None)).collect(); + let obligations = predicates + .map(|predicate| { + predicate_obligation(predicate, ty::ParamEnv::empty(), ObligationCause::dummy()) + }) + .collect(); elaborate_obligations(tcx, obligations) } @@ -109,15 +112,10 @@ pub fn elaborate_obligations<'tcx>( fn predicate_obligation<'tcx>( predicate: ty::Predicate<'tcx>, - span: Option, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, ) -> PredicateObligation<'tcx> { - let cause = if let Some(span) = span { - ObligationCause::dummy_with_span(span) - } else { - ObligationCause::dummy() - }; - - Obligation { cause, param_env: ty::ParamEnv::empty(), recursion_depth: 0, predicate } + Obligation { cause, param_env, recursion_depth: 0, predicate } } impl Elaborator<'tcx> { @@ -133,10 +131,11 @@ impl Elaborator<'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = predicates.predicates.iter().map(|&(pred, span)| { + let obligations = predicates.predicates.iter().map(|&(pred, _)| { predicate_obligation( pred.subst_supertrait(tcx, &ty::Binder::bind(data.trait_ref)), - Some(span), + obligation.param_env, + obligation.cause.clone(), ) }); debug!("super_predicates: data={:?}", data); @@ -233,7 +232,13 @@ impl Elaborator<'tcx> { }) .map(|predicate_kind| predicate_kind.to_predicate(tcx)) .filter(|&predicate| visited.insert(predicate)) - .map(|predicate| predicate_obligation(predicate, None)), + .map(|predicate| { + predicate_obligation( + predicate, + obligation.param_env, + obligation.cause.clone(), + ) + }), ); } ty::PredicateAtom::TypeWellFormedFromEnv(..) => { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 1e8c30071e762..3abd9a6325d6e 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ty::Adt(def, _) => check_must_use_def(cx, def.did, span, descr_pre, descr_post), ty::Opaque(def, _) => { let mut has_emitted = false; - for (predicate, _) in cx.tcx.predicates_of(def).predicates { + for &(predicate, _) in cx.tcx.explicit_item_bounds(def) { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateAtom::Trait(ref poly_trait_predicate, _) = predicate.skip_binders() diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 9f12edf9cb2f8..f0911928e81c9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1266,7 +1266,10 @@ impl EncodeContext<'a, 'tcx> { hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, hir::ItemKind::TyAlias(..) => EntryKind::Type, - hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy, + hir::ItemKind::OpaqueTy(..) => { + self.encode_explicit_item_bounds(def_id); + EntryKind::OpaqueTy + } hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr), hir::ItemKind::Struct(ref struct_def, _) => { let adt_def = self.tcx.adt_def(def_id); diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5cd8f3e787751..e1f02d0f70418 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -607,12 +607,13 @@ pub trait PrettyPrinter<'tcx>: } // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let bounds = self.tcx().item_bounds(def_id).subst(self.tcx(), substs); + let bounds = self.tcx().explicit_item_bounds(def_id); let mut first = true; let mut is_sized = false; p!("impl"); - for predicate in bounds { + for (predicate, _) in bounds { + let predicate = predicate.subst(self.tcx(), substs); // Note: We can't use `to_opt_poly_trait_ref` here as `predicate` // may contain unbound variables. We therefore do this manually. // diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8d1b826ea3595..8f93bce6e9923 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -194,11 +194,14 @@ where // The intent is to treat `impl Trait1 + Trait2` identically to // `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself // (it either has no visibility, or its visibility is insignificant, like - // visibilities of type aliases) and recurse into predicates instead to go + // visibilities of type aliases) and recurse into bounds instead to go // through the trait list (default type visitor doesn't visit those traits). // All traits in the list are considered the "primary" part of the type // and are visited by shallow visitors. - if self.visit_predicates(tcx.predicates_of(def_id)) { + if self.visit_predicates(ty::GenericPredicates { + parent: None, + predicates: tcx.explicit_item_bounds(def_id), + }) { return true; } } @@ -1800,6 +1803,14 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { self } + fn bounds(&mut self) -> &mut Self { + self.visit_predicates(ty::GenericPredicates { + parent: None, + predicates: self.tcx.explicit_item_bounds(self.item_def_id), + }); + self + } + fn ty(&mut self) -> &mut Self { self.visit(self.tcx.type_of(self.item_def_id)); self @@ -1975,7 +1986,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> hir::ItemKind::OpaqueTy(..) => { // `ty()` for opaque types is the underlying type, // it's not a part of interface, so we skip it. - self.check(item.hir_id, item_visibility).generics().predicates(); + self.check(item.hir_id, item_visibility).generics().bounds(); } hir::ItemKind::Trait(.., trait_item_refs) => { self.check(item.hir_id, item_visibility).generics().predicates(); @@ -1987,6 +1998,10 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> trait_item_ref.defaultness, item_visibility, ); + + if let AssocItemKind::Type = trait_item_ref.kind { + self.check(trait_item_ref.id.hir_id, item_visibility).bounds(); + } } } hir::ItemKind::TraitAlias(..) => { diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 828ee6dea6256..35b1064d2e4ad 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -73,18 +73,28 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t } let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); let binders = binders_for(&self.interner, bound_vars); - // FIXME(chalk): this really isn't right I don't think. The functions - // for GATs are a bit hard to figure out. Are these supposed to be where - // clauses or bounds? + let where_clauses = self.where_clauses_for(def_id, bound_vars); + let bounds = self + .tcx + .explicit_item_bounds(def_id) + .iter() + .map(|(bound, _)| bound.subst(self.tcx, &bound_vars)) + .filter_map(|bound| { + LowerInto::< + Option>>, + >::lower_into(bound, &self.interner) + }) + .collect(); + Arc::new(chalk_solve::rust_ir::AssociatedTyDatum { trait_id: chalk_ir::TraitId(trait_def_id), id: assoc_type_id, name: (), binders: chalk_ir::Binders::new( binders, - chalk_solve::rust_ir::AssociatedTyDatumBound { bounds: vec![], where_clauses }, + chalk_solve::rust_ir::AssociatedTyDatumBound { bounds, where_clauses }, ), }) } @@ -443,10 +453,17 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let binders = binders_for(&self.interner, bound_vars); let where_clauses = self.where_clauses_for(opaque_ty_id.0, bound_vars); + let bounds: Vec<_> = predicates + .iter() + .map(|(bound, _)| bound.subst(self.tcx, &bound_vars)) + .filter_map(|bound| LowerInto::>>>::lower_into(bound, &self.interner)) + .collect(); + let value = chalk_solve::rust_ir::OpaqueTyDatumBound { - bounds: chalk_ir::Binders::new(binders.clone(), vec![]), + bounds: chalk_ir::Binders::new(binders, bounds), where_clauses: chalk_ir::Binders::new(binders, where_clauses), }; + Arc::new(chalk_solve::rust_ir::OpaqueTyDatum { opaque_ty_id, bound: chalk_ir::Binders::empty(&self.interner, value), diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 1e1841a57f818..0602f5ea4dcc6 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -728,6 +728,84 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::FnSig>> for ty::Binder LowerInto<'tcx, Option>>> + for ty::Predicate<'tcx> +{ + fn lower_into( + self, + interner: &RustInterner<'tcx>, + ) -> Option>> { + match &self.kind() { + ty::PredicateKind::Trait(predicate, _) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, predicate); + + Some(chalk_ir::Binders::new( + binders, + chalk_solve::rust_ir::InlineBound::TraitBound( + predicate.trait_ref.lower_into(interner), + ), + )) + } + ty::PredicateKind::Projection(predicate) => { + let (predicate, binders, _named_regions) = + collect_bound_vars(interner, interner.tcx, predicate); + + Some(chalk_ir::Binders::new( + binders, + chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)), + )) + } + ty::PredicateKind::TypeOutlives(_predicate) => None, + ty::PredicateKind::WellFormed(_ty) => None, + + ty::PredicateKind::RegionOutlives(..) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::Subtype(..) + | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", &self), + } + } +} + +impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound>> + for ty::TraitRef<'tcx> +{ + fn lower_into( + self, + interner: &RustInterner<'tcx>, + ) -> chalk_solve::rust_ir::TraitBound> { + chalk_solve::rust_ir::TraitBound { + trait_id: chalk_ir::TraitId(self.def_id), + args_no_self: self.substs[1..].iter().map(|arg| arg.lower_into(interner)).collect(), + } + } +} + +impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound>> + for ty::ProjectionPredicate<'tcx> +{ + fn lower_into( + self, + interner: &RustInterner<'tcx>, + ) -> chalk_solve::rust_ir::AliasEqBound> { + let trait_ref = self.projection_ty.trait_ref(interner.tcx); + chalk_solve::rust_ir::AliasEqBound { + trait_bound: trait_ref.lower_into(interner), + associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id), + parameters: self.projection_ty.substs[trait_ref.substs.len()..] + .iter() + .map(|arg| arg.lower_into(interner)) + .collect(), + value: self.ty.lower_into(interner), + } + } +} + /// To collect bound vars, we have to do two passes. In the first pass, we /// collect all `BoundRegion`s and `ty::Bound`s. In the second pass, we then /// replace `BrNamed` into `BrAnon`. The two separate passes are important, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 0647be2dfde0b..2df9007195fae 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1,4 +1,5 @@ use super::coercion::CoerceMany; +use super::compare_method::check_type_bounds; use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl}; use super::*; @@ -453,8 +454,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( ty: None, }; let prohibit_opaque = tcx - .predicates_of(def_id) - .predicates + .explicit_item_bounds(def_id) .iter() .any(|(predicate, _)| predicate.visit_with(&mut visitor)); debug!( @@ -476,7 +476,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( span, E0760, "`{}` return type cannot contain a projection or `Self` that references lifetimes from \ - a parent scope", + a parent scope", if is_async { "async fn" } else { "impl Trait" }, ); @@ -553,9 +553,25 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { for item in items.iter() { let item = tcx.hir().trait_item(item.id); - if let hir::TraitItemKind::Fn(sig, _) = &item.kind { - let abi = sig.header.abi; - fn_maybe_err(tcx, item.ident.span, abi); + match item.kind { + hir::TraitItemKind::Fn(ref sig, _) => { + let abi = sig.header.abi; + fn_maybe_err(tcx, item.ident.span, abi); + } + hir::TraitItemKind::Type(.., Some(_default)) => { + let item_def_id = tcx.hir().local_def_id(item.hir_id).to_def_id(); + let assoc_item = tcx.associated_item(item_def_id); + let trait_substs = + InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); + let _: Result<_, rustc_errors::ErrorReported> = check_type_bounds( + tcx, + assoc_item, + assoc_item, + item.span, + ty::TraitRef { def_id: def_id.to_def_id(), substs: trait_substs }, + ); + } + _ => {} } } } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 8111a0bad9fbf..3515fb12e4ca7 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -5,6 +5,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; +use rustc_infer::traits::util; use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; @@ -1170,20 +1171,13 @@ fn compare_type_predicate_entailment<'tcx>( /// For default associated types the normalization is not possible (the value /// from the impl could be overridden). We also can't normalize generic /// associated types (yet) because they contain bound parameters. -fn check_type_bounds<'tcx>( +pub fn check_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, trait_ty: &ty::AssocItem, impl_ty: &ty::AssocItem, impl_ty_span: Span, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorReported> { - let have_gats = tcx.features().generic_associated_types; - if impl_ty.defaultness.is_final() && !have_gats { - // For "final", non-generic associate type implementations, we - // don't need this as described above. - return Ok(()); - } - // Given // // impl Foo for (A, B) { @@ -1237,10 +1231,20 @@ fn check_type_bounds<'tcx>( ObligationCauseCode::ItemObligation(trait_ty.def_id), ); - let predicates = tcx.item_bounds(trait_ty.def_id); - debug!("check_type_bounds: item_bounds={:?}", predicates); + let obligations = tcx + .explicit_item_bounds(trait_ty.def_id) + .iter() + .map(|&(bound, span)| { + let concrete_ty_bound = + traits::subst_assoc_item_bound(tcx, bound, impl_ty_value, rebased_substs); + debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); - for predicate in predicates { + traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound) + }) + .collect(); + debug!("check_type_bounds: item_bounds={:?}", obligations); + + for obligation in util::elaborate_obligations(tcx, obligations) { let concrete_ty_predicate = predicate.subst(tcx, rebased_substs); debug!("compare_projection_bounds: concrete predicate = {:?}", concrete_ty_predicate); @@ -1252,12 +1256,7 @@ fn check_type_bounds<'tcx>( ); debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); - inh.register_predicates(obligations); - inh.register_predicate(traits::Obligation::new( - cause.clone(), - param_env, - normalized_predicate, - )); + inh.register_predicate(obligation); } // Check that all obligations are satisfied by the implementation's diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 5203f3fa8f1d5..f31ba886d5262 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -420,6 +420,9 @@ fn check_associated_item( check_method_receiver(fcx, hir_sig, &item, self_ty); } ty::AssocKind::Type => { + if let ty::AssocItemContainer::TraitContainer(_) = item.container { + check_associated_type_bounds(fcx, item, span) + } if item.defaultness.has_value() { let ty = fcx.tcx.type_of(item.def_id); let ty = fcx.normalize_associated_types_in(span, &ty); @@ -571,7 +574,6 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { for_item(tcx, item).with_fcx(|fcx, _| { check_where_clauses(tcx, fcx, item.span, trait_def_id.to_def_id(), None); - check_associated_type_defaults(fcx, trait_def_id.to_def_id()); vec![] }); @@ -581,96 +583,26 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { /// /// Assuming the defaults are used, check that all predicates (bounds on the /// assoc type and where clauses on the trait) hold. -fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) { +fn check_associated_type_bounds(fcx: &FnCtxt<'_, '_>, item: &ty::AssocItem, span: Span) { let tcx = fcx.tcx; - let substs = InternalSubsts::identity_for_item(tcx, trait_def_id); - - // For all assoc. types with defaults, build a map from - // `>::Assoc` to the default type. - let map = tcx - .associated_items(trait_def_id) - .in_definition_order() - .filter_map(|item| { - if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { - // `>::Assoc` - let proj = ty::ProjectionTy { substs, item_def_id: item.def_id }; - let default_ty = tcx.type_of(item.def_id); - debug!("assoc. type default mapping: {} -> {}", proj, default_ty); - Some((proj, default_ty)) - } else { - None - } - }) - .collect::>(); - - /// Replaces projections of associated types with their default types. - /// - /// This does a "shallow substitution", meaning that defaults that refer to - /// other defaulted assoc. types will still refer to the projection - /// afterwards, not to the other default. For example: - /// - /// ```compile_fail - /// trait Tr { - /// type A: Clone = Vec; - /// type B = u8; - /// } - /// ``` - /// - /// This will end up replacing the bound `Self::A: Clone` with - /// `Vec: Clone`, not with `Vec: Clone`. If we did a deep - /// substitution and ended up with the latter, the trait would be accepted. - /// If an `impl` then replaced `B` with something that isn't `Clone`, - /// suddenly the default for `A` is no longer valid. The shallow - /// substitution forces the trait to add a `B: Clone` bound to be accepted, - /// which means that an `impl` can replace any default without breaking - /// others. - /// - /// Note that this isn't needed for soundness: The defaults would still be - /// checked in any impl that doesn't override them. - struct DefaultNormalizer<'tcx> { - tcx: TyCtxt<'tcx>, - map: FxHashMap, Ty<'tcx>>, - } - impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx - } + let bounds = tcx.explicit_item_bounds(item.def_id); - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.kind() { - ty::Projection(proj_ty) => { - if let Some(default) = self.map.get(&proj_ty) { - default - } else { - t.super_fold_with(self) - } - } - _ => t.super_fold_with(self), - } - } - } - - // Now take all predicates defined on the trait, replace any mention of - // the assoc. types with their default, and prove them. - // We only consider predicates that directly mention the assoc. type. - let mut norm = DefaultNormalizer { tcx, map }; - let predicates = fcx.tcx.predicates_of(trait_def_id); - for &(orig_pred, span) in predicates.predicates.iter() { - let pred = orig_pred.fold_with(&mut norm); - if pred != orig_pred { - // Mentions one of the defaulted assoc. types - debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred); - let pred = fcx.normalize_associated_types_in(span, &pred); - let cause = traits::ObligationCause::new( - span, - fcx.body_id, - traits::ItemObligation(trait_def_id), - ); - let obligation = traits::Obligation::new(cause, fcx.param_env, pred); + debug!("check_associated_type_bounds: bounds={:?}", bounds); + let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { + let normalized_bound = fcx.normalize_associated_types_in(span, &bound); + traits::wf::predicate_obligations( + fcx, + fcx.param_env, + fcx.body_id, + normalized_bound, + bound_span, + ) + }); - fcx.register_predicate(obligation); - } + for obligation in wf_obligations { + debug!("next obligation cause: {:?}", obligation.cause); + fcx.register_predicate(obligation); } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 4df5135cca579..737bc3a753d75 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -711,8 +711,10 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) { tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); tcx.ensure().predicates_of(def_id); - if let hir::ItemKind::Fn(..) = it.kind { - tcx.ensure().fn_sig(def_id); + match it.kind { + hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id), + hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id), + _ => (), } } } @@ -733,15 +735,25 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { tcx.ensure().type_of(def_id); } - hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(_, Some(_)) => { + hir::TraitItemKind::Const(..) => { tcx.ensure().type_of(def_id); - // Account for `const C: _;` and `type T = _;`. + // Account for `const C: _;`. + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_trait_item(trait_item); + placeholder_type_error(tcx, None, &[], visitor.0, false); + } + + hir::TraitItemKind::Type(_, Some(_)) => { + tcx.ensure().item_bounds(def_id); + tcx.ensure().type_of(def_id); + // Account for `type T = _;`. let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_trait_item(trait_item); placeholder_type_error(tcx, None, &[], visitor.0, false); } hir::TraitItemKind::Type(_, None) => { + tcx.ensure().item_bounds(def_id); // #74612: Visit and try to find bad placeholders // even if there is no concrete type. let mut visitor = PlaceholderHirTyCollector::default(); diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs index 556d8900d1a2e..4c78f17a6a33d 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs @@ -23,19 +23,17 @@ trait Case1 { Debug > > + Sync>; + //~^^^^^^ ERROR `<::C as std::iter::Iterator>::Item` is not an iterator + //~^^^^^^ ERROR `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely + //~^^^ ERROR `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely } pub struct S1; impl Case1 for S1 { -//~^ ERROR `>::App` doesn't implement `Debug` [E0277] type C = Once>; } fn assume_case1() { -//~^ ERROR `<_ as Lam<&'a u8>>::App` doesn't implement `Debug` [E0277] -//~| ERROR `<::C as Iterator>::Item` is not an iterator [E0277] -//~| ERROR `<::C as Iterator>::Item` cannot be sent between threads safely [E0277] -//~| ERROR `<::C as Iterator>::Item` cannot be shared between threads safely [E0277] fn assert_a<_0, A>() where A: Iterator, _0: Debug {} assert_a::<_, T::A>(); diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index 49b5e7fbb89a9..20a087a85a6e8 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -1,79 +1,54 @@ -error[E0277]: `>::App` doesn't implement `Debug` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:29:6 - | -LL | trait Case1 { - | ----- required by a bound in this -... -LL | Debug - | ----- required by this bound in `Case1` -... -LL | impl Case1 for S1 { - | ^^^^^ `>::App` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = help: the trait `for<'a> Debug` is not implemented for `>::App` - -error[E0277]: `<::C as Iterator>::Item` is not an iterator - --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20 - | -LL | fn assume_case1() { - | ^^^^^ `<::C as Iterator>::Item` is not an iterator - | - = help: the trait `Iterator` is not implemented for `<::C as Iterator>::Item` +error[E0277]: `<::C as std::iter::Iterator>::Item` is not an iterator + --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:5 + | +LL | / type C: Clone + Iterator Lam<&'a u8, App: +LL | | Debug +LL | | > +LL | | > + Sync>; + | |__________________^ `<::C as std::iter::Iterator>::Item` is not an iterator + | + = help: the trait `std::iter::Iterator` is not implemented for `<::C as std::iter::Iterator>::Item` help: consider further restricting the associated type | -LL | fn assume_case1() where <::C as Iterator>::Item: Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Case1 where <::C as std::iter::Iterator>::Item: std::iter::Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: `<::C as Iterator>::Item` cannot be sent between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20 +error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely + --> $DIR/bad-bounds-on-assoc-in-trait.rs:23:9 | -LL | trait Case1 { - | ----- required by a bound in this -LL | type C: Clone + Iterator() { - | ^^^^^ `<::C as Iterator>::Item` cannot be sent between threads safely + | ^^^^ `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `<::C as Iterator>::Item` + ::: $SRC_DIR/libcore/marker.rs:LL:COL + | +LL | pub unsafe auto trait Send { + | -------------------------- required by this bound in `std::marker::Send` + | + = help: the trait `std::marker::Send` is not implemented for `<::C as std::iter::Iterator>::Item` help: consider further restricting the associated type | -LL | fn assume_case1() where <::C as Iterator>::Item: Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Case1 where <::C as std::iter::Iterator>::Item: std::marker::Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: `<::C as Iterator>::Item` cannot be shared between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20 +error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely + --> $DIR/bad-bounds-on-assoc-in-trait.rs:27:13 | -LL | trait Case1 { - | ----- required by a bound in this -... LL | > + Sync>; - | ---- required by this bound in `Case1` -... -LL | fn assume_case1() { - | ^^^^^ `<::C as Iterator>::Item` cannot be shared between threads safely + | ^^^^ `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `<::C as Iterator>::Item` -help: consider further restricting the associated type + ::: $SRC_DIR/libcore/marker.rs:LL:COL | -LL | fn assume_case1() where <::C as Iterator>::Item: Sync { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `Debug` - --> $DIR/bad-bounds-on-assoc-in-trait.rs:34:20 +LL | pub unsafe auto trait Sync { + | -------------------------- required by this bound in `std::marker::Sync` | -LL | trait Case1 { - | ----- required by a bound in this -... -LL | Debug - | ----- required by this bound in `Case1` -... -LL | fn assume_case1() { - | ^^^^^ `<_ as Lam<&'a u8>>::App` cannot be formatted using `{:?}` because it doesn't implement `Debug` + = help: the trait `std::marker::Sync` is not implemented for `<::C as std::iter::Iterator>::Item` +help: consider further restricting the associated type | - = help: the trait `for<'a> Debug` is not implemented for `<_ as Lam<&'a u8>>::App` +LL | trait Case1 where <::C as std::iter::Iterator>::Item: std::marker::Sync { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs index ceca54b7cd75f..4025e0fc5e1a6 100644 --- a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs +++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs @@ -1,4 +1,4 @@ -// check-pass +// ignore-tidy-linelength #![feature(associated_type_bounds)] @@ -18,6 +18,7 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; } trait Case1 { type A: Iterator; + //~^ ERROR `<::A as std::iter::Iterator>::Item` doesn't implement `std::fmt::Debug` type B: Iterator; } @@ -30,7 +31,11 @@ impl Case1 for S1 { // Ensure we don't have opaque `impl Trait` desugaring: +// What is this supposed to mean? Rustc currently lowers `: Default` in the +// bounds of `Out`, but trait selection can't find the bound since it applies +// to a type other than `Self::Out`. pub trait Foo { type Out: Baz; } +//~^ ERROR trait bound `<::Out as Baz>::Assoc: std::default::Default` is not satisfied pub trait Baz { type Assoc; } #[derive(Default)] diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr new file mode 100644 index 0000000000000..2be37285e2991 --- /dev/null +++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr @@ -0,0 +1,36 @@ +error[E0277]: `<::A as std::iter::Iterator>::Item` doesn't implement `std::fmt::Debug` + --> $DIR/bounds-on-assoc-in-trait.rs:20:28 + | +LL | type A: Iterator; + | ^^^^^ `<::A as std::iter::Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` + | + ::: $SRC_DIR/libcore/fmt/mod.rs:LL:COL + | +LL | pub trait Debug { + | --------------- required by this bound in `std::fmt::Debug` + | + = help: the trait `std::fmt::Debug` is not implemented for `<::A as std::iter::Iterator>::Item` +help: consider further restricting the associated type + | +LL | trait Case1 where <::A as std::iter::Iterator>::Item: std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `<::Out as Baz>::Assoc: std::default::Default` is not satisfied + --> $DIR/bounds-on-assoc-in-trait.rs:37:38 + | +LL | pub trait Foo { type Out: Baz; } + | ^^^^^^^ the trait `std::default::Default` is not implemented for `<::Out as Baz>::Assoc` + | + ::: $SRC_DIR/libcore/default.rs:LL:COL + | +LL | pub trait Default: Sized { + | ------------------------ required by this bound in `std::default::Default` + | +help: consider further restricting the associated type + | +LL | pub trait Foo where <::Out as Baz>::Assoc: std::default::Default { type Out: Baz; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr index 77cd88e524f5f..b5941fb80c7e7 100644 --- a/src/test/ui/associated-type-bounds/duplicate.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.stderr @@ -512,31 +512,7 @@ LL | trait TRSW3 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:145:43 - | -LL | trait TRA1 { type A: Iterator; } - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:147:43 - | -LL | trait TRA2 { type A: Iterator; } - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:149:46 - | -LL | trait TRA3 { type A: Iterator; } - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:152:40 + --> $DIR/duplicate.rs:167:40 | LL | type TADyn1 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index 2914a7f868b2b..9d084203e3a86 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -1,11 +1,14 @@ -error[E0284]: type annotations needed +error[E0283]: type annotations needed --> $DIR/associated-types-unconstrained.rs:14:20 | +LL | fn bar() -> isize; + | ------------------ required by `Foo::bar` +... LL | let x: isize = Foo::bar(); | ^^^^^^^^ cannot infer type | - = note: cannot satisfy `<_ as Foo>::A == _` + = note: cannot satisfy `_: Foo` error: aborting due to previous error -For more information about this error, try `rustc --explain E0284`. +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs index fa75f6bc15228..afb2b3df716eb 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs @@ -6,11 +6,8 @@ trait Tr { type B = Self::A; } -// ...but is an error in any impl that doesn't override at least one of the defaults impl Tr for () {} -//~^ ERROR overflow evaluating the requirement -// As soon as at least one is redefined, it works: impl Tr for u8 { type A = u8; } @@ -24,16 +21,14 @@ impl Tr for u32 { type B = u8; } -// ...but only if this actually breaks the cycle +// ...but not in an impl that redefines one of the types. impl Tr for bool { - //~^ ERROR type mismatch resolving `::B == _` type A = Box; //~^ ERROR type mismatch resolving `::B == _` } // (the error is shown twice for some reason) impl Tr for usize { - //~^ ERROR type mismatch resolving `::B == _` type B = &'static Self::A; //~^ ERROR type mismatch resolving `::A == _` } diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr index 0aea30b11126b..28decb0934ca7 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -1,34 +1,16 @@ -error[E0275]: overflow evaluating the requirement `<() as Tr>::B == _` - --> $DIR/defaults-cyclic-fail-1.rs:10:6 - | -LL | impl Tr for () {} - | ^^ - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-1.rs:28:6 - | -LL | impl Tr for bool { - | ^^ cyclic type of infinite size - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-1.rs:35:6 - | -LL | impl Tr for usize { - | ^^ cyclic type of infinite size - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-1.rs:30:5 +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-1.rs:26:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error[E0271]: type mismatch resolving `::A == _` - --> $DIR/defaults-cyclic-fail-1.rs:37:5 +error[E0275]: overflow evaluating the requirement `::A` + --> $DIR/defaults-cyclic-fail-1.rs:32:5 | LL | type B = &'static Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0271, E0275. For more information about an error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs index edcd310908aa4..ba4bb0d5a296b 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs @@ -8,11 +8,8 @@ trait Tr { type B = Box; } -// ...but is an error in any impl that doesn't override at least one of the defaults impl Tr for () {} -//~^ ERROR type mismatch resolving `<() as Tr>::B == _` -// As soon as at least one is redefined, it works: impl Tr for u8 { type A = u8; } @@ -26,16 +23,13 @@ impl Tr for u32 { type B = u8; } -// ...but only if this actually breaks the cycle impl Tr for bool { - //~^ ERROR type mismatch resolving `::B == _` type A = Box; //~^ ERROR type mismatch resolving `::B == _` } // (the error is shown twice for some reason) impl Tr for usize { - //~^ ERROR type mismatch resolving `::B == _` type B = &'static Self::A; //~^ ERROR type mismatch resolving `::A == _` } diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr index f39021c30edc1..6b6d5348c153b 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -1,33 +1,15 @@ -error[E0271]: type mismatch resolving `<() as Tr>::B == _` - --> $DIR/defaults-cyclic-fail-2.rs:12:6 - | -LL | impl Tr for () {} - | ^^ cyclic type of infinite size - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-2.rs:30:6 - | -LL | impl Tr for bool { - | ^^ cyclic type of infinite size - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-2.rs:37:6 - | -LL | impl Tr for usize { - | ^^ cyclic type of infinite size - -error[E0271]: type mismatch resolving `::B == _` - --> $DIR/defaults-cyclic-fail-2.rs:32:5 +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-2.rs:27:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error[E0271]: type mismatch resolving `::A == _` - --> $DIR/defaults-cyclic-fail-2.rs:39:5 +error[E0275]: overflow evaluating the requirement `::A` + --> $DIR/defaults-cyclic-fail-2.rs:33:5 | LL | type B = &'static Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs index 30c2555df8bb9..69be300b16f37 100644 --- a/src/test/ui/associated-types/defaults-suitability.rs +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -1,10 +1,8 @@ //! Checks that associated type defaults are properly validated. //! //! This means: -//! * Default types are wfchecked //! * Default types are checked against where clauses on the assoc. type -//! (eg. `type Assoc: Clone = NotClone`), and also against where clauses on -//! the trait itself when possible +//! (eg. `type Assoc: Clone = NotClone`) #![feature(associated_type_defaults)] @@ -17,15 +15,12 @@ trait Tr { } // Where-clauses defined on the trait must also be considered -trait Tr2 where Self::Ty: Clone { - //~^ ERROR the trait bound `NotClone: Clone` is not satisfied +trait Tr2 +where + Self::Ty: Clone, +{ type Ty = NotClone; -} - -// Independent of where-clauses (there are none here), default types must always be wf -trait Tr3 { - type Ty = Vec<[u8]>; - //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied } // Involved type parameters must fulfill all bounds required by defaults that mention them @@ -43,25 +38,24 @@ trait Bar: Sized { trait IsU8 {} impl IsU8 for T {} -// Test that mentioning the assoc. type inside where clauses works +// Test that mentioning the assoc. type inside where clauses is not allowed trait C where Vec: Clone, Self::Assoc: IsU8, bool: IsU8, { type Assoc = u8; + //~^ ERROR the trait bound `u8: IsU8<::Assoc>` is not satisfied } // Test that we get all expected errors if that default is unsuitable trait D where Vec: Clone, - //~^ ERROR the trait bound `NotClone: Clone` is not satisfied Self::Assoc: IsU8, - //~^ ERROR the trait bound `NotClone: IsU8` is not satisfied bool: IsU8, - //~^ ERROR the trait bound `bool: IsU8` is not satisfied { type Assoc = NotClone; + //~^ ERROR the trait bound `NotClone: IsU8<::Assoc>` is not satisfied } // Test behavior of the check when defaults refer to other defaults: @@ -85,18 +79,20 @@ trait Foo25 { // Adding the `Baz: Clone` bound isn't enough since the default is type // parameter `T`, which also might not be `Clone`. -trait Foo3 where +trait Foo3 +where Self::Bar: Clone, Self::Baz: Clone, - //~^ ERROR the trait bound `T: Clone` is not satisfied { type Bar = Vec; type Baz = T; + //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied } // This one finally works, with `Clone` bounds on all assoc. types and the type // parameter. -trait Foo4 where +trait Foo4 +where T: Clone, { type Bar: Clone = Vec; diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index c2ad4c5824ea9..4d8e6f1584d1d 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -1,27 +1,31 @@ -error[E0277]: the trait bound `NotClone: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:15:14 +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:13:5 | -LL | trait Tr { - | -------- required by `Tr` LL | type Ty: Clone = NotClone; - | ^^^^^ the trait `Clone` is not implemented for `NotClone` + | ^^^^^^^^^-----^^^^^^^^^^^^ + | | | + | | required by this bound in `Tr::Ty` + | the trait `std::clone::Clone` is not implemented for `NotClone` -error[E0277]: the trait bound `NotClone: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:20:27 +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:19:5 | LL | trait Tr2 where Self::Ty: Clone { - | --------------------------^^^^^ - | | | - | | the trait `Clone` is not implemented for `NotClone` - | required by `Tr2` + | ----- required by this bound in `Tr2::Ty` +LL | type Ty = NotClone; + | ^^^^^--^^^^^^^^^^^^ + | | | + | | required by a bound in this + | the trait `std::clone::Clone` is not implemented for `NotClone` -error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:33:15 +error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:25:5 | -LL | trait Foo { - | ------------ required by `Foo` LL | type Bar: Clone = Vec; - | ^^^^^ the trait `Clone` is not implemented for `T` + | ^^^^^^^^^^-----^^^^^^^^^^ + | | | + | | required by this bound in `Foo::Bar` + | the trait `std::clone::Clone` is not implemented for `T` | = note: required because of the requirements on the impl of `Clone` for `Vec` help: consider restricting type parameter `T` @@ -30,64 +34,46 @@ LL | trait Foo { | ^^^^^^^ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/defaults-suitability.rs:39:17 + --> $DIR/defaults-suitability.rs:31:5 | -LL | trait Bar: Sized { - | ---------------- required by `Bar` -LL | // `(): Foo` might hold for some possible impls but not all. LL | type Assoc: Foo = (); - | ^^^^^^^^^ the trait `Foo` is not implemented for `()` + | ^^^^^^^^^^^^---------^^^^^^ + | | | + | | required by this bound in `Bar::Assoc` + | the trait `Foo` is not implemented for `()` -error[E0277]: the trait bound `NotClone: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:59:18 - | -LL | / trait D where -LL | | Vec: Clone, -LL | | -LL | | Self::Assoc: IsU8, - | | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` -... | -LL | | type Assoc = NotClone; -LL | | } - | |_- required by `D` +error[E0277]: the trait bound `u8: IsU8<::Assoc>` is not satisfied + --> $DIR/defaults-suitability.rs:44:5 + | +LL | Self::Assoc: IsU8, + | ----------------- required by this bound in `C::Assoc` +... +LL | type Assoc = u8; + | ^^^^^-----^^^^^^ + | | | + | | required by a bound in this + | the trait `IsU8<::Assoc>` is not implemented for `u8` -error[E0277]: the trait bound `bool: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:61:11 - | -LL | / trait D where -LL | | Vec: Clone, -LL | | -LL | | Self::Assoc: IsU8, -LL | | -LL | | bool: IsU8, - | | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `bool` -... | -LL | | type Assoc = NotClone; -LL | | } - | |_- required by `D` +error[E0277]: the trait bound `NotClone: IsU8<::Assoc>` is not satisfied + --> $DIR/defaults-suitability.rs:54:5 + | +LL | Self::Assoc: IsU8, + | ----------------- required by this bound in `D::Assoc` +... +LL | type Assoc = NotClone; + | ^^^^^-----^^^^^^^^^^^^ + | | | + | | required by a bound in this + | the trait `IsU8<::Assoc>` is not implemented for `NotClone` -error[E0277]: the trait bound `NotClone: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:57:23 - | -LL | / trait D where -LL | | Vec: Clone, - | | ^^^^^ the trait `Clone` is not implemented for `NotClone` -LL | | -LL | | Self::Assoc: IsU8, -... | -LL | | type Assoc = NotClone; -LL | | } - | |_- required by `D` - | - = note: required because of the requirements on the impl of `Clone` for `Vec` - -error[E0277]: the trait bound `>::Baz: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:72:15 +error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:63:5 | -LL | trait Foo2 { - | ------------- required by `Foo2` LL | type Bar: Clone = Vec; - | ^^^^^ the trait `Clone` is not implemented for `>::Baz` + | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `Foo2::Bar` + | the trait `std::clone::Clone` is not implemented for `>::Baz` | = note: required because of the requirements on the impl of `Clone` for `Vec<>::Baz>` help: consider further restricting the associated type @@ -95,13 +81,14 @@ help: consider further restricting the associated type LL | trait Foo2 where >::Baz: Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `>::Baz: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:81:15 +error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:72:5 | -LL | trait Foo25 { - | --------------------- required by `Foo25` LL | type Bar: Clone = Vec; - | ^^^^^ the trait `Clone` is not implemented for `>::Baz` + | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `Foo25::Bar` + | the trait `std::clone::Clone` is not implemented for `>::Baz` | = note: required because of the requirements on the impl of `Clone` for `Vec<>::Baz>` help: consider further restricting the associated type @@ -109,37 +96,23 @@ help: consider further restricting the associated type LL | trait Foo25 where >::Baz: Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:90:16 - | -LL | / trait Foo3 where -LL | | Self::Bar: Clone, -LL | | Self::Baz: Clone, - | | ^^^^^ the trait `Clone` is not implemented for `T` -LL | | -... | -LL | | type Baz = T; -LL | | } - | |_- required by `Foo3` +error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:84:5 + | +LL | Self::Baz: Clone, + | ----- required by this bound in `Foo3::Baz` +... +LL | type Baz = T; + | ^^^^^---^^^^^ + | | | + | | required by a bound in this + | the trait `std::clone::Clone` is not implemented for `T` | help: consider further restricting type parameter `T` | LL | Self::Baz: Clone, T: Clone | ^^^^^^^^^^ -error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/defaults-suitability.rs:27:5 - | -LL | type Ty = Vec<[u8]>; - | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - ::: $SRC_DIR/alloc/src/vec.rs:LL:COL - | -LL | pub struct Vec { - | - required by this bound in `Vec` - | - = help: the trait `Sized` is not implemented for `[u8]` - -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs index f283d22b3c7eb..093e32f66be0e 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -11,22 +11,13 @@ use std::{ fmt::Display, - ops::{AddAssign, Deref} + ops::{AddAssign, Deref}, }; - trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self // and it's accepted, not knowing if Self ineed is Copy - type Output: Copy - //~^ ERROR the trait bound `Self: Copy` is not satisfied - + Deref - //~^ ERROR the trait bound `Self: Deref` is not satisfied - + AddAssign<&'static str> - //~^ ERROR cannot add-assign `&'static str` to `Self` - + From - + Display = Self; - //~^ ERROR `Self` doesn't implement `std::fmt::Display` + type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { @@ -39,10 +30,6 @@ trait UncheckedCopy: Sized { } impl UncheckedCopy for T {} -//~^ ERROR `T` doesn't implement `std::fmt::Display` -//~| ERROR the trait bound `T: Deref` is not satisfied -//~| ERROR cannot add-assign `&'static str` to `T` -//~| ERROR the trait bound `T: Copy` is not satisfied fn bug(origin: T) { let origin = T::make_origin(origin); diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index 29a7c2eab41d5..a8584d6dc5c1b 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -1,53 +1,19 @@ -error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:21:18 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | type Output: Copy - | ^^^^ the trait `Copy` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Copy { - | ^^^^^^ - -error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-1.rs:25:7 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + AddAssign<&'static str> - | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` - | -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:23:7 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + Deref - | ^^^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Deref { - | ^^^^^^^ - error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:28:7 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + Display = Self; - | ^^^^^^^ `Self` cannot be formatted with the default formatter + --> $DIR/defaults-unsound-62211-1.rs:21:5 + | +LL | type Output: Copy + | ^ ------ required by a bound in this + | _____| + | | +LL | | +LL | | +LL | | +... | +LL | | + From +LL | | + Display = Self; + | |___________-------_______^ `Self` cannot be formatted with the default formatter + | | + | required by this bound in `UncheckedCopy::Output` | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead help: consider further restricting `Self` @@ -55,75 +21,71 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + std::fmt::Display { | ^^^^^^^^^^^^^^^^^^^ -error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + Display = Self; - | ------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter - | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -help: consider restricting type parameter `T` +error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:21:5 + | +LL | type Output: Copy + | ^ ------ required by a bound in this + | _____| + | | +LL | | +LL | | +LL | | +LL | | +LL | | + Deref + | | ------------------- required by this bound in `UncheckedCopy::Output` +LL | | + AddAssign<&'static str> +LL | | + From +LL | | + Display = Self; + | |_________________________^ the trait `std::ops::Deref` is not implemented for `Self` | -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `T: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + Deref - | ------------------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `Deref` is not implemented for `T` - | -help: consider restricting type parameter `T` +help: consider further restricting `Self` | -LL | impl UncheckedCopy for T {} - | ^^^^^^^ +LL | trait UncheckedCopy: Sized + Deref { + | ^^^^^^^ -error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-1.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + AddAssign<&'static str> - | ----------------------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ no implementation for `T += &'static str` +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-1.rs:21:5 + | +LL | type Output: Copy + | ^ ------ required by a bound in this + | _____| + | | +LL | | +LL | | +LL | | +... | +LL | | + AddAssign<&'static str> + | | ----------------------- required by this bound in `UncheckedCopy::Output` +LL | | + From +LL | | + Display = Self; + | |_________________________^ no implementation for `Self += &'static str` | -help: consider restricting type parameter `T` +help: consider further restricting `Self` | -LL | impl> UncheckedCopy for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + std::ops::AddAssign<&'static str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | type Output: Copy - | ---- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` +error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:21:5 + | +LL | type Output: Copy + | ^ ---- required by this bound in `UncheckedCopy::Output` + | _____| + | | +LL | | +LL | | +LL | | +... | +LL | | + From +LL | | + Display = Self; + | |_________________________^ the trait `std::marker::Copy` is not implemented for `Self` | -help: consider restricting type parameter `T` +help: consider further restricting `Self` | -LL | impl UncheckedCopy for T {} - | ^^^^^^ +LL | trait UncheckedCopy: Sized + std::marker::Copy { + | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs index 5518cda37087c..44bbdc9f52b84 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -11,22 +11,13 @@ use std::{ fmt::Display, - ops::{AddAssign, Deref} + ops::{AddAssign, Deref}, }; - trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self // and it's accepted, not knowing if Self ineed is Copy - type Output: Copy - //~^ ERROR the trait bound `Self: Copy` is not satisfied - + Deref - //~^ ERROR the trait bound `Self: Deref` is not satisfied - + AddAssign<&'static str> - //~^ ERROR cannot add-assign `&'static str` to `Self` - + From - + Display = Self; - //~^ ERROR `Self` doesn't implement `std::fmt::Display` + type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { @@ -39,10 +30,6 @@ trait UncheckedCopy: Sized { } impl UncheckedCopy for T {} -//~^ ERROR `T` doesn't implement `std::fmt::Display` -//~| ERROR the trait bound `T: Deref` is not satisfied -//~| ERROR cannot add-assign `&'static str` to `T` -//~| ERROR the trait bound `T: Copy` is not satisfied fn bug(origin: T) { let origin = T::make_origin(origin); diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index 49c66093bf039..6a8e3ff7b626d 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -1,53 +1,19 @@ -error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:21:18 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | type Output: Copy - | ^^^^ the trait `Copy` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Copy { - | ^^^^^^ - -error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-2.rs:25:7 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + AddAssign<&'static str> - | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` - | -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:23:7 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + Deref - | ^^^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `Self` - | -help: consider further restricting `Self` - | -LL | trait UncheckedCopy: Sized + Deref { - | ^^^^^^^ - error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:28:7 - | -LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` -... -LL | + Display = Self; - | ^^^^^^^ `Self` cannot be formatted with the default formatter + --> $DIR/defaults-unsound-62211-2.rs:21:5 + | +LL | type Output: Copy + | ^ ------ required by a bound in this + | _____| + | | +LL | | +LL | | +LL | | +... | +LL | | + From +LL | | + Display = Self; + | |___________-------_______^ `Self` cannot be formatted with the default formatter + | | + | required by this bound in `UncheckedCopy::Output` | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead help: consider further restricting `Self` @@ -55,75 +21,71 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + std::fmt::Display { | ^^^^^^^^^^^^^^^^^^^ -error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + Display = Self; - | ------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter - | - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -help: consider restricting type parameter `T` +error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:21:5 + | +LL | type Output: Copy + | ^ ------ required by a bound in this + | _____| + | | +LL | | +LL | | +LL | | +LL | | +LL | | + Deref + | | ------------------- required by this bound in `UncheckedCopy::Output` +LL | | + AddAssign<&'static str> +LL | | + From +LL | | + Display = Self; + | |_________________________^ the trait `std::ops::Deref` is not implemented for `Self` | -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `T: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + Deref - | ------------------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `Deref` is not implemented for `T` - | -help: consider restricting type parameter `T` +help: consider further restricting `Self` | -LL | impl UncheckedCopy for T {} - | ^^^^^^^ +LL | trait UncheckedCopy: Sized + Deref { + | ^^^^^^^ -error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-2.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | + AddAssign<&'static str> - | ----------------------- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ no implementation for `T += &'static str` +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-2.rs:21:5 + | +LL | type Output: Copy + | ^ ------ required by a bound in this + | _____| + | | +LL | | +LL | | +LL | | +... | +LL | | + AddAssign<&'static str> + | | ----------------------- required by this bound in `UncheckedCopy::Output` +LL | | + From +LL | | + Display = Self; + | |_________________________^ no implementation for `Self += &'static str` | -help: consider restricting type parameter `T` +help: consider further restricting `Self` | -LL | impl> UncheckedCopy for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + std::ops::AddAssign<&'static str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:41:9 - | -LL | trait UncheckedCopy: Sized { - | ------------- required by a bound in this -... -LL | type Output: Copy - | ---- required by this bound in `UncheckedCopy` -... -LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` +error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:21:5 + | +LL | type Output: Copy + | ^ ---- required by this bound in `UncheckedCopy::Output` + | _____| + | | +LL | | +LL | | +LL | | +... | +LL | | + From +LL | | + Display = Self; + | |_________________________^ the trait `std::marker::Copy` is not implemented for `Self` | -help: consider restricting type parameter `T` +help: consider further restricting `Self` | -LL | impl UncheckedCopy for T {} - | ^^^^^^ +LL | trait UncheckedCopy: Sized + std::marker::Copy { + | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-wf.rs b/src/test/ui/associated-types/defaults-wf.rs new file mode 100644 index 0000000000000..99b5125033465 --- /dev/null +++ b/src/test/ui/associated-types/defaults-wf.rs @@ -0,0 +1,11 @@ +// Check that associated type defaults are wf checked. + +#![feature(associated_type_defaults)] + +// Default types must always be wf +trait Tr3 { + type Ty = Vec<[u8]>; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} + +fn main() {} diff --git a/src/test/ui/associated-types/defaults-wf.stderr b/src/test/ui/associated-types/defaults-wf.stderr new file mode 100644 index 0000000000000..aeb7b6cae1906 --- /dev/null +++ b/src/test/ui/associated-types/defaults-wf.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/defaults-wf.rs:7:5 + | +LL | type Ty = Vec<[u8]>; + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/liballoc/vec.rs:LL:COL + | +LL | pub struct Vec { + | - required by this bound in `std::vec::Vec` + | + = help: the trait `std::marker::Sized` is not implemented for `[u8]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/issue-43924.rs b/src/test/ui/associated-types/issue-43924.rs index 26f1183c6bd76..6a63b3e093674 100644 --- a/src/test/ui/associated-types/issue-43924.rs +++ b/src/test/ui/associated-types/issue-43924.rs @@ -4,12 +4,13 @@ // type-checked. trait Foo { - type Out: Default + ToString + ?Sized = dyn ToString; //~ error: not satisfied + type Out: Default + ToString + ?Sized = dyn ToString; //~ ERROR not satisfied } -impl Foo for () {} //~ error: not satisfied -impl Foo for () {} //~ error: not satisfied +impl Foo for () {} +impl Foo for () {} fn main() { assert_eq!(<() as Foo>::Out::default().to_string(), "false"); + //~^ ERROR no function or associated item named `default` found for trait object } diff --git a/src/test/ui/associated-types/issue-43924.stderr b/src/test/ui/associated-types/issue-43924.stderr index 661730bcd757a..9bcedb05ed4d0 100644 --- a/src/test/ui/associated-types/issue-43924.stderr +++ b/src/test/ui/associated-types/issue-43924.stderr @@ -1,33 +1,19 @@ -error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied - --> $DIR/issue-43924.rs:7:15 +error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied + --> $DIR/issue-43924.rs:7:5 | -LL | trait Foo { - | -------------------------------- required by `Foo` LL | type Out: Default + ToString + ?Sized = dyn ToString; - | ^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)` + | ^^^^^^^^^^-------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `Foo::Out` + | the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)` -error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied - --> $DIR/issue-43924.rs:10:6 +error[E0599]: no function or associated item named `default` found for trait object `(dyn std::string::ToString + 'static)` in the current scope + --> $DIR/issue-43924.rs:14:39 | -LL | trait Foo { - | --- required by a bound in this -LL | type Out: Default + ToString + ?Sized = dyn ToString; - | ------- required by this bound in `Foo` -... -LL | impl Foo for () {} - | ^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)` - -error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied - --> $DIR/issue-43924.rs:11:6 - | -LL | trait Foo { - | --- required by a bound in this -LL | type Out: Default + ToString + ?Sized = dyn ToString; - | ------- required by this bound in `Foo` -... -LL | impl Foo for () {} - | ^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)` +LL | assert_eq!(<() as Foo>::Out::default().to_string(), "false"); + | ^^^^^^^ function or associated item not found in `(dyn std::string::ToString + 'static)` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr index ddc0bf436f6d5..16ae07687e2c7 100644 --- a/src/test/ui/associated-types/issue-63593.stderr +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -1,10 +1,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/issue-63593.rs:9:5 | -LL | trait MyTrait { - | ------------- required by `MyTrait` LL | type This = Self; - | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by this bound in `MyTrait::This` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/issue-65774-1.rs b/src/test/ui/associated-types/issue-65774-1.rs index 0ffd6cc2cf230..9345140558b07 100644 --- a/src/test/ui/associated-types/issue-65774-1.rs +++ b/src/test/ui/associated-types/issue-65774-1.rs @@ -14,7 +14,6 @@ trait MPU { struct S; impl MPU for S { } -//~^ ERROR the trait bound `T: MyDisplay` is not satisfied trait MyWrite { fn my_write(&self, _: &dyn MyDisplay) { } @@ -43,6 +42,7 @@ impl ProcessType for Process { // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), // depth=1),Unimplemented) let closure = |config: &mut ::MpuConfig| writer.my_write(&config); + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied closure(valref); } } diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr index 72f47df5d80e7..f644eb5a1f478 100644 --- a/src/test/ui/associated-types/issue-65774-1.stderr +++ b/src/test/ui/associated-types/issue-65774-1.stderr @@ -1,21 +1,20 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied - --> $DIR/issue-65774-1.rs:10:21 + --> $DIR/issue-65774-1.rs:10:5 | -LL | trait MPU { - | --------- required by `MPU` LL | type MpuConfig: MyDisplay = T; - | ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T` + | ^^^^^^^^^^^^^^^^---------^^^^^ + | | | + | | required by this bound in `MPU::MpuConfig` + | the trait `MyDisplay` is not implemented for `T` error[E0277]: the trait bound `T: MyDisplay` is not satisfied - --> $DIR/issue-65774-1.rs:16:6 + --> $DIR/issue-65774-1.rs:44:76 | -LL | trait MPU { - | --- required by a bound in this -LL | type MpuConfig: MyDisplay = T; - | --------- required by this bound in `MPU` -... -LL | impl MPU for S { } - | ^^^ the trait `MyDisplay` is not implemented for `T` +LL | let closure = |config: &mut ::MpuConfig| writer.my_write(&config); + | ^^^^^^^ the trait `MyDisplay` is not implemented for `T` + | + = note: required because of the requirements on the impl of `MyDisplay` for `&mut T` + = note: required for the cast to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/issue-65774-2.rs b/src/test/ui/associated-types/issue-65774-2.rs index 31e203a81d397..171e0893b4719 100644 --- a/src/test/ui/associated-types/issue-65774-2.rs +++ b/src/test/ui/associated-types/issue-65774-2.rs @@ -14,7 +14,6 @@ trait MPU { struct S; impl MPU for S { } -//~^ ERROR the trait bound `T: MyDisplay` is not satisfied trait MyWrite { fn my_write(&self, _: &dyn MyDisplay) { } @@ -38,6 +37,7 @@ impl ProcessType for Process { // // `Unimplemented` selecting `Binder()` during codegen // writer.my_write(valref) + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied // This one causes the ICE: // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), diff --git a/src/test/ui/associated-types/issue-65774-2.stderr b/src/test/ui/associated-types/issue-65774-2.stderr index aef70885af369..572a9cf190952 100644 --- a/src/test/ui/associated-types/issue-65774-2.stderr +++ b/src/test/ui/associated-types/issue-65774-2.stderr @@ -1,21 +1,19 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied - --> $DIR/issue-65774-2.rs:10:21 + --> $DIR/issue-65774-2.rs:10:5 | -LL | trait MPU { - | --------- required by `MPU` LL | type MpuConfig: MyDisplay = T; - | ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T` + | ^^^^^^^^^^^^^^^^---------^^^^^ + | | | + | | required by this bound in `MPU::MpuConfig` + | the trait `MyDisplay` is not implemented for `T` error[E0277]: the trait bound `T: MyDisplay` is not satisfied - --> $DIR/issue-65774-2.rs:16:6 + --> $DIR/issue-65774-2.rs:39:25 | -LL | trait MPU { - | --- required by a bound in this -LL | type MpuConfig: MyDisplay = T; - | --------- required by this bound in `MPU` -... -LL | impl MPU for S { } - | ^^^ the trait `MyDisplay` is not implemented for `T` +LL | writer.my_write(valref) + | ^^^^^^ the trait `MyDisplay` is not implemented for `T` + | + = note: required for the cast to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/issue-72806.rs b/src/test/ui/associated-types/issue-72806.rs index ae63781d568a1..94758250346d1 100644 --- a/src/test/ui/associated-types/issue-72806.rs +++ b/src/test/ui/associated-types/issue-72806.rs @@ -9,9 +9,10 @@ trait Bar2 { struct Foo; struct Foo2; -impl Bar for Foo { //~ ERROR type mismatch resolving `::Ok == char` +impl Bar for Foo { type Ok = (); type Sibling = Foo2; + //~^ ERROR type mismatch resolving `::Ok == char` } impl Bar2 for Foo2 { type Ok = u32; diff --git a/src/test/ui/associated-types/issue-72806.stderr b/src/test/ui/associated-types/issue-72806.stderr index 03a6565848dc3..23fabbee1c5d4 100644 --- a/src/test/ui/associated-types/issue-72806.stderr +++ b/src/test/ui/associated-types/issue-72806.stderr @@ -1,8 +1,11 @@ error[E0271]: type mismatch resolving `::Ok == char` - --> $DIR/issue-72806.rs:12:6 + --> $DIR/issue-72806.rs:14:5 | -LL | impl Bar for Foo { - | ^^^ expected `u32`, found `char` +LL | type Sibling: Bar2; + | ------- required by this bound in `Bar::Sibling` +... +LL | type Sibling = Foo2; + | ^^^^^^^^^^^^^^^^^^^^ expected `char`, found `u32` error: aborting due to previous error diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs index 67b7c78071c37..4bd3ccab8343a 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs @@ -5,7 +5,9 @@ trait Foo { } impl Foo for () { - type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied + // Doesn't error because we abort compilation after the errors below. + // See point-at-type-on-obligation-failure-3.rs + type Assoc = bool; } trait Baz where Self::Assoc: Bar { diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr index 3118a9c5352c3..f4971105499e3 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr @@ -1,16 +1,5 @@ error[E0277]: the trait bound `bool: Bar` is not satisfied - --> $DIR/point-at-type-on-obligation-failure-2.rs:8:18 - | -LL | trait Foo { - | --- required by a bound in this -LL | type Assoc: Bar; - | --- required by this bound in `Foo` -... -LL | type Assoc = bool; - | ^^^^ the trait `Bar` is not implemented for `bool` - -error[E0277]: the trait bound `bool: Bar` is not satisfied - --> $DIR/point-at-type-on-obligation-failure-2.rs:16:18 + --> $DIR/point-at-type-on-obligation-failure-2.rs:18:18 | LL | trait Baz where Self::Assoc: Bar { | --- required by this bound in `Baz` @@ -19,7 +8,7 @@ LL | type Assoc = bool; | ^^^^ the trait `Bar` is not implemented for `bool` error[E0277]: the trait bound `bool: Bar` is not satisfied - --> $DIR/point-at-type-on-obligation-failure-2.rs:24:18 + --> $DIR/point-at-type-on-obligation-failure-2.rs:26:18 | LL | trait Bat where ::Assoc: Bar { | --- required by this bound in `Bat` @@ -27,6 +16,6 @@ LL | trait Bat where ::Assoc: Bar { LL | type Assoc = bool; | ^^^^ the trait `Bar` is not implemented for `bool` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.rs new file mode 100644 index 0000000000000..9360d96f05e17 --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.rs @@ -0,0 +1,11 @@ +trait Bar {} + +trait Foo { + type Assoc: Bar; +} + +impl Foo for () { + type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.stderr new file mode 100644 index 0000000000000..6ab3d94e10248 --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `bool: Bar` is not satisfied + --> $DIR/point-at-type-on-obligation-failure-3.rs:8:5 + | +LL | type Assoc: Bar; + | --- required by this bound in `Foo::Assoc` +... +LL | type Assoc = bool; + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs index dc43dbaf54b99..66666006887e6 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs @@ -10,8 +10,9 @@ struct Foo; struct Foo2; impl Bar for Foo { - type Ok = (); //~ ERROR type mismatch resolving `::Ok == ()` + type Ok = (); type Sibling = Foo2; + //~^ ERROR type mismatch resolving `::Ok == ()` } impl Bar2 for Foo2 { type Ok = u32; diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr index 818702b7afe2a..7417a5aa3d43a 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr @@ -1,8 +1,11 @@ error[E0271]: type mismatch resolving `::Ok == ()` - --> $DIR/point-at-type-on-obligation-failure.rs:13:15 + --> $DIR/point-at-type-on-obligation-failure.rs:14:5 | -LL | type Ok = (); - | ^^ expected `u32`, found `()` +LL | type Sibling: Bar2; + | ----------- required by this bound in `Bar::Sibling` +... +LL | type Sibling = Foo2; + | ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `u32` error: aborting due to previous error diff --git a/src/test/ui/chalkify/impl_wf.rs b/src/test/ui/chalkify/impl_wf.rs index 465eb10241ea2..66f57c2d11009 100644 --- a/src/test/ui/chalkify/impl_wf.rs +++ b/src/test/ui/chalkify/impl_wf.rs @@ -15,19 +15,6 @@ impl Foo for str { } // Implicit `T: Sized` bound. impl Foo for Option { } -impl Bar for () { - type Item = i32; -} - -impl Bar for Option { - type Item = Option; -} - -impl Bar for f32 { - type Item = f32; - //~^ ERROR the trait bound `f32: Foo` is not satisfied -} - trait Baz where U: Foo { } impl Baz for i32 { } diff --git a/src/test/ui/chalkify/impl_wf.stderr b/src/test/ui/chalkify/impl_wf.stderr index 4ca5ae472f207..24c7f0d82bdc8 100644 --- a/src/test/ui/chalkify/impl_wf.stderr +++ b/src/test/ui/chalkify/impl_wf.stderr @@ -10,18 +10,7 @@ LL | impl Foo for str { } = help: the trait `Sized` is not implemented for `str` error[E0277]: the trait bound `f32: Foo` is not satisfied - --> $DIR/impl_wf.rs:27:17 - | -LL | trait Bar { - | --- required by a bound in this -LL | type Item: Foo; - | --- required by this bound in `Bar` -... -LL | type Item = f32; - | ^^^ the trait `Foo` is not implemented for `f32` - -error[E0277]: the trait bound `f32: Foo` is not satisfied - --> $DIR/impl_wf.rs:35:6 + --> $DIR/impl_wf.rs:22:6 | LL | trait Baz where U: Foo { } | --- required by this bound in `Baz` @@ -29,6 +18,6 @@ LL | trait Baz where U: Foo { } LL | impl Baz for f32 { } | ^^^^^^^^ the trait `Foo` is not implemented for `f32` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/chalkify/impl_wf_2.rs b/src/test/ui/chalkify/impl_wf_2.rs new file mode 100644 index 0000000000000..758a7185e3912 --- /dev/null +++ b/src/test/ui/chalkify/impl_wf_2.rs @@ -0,0 +1,33 @@ +// Split out of impl_wf.rs to work around rust aborting compilation early + +// compile-flags: -Z chalk + +trait Foo: Sized { } + +trait Bar { + type Item: Foo; +} + +impl Foo for i32 { } + +// Implicit `T: Sized` bound. +impl Foo for Option { } + +impl Bar for () { + type Item = i32; +} + +impl Bar for Option { + type Item = Option; +} + +impl Bar for f32 { + type Item = f32; + //~^ ERROR the trait bound `f32: Foo` is not satisfied +} + +trait Baz where U: Foo { } + +impl Baz for i32 { } + +fn main() {} diff --git a/src/test/ui/chalkify/impl_wf_2.stderr b/src/test/ui/chalkify/impl_wf_2.stderr new file mode 100644 index 0000000000000..1da2144c0a5d4 --- /dev/null +++ b/src/test/ui/chalkify/impl_wf_2.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `f32: Foo` is not satisfied + --> $DIR/impl_wf_2.rs:25:5 + | +LL | type Item: Foo; + | --- required by this bound in `Bar::Item` +... +LL | type Item = f32; + | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `f32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs index 9bce274027ee0..c5c8c5c1eca1f 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -14,6 +14,7 @@ impl Tr1 for S1 { type As1 = S2; } trait _Tr3 { type A: Iterator; //~^ ERROR associated type bounds are unstable + //~| ERROR the trait bound `<::A as std::iter::Iterator>::Item: std::marker::Copy` is not satisfied type B: Iterator; //~^ ERROR associated type bounds are unstable diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr index 7f2704e1bc371..db78e287d65e0 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -8,7 +8,7 @@ LL | type A: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:18:22 + --> $DIR/feature-gate-associated_type_bounds.rs:19:22 | LL | type B: Iterator; | ^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | type B: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:22:20 + --> $DIR/feature-gate-associated_type_bounds.rs:23:20 | LL | struct _St1> { | ^^^^^^^^ @@ -26,7 +26,7 @@ LL | struct _St1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:29:18 + --> $DIR/feature-gate-associated_type_bounds.rs:30:18 | LL | enum _En1> { | ^^^^^^^^ @@ -35,7 +35,7 @@ LL | enum _En1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:36:19 + --> $DIR/feature-gate-associated_type_bounds.rs:37:19 | LL | union _Un1> { | ^^^^^^^^ @@ -44,7 +44,7 @@ LL | union _Un1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:43:37 + --> $DIR/feature-gate-associated_type_bounds.rs:44:37 | LL | type _TaWhere1 where T: Iterator = T; | ^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | type _TaWhere1 where T: Iterator = T; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:46:22 + --> $DIR/feature-gate-associated_type_bounds.rs:47:22 | LL | fn _apit(_: impl Tr1) {} | ^^^^^^^^^ @@ -62,7 +62,7 @@ LL | fn _apit(_: impl Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:48:26 + --> $DIR/feature-gate-associated_type_bounds.rs:49:26 | LL | fn _apit_dyn(_: &dyn Tr1) {} | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | fn _apit_dyn(_: &dyn Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:51:24 + --> $DIR/feature-gate-associated_type_bounds.rs:52:24 | LL | fn _rpit() -> impl Tr1 { S1 } | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | fn _rpit() -> impl Tr1 { S1 } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:54:31 + --> $DIR/feature-gate-associated_type_bounds.rs:55:31 | LL | fn _rpit_dyn() -> Box> { Box::new(S1) } | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | fn _rpit_dyn() -> Box> { Box::new(S1) } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:57:23 + --> $DIR/feature-gate-associated_type_bounds.rs:58:23 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -98,7 +98,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:63:24 + --> $DIR/feature-gate-associated_type_bounds.rs:64:24 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -107,7 +107,7 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:70:21 + --> $DIR/feature-gate-associated_type_bounds.rs:71:21 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^ @@ -116,7 +116,7 @@ LL | let _: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:57:14 + --> $DIR/feature-gate-associated_type_bounds.rs:58:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:63:15 + --> $DIR/feature-gate-associated_type_bounds.rs:64:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -132,14 +132,30 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:70:12 + --> $DIR/feature-gate-associated_type_bounds.rs:71:12 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error: aborting due to 16 previous errors +error[E0277]: the trait bound `<::A as std::iter::Iterator>::Item: std::marker::Copy` is not satisfied + --> $DIR/feature-gate-associated_type_bounds.rs:15:28 + | +LL | type A: Iterator; + | ^^^^ the trait `std::marker::Copy` is not implemented for `<::A as std::iter::Iterator>::Item` + | + ::: $SRC_DIR/libcore/marker.rs:LL:COL + | +LL | pub trait Copy: Clone { + | --------------------- required by this bound in `std::marker::Copy` + | +help: consider further restricting the associated type + | +LL | trait _Tr3 where <::A as std::iter::Iterator>::Item: std::marker::Copy { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 17 previous errors -Some errors have detailed explanations: E0562, E0658. -For more information about an error, try `rustc --explain E0562`. +Some errors have detailed explanations: E0277, E0562, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr index 2bcf66dbeae27..e49dc91ec66ae 100644 --- a/src/test/ui/generator/sized-yield.stderr +++ b/src/test/ui/generator/sized-yield.stderr @@ -16,6 +16,11 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t | LL | Pin::new(&mut gen).resume(()); | ^^^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/libcore/ops/generator.rs:LL:COL + | +LL | pub enum GeneratorState { + | - required by this bound in `std::ops::GeneratorState` | = help: the trait `Sized` is not implemented for `str` diff --git a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr index 6ba79dd5437be..b380f0da2ea40 100644 --- a/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr +++ b/src/test/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-68641-check-gat-bounds.rs:15:5 | LL | type Item<'a>: Copy; - | -------------------- required by `UnsafeCopy::Item` + | ---- required by this bound in `UnsafeCopy::Item` ... LL | type Item<'a> = T; | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` diff --git a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr index 15a66e25b191b..61950478c32a8 100644 --- a/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr +++ b/src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T` --> $DIR/issue-68642-broken-llvm-ir.rs:15:5 | LL | type F<'a>: Fn() -> u32; - | ------------------------ required by `Fun::F` + | ----------- required by this bound in `Fun::F` ... LL | type F<'a> = Self; | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` diff --git a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr index 9b2ddb23267ad..13980618987be 100644 --- a/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr +++ b/src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T` --> $DIR/issue-68643-broken-mir.rs:15:5 | LL | type F<'a>: Fn() -> u32; - | ------------------------ required by `Fun::F` + | ----------- required by this bound in `Fun::F` ... LL | type F<'a> = Self; | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` diff --git a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr index f7bfab35052e1..8112425146959 100644 --- a/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr +++ b/src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T` --> $DIR/issue-68644-codegen-selection.rs:15:5 | LL | type F<'a>: Fn() -> u32; - | ------------------------ required by `Fun::F` + | ----------- required by this bound in `Fun::F` ... LL | type F<'a> = Self; | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` diff --git a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr index 6c2d330a19a82..22f50b3949828 100644 --- a/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr +++ b/src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -11,7 +11,7 @@ error[E0277]: expected a `Fn<()>` closure, found `T` --> $DIR/issue-68645-codegen-fulfillment.rs:15:5 | LL | type F<'a>: Fn() -> u32; - | ------------------------ required by `Fun::F` + | ----------- required by this bound in `Fun::F` ... LL | type F<'a> = Self; | ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T` diff --git a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr index a9336151b6afe..c4ee2c4e61872 100644 --- a/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr +++ b/src/test/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -11,7 +11,7 @@ error[E0271]: type mismatch resolving `::Target == T` --> $DIR/issue-68656-unsized-values.rs:16:5 | LL | type Item<'a>: std::ops::Deref; - | ------------------------------------------- required by `UnsafeCopy::Item` + | ---------- required by this bound in `UnsafeCopy::Item` ... LL | impl UnsafeCopy for T { | - this type parameter diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs index 7510c58d57489..d957cae308101 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -7,7 +7,7 @@ trait ATy { impl<'b> ATy for &'b () { type Item<'a> = &'b (); - //~^ ERROR does not fulfill the required lifetime + //~^ ERROR lifetime bound not satisfied } trait StaticTy { @@ -16,7 +16,7 @@ trait StaticTy { impl StaticTy for () { type Item<'a> = &'a (); - //~^ ERROR does not fulfill the required lifetime + //~^ ERROR lifetime bound not satisfied } fn main() {} diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr index 5d612284a2187..f8b96ef3b8a03 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr @@ -1,23 +1,33 @@ -error[E0477]: the type `&'b ()` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/unsatisfied-outlives-bound.rs:9:5 | LL | type Item<'a> = &'b (); | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: type must outlive the lifetime `'a` as defined on the associated item at 9:15 +note: lifetime parameter instantiated with the lifetime `'b` as defined on the impl at 8:6 + --> $DIR/unsatisfied-outlives-bound.rs:8:6 + | +LL | impl<'b> ATy for &'b () { + | ^^ +note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 9:15 --> $DIR/unsatisfied-outlives-bound.rs:9:15 | LL | type Item<'a> = &'b (); | ^^ -error[E0477]: the type `&'a ()` does not fulfill the required lifetime +error[E0478]: lifetime bound not satisfied --> $DIR/unsatisfied-outlives-bound.rs:18:5 | LL | type Item<'a> = &'a (); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: type must satisfy the static lifetime +note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 18:15 + --> $DIR/unsatisfied-outlives-bound.rs:18:15 + | +LL | type Item<'a> = &'a (); + | ^^ + = note: but lifetime parameter must outlive the static lifetime error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0477`. +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr index b6e3bb190ea7f..ec03d18924fea 100644 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr @@ -7,13 +7,13 @@ LL | #![feature(impl_trait_in_bindings)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63065 for more information -error[E0282]: type annotations needed for `impl Future` - --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:9 +error[E0282]: type annotations needed for `impl std::future::Future` + --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20 | LL | let fut = async { | --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified LL | make_unit()?; - | ^^^^^^^^^^^^ cannot infer type + | ^ cannot infer type error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr index bf31fb85cf6db..92a9045f6db50 100644 --- a/src/test/ui/inference/cannot-infer-async.stderr +++ b/src/test/ui/inference/cannot-infer-async.stderr @@ -1,10 +1,10 @@ error[E0282]: type annotations needed - --> $DIR/cannot-infer-async.rs:11:9 + --> $DIR/cannot-infer-async.rs:11:20 | LL | let fut = async { | --- consider giving `fut` a type LL | make_unit()?; - | ^^^^^^^^^^^^ cannot infer type + | ^ cannot infer type error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr index c26c24f1dc573..d5366e422dbff 100644 --- a/src/test/ui/inference/cannot-infer-closure.stderr +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -1,8 +1,8 @@ error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>` - --> $DIR/cannot-infer-closure.rs:3:9 + --> $DIR/cannot-infer-closure.rs:3:15 | LL | Err(a)?; - | ^^^^^^^ cannot infer type + | ^ cannot infer type | help: give this closure an explicit return type without `_` placeholders | diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index e8d16a55e926e..25fa575fc6051 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -4,8 +4,9 @@ error[E0277]: the size for values of type `dyn Iterator` cann LL | for item in *things { *item = 0 } | ^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `dyn Iterator` - = note: required by `into_iter` + = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator` + = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `dyn std::iter::Iterator` + = note: required by `std::iter::IntoIterator::into_iter` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20831-debruijn.rs b/src/test/ui/issues/issue-20831-debruijn.rs index d0e15cb393ae8..20d980763ea9c 100644 --- a/src/test/ui/issues/issue-20831-debruijn.rs +++ b/src/test/ui/issues/issue-20831-debruijn.rs @@ -28,9 +28,6 @@ impl<'a> Publisher<'a> for MyStruct<'a> { fn subscribe(&mut self, t : Box::Output> + 'a>) { // Not obvious, but there is an implicit lifetime here -------^ //~^^ ERROR cannot infer - //~| ERROR cannot infer - //~| ERROR mismatched types - //~| ERROR mismatched types // // The fact that `Publisher` is using an implicit lifetime is // what was causing the debruijn accounting to be off, so diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index 1ab89e818e31e..1764dd3cf67a1 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -1,88 +1,20 @@ -error[E0308]: mismatched types - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | -... | -LL | | self.sub = t; -LL | | } - | |_____^ lifetime mismatch - | - = note: expected type `'a` - found type `'_` -note: the anonymous lifetime #2 defined on the method body at 28:5... - --> $DIR/issue-20831-debruijn.rs:28:5 +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/issue-20831-debruijn.rs:28:33 | LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 26:6 - --> $DIR/issue-20831-debruijn.rs:26:6 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -LL | impl<'a> Publisher<'a> for MyStruct<'a> { - | ^^ - -error[E0308]: mismatched types +note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5... --> $DIR/issue-20831-debruijn.rs:28:5 | LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { LL | | // Not obvious, but there is an implicit lifetime here -------^ LL | | -LL | | +LL | | // ... | LL | | self.sub = t; LL | | } - | |_____^ lifetime mismatch - | - = note: expected type `'a` - found type `'_` -note: the lifetime `'a` as defined on the impl at 26:6... - --> $DIR/issue-20831-debruijn.rs:26:6 - | -LL | impl<'a> Publisher<'a> for MyStruct<'a> { - | ^^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 28:5 - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/issue-20831-debruijn.rs:28:33 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5... - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6... - --> $DIR/issue-20831-debruijn.rs:26:6 - | -LL | impl<'a> Publisher<'a> for MyStruct<'a> { - | ^^ -note: ...so that the types are compatible - --> $DIR/issue-20831-debruijn.rs:28:33 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `Publisher<'_>` - found `Publisher<'_>` - -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/issue-20831-debruijn.rs:28:33 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 28:5... - --> $DIR/issue-20831-debruijn.rs:28:5 - | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | |_____^ note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6... --> $DIR/issue-20831-debruijn.rs:26:6 | @@ -96,7 +28,6 @@ LL | fn subscribe(&mut self, t : Box` found `Publisher<'_>` -error: aborting due to 4 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0308, E0495. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-21946.rs b/src/test/ui/issues/issue-21946.rs index 0a9f8f50bdcbe..d0c052cb2fd39 100644 --- a/src/test/ui/issues/issue-21946.rs +++ b/src/test/ui/issues/issue-21946.rs @@ -5,7 +5,6 @@ trait Foo { struct FooStruct; impl Foo for FooStruct { - //~^ ERROR overflow evaluating the requirement `::A == _` type A = ::A; //~^ ERROR overflow evaluating the requirement `::A == _` } diff --git a/src/test/ui/issues/issue-21946.stderr b/src/test/ui/issues/issue-21946.stderr index 582ce393d7f54..8b96e0f3382bb 100644 --- a/src/test/ui/issues/issue-21946.stderr +++ b/src/test/ui/issues/issue-21946.stderr @@ -1,15 +1,9 @@ -error[E0275]: overflow evaluating the requirement `::A == _` - --> $DIR/issue-21946.rs:7:6 - | -LL | impl Foo for FooStruct { - | ^^^ - -error[E0275]: overflow evaluating the requirement `::A == _` - --> $DIR/issue-21946.rs:9:5 +error[E0275]: overflow evaluating the requirement `::A` + --> $DIR/issue-21946.rs:8:5 | LL | type A = ::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-23122-1.rs b/src/test/ui/issues/issue-23122-1.rs index d6f64650f36bb..0937e029ef45e 100644 --- a/src/test/ui/issues/issue-23122-1.rs +++ b/src/test/ui/issues/issue-23122-1.rs @@ -5,7 +5,6 @@ trait Next { struct GetNext { t: T } impl Next for GetNext { - //~^ ERROR overflow evaluating the requirement type Next = as Next>::Next; //~^ ERROR overflow evaluating the requirement } diff --git a/src/test/ui/issues/issue-23122-1.stderr b/src/test/ui/issues/issue-23122-1.stderr index 4e2e837c07c6b..f837490537067 100644 --- a/src/test/ui/issues/issue-23122-1.stderr +++ b/src/test/ui/issues/issue-23122-1.stderr @@ -1,15 +1,9 @@ -error[E0275]: overflow evaluating the requirement ` as Next>::Next == _` - --> $DIR/issue-23122-1.rs:7:15 - | -LL | impl Next for GetNext { - | ^^^^ - -error[E0275]: overflow evaluating the requirement ` as Next>::Next == _` - --> $DIR/issue-23122-1.rs:9:5 +error[E0275]: overflow evaluating the requirement ` as Next>::Next` + --> $DIR/issue-23122-1.rs:8:5 | LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-23122-2.rs b/src/test/ui/issues/issue-23122-2.rs index 695712d2cc929..84abebf6b74a7 100644 --- a/src/test/ui/issues/issue-23122-2.rs +++ b/src/test/ui/issues/issue-23122-2.rs @@ -5,7 +5,6 @@ trait Next { struct GetNext { t: T } impl Next for GetNext { - //~^ ERROR overflow evaluating the requirement type Next = as Next>::Next; //~^ ERROR overflow evaluating the requirement } diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index 60dbb15d0f9c3..0d645bbcea59f 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -1,14 +1,5 @@ -error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized` - --> $DIR/issue-23122-2.rs:7:15 - | -LL | impl Next for GetNext { - | ^^^^ - | - = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`) - = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` - -error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized` - --> $DIR/issue-23122-2.rs:9:5 +error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized` + --> $DIR/issue-23122-2.rs:8:5 | LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,6 +7,6 @@ LL | type Next = as Next>::Next; = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`) = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-24204.rs b/src/test/ui/issues/issue-24204.rs index 61671b32e9b15..df72283de233e 100644 --- a/src/test/ui/issues/issue-24204.rs +++ b/src/test/ui/issues/issue-24204.rs @@ -12,6 +12,6 @@ trait Trait: Sized { } fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } -//~^ ERROR type mismatch resolving +//~^ ERROR mismatched types fn main() {} diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr index d5cbcf786bf1a..9d66c9ff0a843 100644 --- a/src/test/ui/issues/issue-24204.stderr +++ b/src/test/ui/issues/issue-24204.stderr @@ -1,15 +1,10 @@ -error[E0271]: type mismatch resolving `<::A as MultiDispatch>::O == T` - --> $DIR/issue-24204.rs:14:12 +error[E0308]: mismatched types + --> $DIR/issue-24204.rs:14:72 | -LL | trait Trait: Sized { - | ----- required by a bound in this -LL | type A: MultiDispatch; - | -------- required by this bound in `Trait` -... LL | fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } - | - ^^^^^^^^^^^^ expected type parameter `T`, found associated type - | | - | this type parameter + | - - ^^^^^^^^^ expected type parameter `T`, found associated type + | | | + | this type parameter expected `T` because of return type | = note: expected type parameter `T` found associated type `<::A as MultiDispatch>::O` @@ -17,4 +12,4 @@ LL | fn test>(b: i32) -> T where T::A: MultiDispatch { T::n error: aborting due to previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-28098.stderr b/src/test/ui/issues/issue-28098.stderr index df552fc2d0e2b..04075911111ae 100644 --- a/src/test/ui/issues/issue-28098.stderr +++ b/src/test/ui/issues/issue-28098.stderr @@ -13,8 +13,9 @@ error[E0277]: `bool` is not an iterator LL | for _ in false {} | ^^^^^ `bool` is not an iterator | - = help: the trait `Iterator` is not implemented for `bool` - = note: required by `into_iter` + = help: the trait `std::iter::Iterator` is not implemented for `bool` + = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `bool` + = note: required by `std::iter::IntoIterator::into_iter` error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:9:28 diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index aeab923d2df16..81d97bdbf1242 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -15,7 +15,9 @@ LL | for _ in HashMap::new().iter().cloned() {} | = note: expected tuple `(&_, &_)` found reference `&_` - = note: required because of the requirements on the impl of `Iterator` for `Cloned>` + = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned>` + = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `std::iter::Cloned>` + = note: required by `std::iter::IntoIterator::into_iter` error[E0271]: type mismatch resolving ` as Iterator>::Item == &_` --> $DIR/issue-33941.rs:4:14 diff --git a/src/test/ui/issues/issue-38091.stderr b/src/test/ui/issues/issue-38091.stderr index 81beec8026314..f47fd8d1b0da9 100644 --- a/src/test/ui/issues/issue-38091.stderr +++ b/src/test/ui/issues/issue-38091.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `(): Valid` is not satisfied --> $DIR/issue-38091.rs:9:5 | LL | type Ty: Valid; - | --------------- required by `Iterate::Ty` + | ----- required by this bound in `Iterate::Ty` ... LL | default type Ty = (); | ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()` diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index 039852ad16596..7b656ef8559ca 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -1,8 +1,11 @@ -error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-43784-associated-type.rs:14:18 +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/issue-43784-associated-type.rs:14:5 | +LL | type Assoc: Partial; + | ------------- required by this bound in `Complete::Assoc` +... LL | type Assoc = T; - | ^ the trait `Copy` is not implemented for `T` + | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/issues/issue-43784-supertrait.stderr b/src/test/ui/issues/issue-43784-supertrait.stderr index d92e4fa9e4a5d..c73536ba97332 100644 --- a/src/test/ui/issues/issue-43784-supertrait.stderr +++ b/src/test/ui/issues/issue-43784-supertrait.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-43784-supertrait.rs:8:9 | +LL | pub trait Complete: Partial { + | ------- required by this bound in `Complete` +... LL | impl Complete for T {} | ^^^^^^^^ the trait `Copy` is not implemented for `T` | diff --git a/src/test/ui/issues/issue-65673.stderr b/src/test/ui/issues/issue-65673.stderr index aa43ac9414f19..64cc0bab3f33c 100644 --- a/src/test/ui/issues/issue-65673.stderr +++ b/src/test/ui/issues/issue-65673.stderr @@ -1,13 +1,11 @@ error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/issue-65673.rs:9:16 + --> $DIR/issue-65673.rs:9:5 | -LL | trait WithType { - | -------- required by a bound in this LL | type Ctx; - | --------- required by this bound in `WithType` + | --------- required by this bound in `WithType::Ctx` ... LL | type Ctx = dyn Alias; - | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)` diff --git a/src/test/ui/never_type/issue-51506.stderr b/src/test/ui/never_type/issue-51506.stderr index c54cbe9b4d173..16d93c18900a9 100644 --- a/src/test/ui/never_type/issue-51506.stderr +++ b/src/test/ui/never_type/issue-51506.stderr @@ -2,7 +2,7 @@ error[E0277]: `!` is not an iterator --> $DIR/issue-51506.rs:13:5 | LL | type Out: Iterator; - | ------------------------------- required by `Trait::Out` + | -------------------- required by this bound in `Trait::Out` ... LL | default type Out = !; | ^^^^^^^^^^^^^^^^^^^^^ `!` is not an iterator diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs index d3964a7f515de..44dcd191d1ba2 100644 --- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs +++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs @@ -32,5 +32,4 @@ fn main() { let _x = ::make_f(); //~^ higher-ranked subtype error //~| higher-ranked subtype error - //~| higher-ranked subtype error } diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index 70fb877d71689..190b520c6786c 100644 --- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -10,11 +10,5 @@ error: higher-ranked subtype error LL | let _x = ::make_f(); | ^^^^^^^^^^^^^^^^^^^ -error: higher-ranked subtype error - --> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14 - | -LL | let _x = ::make_f(); - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs index 5238894a974f4..fdf0bc3839112 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.rs +++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs @@ -29,7 +29,11 @@ mod m { //~| WARN this was previously accepted type Alias1: PrivTr; type Alias2: PubTrAux1 = u8; + //~^ WARN private type `m::Priv` in public interface + //~| WARN this was previously accepted type Alias3: PubTrAux2 = u8; + //~^ WARN private type `m::Priv` in public interface + //~| WARN this was previously accepted type Alias4 = Priv; //~^ ERROR private type `Priv` in public interface diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr index acc6e20cf33e8..768dca17e07d2 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr +++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr @@ -10,14 +10,8 @@ LL | type A = Priv; warning: private trait `PrivTr` in public interface (error E0445) --> $DIR/private-in-public-assoc-ty.rs:23:5 | -LL | / pub trait PubTr { -LL | | -LL | | -LL | | -... | -LL | | fn infer_exist() -> Self::Exist; -LL | | } - | |_____^ +LL | type Alias1: PrivTr; + | ^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(private_in_public)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -26,14 +20,8 @@ LL | | } warning: private type `Priv` in public interface (error E0446) --> $DIR/private-in-public-assoc-ty.rs:23:5 | -LL | / pub trait PubTr { -LL | | -LL | | -LL | | -... | -LL | | fn infer_exist() -> Self::Exist; -LL | | } - | |_____^ +LL | type Alias2: PubTrAux1 = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = 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 #34537 @@ -41,14 +29,8 @@ LL | | } warning: private type `Priv` in public interface (error E0446) --> $DIR/private-in-public-assoc-ty.rs:23:5 | -LL | / pub trait PubTr { -LL | | -LL | | -LL | | -... | -LL | | fn infer_exist() -> Self::Exist; -LL | | } - | |_____^ +LL | type Alias3: PubTrAux2 = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = 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 #34537 diff --git a/src/test/ui/privacy/private-in-public-warn.rs b/src/test/ui/privacy/private-in-public-warn.rs index 3022b470b7d81..1c8706d8ad2e1 100644 --- a/src/test/ui/privacy/private-in-public-warn.rs +++ b/src/test/ui/privacy/private-in-public-warn.rs @@ -55,9 +55,9 @@ mod traits { pub trait Tr2 {} //~ ERROR private trait `traits::PrivTr` in public interface //~^ WARNING hard error pub trait Tr3 { + type Alias: PrivTr; //~^ ERROR private trait `traits::PrivTr` in public interface //~| WARNING hard error - type Alias: PrivTr; fn f(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface //~^ WARNING hard error } diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr index 36577a6010260..f50dc48f8add3 100644 --- a/src/test/ui/privacy/private-in-public-warn.stderr +++ b/src/test/ui/privacy/private-in-public-warn.stderr @@ -130,16 +130,10 @@ LL | pub trait Tr2 {} = note: for more information, see issue #34537 error: private trait `traits::PrivTr` in public interface (error E0445) - --> $DIR/private-in-public-warn.rs:57:5 - | -LL | / pub trait Tr3 { -LL | | -LL | | -LL | | type Alias: PrivTr; -LL | | fn f(arg: T) {} -LL | | -LL | | } - | |_____^ + --> $DIR/private-in-public-warn.rs:58:9 + | +LL | type Alias: PrivTr; + | ^^^^^^^^^^^^^^^^^^^ | = 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 #34537 diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs index e485263affcf7..5476e35b5f66b 100644 --- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -1,5 +1,5 @@ - // aux-crate:priv:priv_dep=priv_dep.rs - // aux-build:pub_dep.rs +// aux-crate:priv:priv_dep=priv_dep.rs +// aux-build:pub_dep.rs #![deny(exported_private_dependencies)] // This crate is a private dependency @@ -7,20 +7,20 @@ extern crate priv_dep; // This crate is a public dependency extern crate pub_dep; -use priv_dep::{OtherType, OtherTrait}; +use priv_dep::{OtherTrait, OtherType}; use pub_dep::PubType; // Type from private dependency used in private // type - this is fine struct PrivateType { - field: OtherType + field: OtherType, } pub struct PublicType { pub field: OtherType, //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface - priv_field: OtherType, // Private field - this is fine - pub other_field: PubType // Type from public dependency - this is fine + priv_field: OtherType, // Private field - this is fine + pub other_field: PubType, // Type from public dependency - this is fine } impl PublicType { @@ -32,14 +32,13 @@ impl PublicType { pub trait MyPubTrait { type Foo: OtherTrait; + //~^ ERROR trait `priv_dep::OtherTrait` from private dependency 'priv_dep' in public interface } //~^^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface pub struct AllowedPrivType { #[allow(exported_private_dependencies)] - pub allowed: OtherType + pub allowed: OtherType, } - - fn main() {} diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr index 3b5b78234436e..e6fd6fc7bb8ce 100644 --- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -19,10 +19,8 @@ LL | pub fn pub_fn(param: OtherType) {} error: trait `OtherTrait` from private dependency 'priv_dep' in public interface --> $DIR/pub-priv1.rs:33:1 | -LL | / pub trait MyPubTrait { -LL | | type Foo: OtherTrait; -LL | | } - | |_^ +LL | type Foo: OtherTrait; + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index f530534ec801f..a896d58753321 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -1,4 +1,4 @@ -error[E0284]: type annotations needed +error[E0283]: type annotations needed --> $DIR/question-mark-type-infer.rs:12:21 | LL | l.iter().map(f).collect()? @@ -12,4 +12,4 @@ LL | l.iter().map(f).collect::()? error: aborting due to previous error -For more information about this error, try `rustc --explain E0284`. +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr index a7557320faa4b..e380e5b2f91ff 100644 --- a/src/test/ui/range/range-1.stderr +++ b/src/test/ui/range/range-1.stderr @@ -17,7 +17,7 @@ error[E0277]: the size for values of type `[{integer}]` cannot be known at compi | LL | let range = *arr..; | ^^^^^^ doesn't have a size known at compile-time - | + | ::: $SRC_DIR/core/src/ops/range.rs:LL:COL | LL | pub struct RangeFrom { diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs index 26cb40bb5c2b1..0f86e37b7e5cc 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs @@ -12,13 +12,13 @@ impl<'a> Foo<'a> for &'a i16 { } impl<'a> Foo<'static> for &'a i32 { - //~^ ERROR cannot infer type Value = &'a i32; + //~^ ERROR lifetime bound not satisfied } impl<'a,'b> Foo<'b> for &'a i64 { - //~^ ERROR cannot infer type Value = &'a i32; + //~^ ERROR lifetime bound not satisfied } fn main() { } diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr index c134b3b3ed554..feb9c90bc8f1b 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr @@ -1,57 +1,33 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10 +error[E0478]: lifetime bound not satisfied + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:15:5 | -LL | impl<'a> Foo<'static> for &'a i32 { - | ^^^^^^^^^^^^ +LL | type Value = &'a i32; + | ^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 14:6... +note: lifetime parameter instantiated with the lifetime `'a` as defined on the impl at 14:6 --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6 | LL | impl<'a> Foo<'static> for &'a i32 { | ^^ -note: ...so that the types are compatible - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10 - | -LL | impl<'a> Foo<'static> for &'a i32 { - | ^^^^^^^^^^^^ - = note: expected `Foo<'static>` - found `Foo<'static>` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the type `&i32` will meet its required lifetime bounds - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10 - | -LL | impl<'a> Foo<'static> for &'a i32 { - | ^^^^^^^^^^^^ + = note: but lifetime parameter must outlive the static lifetime -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13 +error[E0478]: lifetime bound not satisfied + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:20:5 | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^^^^^^ +LL | type Value = &'a i32; + | ^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 19:6... +note: lifetime parameter instantiated with the lifetime `'a` as defined on the impl at 19:6 --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6 | LL | impl<'a,'b> Foo<'b> for &'a i64 { | ^^ -note: ...so that the types are compatible - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13 - | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^^^^^^ - = note: expected `Foo<'b>` - found `Foo<'_>` -note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9... +note: but lifetime parameter must outlive the lifetime `'b` as defined on the impl at 19:9 --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9 | LL | impl<'a,'b> Foo<'b> for &'a i64 { | ^^ -note: ...so that the type `&i32` will meet its required lifetime bounds - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:13 - | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^^^^^^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs index 599cd0bb756ea..65b54b45a0a16 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs @@ -7,8 +7,8 @@ trait Foo { } impl<'a> Foo for &'a i32 { - //~^ ERROR cannot infer type Value = &'a i32; + //~^ ERROR lifetime bound not satisfied } impl<'a> Foo for i32 { diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr index ac8c55ccc8fd4..9b98d14a9781f 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr @@ -1,28 +1,16 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10 +error[E0478]: lifetime bound not satisfied + --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:10:5 | -LL | impl<'a> Foo for &'a i32 { - | ^^^ +LL | type Value = &'a i32; + | ^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 9:6... +note: lifetime parameter instantiated with the lifetime `'a` as defined on the impl at 9:6 --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6 | LL | impl<'a> Foo for &'a i32 { | ^^ -note: ...so that the types are compatible - --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10 - | -LL | impl<'a> Foo for &'a i32 { - | ^^^ - = note: expected `Foo` - found `Foo` - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the type `&i32` will meet its required lifetime bounds - --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10 - | -LL | impl<'a> Foo for &'a i32 { - | ^^^ + = note: but lifetime parameter must outlive the static lifetime error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.stderr b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr index 612e22c204fa6..4c21f8db8fad8 100644 --- a/src/test/ui/specialization/deafult-associated-type-bound-1.stderr +++ b/src/test/ui/specialization/deafult-associated-type-bound-1.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/deafult-associated-type-bound-1.rs:18:5 | LL | type U: Clone; - | -------------- required by `X::U` + | ----- required by this bound in `X::U` ... LL | default type U = str; | ^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` diff --git a/src/test/ui/specialization/deafult-associated-type-bound-2.stderr b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr index a14024c160f76..8c9da81d277ef 100644 --- a/src/test/ui/specialization/deafult-associated-type-bound-2.stderr +++ b/src/test/ui/specialization/deafult-associated-type-bound-2.stderr @@ -11,7 +11,7 @@ error[E0277]: can't compare `&'static B` with `B` --> $DIR/deafult-associated-type-bound-2.rs:16:5 | LL | type U: PartialEq; - | --------------------- required by `X::U` + | ------------ required by this bound in `X::U` ... LL | default type U = &'static B; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `&'static B == B` diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs index 8a94ea658d2d0..f14588e6e023c 100644 --- a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.rs @@ -6,7 +6,7 @@ //~^^ WARNING the feature `generic_associated_types` is incomplete trait X { - type U<'a>: PartialEq<&'a Self>; + type U<'a>: PartialEq<&'a Self> where Self: 'a; fn unsafe_compare<'b>(x: Option>, y: Option<&'b Self>) { match (x, y) { (Some(a), Some(b)) => a == b, diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr index 556feda642b54..f145b90f216ab 100644 --- a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr +++ b/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr @@ -18,8 +18,8 @@ LL | #![feature(generic_associated_types)] error[E0277]: can't compare `T` with `T` --> $DIR/deafult-generic-associated-type-bound.rs:19:5 | -LL | type U<'a>: PartialEq<&'a Self>; - | -------------------------------- required by `X::U` +LL | type U<'a>: PartialEq<&'a Self> where Self: 'a; + | ------------------- required by this bound in `X::U` ... LL | default type U<'a> = &'a T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T == T` diff --git a/src/test/ui/specialization/issue-44861.stderr b/src/test/ui/specialization/issue-44861.stderr index be7196a63ce1d..3935a4a5f9931 100644 --- a/src/test/ui/specialization/issue-44861.stderr +++ b/src/test/ui/specialization/issue-44861.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied --> $DIR/issue-44861.rs:21:5 | LL | type Data2: CoerceUnsized<*const [u8]>; - | --------------------------------------- required by `Smartass::Data2` + | -------------------------- required by this bound in `Smartass::Data2` ... LL | default type Data2 = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CoerceUnsized<*const [u8]>` is not implemented for `()` diff --git a/src/test/ui/specialization/issue-59435.stderr b/src/test/ui/specialization/issue-59435.stderr index ee5c0615927a8..f3f8b022b01e1 100644 --- a/src/test/ui/specialization/issue-59435.stderr +++ b/src/test/ui/specialization/issue-59435.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `MyStruct: Default` is not satisfied --> $DIR/issue-59435.rs:11:5 | LL | type MyType: Default; - | --------------------- required by `MyTrait::MyType` + | ------- required by this bound in `MyTrait::MyType` ... LL | default type MyType = MyStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `MyStruct` diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs index 394512c579474..8218fecc3f12d 100644 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs @@ -15,11 +15,9 @@ impl Child for ChildWrapper where T: Child {} struct ParentWrapper(T); impl> Parent for ParentWrapper { - //~^ ERROR the trait bound `::Assoc: Child` is not satisfied type Ty = A; type Assoc = ChildWrapper; //~^ ERROR the trait bound `::Assoc: Child` is not satisfied - //~| ERROR the trait bound `::Assoc: Child` is not satisfied } fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr index a8ea214796183..676e2fb1a51dc 100644 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr @@ -1,55 +1,18 @@ error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:17:19 + --> $DIR/missing-assoc-type-bound-restriction.rs:19:5 | -LL | trait Parent { - | ------ required by a bound in this -LL | type Ty; LL | type Assoc: Child; - | --------------- required by this bound in `Parent` -... -LL | impl> Parent for ParentWrapper { - | ^^^^^^ the trait `Child` is not implemented for `::Assoc` - | -help: consider further restricting the associated type - | -LL | impl> Parent for ParentWrapper where ::Assoc: Child { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:20:18 - | -LL | trait Parent { - | ------ required by a bound in this -LL | type Ty; -LL | type Assoc: Child; - | --------------- required by this bound in `Parent` -... -LL | type Assoc = ChildWrapper; - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` - | - = note: required because of the requirements on the impl of `Child` for `ChildWrapper<::Assoc>` -help: consider further restricting the associated type - | -LL | impl> Parent for ParentWrapper where ::Assoc: Child { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:20:5 - | -LL | trait Parent { - | ------ required by a bound in this -LL | type Ty; -LL | type Assoc: Child; - | --------------- required by this bound in `Parent` + | --------------- required by this bound in `Parent::Assoc` ... LL | type Assoc = ChildWrapper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` | + = note: required because of the requirements on the impl of `Child` for `ChildWrapper<::Assoc>` help: consider further restricting the associated type | LL | impl> Parent for ParentWrapper where ::Assoc: Child { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/cycle-cache-err-60010.rs b/src/test/ui/traits/cycle-cache-err-60010.rs index cbddef082be67..62d558fde888e 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.rs +++ b/src/test/ui/traits/cycle-cache-err-60010.rs @@ -28,7 +28,9 @@ struct SalsaStorage { } impl Database for RootDatabase { - type Storage = SalsaStorage; //~ ERROR overflow + // This would also be an error if we didn't abort compilation on the error + // above. + type Storage = SalsaStorage; } impl HasQueryGroup for RootDatabase {} impl Query for ParseQuery diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.rs b/src/test/ui/traits/traits-inductive-overflow-two-traits.rs index 63dd141920025..463b55d8581f8 100644 --- a/src/test/ui/traits/traits-inductive-overflow-two-traits.rs +++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.rs @@ -9,6 +9,7 @@ pub trait Magic { } impl Magic for T { type X = Self; + //~^ ERROR E0277 } fn check() {} diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr index f66cfce55c903..dbe0146cafaa6 100644 --- a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr @@ -1,5 +1,19 @@ +error[E0277]: `T` cannot be shared between threads safely + --> $DIR/traits-inductive-overflow-two-traits.rs:11:5 + | +LL | type X: Trait; + | ----- required by this bound in `Magic::X` +... +LL | type X = Self; + | ^^^^^^^^^^^^^^ `T` cannot be shared between threads safely + | +help: consider further restricting this bound + | +LL | impl Magic for T { + | ^^^^^^^^^^^^^^^^^^^ + error[E0275]: overflow evaluating the requirement `*mut (): Magic` - --> $DIR/traits-inductive-overflow-two-traits.rs:19:5 + --> $DIR/traits-inductive-overflow-two-traits.rs:20:5 | LL | fn wizard() { check::<::X>(); } | ----- required by this bound in `wizard` @@ -7,6 +21,7 @@ LL | fn wizard() { check::<::X>(); } LL | wizard::<*mut ()>(); | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0275`. +Some errors have detailed explanations: E0275, E0277. +For more information about an error, try `rustc --explain E0275`. diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index 03d5d3661ddf7..dfc1c342a508b 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -41,7 +41,7 @@ LL | let res: i32 = try { 5 }; | = note: required by `from_ok` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0271, E0277. For more information about an error, try `rustc --explain E0271`. From 87f2f42dc2c81dd842451e6c68d12abdc5fe3ecf Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jun 2020 10:51:32 +0100 Subject: [PATCH 05/34] Make projection wf check the predicates for the projection --- .../rustc_trait_selection/src/traits/wf.rs | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 909cd2aa1551e..165e45aa94ae4 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -327,17 +327,31 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// Pushes the obligations required for `trait_ref::Item` to be WF /// into `self.out`. fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) { - // A projection is well-formed if (a) the trait ref itself is - // WF and (b) the trait-ref holds. (It may also be - // normalizable and be WF that way.) - let trait_ref = data.trait_ref(self.infcx.tcx); - self.compute_trait_ref(&trait_ref, Elaborate::None); - - if !data.has_escaping_bound_vars() { - let predicate = trait_ref.without_const().to_predicate(self.infcx.tcx); - let cause = self.cause(traits::ProjectionWf(data)); - self.out.push(traits::Obligation::new(cause, self.param_env, predicate)); - } + // A projection is well-formed if + // (a) its predicates hold + // (b) its substs are wf + let obligations = self.nominal_obligations(data.item_def_id, data.substs); + self.out.extend(obligations); + + let tcx = self.tcx(); + let cause = self.cause(traits::MiscObligation); + let param_env = self.param_env; + + self.out.extend( + data.substs + .iter() + .filter(|arg| { + matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) + }) + .filter(|arg| !arg.has_escaping_bound_vars()) + .map(|arg| { + traits::Obligation::new( + cause.clone(), + param_env, + ty::PredicateKind::WellFormed(arg).to_predicate(tcx), + ) + }), + ); } fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { From b3057f4d5fe7156aa85e1844d3638fa14ba48b79 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jun 2020 12:41:46 +0100 Subject: [PATCH 06/34] Check projections are well-formed when using projection candidates --- .../src/traits/select/candidate_assembly.rs | 6 +- .../src/traits/select/confirmation.rs | 34 ++++++++-- .../src/traits/select/mod.rs | 29 ++++----- .../rustc_typeck/src/check/compare_method.rs | 6 +- compiler/rustc_typeck/src/check/wfcheck.rs | 2 +- .../projection-bound-cycle-generic.rs | 62 ++++++++++++++++++ .../projection-bound-cycle-generic.stderr | 21 ++++++ .../projection-bound-cycle.rs | 64 +++++++++++++++++++ .../projection-bound-cycle.stderr | 21 ++++++ src/test/ui/specialization/issue-38091-2.rs | 23 +++++++ .../ui/specialization/issue-38091-2.stderr | 23 +++++++ .../{issues => specialization}/issue-38091.rs | 1 + .../issue-38091.stderr | 16 ++++- 13 files changed, 278 insertions(+), 30 deletions(-) create mode 100644 src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs create mode 100644 src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr create mode 100644 src/test/ui/generic-associated-types/projection-bound-cycle.rs create mode 100644 src/test/ui/generic-associated-types/projection-bound-cycle.stderr create mode 100644 src/test/ui/specialization/issue-38091-2.rs create mode 100644 src/test/ui/specialization/issue-38091-2.stderr rename src/test/ui/{issues => specialization}/issue-38091.rs (86%) rename src/test/ui/{issues => specialization}/issue-38091.stderr (55%) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 9cb5c232646f8..6c7732f28e41f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -323,9 +323,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, } - let result = self - .infcx - .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); + let result = self.infcx.probe(|_| { + self.match_projection_obligation_against_definition_bounds(obligation).is_some() + }); if result { candidates.vec.push(ProjectionCandidate); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 88b656ce68082..625bb5d7a44fa 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -69,8 +69,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ProjectionCandidate => { - self.confirm_projection_candidate(obligation); - Ok(ImplSource::Param(Vec::new())) + let obligations = self.confirm_projection_candidate(obligation); + Ok(ImplSource::Param(obligations)) } ClosureCandidate => { @@ -116,10 +116,34 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { + fn confirm_projection_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> Vec> { self.infcx.commit_unconditionally(|_| { - let result = self.match_projection_obligation_against_definition_bounds(obligation); - assert!(result); + let candidate = self + .match_projection_obligation_against_definition_bounds(obligation) + .unwrap_or_else(|| bug!("Can't find selected projection candidate")); + let mut obligations = self + .infcx + .at(&obligation.cause, obligation.param_env) + .sup(obligation.predicate.to_poly_trait_ref(), candidate) + .map(|InferOk { obligations, .. }| obligations) + .unwrap_or_else(|_| { + bug!( + "Projection bound `{:?}` was applicable to `{:?}` but now is not", + candidate, + obligation + ); + }); + // Require that the projection is well-formed. + let self_ty = obligation.predicate.skip_binder().self_ty(); + obligations.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env, + ty::PredicateKind::WellFormed(self_ty.into()).to_predicate(self.tcx()), + )); + obligations }) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9bebf8d90c21e..2d6ccfe031e5b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1159,7 +1159,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, - ) -> bool { + ) -> Option> { let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate); let (placeholder_trait_predicate, _) = self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate); @@ -1170,9 +1170,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let tcx = self.infcx.tcx; - let predicates = match *placeholder_trait_predicate.trait_ref.self_ty().kind() { - ty::Projection(ref data) => tcx.item_bounds(data.item_def_id).subst(tcx, data.substs), - ty::Opaque(def_id, substs) => tcx.item_bounds(def_id).subst(tcx, substs), + let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() { + ty::Projection(ref data) => (data.item_def_id, data.substs), + ty::Opaque(def_id, substs) => (def_id, substs), _ => { span_bug!( obligation.cause.span, @@ -1182,12 +1182,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); } }; + let bounds = tcx.item_bounds(def_id).subst(tcx, substs); - let matching_bound = predicates.iter().find_map(|bound| { + let matching_bound = bounds.iter().find_map(|bound| { if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() { let bound = ty::Binder::bind(pred.trait_ref); if self.infcx.probe(|_| { self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref) + .is_ok() }) { return Some(bound); } @@ -1200,17 +1202,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { matching_bound={:?}", matching_bound ); - match matching_bound { - None => false, - Some(bound) => { - // Repeat the successful match, if any, this time outside of a probe. - let result = - self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref); - - assert!(result); - true - } - } + matching_bound } fn match_projection( @@ -1218,12 +1210,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, - ) -> bool { + ) -> Result>, ()> { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) - .is_ok() + .map(|InferOk { obligations, .. }| obligations) + .map_err(|_| ()) } fn evaluate_where_clause<'o>( diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 3515fb12e4ca7..b059b03bc058a 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1269,7 +1269,11 @@ pub fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id); - fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]); + let implied_bounds = match impl_ty.container { + ty::TraitContainer(_) => vec![], + ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span), + }; + fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &implied_bounds); Ok(()) }) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index f31ba886d5262..b4e950ab6e9e5 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1425,7 +1425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect() } - fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec> { + pub(super) fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec> { match self.tcx.impl_trait_ref(impl_def_id) { Some(ref trait_ref) => { // Trait impl: take implied bounds from all types that diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs new file mode 100644 index 0000000000000..c88fb8ad96e3e --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -0,0 +1,62 @@ +// Like `projection-bound-cycle.rs` but this avoids using +// `feature(trivial_bounds)`. + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete + +trait Print { + fn print(); +} + +trait Foo { + type Item: Sized where ::Item: Sized; +} + +struct Number { t: T } + +impl Foo for Number { + // Well-formedness checks require that the following + // goal is true: + // ``` + // if ([T]: Sized) { # if the where clauses hold + // [T]: Sized # then the bound on the associated type hold + // } + // ``` + // which it is :) + type Item where [T]: Sized = [T]; +} + +struct OnlySized where T: Sized { f: T } +impl Print for OnlySized { + fn print() { + println!("{}", std::mem::size_of::()); + } +} + +trait Bar { + type Assoc: Print; +} + +impl Bar for T where T: Foo { + // This is not ok, we need to prove `wf(::Item)`, which requires + // knowing that `::Item: Sized` to satisfy the where clause. We + // can use the bound on `Foo::Item` for this, but that requires + // `wf(::Item)`, which is an invalid cycle. + type Assoc = OnlySized<::Item>; + //~^ ERROR overflow evaluating the requirement `::Item: std::marker::Sized` +} + +fn foo() { + T::print() // oops, in fact `T = OnlySized` which is ill-formed +} + +fn bar() { + // we have `FromEnv(T: Bar)` hence + // `::Assoc` is well-formed and + // `Implemented(::Assoc: Print)` hold + foo::<::Assoc>() +} + +fn main() { + bar::>() +} diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr new file mode 100644 index 0000000000000..5967752ef7973 --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -0,0 +1,21 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/projection-bound-cycle-generic.rs:4:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0275]: overflow evaluating the requirement `::Item: std::marker::Sized` + --> $DIR/projection-bound-cycle-generic.rs:45:5 + | +LL | struct OnlySized where T: Sized { f: T } + | - required by this bound in `OnlySized` +... +LL | type Assoc = OnlySized<::Item>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.rs b/src/test/ui/generic-associated-types/projection-bound-cycle.rs new file mode 100644 index 0000000000000..0728dc1bcbc9b --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.rs @@ -0,0 +1,64 @@ +// Test case from Chalk. +// Make sure that we make sure that we don't allow arbitrary bounds to be +// proven when a bound and a where clause of an associated type are the same. + +#![feature(generic_associated_types)] +//~^ WARNING the feature `generic_associated_types` is incomplete +#![feature(trivial_bounds)] + +trait Print { + fn print(); +} + +trait Foo { + type Item: Sized where ::Item: Sized; +} + +struct Number { } + +impl Foo for Number { + // Well-formedness checks require that the following + // goal is true: + // ``` + // if (str: Sized) { # if the where clauses hold + // str: Sized # then the bound on the associated type hold + // } + // ``` + // which it is :) + type Item where str: Sized = str; +} + +struct OnlySized where T: Sized { f: T } +impl Print for OnlySized { + fn print() { + println!("{}", std::mem::size_of::()); + } +} + +trait Bar { + type Assoc: Print; +} + +impl Bar for T where T: Foo { + // This is not ok, we need to prove `wf(::Item)`, which requires + // knowing that `::Item: Sized` to satisfy the where clause. We + // can use the bound on `Foo::Item` for this, but that requires + // `wf(::Item)`, which is an invalid cycle. + type Assoc = OnlySized<::Item>; + //~^ ERROR overflow evaluating the requirement `::Item: std::marker::Sized` +} + +fn foo() { + T::print() // oops, in fact `T = OnlySized` which is ill-formed +} + +fn bar() { + // we have `FromEnv(T: Bar)` hence + // `::Assoc` is well-formed and + // `Implemented(::Assoc: Print)` hold + foo::<::Assoc>() +} + +fn main() { + bar::() +} diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr new file mode 100644 index 0000000000000..80d102013a79b --- /dev/null +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr @@ -0,0 +1,21 @@ +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/projection-bound-cycle.rs:5:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information + +error[E0275]: overflow evaluating the requirement `::Item: std::marker::Sized` + --> $DIR/projection-bound-cycle.rs:47:5 + | +LL | struct OnlySized where T: Sized { f: T } + | - required by this bound in `OnlySized` +... +LL | type Assoc = OnlySized<::Item>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/specialization/issue-38091-2.rs b/src/test/ui/specialization/issue-38091-2.rs new file mode 100644 index 0000000000000..da7f673773356 --- /dev/null +++ b/src/test/ui/specialization/issue-38091-2.rs @@ -0,0 +1,23 @@ +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Iterate<'a> { + type Ty: Valid; + fn iterate(self); +} +impl<'a, T> Iterate<'a> for T where T: Check { + default type Ty = (); + default fn iterate(self) {} +} + +trait Check {} +impl<'a, T> Check for T where >::Ty: Valid {} + +trait Valid {} + +impl Valid for () {} + +fn main() { + Iterate::iterate(0); + //~^ ERROR overflow evaluating the requirement `{integer}: Check` +} diff --git a/src/test/ui/specialization/issue-38091-2.stderr b/src/test/ui/specialization/issue-38091-2.stderr new file mode 100644 index 0000000000000..e776ff0fafb23 --- /dev/null +++ b/src/test/ui/specialization/issue-38091-2.stderr @@ -0,0 +1,23 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-38091-2.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #31844 for more information + +error[E0275]: overflow evaluating the requirement `{integer}: Check` + --> $DIR/issue-38091-2.rs:21:5 + | +LL | fn iterate(self); + | ----------------- required by `Iterate::iterate` +... +LL | Iterate::iterate(0); + | ^^^^^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `Iterate<'_>` for `{integer}` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/issues/issue-38091.rs b/src/test/ui/specialization/issue-38091.rs similarity index 86% rename from src/test/ui/issues/issue-38091.rs rename to src/test/ui/specialization/issue-38091.rs index a84391b94d1de..cc0eeb53687de 100644 --- a/src/test/ui/issues/issue-38091.rs +++ b/src/test/ui/specialization/issue-38091.rs @@ -18,4 +18,5 @@ trait Valid {} fn main() { Iterate::iterate(0); + //~^ ERROR overflow evaluating the requirement `{integer}: Check` } diff --git a/src/test/ui/issues/issue-38091.stderr b/src/test/ui/specialization/issue-38091.stderr similarity index 55% rename from src/test/ui/issues/issue-38091.stderr rename to src/test/ui/specialization/issue-38091.stderr index f47fd8d1b0da9..beec702b89e46 100644 --- a/src/test/ui/issues/issue-38091.stderr +++ b/src/test/ui/specialization/issue-38091.stderr @@ -16,6 +16,18 @@ LL | type Ty: Valid; LL | default type Ty = (); | ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()` -error: aborting due to previous error; 1 warning emitted +error[E0275]: overflow evaluating the requirement `{integer}: Check` + --> $DIR/issue-38091.rs:20:5 + | +LL | fn iterate(self); + | ----------------- required by `Iterate::iterate` +... +LL | Iterate::iterate(0); + | ^^^^^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `Iterate<'_>` for `{integer}` + +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0275, E0277. +For more information about an error, try `rustc --explain E0275`. From 5b279c801635c2762c013c1d13a9bead3bcd9df4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jun 2020 16:46:02 +0100 Subject: [PATCH 07/34] Check opaque types satisfy their bounds --- .../rustc_trait_selection/src/opaque_types.rs | 3 +- compiler/rustc_typeck/src/check/check.rs | 68 ++++++++++++++++++- ...mpl-trait-return-missing-constraint.stderr | 1 - .../ui/async-await/async-error-span.stderr | 3 - .../issue-64130-4-async-move.stderr | 1 - src/test/ui/async-await/issue-70818.stderr | 1 - .../type-mismatch-signature-deduction.stderr | 1 - .../bound-normalization-fail.stderr | 2 - src/test/ui/impl-trait/issue-55872-1.stderr | 2 - src/test/ui/issues-71798.stderr | 2 - .../lifetime-elision-return-type-trait.stderr | 5 -- .../feature-gate-never_type_fallback.stderr | 5 -- ...mpl-trait-return-trailing-semicolon.stderr | 2 - .../bounds-are-checked-2.rs | 19 ++++++ .../bounds-are-checked-2.stderr | 14 ++++ .../bounds-are-checked.rs | 25 +++++++ .../bounds-are-checked.stderr | 26 +++++++ .../generic_duplicate_param_use10.rs | 4 +- .../generic_duplicate_param_use7.rs | 4 +- .../type-alias-impl-trait/issue-60371.stderr | 1 - .../type-alias-impl-trait/issue-63279.stderr | 1 - .../type-alias-impl-trait.rs | 4 +- 22 files changed, 158 insertions(+), 36 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs create mode 100644 src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr create mode 100644 src/test/ui/type-alias-impl-trait/bounds-are-checked.rs create mode 100644 src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 1babfb8508ed8..0621d9bf09e13 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1170,7 +1170,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // This also instantiates nested instances of `impl Trait`. let predicate = self.instantiate_opaque_types_in_map(&predicate); - let cause = traits::ObligationCause::new(span, self.body_id, traits::SizedReturnType); + let cause = + traits::ObligationCause::new(span, self.body_id, traits::MiscObligation); // Require that the predicate holds for the concrete type. debug!("instantiate_opaque_types: predicate={:?}", predicate); diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 2df9007195fae..f5e6ff07b88b7 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -387,7 +387,10 @@ pub(super) fn check_opaque<'tcx>( ) { check_opaque_for_inheriting_lifetimes(tcx, def_id, span); tcx.ensure().type_of(def_id); - check_opaque_for_cycles(tcx, def_id, substs, span, origin); + if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() { + return; + } + check_opaque_meets_bounds(tcx, def_id, substs, span, origin); } /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result @@ -504,7 +507,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( substs: SubstsRef<'tcx>, span: Span, origin: &hir::OpaqueTyOrigin, -) { +) -> Result<(), ErrorReported> { if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs) { match origin { @@ -514,7 +517,68 @@ pub(super) fn check_opaque_for_cycles<'tcx>( } _ => opaque_type_cycle_error(tcx, def_id, span), } + Err(ErrorReported) + } else { + Ok(()) + } +} + +/// Check that the concrete type behind `impl Trait` actually implements `Trait`. +fn check_opaque_meets_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + substs: SubstsRef<'tcx>, + span: Span, + origin: &hir::OpaqueTyOrigin, +) { + match origin { + // Checked when type checking the function containing them. + hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return, + // Can have different predicates to their defining use + hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => {} } + + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let param_env = tcx.param_env(def_id); + + tcx.infer_ctxt().enter(move |infcx| { + let inh = Inherited::new(infcx, def_id); + let infcx = &inh.infcx; + let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs); + + let misc_cause = traits::ObligationCause::misc(span, hir_id); + + let (_, opaque_type_map) = inh.register_infer_ok_obligations( + infcx.instantiate_opaque_types(def_id.to_def_id(), hir_id, param_env, &opaque_ty, span), + ); + + for (def_id, opaque_defn) in opaque_type_map { + match infcx + .at(&misc_cause, param_env) + .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, opaque_defn.substs)) + { + Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok), + Err(ty_err) => tcx.sess.delay_span_bug( + opaque_defn.definition_span, + &format!( + "could not unify `{}` with revealed type:\n{}", + opaque_defn.concrete_ty, ty_err, + ), + ), + } + } + + // Check that all obligations are satisfied by the implementation's + // version. + if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) { + infcx.report_fulfillment_errors(errors, None, false); + } + + // Finally, resolve all regions. This catches wily misuses of + // lifetime parameters. + let fcx = FnCtxt::new(&inh, param_env, hir_id); + fcx.regionck_item(hir_id, span, &[]); + }); } pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index 566e390a31e48..b0e9e33a6c38e 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -9,7 +9,6 @@ LL | fn baz() -> impl Bar { | = note: expected associated type `::Item` found type `i32` - = note: the return type of a function must have a statically known size help: consider constraining the associated type `::Item` to `i32` | LL | fn bar() -> impl Bar { diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index d808a5939bbe7..8cd0e40c8cf84 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -3,9 +3,6 @@ error[E0277]: `()` is not a future | LL | fn get_future() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future -LL | -LL | panic!() - | -------- this returned value is of type `!` | = help: the trait `Future` is not implemented for `()` = note: the return type of a function must have a statically known size diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index 440ea0a38e6b9..f5d023ab781ff 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -30,7 +30,6 @@ help: consider moving this into a `let` binding to create a shorter lived borrow | LL | match client.status() { | ^^^^^^^^^^^^^^^ - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-70818.stderr b/src/test/ui/async-await/issue-70818.stderr index 364194bea100e..20ee22e448c91 100644 --- a/src/test/ui/async-await/issue-70818.stderr +++ b/src/test/ui/async-await/issue-70818.stderr @@ -12,7 +12,6 @@ note: captured value is not `Send` | LL | async { (ty, ty1) } | ^^^ has type `U` which is not `Send` - = note: the return type of a function must have a statically known size help: consider restricting type parameter `U` | LL | fn foo(ty: T, ty1: U) -> impl Future + Send { diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 260fbb2ec7e6a..8f6f87f78de70 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -15,7 +15,6 @@ LL | fn foo() -> impl Generator { | = note: expected enum `std::result::Result<{integer}, _>` found type `i32` - = note: the return type of a function must have a statically known size error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index 03aba10cc79b4..a7d06c71663de 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -15,7 +15,6 @@ LL | fn foo_fail() -> impl FooLike { | = note: expected type `()` found associated type `::Assoc` - = note: the return type of a function must have a statically known size help: consider constraining the associated type `::Assoc` to `()` | LL | fn foo_fail>() -> impl FooLike { @@ -35,7 +34,6 @@ LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | = note: expected type `()` found associated type `>::Assoc` - = note: the return type of a function must have a statically known size help: consider constraining the associated type `>::Assoc` to `()` | LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr index db49d988bb8eb..64c536cf1fe30 100644 --- a/src/test/ui/impl-trait/issue-55872-1.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.stderr @@ -14,7 +14,6 @@ LL | type E = impl Copy; | ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` | = note: required because it appears within the type `(S, T)` - = note: the return type of a function must have a statically known size help: consider further restricting this bound | LL | impl Bar for S { @@ -27,7 +26,6 @@ LL | type E = impl Copy; | ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` | = note: required because it appears within the type `(S, T)` - = note: the return type of a function must have a statically known size help: consider further restricting this bound | LL | fn foo() -> Self::E { diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr index 867f8f0496c03..835d479f28f19 100644 --- a/src/test/ui/issues-71798.stderr +++ b/src/test/ui/issues-71798.stderr @@ -9,8 +9,6 @@ error[E0277]: `u32` is not a future | LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future -LL | *x - | -- this returned value is of type `u32` | = help: the trait `Future` is not implemented for `u32` = note: the return type of a function must have a statically known size diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index e43fb6d0edfb9..c3d597bec2e40 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -3,11 +3,6 @@ error[E0277]: the trait bound `std::result::Result<(), _>: Future` is not satisf | LL | fn foo() -> impl Future> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>` -LL | -LL | Ok(()) - | ------ this returned value is of type `std::result::Result<(), _>` - | - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr index c652faafad461..670f76867ce45 100644 --- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr +++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr @@ -3,11 +3,6 @@ error[E0277]: the trait bound `(): T` is not satisfied | LL | fn should_ret_unit() -> impl T { | ^^^^^^ the trait `T` is not implemented for `()` -LL | -LL | panic!() - | -------- this returned value is of type `!` - | - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr index cc3a2b9419caf..d826222a06ae5 100644 --- a/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr +++ b/src/test/ui/suggestions/impl-trait-return-trailing-semicolon.stderr @@ -5,8 +5,6 @@ LL | fn foo() -> impl Bar { | ^^^^^^^^ the trait `Bar` is not implemented for `()` LL | 5; | - consider removing this semicolon - | - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs new file mode 100644 index 0000000000000..5566f40f96095 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs @@ -0,0 +1,19 @@ +// Make sure that we check that impl trait types implement the traits that they +// claim to. + +#![feature(type_alias_impl_trait)] + +type X = impl Clone; +//~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied + +fn f(t: T) -> X { + t +} + +fn g(o : Option>) -> Option> { + o.clone() +} + +fn main() { + g(None::>); +} diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr new file mode 100644 index 0000000000000..e20130007ee8b --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied + --> $DIR/bounds-are-checked-2.rs:6:13 + | +LL | type X = impl Clone; + | ^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | type X = impl Clone; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs new file mode 100644 index 0000000000000..759bf4f4f0dee --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.rs @@ -0,0 +1,25 @@ +// Make sure that we check that impl trait types implement the traits that they +// claim to. + +#![feature(type_alias_impl_trait)] + +type X<'a> = impl Into<&'static str> + From<&'a str>; +//~^ ERROR mismatched types + +fn f<'a: 'static>(t: &'a str) -> X<'a> { + //~^ WARNING unnecessary lifetime parameter + t +} + +fn extend_lt<'a>(o: &'a str) -> &'static str { + X::<'_>::from(o).into() +} + +fn main() { + let r = + { + let s = "abcdef".to_string(); + extend_lt(&s) + }; + println!("{}", r); +} diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr new file mode 100644 index 0000000000000..42468b91a6267 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -0,0 +1,26 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/bounds-are-checked.rs:9:6 + | +LL | fn f<'a: 'static>(t: &'a str) -> X<'a> { + | ^^^^^^^^^^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error[E0308]: mismatched types + --> $DIR/bounds-are-checked.rs:6:14 + | +LL | type X<'a> = impl Into<&'static str> + From<&'a str>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected type `std::convert::From<&'a str>` + found type `std::convert::From<&'static str>` +note: the lifetime `'a` as defined on the item at 6:8... + --> $DIR/bounds-are-checked.rs:6:8 + | +LL | type X<'a> = impl Into<&'static str> + From<&'a str>; + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs index 898dab1b0b960..c17d595dbb3ad 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs @@ -1,11 +1,11 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(type_alias_impl_trait)] use std::fmt::Debug; fn main() {} -type Two = impl Debug; +type Two = impl Debug; fn two(t: T, _: U) -> Two { (t, 4u32) diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs index 712a6539f0153..feebf81eef2a7 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs @@ -1,11 +1,11 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(type_alias_impl_trait)] use std::fmt::Debug; fn main() {} -type Two = impl Debug; +type Two = impl Debug; fn two(t: T, u: U) -> Two { (t, t) diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr index bf2d612fcdb41..905248fb33755 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr @@ -15,7 +15,6 @@ LL | type Item = impl Bug; | = help: the following implementations were found: <&() as Bug> - = note: the return type of a function must have a statically known size error: could not find defining uses --> $DIR/issue-60371.rs:8:17 diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr index 9ad181b3684c6..8615b3f741bf5 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -6,7 +6,6 @@ LL | type Closure = impl FnOnce(); | = note: expected opaque type `impl FnOnce<()>` found unit type `()` - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs index 209134acf01f9..80192d19af98b 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait.rs @@ -70,14 +70,14 @@ fn my_other_iter(u: U) -> MyOtherIter { } trait Trait {} -type GenericBound<'a, T: Trait> = impl Sized + 'a; +type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a; fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> { t } mod pass_through { - pub type Passthrough = impl Sized + 'static; + pub type Passthrough = impl Sized + 'static; fn define_passthrough(t: T) -> Passthrough { t From 1b0799157450a2ef6c50b4ffb9c0c40ee105fe8f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jun 2020 17:36:41 +0100 Subject: [PATCH 08/34] Check associated type bounds for object safety violations --- .../src/traits/object_safety.rs | 101 +++++++++++------- .../ui/object-safety/object-safety-bounds.rs | 12 +++ .../object-safety/object-safety-bounds.stderr | 14 +++ 3 files changed, 88 insertions(+), 39 deletions(-) create mode 100644 src/test/ui/object-safety/object-safety-bounds.rs create mode 100644 src/test/ui/object-safety/object-safety-bounds.stderr diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 8fc14cb29971d..0e43f1655ddb2 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -160,6 +160,10 @@ fn object_safety_violations_for_trait( if !spans.is_empty() { violations.push(ObjectSafetyViolation::SupertraitSelf(spans)); } + let spans = bounds_reference_self(tcx, trait_def_id); + if !spans.is_empty() { + violations.push(ObjectSafetyViolation::SupertraitSelf(spans)); + } violations.extend( tcx.associated_items(trait_def_id) @@ -239,51 +243,70 @@ fn predicates_reference_self( } else { tcx.predicates_of(trait_def_id) }; - let self_ty = tcx.types.self_param; - let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into()); predicates .predicates .iter() - .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp)) - .filter_map(|(predicate, &sp)| { - match predicate.skip_binders() { - ty::PredicateAtom::Trait(ref data, _) => { - // In the case of a trait predicate, we can skip the "self" type. - if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None } - } - ty::PredicateAtom::Projection(ref data) => { - // And similarly for projections. This should be redundant with - // the previous check because any projection should have a - // matching `Trait` predicate with the same inputs, but we do - // the check to be safe. - // - // Note that we *do* allow projection *outputs* to contain - // `self` (i.e., `trait Foo: Bar { type Result; }`), - // we just require the user to specify *both* outputs - // in the object type (i.e., `dyn Foo`). - // - // This is ALT2 in issue #56288, see that for discussion of the - // possible alternatives. - if data.projection_ty.trait_ref(tcx).substs[1..].iter().any(has_self_ty) { - Some(sp) - } else { - None - } - } - ty::PredicateAtom::WellFormed(..) - | ty::PredicateAtom::ObjectSafe(..) - | ty::PredicateAtom::TypeOutlives(..) - | ty::PredicateAtom::RegionOutlives(..) - | ty::PredicateAtom::ClosureKind(..) - | ty::PredicateAtom::Subtype(..) - | ty::PredicateAtom::ConstEvaluatable(..) - | ty::PredicateAtom::ConstEquate(..) - | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None, - } - }) + .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), *sp)) + .filter_map(|predicate| predicate_references_self(tcx, predicate)) + .collect() +} + +fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> { + let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id)); + tcx.associated_items(trait_def_id) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Type) + .flat_map(|item| tcx.explicit_item_bounds(item.def_id)) + .map(|(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), *sp)) + .filter_map(|predicate| predicate_references_self(tcx, predicate)) .collect() } +fn predicate_references_self( + tcx: TyCtxt<'tcx>, + (predicate, sp): (ty::Predicate<'tcx>, Span), +) -> Option { + let self_ty = tcx.types.self_param; + let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into()); + match predicate.skip_binders() { + ty::PredicateAtom::Trait(ref data, _) => { + // In the case of a trait predicate, we can skip the "self" type. + if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None } + } + ty::PredicateAtom::Projection(ref data) => { + // And similarly for projections. This should be redundant with + // the previous check because any projection should have a + // matching `Trait` predicate with the same inputs, but we do + // the check to be safe. + // + // It's also won't be redundant if we allow type-generic associated + // types for trait objects. + // + // Note that we *do* allow projection *outputs* to contain + // `self` (i.e., `trait Foo: Bar { type Result; }`), + // we just require the user to specify *both* outputs + // in the object type (i.e., `dyn Foo`). + // + // This is ALT2 in issue #56288, see that for discussion of the + // possible alternatives. + if data.projection_ty.trait_ref(tcx).substs[1..].iter().any(has_self_ty) { + Some(sp) + } else { + None + } + } + ty::PredicateAtom::WellFormed(..) + | ty::PredicateAtom::ObjectSafe(..) + | ty::PredicateAtom::TypeOutlives(..) + | ty::PredicateAtom::RegionOutlives(..) + | ty::PredicateAtom::ClosureKind(..) + | ty::PredicateAtom::Subtype(..) + | ty::PredicateAtom::ConstEvaluatable(..) + | ty::PredicateAtom::ConstEquate(..) + | ty::PredicateAtom::TypeWellFormedFromEnv(..) => None, + } +} + fn trait_has_sized_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { generics_require_sized_self(tcx, trait_def_id) } diff --git a/src/test/ui/object-safety/object-safety-bounds.rs b/src/test/ui/object-safety/object-safety-bounds.rs new file mode 100644 index 0000000000000..44bd369324a4b --- /dev/null +++ b/src/test/ui/object-safety/object-safety-bounds.rs @@ -0,0 +1,12 @@ +// Traits with bounds mentioning `Self` are not object safe + +trait X { + type U: PartialEq; +} + +fn f() -> Box> { + //~^ ERROR the trait `X` cannot be made into an object + loop {} +} + +fn main() {} diff --git a/src/test/ui/object-safety/object-safety-bounds.stderr b/src/test/ui/object-safety/object-safety-bounds.stderr new file mode 100644 index 0000000000000..af4548308631e --- /dev/null +++ b/src/test/ui/object-safety/object-safety-bounds.stderr @@ -0,0 +1,14 @@ +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/object-safety-bounds.rs:7:11 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type U: PartialEq; + | --------------- ...because it uses `Self` as a type parameter in this +... +LL | fn f() -> Box> { + | ^^^^^^^^^^^^^^^^^^^ the trait `X` cannot be made into an object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. From d4d9e7f67fa8661757769b8d87f6343ca8251f24 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jun 2020 20:27:59 +0100 Subject: [PATCH 09/34] Remove unused part of return value from `replace_bound_vars_with_placeholders` --- compiler/rustc_infer/src/infer/higher_ranked/mod.rs | 11 ++++------- compiler/rustc_infer/src/infer/mod.rs | 9 ++------- compiler/rustc_trait_selection/src/traits/project.rs | 2 +- .../src/traits/select/confirmation.rs | 4 ++-- .../rustc_trait_selection/src/traits/select/mod.rs | 6 +++--- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index ea19dff7db125..e3365e8590b5e 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -2,7 +2,7 @@ //! the end of the file for details. use super::combine::CombineFields; -use super::{HigherRankedType, InferCtxt, PlaceholderMap}; +use super::{HigherRankedType, InferCtxt}; use crate::infer::CombinedSnapshot; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; @@ -33,7 +33,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { self.infcx.commit_if_ok(|_| { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. - let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(&b); + let b_prime = self.infcx.replace_bound_vars_with_placeholders(&b); // Next, we instantiate each bound region in the subtype // with a fresh region variable. These region variables -- @@ -66,10 +66,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// the [rustc dev guide]. /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html - pub fn replace_bound_vars_with_placeholders( - &self, - binder: &ty::Binder, - ) -> (T, PlaceholderMap<'tcx>) + pub fn replace_bound_vars_with_placeholders(&self, binder: &ty::Binder) -> T where T: TypeFoldable<'tcx>, { @@ -122,7 +119,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { next_universe, binder, result, map, ); - (result, map) + result } /// See `infer::region_constraints::RegionConstraintCollector::leak_check`. diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 07a55c7f859c3..9742f5e234651 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -351,11 +351,6 @@ pub struct InferCtxt<'a, 'tcx> { universe: Cell, } -/// A map returned by `replace_bound_vars_with_placeholders()` -/// indicating the placeholder region that each late-bound region was -/// replaced with. -pub type PlaceholderMap<'tcx> = BTreeMap>; - /// See the `error_reporting` module for more details. #[derive(Clone, Debug, PartialEq, Eq, TypeFoldable)] pub enum ValuePairs<'tcx> { @@ -992,7 +987,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } Some(self.commit_if_ok(|_snapshot| { - let (ty::SubtypePredicate { a_is_expected, a, b }, _) = + let ty::SubtypePredicate { a_is_expected, a, b } = self.replace_bound_vars_with_placeholders(&predicate); let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; @@ -1007,7 +1002,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) -> UnitResult<'tcx> { self.commit_if_ok(|_snapshot| { - let (ty::OutlivesPredicate(r_a, r_b), _) = + let ty::OutlivesPredicate(r_a, r_b) = self.replace_bound_vars_with_placeholders(&predicate); let origin = SubregionOrigin::from_obligation_cause(cause, || { RelateRegionParamBound(cause.span) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 71e34d2dcd05f..f23d3bb761154 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -167,7 +167,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx(); infcx.commit_if_ok(|_snapshot| { - let (placeholder_predicate, _) = + let placeholder_predicate = infcx.replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation = obligation.with(placeholder_predicate); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 625bb5d7a44fa..76be4a8045282 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -253,7 +253,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_obligations: Vec> = self.infcx.commit_unconditionally(|_| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let (trait_ref, _) = + let trait_ref = self.infcx.replace_bound_vars_with_placeholders(&poly_trait_ref); let cause = obligation.derived_cause(ImplDerivedObligation); self.impl_or_trait_obligations( @@ -437,7 +437,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("confirm_trait_alias_candidate({:?}, {:?})", obligation, alias_def_id); self.infcx.commit_unconditionally(|_| { - let (predicate, _) = + let predicate = self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2d6ccfe031e5b..ab4226c4ed6e2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1161,7 +1161,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, ) -> Option> { let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate); - let (placeholder_trait_predicate, _) = + let placeholder_trait_predicate = self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( "match_projection_obligation_against_definition_bounds: \ @@ -1640,7 +1640,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ self.infcx.commit_unconditionally(|_| { - let (placeholder_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty); + let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(&ty); let Normalized { value: normalized_ty, mut obligations } = ensure_sufficient_stack(|| { project::normalize_with_depth( @@ -1708,7 +1708,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - let (placeholder_obligation, _) = + let placeholder_obligation = self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; From 0a76584dcc6dd6ae8f32f905dde379a99da7e516 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jun 2020 20:29:08 +0100 Subject: [PATCH 10/34] Move some code from rustc_typeck to rustc_trait_selection --- .../rustc_trait_selection/src/traits/mod.rs | 1 + .../rustc_trait_selection/src/traits/util.rs | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index c93087a18cf04..d819740b59665 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -59,6 +59,7 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; pub use self::specialize::{specialization_graph, translate_substs, OverlapError}; pub use self::structural_match::search_for_structural_match_violation; pub use self::structural_match::NonStructuralMatchTy; +pub use self::util::subst_assoc_item_bound; pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{ diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index f626bb0b7e365..3d52453a5c77a 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -11,6 +11,8 @@ use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; pub use rustc_infer::traits::util::*; +use std::iter; + /////////////////////////////////////////////////////////////////////////// // `TraitAliasExpander` iterator /////////////////////////////////////////////////////////////////////////// @@ -357,6 +359,59 @@ pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool { assoc_item.defaultness.is_final() && tcx.impl_defaultness(assoc_item.container.id()).is_final() } +/// Map a bound from an associated item to apply to some other type. +/// For example, given the following trait +/// +/// trait X { type Y<'a>: PartialEq } +/// +/// Say that we know that `<() as X>::Y<'c> = i32` and we need to check that +/// the `PartialEq` bound applies. This function would return +/// `i32: PartialEq`. +pub fn subst_assoc_item_bound<'tcx>( + tcx: TyCtxt<'tcx>, + bound: ty::Predicate<'tcx>, + normalized_projection_ty: Ty<'tcx>, + assoc_item_substs: &[GenericArg<'tcx>], +) -> ty::Predicate<'tcx> { + let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| { + tcx.mk_substs( + iter::once(normalized_projection_ty.into()) + .chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, assoc_item_substs))), + ) + }; + + match bound.kind() { + ty::PredicateKind::Trait(poly_tr, c) => poly_tr + .map_bound(|tr| { + let trait_substs = translate_predicate_substs(tr.trait_ref.substs); + ty::TraitRef { def_id: tr.def_id(), substs: trait_substs } + }) + .with_constness(*c) + .to_predicate(tcx), + ty::PredicateKind::Projection(poly_projection) => poly_projection + .map_bound(|projection| { + let projection_substs = translate_predicate_substs(projection.projection_ty.substs); + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + substs: projection_substs, + item_def_id: projection.projection_ty.item_def_id, + }, + ty: projection.ty.subst(tcx, assoc_item_substs), + } + }) + .to_predicate(tcx), + ty::PredicateKind::TypeOutlives(poly_outlives) => poly_outlives + .map_bound(|outlives| { + ty::OutlivesPredicate( + normalized_projection_ty, + outlives.1.subst(tcx, assoc_item_substs), + ) + }) + .to_predicate(tcx), + _ => bug!("unexepected projection bound: `{:?}`", bound), + } +} + pub enum TupleArgumentsFlag { Yes, No, From 2bdf723da7c465e052a1b1fc448c0014c46b9e51 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 28 Jun 2020 20:34:56 +0100 Subject: [PATCH 11/34] Ensure that associated types for trait objects satisfy their bounds --- .../src/traits/select/confirmation.rs | 64 +++++++++++++++---- src/test/ui/issues/issue-41139.rs | 4 +- src/test/ui/issues/issue-41139.stderr | 13 ++-- .../ui/traits/check-trait-object-bounds-1.rs | 14 ++++ .../traits/check-trait-object-bounds-1.stderr | 12 ++++ .../traits/check-trait-object-bounds-2-ok.rs | 15 +++++ .../ui/traits/check-trait-object-bounds-2.rs | 15 +++++ .../traits/check-trait-object-bounds-2.stderr | 14 ++++ .../ui/traits/check-trait-object-bounds-3.rs | 21 ++++++ .../traits/check-trait-object-bounds-3.stderr | 12 ++++ 10 files changed, 166 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/traits/check-trait-object-bounds-1.rs create mode 100644 src/test/ui/traits/check-trait-object-bounds-1.stderr create mode 100644 src/test/ui/traits/check-trait-object-bounds-2-ok.rs create mode 100644 src/test/ui/traits/check-trait-object-bounds-2.rs create mode 100644 src/test/ui/traits/check-trait-object-bounds-2.stderr create mode 100644 src/test/ui/traits/check-trait-object-bounds-3.rs create mode 100644 src/test/ui/traits/check-trait-object-bounds-3.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 76be4a8045282..1ed4cca107e77 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -9,7 +9,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; -use rustc_infer::infer::InferOk; +use rustc_infer::infer::{self, InferOk}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness}; @@ -342,21 +342,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> ImplSourceObjectData<'tcx, PredicateObligation<'tcx>> { debug!("confirm_object_candidate({:?})", obligation); - // FIXME(nmatsakis) skipping binder here seems wrong -- we should - // probably flatten the binder from the obligation and the binder - // from the object. Have to try to make a broken test case that - // results. - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); - let poly_trait_ref = match self_ty.kind() { - ty::Dynamic(data, ..) => data - .principal() - .unwrap_or_else(|| { - span_bug!(obligation.cause.span, "object candidate with no principal") - }) - .with_self_ty(self.tcx(), self_ty), + let self_ty = self.infcx.replace_bound_vars_with_placeholders(&obligation.self_ty()); + let data = match self_ty.kind() { + ty::Dynamic(data, ..) => data, _ => span_bug!(obligation.cause.span, "object candidate with non-object"), }; + let poly_trait_ref = data + .principal() + .unwrap_or_else(|| { + span_bug!(obligation.cause.span, "object candidate with no principal") + }) + .with_self_ty(self.tcx(), self_ty); + let mut upcast_trait_ref = None; let mut nested = vec![]; let vtable_base; @@ -388,6 +386,46 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum(); } + for bound in data.skip_binder() { + match bound { + ty::ExistentialPredicate::Projection(projection) => { + // This maybe belongs in wf, but that can't (doesn't) handle + // higher-ranked things. + // Prevent, e.g., `dyn Iterator`. + // FIXME(generic_associated_types): We need some way to + // ensure that for `dyn for<'a> X = &'a ()>` the + // bound holds for all `'a`. + let (infer_projection, _) = self.infcx.replace_bound_vars_with_fresh_vars( + obligation.cause.span, + infer::HigherRankedType, + &ty::Binder::bind(projection), + ); + let substs: Vec<_> = + iter::once(self_ty.into()).chain(infer_projection.substs).collect(); + let bounds = + self.tcx().item_bounds(projection.item_def_id).iter().map(|bound| { + // In the example above, `bound` is `::Item: Sized` + // `subst_bound` is `str: Sized`. + let subst_bound = util::subst_assoc_item_bound( + self.tcx(), + bound, + infer_projection.ty, + &substs, + ); + Obligation::new( + obligation.cause.clone(), + obligation.param_env.clone(), + subst_bound, + ) + }); + debug!("confirm_object_candidate: adding bounds: {:?}", bounds); + nested.extend(bounds); + } + ty::ExistentialPredicate::Trait(_) | ty::ExistentialPredicate::AutoTrait(_) => {} + } + } + + debug!("confirm_object_candidate: nested: {:?}", nested); ImplSourceObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base, nested } } diff --git a/src/test/ui/issues/issue-41139.rs b/src/test/ui/issues/issue-41139.rs index 4814232607cf8..ebdc5cb6dbe5d 100644 --- a/src/test/ui/issues/issue-41139.rs +++ b/src/test/ui/issues/issue-41139.rs @@ -3,6 +3,8 @@ trait Trait {} fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { panic!("") } fn main() { + // This isn't great. The issue here is that `dyn Trait` is not sized, so + // `dyn Fn() -> dyn Trait` is not well-formed. let t : &dyn Trait = &get_function()(); - //~^ ERROR cannot move a value of type dyn Trait + //~^ ERROR expected function, found `&dyn std::ops::Fn() -> (dyn Trait + 'static)` } diff --git a/src/test/ui/issues/issue-41139.stderr b/src/test/ui/issues/issue-41139.stderr index 829d0cfa72ca7..083c413c316df 100644 --- a/src/test/ui/issues/issue-41139.stderr +++ b/src/test/ui/issues/issue-41139.stderr @@ -1,9 +1,14 @@ -error[E0161]: cannot move a value of type dyn Trait: the size of dyn Trait cannot be statically determined - --> $DIR/issue-41139.rs:6:27 +error[E0618]: expected function, found `&dyn std::ops::Fn() -> (dyn Trait + 'static)` + --> $DIR/issue-41139.rs:8:27 | +LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { panic!("") } + | ----------------------------------------------------------------- `get_function` defined here returns `&dyn std::ops::Fn() -> (dyn Trait + 'static)` +... LL | let t : &dyn Trait = &get_function()(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^-- + | | + | call expression requires function error: aborting due to previous error -For more information about this error, try `rustc --explain E0161`. +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/traits/check-trait-object-bounds-1.rs b/src/test/ui/traits/check-trait-object-bounds-1.rs new file mode 100644 index 0000000000000..ad908a750b431 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-1.rs @@ -0,0 +1,14 @@ +// Check that we validate associated type bounds for trait objects + +trait X { + type Y: Clone; +} + +fn f() { + None::.clone(); +} + +fn main() { + f::>(); + //~^ ERROR the trait bound `str: std::clone::Clone` is not satisfied +} diff --git a/src/test/ui/traits/check-trait-object-bounds-1.stderr b/src/test/ui/traits/check-trait-object-bounds-1.stderr new file mode 100644 index 0000000000000..c53c91d42a754 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-1.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied + --> $DIR/check-trait-object-bounds-1.rs:12:5 + | +LL | fn f() { + | - required by this bound in `f` +... +LL | f::>(); + | ^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/check-trait-object-bounds-2-ok.rs b/src/test/ui/traits/check-trait-object-bounds-2-ok.rs new file mode 100644 index 0000000000000..1422dda276b9b --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-2-ok.rs @@ -0,0 +1,15 @@ +// Make sure that we're handling bound lifetimes correctly when validating trait +// bounds. +// run-pass + +trait X<'a> { + type F: FnOnce(&i32) -> &'a i32; +} + +fn f X<'r> + ?Sized>() { + None::.map(|f| f(&0)); +} + +fn main() { + f:: X<'x, F = fn(&i32) -> &'x i32>>(); +} diff --git a/src/test/ui/traits/check-trait-object-bounds-2.rs b/src/test/ui/traits/check-trait-object-bounds-2.rs new file mode 100644 index 0000000000000..f825008c6a233 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-2.rs @@ -0,0 +1,15 @@ +// Check that we validate associated type bounds for trait objects when they +// have bound lifetimes + +trait X<'a> { + type F: FnOnce(&i32) -> &'a i32; +} + +fn f X<'r> + ?Sized>() { + None::.map(|f| f(&0)); +} + +fn main() { + f:: X<'x, F = i32>>(); + //~^ expected a `std::ops::FnOnce<(&i32,)>` closure, found `i32` +} diff --git a/src/test/ui/traits/check-trait-object-bounds-2.stderr b/src/test/ui/traits/check-trait-object-bounds-2.stderr new file mode 100644 index 0000000000000..1241fc8cb51df --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: expected a `std::ops::FnOnce<(&i32,)>` closure, found `i32` + --> $DIR/check-trait-object-bounds-2.rs:13:5 + | +LL | fn f X<'r> + ?Sized>() { + | ------------- required by this bound in `f` +... +LL | f:: X<'x, F = i32>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32` + | + = help: the trait `for<'r> std::ops::FnOnce<(&'r i32,)>` is not implemented for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/check-trait-object-bounds-3.rs b/src/test/ui/traits/check-trait-object-bounds-3.rs new file mode 100644 index 0000000000000..d05aa14f2cf5f --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-3.rs @@ -0,0 +1,21 @@ +// Check that we validate associated type bounds for trait objects + +trait X<'a> { + type Y: Into<&'static str> + From<&'a str>; +} + +fn f<'a, T: X<'a> + ?Sized>(s: &'a str) -> &'static str { + T::Y::from(s).into() +} + +pub fn main() { + let z; + { + let s = String::from("abcdef"); + z = f::>(&s); + //~^ ERROR `s` does not live long enough + } + + println!("{}", z) +} + diff --git a/src/test/ui/traits/check-trait-object-bounds-3.stderr b/src/test/ui/traits/check-trait-object-bounds-3.stderr new file mode 100644 index 0000000000000..e2a4341454a63 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-3.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied + --> $DIR/check-trait-object-bounds-3.rs:12:5 + | +LL | fn f() { + | - required by this bound in `f` +... +LL | f::>(); + | ^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 042464f75ae1272260b24896b3266a5c1ba62c6b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 29 Jun 2020 22:15:11 +0100 Subject: [PATCH 12/34] Fix tests and bootstrap --- .../rustc_trait_selection/src/opaque_types.rs | 3 +- .../rustc_trait_selection/src/traits/wf.rs | 21 +++++++--- .../rustc_typeck/src/check/compare_method.rs | 1 + compiler/rustc_typeck/src/collect.rs | 16 +++++++- src/test/incremental/issue-54242.rs | 2 +- ...mplify_arm.id_try.SimplifyArmIdentity.diff | 14 +++---- ...implify_arm.id_try.SimplifyBranchSame.diff | 14 +++---- ...y.try_identity.DestinationPropagation.diff | 2 +- ..._try.try_identity.SimplifyArmIdentity.diff | 2 +- ....try_identity.SimplifyBranchSame.after.mir | 2 +- .../param-env-normalize-cycle.rs | 39 +++++++++++++++++++ .../feature-gate-associated_type_bounds.rs | 1 + ...feature-gate-associated_type_bounds.stderr | 34 ++++++++-------- src/test/ui/for/for-c-in-str.rs | 18 +++++---- src/test/ui/for/for-c-in-str.stderr | 2 +- .../auxiliary/foo_defn.rs | 8 ++++ .../cross-crate-bounds.rs | 32 +++++++++++++++ .../cross-crate-bounds.stderr | 14 +++++++ .../ui/traits/check-trait-object-bounds-3.rs | 1 - .../traits/check-trait-object-bounds-3.stderr | 19 +++++---- 20 files changed, 182 insertions(+), 63 deletions(-) create mode 100644 src/test/ui/associated-types/param-env-normalize-cycle.rs create mode 100644 src/test/ui/generic-associated-types/auxiliary/foo_defn.rs create mode 100644 src/test/ui/generic-associated-types/cross-crate-bounds.rs create mode 100644 src/test/ui/generic-associated-types/cross-crate-bounds.stderr diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 0621d9bf09e13..610c6fd7e35f8 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1170,8 +1170,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // This also instantiates nested instances of `impl Trait`. let predicate = self.instantiate_opaque_types_in_map(&predicate); - let cause = - traits::ObligationCause::new(span, self.body_id, traits::MiscObligation); + let cause = traits::ObligationCause::new(span, self.body_id, traits::MiscObligation); // Require that the predicate holds for the concrete type. debug!("instantiate_opaque_types: predicate={:?}", predicate); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 165e45aa94ae4..9fd635c64a0f3 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -241,18 +241,27 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { traits::ObligationCause::new(self.span, self.body_id, code) } - fn normalize(&mut self) -> Vec> { + fn normalize(mut self) -> Vec> { let cause = self.cause(traits::MiscObligation); let infcx = &mut self.infcx; let param_env = self.param_env; let mut obligations = Vec::with_capacity(self.out.len()); - for pred in &self.out { - assert!(!pred.has_escaping_bound_vars()); + for mut obligation in self.out { + assert!(!obligation.has_escaping_bound_vars()); let mut selcx = traits::SelectionContext::new(infcx); let i = obligations.len(); - let value = - traits::normalize_to(&mut selcx, param_env, cause.clone(), pred, &mut obligations); - obligations.insert(i, value); + // Don't normalize the whole obligation, the param env is either + // already normalized, or we're currently normalizing the + // param_env. Either way we should only normalize the predicate. + let normalized_predicate = traits::normalize_to( + &mut selcx, + param_env, + cause.clone(), + &obligation.predicate, + &mut obligations, + ); + obligation.predicate = normalized_predicate; + obligations.insert(i, obligation); } obligations } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index b059b03bc058a..ee21167ff975d 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1256,6 +1256,7 @@ pub fn check_type_bounds<'tcx>( ); debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); + inh.register_predicates(obligations); inh.register_predicate(obligation); } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 737bc3a753d75..ac4abd6a51166 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1787,10 +1787,22 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat }) => { if impl_trait_fn.is_some() { // return-position impl trait - // TODO: Investigate why we have this special case? + // + // We don't inherit predicates from the parent here: + // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` + // then the return type is `f::<'static, T>::{{opaque}}`. + // + // If we inherited the predicates of `f` then we would + // require that `T: 'static` to show that the return + // type is well-formed. + // + // The only way to have something with this opaque type + // is from the return type of the containing function, + // which will ensure that the function's predicates + // hold. return ty::GenericPredicates { parent: None, predicates: &[] }; } else { - // type alias impl trait + // type-alias impl trait generics } } diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs index 25dc7cdf129d5..a95cf776c2e01 100644 --- a/src/test/incremental/issue-54242.rs +++ b/src/test/incremental/issue-54242.rs @@ -1,6 +1,6 @@ // revisions: rpass cfail -trait Tr { +trait Tr where Self::Arr: Sized { type Arr; const C: usize = 0; diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff index 33245b65e8c42..6ec2b98bf5b26 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff @@ -1,6 +1,6 @@ - // MIR for `id_try` before SimplifyArmIdentity + // MIR for `id_try` after SimplifyArmIdentity - + fn id_try(_1: std::result::Result) -> std::result::Result { debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49 @@ -42,7 +42,7 @@ scope 6 { debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL } - + bb0: { StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 @@ -53,7 +53,7 @@ _5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 } - + bb1: { - StorageLive(_10); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - _10 = ((_3 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 @@ -69,11 +69,11 @@ StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } - + bb2: { unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 } - + bb3: { - StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 @@ -94,9 +94,9 @@ StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } - + bb4: { return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } } - + diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff index eb2521c8ba08e..172fb04a3cca8 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff @@ -1,6 +1,6 @@ - // MIR for `id_try` before SimplifyBranchSame + // MIR for `id_try` after SimplifyBranchSame - + fn id_try(_1: std::result::Result) -> std::result::Result { debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49 @@ -37,7 +37,7 @@ scope 6 { debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL } - + bb0: { StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 @@ -49,7 +49,7 @@ - switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + goto -> bb1; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 } - + bb1: { _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 @@ -57,20 +57,20 @@ - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + goto -> bb2; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } - + bb2: { - unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - } -- +- - bb3: { - _0 = move _3; // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 - StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 - } -- +- - bb4: { return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } } - + diff --git a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff index 2af387a73b762..12a6617cc5a27 100644 --- a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff +++ b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff @@ -25,7 +25,7 @@ } scope 8 { debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15 + let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 } } } diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff index 6fa14f1e0d840..534836eff7b2d 100644 --- a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff @@ -29,7 +29,7 @@ scope 8 { - debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15 + let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 } } } diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir index ceb5bfb19a133..d2e37bf4e12eb 100644 --- a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir +++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir @@ -24,7 +24,7 @@ fn try_identity(_1: std::result::Result) -> std::result::Result ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:14: 8:15 + let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 } } } diff --git a/src/test/ui/associated-types/param-env-normalize-cycle.rs b/src/test/ui/associated-types/param-env-normalize-cycle.rs new file mode 100644 index 0000000000000..12db595ed2572 --- /dev/null +++ b/src/test/ui/associated-types/param-env-normalize-cycle.rs @@ -0,0 +1,39 @@ +// Minimized case from typenum that didn't compile because: +// - We tried to normalize the ParamEnv of the second impl +// - This requires trying to normalize `GrEq>>` +// - This requires proving `Square>: Sized` so that the first impl +// applies +// - This requires Providing `Square>` is well-formed, so that we +// can use the `Sized` bound on `Mul::Output` +// - This requires proving `Square: Mul` +// - But first we tried normalizing the whole obligation, including the +// ParamEnv, which leads to a cycle error. + +// check-pass + +trait PrivateSquareRoot {} + +pub trait Mul { + type Output; +} + +pub trait IsGreaterOrEqual { + type Output; +} + +pub type Square = ::Output; +pub type GrEq = >::Output; + +impl IsGreaterOrEqual for A { + type Output = (); +} + +impl PrivateSquareRoot for U +where + U: Mul, + Square: Mul, + GrEq>>: Sized, +{ +} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs index c5c8c5c1eca1f..7dac2b26cce09 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -1,3 +1,4 @@ +// ignore-tidy-linelength // compile-flags: -Zsave-analysis // This is also a regression test for #69415 and the above flag is needed. diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr index db78e287d65e0..03011bd1e32d1 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -1,5 +1,5 @@ error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:15:22 + --> $DIR/feature-gate-associated_type_bounds.rs:16:22 | LL | type A: Iterator; | ^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | type A: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:19:22 + --> $DIR/feature-gate-associated_type_bounds.rs:20:22 | LL | type B: Iterator; | ^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | type B: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:23:20 + --> $DIR/feature-gate-associated_type_bounds.rs:24:20 | LL | struct _St1> { | ^^^^^^^^ @@ -26,7 +26,7 @@ LL | struct _St1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:30:18 + --> $DIR/feature-gate-associated_type_bounds.rs:31:18 | LL | enum _En1> { | ^^^^^^^^ @@ -35,7 +35,7 @@ LL | enum _En1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:37:19 + --> $DIR/feature-gate-associated_type_bounds.rs:38:19 | LL | union _Un1> { | ^^^^^^^^ @@ -44,7 +44,7 @@ LL | union _Un1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:44:37 + --> $DIR/feature-gate-associated_type_bounds.rs:45:37 | LL | type _TaWhere1 where T: Iterator = T; | ^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | type _TaWhere1 where T: Iterator = T; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:47:22 + --> $DIR/feature-gate-associated_type_bounds.rs:48:22 | LL | fn _apit(_: impl Tr1) {} | ^^^^^^^^^ @@ -62,7 +62,7 @@ LL | fn _apit(_: impl Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:49:26 + --> $DIR/feature-gate-associated_type_bounds.rs:50:26 | LL | fn _apit_dyn(_: &dyn Tr1) {} | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | fn _apit_dyn(_: &dyn Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:52:24 + --> $DIR/feature-gate-associated_type_bounds.rs:53:24 | LL | fn _rpit() -> impl Tr1 { S1 } | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | fn _rpit() -> impl Tr1 { S1 } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:55:31 + --> $DIR/feature-gate-associated_type_bounds.rs:56:31 | LL | fn _rpit_dyn() -> Box> { Box::new(S1) } | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | fn _rpit_dyn() -> Box> { Box::new(S1) } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:58:23 + --> $DIR/feature-gate-associated_type_bounds.rs:59:23 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -98,7 +98,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:64:24 + --> $DIR/feature-gate-associated_type_bounds.rs:65:24 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -107,7 +107,7 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:71:21 + --> $DIR/feature-gate-associated_type_bounds.rs:72:21 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^ @@ -116,7 +116,7 @@ LL | let _: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:58:14 + --> $DIR/feature-gate-associated_type_bounds.rs:59:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:64:15 + --> $DIR/feature-gate-associated_type_bounds.rs:65:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:71:12 + --> $DIR/feature-gate-associated_type_bounds.rs:72:12 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -140,7 +140,7 @@ LL | let _: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0277]: the trait bound `<::A as std::iter::Iterator>::Item: std::marker::Copy` is not satisfied - --> $DIR/feature-gate-associated_type_bounds.rs:15:28 + --> $DIR/feature-gate-associated_type_bounds.rs:16:28 | LL | type A: Iterator; | ^^^^ the trait `std::marker::Copy` is not implemented for `<::A as std::iter::Iterator>::Item` diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs index df66127c6041a..8aca8c388d4a3 100644 --- a/src/test/ui/for/for-c-in-str.rs +++ b/src/test/ui/for/for-c-in-str.rs @@ -1,14 +1,16 @@ -// E0277 should point exclusively at line 14, not the entire for loop span +// E0277 should point exclusively at line 6, not the entire for loop span + +// ignore-tidy-linelength fn main() { for c in "asdf" { - //~^ ERROR `&str` is not an iterator - //~| NOTE `&str` is not an iterator - //~| HELP the trait `Iterator` is not implemented for `&str` - //~| NOTE required by `into_iter` - //~| NOTE in this expansion of desugaring of `for` loop - //~| NOTE in this expansion of desugaring of `for` loop - //~| NOTE in this expansion of desugaring of `for` loop + //~^ ERROR `&str` is not an iterator + //~| NOTE `&str` is not an iterator + //~| HELP the trait `Iterator` is not implemented for `&str` + //~| NOTE required by `into_iter` + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop println!(); } } diff --git a/src/test/ui/for/for-c-in-str.stderr b/src/test/ui/for/for-c-in-str.stderr index b0f959ba0273c..f991e08e518cc 100644 --- a/src/test/ui/for/for-c-in-str.stderr +++ b/src/test/ui/for/for-c-in-str.stderr @@ -1,5 +1,5 @@ error[E0277]: `&str` is not an iterator - --> $DIR/for-c-in-str.rs:4:14 + --> $DIR/for-c-in-str.rs:6:14 | LL | for c in "asdf" { | ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` diff --git a/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs b/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs new file mode 100644 index 0000000000000..0e8e14852d9db --- /dev/null +++ b/src/test/ui/generic-associated-types/auxiliary/foo_defn.rs @@ -0,0 +1,8 @@ +#![feature(generic_associated_types)] + +use std::{future::Future, pin::Pin}; + +pub trait Foo { + type Bar: AsRef<()>; + fn foo(&self) -> Pin + '_>>; +} diff --git a/src/test/ui/generic-associated-types/cross-crate-bounds.rs b/src/test/ui/generic-associated-types/cross-crate-bounds.rs new file mode 100644 index 0000000000000..4e2bab38c88a3 --- /dev/null +++ b/src/test/ui/generic-associated-types/cross-crate-bounds.rs @@ -0,0 +1,32 @@ +// regression test for #73816 +// We handled bounds differently when `feature(generic_associated_types)` was enabled + +// edition:2018 +// aux-build:foo_defn.rs + +extern crate foo_defn; + +use foo_defn::Foo; +use std::{future::Future, pin::Pin}; + +pub struct FooImpl; + +impl Foo for FooImpl { + type Bar = (); + //~^ ERROR the trait bound `(): std::convert::AsRef<()>` is not satisfied + fn foo(&self) -> Pin + '_>> { + panic!() + } +} + +async fn foo() { + bar(&FooImpl).await; +} + +async fn bar(foo: &F) { + foo.foo().await.as_ref(); +} + +fn main() { + // futures::executor::block_on(foo()); +} diff --git a/src/test/ui/generic-associated-types/cross-crate-bounds.stderr b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr new file mode 100644 index 0000000000000..5fd2750868fef --- /dev/null +++ b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `(): std::convert::AsRef<()>` is not satisfied + --> $DIR/cross-crate-bounds.rs:15:5 + | +LL | type Bar = (); + | ^^^^^^^^^^^^^^ the trait `std::convert::AsRef<()>` is not implemented for `()` + | + ::: $DIR/auxiliary/foo_defn.rs:6:15 + | +LL | type Bar: AsRef<()>; + | --------- required by this bound in `foo_defn::Foo::Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/check-trait-object-bounds-3.rs b/src/test/ui/traits/check-trait-object-bounds-3.rs index d05aa14f2cf5f..ba04fd93accec 100644 --- a/src/test/ui/traits/check-trait-object-bounds-3.rs +++ b/src/test/ui/traits/check-trait-object-bounds-3.rs @@ -18,4 +18,3 @@ pub fn main() { println!("{}", z) } - diff --git a/src/test/ui/traits/check-trait-object-bounds-3.stderr b/src/test/ui/traits/check-trait-object-bounds-3.stderr index e2a4341454a63..ade552c4bab41 100644 --- a/src/test/ui/traits/check-trait-object-bounds-3.stderr +++ b/src/test/ui/traits/check-trait-object-bounds-3.stderr @@ -1,12 +1,15 @@ -error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied - --> $DIR/check-trait-object-bounds-3.rs:12:5 +error[E0597]: `s` does not live long enough + --> $DIR/check-trait-object-bounds-3.rs:15:34 | -LL | fn f() { - | - required by this bound in `f` -... -LL | f::>(); - | ^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str` +LL | z = f::>(&s); + | ---------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `s` is borrowed for `'static` +LL | +LL | } + | - `s` dropped here while still borrowed error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0597`. From 0dda4154bd254b629567739085471b8e50676c83 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 30 Jun 2020 22:41:57 +0100 Subject: [PATCH 13/34] Fix tools --- .../src/error_codes/E0284.md | 38 +++++++--------- src/librustdoc/clean/mod.rs | 44 +++++++++---------- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/html/render/mod.rs | 2 +- .../clippy_lints/src/future_not_send.rs | 15 +++++-- .../clippy/clippy_lints/src/methods/mod.rs | 6 ++- .../clippy/clippy_lints/src/utils/mod.rs | 5 ++- 7 files changed, 55 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0284.md b/compiler/rustc_error_codes/src/error_codes/E0284.md index a1ffa2bda0050..18519b471b203 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0284.md +++ b/compiler/rustc_error_codes/src/error_codes/E0284.md @@ -5,37 +5,29 @@ as the `collect` method for `Iterator`s. For example: ```compile_fail,E0284 -fn foo() -> Result { - let results = [Ok(true), Ok(false), Err(())].iter().cloned(); - let v: Vec = results.collect()?; - // Do things with v... - Ok(true) +fn main() { + let n: u32 = 1; + let mut d: u64 = 2; + d = d + n.into(); } ``` -Here we have an iterator `results` over `Result`. -Hence, `results.collect()` can return any type implementing -`FromIterator>`. On the other hand, the -`?` operator can accept any type implementing `Try`. +Here we have an addition of `d` and `n.into()`. Hence, `n.into()` can return +any type `T` where `u64: Add`. On the other hand, the `into` method can +rteurn any type where `u32: Into`. -The author of this code probably wants `collect()` to return a -`Result, ()>`, but the compiler can't be sure -that there isn't another type `T` implementing both `Try` and -`FromIterator>` in scope such that -`T::Ok == Vec`. Hence, this code is ambiguous and an error -is returned. +The author of this code probably wants `into()` to return a `u64`, but the +compiler can't be sure that there isn't another type `T` where both +`u32: Into` and `u64: Add`. To resolve this error, use a concrete type for the intermediate expression: ``` -fn foo() -> Result { - let results = [Ok(true), Ok(false), Err(())].iter().cloned(); - let v = { - let temp: Result, ()> = results.collect(); - temp? - }; - // Do things with v... - Ok(true) +fn main() { + let n: u32 = 1; + let mut d: u64 = 2; + let m: u64 = n.into(); + d = d + m; } ``` diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 788bb5e787b82..ac1e2b467045c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -21,7 +21,7 @@ use rustc_middle::bug; use rustc_middle::middle::resolve_lifetime as rl; use rustc_middle::middle::stability; use rustc_middle::ty::fold::TypeFolder; -use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt}; use rustc_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn}; use rustc_span::hygiene::MacroKind; @@ -1268,13 +1268,10 @@ impl Clean for ty::AssocItem { ty::AssocKind::Type => { let my_name = self.ident.name.clean(cx); - if let ty::TraitContainer(did) = self.container { - // When loading a cross-crate associated type, the bounds for this type - // are actually located on the trait/impl itself, so we need to load - // all of the generics from there and then look for bounds that are - // applied to this associated type in question. - let predicates = cx.tcx.explicit_predicates_of(did); - let generics = (cx.tcx.generics_of(did), predicates).clean(cx); + if let ty::TraitContainer(_) = self.container { + let bounds = cx.tcx.explicit_item_bounds(self.def_id); + let predicates = ty::GenericPredicates { parent: None, predicates: bounds }; + let generics = (cx.tcx.generics_of(self.def_id), predicates).clean(cx); let mut bounds = generics .where_predicates .iter() @@ -1678,19 +1675,22 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Opaque(def_id, substs) => { // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, - // by looking up the projections associated with the def_id. - let predicates_of = cx.tcx.explicit_predicates_of(def_id); + // by looking up the bounds associated with the def_id. let substs = cx.tcx.lift(&substs).expect("Opaque lift failed"); - let bounds = predicates_of.instantiate(cx.tcx, substs); + let bounds = cx + .tcx + .explicit_item_bounds(def_id) + .iter() + .map(|(bound, _)| bound.subst(cx.tcx, substs)) + .collect::>(); let mut regions = vec![]; let mut has_sized = false; let mut bounds = bounds - .predicates .iter() - .filter_map(|predicate| { + .filter_map(|bound| { // Note: The substs of opaque types can contain unbound variables, // meaning that we have to use `ignore_quantifiers_with_unbound_vars` here. - let trait_ref = match predicate.bound_atom(cx.tcx).skip_binder() { + let trait_ref = match bound.bound_atom(cx.tcx).skip_binder() { ty::PredicateAtom::Trait(tr, _constness) => { ty::Binder::bind(tr.trait_ref) } @@ -1711,11 +1711,10 @@ impl<'tcx> Clean for Ty<'tcx> { } let bounds: Vec<_> = bounds - .predicates .iter() - .filter_map(|pred| { + .filter_map(|bound| { if let ty::PredicateAtom::Projection(proj) = - pred.bound_atom(cx.tcx).skip_binder() + bound.bound_atom(cx.tcx).skip_binder() { if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() @@ -2067,13 +2066,10 @@ impl Clean for doctree::OpaqueTy<'_> { visibility: self.vis.clean(cx), stability: cx.stability(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx), - inner: OpaqueTyItem( - OpaqueTy { - bounds: self.opaque_ty.bounds.clean(cx), - generics: self.opaque_ty.generics.clean(cx), - }, - false, - ), + inner: OpaqueTyItem(OpaqueTy { + bounds: self.opaque_ty.bounds.clean(cx), + generics: self.opaque_ty.generics.clean(cx), + }), } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d70446d257498..bb6f449e3550d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -252,7 +252,7 @@ pub enum ItemEnum { FunctionItem(Function), ModuleItem(Module), TypedefItem(Typedef, bool /* is associated type */), - OpaqueTyItem(OpaqueTy, bool /* is associated type */), + OpaqueTyItem(OpaqueTy), StaticItem(Static), ConstantItem(Constant), TraitItem(Trait), diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8b5ba7a239c5f..afd1dc596427f 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1709,7 +1709,7 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache) clean::ConstantItem(ref c) => item_constant(buf, cx, item, c), clean::ForeignTypeItem => item_foreign_type(buf, cx, item, cache), clean::KeywordItem(_) => item_keyword(buf, cx, item), - clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e, cache), + clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e, cache), clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta, cache), _ => { // We don't generate pages for any other type. diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index 2ab257ca88e3b..d2a322e1223c6 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -3,6 +3,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, HirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{Opaque, PredicateAtom::Trait}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, Span}; @@ -62,9 +63,10 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } let ret_ty = utils::return_ty(cx, hir_id); if let Opaque(id, subst) = *ret_ty.kind() { - let preds = cx.tcx.predicates_of(id).instantiate(cx.tcx, subst); + let preds = cx.tcx.explicit_item_bounds(id); let mut is_future = false; - for p in preds.predicates { + for &(p, _span) in preds { + let p = p.subst(cx.tcx, subst); if let Some(trait_ref) = p.to_opt_poly_trait_ref() { if Some(trait_ref.def_id()) == cx.tcx.lang_items().future_trait() { is_future = true; @@ -90,8 +92,13 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { |db| { cx.tcx.infer_ctxt().enter(|infcx| { for FulfillmentError { obligation, .. } in send_errors { - infcx.maybe_note_obligation_cause_for_async_await(db, &obligation); - if let Trait(trait_pred, _) = obligation.predicate.skip_binders() { + infcx.maybe_note_obligation_cause_for_async_await( + db, + &obligation, + ); + if let Trait(trait_pred, _) = + obligation.predicate.skip_binders() + { db.note(&format!( "`{}` doesn't implement `{}`", trait_pred.self_ty(), diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index dadd0f8ebb7c8..e0651f9ab5d6c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -1667,8 +1667,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods { // if return type is impl trait, check the associated types if let ty::Opaque(def_id, _) = *ret_ty.kind() { // one of the associated types must be Self - for &(predicate, _span) in cx.tcx.predicates_of(def_id).predicates { - if let ty::PredicateAtom::Projection(projection_predicate) = predicate.skip_binders() { + for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { + if let ty::PredicateAtom::Projection(projection_predicate) = + predicate.skip_binders() + { // walk the associated type and check for Self if contains_ty(projection_predicate.ty, self_ty) { return; diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index 96d9905027b62..247effde19b9c 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -1285,9 +1285,10 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), ty::Opaque(ref def_id, _) => { - for (predicate, _) in cx.tcx.predicates_of(*def_id).predicates { + for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { if let ty::PredicateAtom::Trait(trait_predicate, _) = predicate.skip_binders() { - if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() { + if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() + { return true; } } From 21eccbb587d7e9cff6fc6ebbd2a8844e8993fee4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 1 Jul 2020 21:56:35 +0100 Subject: [PATCH 14/34] Fix ICE --- .../src/traits/select/confirmation.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 1ed4cca107e77..319217e8fdc44 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -342,7 +342,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> ImplSourceObjectData<'tcx, PredicateObligation<'tcx>> { debug!("confirm_object_candidate({:?})", obligation); - let self_ty = self.infcx.replace_bound_vars_with_placeholders(&obligation.self_ty()); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + let self_ty = self.infcx.replace_bound_vars_with_placeholders(&self_ty); let data = match self_ty.kind() { ty::Dynamic(data, ..) => data, _ => span_bug!(obligation.cause.span, "object candidate with non-object"), @@ -448,7 +449,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) .map_bound(|(trait_ref, _)| trait_ref); - let Normalized { value: trait_ref, obligations } = ensure_sufficient_stack(|| { + let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { project::normalize_with_depth( self, obligation.param_env, @@ -458,12 +459,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }); - self.confirm_poly_trait_refs( + obligations.extend(self.confirm_poly_trait_refs( obligation.cause.clone(), obligation.param_env, obligation.predicate.to_poly_trait_ref(), trait_ref, - )?; + )?); Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested: obligations }) } From 8787090964e33cd633671025d9acf20dfeaf8765 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 2 Jul 2020 21:45:28 +0100 Subject: [PATCH 15/34] Address review comments --- compiler/rustc_middle/src/query/mod.rs | 24 +++++++++++++++---- .../src/traits/select/mod.rs | 5 ++++ .../rustc_trait_selection/src/traits/util.rs | 16 ++++++++++--- .../rustc_trait_selection/src/traits/wf.rs | 20 +++++++++++++++- compiler/rustc_typeck/src/check/check.rs | 12 ++++++++++ 5 files changed, 69 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8b94818d8e651..808a0793a94f4 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -159,9 +159,8 @@ rustc_queries! { /// Returns the list of bounds that can be used for /// `SelectionCandidate::ProjectionCandidate` and /// `ProjectionTyCandidate::TraitDef`. - /// Specifically this is the bounds (equivalent to) those - /// written on the trait's type definition, or those - /// after the `impl` keyword + /// Specifically this is the bounds written on the trait's type + /// definition, or those after the `impl` keyword /// /// type X: Bound + 'lt /// ^^^^^^^^^^^ @@ -169,11 +168,28 @@ rustc_queries! { /// ^^^^^^^^^^^^^^^ /// /// `key` is the `DefId` of the associated type or opaque type. + /// + /// Bounds from the parent (e.g. with nested impl trait) are not included. query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } } - /// Elaborated the predicates from `explicit_item_bounds`. + /// Elaborated version of the predicates from `explicit_item_bounds`. + /// + /// Example for + /// + /// trait MyTrait { + /// type MyAType: Eq + ?Sized` + /// } + /// + /// `explicit_item_bounds` returns `[::MyAType: Eq]`, + /// and `item_bounds` returns + /// [ + /// ::MyAType: Eq, + /// ::MyAType: PartialEq<::MyAType> + /// ] + /// + /// Bounds from the parent (e.g. with nested impl trait) are not included. query item_bounds(key: DefId) -> &'tcx ty::List> { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ab4226c4ed6e2..af90bc80d4d98 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1156,6 +1156,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate); } + /// Matches a predicate against the bounds of its self type. + /// + /// Given an obligation like `::Bar: Baz` where the self type is + /// a projection, look at the bounds of `T::Bar`, see if we can find a + /// `Baz` bound and it there is one it returns it. fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 3d52453a5c77a..0a4ce34c7f8e0 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -6,7 +6,7 @@ use smallvec::SmallVec; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; pub use rustc_infer::traits::util::*; @@ -365,14 +365,24 @@ pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool { /// trait X { type Y<'a>: PartialEq } /// /// Say that we know that `<() as X>::Y<'c> = i32` and we need to check that -/// the `PartialEq` bound applies. This function would return -/// `i32: PartialEq`. +/// the `PartialEq` bound applies. We would then call this function with: +/// +/// - `bound` = `>::Y<'a>: PartialEq` +/// - `normalized_projection_ty` = `i32` +/// - `assoc_item_substs` = `[(), B, 'c]` +/// +/// This method would then return `i32: PartialEq`. pub fn subst_assoc_item_bound<'tcx>( tcx: TyCtxt<'tcx>, bound: ty::Predicate<'tcx>, normalized_projection_ty: Ty<'tcx>, assoc_item_substs: &[GenericArg<'tcx>], ) -> ty::Predicate<'tcx> { + // We're substituting these inside the closure passed to map_bound, so they + // can't have escaping bound regions. + assert!(!normalized_projection_ty.has_escaping_bound_vars()); + assert!(!assoc_item_substs.iter().all(|arg| arg.has_escaping_bound_vars())); + let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| { tcx.mk_substs( iter::once(normalized_projection_ty.into()) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 9fd635c64a0f3..df816bbd34810 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -337,8 +337,26 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// into `self.out`. fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) { // A projection is well-formed if - // (a) its predicates hold + // + // (a) its predicates hold (*) // (b) its substs are wf + // + // (*) The predicates of an associated type include the predicates of + // the trait that it's contained in. For example, given + // + // trait A: Clone { + // type X where T: Copy; + // } + // + // The predicates of `<() as A>::X` are: + // [ + // `(): Sized` + // `(): Clone` + // `(): A` + // `i32: Sized` + // `i32: Clone` + // `i32: Copy` + // ] let obligations = self.nominal_obligations(data.item_def_id, data.substs); self.out.extend(obligations); diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index f5e6ff07b88b7..fbb19617c7fcf 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -524,6 +524,18 @@ pub(super) fn check_opaque_for_cycles<'tcx>( } /// Check that the concrete type behind `impl Trait` actually implements `Trait`. +/// +/// This is mostly checked at the places that specify the opaque type, but we +/// check those cases in the `param_env` of that function, which may have +/// bounds not on this opaque type: +/// +/// type X = impl Clone +/// fn f(t: T) -> X { +/// t +/// } +/// +/// Without this check the above code is incorrectly accepted: we would ICE if +/// some tried, for example, to clone an `Option>`. fn check_opaque_meets_bounds<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, From 582ccec1c577eedf6394078e93366714273f922b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 4 Jul 2020 12:15:04 +0100 Subject: [PATCH 16/34] Remove predicates on associated types from traits These need to only be bounds to avoid cycle errors in trait checking. --- compiler/rustc_middle/src/query/mod.rs | 18 +++++ compiler/rustc_typeck/src/collect.rs | 68 ++++++++++++++++++- .../rustc_typeck/src/collect/item_bounds.rs | 2 +- src/test/incremental/issue-54242.rs | 5 +- .../assoc-type-bound-through-where-clause.rs | 16 +++++ .../point-at-type-on-obligation-failure-2.rs | 14 ++-- ...int-at-type-on-obligation-failure-2.stderr | 33 ++++++--- .../point-at-type-on-obligation-failure-3.rs | 11 --- ...int-at-type-on-obligation-failure-3.stderr | 12 ---- .../issue-67765-async-diagnostic.stderr | 4 +- 10 files changed, 141 insertions(+), 42 deletions(-) create mode 100644 src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs delete mode 100644 src/test/ui/associated-types/point-at-type-on-obligation-failure-3.rs delete mode 100644 src/test/ui/associated-types/point-at-type-on-obligation-failure-3.stderr diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 808a0793a94f4..240f2c0792cf2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -391,6 +391,24 @@ rustc_queries! { desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } } + /// Returns everything that looks like a predicate written explicitly + /// by the user on a trait item. + /// + /// Traits are unusual, because predicates on associated types are + /// converted into bounds on that type for backwards compatibility: + /// + /// trait X where Self::U: Copy { type U; } + /// + /// becomes + /// + /// trait X { type U: Copy; } + /// + /// `explicit_predicates_of` and `explicit_item_bounds` will then take + /// the appropriate subsets of the predicates here. + query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> { + desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key.to_def_id()) } + } + /// Returns the predicates written explicitly by the user. query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index ac4abd6a51166..7e125481671f5 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -77,6 +77,7 @@ pub fn provide(providers: &mut Providers) { projection_ty_from_predicates, explicit_predicates_of, super_predicates_of, + trait_explicit_predicates_and_bounds, type_param_predicates, trait_def, adt_def, @@ -1731,7 +1732,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { /// Returns a list of user-specified type predicates for the definition with ID `def_id`. /// N.B., this does not include any implied/inferred constraints. -fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { +fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { use rustc_hir::*; debug!("explicit_predicates_of(def_id={:?})", def_id); @@ -2116,6 +2117,71 @@ fn const_evaluatable_predicates_of<'tcx>( collector.preds } +fn trait_explicit_predicates_and_bounds( + tcx: TyCtxt<'_>, + def_id: LocalDefId, +) -> ty::GenericPredicates<'_> { + assert_eq!(tcx.def_kind(def_id), DefKind::Trait); + gather_explicit_predicates_of(tcx, def_id.to_def_id()) +} + +fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { + if let DefKind::Trait = tcx.def_kind(def_id) { + // Remove bounds on associated types from the predicates, they will be + // returned by `explicit_item_bounds`. + let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local()); + let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id); + + let is_assoc_item_ty = |ty: Ty<'_>| { + // For a predicate from a where clause to become a bound on an + // associated type: + // * It must use the identity substs of the item. + // * Since any generic parameters on the item are not in scope, + // this means that the item is not a GAT, and its identity substs + // are the same as the trait's. + // * It must be an associated type for this trait (*not* a + // supertrait). + if let ty::Projection(projection) = ty.kind { + if projection.substs == trait_identity_substs + && tcx.associated_item(projection.item_def_id).container.id() == def_id + { + true + } else { + false + } + } else { + false + } + }; + + let predicates: Vec<_> = predicates_and_bounds + .predicates + .iter() + .copied() + .filter(|(pred, _)| match pred.kind() { + ty::PredicateKind::Trait(tr, _) => !is_assoc_item_ty(tr.skip_binder().self_ty()), + ty::PredicateKind::Projection(proj) => { + !is_assoc_item_ty(proj.skip_binder().projection_ty.self_ty()) + } + ty::PredicateKind::TypeOutlives(outlives) => { + !is_assoc_item_ty(outlives.skip_binder().0) + } + _ => true, + }) + .collect(); + if predicates.len() == predicates_and_bounds.predicates.len() { + predicates_and_bounds + } else { + ty::GenericPredicates { + parent: predicates_and_bounds.parent, + predicates: tcx.arena.alloc_slice(&predicates), + } + } + } else { + gather_explicit_predicates_of(tcx, def_id) + } +} + fn projection_ty_from_predicates( tcx: TyCtxt<'tcx>, key: ( diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 96e331ba516de..c9af86f70fd92 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -34,7 +34,7 @@ fn associated_type_bounds<'tcx>( ); let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id(); - let trait_predicates = tcx.predicates_of(trait_def_id); + let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.kind() { diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs index a95cf776c2e01..9e449de0cf5ac 100644 --- a/src/test/incremental/issue-54242.rs +++ b/src/test/incremental/issue-54242.rs @@ -1,6 +1,9 @@ // revisions: rpass cfail -trait Tr where Self::Arr: Sized { +trait Tr +where + (Self::Arr,): Sized, +{ type Arr; const C: usize = 0; diff --git a/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs b/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs new file mode 100644 index 0000000000000..49f11140741c2 --- /dev/null +++ b/src/test/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs @@ -0,0 +1,16 @@ +// Check that `where Self::Output: Copy` is turned into a bound on `Op::Output`. + +//check-pass + +trait Op +where + Self::Output: Copy, +{ + type Output; +} + +fn duplicate(x: T::Output) -> (T::Output, T::Output) { + (x, x) +} + +fn main() {} diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs index 4bd3ccab8343a..4b3d6e9d6067f 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs @@ -5,12 +5,13 @@ trait Foo { } impl Foo for () { - // Doesn't error because we abort compilation after the errors below. - // See point-at-type-on-obligation-failure-3.rs - type Assoc = bool; + type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied } -trait Baz where Self::Assoc: Bar { +trait Baz +where + Self::Assoc: Bar, +{ type Assoc; } @@ -18,7 +19,10 @@ impl Baz for () { type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied } -trait Bat where ::Assoc: Bar { +trait Bat +where + ::Assoc: Bar, +{ type Assoc; } diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr index f4971105499e3..b23030d7cb52b 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr @@ -1,21 +1,36 @@ error[E0277]: the trait bound `bool: Bar` is not satisfied - --> $DIR/point-at-type-on-obligation-failure-2.rs:18:18 + --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 | -LL | trait Baz where Self::Assoc: Bar { - | --- required by this bound in `Baz` +LL | type Assoc: Bar; + | --- required by this bound in `Foo::Assoc` ... LL | type Assoc = bool; - | ^^^^ the trait `Bar` is not implemented for `bool` + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` error[E0277]: the trait bound `bool: Bar` is not satisfied - --> $DIR/point-at-type-on-obligation-failure-2.rs:26:18 + --> $DIR/point-at-type-on-obligation-failure-2.rs:19:5 | -LL | trait Bat where ::Assoc: Bar { - | --- required by this bound in `Bat` +LL | Self::Assoc: Bar, + | --- required by this bound in `Baz::Assoc` +LL | { +LL | type Assoc; + | ----- required by a bound in this ... LL | type Assoc = bool; - | ^^^^ the trait `Bar` is not implemented for `bool` + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` -error: aborting due to 2 previous errors +error[E0277]: the trait bound `bool: Bar` is not satisfied + --> $DIR/point-at-type-on-obligation-failure-2.rs:30:5 + | +LL | ::Assoc: Bar, + | --- required by this bound in `Bat::Assoc` +LL | { +LL | type Assoc; + | ----- required by a bound in this +... +LL | type Assoc = bool; + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.rs deleted file mode 100644 index 9360d96f05e17..0000000000000 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.rs +++ /dev/null @@ -1,11 +0,0 @@ -trait Bar {} - -trait Foo { - type Assoc: Bar; -} - -impl Foo for () { - type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied -} - -fn main() {} diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.stderr deleted file mode 100644 index 6ab3d94e10248..0000000000000 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-3.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0277]: the trait bound `bool: Bar` is not satisfied - --> $DIR/point-at-type-on-obligation-failure-3.rs:8:5 - | -LL | type Assoc: Bar; - | --- required by this bound in `Foo::Assoc` -... -LL | type Assoc = bool; - | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-67765-async-diagnostic.stderr b/src/test/ui/async-await/issue-67765-async-diagnostic.stderr index 78253042bee1c..832b736ad8642 100644 --- a/src/test/ui/async-await/issue-67765-async-diagnostic.stderr +++ b/src/test/ui/async-await/issue-67765-async-diagnostic.stderr @@ -1,11 +1,11 @@ error[E0515]: cannot return value referencing local variable `s` - --> $DIR/issue-67765-async-diagnostic.rs:13:11 + --> $DIR/issue-67765-async-diagnostic.rs:13:5 | LL | let b = &s[..]; | - `s` is borrowed here LL | LL | Err(b)?; - | ^ returns a value referencing data owned by the current function + | ^^^^^^^ returns a value referencing data owned by the current function error: aborting due to previous error From f52b2d88903036beb0533b04011064575b3abd36 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 5 Jul 2020 12:16:25 +0100 Subject: [PATCH 17/34] Avoid cycle in nested obligations for object candidate Bounds of the form `type Future: Future` exist in some ecosystem crates. To validate these bounds for trait objects we need to normalize `Self::Result` in a way that doesn't cause a cycle. --- compiler/rustc_middle/src/ty/sty.rs | 1 + .../src/traits/select/confirmation.rs | 227 ++++++++++++++---- .../ui/traits/check-trait-object-bounds-4.rs | 17 ++ .../traits/check-trait-object-bounds-4.stderr | 12 + .../ui/traits/check-trait-object-bounds-5.rs | 27 +++ .../traits/check-trait-object-bounds-5.stderr | 12 + .../ui/traits/check-trait-object-bounds-6.rs | 24 ++ .../traits/check-trait-object-bounds-6.stderr | 12 + .../ui/traits/trait-object-bounds-cycle-1.rs | 24 ++ .../ui/traits/trait-object-bounds-cycle-2.rs | 28 +++ .../ui/traits/trait-object-bounds-cycle-3.rs | 25 ++ .../ui/traits/trait-object-bounds-cycle-4.rs | 25 ++ 12 files changed, 382 insertions(+), 52 deletions(-) create mode 100644 src/test/ui/traits/check-trait-object-bounds-4.rs create mode 100644 src/test/ui/traits/check-trait-object-bounds-4.stderr create mode 100644 src/test/ui/traits/check-trait-object-bounds-5.rs create mode 100644 src/test/ui/traits/check-trait-object-bounds-5.stderr create mode 100644 src/test/ui/traits/check-trait-object-bounds-6.rs create mode 100644 src/test/ui/traits/check-trait-object-bounds-6.stderr create mode 100644 src/test/ui/traits/trait-object-bounds-cycle-1.rs create mode 100644 src/test/ui/traits/trait-object-bounds-cycle-2.rs create mode 100644 src/test/ui/traits/trait-object-bounds-cycle-3.rs create mode 100644 src/test/ui/traits/trait-object-bounds-cycle-4.rs diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5cba451ea6e3c..09895605dca86 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1513,6 +1513,7 @@ impl<'tcx> ExistentialProjection<'tcx> { /// then this function would return a `exists T. T: Iterator` existential trait /// reference. pub fn trait_ref(&self, tcx: TyCtxt<'_>) -> ty::ExistentialTraitRef<'tcx> { + // FIXME(generic_associated_types): truncate substs to have the right length. let def_id = tcx.associated_item(self.item_def_id).container.id(); ty::ExistentialTraitRef { def_id, substs: self.substs } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 319217e8fdc44..59399133dff8a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -9,13 +9,15 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; +use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::{self, InferOk}; +use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness}; use rustc_span::def_id::DefId; -use crate::traits::project::{self, normalize_with_depth}; +use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::select::TraitObligationExt; use crate::traits::util; use crate::traits::util::{closure_trait_ref_and_return_type, predicate_for_trait_def}; @@ -340,16 +342,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, ) -> ImplSourceObjectData<'tcx, PredicateObligation<'tcx>> { + let tcx = self.tcx(); debug!("confirm_object_candidate({:?})", obligation); - let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); - let self_ty = self.infcx.replace_bound_vars_with_placeholders(&self_ty); + let trait_predicate = + self.infcx.replace_bound_vars_with_placeholders(&obligation.predicate); + let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty()); + let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref); let data = match self_ty.kind() { - ty::Dynamic(data, ..) => data, + ty::Dynamic(data, ..) => { + self.infcx + .replace_bound_vars_with_fresh_vars( + obligation.cause.span, + HigherRankedType, + data, + ) + .0 + } _ => span_bug!(obligation.cause.span, "object candidate with non-object"), }; - let poly_trait_ref = data + let object_trait_ref = data .principal() .unwrap_or_else(|| { span_bug!(obligation.cause.span, "object candidate with no principal") @@ -361,24 +374,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let vtable_base; { - let tcx = self.tcx(); - // We want to find the first supertrait in the list of // supertraits that we can unify with, and do that // unification. We know that there is exactly one in the list // where we can unify, because otherwise select would have // reported an ambiguity. (When we do find a match, also // record it for later.) - let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while(|&t| { - match self.infcx.commit_if_ok(|_| self.match_poly_trait_ref(obligation, t)) { - Ok(obligations) => { - upcast_trait_ref = Some(t); - nested.extend(obligations); - false + let nonmatching = util::supertraits(tcx, ty::Binder::dummy(object_trait_ref)) + .take_while(|&t| { + match self.infcx.commit_if_ok(|_| { + self.infcx + .at(&obligation.cause, obligation.param_env) + .sup(obligation_trait_ref, t) + .map(|InferOk { obligations, .. }| obligations) + .map_err(|_| ()) + }) { + Ok(obligations) => { + upcast_trait_ref = Some(t); + nested.extend(obligations); + false + } + Err(_) => true, } - Err(_) => true, - } - }); + }); // Additionally, for each of the non-matching predicates that // we pass over, we sum up the set of number of vtable @@ -387,47 +405,105 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum(); } - for bound in data.skip_binder() { - match bound { - ty::ExistentialPredicate::Projection(projection) => { - // This maybe belongs in wf, but that can't (doesn't) handle - // higher-ranked things. - // Prevent, e.g., `dyn Iterator`. - // FIXME(generic_associated_types): We need some way to - // ensure that for `dyn for<'a> X = &'a ()>` the - // bound holds for all `'a`. - let (infer_projection, _) = self.infcx.replace_bound_vars_with_fresh_vars( + // Check supertraits hold + nested.extend(util::supertraits(tcx, obligation_trait_ref).skip(1).map(|super_trait| { + Obligation::new( + obligation.cause.clone(), + obligation.param_env, + super_trait.without_const().to_predicate(tcx), + ) + })); + + let upcast_trait_ref = upcast_trait_ref.unwrap(); + + let assoc_types: Vec<_> = tcx + .associated_items(upcast_trait_ref.def_id()) + .in_definition_order() + .filter_map( + |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None }, + ) + .collect(); + + if !assoc_types.is_empty() { + let predicates: Vec<_> = + data.iter() + .filter_map(|pred| match pred { + ty::ExistentialPredicate::Projection(proj) => { + if assoc_types.contains(&proj.item_def_id) { + match self.infcx.commit_if_ok(|_| { + self.infcx + .at(&obligation.cause, obligation.param_env) + .sup( + ty::Binder::dummy( + proj.trait_ref(tcx).with_self_ty(tcx, self_ty), + ), + upcast_trait_ref, + ) + .map(|InferOk { obligations, .. }| obligations) + .map_err(|_| ()) + }) { + Ok(obligations) => { + nested.extend(obligations); + Some(proj) + } + Err(_) => None, + } + } else { + None + } + } + ty::ExistentialPredicate::AutoTrait(_) + | ty::ExistentialPredicate::Trait(_) => None, + }) + .collect(); + + let upcast_trait_ref = upcast_trait_ref + .no_bound_vars() + .expect("sup shouldn't return binder with bound vars"); + let mut normalizer = ObjectAssociatedTypeNormalizer { + infcx: self.infcx, + object_ty: self_ty, + object_bounds: &predicates, + param_env: obligation.param_env, + cause: &obligation.cause, + nested: &mut nested, + }; + for assoc_type in assoc_types { + if !tcx.generics_of(assoc_type).params.is_empty() { + // FIXME(generic_associated_types) generate placeholders to + // extend the trait substs. + tcx.sess.span_fatal( obligation.cause.span, - infer::HigherRankedType, - &ty::Binder::bind(projection), + "generic associated types in trait objects are not supported yet", ); - let substs: Vec<_> = - iter::once(self_ty.into()).chain(infer_projection.substs).collect(); - let bounds = - self.tcx().item_bounds(projection.item_def_id).iter().map(|bound| { - // In the example above, `bound` is `::Item: Sized` - // `subst_bound` is `str: Sized`. - let subst_bound = util::subst_assoc_item_bound( - self.tcx(), - bound, - infer_projection.ty, - &substs, - ); - Obligation::new( - obligation.cause.clone(), - obligation.param_env.clone(), - subst_bound, - ) - }); - debug!("confirm_object_candidate: adding bounds: {:?}", bounds); - nested.extend(bounds); } - ty::ExistentialPredicate::Trait(_) | ty::ExistentialPredicate::AutoTrait(_) => {} + // This maybe belongs in wf, but that can't (doesn't) handle + // higher-ranked things. + // Prevent, e.g., `dyn Iterator`. + for bound in self.tcx().item_bounds(assoc_type) { + let subst_bound = bound.subst(tcx, upcast_trait_ref.substs); + // Normalize projections the trait object manually to + // avoid evaluation overflow. + let object_normalized = subst_bound.fold_with(&mut normalizer); + let normalized_bound = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &object_normalized, + normalizer.nested, + ); + normalizer.nested.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env.clone(), + normalized_bound, + )); + } } } debug!("confirm_object_candidate: nested: {:?}", nested); - ImplSourceObjectData { upcast_trait_ref: upcast_trait_ref.unwrap(), vtable_base, nested } + ImplSourceObjectData { upcast_trait_ref, vtable_base, nested } } fn confirm_fn_pointer_candidate( @@ -450,7 +526,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_bound(|(trait_ref, _)| trait_ref); let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { - project::normalize_with_depth( + normalize_with_depth( self, obligation.param_env, obligation.cause.clone(), @@ -867,3 +943,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSourceBuiltinData { nested }) } } + +struct ObjectAssociatedTypeNormalizer<'a, 'tcx> { + infcx: &'a infer::InferCtxt<'a, 'tcx>, + object_ty: Ty<'tcx>, + object_bounds: &'a [ty::ExistentialProjection<'tcx>], + param_env: ty::ParamEnv<'tcx>, + cause: &'a ObligationCause<'tcx>, + nested: &'a mut Vec>, +} + +impl<'tcx> TypeFolder<'tcx> for ObjectAssociatedTypeNormalizer<'_, 'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.infcx.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + if !t.has_projections() { + return t; + } + if let ty::Projection(proj) = t.kind { + if let ty::Dynamic(..) = proj.self_ty().kind { + for bound in self.object_bounds { + if proj.item_def_id == bound.item_def_id { + // FIXME(generic_associated_types): This isn't relating + // the substs for the associated type. + match self.infcx.commit_if_ok(|_| { + self.infcx.at(self.cause, self.param_env).sub( + bound + .with_self_ty(self.infcx.tcx, self.object_ty) + .projection_ty + .trait_ref(self.infcx.tcx), + proj.trait_ref(self.infcx.tcx), + ) + }) { + Ok(InferOk { value: (), obligations }) => { + self.nested.extend(obligations); + return bound.ty; + } + Err(_) => {} + } + } + } + } + } + t.super_fold_with(self) + } +} diff --git a/src/test/ui/traits/check-trait-object-bounds-4.rs b/src/test/ui/traits/check-trait-object-bounds-4.rs new file mode 100644 index 0000000000000..323508db2f2b1 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-4.rs @@ -0,0 +1,17 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Super { + type Y: Clone; +} + +trait X: Super {} + +fn f() { + None::.clone(); +} + +fn main() { + f::>(); + //~^ ERROR the trait bound `str: std::clone::Clone` is not satisfied +} diff --git a/src/test/ui/traits/check-trait-object-bounds-4.stderr b/src/test/ui/traits/check-trait-object-bounds-4.stderr new file mode 100644 index 0000000000000..75d6862579d11 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-4.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied + --> $DIR/check-trait-object-bounds-4.rs:15:5 + | +LL | fn f() { + | - required by this bound in `f` +... +LL | f::>(); + | ^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/check-trait-object-bounds-5.rs b/src/test/ui/traits/check-trait-object-bounds-5.rs new file mode 100644 index 0000000000000..7d733ad26b752 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-5.rs @@ -0,0 +1,27 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Super { + type V; +} + +trait Obj: Super { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) + //~^ type mismatch resolving `::T == i64` +} + +fn main() {} diff --git a/src/test/ui/traits/check-trait-object-bounds-5.stderr b/src/test/ui/traits/check-trait-object-bounds-5.stderr new file mode 100644 index 0000000000000..bd2b789cd9908 --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-5.stderr @@ -0,0 +1,12 @@ +error[E0271]: type mismatch resolving `::T == i64` + --> $DIR/check-trait-object-bounds-5.rs:23:5 + | +LL | fn is_obj(_: &T) {} + | --- required by this bound in `is_obj` +... +LL | is_obj(x) + | ^^^^^^ expected `i64`, found `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/traits/check-trait-object-bounds-6.rs b/src/test/ui/traits/check-trait-object-bounds-6.rs new file mode 100644 index 0000000000000..cb196d67f673d --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-6.rs @@ -0,0 +1,24 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; + type V; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) + //~^ ERROR type mismatch resolving `::T == i64` +} + +fn main() {} diff --git a/src/test/ui/traits/check-trait-object-bounds-6.stderr b/src/test/ui/traits/check-trait-object-bounds-6.stderr new file mode 100644 index 0000000000000..ea1fdaf46f6ae --- /dev/null +++ b/src/test/ui/traits/check-trait-object-bounds-6.stderr @@ -0,0 +1,12 @@ +error[E0271]: type mismatch resolving `::T == i64` + --> $DIR/check-trait-object-bounds-6.rs:20:5 + | +LL | fn is_obj(_: &T) {} + | --- required by this bound in `is_obj` +... +LL | is_obj(x) + | ^^^^^^ expected `i64`, found `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/traits/trait-object-bounds-cycle-1.rs b/src/test/ui/traits/trait-object-bounds-cycle-1.rs new file mode 100644 index 0000000000000..3146764927cd8 --- /dev/null +++ b/src/test/ui/traits/trait-object-bounds-cycle-1.rs @@ -0,0 +1,24 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/trait-object-bounds-cycle-2.rs b/src/test/ui/traits/trait-object-bounds-cycle-2.rs new file mode 100644 index 0000000000000..4c1df38058dad --- /dev/null +++ b/src/test/ui/traits/trait-object-bounds-cycle-2.rs @@ -0,0 +1,28 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Super { + type V; +} + +trait Obj: Super { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/trait-object-bounds-cycle-3.rs b/src/test/ui/traits/trait-object-bounds-cycle-3.rs new file mode 100644 index 0000000000000..55726a5ae4557 --- /dev/null +++ b/src/test/ui/traits/trait-object-bounds-cycle-3.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; + type V; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/src/test/ui/traits/trait-object-bounds-cycle-4.rs b/src/test/ui/traits/trait-object-bounds-cycle-4.rs new file mode 100644 index 0000000000000..f83cb75c7f29b --- /dev/null +++ b/src/test/ui/traits/trait-object-bounds-cycle-4.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. Make sure that having a lifetime on the trait object doesn't break things + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj<'a> { + type U: Is; + type V; +} + +fn is_obj<'a, T: ?Sized + Obj<'a>>(_: &T) {} + +fn f<'a>(x: &dyn Obj<'a, U = i32, V = i32>) { + is_obj(x) +} + +fn main() {} From bc08b791bce1c5b31052da5dfda74302b6f61a99 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 22 Jul 2020 22:43:18 +0100 Subject: [PATCH 18/34] Fix bugs in evaluating WellFormed predicates - List the nestsed obligations in an order that works with the single pass used by evaluation - Propagate recursion depth correctly --- .../src/traits/fulfill.rs | 1 + .../src/traits/select/confirmation.rs | 17 ++++-- .../src/traits/select/mod.rs | 37 ++++++------ .../rustc_trait_selection/src/traits/wf.rs | 58 +++++++++++++------ .../src/implied_outlives_bounds.rs | 4 +- compiler/rustc_typeck/src/check/check.rs | 2 +- .../src/impl_wf_check/min_specialization.rs | 1 + src/test/ui/impl-trait/wf-eval-order.rs | 39 +++++++++++++ 8 files changed, 117 insertions(+), 42 deletions(-) create mode 100644 src/test/ui/impl-trait/wf-eval-order.rs diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 8586a550230f9..289e0e0ba63ec 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -449,6 +449,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { self.selcx.infcx(), obligation.param_env, obligation.cause.body_id, + obligation.recursion_depth + 1, arg, obligation.cause.span, ) { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 59399133dff8a..ced99b3eb641c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -139,9 +139,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); }); // Require that the projection is well-formed. - let self_ty = obligation.predicate.skip_binder().self_ty(); - obligations.push(Obligation::new( + let self_ty = self.infcx.replace_bound_vars_with_placeholders(&obligation.self_ty()); + let self_ty = normalize_with_depth_to( + self, + obligation.param_env, obligation.cause.clone(), + obligation.recursion_depth + 1, + &self_ty, + &mut obligations, + ); + obligations.push(Obligation::with_depth( + obligation.cause.clone(), + obligation.recursion_depth + 1, obligation.param_env, ty::PredicateKind::WellFormed(self_ty.into()).to_predicate(self.tcx()), )); @@ -333,9 +342,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // relying on projections in the impl-trait-ref. // // e.g., `impl> Foo<::T> for V` - impl_obligations.append(&mut substs.obligations); + substs.obligations.append(&mut impl_obligations); - ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations } + ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: substs.obligations } } fn confirm_object_candidate( diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index af90bc80d4d98..0537e94cc1c21 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -343,7 +343,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(SelectionError::Overflow) } Err(e) => Err(e), - Ok(candidate) => Ok(Some(candidate)), + Ok(candidate) => { + debug!("select: candidate = {:?}", candidate); + Ok(Some(candidate)) + } } } @@ -413,9 +416,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { predicates: I, ) -> Result where - I: IntoIterator>, + I: IntoIterator> + std::fmt::Debug, { let mut result = EvaluatedToOk; + debug!("evaluate_predicates_recursively({:?})", predicates); for obligation in predicates { let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?; debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval); @@ -436,7 +440,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: PredicateObligation<'tcx>, ) -> Result { debug!( - "evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})", + "evaluate_predicate_recursively(obligation={:?}, previous_stack={:?})", previous_stack.head(), obligation ); @@ -479,15 +483,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx, obligation.param_env, obligation.cause.body_id, + obligation.recursion_depth + 1, arg, obligation.cause.span, ) { Some(mut obligations) => { self.add_depth(obligations.iter_mut(), obligation.recursion_depth); - self.evaluate_predicates_recursively( - previous_stack, - obligations.into_iter(), - ) + self.evaluate_predicates_recursively(previous_stack, obligations) } None => Ok(EvaluatedToAmbig), }, @@ -511,10 +513,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match project::poly_project_and_unify_type(self, &project_obligation) { Ok(Ok(Some(mut subobligations))) => { self.add_depth(subobligations.iter_mut(), obligation.recursion_depth); - let result = self.evaluate_predicates_recursively( - previous_stack, - subobligations.into_iter(), - ); + let result = self + .evaluate_predicates_recursively(previous_stack, subobligations); if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate(self, data) { @@ -879,10 +879,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let result = self.evaluation_probe(|this| { let candidate = (*candidate).clone(); match this.confirm_candidate(stack.obligation, candidate) { - Ok(selection) => this.evaluate_predicates_recursively( - stack.list(), - selection.nested_obligations().into_iter(), - ), + Ok(selection) => { + debug!("evaluate_candidate: selection = {:?}", selection); + this.evaluate_predicates_recursively( + stack.list(), + selection.nested_obligations().into_iter(), + ) + } Err(..) => Ok(EvaluatedToErr), } })?; @@ -1231,9 +1234,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result { self.evaluation_probe(|this| { match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { - Ok(obligations) => { - this.evaluate_predicates_recursively(stack.list(), obligations.into_iter()) - } + Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations), Err(()) => Ok(EvaluatedToErr), } }) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index df816bbd34810..0b4edf5e71b18 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -20,6 +20,7 @@ pub fn obligations<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, + recursion_depth: usize, arg: GenericArg<'tcx>, span: Span, ) -> Option>> { @@ -59,7 +60,8 @@ pub fn obligations<'a, 'tcx>( GenericArgKind::Lifetime(..) => return Some(Vec::new()), }; - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None }; + let mut wf = + WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth, item: None }; wf.compute(arg); debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out); @@ -80,7 +82,8 @@ pub fn trait_obligations<'a, 'tcx>( span: Span, item: Option<&'tcx hir::Item<'tcx>>, ) -> Vec> { - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item }; + let mut wf = + WfPredicates { infcx, param_env, body_id, span, out: vec![], recursion_depth: 0, item }; wf.compute_trait_ref(trait_ref, Elaborate::All); wf.normalize() } @@ -92,7 +95,15 @@ pub fn predicate_obligations<'a, 'tcx>( predicate: ty::Predicate<'tcx>, span: Span, ) -> Vec> { - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None }; + let mut wf = WfPredicates { + infcx, + param_env, + body_id, + span, + out: vec![], + recursion_depth: 0, + item: None, + }; // It's ok to skip the binder here because wf code is prepared for it match predicate.skip_binders() { @@ -142,6 +153,7 @@ struct WfPredicates<'a, 'tcx> { body_id: hir::HirId, span: Span, out: Vec>, + recursion_depth: usize, item: Option<&'tcx hir::Item<'tcx>>, } @@ -249,19 +261,19 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { for mut obligation in self.out { assert!(!obligation.has_escaping_bound_vars()); let mut selcx = traits::SelectionContext::new(infcx); - let i = obligations.len(); // Don't normalize the whole obligation, the param env is either // already normalized, or we're currently normalizing the // param_env. Either way we should only normalize the predicate. - let normalized_predicate = traits::normalize_to( + let normalized_predicate = traits::project::normalize_with_depth_to( &mut selcx, param_env, cause.clone(), + self.recursion_depth, &obligation.predicate, &mut obligations, ); obligation.predicate = normalized_predicate; - obligations.insert(i, obligation); + obligations.push(obligation); } obligations } @@ -274,6 +286,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { debug!("compute_trait_ref obligations {:?}", obligations); let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; + let depth = self.recursion_depth; let item = self.item; @@ -295,7 +308,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { &obligation.predicate, tcx.associated_items(trait_ref.def_id).in_definition_order(), ); - traits::Obligation::new(cause, param_env, obligation.predicate) + traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate) }; if let Elaborate::All = elaborate { @@ -324,8 +337,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { new_cause.make_mut().span = self_ty.span; } } - traits::Obligation::new( + traits::Obligation::with_depth( new_cause, + depth, param_env, ty::PredicateAtom::WellFormed(arg).to_predicate(tcx), ) @@ -363,6 +377,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let tcx = self.tcx(); let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; + let depth = self.recursion_depth; self.out.extend( data.substs @@ -372,8 +387,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { }) .filter(|arg| !arg.has_escaping_bound_vars()) .map(|arg| { - traits::Obligation::new( + traits::Obligation::with_depth( cause.clone(), + depth, param_env, ty::PredicateKind::WellFormed(arg).to_predicate(tcx), ) @@ -388,8 +404,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { def_id: self.infcx.tcx.require_lang_item(LangItem::Sized, None), substs: self.infcx.tcx.mk_substs_trait(subty, &[]), }; - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, self.param_env, trait_ref.without_const().to_predicate(self.infcx.tcx), )); @@ -400,6 +417,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { fn compute(&mut self, arg: GenericArg<'tcx>) { let mut walker = arg.walk(); let param_env = self.param_env; + let depth = self.recursion_depth; while let Some(arg) = walker.next() { let ty = match arg.unpack() { GenericArgKind::Type(ty) => ty, @@ -419,8 +437,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let predicate = ty::PredicateAtom::ConstEvaluatable(def, substs) .to_predicate(self.tcx()); let cause = self.cause(traits::MiscObligation); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, self.param_env, predicate, )); @@ -435,8 +454,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { val: ty::ConstKind::Infer(resolved), ..*constant }); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, self.param_env, ty::PredicateAtom::WellFormed(resolved_constant.into()) .to_predicate(self.tcx()), @@ -521,8 +541,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // WfReference if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + depth, param_env, ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(rty, r)) .to_predicate(self.tcx()), @@ -612,8 +633,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let component_traits = data.auto_traits().chain(data.principal_def_id()); let tcx = self.tcx(); self.out.extend(component_traits.map(|did| { - traits::Obligation::new( + traits::Obligation::with_depth( cause.clone(), + depth, param_env, ty::PredicateAtom::ObjectSafe(did).to_predicate(tcx), ) @@ -638,8 +660,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { if let ty::Infer(ty::TyVar(_)) = ty.kind() { // Not yet resolved, but we've made progress. let cause = self.cause(traits::MiscObligation); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, param_env, ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()), )); @@ -676,7 +699,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { .zip(origins.into_iter().rev()) .map(|((pred, span), origin_def_id)| { let cause = self.cause(traits::BindingObligation(origin_def_id, span)); - traits::Obligation::new(cause, self.param_env, pred) + traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred) }) .filter(|pred| !pred.has_escaping_bound_vars()) .collect() @@ -729,8 +752,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound)); let outlives = ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound)); - self.out.push(traits::Obligation::new( + self.out.push(traits::Obligation::with_depth( cause, + self.recursion_depth, self.param_env, outlives.to_predicate(self.infcx.tcx), )); diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 79308b032eccd..bc5c07fce045c 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -61,8 +61,8 @@ fn compute_implied_outlives_bounds<'tcx>( // than the ultimate set. (Note: normally there won't be // unresolved inference variables here anyway, but there might be // during typeck under some circumstances.) - let obligations = - wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, arg, DUMMY_SP).unwrap_or(vec![]); + let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP) + .unwrap_or(vec![]); // N.B., all of these predicates *ought* to be easily proven // true. In fact, their correctness is (mostly) implied by diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index fbb19617c7fcf..cfd75db61f7cd 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -561,7 +561,7 @@ fn check_opaque_meets_bounds<'tcx>( let misc_cause = traits::ObligationCause::misc(span, hir_id); let (_, opaque_type_map) = inh.register_infer_ok_obligations( - infcx.instantiate_opaque_types(def_id.to_def_id(), hir_id, param_env, &opaque_ty, span), + infcx.instantiate_opaque_types(def_id, hir_id, param_env, &opaque_ty, span), ); for (def_id, opaque_defn) in opaque_type_map { diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 60b9467fca8b3..4cf3efcf5136d 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -337,6 +337,7 @@ fn check_predicates<'tcx>( infcx, tcx.param_env(impl1_def_id), tcx.hir().local_def_id_to_hir_id(impl1_def_id), + 0, arg, span, ) { diff --git a/src/test/ui/impl-trait/wf-eval-order.rs b/src/test/ui/impl-trait/wf-eval-order.rs new file mode 100644 index 0000000000000..c7d6bb870962a --- /dev/null +++ b/src/test/ui/impl-trait/wf-eval-order.rs @@ -0,0 +1,39 @@ +// Check that we handle evaluating `wf` predicates correctly. + +// check-pass + +struct X(T) +where + T::V: Clone; + +fn hide(t: T) -> impl Sized { + t +} + +trait A { + type U; +} + +impl A for T { + type U = T; +} + +trait B { + type V; +} + +impl, T> B for S { + type V = T; +} + +fn main() { + // Evaluating `typeof(x): Sized` requires + // + // - `wf(typeof(x))` because we use a projection candidate. + // - `::V: Clone` because that's a bound on the trait. + // - `::V` normalizes to `_#1` where `::U == _#1` + // + // This all works if we evaluate `::U == _#1` before + // `::V`, but we previously had the opposite order. + let x = hide(X(0)); +} From cfee49593d756bb97018d1d2ac194e0821d2dfca Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 23 Jul 2020 21:59:20 +0100 Subject: [PATCH 19/34] Handle multiple applicable projection candidates --- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/traits/select.rs | 7 +-- .../src/traits/select/candidate_assembly.rs | 10 ++-- .../src/traits/select/confirmation.rs | 25 ++++++--- .../src/traits/select/mod.rs | 52 +++++++++++-------- .../associated-types-bound-ambiguity.rs | 23 ++++++++ 6 files changed, 82 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/associated-types/associated-types-bound-ambiguity.rs diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 240f2c0792cf2..fc4c343372a42 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -157,7 +157,7 @@ rustc_queries! { } /// Returns the list of bounds that can be used for - /// `SelectionCandidate::ProjectionCandidate` and + /// `SelectionCandidate::ProjectionCandidate(_)` and /// `ProjectionTyCandidate::TraitDef`. /// Specifically this is the bounds written on the trait's type /// definition, or those after the `impl` keyword diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 6ad514c6be21b..358ead507b4d0 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -105,9 +105,10 @@ pub enum SelectionCandidate<'tcx> { ImplCandidate(DefId), AutoImplCandidate(DefId), - /// This is a trait matching with a projected type as `Self`, and - /// we found an applicable bound in the trait definition. - ProjectionCandidate, + /// This is a trait matching with a projected type as `Self`, and we found + /// an applicable bound in the trait definition. The `usize` is an index + /// into the list returned by `tcx.item_bounds`. + ProjectionCandidate(usize), /// Implementation of a `Fn`-family trait by one of the anonymous types /// generated for a `||` expression. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 6c7732f28e41f..1ac9be64f1f1f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -323,12 +323,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, } - let result = self.infcx.probe(|_| { - self.match_projection_obligation_against_definition_bounds(obligation).is_some() - }); + let result = self + .infcx + .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); - if result { - candidates.vec.push(ProjectionCandidate); + for predicate_index in result { + candidates.vec.push(ProjectionCandidate(predicate_index)); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ced99b3eb641c..d0b4bec1b1a0a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -70,8 +70,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSource::AutoImpl(data)) } - ProjectionCandidate => { - let obligations = self.confirm_projection_candidate(obligation); + ProjectionCandidate(idx) => { + let obligations = self.confirm_projection_candidate(obligation, idx); Ok(ImplSource::Param(obligations)) } @@ -121,11 +121,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_projection_candidate( &mut self, obligation: &TraitObligation<'tcx>, + idx: usize, ) -> Vec> { self.infcx.commit_unconditionally(|_| { - let candidate = self - .match_projection_obligation_against_definition_bounds(obligation) - .unwrap_or_else(|| bug!("Can't find selected projection candidate")); + let tcx = self.tcx(); + + let bound_self_ty = self.infcx.shallow_resolve(obligation.self_ty()); + let (def_id, substs) = match bound_self_ty.skip_binder().kind { + ty::Projection(proj) => (proj.item_def_id, proj.substs), + ty::Opaque(def_id, substs) => (def_id, substs), + _ => bug!("projection candidate for unexpected type: {:?}", bound_self_ty), + }; + + let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs); + let candidate = candidate_predicate + .to_opt_poly_trait_ref() + .expect("projection candidate is not a trait predicate"); let mut obligations = self .infcx .at(&obligation.cause, obligation.param_env) @@ -139,7 +150,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); }); // Require that the projection is well-formed. - let self_ty = self.infcx.replace_bound_vars_with_placeholders(&obligation.self_ty()); + let self_ty = self.infcx.replace_bound_vars_with_placeholders(&bound_self_ty); let self_ty = normalize_with_depth_to( self, obligation.param_env, @@ -152,7 +163,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.clone(), obligation.recursion_depth + 1, obligation.param_env, - ty::PredicateKind::WellFormed(self_ty.into()).to_predicate(self.tcx()), + ty::PredicateKind::WellFormed(self_ty.into()).to_predicate(tcx), )); obligations }) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0537e94cc1c21..e1dd3f215ca8c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1163,11 +1163,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// /// Given an obligation like `::Bar: Baz` where the self type is /// a projection, look at the bounds of `T::Bar`, see if we can find a - /// `Baz` bound and it there is one it returns it. + /// `Baz` bound. We return indexes into the list returned by + /// `tcx.item_bounds` for any applicable bounds. fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Option> { + ) -> smallvec::SmallVec<[usize; 2]> { let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate); let placeholder_trait_predicate = self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate); @@ -1192,25 +1193,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; let bounds = tcx.item_bounds(def_id).subst(tcx, substs); - let matching_bound = bounds.iter().find_map(|bound| { - if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() { - let bound = ty::Binder::bind(pred.trait_ref); - if self.infcx.probe(|_| { - self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref) + let matching_bounds = bounds + .iter() + .enumerate() + .filter_map(|(idx, bound)| { + if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() { + let bound = ty::Binder::bind(pred.trait_ref); + if self.infcx.probe(|_| { + self.match_projection( + obligation, + bound, + placeholder_trait_predicate.trait_ref, + ) .is_ok() - }) { - return Some(bound); + }) { + return Some(idx); + } } - } - None - }); + None + }) + .collect(); debug!( "match_projection_obligation_against_definition_bounds: \ - matching_bound={:?}", - matching_bound + matching_bounds={:?}", + matching_bounds ); - matching_bound + matching_bounds } fn match_projection( @@ -1299,14 +1308,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // clause so don't go around looking for impls. !is_global(cand) } - ObjectCandidate | ProjectionCandidate => { + ObjectCandidate | ProjectionCandidate(_) => { // Arbitrarily give param candidates priority // over projection and object candidates. !is_global(cand) } ParamCandidate(..) => false, }, - ObjectCandidate | ProjectionCandidate => match victim.candidate { + ObjectCandidate | ProjectionCandidate(_) => match victim.candidate { AutoImplCandidate(..) => { bug!( "default implementations shouldn't be recorded \ @@ -1323,10 +1332,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | BuiltinUnsizeCandidate | BuiltinCandidate { .. } | TraitAliasCandidate(..) => true, - ObjectCandidate | ProjectionCandidate => { - // Arbitrarily give param candidates priority - // over projection and object candidates. - true + ObjectCandidate | ProjectionCandidate(_) => { + // Shouldn't have both an object and projection candidate, + // nor multiple object candidates. Multiple projection + // candidates are ambiguous. + false } ParamCandidate(ref cand) => is_global(cand), }, diff --git a/src/test/ui/associated-types/associated-types-bound-ambiguity.rs b/src/test/ui/associated-types/associated-types-bound-ambiguity.rs new file mode 100644 index 0000000000000..9f179b6454e52 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-bound-ambiguity.rs @@ -0,0 +1,23 @@ +// Make sure that if there are multiple applicable bounds on a projection, we +// consider them ambiguous. In this test we are initially trying to solve +// `Self::Repr: From<_>`, which is ambiguous until we later infer `_` to +// `{integer}`. + +// check-pass + +trait PrimeField: Sized { + type Repr: From + From; + type Repr2: From + From; + + fn method() { + Self::Repr::from(10); + Self::Repr2::from(10); + } +} + +fn function() { + T::Repr::from(10); + T::Repr2::from(10); +} + +fn main() {} From 34e5a4992c920ce9e68c333621f3d4c967c012c4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 24 Jul 2020 19:10:22 +0100 Subject: [PATCH 20/34] Normalize projection bounds when considering candidates This unfortunately requires some winnowing hacks to avoid now ambiguous candidates. --- .../src/traits/project.rs | 58 ++- .../src/traits/select/confirmation.rs | 33 +- .../src/traits/select/mod.rs | 336 +++++++++++------- .../bad-bounds-on-assoc-in-trait.rs | 40 ++- .../bad-bounds-on-assoc-in-trait.stderr | 8 +- .../associate-type-bound-normalization.rs | 25 ++ src/test/ui/closures/issue-41366.rs | 1 + src/test/ui/closures/issue-41366.stderr | 22 +- src/test/ui/issues/issue-24204.rs | 14 +- src/test/ui/issues/issue-24204.stderr | 15 - src/test/ui/issues/issue-58344.rs | 24 +- src/test/ui/issues/issue-58344.stderr | 25 -- src/test/ui/issues/issue-60283.rs | 1 + src/test/ui/issues/issue-60283.stderr | 22 +- .../missing-assoc-type-bound-restriction.rs | 4 +- ...issing-assoc-type-bound-restriction.stderr | 18 - 16 files changed, 390 insertions(+), 256 deletions(-) create mode 100644 src/test/ui/associated-types/associate-type-bound-normalization.rs delete mode 100644 src/test/ui/issues/issue-24204.stderr delete mode 100644 src/test/ui/issues/issue-58344.stderr delete mode 100644 src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index f23d3bb761154..d52e54191006a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -884,6 +884,7 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>( candidate_set, ProjectionTyCandidate::ParamEnv, obligation.param_env.caller_bounds().iter(), + false, ); } @@ -927,6 +928,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( candidate_set, ProjectionTyCandidate::TraitDef, bounds.iter(), + true, ) } @@ -937,6 +939,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( candidate_set: &mut ProjectionTyCandidateSet<'tcx>, ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>, env_predicates: impl Iterator>, + potentially_unnormalized_candidates: bool, ) { debug!("assemble_candidates_from_predicates(obligation={:?})", obligation); let infcx = selcx.infcx(); @@ -948,16 +951,12 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( let is_match = same_def_id && infcx.probe(|_| { - let data_poly_trait_ref = data.to_poly_trait_ref(infcx.tcx); - let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); - infcx - .at(&obligation.cause, obligation.param_env) - .sup(obligation_poly_trait_ref, data_poly_trait_ref) - .map(|InferOk { obligations: _, value: () }| { - // FIXME(#32730) -- do we need to take obligations - // into account in any way? At the moment, no. - }) - .is_ok() + selcx.match_projection_projections( + obligation, + obligation_trait_ref, + &data, + potentially_unnormalized_candidates, + ) }); debug!( @@ -1157,9 +1156,12 @@ fn confirm_candidate<'cx, 'tcx>( debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation); let mut progress = match candidate { - ProjectionTyCandidate::ParamEnv(poly_projection) - | ProjectionTyCandidate::TraitDef(poly_projection) => { - confirm_param_env_candidate(selcx, obligation, poly_projection) + ProjectionTyCandidate::ParamEnv(poly_projection) => { + confirm_param_env_candidate(selcx, obligation, poly_projection, false) + } + + ProjectionTyCandidate::TraitDef(poly_projection) => { + confirm_param_env_candidate(selcx, obligation, poly_projection, true) } ProjectionTyCandidate::Select(impl_source) => { @@ -1272,7 +1274,7 @@ fn confirm_object_candidate<'cx, 'tcx>( } }; - confirm_param_env_candidate(selcx, obligation, env_predicate) + confirm_param_env_candidate(selcx, obligation, env_predicate, false) } fn confirm_generator_candidate<'cx, 'tcx>( @@ -1323,7 +1325,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( } }); - confirm_param_env_candidate(selcx, obligation, predicate) + confirm_param_env_candidate(selcx, obligation, predicate, false) .with_addl_obligations(impl_source.nested) .with_addl_obligations(obligations) } @@ -1345,7 +1347,7 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>( ty: self_ty.discriminant_ty(tcx), }; - confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate)) + confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( @@ -1420,13 +1422,14 @@ fn confirm_callable_candidate<'cx, 'tcx>( ty: ret_type, }); - confirm_param_env_candidate(selcx, obligation, predicate) + confirm_param_env_candidate(selcx, obligation, predicate, false) } fn confirm_param_env_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, poly_cache_entry: ty::PolyProjectionPredicate<'tcx>, + potentially_unnormalized_candidate: bool, ) -> Progress<'tcx> { let infcx = selcx.infcx(); let cause = &obligation.cause; @@ -1440,8 +1443,27 @@ fn confirm_param_env_candidate<'cx, 'tcx>( let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx); let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx); + let mut nested_obligations = Vec::new(); + let cache_trait_ref = if potentially_unnormalized_candidate { + ensure_sufficient_stack(|| { + normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &cache_trait_ref, + &mut nested_obligations, + ) + }) + } else { + cache_trait_ref + }; + match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) { - Ok(InferOk { value: _, obligations }) => Progress { ty: cache_entry.ty, obligations }, + Ok(InferOk { value: _, obligations }) => { + nested_obligations.extend(obligations); + Progress { ty: cache_entry.ty, obligations: nested_obligations } + } Err(e) => { let msg = format!( "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}", diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index d0b4bec1b1a0a..e6fce78f269ca 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -137,18 +137,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let candidate = candidate_predicate .to_opt_poly_trait_ref() .expect("projection candidate is not a trait predicate"); - let mut obligations = self - .infcx - .at(&obligation.cause, obligation.param_env) - .sup(obligation.predicate.to_poly_trait_ref(), candidate) - .map(|InferOk { obligations, .. }| obligations) - .unwrap_or_else(|_| { - bug!( - "Projection bound `{:?}` was applicable to `{:?}` but now is not", - candidate, - obligation - ); - }); + let Normalized { value: candidate, mut obligations } = normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &candidate, + ); + + obligations.extend( + self.infcx + .at(&obligation.cause, obligation.param_env) + .sup(obligation.predicate.to_poly_trait_ref(), candidate) + .map(|InferOk { obligations, .. }| obligations) + .unwrap_or_else(|_| { + bug!( + "Projection bound `{:?}` was applicable to `{:?}` but now is not", + candidate, + obligation + ); + }), + ); // Require that the projection is well-formed. let self_ty = self.infcx.replace_bound_vars_with_placeholders(&bound_self_ty); let self_ty = normalize_with_depth_to( diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e1dd3f215ca8c..147b0c74d16e8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -9,6 +9,7 @@ use super::coherence::{self, Conflict}; use super::const_evaluatable; use super::project; use super::project::normalize_with_depth_to; +use super::project::ProjectionTyObligation; use super::util; use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def}; use super::wf; @@ -36,9 +37,8 @@ use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef}; -use rustc_middle::ty::{ - self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, -}; +use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; +use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::sym; use std::cell::{Cell, RefCell}; @@ -946,10 +946,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// to have a *lower* recursion_depth than the obligation used to create it. /// Projection sub-obligations may be returned from the projection cache, /// which results in obligations with an 'old' `recursion_depth`. - /// Additionally, methods like `wf::obligations` and - /// `InferCtxt.subtype_predicate` produce subobligations without - /// taking in a 'parent' depth, causing the generated subobligations - /// to have a `recursion_depth` of `0`. + /// Additionally, methods like `InferCtxt.subtype_predicate` produce + /// subobligations without taking in a 'parent' depth, causing the + /// generated subobligations to have a `recursion_depth` of `0`. /// /// To ensure that obligation_depth never decreasees, we force all subobligations /// to have at least the depth of the original obligation. @@ -1229,10 +1228,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { placeholder_trait_ref: ty::TraitRef<'tcx>, ) -> Result>, ()> { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); + if placeholder_trait_ref.def_id != trait_bound.def_id() { + // Avoid unnecessary normalization + return Err(()); + } + + let Normalized { value: trait_bound, obligations: mut nested_obligations } = + ensure_sufficient_stack(|| { + project::normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_bound, + ) + }); self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) - .map(|InferOk { obligations, .. }| obligations) + .map(|InferOk { obligations, .. }| { + nested_obligations.extend(obligations); + nested_obligations + }) .map_err(|_| ()) } @@ -1249,6 +1266,44 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) } + pub(super) fn match_projection_projections( + &mut self, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + data: &PolyProjectionPredicate<'tcx>, + potentially_unnormalized_candidates: bool, + ) -> bool { + let mut nested_obligations = Vec::new(); + let projection_ty = if potentially_unnormalized_candidates { + ensure_sufficient_stack(|| { + project::normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &data.map_bound_ref(|data| data.projection_ty), + &mut nested_obligations, + ) + }) + } else { + data.map_bound_ref(|data| data.projection_ty) + }; + + // FIXME(generic_associated_types): Compare the whole projections + let data_poly_trait_ref = projection_ty.map_bound(|proj| proj.trait_ref(self.tcx())); + let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); + self.infcx + .at(&obligation.cause, obligation.param_env) + .sup(obligation_poly_trait_ref, data_poly_trait_ref) + .map_or(false, |InferOk { obligations, value: () }| { + self.evaluate_predicates_recursively( + TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), + nested_obligations.into_iter().chain(obligations), + ) + .map_or(false, |res| res.may_apply()) + }) + } + /////////////////////////////////////////////////////////////////////////// // WINNOW // @@ -1283,18 +1338,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // This is a fix for #53123 and prevents winnowing from accidentally extending the // lifetime of a variable. - match other.candidate { + match (&other.candidate, &victim.candidate) { + (_, AutoImplCandidate(..)) | (AutoImplCandidate(..), _) => { + bug!( + "default implementations shouldn't be recorded \ + when there are other valid candidates" + ); + } + // (*) - BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => true, - ParamCandidate(ref cand) => match victim.candidate { - AutoImplCandidate(..) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other valid candidates" - ); - } - // (*) - BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => false, + (BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate, _) => true, + (_, BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate) => false, + + (ParamCandidate(..), ParamCandidate(..)) => false, + + // Global bounds from the where clause should be ignored + // here (see issue #50825). Otherwise, we have a where + // clause so don't go around looking for impls. + // Arbitrarily give param candidates priority + // over projection and object candidates. + ( + ParamCandidate(ref cand), ImplCandidate(..) | ClosureCandidate | GeneratorCandidate @@ -1302,28 +1366,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | BuiltinObjectCandidate | BuiltinUnsizeCandidate | BuiltinCandidate { .. } - | TraitAliasCandidate(..) => { - // Global bounds from the where clause should be ignored - // here (see issue #50825). Otherwise, we have a where - // clause so don't go around looking for impls. - !is_global(cand) - } - ObjectCandidate | ProjectionCandidate(_) => { - // Arbitrarily give param candidates priority - // over projection and object candidates. - !is_global(cand) - } - ParamCandidate(..) => false, - }, - ObjectCandidate | ProjectionCandidate(_) => match victim.candidate { - AutoImplCandidate(..) => { - bug!( - "default implementations shouldn't be recorded \ - when there are other valid candidates" - ); - } - // (*) - BuiltinCandidate { has_nested: false } | DiscriminantKindCandidate => false, + | TraitAliasCandidate(..) + | ObjectCandidate + | ProjectionCandidate(_), + ) => !is_global(cand), + (ObjectCandidate | ProjectionCandidate(_), ParamCandidate(ref cand)) => { + // Prefer these to a global where-clause bound + // (see issue #50825). + is_global(cand) + } + ( + ImplCandidate(_) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { has_nested: true } + | TraitAliasCandidate(..), + ParamCandidate(ref cand), + ) => { + // Prefer these to a global where-clause bound + // (see issue #50825). + is_global(cand) && other.evaluation.must_apply_modulo_regions() + } + + (ProjectionCandidate(i), ProjectionCandidate(j)) => { + // Arbitrarily pick the first candidate for backwards + // compatibility reasons. Don't let this affect inference. + i > j && !needs_infer + } + (ObjectCandidate, ObjectCandidate) => bug!("Duplicate object candidate"), + (ObjectCandidate, ProjectionCandidate(_)) + | (ProjectionCandidate(_), ObjectCandidate) => { + bug!("Have both object and projection candidate") + } + + // Arbitrarily give projection and object candidates priority. + ( + ObjectCandidate | ProjectionCandidate(_), ImplCandidate(..) | ClosureCandidate | GeneratorCandidate @@ -1331,99 +1412,100 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | BuiltinObjectCandidate | BuiltinUnsizeCandidate | BuiltinCandidate { .. } - | TraitAliasCandidate(..) => true, - ObjectCandidate | ProjectionCandidate(_) => { - // Shouldn't have both an object and projection candidate, - // nor multiple object candidates. Multiple projection - // candidates are ambiguous. - false - } - ParamCandidate(ref cand) => is_global(cand), - }, - ImplCandidate(other_def) => { + | TraitAliasCandidate(..), + ) => true, + + ( + ImplCandidate(..) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { .. } + | TraitAliasCandidate(..), + ObjectCandidate | ProjectionCandidate(_), + ) => false, + + (&ImplCandidate(other_def), &ImplCandidate(victim_def)) => { // See if we can toss out `victim` based on specialization. // This requires us to know *for sure* that the `other` impl applies // i.e., `EvaluatedToOk`. if other.evaluation.must_apply_modulo_regions() { - match victim.candidate { - ImplCandidate(victim_def) => { - let tcx = self.tcx(); - if tcx.specializes((other_def, victim_def)) { - return true; - } - return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) { - Some(ty::ImplOverlapKind::Permitted { marker: true }) => { - // Subtle: If the predicate we are evaluating has inference - // variables, do *not* allow discarding candidates due to - // marker trait impls. - // - // Without this restriction, we could end up accidentally - // constrainting inference variables based on an arbitrarily - // chosen trait impl. - // - // Imagine we have the following code: - // - // ```rust - // #[marker] trait MyTrait {} - // impl MyTrait for u8 {} - // impl MyTrait for bool {} - // ``` - // - // And we are evaluating the predicate `<_#0t as MyTrait>`. - // - // During selection, we will end up with one candidate for each - // impl of `MyTrait`. If we were to discard one impl in favor - // of the other, we would be left with one candidate, causing - // us to "successfully" select the predicate, unifying - // _#0t with (for example) `u8`. - // - // However, we have no reason to believe that this unification - // is correct - we've essentially just picked an arbitrary - // *possibility* for _#0t, and required that this be the *only* - // possibility. - // - // Eventually, we will either: - // 1) Unify all inference variables in the predicate through - // some other means (e.g. type-checking of a function). We will - // then be in a position to drop marker trait candidates - // without constraining inference variables (since there are - // none left to constrin) - // 2) Be left with some unconstrained inference variables. We - // will then correctly report an inference error, since the - // existence of multiple marker trait impls tells us nothing - // about which one should actually apply. - !needs_infer - } - Some(_) => true, - None => false, - }; - } - ParamCandidate(ref cand) => { - // Prefer the impl to a global where clause candidate. - return is_global(cand); - } - _ => (), - } - } - - false - } - ClosureCandidate - | GeneratorCandidate - | FnPointerCandidate - | BuiltinObjectCandidate - | BuiltinUnsizeCandidate - | BuiltinCandidate { has_nested: true } => { - match victim.candidate { - ParamCandidate(ref cand) => { - // Prefer these to a global where-clause bound - // (see issue #50825). - is_global(cand) && other.evaluation.must_apply_modulo_regions() + let tcx = self.tcx(); + if tcx.specializes((other_def, victim_def)) { + return true; } - _ => false, + return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) { + Some(ty::ImplOverlapKind::Permitted { marker: true }) => { + // Subtle: If the predicate we are evaluating has inference + // variables, do *not* allow discarding candidates due to + // marker trait impls. + // + // Without this restriction, we could end up accidentally + // constrainting inference variables based on an arbitrarily + // chosen trait impl. + // + // Imagine we have the following code: + // + // ```rust + // #[marker] trait MyTrait {} + // impl MyTrait for u8 {} + // impl MyTrait for bool {} + // ``` + // + // And we are evaluating the predicate `<_#0t as MyTrait>`. + // + // During selection, we will end up with one candidate for each + // impl of `MyTrait`. If we were to discard one impl in favor + // of the other, we would be left with one candidate, causing + // us to "successfully" select the predicate, unifying + // _#0t with (for example) `u8`. + // + // However, we have no reason to believe that this unification + // is correct - we've essentially just picked an arbitrary + // *possibility* for _#0t, and required that this be the *only* + // possibility. + // + // Eventually, we will either: + // 1) Unify all inference variables in the predicate through + // some other means (e.g. type-checking of a function). We will + // then be in a position to drop marker trait candidates + // without constraining inference variables (since there are + // none left to constrin) + // 2) Be left with some unconstrained inference variables. We + // will then correctly report an inference error, since the + // existence of multiple marker trait impls tells us nothing + // about which one should actually apply. + !needs_infer + } + Some(_) => true, + None => false, + }; + } else { + false } } - _ => false, + + // Everything else is ambiguous + ( + ImplCandidate(_) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { has_nested: true } + | TraitAliasCandidate(..), + ImplCandidate(_) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { has_nested: true } + | TraitAliasCandidate(..), + ) => false, } } diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs index 4c78f17a6a33d..8093c4b9d9ec0 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs @@ -6,26 +6,25 @@ use std::fmt::Debug; use std::iter::Once; -trait Lam { type App; } +trait Lam { + type App; +} #[derive(Clone)] struct L1; -impl<'a> Lam<&'a u8> for L1 { type App = u8; } +impl<'a> Lam<&'a u8> for L1 { + type App = u8; +} #[derive(Clone)] struct L2; -impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; } +impl<'a, 'b> Lam<&'a &'b u8> for L2 { + type App = u8; +} trait Case1 { - type C: Clone + Iterator Lam<&'a u8, App: - Debug - > - > + Sync>; - //~^^^^^^ ERROR `<::C as std::iter::Iterator>::Item` is not an iterator - //~^^^^^^ ERROR `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely - //~^^^ ERROR `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely + type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + //~^ ERROR overflow evaluating the requirement `<::C as std::iter::Iterator>::Item` } pub struct S1; @@ -34,10 +33,20 @@ impl Case1 for S1 { } fn assume_case1() { - fn assert_a<_0, A>() where A: Iterator, _0: Debug {} + fn assert_a<_0, A>() + where + A: Iterator, + _0: Debug, + { + } assert_a::<_, T::A>(); - fn assert_b<_0, B>() where B: Iterator, _0: 'static {} + fn assert_b<_0, B>() + where + B: Iterator, + _0: 'static, + { + } assert_b::<_, T::B>(); fn assert_c<_0, _1, _2, C>() @@ -46,7 +55,8 @@ fn assume_case1() { _2: Send + Iterator, _1: for<'a> Lam<&'a u8, App = _0>, _0: Debug, - {} + { + } assert_c::<_, _, _, T::C>(); } diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index 20a087a85a6e8..abaae7e5343dd 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -1,5 +1,5 @@ -error[E0277]: `<::C as std::iter::Iterator>::Item` is not an iterator - --> $DIR/bad-bounds-on-assoc-in-trait.rs:22:5 +error[E0275]: overflow evaluating the requirement `<::C as std::iter::Iterator>::Item` + --> $DIR/bad-bounds-on-assoc-in-trait.rs:28:5 | LL | / type C: Clone + Iterator::C as std::iter::Iterator>::Item: std::marker::Sync { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/associate-type-bound-normalization.rs b/src/test/ui/associated-types/associate-type-bound-normalization.rs new file mode 100644 index 0000000000000..db092970f79b8 --- /dev/null +++ b/src/test/ui/associated-types/associate-type-bound-normalization.rs @@ -0,0 +1,25 @@ +// Make sure that we normalize bounds on associated types before checking them +// as candidates. + +// check-pass + +trait Mul { + type Output; +} + +trait Matrix: Mul<::Row, Output = ()> { + type Row; + + type Transpose: Matrix; +} + +fn is_mul>() {} + +fn f() { + // The unnormalized bound on `T::Transpose` is + // `Mul<::Row` which has to be normalized to be + // equal to `T::Row`. + is_mul::(); +} + +fn main() {} diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs index af1e37ba867de..909c33f642d31 100644 --- a/src/test/ui/closures/issue-41366.rs +++ b/src/test/ui/closures/issue-41366.rs @@ -9,4 +9,5 @@ impl<'g> T<'g> for u32 { fn main() { (&|_| ()) as &dyn for<'x> Fn(>::V); //~^ ERROR: type mismatch in closure arguments + //~| ERROR: size for values of type `>::V` cannot be known at compilation time } diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr index df0495cdc4643..97c33c0708e49 100644 --- a/src/test/ui/closures/issue-41366.stderr +++ b/src/test/ui/closures/issue-41366.stderr @@ -9,6 +9,24 @@ LL | (&|_| ()) as &dyn for<'x> Fn(>::V); | = note: required for the cast to the object type `dyn for<'x> Fn(>::V)` -error: aborting due to previous error +error[E0277]: the size for values of type `>::V` cannot be known at compilation time + --> $DIR/issue-41366.rs:10:8 + | +LL | (&|_| ()) as &dyn for<'x> Fn(>::V); + | ^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `>::V` + = help: unsized locals are gated as an unstable feature +help: consider further restricting the associated type + | +LL | fn main() where >::V: std::marker::Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | (&|&_| ()) as &dyn for<'x> Fn(>::V); + | ^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0631`. +Some errors have detailed explanations: E0277, E0631. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-24204.rs b/src/test/ui/issues/issue-24204.rs index df72283de233e..5a7b3459589eb 100644 --- a/src/test/ui/issues/issue-24204.rs +++ b/src/test/ui/issues/issue-24204.rs @@ -1,3 +1,5 @@ +// check-pass + #![allow(dead_code)] trait MultiDispatch { @@ -8,10 +10,16 @@ trait Trait: Sized { type A: MultiDispatch; type B; - fn new(u: U) -> >::O where Self::A : MultiDispatch; + fn new(u: U) -> >::O + where + Self::A: MultiDispatch; } -fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } -//~^ ERROR mismatched types +fn test>(b: i32) -> T +where + T::A: MultiDispatch, +{ + T::new(b) +} fn main() {} diff --git a/src/test/ui/issues/issue-24204.stderr b/src/test/ui/issues/issue-24204.stderr deleted file mode 100644 index 9d66c9ff0a843..0000000000000 --- a/src/test/ui/issues/issue-24204.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-24204.rs:14:72 - | -LL | fn test>(b: i32) -> T where T::A: MultiDispatch { T::new(b) } - | - - ^^^^^^^^^ expected type parameter `T`, found associated type - | | | - | this type parameter expected `T` because of return type - | - = note: expected type parameter `T` - found associated type `<::A as MultiDispatch>::O` - = note: you might be missing a type parameter or trait bound - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-58344.rs b/src/test/ui/issues/issue-58344.rs index 9b184e296aa6f..0cb04dcb22a54 100644 --- a/src/test/ui/issues/issue-58344.rs +++ b/src/test/ui/issues/issue-58344.rs @@ -1,3 +1,5 @@ +// check-pass + use std::ops::Add; trait Trait { @@ -18,7 +20,11 @@ enum Either { } impl Either { - fn converge(self) -> T where L: Trait, R: Trait { + fn converge(self) -> T + where + L: Trait, + R: Trait, + { match self { Either::Left(val) => val.get(), Either::Right(val) => val.get(), @@ -26,22 +32,16 @@ impl Either { } } -fn add_generic, B>(lhs: A, rhs: B) -> Either< - impl Trait<>::Output>, - impl Trait<>::Output> -> { - if true { - Either::Left(Holder(lhs + rhs)) - } else { - Either::Right(Holder(lhs + rhs)) - } +fn add_generic, B>( + lhs: A, + rhs: B, +) -> Either>::Output>, impl Trait<>::Output>> { + if true { Either::Left(Holder(lhs + rhs)) } else { Either::Right(Holder(lhs + rhs)) } } fn add_one( value: u32, ) -> Either>::Output>, impl Trait<>::Output>> { - //~^ ERROR: the trait bound `impl Trait<::Output>: Trait` - //~| ERROR: the trait bound `impl Trait<::Output>: Trait` add_generic(value, 1u32) } diff --git a/src/test/ui/issues/issue-58344.stderr b/src/test/ui/issues/issue-58344.stderr deleted file mode 100644 index ade85d8b0168c..0000000000000 --- a/src/test/ui/issues/issue-58344.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0277]: the trait bound `impl Trait<::Output>: Trait` is not satisfied - --> $DIR/issue-58344.rs:42:13 - | -LL | ) -> Either>::Output>, impl Trait<>::Output>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Trait<::Output>` -... -LL | add_generic(value, 1u32) - | ------------------------ this returned value is of type `Either::Output>, impl Trait<::Output>>` - | - = note: the return type of a function must have a statically known size - -error[E0277]: the trait bound `impl Trait<::Output>: Trait` is not satisfied - --> $DIR/issue-58344.rs:42:52 - | -LL | ) -> Either>::Output>, impl Trait<>::Output>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `impl Trait<::Output>` -... -LL | add_generic(value, 1u32) - | ------------------------ this returned value is of type `Either::Output>, impl Trait<::Output>>` - | - = note: the return type of a function must have a statically known size - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs index 9c2b2dc9f4dae..9f4813071a1e7 100644 --- a/src/test/ui/issues/issue-60283.rs +++ b/src/test/ui/issues/issue-60283.rs @@ -16,4 +16,5 @@ where fn main() { foo((), drop) //~^ ERROR type mismatch in function arguments + //~| ERROR the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time } diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index ad679bfa22063..2922eb87e825f 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -13,6 +13,24 @@ LL | foo((), drop) | expected signature of `fn(<() as Trait<'a>>::Item) -> _` | found signature of `fn(()) -> _` -error: aborting due to previous error +error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time + --> $DIR/issue-60283.rs:17:13 + | +LL | foo((), drop) + | ^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/libcore/mem/mod.rs:LL:COL + | +LL | pub fn drop(_x: T) {} + | - required by this bound in `std::mem::drop` + | + = help: the trait `std::marker::Sized` is not implemented for `<() as Trait<'_>>::Item` +help: consider further restricting the associated type + | +LL | fn main() where <() as Trait<'_>>::Item: std::marker::Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0631`. +Some errors have detailed explanations: E0277, E0631. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs index 8218fecc3f12d..4954a8a6965be 100644 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs @@ -1,5 +1,4 @@ -// Running rustfix would cause the same suggestion to be applied multiple times, which results in -// invalid code. +// check-pass trait Parent { type Ty; @@ -17,7 +16,6 @@ struct ParentWrapper(T); impl> Parent for ParentWrapper { type Ty = A; type Assoc = ChildWrapper; - //~^ ERROR the trait bound `::Assoc: Child` is not satisfied } fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr deleted file mode 100644 index 676e2fb1a51dc..0000000000000 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:19:5 - | -LL | type Assoc: Child; - | --------------- required by this bound in `Parent::Assoc` -... -LL | type Assoc = ChildWrapper; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` - | - = note: required because of the requirements on the impl of `Child` for `ChildWrapper<::Assoc>` -help: consider further restricting the associated type - | -LL | impl> Parent for ParentWrapper where ::Assoc: Child { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. From 596d6c4b3b5e86e024cd02f7221749ee6958bec6 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 24 Jul 2020 21:59:43 +0100 Subject: [PATCH 21/34] Avoid cycle with projections from object types Normalizing ` as Iterator>::Item` no longer requires selecting `dyn Iterator: Iterator`. This was previously worked around by using a special type-folder to normalize things. --- .../src/traits/project.rs | 207 +++++++----------- .../src/traits/select/confirmation.rs | 176 ++++----------- .../src/traits/select/mod.rs | 4 +- src/test/ui/regions/regions-enum-not-wf.rs | 23 +- .../ui/regions/regions-enum-not-wf.stderr | 24 +- .../regions-normalize-in-where-clause-list.rs | 17 +- ...ions-normalize-in-where-clause-list.stderr | 24 +- .../regions-enum-not-wf.rs | 23 +- .../regions-enum-not-wf.stderr | 24 +- src/test/ui/traits/cycle-cache-err-60010.rs | 3 +- .../ui/traits/cycle-cache-err-60010.stderr | 18 +- 11 files changed, 193 insertions(+), 350 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index d52e54191006a..71a4623cd629b 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1,6 +1,5 @@ //! Code for projecting associated types out of trait references. -use super::elaborate_predicates; use super::specialization_graph; use super::translate_substs; use super::util; @@ -53,13 +52,16 @@ pub enum ProjectionTyError<'tcx> { #[derive(PartialEq, Eq, Debug)] enum ProjectionTyCandidate<'tcx> { - // from a where-clause in the env or object type + /// From a where-clause in the env or object type ParamEnv(ty::PolyProjectionPredicate<'tcx>), - // from the definition of `Trait` when you have something like <::B as Trait2>::C + /// From the definition of `Trait` when you have something like <::B as Trait2>::C TraitDef(ty::PolyProjectionPredicate<'tcx>), - // from a "impl" (or a "pseudo-impl" returned by select) + /// Bounds specified on an object type + Object(ty::PolyProjectionPredicate<'tcx>), + + /// From a "impl" (or a "pseudo-impl" returned by select) Select(Selection<'tcx>), } @@ -561,14 +563,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( } else { obligations.extend(ty.obligations); } - - obligations.push(get_paranoid_cache_value_obligation( - infcx, - param_env, - projection_ty, - cause, - depth, - )); return Ok(Some(ty.value)); } Err(ProjectionCacheEntry::Error) => { @@ -703,45 +697,6 @@ fn prune_cache_value_obligations<'a, 'tcx>( NormalizedTy { value: result.value, obligations } } -/// Whenever we give back a cache result for a projection like `::Item ==> X`, we *always* include the obligation to prove -/// that `T: Trait` (we may also include some other obligations). This -/// may or may not be necessary -- in principle, all the obligations -/// that must be proven to show that `T: Trait` were also returned -/// when the cache was first populated. But there are some vague concerns, -/// and so we take the precautionary measure of including `T: Trait` in -/// the result: -/// -/// Concern #1. The current setup is fragile. Perhaps someone could -/// have failed to prove the concerns from when the cache was -/// populated, but also not have used a snapshot, in which case the -/// cache could remain populated even though `T: Trait` has not been -/// shown. In this case, the "other code" is at fault -- when you -/// project something, you are supposed to either have a snapshot or -/// else prove all the resulting obligations -- but it's still easy to -/// get wrong. -/// -/// Concern #2. Even within the snapshot, if those original -/// obligations are not yet proven, then we are able to do projections -/// that may yet turn out to be wrong. This *may* lead to some sort -/// of trouble, though we don't have a concrete example of how that -/// can occur yet. But it seems risky at best. -fn get_paranoid_cache_value_obligation<'a, 'tcx>( - infcx: &'a InferCtxt<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::ProjectionTy<'tcx>, - cause: ObligationCause<'tcx>, - depth: usize, -) -> PredicateObligation<'tcx> { - let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref(); - Obligation { - cause, - recursion_depth: depth, - param_env, - predicate: trait_ref.without_const().to_predicate(infcx.tcx), - } -} - /// If we are projecting `::Item`, but `T: Trait` does not /// hold. In various error cases, we cannot generate a valid /// normalized projection. Therefore, we create an inference variable @@ -848,12 +803,21 @@ fn project_type<'cx, 'tcx>( assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates); - assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates); + assemble_candidates_from_object_ty(selcx, obligation, &obligation_trait_ref, &mut candidates); + + if let ProjectionTyCandidateSet::Single(ProjectionTyCandidate::Object(_)) = candidates { + // Avoid normalization cycle from selection (see + // `assemble_candidates_from_object_ty`). + // FIXME(lazy_normalization): Lazy normalization should save us from + // having to do special case this. + } else { + assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates); + }; match candidates { - ProjectionTyCandidateSet::Single(candidate) => Ok(ProjectedTy::Progress( - confirm_candidate(selcx, obligation, &obligation_trait_ref, candidate), - )), + ProjectionTyCandidateSet::Single(candidate) => { + Ok(ProjectedTy::Progress(confirm_candidate(selcx, obligation, candidate))) + } ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress( selcx .tcx() @@ -932,6 +896,53 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( ) } +/// In the case of a trait object like +/// ` as Iterator>::Item` we can use the existential +/// predicate in the trait object. +/// +/// We don't go through the select candidate for these bounds to avoid cycles: +/// In the above case, `dyn Iterator: Iterator` would create a +/// nested obligation of ` as Iterator>::Item: Sized`, +/// this then has to be normalized without having to prove +/// `dyn Iterator: Iterator` again. +fn assemble_candidates_from_object_ty<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + obligation_trait_ref: &ty::TraitRef<'tcx>, + candidate_set: &mut ProjectionTyCandidateSet<'tcx>, +) { + debug!("assemble_candidates_from_object_ty(..)"); + + let tcx = selcx.tcx(); + + let self_ty = obligation_trait_ref.self_ty(); + let object_ty = selcx.infcx().shallow_resolve(self_ty); + let data = match object_ty.kind { + ty::Dynamic(ref data, ..) => data, + ty::Infer(ty::TyVar(_)) => { + // If the self-type is an inference variable, then it MAY wind up + // being an object type, so induce an ambiguity. + candidate_set.mark_ambiguous(); + return; + } + _ => return, + }; + let env_predicates = data + .projection_bounds() + .filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id) + .map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx)); + + assemble_candidates_from_predicates( + selcx, + obligation, + obligation_trait_ref, + candidate_set, + ProjectionTyCandidate::Object, + env_predicates, + false, + ); +} + fn assemble_candidates_from_predicates<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, @@ -1000,7 +1011,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( super::ImplSource::Closure(_) | super::ImplSource::Generator(_) | super::ImplSource::FnPointer(_) - | super::ImplSource::Object(_) | super::ImplSource::TraitAlias(_) => { debug!("assemble_candidates_from_impls: impl_source={:?}", impl_source); true @@ -1125,6 +1135,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // in `assemble_candidates_from_param_env`. false } + super::ImplSource::Object(_) => { + // Handled by the `Object` projection candidate. See + // `assemble_candidates_from_object_ty` for an explanation of + // why we special case object types. + false + } super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) => { // These traits have no associated types. selcx.tcx().sess.delay_span_bug( @@ -1150,13 +1166,13 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( fn confirm_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, candidate: ProjectionTyCandidate<'tcx>, ) -> Progress<'tcx> { debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation); let mut progress = match candidate { - ProjectionTyCandidate::ParamEnv(poly_projection) => { + ProjectionTyCandidate::ParamEnv(poly_projection) + | ProjectionTyCandidate::Object(poly_projection) => { confirm_param_env_candidate(selcx, obligation, poly_projection, false) } @@ -1165,7 +1181,7 @@ fn confirm_candidate<'cx, 'tcx>( } ProjectionTyCandidate::Select(impl_source) => { - confirm_select_candidate(selcx, obligation, obligation_trait_ref, impl_source) + confirm_select_candidate(selcx, obligation, impl_source) } }; // When checking for cycle during evaluation, we compare predicates with @@ -1182,7 +1198,6 @@ fn confirm_candidate<'cx, 'tcx>( fn confirm_select_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, impl_source: Selection<'tcx>, ) -> Progress<'tcx> { match impl_source { @@ -1193,10 +1208,8 @@ fn confirm_select_candidate<'cx, 'tcx>( super::ImplSource::DiscriminantKind(data) => { confirm_discriminant_kind_candidate(selcx, obligation, data) } - super::ImplSource::Object(_) => { - confirm_object_candidate(selcx, obligation, obligation_trait_ref) - } - super::ImplSource::AutoImpl(..) + super::ImplSource::Object(_) + | super::ImplSource::AutoImpl(..) | super::ImplSource::Param(..) | super::ImplSource::Builtin(..) | super::ImplSource::TraitAlias(..) => @@ -1211,72 +1224,6 @@ fn confirm_select_candidate<'cx, 'tcx>( } } -fn confirm_object_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTyObligation<'tcx>, - obligation_trait_ref: &ty::TraitRef<'tcx>, -) -> Progress<'tcx> { - let self_ty = obligation_trait_ref.self_ty(); - let object_ty = selcx.infcx().shallow_resolve(self_ty); - debug!("confirm_object_candidate(object_ty={:?})", object_ty); - let data = match object_ty.kind() { - ty::Dynamic(data, ..) => data, - _ => span_bug!( - obligation.cause.span, - "confirm_object_candidate called with non-object: {:?}", - object_ty - ), - }; - let env_predicates = data - .projection_bounds() - .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate(selcx.tcx())); - let env_predicate = { - let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates); - - // select only those projections that are actually projecting an - // item with the correct name - - let env_predicates = env_predicates.filter_map(|o| match o.predicate.skip_binders() { - ty::PredicateAtom::Projection(data) - if data.projection_ty.item_def_id == obligation.predicate.item_def_id => - { - Some(ty::Binder::bind(data)) - } - _ => None, - }); - - // select those with a relevant trait-ref - let mut env_predicates = env_predicates.filter(|data| { - let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx()); - let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); - selcx.infcx().probe(|_| { - selcx - .infcx() - .at(&obligation.cause, obligation.param_env) - .sup(obligation_poly_trait_ref, data_poly_trait_ref) - .is_ok() - }) - }); - - // select the first matching one; there really ought to be one or - // else the object type is not WF, since an object type should - // include all of its projections explicitly - match env_predicates.next() { - Some(env_predicate) => env_predicate, - None => { - debug!( - "confirm_object_candidate: no env-predicate \ - found in object type `{:?}`; ill-formed", - object_ty - ); - return Progress::error(selcx.tcx()); - } - } - }; - - confirm_param_env_candidate(selcx, obligation, env_predicate, false) -} - fn confirm_generator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index e6fce78f269ca..1e68554fecf53 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -9,11 +9,10 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; +use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; -use rustc_infer::infer::{self, InferOk}; -use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness}; use rustc_span::def_id::DefId; @@ -434,100 +433,54 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vtable_base = nonmatching.map(|t| super::util::count_own_vtable_entries(tcx, t)).sum(); } - // Check supertraits hold - nested.extend(util::supertraits(tcx, obligation_trait_ref).skip(1).map(|super_trait| { - Obligation::new( - obligation.cause.clone(), - obligation.param_env, - super_trait.without_const().to_predicate(tcx), - ) - })); - let upcast_trait_ref = upcast_trait_ref.unwrap(); + // Check supertraits hold + nested.extend( + tcx.super_predicates_of(trait_predicate.def_id()) + .instantiate(tcx, trait_predicate.trait_ref.substs) + .predicates + .into_iter() + .map(|super_trait| { + Obligation::new(obligation.cause.clone(), obligation.param_env, super_trait) + }), + ); + let assoc_types: Vec<_> = tcx - .associated_items(upcast_trait_ref.def_id()) + .associated_items(trait_predicate.def_id()) .in_definition_order() .filter_map( |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None }, ) .collect(); - if !assoc_types.is_empty() { - let predicates: Vec<_> = - data.iter() - .filter_map(|pred| match pred { - ty::ExistentialPredicate::Projection(proj) => { - if assoc_types.contains(&proj.item_def_id) { - match self.infcx.commit_if_ok(|_| { - self.infcx - .at(&obligation.cause, obligation.param_env) - .sup( - ty::Binder::dummy( - proj.trait_ref(tcx).with_self_ty(tcx, self_ty), - ), - upcast_trait_ref, - ) - .map(|InferOk { obligations, .. }| obligations) - .map_err(|_| ()) - }) { - Ok(obligations) => { - nested.extend(obligations); - Some(proj) - } - Err(_) => None, - } - } else { - None - } - } - ty::ExistentialPredicate::AutoTrait(_) - | ty::ExistentialPredicate::Trait(_) => None, - }) - .collect(); - - let upcast_trait_ref = upcast_trait_ref - .no_bound_vars() - .expect("sup shouldn't return binder with bound vars"); - let mut normalizer = ObjectAssociatedTypeNormalizer { - infcx: self.infcx, - object_ty: self_ty, - object_bounds: &predicates, - param_env: obligation.param_env, - cause: &obligation.cause, - nested: &mut nested, - }; - for assoc_type in assoc_types { - if !tcx.generics_of(assoc_type).params.is_empty() { - // FIXME(generic_associated_types) generate placeholders to - // extend the trait substs. - tcx.sess.span_fatal( - obligation.cause.span, - "generic associated types in trait objects are not supported yet", - ); - } - // This maybe belongs in wf, but that can't (doesn't) handle - // higher-ranked things. - // Prevent, e.g., `dyn Iterator`. - for bound in self.tcx().item_bounds(assoc_type) { - let subst_bound = bound.subst(tcx, upcast_trait_ref.substs); - // Normalize projections the trait object manually to - // avoid evaluation overflow. - let object_normalized = subst_bound.fold_with(&mut normalizer); - let normalized_bound = normalize_with_depth_to( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &object_normalized, - normalizer.nested, - ); - normalizer.nested.push(Obligation::new( - obligation.cause.clone(), - obligation.param_env.clone(), - normalized_bound, - )); - } + for assoc_type in assoc_types { + if !tcx.generics_of(assoc_type).params.is_empty() { + // FIXME(generic_associated_types) generate placeholders to + // extend the trait substs. + tcx.sess.span_fatal( + obligation.cause.span, + "generic associated types in trait objects are not supported yet", + ); + } + // This maybe belongs in wf, but that can't (doesn't) handle + // higher-ranked things. + // Prevent, e.g., `dyn Iterator`. + for bound in self.tcx().item_bounds(assoc_type) { + let subst_bound = bound.subst(tcx, trait_predicate.trait_ref.substs); + let normalized_bound = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &subst_bound, + &mut nested, + ); + nested.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env.clone(), + normalized_bound, + )); } } @@ -972,50 +925,3 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(ImplSourceBuiltinData { nested }) } } - -struct ObjectAssociatedTypeNormalizer<'a, 'tcx> { - infcx: &'a infer::InferCtxt<'a, 'tcx>, - object_ty: Ty<'tcx>, - object_bounds: &'a [ty::ExistentialProjection<'tcx>], - param_env: ty::ParamEnv<'tcx>, - cause: &'a ObligationCause<'tcx>, - nested: &'a mut Vec>, -} - -impl<'tcx> TypeFolder<'tcx> for ObjectAssociatedTypeNormalizer<'_, 'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.has_projections() { - return t; - } - if let ty::Projection(proj) = t.kind { - if let ty::Dynamic(..) = proj.self_ty().kind { - for bound in self.object_bounds { - if proj.item_def_id == bound.item_def_id { - // FIXME(generic_associated_types): This isn't relating - // the substs for the associated type. - match self.infcx.commit_if_ok(|_| { - self.infcx.at(self.cause, self.param_env).sub( - bound - .with_self_ty(self.infcx.tcx, self.object_ty) - .projection_ty - .trait_ref(self.infcx.tcx), - proj.trait_ref(self.infcx.tcx), - ) - }) { - Ok(InferOk { value: (), obligations }) => { - self.nested.extend(obligations); - return bound.ty; - } - Err(_) => {} - } - } - } - } - } - t.super_fold_with(self) - } -} diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 147b0c74d16e8..d0c0e658c921f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -441,8 +441,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result { debug!( "evaluate_predicate_recursively(obligation={:?}, previous_stack={:?})", - previous_stack.head(), - obligation + obligation, + previous_stack.head() ); // `previous_stack` stores a `TraitObligation`, while `obligation` is diff --git a/src/test/ui/regions/regions-enum-not-wf.rs b/src/test/ui/regions/regions-enum-not-wf.rs index 781cdb7286a0e..6de08f66d7536 100644 --- a/src/test/ui/regions/regions-enum-not-wf.rs +++ b/src/test/ui/regions/regions-enum-not-wf.rs @@ -5,17 +5,18 @@ #![allow(dead_code)] trait Dummy<'a> { - type Out; + type Out; } impl<'a, T> Dummy<'a> for T -where T: 'a +where + T: 'a, { - type Out = (); + type Out = (); } type RequireOutlives<'a, T> = >::Out; enum Ref1<'a, T> { - Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough + Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough } enum Ref2<'a, T> { @@ -23,18 +24,18 @@ enum Ref2<'a, T> { Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough } -enum RefOk<'a, T:'a> { - RefOkVariant1(&'a T) +enum RefOk<'a, T: 'a> { + RefOkVariant1(&'a T), } // This is now well formed. RFC 2093 enum RefIndirect<'a, T> { - RefIndirectVariant1(isize, RefOk<'a,T>) + RefIndirectVariant1(isize, RefOk<'a, T>), } -enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309] - RefDoubleVariant1(&'a RequireOutlives<'b, T>) - //~^ the parameter type `T` may not live long enough [E0309] +enum RefDouble<'a, 'b, T> { + RefDoubleVariant1(&'a RequireOutlives<'b, T>), + //~^ the parameter type `T` may not live long enough [E0309] } -fn main() { } +fn main() {} diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr index e32a36f72cd14..36686eaf92f32 100644 --- a/src/test/ui/regions/regions-enum-not-wf.stderr +++ b/src/test/ui/regions/regions-enum-not-wf.stderr @@ -1,13 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:18:18 + --> $DIR/regions-enum-not-wf.rs:19:18 | LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` -LL | Ref1Variant1(RequireOutlives<'a, T>) +LL | Ref1Variant1(RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:23:25 + --> $DIR/regions-enum-not-wf.rs:24:25 | LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` @@ -16,25 +16,13 @@ LL | Ref2Variant2(isize, RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:35:1 - | -LL | enum RefDouble<'a, 'b, T> { - | ^ - help: consider adding an explicit lifetime bound...: `T: 'b` - | _| - | | -LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) -LL | | -LL | | } - | |_^ ...so that the type `T` will meet its required lifetime bounds - -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:36:23 + --> $DIR/regions-enum-not-wf.rs:37:23 | LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` -LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) +LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs index e912805d855d2..9912e88c2ec57 100644 --- a/src/test/ui/regions/regions-normalize-in-where-clause-list.rs +++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.rs @@ -6,7 +6,8 @@ trait Project<'a, 'b> { } impl<'a, 'b> Project<'a, 'b> for () - where 'a: 'b +where + 'a: 'b, { type Item = (); } @@ -14,16 +15,18 @@ impl<'a, 'b> Project<'a, 'b> for () // No error here, we have 'a: 'b. We used to report an error here // though, see https://github.com/rust-lang/rust/issues/45937. fn foo<'a: 'b, 'b>() - where <() as Project<'a, 'b>>::Item : Eq +where + <() as Project<'a, 'b>>::Item: Eq, { } // Here we get an error: we need `'a: 'b`. -fn bar<'a, 'b>() //~ ERROR cannot infer - //~| ERROR cannot infer - //~| ERROR cannot infer - where <() as Project<'a, 'b>>::Item : Eq +fn bar<'a, 'b>() +//~^ ERROR cannot infer +//~| ERROR cannot infer +where + <() as Project<'a, 'b>>::Item: Eq, { } -fn main() { } +fn main() {} diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr index 10ecb8d526292..24bf64261e9d2 100644 --- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr +++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -1,5 +1,5 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-normalize-in-where-clause-list.rs:22:1 + --> $DIR/regions-normalize-in-where-clause-list.rs:24:1 | LL | / fn bar<'a, 'b>() LL | | @@ -7,18 +7,18 @@ LL | | LL | | where <() as Project<'a, 'b>>::Item : Eq | |____________________________________________^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:8 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:8 | LL | fn bar<'a, 'b>() | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:12 +note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:12 | LL | fn bar<'a, 'b>() | ^^ note: ...so that the types are compatible - --> $DIR/regions-normalize-in-where-clause-list.rs:22:1 + --> $DIR/regions-normalize-in-where-clause-list.rs:24:1 | LL | / fn bar<'a, 'b>() LL | | @@ -64,24 +64,24 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | fn bar<'a, 'b>() | ^^^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:8 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:8 | LL | fn bar<'a, 'b>() | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:12 +note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 24:12... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:12 | LL | fn bar<'a, 'b>() | ^^ note: ...so that the types are compatible - --> $DIR/regions-normalize-in-where-clause-list.rs:22:4 + --> $DIR/regions-normalize-in-where-clause-list.rs:24:4 | LL | fn bar<'a, 'b>() | ^^^ = note: expected `Project<'a, 'b>` found `Project<'_, '_>` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs index 781cdb7286a0e..6de08f66d7536 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs +++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs @@ -5,17 +5,18 @@ #![allow(dead_code)] trait Dummy<'a> { - type Out; + type Out; } impl<'a, T> Dummy<'a> for T -where T: 'a +where + T: 'a, { - type Out = (); + type Out = (); } type RequireOutlives<'a, T> = >::Out; enum Ref1<'a, T> { - Ref1Variant1(RequireOutlives<'a, T>) //~ ERROR the parameter type `T` may not live long enough + Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough } enum Ref2<'a, T> { @@ -23,18 +24,18 @@ enum Ref2<'a, T> { Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough } -enum RefOk<'a, T:'a> { - RefOkVariant1(&'a T) +enum RefOk<'a, T: 'a> { + RefOkVariant1(&'a T), } // This is now well formed. RFC 2093 enum RefIndirect<'a, T> { - RefIndirectVariant1(isize, RefOk<'a,T>) + RefIndirectVariant1(isize, RefOk<'a, T>), } -enum RefDouble<'a, 'b, T> { //~ ERROR the parameter type `T` may not live long enough [E0309] - RefDoubleVariant1(&'a RequireOutlives<'b, T>) - //~^ the parameter type `T` may not live long enough [E0309] +enum RefDouble<'a, 'b, T> { + RefDoubleVariant1(&'a RequireOutlives<'b, T>), + //~^ the parameter type `T` may not live long enough [E0309] } -fn main() { } +fn main() {} diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr index e32a36f72cd14..36686eaf92f32 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr @@ -1,13 +1,13 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:18:18 + --> $DIR/regions-enum-not-wf.rs:19:18 | LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` -LL | Ref1Variant1(RequireOutlives<'a, T>) +LL | Ref1Variant1(RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:23:25 + --> $DIR/regions-enum-not-wf.rs:24:25 | LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` @@ -16,25 +16,13 @@ LL | Ref2Variant2(isize, RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:35:1 - | -LL | enum RefDouble<'a, 'b, T> { - | ^ - help: consider adding an explicit lifetime bound...: `T: 'b` - | _| - | | -LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) -LL | | -LL | | } - | |_^ ...so that the type `T` will meet its required lifetime bounds - -error[E0309]: the parameter type `T` may not live long enough - --> $DIR/regions-enum-not-wf.rs:36:23 + --> $DIR/regions-enum-not-wf.rs:37:23 | LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` -LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) +LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/traits/cycle-cache-err-60010.rs b/src/test/ui/traits/cycle-cache-err-60010.rs index 62d558fde888e..98bfcb8d67b51 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.rs +++ b/src/test/ui/traits/cycle-cache-err-60010.rs @@ -24,7 +24,7 @@ struct Runtime { _storage: Box, } struct SalsaStorage { - _parse: >::Data, //~ ERROR overflow + _parse: >::Data, } impl Database for RootDatabase { @@ -67,6 +67,7 @@ pub(crate) fn goto_implementation(db: &RootDatabase) -> u32 { // we used to fail to report an error here because we got the // caching wrong. SourceDatabase::parse(db); + //~^ ERROR overflow 22 } diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index 25b1f427f3a16..738b052a11ebb 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -1,10 +1,18 @@ -error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase` - --> $DIR/cycle-cache-err-60010.rs:27:13 +error[E0275]: overflow evaluating the requirement `SalsaStorage: std::panic::RefUnwindSafe` + --> $DIR/cycle-cache-err-60010.rs:69:5 | -LL | _parse: >::Data, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn parse(&self) { + | --------------- required by `SourceDatabase::parse` +... +LL | SourceDatabase::parse(db); + | ^^^^^^^^^^^^^^^^^^^^^ | - = note: required because of the requirements on the impl of `Query` for `ParseQuery` + = note: required because it appears within the type `*const SalsaStorage` + = note: required because it appears within the type `std::ptr::Unique` + = note: required because it appears within the type `std::boxed::Box` + = note: required because it appears within the type `Runtime` + = note: required because it appears within the type `RootDatabase` + = note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase` error[E0275]: overflow evaluating the requirement `Runtime: RefUnwindSafe` --> $DIR/cycle-cache-err-60010.rs:31:20 From 0dfa6ff3be2316f91b7f148ff30617287278617a Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 25 Jul 2020 13:41:53 +0100 Subject: [PATCH 22/34] Avoid cycles from projection bounds Only check the own predicates of associated types when confirming projection candidates. Also consider implied bounds when comparing trait and impl methods. --- .../src/traits/project.rs | 39 +++++++++++++++++-- .../src/traits/select/confirmation.rs | 36 +++++++++-------- .../rustc_typeck/src/check/compare_method.rs | 2 +- src/test/ui/associated-types/wf-cycle-2.rs | 18 +++++++++ src/test/ui/associated-types/wf-cycle.rs | 13 +++++++ src/test/ui/regions/regions-trait-1.rs | 23 ++++++----- src/test/ui/regions/regions-trait-1.stderr | 22 ----------- src/test/ui/specialization/issue-38091-2.rs | 9 ++++- .../ui/specialization/issue-38091-2.stderr | 13 ++----- src/test/ui/specialization/issue-38091.rs | 6 ++- src/test/ui/specialization/issue-38091.stderr | 18 ++------- 11 files changed, 118 insertions(+), 81 deletions(-) create mode 100644 src/test/ui/associated-types/wf-cycle-2.rs create mode 100644 src/test/ui/associated-types/wf-cycle.rs delete mode 100644 src/test/ui/regions/regions-trait-1.stderr diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 71a4623cd629b..8f7513cf27c36 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -28,7 +28,6 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_span::symbol::sym; -use rustc_span::DUMMY_SP; pub use rustc_middle::traits::Reveal; @@ -1409,6 +1408,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) { Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); + assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); Progress { ty: cache_entry.ty, obligations: nested_obligations } } Err(e) => { @@ -1430,7 +1430,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { let tcx = selcx.tcx(); - let ImplSourceUserDefinedData { impl_def_id, substs, nested } = impl_impl_source; + let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source; let assoc_item_id = obligation.predicate.item_def_id; let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); @@ -1463,15 +1463,48 @@ fn confirm_impl_candidate<'cx, 'tcx>( let ty = tcx.type_of(assoc_ty.item.def_id); if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() { let err = tcx.ty_error_with_message( - DUMMY_SP, + obligation.cause.span, "impl item and trait item have different parameter counts", ); Progress { ty: err, obligations: nested } } else { + assoc_ty_own_obligations(selcx, obligation, &mut nested); Progress { ty: ty.subst(tcx, substs), obligations: nested } } } +// Get obligations corresponding to the predicates from the where-clause of the +// associated type itself. +// Note: `feature(generic_associated_types)` is required to write such +// predicates, even for non-generic associcated types. +fn assoc_ty_own_obligations<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + nested: &mut Vec>, +) { + let tcx = selcx.tcx(); + for predicate in tcx + .predicates_of(obligation.predicate.item_def_id) + .instantiate_own(tcx, obligation.predicate.substs) + .predicates + { + let normalized = normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &predicate, + nested, + ); + nested.push(Obligation::with_depth( + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + normalized, + )); + } +} + /// Locate the definition of an associated type in the specialization hierarchy, /// starting from the given impl. /// diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 1e68554fecf53..21293615bc98c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -157,22 +157,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); }), ); - // Require that the projection is well-formed. - let self_ty = self.infcx.replace_bound_vars_with_placeholders(&bound_self_ty); - let self_ty = normalize_with_depth_to( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &self_ty, - &mut obligations, - ); - obligations.push(Obligation::with_depth( - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - ty::PredicateKind::WellFormed(self_ty.into()).to_predicate(tcx), - )); + + if let ty::Projection(..) = bound_self_ty.skip_binder().kind { + for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates { + let normalized = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &predicate, + &mut obligations, + ); + obligations.push(Obligation::with_depth( + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + normalized, + )); + } + } + obligations }) } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index ee21167ff975d..788590e50f3b0 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -328,7 +328,7 @@ fn compare_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id); - fcx.regionck_item(impl_m_hir_id, impl_m_span, &[]); + fcx.regionck_item(impl_m_hir_id, impl_m_span, trait_sig.inputs_and_output); Ok(()) }) diff --git a/src/test/ui/associated-types/wf-cycle-2.rs b/src/test/ui/associated-types/wf-cycle-2.rs new file mode 100644 index 0000000000000..d7467ac22371f --- /dev/null +++ b/src/test/ui/associated-types/wf-cycle-2.rs @@ -0,0 +1,18 @@ +// check-pass + +trait IntoIt { + type Item; +} + +impl IntoIt for I { + type Item = (); +} + +trait BaseGraph +where + ::Item: Sized, +{ + type VertexIter: IntoIt; +} + +fn main() {} diff --git a/src/test/ui/associated-types/wf-cycle.rs b/src/test/ui/associated-types/wf-cycle.rs new file mode 100644 index 0000000000000..cf6508551a558 --- /dev/null +++ b/src/test/ui/associated-types/wf-cycle.rs @@ -0,0 +1,13 @@ +// check-pass + +trait A { + type U: Copy; +} + +trait B where + ::U: Copy, +{ + type V: A; +} + +fn main() {} diff --git a/src/test/ui/regions/regions-trait-1.rs b/src/test/ui/regions/regions-trait-1.rs index 0da8ac53695e9..b6dab1c32e8b2 100644 --- a/src/test/ui/regions/regions-trait-1.rs +++ b/src/test/ui/regions/regions-trait-1.rs @@ -1,30 +1,33 @@ -#![feature(box_syntax)] +// check-pass -struct Ctxt { v: usize } +struct Ctxt { + v: usize, +} trait GetCtxt { // Here the `&` is bound in the method definition: fn get_ctxt(&self) -> &Ctxt; } -struct HasCtxt<'a> { c: &'a Ctxt } +struct HasCtxt<'a> { + c: &'a Ctxt, +} impl<'a> GetCtxt for HasCtxt<'a> { - - // Here an error occurs because we used `&self` but - // the definition used `&`: - fn get_ctxt(&self) -> &'a Ctxt { //~ ERROR method not compatible with trait + // Ok: Have implied bound of WF(&'b HasCtxt<'a>) + // so know 'a: 'b + // so know &'a Ctxt <: &'b Ctxt + fn get_ctxt<'b>(&'b self) -> &'a Ctxt { self.c } - } -fn get_v(gc: Box) -> usize { +fn get_v(gc: Box) -> usize { gc.get_ctxt().v } fn main() { let ctxt = Ctxt { v: 22 }; let hc = HasCtxt { c: &ctxt }; - assert_eq!(get_v(box hc as Box), 22); + assert_eq!(get_v(Box::new(hc) as Box), 22); } diff --git a/src/test/ui/regions/regions-trait-1.stderr b/src/test/ui/regions/regions-trait-1.stderr deleted file mode 100644 index 92d96a722d4e9..0000000000000 --- a/src/test/ui/regions/regions-trait-1.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0308]: method not compatible with trait - --> $DIR/regions-trait-1.rs:16:5 - | -LL | fn get_ctxt(&self) -> &'a Ctxt { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected fn pointer `fn(&HasCtxt<'a>) -> &Ctxt` - found fn pointer `fn(&HasCtxt<'a>) -> &'a Ctxt` -note: the lifetime `'a` as defined on the impl at 12:6... - --> $DIR/regions-trait-1.rs:12:6 - | -LL | impl<'a> GetCtxt for HasCtxt<'a> { - | ^^ -note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 16:5 - --> $DIR/regions-trait-1.rs:16:5 - | -LL | fn get_ctxt(&self) -> &'a Ctxt { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/specialization/issue-38091-2.rs b/src/test/ui/specialization/issue-38091-2.rs index da7f673773356..9ed0b240d0a0f 100644 --- a/src/test/ui/specialization/issue-38091-2.rs +++ b/src/test/ui/specialization/issue-38091-2.rs @@ -1,3 +1,6 @@ +// build-fail +//~^ ERROR overflow evaluating the requirement `i32: Check` + #![feature(specialization)] //~^ WARN the feature `specialization` is incomplete @@ -5,7 +8,10 @@ trait Iterate<'a> { type Ty: Valid; fn iterate(self); } -impl<'a, T> Iterate<'a> for T where T: Check { +impl<'a, T> Iterate<'a> for T +where + T: Check, +{ default type Ty = (); default fn iterate(self) {} } @@ -19,5 +25,4 @@ impl Valid for () {} fn main() { Iterate::iterate(0); - //~^ ERROR overflow evaluating the requirement `{integer}: Check` } diff --git a/src/test/ui/specialization/issue-38091-2.stderr b/src/test/ui/specialization/issue-38091-2.stderr index e776ff0fafb23..a314c26ad147d 100644 --- a/src/test/ui/specialization/issue-38091-2.stderr +++ b/src/test/ui/specialization/issue-38091-2.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-38091-2.rs:1:12 + --> $DIR/issue-38091-2.rs:4:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -7,16 +7,9 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #31844 for more information -error[E0275]: overflow evaluating the requirement `{integer}: Check` - --> $DIR/issue-38091-2.rs:21:5 +error[E0275]: overflow evaluating the requirement `i32: Check` | -LL | fn iterate(self); - | ----------------- required by `Iterate::iterate` -... -LL | Iterate::iterate(0); - | ^^^^^^^^^^^^^^^^ - | - = note: required because of the requirements on the impl of `Iterate<'_>` for `{integer}` + = note: required because of the requirements on the impl of `Iterate` for `i32` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/specialization/issue-38091.rs b/src/test/ui/specialization/issue-38091.rs index cc0eeb53687de..5b398368a6733 100644 --- a/src/test/ui/specialization/issue-38091.rs +++ b/src/test/ui/specialization/issue-38091.rs @@ -5,7 +5,10 @@ trait Iterate<'a> { type Ty: Valid; fn iterate(self); } -impl<'a, T> Iterate<'a> for T where T: Check { +impl<'a, T> Iterate<'a> for T +where + T: Check, +{ default type Ty = (); //~^ ERROR the trait bound `(): Valid` is not satisfied default fn iterate(self) {} @@ -18,5 +21,4 @@ trait Valid {} fn main() { Iterate::iterate(0); - //~^ ERROR overflow evaluating the requirement `{integer}: Check` } diff --git a/src/test/ui/specialization/issue-38091.stderr b/src/test/ui/specialization/issue-38091.stderr index beec702b89e46..6be0f26849f90 100644 --- a/src/test/ui/specialization/issue-38091.stderr +++ b/src/test/ui/specialization/issue-38091.stderr @@ -8,7 +8,7 @@ LL | #![feature(specialization)] = note: see issue #31844 for more information error[E0277]: the trait bound `(): Valid` is not satisfied - --> $DIR/issue-38091.rs:9:5 + --> $DIR/issue-38091.rs:12:5 | LL | type Ty: Valid; | ----- required by this bound in `Iterate::Ty` @@ -16,18 +16,6 @@ LL | type Ty: Valid; LL | default type Ty = (); | ^^^^^^^^^^^^^^^^^^^^^ the trait `Valid` is not implemented for `()` -error[E0275]: overflow evaluating the requirement `{integer}: Check` - --> $DIR/issue-38091.rs:20:5 - | -LL | fn iterate(self); - | ----------------- required by `Iterate::iterate` -... -LL | Iterate::iterate(0); - | ^^^^^^^^^^^^^^^^ - | - = note: required because of the requirements on the impl of `Iterate<'_>` for `{integer}` - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted -Some errors have detailed explanations: E0275, E0277. -For more information about an error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0277`. From ed324825341dbc763a8044f769eb0544afe87f08 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 25 Jul 2020 14:00:13 +0100 Subject: [PATCH 23/34] Handle multiple trait-def projection candidates --- .../rustc_trait_selection/src/traits/project.rs | 7 +++++++ ...ssociated-types-projection-bound-ambiguity.rs | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8f7513cf27c36..c33c8a67aa849 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -977,6 +977,13 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( if is_match { candidate_set.push_candidate(ctor(data)); + + if potentially_unnormalized_candidates && !obligation.predicate.needs_infer() { + // HACK: Pick the first trait def candidate for a fully + // inferred predicate. This is to allow duplicates that + // differ only in normalization. + return; + } } } } diff --git a/src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs b/src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs new file mode 100644 index 0000000000000..353f82e7c6e63 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-projection-bound-ambiguity.rs @@ -0,0 +1,16 @@ +// Check that if we have multiple applicable projection bounds we pick one (for +// backwards compatibility reasons). + +// check-pass +use std::ops::Mul; + +trait A { + type V; + type U: Mul + Mul<(), Output = ()>; +} + +fn g>() { + let y: >::Output = (); +} + +fn main() {} From 6c4feb681f8062060ed0c21d311c27eba8791d42 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 25 Jul 2020 15:14:12 +0100 Subject: [PATCH 24/34] Fix bootstrap --- compiler/rustc_trait_selection/src/traits/project.rs | 4 +++- .../src/traits/select/candidate_assembly.rs | 2 +- src/test/ui/issues/issue-60283.rs | 2 +- src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c33c8a67aa849..518719d76d4f6 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -978,7 +978,9 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( if is_match { candidate_set.push_candidate(ctor(data)); - if potentially_unnormalized_candidates && !obligation.predicate.needs_infer() { + if potentially_unnormalized_candidates + && !obligation.predicate.has_infer_types_or_consts() + { // HACK: Pick the first trait def candidate for a fully // inferred predicate. This is to allow duplicates that // differ only in normalization. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 1ac9be64f1f1f..038ba431c47d3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -165,7 +165,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates); - let needs_infer = stack.obligation.predicate.needs_infer(); + let needs_infer = stack.obligation.predicate.has_infer_types_or_consts(); // If there are STILL multiple candidates, we can further // reduce the list by dropping duplicates -- including diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs index 9f4813071a1e7..c63b1544a5379 100644 --- a/src/test/ui/issues/issue-60283.rs +++ b/src/test/ui/issues/issue-60283.rs @@ -16,5 +16,5 @@ where fn main() { foo((), drop) //~^ ERROR type mismatch in function arguments - //~| ERROR the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time + //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time } diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr index 42468b91a6267..574be0eb0a257 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -12,8 +12,8 @@ error[E0308]: mismatched types LL | type X<'a> = impl Into<&'static str> + From<&'a str>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected type `std::convert::From<&'a str>` - found type `std::convert::From<&'static str>` + = note: expected trait `std::convert::From<&'a str>` + found trait `std::convert::From<&'static str>` note: the lifetime `'a` as defined on the item at 6:8... --> $DIR/bounds-are-checked.rs:6:8 | From e29765250b84809dc11fc26220dfcc544680d582 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 25 Jul 2020 21:27:34 +0100 Subject: [PATCH 25/34] Don't immediately error for recursive projections --- compiler/rustc_error_codes/src/error_codes/E0284.md | 2 +- .../associated-type-bounds/bad-bounds-on-assoc-in-trait.rs | 4 +++- .../bad-bounds-on-assoc-in-trait.stderr | 6 +++--- src/test/ui/associated-types/defaults-cyclic-fail-1.stderr | 7 +++---- src/test/ui/associated-types/defaults-cyclic-fail-2.stderr | 4 ++-- src/test/ui/issues/issue-21946.stderr | 2 +- src/test/ui/issues/issue-23122-1.stderr | 2 +- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0284.md b/compiler/rustc_error_codes/src/error_codes/E0284.md index 18519b471b203..82598aeec0215 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0284.md +++ b/compiler/rustc_error_codes/src/error_codes/E0284.md @@ -14,7 +14,7 @@ fn main() { Here we have an addition of `d` and `n.into()`. Hence, `n.into()` can return any type `T` where `u64: Add`. On the other hand, the `into` method can -rteurn any type where `u32: Into`. +return any type where `u32: Into`. The author of this code probably wants `into()` to return a `u64`, but the compiler can't be sure that there isn't another type `T` where both diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs index 8093c4b9d9ec0..4f9100b677449 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs @@ -24,7 +24,9 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { trait Case1 { type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; - //~^ ERROR overflow evaluating the requirement `<::C as std::iter::Iterator>::Item` + //~^ ERROR `<::C as std::iter::Iterator>::Item` is not an iterator + //~| ERROR `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely + //~| ERROR `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely } pub struct S1; diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index abaae7e5343dd..c95c5ca588486 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `<::C as std::iter::Iterator>::Item` +error[E0277]: `<::C as std::iter::Iterator>::Item` is not an iterator --> $DIR/bad-bounds-on-assoc-in-trait.rs:28:5 | LL | / type C: Clone + Iterator::C as std::iter::Iterator>::Item: std::marker::Sync { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr index 28decb0934ca7..ae7150d47ca99 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -1,10 +1,10 @@ -error[E0275]: overflow evaluating the requirement `::B` +error[E0271]: type mismatch resolving `::B == _` --> $DIR/defaults-cyclic-fail-1.rs:26:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error[E0275]: overflow evaluating the requirement `::A` +error[E0271]: type mismatch resolving `::A == _` --> $DIR/defaults-cyclic-fail-1.rs:32:5 | LL | type B = &'static Self::A; @@ -12,5 +12,4 @@ LL | type B = &'static Self::A; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0271, E0275. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr index 6b6d5348c153b..0dfbac2dec5d5 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -1,10 +1,10 @@ -error[E0275]: overflow evaluating the requirement `::B` +error[E0271]: type mismatch resolving `::B == _` --> $DIR/defaults-cyclic-fail-2.rs:27:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size -error[E0275]: overflow evaluating the requirement `::A` +error[E0271]: type mismatch resolving `::A == _` --> $DIR/defaults-cyclic-fail-2.rs:33:5 | LL | type B = &'static Self::A; diff --git a/src/test/ui/issues/issue-21946.stderr b/src/test/ui/issues/issue-21946.stderr index 8b96e0f3382bb..0497bd20469a0 100644 --- a/src/test/ui/issues/issue-21946.stderr +++ b/src/test/ui/issues/issue-21946.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `::A` +error[E0275]: overflow evaluating the requirement `::A == _` --> $DIR/issue-21946.rs:8:5 | LL | type A = ::A; diff --git a/src/test/ui/issues/issue-23122-1.stderr b/src/test/ui/issues/issue-23122-1.stderr index f837490537067..1f78b0d152d1b 100644 --- a/src/test/ui/issues/issue-23122-1.stderr +++ b/src/test/ui/issues/issue-23122-1.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement ` as Next>::Next` +error[E0275]: overflow evaluating the requirement ` as Next>::Next == _` --> $DIR/issue-23122-1.rs:8:5 | LL | type Next = as Next>::Next; From d08ab945de8ede93366c6ffc12ed58068a73b4a0 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 14 Aug 2020 21:41:20 +0100 Subject: [PATCH 26/34] Fix rebase --- .../src/traits/fulfill.rs | 4 +- .../rustc_trait_selection/src/traits/mod.rs | 1 - .../src/traits/select/mod.rs | 2 +- .../rustc_trait_selection/src/traits/util.rs | 67 +------------------ .../rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_traits/src/chalk/lowering.rs | 28 ++++---- .../rustc_typeck/src/check/compare_method.rs | 23 +++---- compiler/rustc_typeck/src/collect.rs | 16 ++--- .../rustc_typeck/src/collect/item_bounds.rs | 10 ++- .../bounds-on-assoc-in-trait.stderr | 4 +- .../associated-types/defaults-suitability.rs | 3 +- .../defaults-suitability.stderr | 26 ++----- .../ui/associated-types/defaults-wf.stderr | 2 +- ...feature-gate-associated_type_bounds.stderr | 2 +- .../feature-gate-generic_associated_types.rs | 1 + ...ature-gate-generic_associated_types.stderr | 20 ++++-- src/test/ui/generator/sized-yield.stderr | 2 +- .../generic-associated-types-where.rs | 3 +- .../generic-associated-types-where.stderr | 19 +++++- .../generic-associated-types/impl_bounds.rs | 1 + .../impl_bounds.stderr | 2 +- .../impl_bounds_ok.rs | 5 +- .../unsatisfied-outlives-bound.rs | 4 +- .../unsatisfied-outlives-bound.stderr | 20 ++---- src/test/ui/issues/issue-60283.stderr | 2 +- ...ssoc-type-region-bound-in-trait-not-met.rs | 10 +-- ...-type-region-bound-in-trait-not-met.stderr | 26 +++---- ...ssoc-type-static-bound-in-trait-not-met.rs | 6 +- ...-type-static-bound-in-trait-not-met.stderr | 11 +-- 29 files changed, 121 insertions(+), 201 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 289e0e0ba63ec..27751eb554d3c 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -376,7 +376,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { | ty::PredicateAtom::Subtype(_) | ty::PredicateAtom::ConstEvaluatable(..) | ty::PredicateAtom::ConstEquate(..) => { - let (pred, _) = infcx.replace_bound_vars_with_placeholders(binder); + let pred = infcx.replace_bound_vars_with_placeholders(binder); ProcessResult::Changed(mk_pending(vec![ obligation.with(pred.to_predicate(self.selcx.tcx())), ])) @@ -673,7 +673,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { Ok(Ok(None)) => { *stalled_on = trait_ref_infer_vars( self.selcx, - project_obligation.predicate.to_poly_trait_ref(self.selcx.tcx()), + project_obligation.predicate.to_poly_trait_ref(tcx), ); ProcessResult::Unchanged } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index d819740b59665..c93087a18cf04 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -59,7 +59,6 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; pub use self::specialize::{specialization_graph, translate_substs, OverlapError}; pub use self::structural_match::search_for_structural_match_violation; pub use self::structural_match::NonStructuralMatchTy; -pub use self::util::subst_assoc_item_bound; pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{ diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index d0c0e658c921f..6527d8277f8dc 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -38,7 +38,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; -use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_span::symbol::sym; use std::cell::{Cell, RefCell}; diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 0a4ce34c7f8e0..f626bb0b7e365 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -6,13 +6,11 @@ use smallvec::SmallVec; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; pub use rustc_infer::traits::util::*; -use std::iter; - /////////////////////////////////////////////////////////////////////////// // `TraitAliasExpander` iterator /////////////////////////////////////////////////////////////////////////// @@ -359,69 +357,6 @@ pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool { assoc_item.defaultness.is_final() && tcx.impl_defaultness(assoc_item.container.id()).is_final() } -/// Map a bound from an associated item to apply to some other type. -/// For example, given the following trait -/// -/// trait X { type Y<'a>: PartialEq } -/// -/// Say that we know that `<() as X>::Y<'c> = i32` and we need to check that -/// the `PartialEq` bound applies. We would then call this function with: -/// -/// - `bound` = `>::Y<'a>: PartialEq` -/// - `normalized_projection_ty` = `i32` -/// - `assoc_item_substs` = `[(), B, 'c]` -/// -/// This method would then return `i32: PartialEq`. -pub fn subst_assoc_item_bound<'tcx>( - tcx: TyCtxt<'tcx>, - bound: ty::Predicate<'tcx>, - normalized_projection_ty: Ty<'tcx>, - assoc_item_substs: &[GenericArg<'tcx>], -) -> ty::Predicate<'tcx> { - // We're substituting these inside the closure passed to map_bound, so they - // can't have escaping bound regions. - assert!(!normalized_projection_ty.has_escaping_bound_vars()); - assert!(!assoc_item_substs.iter().all(|arg| arg.has_escaping_bound_vars())); - - let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| { - tcx.mk_substs( - iter::once(normalized_projection_ty.into()) - .chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, assoc_item_substs))), - ) - }; - - match bound.kind() { - ty::PredicateKind::Trait(poly_tr, c) => poly_tr - .map_bound(|tr| { - let trait_substs = translate_predicate_substs(tr.trait_ref.substs); - ty::TraitRef { def_id: tr.def_id(), substs: trait_substs } - }) - .with_constness(*c) - .to_predicate(tcx), - ty::PredicateKind::Projection(poly_projection) => poly_projection - .map_bound(|projection| { - let projection_substs = translate_predicate_substs(projection.projection_ty.substs); - ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - substs: projection_substs, - item_def_id: projection.projection_ty.item_def_id, - }, - ty: projection.ty.subst(tcx, assoc_item_substs), - } - }) - .to_predicate(tcx), - ty::PredicateKind::TypeOutlives(poly_outlives) => poly_outlives - .map_bound(|outlives| { - ty::OutlivesPredicate( - normalized_projection_ty, - outlives.1.subst(tcx, assoc_item_substs), - ) - }) - .to_predicate(tcx), - _ => bug!("unexepected projection bound: `{:?}`", bound), - } -} - pub enum TupleArgumentsFlag { Yes, No, diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 0b4edf5e71b18..d66bfd482069d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -391,7 +391,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause.clone(), depth, param_env, - ty::PredicateKind::WellFormed(arg).to_predicate(tcx), + ty::PredicateAtom::WellFormed(arg).to_predicate(tcx), ) }), ); diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 0602f5ea4dcc6..a59c81aa9b835 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -738,10 +738,10 @@ impl<'tcx> LowerInto<'tcx, Option, ) -> Option>> { - match &self.kind() { - ty::PredicateKind::Trait(predicate, _) => { + match self.bound_atom(interner.tcx).skip_binder() { + ty::PredicateAtom::Trait(predicate, _) => { let (predicate, binders, _named_regions) = - collect_bound_vars(interner, interner.tcx, predicate); + collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate)); Some(chalk_ir::Binders::new( binders, @@ -750,24 +750,24 @@ impl<'tcx> LowerInto<'tcx, Option { + ty::PredicateAtom::Projection(predicate) => { let (predicate, binders, _named_regions) = - collect_bound_vars(interner, interner.tcx, predicate); + collect_bound_vars(interner, interner.tcx, &ty::Binder::bind(predicate)); Some(chalk_ir::Binders::new( binders, chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)), )) } - ty::PredicateKind::TypeOutlives(_predicate) => None, - ty::PredicateKind::WellFormed(_ty) => None, - - ty::PredicateKind::RegionOutlives(..) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::ConstEvaluatable(..) - | ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", &self), + ty::PredicateAtom::TypeOutlives(_predicate) => None, + ty::PredicateAtom::WellFormed(_ty) => None, + + ty::PredicateAtom::RegionOutlives(..) + | ty::PredicateAtom::ObjectSafe(..) + | ty::PredicateAtom::ClosureKind(..) + | ty::PredicateAtom::Subtype(..) + | ty::PredicateAtom::ConstEvaluatable(..) + | ty::PredicateAtom::ConstEquate(..) => bug!("unexpected predicate {}", &self), } } } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 788590e50f3b0..817b4070754a6 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1225,18 +1225,19 @@ pub fn check_type_bounds<'tcx>( let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()); let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); - let cause = ObligationCause::new( - impl_ty_span, - impl_ty_hir_id, - ObligationCauseCode::ItemObligation(trait_ty.def_id), - ); + let mk_cause = |span| { + ObligationCause::new( + impl_ty_span, + impl_ty_hir_id, + ObligationCauseCode::BindingObligation(trait_ty.def_id, span), + ) + }; let obligations = tcx .explicit_item_bounds(trait_ty.def_id) .iter() .map(|&(bound, span)| { - let concrete_ty_bound = - traits::subst_assoc_item_bound(tcx, bound, impl_ty_value, rebased_substs); + let concrete_ty_bound = bound.subst(tcx, rebased_substs); debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound) @@ -1244,17 +1245,15 @@ pub fn check_type_bounds<'tcx>( .collect(); debug!("check_type_bounds: item_bounds={:?}", obligations); - for obligation in util::elaborate_obligations(tcx, obligations) { - let concrete_ty_predicate = predicate.subst(tcx, rebased_substs); - debug!("compare_projection_bounds: concrete predicate = {:?}", concrete_ty_predicate); - + for mut obligation in util::elaborate_obligations(tcx, obligations) { let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize( &mut selcx, normalize_param_env, normalize_cause.clone(), - &concrete_ty_predicate, + &obligation.predicate, ); debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); + obligation.predicate = normalized_predicate; inh.register_predicates(obligations); inh.register_predicate(obligation); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 7e125481671f5..ad306fc1a0b09 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2137,8 +2137,8 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat // associated type: // * It must use the identity substs of the item. // * Since any generic parameters on the item are not in scope, - // this means that the item is not a GAT, and its identity substs - // are the same as the trait's. + // this means that the item is not a GAT, and its identity + // substs are the same as the trait's. // * It must be an associated type for this trait (*not* a // supertrait). if let ty::Projection(projection) = ty.kind { @@ -2158,14 +2158,12 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat .predicates .iter() .copied() - .filter(|(pred, _)| match pred.kind() { - ty::PredicateKind::Trait(tr, _) => !is_assoc_item_ty(tr.skip_binder().self_ty()), - ty::PredicateKind::Projection(proj) => { - !is_assoc_item_ty(proj.skip_binder().projection_ty.self_ty()) - } - ty::PredicateKind::TypeOutlives(outlives) => { - !is_assoc_item_ty(outlives.skip_binder().0) + .filter(|(pred, _)| match pred.skip_binders() { + ty::PredicateAtom::Trait(tr, _) => !is_assoc_item_ty(tr.self_ty()), + ty::PredicateAtom::Projection(proj) => { + !is_assoc_item_ty(proj.projection_ty.self_ty()) } + ty::PredicateAtom::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0), _ => true, }) .collect(); diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index c9af86f70fd92..9c29ceeb593df 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -37,12 +37,10 @@ fn associated_type_bounds<'tcx>( let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); let bounds_from_parent = - trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.kind() { - ty::PredicateKind::Trait(tr, _) => tr.skip_binder().self_ty() == item_ty, - ty::PredicateKind::Projection(proj) => { - proj.skip_binder().projection_ty.self_ty() == item_ty - } - ty::PredicateKind::TypeOutlives(outlives) => outlives.skip_binder().0 == item_ty, + trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.skip_binders() { + ty::PredicateAtom::Trait(tr, _) => tr.self_ty() == item_ty, + ty::PredicateAtom::Projection(proj) => proj.projection_ty.self_ty() == item_ty, + ty::PredicateAtom::TypeOutlives(outlives) => outlives.0 == item_ty, _ => false, }); diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr index 2be37285e2991..cc0b58188e624 100644 --- a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr @@ -4,7 +4,7 @@ error[E0277]: `<::A as std::iter::Iterator>::Item` doesn't implem LL | type A: Iterator; | ^^^^^ `<::A as std::iter::Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` | - ::: $SRC_DIR/libcore/fmt/mod.rs:LL:COL + ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL | LL | pub trait Debug { | --------------- required by this bound in `std::fmt::Debug` @@ -21,7 +21,7 @@ error[E0277]: the trait bound `<::Out as Baz>::Assoc: std::default: LL | pub trait Foo { type Out: Baz; } | ^^^^^^^ the trait `std::default::Default` is not implemented for `<::Out as Baz>::Assoc` | - ::: $SRC_DIR/libcore/default.rs:LL:COL + ::: $SRC_DIR/core/src/default.rs:LL:COL | LL | pub trait Default: Sized { | ------------------------ required by this bound in `std::default::Default` diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs index 69be300b16f37..44cc7738d7e2c 100644 --- a/src/test/ui/associated-types/defaults-suitability.rs +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -45,7 +45,6 @@ trait C where bool: IsU8, { type Assoc = u8; - //~^ ERROR the trait bound `u8: IsU8<::Assoc>` is not satisfied } // Test that we get all expected errors if that default is unsuitable @@ -55,7 +54,7 @@ trait D where bool: IsU8, { type Assoc = NotClone; - //~^ ERROR the trait bound `NotClone: IsU8<::Assoc>` is not satisfied + //~^ ERROR the trait bound `NotClone: IsU8` is not satisfied } // Test behavior of the check when defaults refer to other defaults: diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 4d8e6f1584d1d..5ee800e19133d 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -42,20 +42,8 @@ LL | type Assoc: Foo = (); | | required by this bound in `Bar::Assoc` | the trait `Foo` is not implemented for `()` -error[E0277]: the trait bound `u8: IsU8<::Assoc>` is not satisfied - --> $DIR/defaults-suitability.rs:44:5 - | -LL | Self::Assoc: IsU8, - | ----------------- required by this bound in `C::Assoc` -... -LL | type Assoc = u8; - | ^^^^^-----^^^^^^ - | | | - | | required by a bound in this - | the trait `IsU8<::Assoc>` is not implemented for `u8` - -error[E0277]: the trait bound `NotClone: IsU8<::Assoc>` is not satisfied - --> $DIR/defaults-suitability.rs:54:5 +error[E0277]: the trait bound `NotClone: IsU8` is not satisfied + --> $DIR/defaults-suitability.rs:53:5 | LL | Self::Assoc: IsU8, | ----------------- required by this bound in `D::Assoc` @@ -64,10 +52,10 @@ LL | type Assoc = NotClone; | ^^^^^-----^^^^^^^^^^^^ | | | | | required by a bound in this - | the trait `IsU8<::Assoc>` is not implemented for `NotClone` + | the trait `IsU8` is not implemented for `NotClone` error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:63:5 + --> $DIR/defaults-suitability.rs:62:5 | LL | type Bar: Clone = Vec; | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ @@ -82,7 +70,7 @@ LL | trait Foo2 where >::Baz: Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:72:5 + --> $DIR/defaults-suitability.rs:71:5 | LL | type Bar: Clone = Vec; | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ @@ -97,7 +85,7 @@ LL | trait Foo25 where >::Baz: Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:84:5 + --> $DIR/defaults-suitability.rs:83:5 | LL | Self::Baz: Clone, | ----- required by this bound in `Foo3::Baz` @@ -113,6 +101,6 @@ help: consider further restricting type parameter `T` LL | Self::Baz: Clone, T: Clone | ^^^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-wf.stderr b/src/test/ui/associated-types/defaults-wf.stderr index aeb7b6cae1906..d1832cdbc0cd4 100644 --- a/src/test/ui/associated-types/defaults-wf.stderr +++ b/src/test/ui/associated-types/defaults-wf.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | type Ty = Vec<[u8]>; | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - ::: $SRC_DIR/liballoc/vec.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec.rs:LL:COL | LL | pub struct Vec { | - required by this bound in `std::vec::Vec` diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr index 03011bd1e32d1..987b678758173 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -145,7 +145,7 @@ error[E0277]: the trait bound `<::A as std::iter::Iterator>::Item: LL | type A: Iterator; | ^^^^ the trait `std::marker::Copy` is not implemented for `<::A as std::iter::Iterator>::Item` | - ::: $SRC_DIR/libcore/marker.rs:LL:COL + ::: $SRC_DIR/core/src/marker.rs:LL:COL | LL | pub trait Copy: Clone { | --------------------- required by this bound in `std::marker::Copy` diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs index 17548d7b9e88c..34823cbafd321 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs @@ -15,6 +15,7 @@ impl PointerFamily for Foo { //~^ ERROR generic associated types are unstable type Pointer2 = Box; //~^ ERROR generic associated types are unstable + //~| ERROR the trait bound `U32: std::clone::Clone` is not satisfied } trait Bar { diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr index 8499b1ab70f5d..e04a129dbbbb6 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr @@ -44,7 +44,7 @@ LL | type Pointer2 = Box; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: where clauses on associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:21:5 + --> $DIR/feature-gate-generic_associated_types.rs:22:5 | LL | type Assoc where Self: Sized; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | type Assoc where Self: Sized; = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable error[E0658]: where clauses on associated types are unstable - --> $DIR/feature-gate-generic_associated_types.rs:26:5 + --> $DIR/feature-gate-generic_associated_types.rs:27:5 | LL | type Assoc where Self: Sized = Foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,6 +61,18 @@ LL | type Assoc where Self: Sized = Foo; = note: see issue #44265 for more information = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable -error: aborting due to 7 previous errors +error[E0277]: the trait bound `U32: std::clone::Clone` is not satisfied + --> $DIR/feature-gate-generic_associated_types.rs:16:5 + | +LL | type Pointer2 = Box; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `U32` + | +help: consider restricting type parameter `U32` + | +LL | type Pointer2 = Box; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr index e49dc91ec66ae..19658528a0b89 100644 --- a/src/test/ui/generator/sized-yield.stderr +++ b/src/test/ui/generator/sized-yield.stderr @@ -17,7 +17,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | Pin::new(&mut gen).resume(()); | ^^^^^^ doesn't have a size known at compile-time | - ::: $SRC_DIR/libcore/ops/generator.rs:LL:COL + ::: $SRC_DIR/core/src/ops/generator.rs:LL:COL | LL | pub enum GeneratorState { | - required by this bound in `std::ops::GeneratorState` diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.rs b/src/test/ui/generic-associated-types/generic-associated-types-where.rs index 1a94796535c14..27970b15a411d 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.rs +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.rs @@ -19,8 +19,9 @@ struct Bar; impl Foo for Bar { type Assoc = usize; type Assoc2 = Vec; + //~^ ERROR `T` doesn't implement `std::fmt::Display` type Assoc3 where T: Iterator = Vec; - //~^ impl has stricter requirements than trait + //~^ ERROR impl has stricter requirements than trait type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator; type NoGenerics = ::std::cell::Cell; } diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr index c95765d906c22..da8b625ea7f75 100644 --- a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr +++ b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr @@ -1,5 +1,17 @@ +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/generic-associated-types-where.rs:21:5 + | +LL | type Assoc2 = Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider restricting type parameter `T` + | +LL | type Assoc2 = Vec; + | ^^^^^^^^^^^^^^^^^^^ + error[E0276]: impl has stricter requirements than trait - --> $DIR/generic-associated-types-where.rs:22:5 + --> $DIR/generic-associated-types-where.rs:23:5 | LL | type Assoc3; | --------------- definition of `Assoc3` from trait @@ -7,6 +19,7 @@ LL | type Assoc3; LL | type Assoc3 where T: Iterator = Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0276`. +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index 77bebc9854aa0..089a214667ea2 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -16,6 +16,7 @@ impl Foo for Fooy { //~^ ERROR the parameter type `T` may not live long enough type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); //~^ ERROR lifetime bound not satisfied + //~| ERROR lifetime bound not satisfied type C where Self: Copy = String; //~^ ERROR the trait bound `T: Copy` is not satisfied } diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 0546e38a33da7..e6f27a45a3cfb 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -37,7 +37,7 @@ help: consider restricting type parameter `T` LL | impl Foo for Fooy { | ^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0310, E0478. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/generic-associated-types/impl_bounds_ok.rs b/src/test/ui/generic-associated-types/impl_bounds_ok.rs index 2387b89175524..98aa82aba8305 100644 --- a/src/test/ui/generic-associated-types/impl_bounds_ok.rs +++ b/src/test/ui/generic-associated-types/impl_bounds_ok.rs @@ -10,11 +10,12 @@ trait Foo { type C where Self: Clone; } +#[derive(Clone)] struct Fooy; impl Foo for Fooy { type A<'a> = (&'a ()); - type B<'a, 'b> = (&'a(), &'b ()); + type B<'a: 'b, 'b> = (&'a(), &'b ()); type C = String; } @@ -24,7 +25,7 @@ struct Fooer(T); impl Foo for Fooer { type A<'x> where T: 'x = (&'x ()); type B<'u, 'v> where 'u: 'v = (&'v &'u ()); - type C where Self: ToOwned = String; + type C where Self: Clone + ToOwned = String; } fn main() {} diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs index d957cae308101..99d5bcf2bace9 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -7,7 +7,7 @@ trait ATy { impl<'b> ATy for &'b () { type Item<'a> = &'b (); - //~^ ERROR lifetime bound not satisfied + //~^ ERROR the type `&'b ()` does not fulfill the required lifetime } trait StaticTy { @@ -16,7 +16,7 @@ trait StaticTy { impl StaticTy for () { type Item<'a> = &'a (); - //~^ ERROR lifetime bound not satisfied + //~^ ERROR the type `&'a ()` does not fulfill the required lifetime } fn main() {} diff --git a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr index f8b96ef3b8a03..5d612284a2187 100644 --- a/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr +++ b/src/test/ui/generic-associated-types/unsatisfied-outlives-bound.stderr @@ -1,33 +1,23 @@ -error[E0478]: lifetime bound not satisfied +error[E0477]: the type `&'b ()` does not fulfill the required lifetime --> $DIR/unsatisfied-outlives-bound.rs:9:5 | LL | type Item<'a> = &'b (); | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'b` as defined on the impl at 8:6 - --> $DIR/unsatisfied-outlives-bound.rs:8:6 - | -LL | impl<'b> ATy for &'b () { - | ^^ -note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 9:15 +note: type must outlive the lifetime `'a` as defined on the associated item at 9:15 --> $DIR/unsatisfied-outlives-bound.rs:9:15 | LL | type Item<'a> = &'b (); | ^^ -error[E0478]: lifetime bound not satisfied +error[E0477]: the type `&'a ()` does not fulfill the required lifetime --> $DIR/unsatisfied-outlives-bound.rs:18:5 | LL | type Item<'a> = &'a (); | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 18:15 - --> $DIR/unsatisfied-outlives-bound.rs:18:15 - | -LL | type Item<'a> = &'a (); - | ^^ - = note: but lifetime parameter must outlive the static lifetime + = note: type must satisfy the static lifetime error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0478`. +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index 2922eb87e825f..80f118e12c4a7 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -19,7 +19,7 @@ error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be kn LL | foo((), drop) | ^^^^ doesn't have a size known at compile-time | - ::: $SRC_DIR/libcore/mem/mod.rs:LL:COL + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL | LL | pub fn drop(_x: T) {} | - required by this bound in `std::mem::drop` diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs index 0f86e37b7e5cc..575dfafe15efc 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs @@ -3,7 +3,7 @@ trait Foo<'a> { type Value: 'a; - fn dummy(&'a self) { } + fn dummy(&'a self) {} } impl<'a> Foo<'a> for &'a i16 { @@ -13,12 +13,12 @@ impl<'a> Foo<'a> for &'a i16 { impl<'a> Foo<'static> for &'a i32 { type Value = &'a i32; - //~^ ERROR lifetime bound not satisfied + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime } -impl<'a,'b> Foo<'b> for &'a i64 { +impl<'a, 'b> Foo<'b> for &'a i64 { type Value = &'a i32; - //~^ ERROR lifetime bound not satisfied + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime } -fn main() { } +fn main() {} diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr index feb9c90bc8f1b..03da33ae11ffe 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr @@ -1,33 +1,23 @@ -error[E0478]: lifetime bound not satisfied +error[E0477]: the type `&'a i32` does not fulfill the required lifetime --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:15:5 | LL | type Value = &'a i32; | ^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the impl at 14:6 - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6 - | -LL | impl<'a> Foo<'static> for &'a i32 { - | ^^ - = note: but lifetime parameter must outlive the static lifetime + = note: type must satisfy the static lifetime -error[E0478]: lifetime bound not satisfied +error[E0477]: the type `&'a i32` does not fulfill the required lifetime --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:20:5 | LL | type Value = &'a i32; | ^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the impl at 19:6 - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6 - | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^ -note: but lifetime parameter must outlive the lifetime `'b` as defined on the impl at 19:9 - --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9 +note: type must outlive the lifetime `'b` as defined on the impl at 19:10 + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:10 | -LL | impl<'a,'b> Foo<'b> for &'a i64 { - | ^^ +LL | impl<'a, 'b> Foo<'b> for &'a i64 { + | ^^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0478`. +For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs index 65b54b45a0a16..00100e0e9ea75 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs @@ -3,12 +3,12 @@ trait Foo { type Value: 'static; - fn dummy(&self) { } + fn dummy(&self) {} } impl<'a> Foo for &'a i32 { type Value = &'a i32; - //~^ ERROR lifetime bound not satisfied + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime } impl<'a> Foo for i32 { @@ -16,4 +16,4 @@ impl<'a> Foo for i32 { type Value = i32; } -fn main() { } +fn main() {} diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr index 9b98d14a9781f..d8efeac5b8a30 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr @@ -1,16 +1,11 @@ -error[E0478]: lifetime bound not satisfied +error[E0477]: the type `&'a i32` does not fulfill the required lifetime --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:10:5 | LL | type Value = &'a i32; | ^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime `'a` as defined on the impl at 9:6 - --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6 - | -LL | impl<'a> Foo for &'a i32 { - | ^^ - = note: but lifetime parameter must outlive the static lifetime + = note: type must satisfy the static lifetime error: aborting due to previous error -For more information about this error, try `rustc --explain E0478`. +For more information about this error, try `rustc --explain E0477`. From e674cf0200347c5e58f8a3867657187b12e7b496 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 14 Aug 2020 21:51:28 +0100 Subject: [PATCH 27/34] Normalize super trait bounds when confirming object candidates --- .../src/traits/select/confirmation.rs | 29 +++++++++++++------ .../associated-types/object-normalization.rs | 26 +++++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/associated-types/object-normalization.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 21293615bc98c..8c58d4191c5af 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -440,15 +440,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let upcast_trait_ref = upcast_trait_ref.unwrap(); // Check supertraits hold - nested.extend( - tcx.super_predicates_of(trait_predicate.def_id()) - .instantiate(tcx, trait_predicate.trait_ref.substs) - .predicates - .into_iter() - .map(|super_trait| { - Obligation::new(obligation.cause.clone(), obligation.param_env, super_trait) - }), - ); + for super_trait in tcx + .super_predicates_of(trait_predicate.def_id()) + .instantiate(tcx, trait_predicate.trait_ref.substs) + .predicates + .into_iter() + { + let normalized_super_trait = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &super_trait, + &mut nested, + ); + nested.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env.clone(), + normalized_super_trait, + )); + } let assoc_types: Vec<_> = tcx .associated_items(trait_predicate.def_id()) diff --git a/src/test/ui/associated-types/object-normalization.rs b/src/test/ui/associated-types/object-normalization.rs new file mode 100644 index 0000000000000..1f93248e10ec4 --- /dev/null +++ b/src/test/ui/associated-types/object-normalization.rs @@ -0,0 +1,26 @@ +// ignore-tidy-linelength + +// Check that we normalize super predicates for object candidates. + +// check-pass + +use std::ops::Index; + +fn next<'a, T>(s: &'a mut dyn SVec) { + // To prove + // `dyn SVec: SVec` + // we need to show + // `dyn SVec as Index>::Output == as SVec>::Item` + // which, with the current normalization strategy, has to be eagerly + // normalized to: + // `dyn SVec as Index>::Output == T`. + let _ = s.len(); +} + +trait SVec: Index::Item> { + type Item; + + fn len(&self) -> usize; +} + +fn main() {} From e42c97919cd5a7fe856865cfd1034dfe14206ceb Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Aug 2020 12:29:23 +0100 Subject: [PATCH 28/34] Don't require lifetime super-bounds on traits apply to trait objects of that trait --- .../src/traits/select/confirmation.rs | 31 ++++++++++--------- .../trait-object-supertrait-lifetime-bound.rs | 16 ++++++++++ 2 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 8c58d4191c5af..7f9525c842a0c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -439,26 +439,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let upcast_trait_ref = upcast_trait_ref.unwrap(); - // Check supertraits hold + // Check supertraits hold. This is so that their associated type bounds + // will be checked in the code below. for super_trait in tcx .super_predicates_of(trait_predicate.def_id()) .instantiate(tcx, trait_predicate.trait_ref.substs) .predicates .into_iter() { - let normalized_super_trait = normalize_with_depth_to( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &super_trait, - &mut nested, - ); - nested.push(Obligation::new( - obligation.cause.clone(), - obligation.param_env.clone(), - normalized_super_trait, - )); + if let ty::PredicateAtom::Trait(..) = super_trait.skip_binders() { + let normalized_super_trait = normalize_with_depth_to( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &super_trait, + &mut nested, + ); + nested.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env.clone(), + normalized_super_trait, + )); + } } let assoc_types: Vec<_> = tcx diff --git a/src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs b/src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs new file mode 100644 index 0000000000000..9d834727a4a1b --- /dev/null +++ b/src/test/ui/traits/trait-object-supertrait-lifetime-bound.rs @@ -0,0 +1,16 @@ +// check-pass + +use std::any::Any; + +trait A: Any { + fn m(&self) {} +} + +impl A for T {} + +fn call_obj<'a>() { + let obj: &dyn A<&'a ()> = &(); + obj.m(); +} + +fn main() {} From 852073a7d2fc90597fa0369ce86611ed23f7e85d Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Aug 2020 20:31:07 +0100 Subject: [PATCH 29/34] Deduplicate item bounds after normalization --- .../src/traits/select/mod.rs | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6527d8277f8dc..3b2cae0dbd5a2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1192,6 +1192,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; let bounds = tcx.item_bounds(def_id).subst(tcx, substs); + // The bounds returned by `item_bounds` may contain duplicates after + // normalization, so try to deduplicate when possible to avoid + // unnecessary ambiguity. + let mut distinct_normalized_bounds = FxHashSet::default(); + let matching_bounds = bounds .iter() .enumerate() @@ -1199,12 +1204,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() { let bound = ty::Binder::bind(pred.trait_ref); if self.infcx.probe(|_| { - self.match_projection( + if let Ok(normalized_trait) = self.match_projection( obligation, bound, placeholder_trait_predicate.trait_ref, - ) - .is_ok() + ) { + match normalized_trait { + None => true, + Some(normalized_trait) + if distinct_normalized_bounds.insert(normalized_trait) => + { + true + } + _ => false, + } + } else { + false + } }) { return Some(idx); } @@ -1221,34 +1237,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { matching_bounds } + /// Equates the trait in `obligation` with trait bound. If the two traits + /// can be equated and the normalized trait bound doesn't contain inference + /// variables or placeholders, the normalized bound is returned. fn match_projection( &mut self, obligation: &TraitObligation<'tcx>, trait_bound: ty::PolyTraitRef<'tcx>, placeholder_trait_ref: ty::TraitRef<'tcx>, - ) -> Result>, ()> { + ) -> Result>, ()> { debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars()); if placeholder_trait_ref.def_id != trait_bound.def_id() { // Avoid unnecessary normalization return Err(()); } - let Normalized { value: trait_bound, obligations: mut nested_obligations } = - ensure_sufficient_stack(|| { - project::normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &trait_bound, - ) - }); + let Normalized { value: trait_bound, obligations: _ } = ensure_sufficient_stack(|| { + project::normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_bound, + ) + }); self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound) - .map(|InferOk { obligations, .. }| { - nested_obligations.extend(obligations); - nested_obligations + .map(|InferOk { obligations: _, value: () }| { + // This method is called within a probe, so we can't have + // inference variables and placeholders escape. + if !trait_bound.needs_infer() && !trait_bound.has_placeholders() { + Some(trait_bound) + } else { + None + } }) .map_err(|_| ()) } From 27534b3932d06959b3d12e8431a0b396c9bd3ded Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 6 Sep 2020 20:04:52 +0100 Subject: [PATCH 30/34] Fix rebase --- .../rustc_trait_selection/src/traits/project.rs | 4 ++-- .../src/traits/select/confirmation.rs | 4 ++-- compiler/rustc_traits/src/chalk/db.rs | 16 +++++++++++----- compiler/rustc_typeck/src/collect.rs | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 518719d76d4f6..de42aa0e6b764 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -916,8 +916,8 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( let self_ty = obligation_trait_ref.self_ty(); let object_ty = selcx.infcx().shallow_resolve(self_ty); - let data = match object_ty.kind { - ty::Dynamic(ref data, ..) => data, + let data = match object_ty.kind() { + ty::Dynamic(data, ..) => data, ty::Infer(ty::TyVar(_)) => { // If the self-type is an inference variable, then it MAY wind up // being an object type, so induce an ambiguity. diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 7f9525c842a0c..905a2ab7057c6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -126,7 +126,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); let bound_self_ty = self.infcx.shallow_resolve(obligation.self_ty()); - let (def_id, substs) = match bound_self_ty.skip_binder().kind { + let (def_id, substs) = match *bound_self_ty.skip_binder().kind() { ty::Projection(proj) => (proj.item_def_id, proj.substs), ty::Opaque(def_id, substs) => (def_id, substs), _ => bug!("projection candidate for unexpected type: {:?}", bound_self_ty), @@ -158,7 +158,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }), ); - if let ty::Projection(..) = bound_self_ty.skip_binder().kind { + if let ty::Projection(..) = bound_self_ty.skip_binder().kind() { for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates { let normalized = normalize_with_depth_to( self, diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 35b1064d2e4ad..5553d4585244d 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -77,10 +77,11 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let where_clauses = self.where_clauses_for(def_id, bound_vars); let bounds = self + .interner .tcx .explicit_item_bounds(def_id) .iter() - .map(|(bound, _)| bound.subst(self.tcx, &bound_vars)) + .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) .filter_map(|bound| { LowerInto::< Option>>, @@ -453,14 +454,19 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let binders = binders_for(&self.interner, bound_vars); let where_clauses = self.where_clauses_for(opaque_ty_id.0, bound_vars); - let bounds: Vec<_> = predicates + let bounds: Vec<_> = self + .interner + .tcx + .explicit_item_bounds(opaque_ty_id.0) .iter() - .map(|(bound, _)| bound.subst(self.tcx, &bound_vars)) - .filter_map(|bound| LowerInto::>>>::lower_into(bound, &self.interner)) + .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) + .filter_map(|bound| { + LowerInto::>>>::lower_into(bound, &self.interner) + }) .collect(); let value = chalk_solve::rust_ir::OpaqueTyDatumBound { - bounds: chalk_ir::Binders::new(binders, bounds), + bounds: chalk_ir::Binders::new(binders.clone(), bounds), where_clauses: chalk_ir::Binders::new(binders, where_clauses), }; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index ad306fc1a0b09..82d46b78178b9 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2141,7 +2141,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat // substs are the same as the trait's. // * It must be an associated type for this trait (*not* a // supertrait). - if let ty::Projection(projection) = ty.kind { + if let ty::Projection(projection) = ty.kind() { if projection.substs == trait_identity_substs && tcx.associated_item(projection.item_def_id).container.id() == def_id { From 1db284ecb0039798a09e53a519219c5c556c9b38 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 7 Sep 2020 09:38:09 +0100 Subject: [PATCH 31/34] Avoid creating useless projection predicate --- .../rustc_typeck/src/check/compare_method.rs | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 817b4070754a6..4acc7451a2131 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1205,16 +1205,27 @@ pub fn check_type_bounds<'tcx>( // ParamEnv for normalization specifically. let normalize_param_env = { let mut predicates = param_env.caller_bounds().iter().collect::>(); - predicates.push( - ty::Binder::dummy(ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - item_def_id: trait_ty.def_id, - substs: rebased_substs, - }, - ty: impl_ty_value, - }) - .to_predicate(tcx), - ); + match impl_ty_value.kind() { + ty::Projection(proj) + if proj.item_def_id == trait_ty.def_id && proj.substs == rebased_substs => + { + // Don't include this predicate if the projected type is + // exactly the same as the projection. This can occur in + // (somewhat dubious) code like this: + // + // impl X for T where T: X { type Y = ::Y; } + } + _ => predicates.push( + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + item_def_id: trait_ty.def_id, + substs: rebased_substs, + }, + ty: impl_ty_value, + }) + .to_predicate(tcx), + ), + }; ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing) }; From 022c148fcd9e4339b4b59dfaee58ca5905d71b2d Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 7 Sep 2020 10:01:45 +0100 Subject: [PATCH 32/34] Fix tests from rebase --- compiler/rustc_middle/src/ty/sty.rs | 4 +- .../src/traits/select/confirmation.rs | 17 ++-- .../src/traits/select/mod.rs | 18 ++-- compiler/rustc_traits/src/chalk/lowering.rs | 5 +- compiler/rustc_typeck/src/check/check.rs | 10 +- compiler/rustc_typeck/src/collect.rs | 1 + ...issue_62289.test.ElaborateDrops.before.mir | 2 +- ...mplify_arm.id_try.SimplifyArmIdentity.diff | 16 ++-- ...implify_arm.id_try.SimplifyBranchSame.diff | 16 ++-- .../assoc-type-eq-with-dyn-atb-fail.rs | 9 +- .../assoc-type-eq-with-dyn-atb-fail.stderr | 10 +- .../bad-bounds-on-assoc-in-trait.rs | 6 +- .../bad-bounds-on-assoc-in-trait.stderr | 63 ++++++------- .../bounds-on-assoc-in-trait.rs | 6 +- .../bounds-on-assoc-in-trait.stderr | 26 +++--- .../associated-type-bounds/duplicate.stderr | 26 +++++- .../associated-types/defaults-suitability.rs | 4 +- .../defaults-suitability.stderr | 43 ++++----- .../defaults-unsound-62211-1.rs | 4 + .../defaults-unsound-62211-1.stderr | 91 ++++++------------- .../defaults-unsound-62211-2.rs | 4 + .../defaults-unsound-62211-2.stderr | 91 ++++++------------- .../ui/associated-types/defaults-wf.stderr | 4 +- .../ui/associated-types/issue-43924.stderr | 8 +- .../ui/async-await/async-error-span.stderr | 1 - src/test/ui/async-await/issue-61076.stderr | 19 ---- .../issue-64130-4-async-move.stderr | 13 +-- src/test/ui/async-await/issue-70818.stderr | 3 - src/test/ui/closures/issue-41366.stderr | 6 +- src/test/ui/conservative_impl_trait.stderr | 1 - .../feature-gate-associated_type_bounds.rs | 3 +- ...feature-gate-associated_type_bounds.stderr | 44 ++++----- .../feature-gate-generic_associated_types.rs | 2 +- ...ature-gate-generic_associated_types.stderr | 8 +- src/test/ui/for/for-c-in-str.rs | 4 +- src/test/ui/for/for-c-in-str.stderr | 3 +- src/test/ui/for/for-loop-bogosity.stderr | 1 + src/test/ui/generator/sized-yield.stderr | 2 +- .../cross-crate-bounds.rs | 2 +- .../cross-crate-bounds.stderr | 4 +- .../impl_bounds.stderr | 19 +++- .../projection-bound-cycle-generic.rs | 2 +- .../projection-bound-cycle-generic.stderr | 2 +- .../projection-bound-cycle.rs | 2 +- .../projection-bound-cycle.stderr | 2 +- src/test/ui/impl-trait/issue-55872-2.stderr | 2 - ...r-async-enabled-impl-trait-bindings.stderr | 2 +- src/test/ui/issues-71798.stderr | 1 - src/test/ui/issues/issue-20605.stderr | 6 +- .../ui/issues/issue-20831-debruijn.stderr | 10 +- src/test/ui/issues/issue-23122-2.stderr | 2 +- src/test/ui/issues/issue-28098.stderr | 7 +- src/test/ui/issues/issue-33941.stderr | 7 +- src/test/ui/issues/issue-41139.rs | 8 +- src/test/ui/issues/issue-41139.stderr | 16 ++-- .../issues/issue-43784-associated-type.stderr | 4 +- src/test/ui/issues/issue-60283.stderr | 6 +- src/test/ui/iterators/array-of-ranges.stderr | 9 ++ src/test/ui/iterators/array.stderr | 3 + src/test/ui/iterators/integral.stderr | 12 +++ src/test/ui/iterators/ranges.stderr | 2 + src/test/ui/iterators/string.stderr | 2 + .../ui/parser/struct-literal-in-for.stderr | 1 + .../ui/privacy/private-in-public-assoc-ty.rs | 10 +- .../privacy/private-in-public-assoc-ty.stderr | 6 +- src/test/ui/privacy/pub-priv-dep/pub-priv1.rs | 3 +- .../ui/privacy/pub-priv-dep/pub-priv1.stderr | 2 +- src/test/ui/question-mark-type-infer.stderr | 3 +- src/test/ui/range/range-1.stderr | 4 +- ...ions-normalize-in-where-clause-list.stderr | 42 ++------- .../suggestions/suggest-remove-refs-1.stderr | 1 + .../suggestions/suggest-remove-refs-2.stderr | 1 + .../suggestions/suggest-remove-refs-3.stderr | 1 + .../ui/traits/check-trait-object-bounds-1.rs | 2 +- .../traits/check-trait-object-bounds-1.stderr | 4 +- .../ui/traits/check-trait-object-bounds-2.rs | 2 +- .../traits/check-trait-object-bounds-2.stderr | 4 +- .../ui/traits/check-trait-object-bounds-4.rs | 2 +- .../traits/check-trait-object-bounds-4.stderr | 4 +- .../ui/traits/cycle-cache-err-60010.stderr | 24 +---- ...raits-inductive-overflow-two-traits.stderr | 4 +- src/test/ui/try-block/try-block-bad-type.rs | 4 +- .../ui/try-block/try-block-bad-type.stderr | 14 ++- .../ui/try-block/try-block-in-while.stderr | 4 +- .../bounds-are-checked-2.rs | 4 +- .../bounds-are-checked-2.stderr | 8 +- .../bounds-are-checked.stderr | 4 +- .../generic_duplicate_param_use5.rs | 4 +- .../generic_duplicate_param_use5.stderr | 31 ++++++- .../generic_duplicate_param_use6.rs | 3 +- .../generic_duplicate_param_use6.stderr | 19 +++- .../generic_duplicate_param_use8.rs | 3 +- .../generic_duplicate_param_use8.stderr | 19 +++- .../generic_duplicate_param_use9.rs | 3 + .../generic_duplicate_param_use9.stderr | 43 ++++++++- .../generic_type_does_not_live_long_enough.rs | 3 +- ...eric_type_does_not_live_long_enough.stderr | 11 ++- .../issue-57611-trait-alias.rs | 4 + .../issue-57611-trait-alias.stderr | 38 +++++++- .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 1 + 100 files changed, 585 insertions(+), 481 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 09895605dca86..1af56972ad083 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1513,7 +1513,9 @@ impl<'tcx> ExistentialProjection<'tcx> { /// then this function would return a `exists T. T: Iterator` existential trait /// reference. pub fn trait_ref(&self, tcx: TyCtxt<'_>) -> ty::ExistentialTraitRef<'tcx> { - // FIXME(generic_associated_types): truncate substs to have the right length. + // FIXME(generic_associated_types): substs is the substs of the + // associated type, which should be truncated to get the correct substs + // for the trait. let def_id = tcx.associated_item(self.item_def_id).container.id(); ty::ExistentialTraitRef { def_id, substs: self.substs } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 905a2ab7057c6..96f0bedf6f1a7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -125,29 +125,34 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.commit_unconditionally(|_| { let tcx = self.tcx(); - let bound_self_ty = self.infcx.shallow_resolve(obligation.self_ty()); - let (def_id, substs) = match *bound_self_ty.skip_binder().kind() { + let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); + let placeholder_trait_predicate = + self.infcx().replace_bound_vars_with_placeholders(&trait_predicate); + let placeholder_self_ty = placeholder_trait_predicate.self_ty(); + let (def_id, substs) = match *placeholder_self_ty.kind() { ty::Projection(proj) => (proj.item_def_id, proj.substs), ty::Opaque(def_id, substs) => (def_id, substs), - _ => bug!("projection candidate for unexpected type: {:?}", bound_self_ty), + _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty), }; let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs); let candidate = candidate_predicate .to_opt_poly_trait_ref() .expect("projection candidate is not a trait predicate"); - let Normalized { value: candidate, mut obligations } = normalize_with_depth( + let mut obligations = Vec::new(); + let candidate = normalize_with_depth_to( self, obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, &candidate, + &mut obligations, ); obligations.extend( self.infcx .at(&obligation.cause, obligation.param_env) - .sup(obligation.predicate.to_poly_trait_ref(), candidate) + .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate) .map(|InferOk { obligations, .. }| obligations) .unwrap_or_else(|_| { bug!( @@ -158,7 +163,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }), ); - if let ty::Projection(..) = bound_self_ty.skip_binder().kind() { + if let ty::Projection(..) = placeholder_self_ty.kind() { for predicate in tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates { let normalized = normalize_with_depth_to( self, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3b2cae0dbd5a2..a142ba58a6904 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1204,22 +1204,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ty::PredicateAtom::Trait(pred, _) = bound.skip_binders() { let bound = ty::Binder::bind(pred.trait_ref); if self.infcx.probe(|_| { - if let Ok(normalized_trait) = self.match_projection( + match self.match_projection( obligation, bound, placeholder_trait_predicate.trait_ref, ) { - match normalized_trait { - None => true, - Some(normalized_trait) - if distinct_normalized_bounds.insert(normalized_trait) => - { - true - } - _ => false, + Ok(None) => true, + Ok(Some(normalized_trait)) + if distinct_normalized_bounds.insert(normalized_trait) => + { + true } - } else { - false + _ => false, } }) { return Some(idx); diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index a59c81aa9b835..bdb2513cc4602 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -767,7 +767,10 @@ impl<'tcx> LowerInto<'tcx, Option bug!("unexpected predicate {}", &self), + | ty::PredicateAtom::ConstEquate(..) + | ty::PredicateAtom::TypeWellFormedFromEnv(..) => { + bug!("unexpected predicate {}", &self) + } } } } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index cfd75db61f7cd..d319ac2cba654 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -4,13 +4,13 @@ use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_ use super::*; use rustc_attr as attr; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ItemKind, Node}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::RegionVariableOrigin; +use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt, Representability}; @@ -19,6 +19,8 @@ use rustc_session::config::EntryFnType; use rustc_span::symbol::sym; use rustc_span::{self, MultiSpan, Span}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::opaque_types::InferCtxtExt as _; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCauseCode}; pub fn check_wf_new(tcx: TyCtxt<'_>) { @@ -386,7 +388,9 @@ pub(super) fn check_opaque<'tcx>( origin: &hir::OpaqueTyOrigin, ) { check_opaque_for_inheriting_lifetimes(tcx, def_id, span); - tcx.ensure().type_of(def_id); + if tcx.type_of(def_id).references_error() { + return; + } if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() { return; } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 82d46b78178b9..092dae18192e5 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -704,6 +704,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) { hir::ItemKind::OpaqueTy(..) => { tcx.ensure().generics_of(def_id); tcx.ensure().predicates_of(def_id); + tcx.ensure().explicit_item_bounds(def_id); } hir::ItemKind::TyAlias(..) | hir::ItemKind::Static(..) diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir index 62bf97a772ead..c1421f20a0ba2 100644 --- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -69,7 +69,7 @@ fn test() -> Option> { bb5: { StorageDead(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _0 = > as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 + _0 = > as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:15: 9:20 // + literal: Const { ty: fn(> as std::ops::Try>::Error) -> std::option::Option> {> as std::ops::Try>::from_error}, val: Value(Scalar()) } diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff index 6ec2b98bf5b26..a811a2c178f17 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff @@ -1,6 +1,6 @@ - // MIR for `id_try` before SimplifyArmIdentity + // MIR for `id_try` after SimplifyArmIdentity - + fn id_try(_1: std::result::Result) -> std::result::Result { debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49 @@ -29,7 +29,7 @@ scope 8 { - debug v => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 } } } @@ -42,7 +42,7 @@ scope 6 { debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL } - + bb0: { StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 @@ -53,7 +53,7 @@ _5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 } - + bb1: { - StorageLive(_10); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - _10 = ((_3 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 @@ -69,11 +69,11 @@ StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } - + bb2: { unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 } - + bb3: { - StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 - _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 @@ -94,9 +94,9 @@ StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } - + bb4: { return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } } - + diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff index 172fb04a3cca8..b0cc3e88f35ac 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff @@ -1,6 +1,6 @@ - // MIR for `id_try` before SimplifyBranchSame + // MIR for `id_try` after SimplifyBranchSame - + fn id_try(_1: std::result::Result) -> std::result::Result { debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49 @@ -25,7 +25,7 @@ } scope 8 { debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 } } } @@ -37,7 +37,7 @@ scope 6 { debug self => _4; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL } - + bb0: { StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 @@ -49,7 +49,7 @@ - switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + goto -> bb1; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 } - + bb1: { _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 @@ -57,20 +57,20 @@ - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + goto -> bb2; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } - + bb2: { - unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 - } -- +- - bb3: { - _0 = move _3; // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 - StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 - goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 - } -- +- - bb4: { return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } } - + diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs index 498a555c441b8..73b23da5bcb66 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs @@ -12,7 +12,9 @@ fn main() {} -trait Bar { type Assoc; } +trait Bar { + type Assoc; +} trait Thing { type Out; @@ -20,11 +22,14 @@ trait Thing { } struct AssocNoCopy; -impl Bar for AssocNoCopy { type Assoc = String; } +impl Bar for AssocNoCopy { + type Assoc = String; +} impl Thing for AssocNoCopy { type Out = Box>; //~^ ERROR the trait bound `String: Copy` is not satisfied + //~| ERROR the trait bound `String: Copy` is not satisfied fn func() -> Self::Out { Box::new(AssocNoCopy) diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index 5236f0efa869e..414d74d4786d9 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -1,11 +1,15 @@ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:26:28 + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28 | LL | type Out = Box>; | ^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28 | - = note: the return type of a function must have a statically known size +LL | type Out = Box>; + | ^^^^^^^^^^^ the trait `Copy` is not implemented for `String` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs index 4f9100b677449..d180de9be3bf3 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs @@ -24,9 +24,9 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { trait Case1 { type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; - //~^ ERROR `<::C as std::iter::Iterator>::Item` is not an iterator - //~| ERROR `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely - //~| ERROR `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely + //~^ ERROR `<::C as Iterator>::Item` is not an iterator + //~| ERROR `<::C as Iterator>::Item` cannot be sent between threads safely + //~| ERROR `<::C as Iterator>::Item` cannot be shared between threads safely } pub struct S1; diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index c95c5ca588486..e68b5b342a40c 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -1,53 +1,48 @@ -error[E0277]: `<::C as std::iter::Iterator>::Item` is not an iterator - --> $DIR/bad-bounds-on-assoc-in-trait.rs:28:5 - | -LL | / type C: Clone + Iterator Lam<&'a u8, App: -LL | | Debug -LL | | > -LL | | > + Sync>; - | |__________________^ `<::C as std::iter::Iterator>::Item` is not an iterator - | - = help: the trait `std::iter::Iterator` is not implemented for `<::C as std::iter::Iterator>::Item` +error[E0277]: `<::C as Iterator>::Item` is not an iterator + --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:5 + | +LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<::C as Iterator>::Item` is not an iterator + | + = help: the trait `Iterator` is not implemented for `<::C as Iterator>::Item` help: consider further restricting the associated type | -LL | trait Case1 where <::C as std::iter::Iterator>::Item: std::iter::Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Case1 where <::C as Iterator>::Item: Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:23:9 +error[E0277]: `<::C as Iterator>::Item` cannot be sent between threads safely + --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:36 | -LL | Send + Iterator::C as std::iter::Iterator>::Item` cannot be sent between threads safely - | - ::: $SRC_DIR/libcore/marker.rs:LL:COL +LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + | ^^^^ `<::C as Iterator>::Item` cannot be sent between threads safely + | + ::: $SRC_DIR/core/src/marker.rs:LL:COL | LL | pub unsafe auto trait Send { - | -------------------------- required by this bound in `std::marker::Send` + | -------------------------- required by this bound in `Send` | - = help: the trait `std::marker::Send` is not implemented for `<::C as std::iter::Iterator>::Item` + = help: the trait `Send` is not implemented for `<::C as Iterator>::Item` help: consider further restricting the associated type | -LL | trait Case1 where <::C as std::iter::Iterator>::Item: std::marker::Send { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Case1 where <::C as Iterator>::Item: Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:27:13 - | -LL | > + Sync>; - | ^^^^ `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely +error[E0277]: `<::C as Iterator>::Item` cannot be shared between threads safely + --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:93 | - ::: $SRC_DIR/libcore/marker.rs:LL:COL +LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + | ^^^^ `<::C as Iterator>::Item` cannot be shared between threads safely + | + ::: $SRC_DIR/core/src/marker.rs:LL:COL | LL | pub unsafe auto trait Sync { - | -------------------------- required by this bound in `std::marker::Sync` + | -------------------------- required by this bound in `Sync` | - = help: the trait `std::marker::Sync` is not implemented for `<::C as std::iter::Iterator>::Item` + = help: the trait `Sync` is not implemented for `<::C as Iterator>::Item` help: consider further restricting the associated type | -LL | trait Case1 where <::C as std::iter::Iterator>::Item: std::marker::Sync { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Case1 where <::C as Iterator>::Item: Sync { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs index 4025e0fc5e1a6..23be735010bf3 100644 --- a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs +++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - #![feature(associated_type_bounds)] use std::fmt::Debug; @@ -18,7 +16,7 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; } trait Case1 { type A: Iterator; - //~^ ERROR `<::A as std::iter::Iterator>::Item` doesn't implement `std::fmt::Debug` + //~^ ERROR `<::A as Iterator>::Item` doesn't implement `Debug` type B: Iterator; } @@ -35,7 +33,7 @@ impl Case1 for S1 { // bounds of `Out`, but trait selection can't find the bound since it applies // to a type other than `Self::Out`. pub trait Foo { type Out: Baz; } -//~^ ERROR trait bound `<::Out as Baz>::Assoc: std::default::Default` is not satisfied +//~^ ERROR trait bound `<::Out as Baz>::Assoc: Default` is not satisfied pub trait Baz { type Assoc; } #[derive(Default)] diff --git a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr index cc0b58188e624..919b18632e61c 100644 --- a/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr @@ -1,35 +1,35 @@ -error[E0277]: `<::A as std::iter::Iterator>::Item` doesn't implement `std::fmt::Debug` - --> $DIR/bounds-on-assoc-in-trait.rs:20:28 +error[E0277]: `<::A as Iterator>::Item` doesn't implement `Debug` + --> $DIR/bounds-on-assoc-in-trait.rs:18:28 | LL | type A: Iterator; - | ^^^^^ `<::A as std::iter::Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` + | ^^^^^ `<::A as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` | ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL | LL | pub trait Debug { - | --------------- required by this bound in `std::fmt::Debug` + | --------------- required by this bound in `Debug` | - = help: the trait `std::fmt::Debug` is not implemented for `<::A as std::iter::Iterator>::Item` + = help: the trait `Debug` is not implemented for `<::A as Iterator>::Item` help: consider further restricting the associated type | -LL | trait Case1 where <::A as std::iter::Iterator>::Item: std::fmt::Debug { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Case1 where <::A as Iterator>::Item: Debug { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `<::Out as Baz>::Assoc: std::default::Default` is not satisfied - --> $DIR/bounds-on-assoc-in-trait.rs:37:38 +error[E0277]: the trait bound `<::Out as Baz>::Assoc: Default` is not satisfied + --> $DIR/bounds-on-assoc-in-trait.rs:35:38 | LL | pub trait Foo { type Out: Baz; } - | ^^^^^^^ the trait `std::default::Default` is not implemented for `<::Out as Baz>::Assoc` + | ^^^^^^^ the trait `Default` is not implemented for `<::Out as Baz>::Assoc` | ::: $SRC_DIR/core/src/default.rs:LL:COL | LL | pub trait Default: Sized { - | ------------------------ required by this bound in `std::default::Default` + | ------------------------ required by this bound in `Default` | help: consider further restricting the associated type | -LL | pub trait Foo where <::Out as Baz>::Assoc: std::default::Default { type Out: Baz; } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub trait Foo where <::Out as Baz>::Assoc: Default { type Out: Baz; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr index b5941fb80c7e7..de2876d6b60b8 100644 --- a/src/test/ui/associated-type-bounds/duplicate.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.stderr @@ -512,7 +512,7 @@ LL | trait TRSW3 where Self: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:167:40 + --> $DIR/duplicate.rs:152:40 | LL | type TADyn1 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -535,6 +535,30 @@ LL | type TADyn3 = dyn Iterator; | | | `Item` bound here first +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:145:43 + | +LL | trait TRA1 { type A: Iterator; } + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:147:43 + | +LL | trait TRA2 { type A: Iterator; } + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:149:46 + | +LL | trait TRA3 { type A: Iterator; } + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + error: aborting due to 69 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0719`. diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs index 44cc7738d7e2c..504c957d98753 100644 --- a/src/test/ui/associated-types/defaults-suitability.rs +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -20,7 +20,7 @@ where Self::Ty: Clone, { type Ty = NotClone; - //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied + //~^ ERROR the trait bound `NotClone: Clone` is not satisfied } // Involved type parameters must fulfill all bounds required by defaults that mention them @@ -85,7 +85,7 @@ where { type Bar = Vec; type Baz = T; - //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied + //~^ ERROR the trait bound `T: Clone` is not satisfied } // This one finally works, with `Clone` bounds on all assoc. types and the type diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 5ee800e19133d..274d09fd09c86 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -1,31 +1,32 @@ -error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied +error[E0277]: the trait bound `NotClone: Clone` is not satisfied --> $DIR/defaults-suitability.rs:13:5 | LL | type Ty: Clone = NotClone; | ^^^^^^^^^-----^^^^^^^^^^^^ | | | | | required by this bound in `Tr::Ty` - | the trait `std::clone::Clone` is not implemented for `NotClone` + | the trait `Clone` is not implemented for `NotClone` -error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:19:5 +error[E0277]: the trait bound `NotClone: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:22:5 | -LL | trait Tr2 where Self::Ty: Clone { - | ----- required by this bound in `Tr2::Ty` +LL | Self::Ty: Clone, + | ----- required by this bound in `Tr2::Ty` +LL | { LL | type Ty = NotClone; | ^^^^^--^^^^^^^^^^^^ | | | | | required by a bound in this - | the trait `std::clone::Clone` is not implemented for `NotClone` + | the trait `Clone` is not implemented for `NotClone` -error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:25:5 +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:28:5 | LL | type Bar: Clone = Vec; | ^^^^^^^^^^-----^^^^^^^^^^ | | | | | required by this bound in `Foo::Bar` - | the trait `std::clone::Clone` is not implemented for `T` + | the trait `Clone` is not implemented for `T` | = note: required because of the requirements on the impl of `Clone` for `Vec` help: consider restricting type parameter `T` @@ -34,7 +35,7 @@ LL | trait Foo { | ^^^^^^^ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/defaults-suitability.rs:31:5 + --> $DIR/defaults-suitability.rs:34:5 | LL | type Assoc: Foo = (); | ^^^^^^^^^^^^---------^^^^^^ @@ -43,7 +44,7 @@ LL | type Assoc: Foo = (); | the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `NotClone: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:53:5 + --> $DIR/defaults-suitability.rs:56:5 | LL | Self::Assoc: IsU8, | ----------------- required by this bound in `D::Assoc` @@ -54,14 +55,14 @@ LL | type Assoc = NotClone; | | required by a bound in this | the trait `IsU8` is not implemented for `NotClone` -error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:62:5 +error[E0277]: the trait bound `>::Baz: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:65:5 | LL | type Bar: Clone = Vec; | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ | | | | | required by this bound in `Foo2::Bar` - | the trait `std::clone::Clone` is not implemented for `>::Baz` + | the trait `Clone` is not implemented for `>::Baz` | = note: required because of the requirements on the impl of `Clone` for `Vec<>::Baz>` help: consider further restricting the associated type @@ -69,14 +70,14 @@ help: consider further restricting the associated type LL | trait Foo2 where >::Baz: Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:71:5 +error[E0277]: the trait bound `>::Baz: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:74:5 | LL | type Bar: Clone = Vec; | ^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^ | | | | | required by this bound in `Foo25::Bar` - | the trait `std::clone::Clone` is not implemented for `>::Baz` + | the trait `Clone` is not implemented for `>::Baz` | = note: required because of the requirements on the impl of `Clone` for `Vec<>::Baz>` help: consider further restricting the associated type @@ -84,8 +85,8 @@ help: consider further restricting the associated type LL | trait Foo25 where >::Baz: Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:83:5 +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:87:5 | LL | Self::Baz: Clone, | ----- required by this bound in `Foo3::Baz` @@ -94,7 +95,7 @@ LL | type Baz = T; | ^^^^^---^^^^^ | | | | | required by a bound in this - | the trait `std::clone::Clone` is not implemented for `T` + | the trait `Clone` is not implemented for `T` | help: consider further restricting type parameter `T` | diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs index 093e32f66be0e..fa6a208b4f1ba 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -18,6 +18,10 @@ trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self // and it's accepted, not knowing if Self ineed is Copy type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + //~^ ERROR the trait bound `Self: Copy` is not satisfied + //~| ERROR the trait bound `Self: Deref` is not satisfied + //~| ERROR cannot add-assign `&'static str` to `Self` + //~| ERROR `Self` doesn't implement `std::fmt::Display` // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index a8584d6dc5c1b..8e446cf051f47 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -1,19 +1,11 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:21:5 + --> $DIR/defaults-unsound-62211-1.rs:20:5 | -LL | type Output: Copy - | ^ ------ required by a bound in this - | _____| - | | -LL | | -LL | | -LL | | -... | -LL | | + From -LL | | + Display = Self; - | |___________-------_______^ `Self` cannot be formatted with the default formatter - | | - | required by this bound in `UncheckedCopy::Output` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | `Self` cannot be formatted with the default formatter | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead help: consider further restricting `Self` @@ -21,23 +13,14 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + std::fmt::Display { | ^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:21:5 +error[E0277]: the trait bound `Self: Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:20:5 | -LL | type Output: Copy - | ^ ------ required by a bound in this - | _____| - | | -LL | | -LL | | -LL | | -LL | | -LL | | + Deref - | | ------------------- required by this bound in `UncheckedCopy::Output` -LL | | + AddAssign<&'static str> -LL | | + From -LL | | + Display = Self; - | |_________________________^ the trait `std::ops::Deref` is not implemented for `Self` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | the trait `Deref` is not implemented for `Self` | help: consider further restricting `Self` | @@ -45,46 +28,32 @@ LL | trait UncheckedCopy: Sized + Deref { | ^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-1.rs:21:5 + --> $DIR/defaults-unsound-62211-1.rs:20:5 | -LL | type Output: Copy - | ^ ------ required by a bound in this - | _____| - | | -LL | | -LL | | -LL | | -... | -LL | | + AddAssign<&'static str> - | | ----------------------- required by this bound in `UncheckedCopy::Output` -LL | | + From -LL | | + Display = Self; - | |_________________________^ no implementation for `Self += &'static str` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | no implementation for `Self += &'static str` | help: consider further restricting `Self` | -LL | trait UncheckedCopy: Sized + std::ops::AddAssign<&'static str> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:21:5 +error[E0277]: the trait bound `Self: Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:20:5 | -LL | type Output: Copy - | ^ ---- required by this bound in `UncheckedCopy::Output` - | _____| - | | -LL | | -LL | | -LL | | -... | -LL | | + From -LL | | + Display = Self; - | |_________________________^ the trait `std::marker::Copy` is not implemented for `Self` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | the trait `Copy` is not implemented for `Self` | help: consider further restricting `Self` | -LL | trait UncheckedCopy: Sized + std::marker::Copy { - | ^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + Copy { + | ^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs index 44bbdc9f52b84..c13ec776afe2b 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -18,6 +18,10 @@ trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self // and it's accepted, not knowing if Self ineed is Copy type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + //~^ ERROR the trait bound `Self: Copy` is not satisfied + //~| ERROR the trait bound `Self: Deref` is not satisfied + //~| ERROR cannot add-assign `&'static str` to `Self` + //~| ERROR `Self` doesn't implement `std::fmt::Display` // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index 6a8e3ff7b626d..93f4f497b38a2 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -1,19 +1,11 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:21:5 + --> $DIR/defaults-unsound-62211-2.rs:20:5 | -LL | type Output: Copy - | ^ ------ required by a bound in this - | _____| - | | -LL | | -LL | | -LL | | -... | -LL | | + From -LL | | + Display = Self; - | |___________-------_______^ `Self` cannot be formatted with the default formatter - | | - | required by this bound in `UncheckedCopy::Output` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | `Self` cannot be formatted with the default formatter | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead help: consider further restricting `Self` @@ -21,23 +13,14 @@ help: consider further restricting `Self` LL | trait UncheckedCopy: Sized + std::fmt::Display { | ^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:21:5 +error[E0277]: the trait bound `Self: Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:20:5 | -LL | type Output: Copy - | ^ ------ required by a bound in this - | _____| - | | -LL | | -LL | | -LL | | -LL | | -LL | | + Deref - | | ------------------- required by this bound in `UncheckedCopy::Output` -LL | | + AddAssign<&'static str> -LL | | + From -LL | | + Display = Self; - | |_________________________^ the trait `std::ops::Deref` is not implemented for `Self` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | the trait `Deref` is not implemented for `Self` | help: consider further restricting `Self` | @@ -45,46 +28,32 @@ LL | trait UncheckedCopy: Sized + Deref { | ^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-2.rs:21:5 + --> $DIR/defaults-unsound-62211-2.rs:20:5 | -LL | type Output: Copy - | ^ ------ required by a bound in this - | _____| - | | -LL | | -LL | | -LL | | -... | -LL | | + AddAssign<&'static str> - | | ----------------------- required by this bound in `UncheckedCopy::Output` -LL | | + From -LL | | + Display = Self; - | |_________________________^ no implementation for `Self += &'static str` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | no implementation for `Self += &'static str` | help: consider further restricting `Self` | -LL | trait UncheckedCopy: Sized + std::ops::AddAssign<&'static str> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:21:5 +error[E0277]: the trait bound `Self: Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:20:5 | -LL | type Output: Copy - | ^ ---- required by this bound in `UncheckedCopy::Output` - | _____| - | | -LL | | -LL | | -LL | | -... | -LL | | + From -LL | | + Display = Self; - | |_________________________^ the trait `std::marker::Copy` is not implemented for `Self` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | required by this bound in `UncheckedCopy::Output` + | the trait `Copy` is not implemented for `Self` | help: consider further restricting `Self` | -LL | trait UncheckedCopy: Sized + std::marker::Copy { - | ^^^^^^^^^^^^^^^^^^^ +LL | trait UncheckedCopy: Sized + Copy { + | ^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/associated-types/defaults-wf.stderr b/src/test/ui/associated-types/defaults-wf.stderr index d1832cdbc0cd4..f9044c2ea1b66 100644 --- a/src/test/ui/associated-types/defaults-wf.stderr +++ b/src/test/ui/associated-types/defaults-wf.stderr @@ -7,9 +7,9 @@ LL | type Ty = Vec<[u8]>; ::: $SRC_DIR/alloc/src/vec.rs:LL:COL | LL | pub struct Vec { - | - required by this bound in `std::vec::Vec` + | - required by this bound in `Vec` | - = help: the trait `std::marker::Sized` is not implemented for `[u8]` + = help: the trait `Sized` is not implemented for `[u8]` error: aborting due to previous error diff --git a/src/test/ui/associated-types/issue-43924.stderr b/src/test/ui/associated-types/issue-43924.stderr index 9bcedb05ed4d0..8d4ecac750268 100644 --- a/src/test/ui/associated-types/issue-43924.stderr +++ b/src/test/ui/associated-types/issue-43924.stderr @@ -1,17 +1,17 @@ -error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied +error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied --> $DIR/issue-43924.rs:7:5 | LL | type Out: Default + ToString + ?Sized = dyn ToString; | ^^^^^^^^^^-------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | | | required by this bound in `Foo::Out` - | the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)` + | the trait `Default` is not implemented for `(dyn ToString + 'static)` -error[E0599]: no function or associated item named `default` found for trait object `(dyn std::string::ToString + 'static)` in the current scope +error[E0599]: no function or associated item named `default` found for trait object `(dyn ToString + 'static)` in the current scope --> $DIR/issue-43924.rs:14:39 | LL | assert_eq!(<() as Foo>::Out::default().to_string(), "false"); - | ^^^^^^^ function or associated item not found in `(dyn std::string::ToString + 'static)` + | ^^^^^^^ function or associated item not found in `(dyn ToString + 'static)` error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index 8cd0e40c8cf84..994bfd33ba42e 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -5,7 +5,6 @@ LL | fn get_future() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future | = help: the trait `Future` is not implemented for `()` - = note: the return type of a function must have a statically known size error[E0698]: type inside `async fn` body must be known in this context --> $DIR/async-error-span.rs:13:9 diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index f1f1b2d4439ec..88ea7251eaf1f 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -27,33 +27,18 @@ error[E0609]: no field `0` on type `impl Future` | LL | let _: i32 = tuple().0; | ^ - | -help: consider awaiting before field access - | -LL | let _: i32 = tuple().await.0; - | ^^^^^^ error[E0609]: no field `a` on type `impl Future` --> $DIR/issue-61076.rs:60:28 | LL | let _: i32 = struct_().a; | ^ - | -help: consider awaiting before field access - | -LL | let _: i32 = struct_().await.a; - | ^^^^^^ error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope --> $DIR/issue-61076.rs:62:15 | LL | struct_().method(); | ^^^^^^ method not found in `impl Future` - | -help: consider awaiting before this method call - | -LL | struct_().await.method(); - | ^^^^^^ error[E0308]: mismatched types --> $DIR/issue-61076.rs:69:9 @@ -66,10 +51,6 @@ LL | Tuple(_) => {} | = note: expected opaque type `impl Future` found struct `Tuple` -help: consider awaiting on the future - | -LL | match tuple().await { - | ^^^^^^ error: aborting due to 6 previous errors diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index f5d023ab781ff..2d46dfb7269d1 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -1,17 +1,8 @@ error: future cannot be sent between threads safely --> $DIR/issue-64130-4-async-move.rs:15:17 | -LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` -... -LL | / async move { -LL | | match client.status() { -LL | | 200 => { -LL | | let _x = get().await; -... | -LL | | } -LL | | } - | |_____- this returned value is of type `impl Future` +LL | pub fn foo() -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` note: future is not `Send` as this value is used across an await diff --git a/src/test/ui/async-await/issue-70818.stderr b/src/test/ui/async-await/issue-70818.stderr index 20ee22e448c91..11fca2dd8ef4c 100644 --- a/src/test/ui/async-await/issue-70818.stderr +++ b/src/test/ui/async-await/issue-70818.stderr @@ -3,9 +3,6 @@ error: future cannot be sent between threads safely | LL | fn foo(ty: T, ty1: U) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` -LL | -LL | async { (ty, ty1) } - | ------------------- this returned value is of type `impl Future` | note: captured value is not `Send` --> $DIR/issue-70818.rs:6:18 diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr index 97c33c0708e49..200d411b51194 100644 --- a/src/test/ui/closures/issue-41366.stderr +++ b/src/test/ui/closures/issue-41366.stderr @@ -15,12 +15,12 @@ error[E0277]: the size for values of type `>::V` cannot be known at LL | (&|_| ()) as &dyn for<'x> Fn(>::V); | ^ doesn't have a size known at compile-time | - = help: the trait `std::marker::Sized` is not implemented for `>::V` + = help: the trait `Sized` is not implemented for `>::V` = help: unsized locals are gated as an unstable feature help: consider further restricting the associated type | -LL | fn main() where >::V: std::marker::Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn main() where >::V: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: function arguments must have a statically known size, borrowed types always have a known size | LL | (&|&_| ()) as &dyn for<'x> Fn(>::V); diff --git a/src/test/ui/conservative_impl_trait.stderr b/src/test/ui/conservative_impl_trait.stderr index 87058c3c29cf4..63a4df242f85f 100644 --- a/src/test/ui/conservative_impl_trait.stderr +++ b/src/test/ui/conservative_impl_trait.stderr @@ -5,7 +5,6 @@ LL | fn will_ice(something: &u32) -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` - = note: the return type of a function must have a statically known size error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs index 7dac2b26cce09..38be85ff8201e 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength // compile-flags: -Zsave-analysis // This is also a regression test for #69415 and the above flag is needed. @@ -15,7 +14,7 @@ impl Tr1 for S1 { type As1 = S2; } trait _Tr3 { type A: Iterator; //~^ ERROR associated type bounds are unstable - //~| ERROR the trait bound `<::A as std::iter::Iterator>::Item: std::marker::Copy` is not satisfied + //~| ERROR the trait bound `<::A as Iterator>::Item: Copy` is not satisfied type B: Iterator; //~^ ERROR associated type bounds are unstable diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr index 987b678758173..be5d35139b65c 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -1,5 +1,5 @@ error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:16:22 + --> $DIR/feature-gate-associated_type_bounds.rs:15:22 | LL | type A: Iterator; | ^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | type A: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:20:22 + --> $DIR/feature-gate-associated_type_bounds.rs:19:22 | LL | type B: Iterator; | ^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | type B: Iterator; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:24:20 + --> $DIR/feature-gate-associated_type_bounds.rs:23:20 | LL | struct _St1> { | ^^^^^^^^ @@ -26,7 +26,7 @@ LL | struct _St1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:31:18 + --> $DIR/feature-gate-associated_type_bounds.rs:30:18 | LL | enum _En1> { | ^^^^^^^^ @@ -35,7 +35,7 @@ LL | enum _En1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:38:19 + --> $DIR/feature-gate-associated_type_bounds.rs:37:19 | LL | union _Un1> { | ^^^^^^^^ @@ -44,7 +44,7 @@ LL | union _Un1> { = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:45:37 + --> $DIR/feature-gate-associated_type_bounds.rs:44:37 | LL | type _TaWhere1 where T: Iterator = T; | ^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | type _TaWhere1 where T: Iterator = T; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:48:22 + --> $DIR/feature-gate-associated_type_bounds.rs:47:22 | LL | fn _apit(_: impl Tr1) {} | ^^^^^^^^^ @@ -62,7 +62,7 @@ LL | fn _apit(_: impl Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:50:26 + --> $DIR/feature-gate-associated_type_bounds.rs:49:26 | LL | fn _apit_dyn(_: &dyn Tr1) {} | ^^^^^^^^^ @@ -71,7 +71,7 @@ LL | fn _apit_dyn(_: &dyn Tr1) {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:53:24 + --> $DIR/feature-gate-associated_type_bounds.rs:52:24 | LL | fn _rpit() -> impl Tr1 { S1 } | ^^^^^^^^^ @@ -80,7 +80,7 @@ LL | fn _rpit() -> impl Tr1 { S1 } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:56:31 + --> $DIR/feature-gate-associated_type_bounds.rs:55:31 | LL | fn _rpit_dyn() -> Box> { Box::new(S1) } | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | fn _rpit_dyn() -> Box> { Box::new(S1) } = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:59:23 + --> $DIR/feature-gate-associated_type_bounds.rs:58:23 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -98,7 +98,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:65:24 + --> $DIR/feature-gate-associated_type_bounds.rs:64:24 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -107,7 +107,7 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:72:21 + --> $DIR/feature-gate-associated_type_bounds.rs:71:21 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^ @@ -116,7 +116,7 @@ LL | let _: impl Tr1 = S1; = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:59:14 + --> $DIR/feature-gate-associated_type_bounds.rs:58:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | const _cdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:65:15 + --> $DIR/feature-gate-associated_type_bounds.rs:64:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -132,28 +132,28 @@ LL | static _sdef: impl Tr1 = S1; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/feature-gate-associated_type_bounds.rs:72:12 + --> $DIR/feature-gate-associated_type_bounds.rs:71:12 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error[E0277]: the trait bound `<::A as std::iter::Iterator>::Item: std::marker::Copy` is not satisfied - --> $DIR/feature-gate-associated_type_bounds.rs:16:28 +error[E0277]: the trait bound `<::A as Iterator>::Item: Copy` is not satisfied + --> $DIR/feature-gate-associated_type_bounds.rs:15:28 | LL | type A: Iterator; - | ^^^^ the trait `std::marker::Copy` is not implemented for `<::A as std::iter::Iterator>::Item` + | ^^^^ the trait `Copy` is not implemented for `<::A as Iterator>::Item` | ::: $SRC_DIR/core/src/marker.rs:LL:COL | LL | pub trait Copy: Clone { - | --------------------- required by this bound in `std::marker::Copy` + | --------------------- required by this bound in `Copy` | help: consider further restricting the associated type | -LL | trait _Tr3 where <::A as std::iter::Iterator>::Item: std::marker::Copy { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait _Tr3 where <::A as Iterator>::Item: Copy { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 17 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs index 34823cbafd321..1d2be3657ffb2 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs @@ -15,7 +15,7 @@ impl PointerFamily for Foo { //~^ ERROR generic associated types are unstable type Pointer2 = Box; //~^ ERROR generic associated types are unstable - //~| ERROR the trait bound `U32: std::clone::Clone` is not satisfied + //~| ERROR the trait bound `U32: Clone` is not satisfied } trait Bar { diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr index e04a129dbbbb6..266008cc0def4 100644 --- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr +++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr @@ -61,16 +61,16 @@ LL | type Assoc where Self: Sized = Foo; = note: see issue #44265 for more information = help: add `#![feature(generic_associated_types)]` to the crate attributes to enable -error[E0277]: the trait bound `U32: std::clone::Clone` is not satisfied +error[E0277]: the trait bound `U32: Clone` is not satisfied --> $DIR/feature-gate-generic_associated_types.rs:16:5 | LL | type Pointer2 = Box; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `U32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `U32` | help: consider restricting type parameter `U32` | -LL | type Pointer2 = Box; - | ^^^^^^^^^^^^^^^^^^^ +LL | type Pointer2 = Box; + | ^^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs index 8aca8c388d4a3..97a4ea53af583 100644 --- a/src/test/ui/for/for-c-in-str.rs +++ b/src/test/ui/for/for-c-in-str.rs @@ -1,16 +1,16 @@ // E0277 should point exclusively at line 6, not the entire for loop span -// ignore-tidy-linelength - fn main() { for c in "asdf" { //~^ ERROR `&str` is not an iterator //~| NOTE `&str` is not an iterator //~| HELP the trait `Iterator` is not implemented for `&str` + //~| NOTE required because of the requirements on the impl of `IntoIterator` for `&str` //~| NOTE required by `into_iter` //~| NOTE in this expansion of desugaring of `for` loop //~| NOTE in this expansion of desugaring of `for` loop //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop println!(); } } diff --git a/src/test/ui/for/for-c-in-str.stderr b/src/test/ui/for/for-c-in-str.stderr index f991e08e518cc..18e46e1d7ded7 100644 --- a/src/test/ui/for/for-c-in-str.stderr +++ b/src/test/ui/for/for-c-in-str.stderr @@ -1,10 +1,11 @@ error[E0277]: `&str` is not an iterator - --> $DIR/for-c-in-str.rs:6:14 + --> $DIR/for-c-in-str.rs:4:14 | LL | for c in "asdf" { | ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | = help: the trait `Iterator` is not implemented for `&str` + = note: required because of the requirements on the impl of `IntoIterator` for `&str` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/for/for-loop-bogosity.stderr b/src/test/ui/for/for-loop-bogosity.stderr index ccacd655a147d..0d9409626897f 100644 --- a/src/test/ui/for/for-loop-bogosity.stderr +++ b/src/test/ui/for/for-loop-bogosity.stderr @@ -5,6 +5,7 @@ LL | for x in bogus { | ^^^^^ `MyStruct` is not an iterator | = help: the trait `Iterator` is not implemented for `MyStruct` + = note: required because of the requirements on the impl of `IntoIterator` for `MyStruct` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr index 19658528a0b89..8e3c2f67ed165 100644 --- a/src/test/ui/generator/sized-yield.stderr +++ b/src/test/ui/generator/sized-yield.stderr @@ -20,7 +20,7 @@ LL | Pin::new(&mut gen).resume(()); ::: $SRC_DIR/core/src/ops/generator.rs:LL:COL | LL | pub enum GeneratorState { - | - required by this bound in `std::ops::GeneratorState` + | - required by this bound in `GeneratorState` | = help: the trait `Sized` is not implemented for `str` diff --git a/src/test/ui/generic-associated-types/cross-crate-bounds.rs b/src/test/ui/generic-associated-types/cross-crate-bounds.rs index 4e2bab38c88a3..8934a07fd4e39 100644 --- a/src/test/ui/generic-associated-types/cross-crate-bounds.rs +++ b/src/test/ui/generic-associated-types/cross-crate-bounds.rs @@ -13,7 +13,7 @@ pub struct FooImpl; impl Foo for FooImpl { type Bar = (); - //~^ ERROR the trait bound `(): std::convert::AsRef<()>` is not satisfied + //~^ ERROR the trait bound `(): AsRef<()>` is not satisfied fn foo(&self) -> Pin + '_>> { panic!() } diff --git a/src/test/ui/generic-associated-types/cross-crate-bounds.stderr b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr index 5fd2750868fef..d96c5f4540ef5 100644 --- a/src/test/ui/generic-associated-types/cross-crate-bounds.stderr +++ b/src/test/ui/generic-associated-types/cross-crate-bounds.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `(): std::convert::AsRef<()>` is not satisfied +error[E0277]: the trait bound `(): AsRef<()>` is not satisfied --> $DIR/cross-crate-bounds.rs:15:5 | LL | type Bar = (); - | ^^^^^^^^^^^^^^ the trait `std::convert::AsRef<()>` is not implemented for `()` + | ^^^^^^^^^^^^^^ the trait `AsRef<()>` is not implemented for `()` | ::: $DIR/auxiliary/foo_defn.rs:6:15 | diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index e6f27a45a3cfb..645d292714562 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -24,8 +24,25 @@ note: but lifetime parameter must outlive the lifetime `'a` as defined on the as LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); | ^^ +error[E0478]: lifetime bound not satisfied + --> $DIR/impl_bounds.rs:17:5 + | +LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined on the associated item at 17:12 + --> $DIR/impl_bounds.rs:17:12 + | +LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); + | ^^ +note: but lifetime parameter must outlive the lifetime `'b` as defined on the associated item at 17:16 + --> $DIR/impl_bounds.rs:17:16 + | +LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ()); + | ^^ + error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:19:5 + --> $DIR/impl_bounds.rs:20:5 | LL | type C where Self: Copy = String; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs index c88fb8ad96e3e..0cd676a9b37f3 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -43,7 +43,7 @@ impl Bar for T where T: Foo { // can use the bound on `Foo::Item` for this, but that requires // `wf(::Item)`, which is an invalid cycle. type Assoc = OnlySized<::Item>; - //~^ ERROR overflow evaluating the requirement `::Item: std::marker::Sized` + //~^ ERROR overflow evaluating the requirement `::Item: Sized` } fn foo() { diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr index 5967752ef7973..d27e46f6836df 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -7,7 +7,7 @@ LL | #![feature(generic_associated_types)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44265 for more information -error[E0275]: overflow evaluating the requirement `::Item: std::marker::Sized` +error[E0275]: overflow evaluating the requirement `::Item: Sized` --> $DIR/projection-bound-cycle-generic.rs:45:5 | LL | struct OnlySized where T: Sized { f: T } diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.rs b/src/test/ui/generic-associated-types/projection-bound-cycle.rs index 0728dc1bcbc9b..5043fe5c08f51 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.rs @@ -45,7 +45,7 @@ impl Bar for T where T: Foo { // can use the bound on `Foo::Item` for this, but that requires // `wf(::Item)`, which is an invalid cycle. type Assoc = OnlySized<::Item>; - //~^ ERROR overflow evaluating the requirement `::Item: std::marker::Sized` + //~^ ERROR overflow evaluating the requirement `::Item: Sized` } fn foo() { diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr index 80d102013a79b..400b664f97ca9 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.stderr +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.stderr @@ -7,7 +7,7 @@ LL | #![feature(generic_associated_types)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #44265 for more information -error[E0275]: overflow evaluating the requirement `::Item: std::marker::Sized` +error[E0275]: overflow evaluating the requirement `::Item: Sized` --> $DIR/projection-bound-cycle.rs:47:5 | LL | struct OnlySized where T: Sized { f: T } diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr index 6da3704184abb..58c5ee45051af 100644 --- a/src/test/ui/impl-trait/issue-55872-2.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.stderr @@ -3,8 +3,6 @@ error[E0277]: the trait bound `impl Future: Copy` is not satisfied | LL | type E = impl std::marker::Copy; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` - | - = note: the return type of a function must have a statically known size error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias --> $DIR/issue-55872-2.rs:15:28 diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr index ec03d18924fea..2f630c2c9ad71 100644 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr @@ -7,7 +7,7 @@ LL | #![feature(impl_trait_in_bindings)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63065 for more information -error[E0282]: type annotations needed for `impl std::future::Future` +error[E0282]: type annotations needed for `impl Future` --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20 | LL | let fut = async { diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr index 835d479f28f19..bbcdd3e37a96e 100644 --- a/src/test/ui/issues-71798.stderr +++ b/src/test/ui/issues-71798.stderr @@ -11,7 +11,6 @@ LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future | = help: the trait `Future` is not implemented for `u32` - = note: the return type of a function must have a statically known size error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index 25fa575fc6051..9940f43cc4440 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -4,9 +4,9 @@ error[E0277]: the size for values of type `dyn Iterator` cann LL | for item in *things { *item = 0 } | ^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator` - = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `dyn std::iter::Iterator` - = note: required by `std::iter::IntoIterator::into_iter` + = help: the trait `Sized` is not implemented for `dyn Iterator` + = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator` + = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index 1764dd3cf67a1..bcfb6b70b2e5f 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -7,14 +7,8 @@ LL | fn subscribe(&mut self, t : Box $DIR/issue-20831-debruijn.rs:28:5 | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | // -... | -LL | | self.sub = t; -LL | | } - | |_____^ +LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6... --> $DIR/issue-20831-debruijn.rs:26:6 | diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index 0d645bbcea59f..7ed04519b69ca 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized` +error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized` --> $DIR/issue-23122-2.rs:8:5 | LL | type Next = as Next>::Next; diff --git a/src/test/ui/issues/issue-28098.stderr b/src/test/ui/issues/issue-28098.stderr index 04075911111ae..4c927a0cb458f 100644 --- a/src/test/ui/issues/issue-28098.stderr +++ b/src/test/ui/issues/issue-28098.stderr @@ -13,9 +13,9 @@ error[E0277]: `bool` is not an iterator LL | for _ in false {} | ^^^^^ `bool` is not an iterator | - = help: the trait `std::iter::Iterator` is not implemented for `bool` - = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `bool` - = note: required by `std::iter::IntoIterator::into_iter` + = help: the trait `Iterator` is not implemented for `bool` + = note: required because of the requirements on the impl of `IntoIterator` for `bool` + = note: required by `into_iter` error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:9:28 @@ -59,6 +59,7 @@ LL | for _ in false {} | ^^^^^ `bool` is not an iterator | = help: the trait `Iterator` is not implemented for `bool` + = note: required because of the requirements on the impl of `IntoIterator` for `bool` = note: required by `into_iter` error[E0277]: `()` is not an iterator diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr index 81d97bdbf1242..e91dae08b3a33 100644 --- a/src/test/ui/issues/issue-33941.stderr +++ b/src/test/ui/issues/issue-33941.stderr @@ -15,9 +15,9 @@ LL | for _ in HashMap::new().iter().cloned() {} | = note: expected tuple `(&_, &_)` found reference `&_` - = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned>` - = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `std::iter::Cloned>` - = note: required by `std::iter::IntoIterator::into_iter` + = note: required because of the requirements on the impl of `Iterator` for `Cloned>` + = note: required because of the requirements on the impl of `IntoIterator` for `Cloned>` + = note: required by `into_iter` error[E0271]: type mismatch resolving ` as Iterator>::Item == &_` --> $DIR/issue-33941.rs:4:14 @@ -28,6 +28,7 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: expected tuple `(&_, &_)` found reference `&_` = note: required because of the requirements on the impl of `Iterator` for `Cloned>` + = note: required by `std::iter::Iterator::next` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-41139.rs b/src/test/ui/issues/issue-41139.rs index ebdc5cb6dbe5d..94c53216f50ac 100644 --- a/src/test/ui/issues/issue-41139.rs +++ b/src/test/ui/issues/issue-41139.rs @@ -1,10 +1,12 @@ trait Trait {} -fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { panic!("") } +fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { + panic!("") +} fn main() { // This isn't great. The issue here is that `dyn Trait` is not sized, so // `dyn Fn() -> dyn Trait` is not well-formed. - let t : &dyn Trait = &get_function()(); - //~^ ERROR expected function, found `&dyn std::ops::Fn() -> (dyn Trait + 'static)` + let t: &dyn Trait = &get_function()(); + //~^ ERROR expected function, found `&dyn Fn() -> (dyn Trait + 'static)` } diff --git a/src/test/ui/issues/issue-41139.stderr b/src/test/ui/issues/issue-41139.stderr index 083c413c316df..48b22bca20f06 100644 --- a/src/test/ui/issues/issue-41139.stderr +++ b/src/test/ui/issues/issue-41139.stderr @@ -1,13 +1,13 @@ -error[E0618]: expected function, found `&dyn std::ops::Fn() -> (dyn Trait + 'static)` - --> $DIR/issue-41139.rs:8:27 +error[E0618]: expected function, found `&dyn Fn() -> (dyn Trait + 'static)` + --> $DIR/issue-41139.rs:10:26 | -LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { panic!("") } - | ----------------------------------------------------------------- `get_function` defined here returns `&dyn std::ops::Fn() -> (dyn Trait + 'static)` +LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { + | -------------------------------------------------- `get_function` defined here returns `&dyn Fn() -> (dyn Trait + 'static)` ... -LL | let t : &dyn Trait = &get_function()(); - | ^^^^^^^^^^^^^^-- - | | - | call expression requires function +LL | let t: &dyn Trait = &get_function()(); + | ^^^^^^^^^^^^^^-- + | | + | call expression requires function error: aborting due to previous error diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index 7b656ef8559ca..d5105ae3b5815 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied +error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-43784-associated-type.rs:14:5 | LL | type Assoc: Partial; | ------------- required by this bound in `Complete::Assoc` ... LL | type Assoc = T; - | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index 80f118e12c4a7..650570b6471eb 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -24,11 +24,11 @@ LL | foo((), drop) LL | pub fn drop(_x: T) {} | - required by this bound in `std::mem::drop` | - = help: the trait `std::marker::Sized` is not implemented for `<() as Trait<'_>>::Item` + = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item` help: consider further restricting the associated type | -LL | fn main() where <() as Trait<'_>>::Item: std::marker::Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn main() where <() as Trait<'_>>::Item: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/array-of-ranges.stderr b/src/test/ui/iterators/array-of-ranges.stderr index 6271d8107bc05..601983a6153fd 100644 --- a/src/test/ui/iterators/array-of-ranges.stderr +++ b/src/test/ui/iterators/array-of-ranges.stderr @@ -6,6 +6,7 @@ LL | for _ in [0..1] {} | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]` = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end` + = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator @@ -16,6 +17,7 @@ LL | for _ in [0..=1] {} | = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[RangeFrom<{integer}>; 1]` is not an iterator @@ -26,6 +28,7 @@ LL | for _ in [0..] {} | = help: the trait `Iterator` is not implemented for `[RangeFrom<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeFrom<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[RangeTo<{integer}>; 1]` is not an iterator @@ -36,6 +39,7 @@ LL | for _ in [..1] {} | = help: the trait `Iterator` is not implemented for `[RangeTo<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeTo<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[RangeToInclusive<{integer}>; 1]` is not an iterator @@ -46,6 +50,7 @@ LL | for _ in [..=1] {} | = help: the trait `Iterator` is not implemented for `[RangeToInclusive<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeToInclusive<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator @@ -56,6 +61,7 @@ LL | for _ in [start..end] {} | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]` = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end` + = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[std::ops::Range<{integer}>; 1]` is not an iterator @@ -66,6 +72,7 @@ LL | for _ in array_of_range {} | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 1]` = note: `[start..end]` is an array of one `Range`; you might have meant to have a `Range` without the brackets: `start..end` + = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 1]` = note: required by `into_iter` error[E0277]: `[std::ops::Range<{integer}>; 2]` is not an iterator @@ -76,6 +83,7 @@ LL | for _ in [0..1, 2..3] {} | = help: the trait `Iterator` is not implemented for `[std::ops::Range<{integer}>; 2]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[std::ops::Range<{integer}>; 2]` = note: required by `into_iter` error[E0277]: `[RangeInclusive<{integer}>; 1]` is not an iterator @@ -86,6 +94,7 @@ LL | for _ in [0..=1] {} | = help: the trait `Iterator` is not implemented for `[RangeInclusive<{integer}>; 1]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[RangeInclusive<{integer}>; 1]` = note: required by `into_iter` error: aborting due to 9 previous errors diff --git a/src/test/ui/iterators/array.stderr b/src/test/ui/iterators/array.stderr index f86c82e4917e6..68c6de5493f13 100644 --- a/src/test/ui/iterators/array.stderr +++ b/src/test/ui/iterators/array.stderr @@ -6,6 +6,7 @@ LL | for _ in [1, 2] {} | = help: the trait `Iterator` is not implemented for `[{integer}; 2]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` = note: required by `into_iter` error[E0277]: `[{integer}; 2]` is not an iterator @@ -16,6 +17,7 @@ LL | for _ in x {} | = help: the trait `Iterator` is not implemented for `[{integer}; 2]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[{integer}; 2]` = note: required by `into_iter` error[E0277]: `[{float}; 2]` is not an iterator @@ -26,6 +28,7 @@ LL | for _ in [1.0, 2.0] {} | = help: the trait `Iterator` is not implemented for `[{float}; 2]` = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]` + = note: required because of the requirements on the impl of `IntoIterator` for `[{float}; 2]` = note: required by `into_iter` error: aborting due to 3 previous errors diff --git a/src/test/ui/iterators/integral.stderr b/src/test/ui/iterators/integral.stderr index c4c464126111d..e31ee59785c8b 100644 --- a/src/test/ui/iterators/integral.stderr +++ b/src/test/ui/iterators/integral.stderr @@ -6,6 +6,7 @@ LL | for _ in 42 {} | = help: the trait `Iterator` is not implemented for `{integer}` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `{integer}` = note: required by `into_iter` error[E0277]: `u8` is not an iterator @@ -16,6 +17,7 @@ LL | for _ in 42 as u8 {} | = help: the trait `Iterator` is not implemented for `u8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `u8` = note: required by `into_iter` error[E0277]: `i8` is not an iterator @@ -26,6 +28,7 @@ LL | for _ in 42 as i8 {} | = help: the trait `Iterator` is not implemented for `i8` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `i8` = note: required by `into_iter` error[E0277]: `u16` is not an iterator @@ -36,6 +39,7 @@ LL | for _ in 42 as u16 {} | = help: the trait `Iterator` is not implemented for `u16` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `u16` = note: required by `into_iter` error[E0277]: `i16` is not an iterator @@ -46,6 +50,7 @@ LL | for _ in 42 as i16 {} | = help: the trait `Iterator` is not implemented for `i16` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `i16` = note: required by `into_iter` error[E0277]: `u32` is not an iterator @@ -56,6 +61,7 @@ LL | for _ in 42 as u32 {} | = help: the trait `Iterator` is not implemented for `u32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `u32` = note: required by `into_iter` error[E0277]: `i32` is not an iterator @@ -66,6 +72,7 @@ LL | for _ in 42 as i32 {} | = help: the trait `Iterator` is not implemented for `i32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `i32` = note: required by `into_iter` error[E0277]: `u64` is not an iterator @@ -76,6 +83,7 @@ LL | for _ in 42 as u64 {} | = help: the trait `Iterator` is not implemented for `u64` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `u64` = note: required by `into_iter` error[E0277]: `i64` is not an iterator @@ -86,6 +94,7 @@ LL | for _ in 42 as i64 {} | = help: the trait `Iterator` is not implemented for `i64` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `i64` = note: required by `into_iter` error[E0277]: `usize` is not an iterator @@ -96,6 +105,7 @@ LL | for _ in 42 as usize {} | = help: the trait `Iterator` is not implemented for `usize` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `usize` = note: required by `into_iter` error[E0277]: `isize` is not an iterator @@ -106,6 +116,7 @@ LL | for _ in 42 as isize {} | = help: the trait `Iterator` is not implemented for `isize` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required because of the requirements on the impl of `IntoIterator` for `isize` = note: required by `into_iter` error[E0277]: `{float}` is not an iterator @@ -115,6 +126,7 @@ LL | for _ in 42.0 {} | ^^^^ `{float}` is not an iterator | = help: the trait `Iterator` is not implemented for `{float}` + = note: required because of the requirements on the impl of `IntoIterator` for `{float}` = note: required by `into_iter` error: aborting due to 12 previous errors diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr index 0324d5f1a92a1..4678bafd196b5 100644 --- a/src/test/ui/iterators/ranges.stderr +++ b/src/test/ui/iterators/ranges.stderr @@ -5,6 +5,7 @@ LL | for _ in ..10 {} | ^^^^ `RangeTo<{integer}>` is not an iterator | = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` + = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>` = note: required by `into_iter` error[E0277]: `RangeToInclusive<{integer}>` is not an iterator @@ -14,6 +15,7 @@ LL | for _ in ..=10 {} | ^^^^^ `RangeToInclusive<{integer}>` is not an iterator | = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` + = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>` = note: required by `into_iter` error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr index fecdbd1785f61..1653006682427 100644 --- a/src/test/ui/iterators/string.stderr +++ b/src/test/ui/iterators/string.stderr @@ -5,6 +5,7 @@ LL | for _ in "".to_owned() {} | ^^^^^^^^^^^^^ `String` is not an iterator | = help: the trait `Iterator` is not implemented for `String` + = note: required because of the requirements on the impl of `IntoIterator` for `String` = note: required by `into_iter` error[E0277]: `&str` is not an iterator @@ -14,6 +15,7 @@ LL | for _ in "" {} | ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | = help: the trait `Iterator` is not implemented for `&str` + = note: required because of the requirements on the impl of `IntoIterator` for `&str` = note: required by `into_iter` error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/struct-literal-in-for.stderr b/src/test/ui/parser/struct-literal-in-for.stderr index 42f5f1e7e736d..fe9c113710c3c 100644 --- a/src/test/ui/parser/struct-literal-in-for.stderr +++ b/src/test/ui/parser/struct-literal-in-for.stderr @@ -24,6 +24,7 @@ LL | | }.hi() { | |__________^ `bool` is not an iterator | = help: the trait `Iterator` is not implemented for `bool` + = note: required because of the requirements on the impl of `IntoIterator` for `bool` = note: required by `into_iter` error: aborting due to 2 previous errors diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs index fdf0bc3839112..fba72c13170fe 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.rs +++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs @@ -21,18 +21,14 @@ mod m { // "Private-in-public in associated types is hard error" in RFC 2145 // applies only to the aliased types, not bounds. pub trait PubTr { + type Alias1: PrivTr; //~^ WARN private trait `PrivTr` in public interface //~| WARN this was previously accepted - //~| WARN private type `Priv` in public interface - //~| WARN private type `Priv` in public interface - //~| WARN this was previously accepted - //~| WARN this was previously accepted - type Alias1: PrivTr; type Alias2: PubTrAux1 = u8; - //~^ WARN private type `m::Priv` in public interface + //~^ WARN private type `Priv` in public interface //~| WARN this was previously accepted type Alias3: PubTrAux2 = u8; - //~^ WARN private type `m::Priv` in public interface + //~^ WARN private type `Priv` in public interface //~| WARN this was previously accepted type Alias4 = Priv; diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr index 768dca17e07d2..430be143f9187 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr +++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr @@ -8,7 +8,7 @@ LL | type A = Priv; | ^^^^^^^^^^^^^^ can't leak private type warning: private trait `PrivTr` in public interface (error E0445) - --> $DIR/private-in-public-assoc-ty.rs:23:5 + --> $DIR/private-in-public-assoc-ty.rs:24:9 | LL | type Alias1: PrivTr; | ^^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | type Alias1: PrivTr; = note: for more information, see issue #34537 warning: private type `Priv` in public interface (error E0446) - --> $DIR/private-in-public-assoc-ty.rs:23:5 + --> $DIR/private-in-public-assoc-ty.rs:27:9 | LL | type Alias2: PubTrAux1 = u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | type Alias2: PubTrAux1 = u8; = note: for more information, see issue #34537 warning: private type `Priv` in public interface (error E0446) - --> $DIR/private-in-public-assoc-ty.rs:23:5 + --> $DIR/private-in-public-assoc-ty.rs:30:9 | LL | type Alias3: PubTrAux2 = u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs index 5476e35b5f66b..f926eee9d92b2 100644 --- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -32,9 +32,8 @@ impl PublicType { pub trait MyPubTrait { type Foo: OtherTrait; - //~^ ERROR trait `priv_dep::OtherTrait` from private dependency 'priv_dep' in public interface } -//~^^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface +//~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface pub struct AllowedPrivType { #[allow(exported_private_dependencies)] diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr index e6fd6fc7bb8ce..e6b4d33f10316 100644 --- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -17,7 +17,7 @@ LL | pub fn pub_fn(param: OtherType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:33:1 + --> $DIR/pub-priv1.rs:34:5 | LL | type Foo: OtherTrait; | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index a896d58753321..381959b7ae4cd 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -4,7 +4,8 @@ error[E0283]: type annotations needed LL | l.iter().map(f).collect()? | ^^^^^^^ cannot infer type | - = note: cannot satisfy `<_ as Try>::Ok == _` + = note: cannot satisfy `_: Try` + = note: required by `into_result` help: consider specifying the type argument in the method call | LL | l.iter().map(f).collect::()? diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr index e380e5b2f91ff..2cebffec990f6 100644 --- a/src/test/ui/range/range-1.stderr +++ b/src/test/ui/range/range-1.stderr @@ -11,13 +11,15 @@ LL | for i in false..true {} | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` | = note: required because of the requirements on the impl of `Iterator` for `std::ops::Range` + = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range` + = note: required by `into_iter` error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time --> $DIR/range-1.rs:14:17 | LL | let range = *arr..; | ^^^^^^ doesn't have a size known at compile-time - | + | ::: $SRC_DIR/core/src/ops/range.rs:LL:COL | LL | pub struct RangeFrom { diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr index 24bf64261e9d2..ddb2b31ce1095 100644 --- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr +++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -4,8 +4,9 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | / fn bar<'a, 'b>() LL | | LL | | -LL | | where <() as Project<'a, 'b>>::Item : Eq - | |____________________________________________^ +LL | | where +LL | | <() as Project<'a, 'b>>::Item: Eq, + | |______________________________________^ | note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:8... --> $DIR/regions-normalize-in-where-clause-list.rs:24:8 @@ -23,43 +24,14 @@ note: ...so that the types are compatible LL | / fn bar<'a, 'b>() LL | | LL | | -LL | | where <() as Project<'a, 'b>>::Item : Eq - | |____________________________________________^ +LL | | where +LL | | <() as Project<'a, 'b>>::Item: Eq, + | |______________________________________^ = note: expected `Project<'a, 'b>` found `Project<'_, '_>` error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-normalize-in-where-clause-list.rs:22:1 - | -LL | / fn bar<'a, 'b>() -LL | | -LL | | -LL | | where <() as Project<'a, 'b>>::Item : Eq - | |____________________________________________^ - | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:8 - | -LL | fn bar<'a, 'b>() - | ^^ -note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12... - --> $DIR/regions-normalize-in-where-clause-list.rs:22:12 - | -LL | fn bar<'a, 'b>() - | ^^ -note: ...so that the types are compatible - --> $DIR/regions-normalize-in-where-clause-list.rs:22:1 - | -LL | / fn bar<'a, 'b>() -LL | | -LL | | -LL | | where <() as Project<'a, 'b>>::Item : Eq - | |____________________________________________^ - = note: expected `Project<'a, 'b>` - found `Project<'_, '_>` - -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/regions-normalize-in-where-clause-list.rs:22:4 + --> $DIR/regions-normalize-in-where-clause-list.rs:24:4 | LL | fn bar<'a, 'b>() | ^^^ diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr index 0dd1b2a59eb9a..4aa0ad219cf25 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr @@ -8,6 +8,7 @@ LL | for (i, _) in &v.iter().enumerate() { | help: consider removing the leading `&`-reference | = help: the trait `Iterator` is not implemented for `&Enumerate>` + = note: required because of the requirements on the impl of `IntoIterator` for `&Enumerate>` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.stderr b/src/test/ui/suggestions/suggest-remove-refs-2.stderr index 5c2efdb197f8c..15c4b7fcb8b3b 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-2.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-2.stderr @@ -8,6 +8,7 @@ LL | for (i, _) in & & & & &v.iter().enumerate() { | help: consider removing 5 leading `&`-references | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate>` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.stderr b/src/test/ui/suggestions/suggest-remove-refs-3.stderr index c7fbd3d9bd961..0bd6d956aff97 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-3.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-3.stderr @@ -12,6 +12,7 @@ LL | | .enumerate() { | |_____________________^ `&&&&&Enumerate>` is not an iterator | = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate>` = note: required by `into_iter` error: aborting due to previous error diff --git a/src/test/ui/traits/check-trait-object-bounds-1.rs b/src/test/ui/traits/check-trait-object-bounds-1.rs index ad908a750b431..b1f124c7ea26a 100644 --- a/src/test/ui/traits/check-trait-object-bounds-1.rs +++ b/src/test/ui/traits/check-trait-object-bounds-1.rs @@ -10,5 +10,5 @@ fn f() { fn main() { f::>(); - //~^ ERROR the trait bound `str: std::clone::Clone` is not satisfied + //~^ ERROR the trait bound `str: Clone` is not satisfied } diff --git a/src/test/ui/traits/check-trait-object-bounds-1.stderr b/src/test/ui/traits/check-trait-object-bounds-1.stderr index c53c91d42a754..170ed6eacfd41 100644 --- a/src/test/ui/traits/check-trait-object-bounds-1.stderr +++ b/src/test/ui/traits/check-trait-object-bounds-1.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/check-trait-object-bounds-1.rs:12:5 | LL | fn f() { | - required by this bound in `f` ... LL | f::>(); - | ^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str` + | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` error: aborting due to previous error diff --git a/src/test/ui/traits/check-trait-object-bounds-2.rs b/src/test/ui/traits/check-trait-object-bounds-2.rs index f825008c6a233..eb2fb6e841bce 100644 --- a/src/test/ui/traits/check-trait-object-bounds-2.rs +++ b/src/test/ui/traits/check-trait-object-bounds-2.rs @@ -11,5 +11,5 @@ fn f X<'r> + ?Sized>() { fn main() { f:: X<'x, F = i32>>(); - //~^ expected a `std::ops::FnOnce<(&i32,)>` closure, found `i32` + //~^ expected a `FnOnce<(&i32,)>` closure, found `i32` } diff --git a/src/test/ui/traits/check-trait-object-bounds-2.stderr b/src/test/ui/traits/check-trait-object-bounds-2.stderr index 1241fc8cb51df..04e2348634ed8 100644 --- a/src/test/ui/traits/check-trait-object-bounds-2.stderr +++ b/src/test/ui/traits/check-trait-object-bounds-2.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `std::ops::FnOnce<(&i32,)>` closure, found `i32` +error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32` --> $DIR/check-trait-object-bounds-2.rs:13:5 | LL | fn f X<'r> + ?Sized>() { @@ -7,7 +7,7 @@ LL | fn f X<'r> + ?Sized>() { LL | f:: X<'x, F = i32>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32` | - = help: the trait `for<'r> std::ops::FnOnce<(&'r i32,)>` is not implemented for `i32` + = help: the trait `for<'r> FnOnce<(&'r i32,)>` is not implemented for `i32` error: aborting due to previous error diff --git a/src/test/ui/traits/check-trait-object-bounds-4.rs b/src/test/ui/traits/check-trait-object-bounds-4.rs index 323508db2f2b1..e9ca1563f3b67 100644 --- a/src/test/ui/traits/check-trait-object-bounds-4.rs +++ b/src/test/ui/traits/check-trait-object-bounds-4.rs @@ -13,5 +13,5 @@ fn f() { fn main() { f::>(); - //~^ ERROR the trait bound `str: std::clone::Clone` is not satisfied + //~^ ERROR the trait bound `str: Clone` is not satisfied } diff --git a/src/test/ui/traits/check-trait-object-bounds-4.stderr b/src/test/ui/traits/check-trait-object-bounds-4.stderr index 75d6862579d11..fc9f31c5ebc7e 100644 --- a/src/test/ui/traits/check-trait-object-bounds-4.stderr +++ b/src/test/ui/traits/check-trait-object-bounds-4.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `str: std::clone::Clone` is not satisfied +error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/check-trait-object-bounds-4.rs:15:5 | LL | fn f() { | - required by this bound in `f` ... LL | f::>(); - | ^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `str` + | ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` error: aborting due to previous error diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index 738b052a11ebb..b2702d977f8b6 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `SalsaStorage: std::panic::RefUnwindSafe` +error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe` --> $DIR/cycle-cache-err-60010.rs:69:5 | LL | fn parse(&self) { @@ -8,28 +8,12 @@ LL | SourceDatabase::parse(db); | ^^^^^^^^^^^^^^^^^^^^^ | = note: required because it appears within the type `*const SalsaStorage` - = note: required because it appears within the type `std::ptr::Unique` - = note: required because it appears within the type `std::boxed::Box` + = note: required because it appears within the type `Unique` + = note: required because it appears within the type `Box` = note: required because it appears within the type `Runtime` = note: required because it appears within the type `RootDatabase` = note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase` -error[E0275]: overflow evaluating the requirement `Runtime: RefUnwindSafe` - --> $DIR/cycle-cache-err-60010.rs:31:20 - | -LL | trait Database { - | -------- required by a bound in this -LL | type Storage; - | ------------- required by this bound in `Database` -... -LL | type Storage = SalsaStorage; - | ^^^^^^^^^^^^ - | - = note: required because it appears within the type `RootDatabase` - = note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase` - = note: required because of the requirements on the impl of `Query` for `ParseQuery` - = note: required because it appears within the type `SalsaStorage` - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr index dbe0146cafaa6..996544ae5162d 100644 --- a/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-two-traits.stderr @@ -9,8 +9,8 @@ LL | type X = Self; | help: consider further restricting this bound | -LL | impl Magic for T { - | ^^^^^^^^^^^^^^^^^^^ +LL | impl Magic for T { + | ^^^^^^ error[E0275]: overflow evaluating the requirement `*mut (): Magic` --> $DIR/traits-inductive-overflow-two-traits.rs:20:5 diff --git a/src/test/ui/try-block/try-block-bad-type.rs b/src/test/ui/try-block/try-block-bad-type.rs index c338294913f6c..496ba145810fb 100644 --- a/src/test/ui/try-block/try-block-bad-type.rs +++ b/src/test/ui/try-block/try-block-bad-type.rs @@ -14,7 +14,9 @@ pub fn main() { let res: Result = try { }; //~ ERROR type mismatch - let res: () = try { }; //~ the trait bound `(): Try` is not satisfied + let res: () = try { }; + //~^ ERROR the trait bound `(): Try` is not satisfied + //~| ERROR the trait bound `(): Try` is not satisfied let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied } diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index dfc1c342a508b..cadf3a841c961 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -26,18 +26,24 @@ LL | let res: Result = try { }; | ^ expected `i32`, found `()` error[E0277]: the trait bound `(): Try` is not satisfied - --> $DIR/try-block-bad-type.rs:17:23 + --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^^^ the trait `Try` is not implemented for `()` + | ^ the trait `Try` is not implemented for `()` | = note: required by `from_ok` +error[E0277]: the trait bound `(): Try` is not satisfied + --> $DIR/try-block-bad-type.rs:17:25 + | +LL | let res: () = try { }; + | ^ the trait `Try` is not implemented for `()` + error[E0277]: the trait bound `i32: Try` is not satisfied - --> $DIR/try-block-bad-type.rs:19:24 + --> $DIR/try-block-bad-type.rs:21:26 | LL | let res: i32 = try { 5 }; - | ^^^^^ the trait `Try` is not implemented for `i32` + | ^ the trait `Try` is not implemented for `i32` | = note: required by `from_ok` diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr index bc0f5bb6505b2..75a4e8d065cab 100644 --- a/src/test/ui/try-block/try-block-in-while.stderr +++ b/src/test/ui/try-block/try-block-in-while.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `bool: Try` is not satisfied - --> $DIR/try-block-in-while.rs:6:15 + --> $DIR/try-block-in-while.rs:6:17 | LL | while try { false } {} - | ^^^^^^^^^ the trait `Try` is not implemented for `bool` + | ^^^^^ the trait `Try` is not implemented for `bool` | = note: required by `from_ok` diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs index 5566f40f96095..c0359159aebea 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.rs @@ -4,13 +4,13 @@ #![feature(type_alias_impl_trait)] type X = impl Clone; -//~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied +//~^ ERROR the trait bound `T: Clone` is not satisfied fn f(t: T) -> X { t } -fn g(o : Option>) -> Option> { +fn g(o: Option>) -> Option> { o.clone() } diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr index e20130007ee8b..26a2f4135cb0a 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -1,13 +1,13 @@ -error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied +error[E0277]: the trait bound `T: Clone` is not satisfied --> $DIR/bounds-are-checked-2.rs:6:13 | LL | type X = impl Clone; - | ^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `T` + | ^^^^^^^^^^ the trait `Clone` is not implemented for `T` | help: consider restricting type parameter `T` | -LL | type X = impl Clone; - | ^^^^^^^^^^^^^^^^^^^ +LL | type X = impl Clone; + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr index 574be0eb0a257..d5fafe05887b9 100644 --- a/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr +++ b/src/test/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -12,8 +12,8 @@ error[E0308]: mismatched types LL | type X<'a> = impl Into<&'static str> + From<&'a str>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected trait `std::convert::From<&'a str>` - found trait `std::convert::From<&'static str>` + = note: expected trait `From<&'a str>` + found trait `From<&'static str>` note: the lifetime `'a` as defined on the item at 6:8... --> $DIR/bounds-are-checked.rs:6:8 | diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs index ac8773104147e..dd2f202cf5dc0 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs @@ -6,12 +6,14 @@ fn main() {} // test that unused generic parameters are ok type Two = impl Debug; +//~^ ERROR `T` doesn't implement `Debug` +//~| ERROR `U` doesn't implement `Debug` fn two(t: T, u: U) -> Two { (t, u) } fn three(t: T, u: U) -> Two { -//~^ concrete type differs from previous + //~^ concrete type differs from previous (u, t) } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr index 1ddbc0c8d6a8e..b4aed4a6323bf 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr @@ -1,14 +1,39 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use5.rs:14:1 + --> $DIR/generic_duplicate_param_use5.rs:16:1 | LL | fn three(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, U)`, got `(U, T)` | note: previous use here - --> $DIR/generic_duplicate_param_use5.rs:10:1 + --> $DIR/generic_duplicate_param_use5.rs:12:1 | LL | fn two(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:8:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(T, U)` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:8:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(T, U)` +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs index 6cbb3069ecd4b..d54d3cd62e020 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs @@ -6,12 +6,13 @@ fn main() {} // test that unused generic parameters are ok type Two = impl Debug; +//~^ ERROR `T` doesn't implement `Debug` fn two(t: T, u: U) -> Two { (t, t) } fn three(t: T, u: U) -> Two { - //~^ concrete type differs from previous + //~^ ERROR concrete type differs from previous (u, t) } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr index ebd07b7c300f1..22e4d00667492 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr @@ -1,14 +1,27 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use6.rs:14:1 + --> $DIR/generic_duplicate_param_use6.rs:15:1 | LL | fn three(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, T)`, got `(U, T)` | note: previous use here - --> $DIR/generic_duplicate_param_use6.rs:10:1 + --> $DIR/generic_duplicate_param_use6.rs:11:1 | LL | fn two(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use6.rs:8:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(T, T)` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs index 777ded52609b8..4a723b64cdc4f 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs @@ -5,12 +5,13 @@ use std::fmt::Debug; fn main() {} type Two = impl Debug; +//~^ ERROR `T` doesn't implement `Debug` fn two(t: T, _: U) -> Two { (t, 4u32) } fn three(_: T, u: U) -> Two { -//~^ concrete type differs from previous + //~^ concrete type differs from previous (u, 4u32) } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr index 4778ee5155cf0..82da704c9ee22 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr @@ -1,14 +1,27 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use8.rs:13:1 + --> $DIR/generic_duplicate_param_use8.rs:14:1 | LL | fn three(_: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, u32)`, got `(U, u32)` | note: previous use here - --> $DIR/generic_duplicate_param_use8.rs:9:1 + --> $DIR/generic_duplicate_param_use8.rs:10:1 | LL | fn two(t: T, _: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use8.rs:7:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(T, u32)` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs index 491e6647f45d0..747081933172b 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs @@ -5,6 +5,9 @@ use std::fmt::Debug; fn main() {} type Two = impl Debug; +//~^ ERROR the trait bound `A: Foo` is not satisfied in `(A, B, ::Bar)` +//~| ERROR `A` doesn't implement `Debug` +//~| ERROR `B` doesn't implement `Debug` trait Foo { type Bar: Debug; diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr index 247b042f61e05..63aa0f8a81c9a 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -1,14 +1,51 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/generic_duplicate_param_use9.rs:18:1 + --> $DIR/generic_duplicate_param_use9.rs:21:1 | LL | fn three(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(A, B, ::Bar)`, got `(A, B, i32)` | note: previous use here - --> $DIR/generic_duplicate_param_use9.rs:14:1 + --> $DIR/generic_duplicate_param_use9.rs:17:1 | LL | fn two(t: T, u: U) -> Two { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0277]: the trait bound `A: Foo` is not satisfied in `(A, B, ::Bar)` + --> $DIR/generic_duplicate_param_use9.rs:7:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ within `(A, B, ::Bar)`, the trait `Foo` is not implemented for `A` + | + = note: required because it appears within the type `(A, B, ::Bar)` +help: consider restricting type parameter `A` + | +LL | type Two = impl Debug; + | ^^^^^ + +error[E0277]: `A` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:7:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(A, B, ::Bar)` +help: consider restricting type parameter `A` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error[E0277]: `B` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:7:18 + | +LL | type Two = impl Debug; + | ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required because of the requirements on the impl of `Debug` for `(A, B, ::Bar)` +help: consider restricting type parameter `B` + | +LL | type Two = impl Debug; + | ^^^^^^^ + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs index c0f939a50482f..f6d490960365a 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -8,7 +8,8 @@ fn main() { type WrongGeneric = impl 'static; //~^ ERROR the parameter type `T` may not live long enough -//~^^ ERROR: at least one trait must be specified +//~| ERROR the parameter type `T` may not live long enough +//~| ERROR: at least one trait must be specified fn wrong_generic(t: T) -> WrongGeneric { t diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index 18d8daa05e63d..4924c447d7e40 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -27,7 +27,16 @@ LL | type WrongGeneric = impl 'static; LL | fn wrong_generic(t: T) -> WrongGeneric { | - help: consider adding an explicit lifetime bound...: `T: 'static` -error: aborting due to 3 previous errors +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generic_type_does_not_live_long_enough.rs:9:24 + | +LL | type WrongGeneric = impl 'static; + | ^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'static`... + = note: ...so that the type `T` will meet its required lifetime bounds + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0308, E0310. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 782eb0fb3df5e..3372b81404ecb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -16,6 +16,10 @@ struct X; impl Foo for X { type Bar = impl Baz; //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types fn bar(&self) -> Self::Bar { |x| x diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index a8706aa9a241f..5e2a8db02867f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -7,6 +7,42 @@ LL | type Bar = impl Baz; = note: expected type `FnOnce<(&X,)>` found type `FnOnce<(&X,)>` -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r X,)>` + found type `Fn<(&' X,)>` + +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&X,)>` + found type `FnOnce<(&' X,)>` + +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r X,)>` + found type `Fn<(&' X,)>` + +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&X,)>` + found type `FnOnce<(&' X,)>` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index 9e710c15fdbce..a2bf963044582 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -5,6 +5,7 @@ LL | >::add(1, 2); | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` | = help: the trait `Add` is not implemented for `i32` + = note: required by `add` error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:6:28 From c9eeb60b638fcb347c7c6ba066390144d8c7a24e Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 5 Oct 2020 17:19:24 +0100 Subject: [PATCH 33/34] Deduplicate some code --- compiler/rustc_traits/src/chalk/db.rs | 39 +++++++++++---------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 5553d4585244d..223635e9aecd9 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -50,6 +50,19 @@ impl<'tcx> RustIrDatabase<'tcx> { .map(|wc| wc.fold_with(&mut regions_substitutor)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect() } + + fn bounds_for(&self, def_id: DefId, bound_vars: SubstsRef<'tcx>) -> Vec + where + ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option>, + { + self.interner + .tcx + .explicit_item_bounds(def_id) + .iter() + .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) + .filter_map(|bound| LowerInto::>::lower_into(bound, &self.interner)) + .collect() + } } impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'tcx> { @@ -75,19 +88,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let binders = binders_for(&self.interner, bound_vars); let where_clauses = self.where_clauses_for(def_id, bound_vars); - - let bounds = self - .interner - .tcx - .explicit_item_bounds(def_id) - .iter() - .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) - .filter_map(|bound| { - LowerInto::< - Option>>, - >::lower_into(bound, &self.interner) - }) - .collect(); + let bounds = self.bounds_for(def_id, bound_vars); Arc::new(chalk_solve::rust_ir::AssociatedTyDatum { trait_id: chalk_ir::TraitId(trait_def_id), @@ -453,17 +454,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let bound_vars = bound_vars_for_item(self.interner.tcx, opaque_ty_id.0); let binders = binders_for(&self.interner, bound_vars); let where_clauses = self.where_clauses_for(opaque_ty_id.0, bound_vars); - - let bounds: Vec<_> = self - .interner - .tcx - .explicit_item_bounds(opaque_ty_id.0) - .iter() - .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) - .filter_map(|bound| { - LowerInto::>>>::lower_into(bound, &self.interner) - }) - .collect(); + let bounds = self.bounds_for(opaque_ty_id.0, bound_vars); let value = chalk_solve::rust_ir::OpaqueTyDatumBound { bounds: chalk_ir::Binders::new(binders.clone(), bounds), From 69fc6d8c5c27da57a399a3f5ab51f2ecf2bb954a Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 6 Oct 2020 08:39:49 +0100 Subject: [PATCH 34/34] Fix NLL compare mode tests --- .../borrow_check/diagnostics/region_errors.rs | 9 ++++--- ..._type_does_not_live_long_enough.nll.stderr | 22 ++++++++++++++-- .../issue-57611-trait-alias.nll.stderr | 25 ++++++++++++++++--- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs index b145e1d5fa333..e22dab0151703 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::{ error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin, }; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; +use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; @@ -585,14 +586,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // // eg. check for `impl Trait + 'static` instead of `impl Trait`. let has_static_predicate = { - let predicates_of = self.infcx.tcx.predicates_of(did); - let bounds = predicates_of.instantiate(self.infcx.tcx, substs); + let bounds = self.infcx.tcx.explicit_item_bounds(did); let mut found = false; - for predicate in bounds.predicates { + for (bound, _) in bounds { if let ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(_, r)) = - predicate.skip_binders() + bound.skip_binders() { + let r = r.subst(self.infcx.tcx, substs); if let ty::RegionKind::ReStatic = r { found = true; break; diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr index 76654d7a718b8..ffd6f34c4b00e 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr @@ -18,6 +18,24 @@ LL | type WrongGeneric = impl 'static; = note: expected type `i32` found opaque type `impl Sized` -error: aborting due to 2 previous errors +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generic_type_does_not_live_long_enough.rs:14:30 + | +LL | fn wrong_generic(t: T) -> WrongGeneric { + | ^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'static`... + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generic_type_does_not_live_long_enough.rs:9:24 + | +LL | type WrongGeneric = impl 'static; + | ^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `T: 'static`... + = note: ...so that the type `T` will meet its required lifetime bounds + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0310. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index 8c9cb742fac91..790aea87510e6 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -1,14 +1,33 @@ error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:21:9 + --> $DIR/issue-57611-trait-alias.rs:25:9 | LL | |x| x | ^^^^^ error: higher-ranked subtype error - --> $DIR/issue-57611-trait-alias.rs:21:9 + --> $DIR/issue-57611-trait-alias.rs:25:9 | LL | |x| x | ^^^^^ -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r X,)>` + found type `Fn<(&'static X,)>` + +error[E0308]: mismatched types + --> $DIR/issue-57611-trait-alias.rs:17:16 + | +LL | type Bar = impl Baz; + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&X,)>` + found type `FnOnce<(&'static X,)>` + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`.